## Automatically generated incremental diff ## From: linux-2.6.3-rc2 ## To: linux-2.6.3-rc3 ## Robot: $Id: make-incremental-diff,v 1.12 2004/01/06 07:19:36 hpa Exp $ diff -urN linux-2.6.3-rc2/Makefile linux-2.6.3-rc3/Makefile --- linux-2.6.3-rc2/Makefile 2004-02-14 19:30:50.000000000 -0800 +++ linux-2.6.3-rc3/Makefile 2004-02-14 19:30:59.000000000 -0800 @@ -1,7 +1,7 @@ VERSION = 2 PATCHLEVEL = 6 SUBLEVEL = 3 -EXTRAVERSION =-rc2 +EXTRAVERSION =-rc3 NAME=Feisty Dunnart # *DOCUMENTATION* diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_apecs.c linux-2.6.3-rc3/arch/alpha/kernel/core_apecs.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_apecs.c 2004-02-03 19:43:32.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_apecs.c 2004-02-14 19:30:59.000000000 -0800 @@ -10,20 +10,18 @@ * Code common to all APECS core logic chips. */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include #include #include -#include #include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_cia.c linux-2.6.3-rc3/arch/alpha/kernel/core_cia.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_cia.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_cia.c 2004-02-14 19:30:59.000000000 -0800 @@ -11,23 +11,19 @@ * Code common to all CIA core logic chips. */ -#include -#include -#include -#include -#include - -#include -#include -#include - #define __EXTERN_INLINE inline #include #include #undef __EXTERN_INLINE +#include +#include +#include +#include #include +#include + #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_irongate.c linux-2.6.3-rc3/arch/alpha/kernel/core_irongate.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_irongate.c 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_irongate.c 2004-02-14 19:30:59.000000000 -0800 @@ -9,27 +9,23 @@ * Code common to all IRONGATE core logic chips. */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include #include #include #include #include +#include #include -#include #include -#include #include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - -#include - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_lca.c linux-2.6.3-rc3/arch/alpha/kernel/core_lca.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_lca.c 2004-02-03 19:44:21.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_lca.c 2004-02-14 19:30:59.000000000 -0800 @@ -8,21 +8,19 @@ * Code common to all LCA core logic chips. */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include #include #include #include #include -#include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_marvel.c linux-2.6.3-rc3/arch/alpha/kernel/core_marvel.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_marvel.c 2004-02-03 19:43:10.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_marvel.c 2004-02-14 19:30:59.000000000 -0800 @@ -4,14 +4,11 @@ * Code common to all Marvel based systems. */ -#include - #define __EXTERN_INLINE inline #include #include #undef __EXTERN_INLINE -#include #include #include #include @@ -20,18 +17,15 @@ #include #include #include +#include #include -#include #include -#include #include #include #include #include -#include - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_mcpcia.c linux-2.6.3-rc3/arch/alpha/kernel/core_mcpcia.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_mcpcia.c 2004-02-03 19:43:57.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_mcpcia.c 2004-02-14 19:30:59.000000000 -0800 @@ -6,7 +6,11 @@ * Code common to all MCbus-PCI Adaptor core logic chipsets */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include #include #include @@ -14,13 +18,6 @@ #include #include -#include -#include - -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_polaris.c linux-2.6.3-rc3/arch/alpha/kernel/core_polaris.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_polaris.c 2004-02-03 19:43:17.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_polaris.c 2004-02-14 19:30:59.000000000 -0800 @@ -4,20 +4,18 @@ * POLARIS chip-specific code */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include #include #include #include -#include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_t2.c linux-2.6.3-rc3/arch/alpha/kernel/core_t2.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_t2.c 2004-02-03 19:43:06.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_t2.c 2004-02-14 19:30:59.000000000 -0800 @@ -9,21 +9,19 @@ * Code common to all T2 core logic chips. */ -#include +#define __EXTERN_INLINE +#include +#include +#undef __EXTERN_INLINE + #include #include #include #include #include -#include #include -#define __EXTERN_INLINE -#include -#include -#undef __EXTERN_INLINE - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_titan.c linux-2.6.3-rc3/arch/alpha/kernel/core_titan.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_titan.c 2004-02-03 19:43:34.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_titan.c 2004-02-14 19:30:59.000000000 -0800 @@ -4,29 +4,24 @@ * Code common to all TITAN core logic chips. */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include -#include #include #include #include #include #include +#include -#include #include -#include #include #include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - -#include - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_tsunami.c linux-2.6.3-rc3/arch/alpha/kernel/core_tsunami.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_tsunami.c 2004-02-03 19:43:42.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_tsunami.c 2004-02-14 19:30:59.000000000 -0800 @@ -6,23 +6,20 @@ * Code common to all TSUNAMI core logic chips. */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include #include #include #include +#include #include -#include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - -#include - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/alpha/kernel/core_wildfire.c linux-2.6.3-rc3/arch/alpha/kernel/core_wildfire.c --- linux-2.6.3-rc2/arch/alpha/kernel/core_wildfire.c 2004-02-03 19:43:04.000000000 -0800 +++ linux-2.6.3-rc3/arch/alpha/kernel/core_wildfire.c 2004-02-14 19:30:59.000000000 -0800 @@ -6,21 +6,19 @@ * Copyright (C) 2000 Andrea Arcangeli SuSE */ -#include +#define __EXTERN_INLINE inline +#include +#include +#undef __EXTERN_INLINE + #include #include #include #include #include -#include #include -#define __EXTERN_INLINE inline -#include -#include -#undef __EXTERN_INLINE - #include "proto.h" #include "pci_impl.h" diff -urN linux-2.6.3-rc2/arch/arm/common/amba.c linux-2.6.3-rc3/arch/arm/common/amba.c --- linux-2.6.3-rc2/arch/arm/common/amba.c 2004-02-14 19:30:50.000000000 -0800 +++ linux-2.6.3-rc3/arch/arm/common/amba.c 2004-02-14 19:30:59.000000000 -0800 @@ -50,7 +50,7 @@ if (nr_env < 2) return -ENOMEM; - snprintf(buf, bufsz, "AMBA_ID=%08lx", pcdev->periphid); + snprintf(buf, bufsz, "AMBA_ID=%08x", pcdev->periphid); *envp++ = buf; *envp++ = NULL; return 0; diff -urN linux-2.6.3-rc2/arch/arm/kernel/time.c linux-2.6.3-rc3/arch/arm/kernel/time.c --- linux-2.6.3-rc2/arch/arm/kernel/time.c 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/arm/kernel/time.c 2004-02-14 19:30:59.000000000 -0800 @@ -72,8 +72,10 @@ /* * Scheduler clock - returns current time in nanosec units. + * This is the default implementation. Sub-architecture + * implementations can override this. */ -unsigned long long sched_clock(void) +unsigned long long __attribute__((weak)) sched_clock(void) { return (unsigned long long)jiffies * (1000000000 / HZ); } @@ -114,7 +116,7 @@ return; if (next_rtc_update && - time_before(xtime.tv_sec, next_rtc_update)) + time_before((unsigned long)xtime.tv_sec, next_rtc_update)) return; if (xtime.tv_nsec < 500000000 - ((unsigned) tick_nsec >> 1) && diff -urN linux-2.6.3-rc2/arch/arm/mach-sa1100/generic.c linux-2.6.3-rc3/arch/arm/mach-sa1100/generic.c --- linux-2.6.3-rc2/arch/arm/mach-sa1100/generic.c 2004-02-03 19:43:32.000000000 -0800 +++ linux-2.6.3-rc3/arch/arm/mach-sa1100/generic.c 2004-02-14 19:30:59.000000000 -0800 @@ -159,9 +159,14 @@ }, }; +static u64 sa11x0mcp_dma_mask = 0xffffffffUL; + static struct platform_device sa11x0mcp_device = { .name = "sa11x0-mcp", .id = 0, + .dev = { + .dma_mask = &sa11x0mcp_dma_mask, + }, .num_resources = ARRAY_SIZE(sa11x0mcp_resources), .resource = sa11x0mcp_resources, }; diff -urN linux-2.6.3-rc2/arch/arm/mm/Kconfig linux-2.6.3-rc3/arch/arm/mm/Kconfig --- linux-2.6.3-rc2/arch/arm/mm/Kconfig 2004-02-03 19:43:42.000000000 -0800 +++ linux-2.6.3-rc3/arch/arm/mm/Kconfig 2004-02-14 19:30:59.000000000 -0800 @@ -291,8 +291,8 @@ depends on CPU_ARM720T || CPU_ARM920T || CPU_ARM922T || CPU_ARM926T || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE default y help - Say Y if you want to have kernel support for ARM Thumb instructions, - fault handlers, and system calls. + Say Y if you want to include kernel support for running user space + Thumb binaries. The Thumb instruction set is a compressed form of the standard ARM instruction set resulting in smaller binaries at the expense of diff -urN linux-2.6.3-rc2/arch/i386/Kconfig linux-2.6.3-rc3/arch/i386/Kconfig --- linux-2.6.3-rc2/arch/i386/Kconfig 2004-02-03 19:43:13.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/Kconfig 2004-02-14 19:30:59.000000000 -0800 @@ -701,7 +701,7 @@ # Common NUMA Features config NUMA bool "Numa Memory Allocation Support" - depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI && !ACPI_HT_ONLY)) + depends on SMP && HIGHMEM64G && (X86_PC || X86_NUMAQ || X86_GENERICARCH || (X86_SUMMIT && ACPI)) default n if X86_PC default y if (X86_NUMAQ || X86_SUMMIT) @@ -709,8 +709,8 @@ comment "NUMA (NUMA-Q) requires SMP, 64GB highmem support" depends on X86_NUMAQ && (!HIGHMEM64G || !SMP) -comment "NUMA (Summit) requires SMP, 64GB highmem support, full ACPI" - depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI || ACPI_HT_ONLY) +comment "NUMA (Summit) requires SMP, 64GB highmem support, ACPI" + depends on X86_SUMMIT && (!HIGHMEM64G || !ACPI) config DISCONTIGMEM bool diff -urN linux-2.6.3-rc2/arch/i386/kernel/acpi/boot.c linux-2.6.3-rc3/arch/i386/kernel/acpi/boot.c --- linux-2.6.3-rc2/arch/i386/kernel/acpi/boot.c 2004-02-14 19:30:50.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/acpi/boot.c 2004-02-14 19:30:59.000000000 -0800 @@ -141,6 +141,10 @@ acpi_table_print_madt_entry(header); + /* no utility in registering a disabled processor */ + if (processor->flags.enabled == 0) + return 0; + mp_register_lapic ( processor->id, /* APIC ID */ processor->flags.enabled); /* Enabled? */ diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c --- linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-02-03 19:43:47.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/gx-suspmod.c 2004-02-14 19:30:59.000000000 -0800 @@ -28,30 +28,34 @@ * with 'Suspend Modulation OFF Count Register' * and 'Suspend Modulation ON Count Register'. * These registers are 8bit counters that represent the number of - * 32us intervals which the SUSP# pin is asserted/de-asserted to the - * processor. + * 32us intervals which the SUSP# pin is asserted(ON)/de-asserted(OFF) + * to the processor. * * These counters define a ratio which is the effective frequency * of operation of the system. * - * On Count + * OFF Count * F_eff = Fgx * ---------------------- - * On Count + Off Count + * OFF Count + ON Count * * 0 <= On Count, Off Count <= 255 * * From these limits, we can get register values * - * on_duration + off_duration <= MAX_DURATION - * off_duration = on_duration * (stock_freq - freq) / freq + * off_duration + on_duration <= MAX_DURATION + * on_duration = off_duration * (stock_freq - freq) / freq * - * on_duration = (freq * DURATION) / stock_freq - * off_duration = DURATION - on_duration + * off_duration = (freq * DURATION) / stock_freq + * on_duration = DURATION - off_duration * * *--------------------------------------------------------------------------- * * ChangeLog: + * Dec. 12, 2003 Hiroshi Miura + * - fix on/off register mistake + * - fix cpu_khz calc when it stops cpu modulation. + * * Dec. 11, 2002 Hiroshi Miura * - rewrite for Cyrix MediaGX Cx5510/5520 and * NatSemi Geode Cs5530(A). @@ -233,13 +237,13 @@ int old_tmp_freq = stock_freq; int tmp_freq; - *on_duration=1; - *off_duration=0; + *off_duration=1; + *on_duration=0; for (i=max_duration; i>0; i--) { - tmp_on = ((khz * i) / stock_freq) & 0xff; - tmp_off = i - tmp_on; - tmp_freq = (stock_freq * tmp_on) / i; + tmp_off = ((khz * i) / stock_freq) & 0xff; + tmp_on = i - tmp_off; + tmp_freq = (stock_freq * tmp_off) / i; /* if this relation is closer to khz, use this. If it's equal, * prefer it, too - lower latency */ if (abs(tmp_freq - khz) <= abs(old_tmp_freq - khz)) { @@ -273,42 +277,37 @@ freqs.new = new_khz; - if (new_khz == stock_freq) { /* if new khz == 100% of CPU speed, it is special case */ - local_irq_save(flags); - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - pci_write_config_byte(gx_params->cs55x0, PCI_SUSCFG, (gx_params->pci_suscfg & ~(SUSMOD))); - pci_read_config_byte(gx_params->cs55x0, PCI_SUSCFG, &(gx_params->pci_suscfg)); - local_irq_restore(flags); - dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n"); - cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE); - return; - } - cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE); - local_irq_save(flags); - switch (gx_params->cs55x0->device) { - case PCI_DEVICE_ID_CYRIX_5530_LEGACY: - pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP; - /* FIXME: need to test other values -- Zwane,Miura */ - pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */ - pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */ - pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1); - if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */ + if (new_khz != stock_freq) { /* if new khz == 100% of CPU speed, it is special case */ + switch (gx_params->cs55x0->device) { + case PCI_DEVICE_ID_CYRIX_5530_LEGACY: + pmer1 = gx_params->pci_pmer1 | IRQ_SPDUP | VID_SPDUP; + /* FIXME: need to test other values -- Zwane,Miura */ + pci_write_config_byte(gx_params->cs55x0, PCI_IRQTC, 4); /* typical 2 to 4ms */ + pci_write_config_byte(gx_params->cs55x0, PCI_VIDTC, 100);/* typical 50 to 100ms */ + pci_write_config_byte(gx_params->cs55x0, PCI_PMER1, pmer1); + + if (gx_params->pci_rev < 0x10) { /* CS5530(rev 1.2, 1.3) */ + suscfg = gx_params->pci_suscfg | SUSMOD; + } else { /* CS5530A,B.. */ + suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE; + } + break; + case PCI_DEVICE_ID_CYRIX_5520: + case PCI_DEVICE_ID_CYRIX_5510: suscfg = gx_params->pci_suscfg | SUSMOD; - } else { /* CS5530A,B.. */ - suscfg = gx_params->pci_suscfg | SUSMOD | PWRSVE; + default: + local_irq_restore(flags); + dprintk("fatal: try to set unknown chipset.\n"); + return; } - break; - case PCI_DEVICE_ID_CYRIX_5520: - case PCI_DEVICE_ID_CYRIX_5510: - suscfg = gx_params->pci_suscfg | SUSMOD; - break; - default: - local_irq_restore(flags); - dprintk("fatal: try to set unknown chipset.\n"); - return; + } else { + suscfg = gx_params->pci_suscfg & ~(SUSMOD); + gx_params->off_duration = 0; + gx_params->on_duration = 0; + dprintk("suspend modulation disabled: cpu runs 100 percent speed.\n"); } pci_write_config_byte(gx_params->cs55x0, PCI_MODOFF, gx_params->off_duration); diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/longhaul.c linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/longhaul.c --- linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-02-03 19:43:07.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/longhaul.c 2004-02-14 19:30:59.000000000 -0800 @@ -63,11 +63,12 @@ static unsigned int calc_speed (int mult, int fsb) { - int mhz; - mhz = (mult/10)*fsb; + int khz; + khz = (mult/10)*fsb; if (mult%10) - mhz += fsb/2; - return mhz; + khz += fsb/2; + khz *= 1000; + return khz; } @@ -253,7 +254,7 @@ highest_speed = calc_speed (maxmult, fsb); lowest_speed = calc_speed (minmult,fsb); dprintk (KERN_INFO PFX "FSB: %dMHz Lowestspeed=%dMHz Highestspeed=%dMHz\n", - fsb, lowest_speed, highest_speed); + fsb, lowest_speed/1000, highest_speed/1000); longhaul_table = kmalloc((numscales + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if(!longhaul_table) @@ -267,7 +268,7 @@ if (ratio > maxmult || ratio < minmult) continue; longhaul_table[k].frequency = calc_speed (ratio, fsb); - longhaul_table[k].index = (j << 8); + longhaul_table[k].index = j; k++; } diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c --- linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-02-03 19:44:38.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/p4-clockmod.c 2004-02-14 19:30:59.000000000 -0800 @@ -246,7 +246,7 @@ static int cpufreq_p4_cpu_exit(struct cpufreq_policy *policy) { cpufreq_frequency_table_put_attr(policy->cpu); - return cpufreq_p4_setdc(policy->cpu, DC_DISABLE); + return 0; } static struct freq_attr* p4clockmod_attr[] = { diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k7.c linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/powernow-k7.c --- linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2004-02-03 19:43:06.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/powernow-k7.c 2004-02-14 19:30:59.000000000 -0800 @@ -91,18 +91,13 @@ struct cpuinfo_x86 *c = cpu_data; unsigned int maxei, eax, ebx, ecx, edx; - if (c->x86_vendor != X86_VENDOR_AMD) { - printk (KERN_INFO PFX "AMD processor not detected.\n"); - return 0; - } - - if (c->x86 !=6) { + if ((c->x86_vendor != X86_VENDOR_AMD) || (c->x86 !=6)) { +#ifdef MODULE printk (KERN_INFO PFX "This module only works with AMD K7 CPUs\n"); +#endif return 0; } - printk (KERN_INFO PFX "AMD K7 CPU detected.\n"); - if ((c->x86_model == 6) && (c->x86_mask == 0)) { printk (KERN_INFO PFX "K7 660[A0] core detected, enabling errata workarounds\n"); have_a0 = 1; diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k8.c linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/powernow-k8.c --- linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/powernow-k8.c 2004-02-14 19:30:59.000000000 -0800 @@ -31,7 +31,7 @@ #define PFX "powernow-k8: " #define BFX PFX "BIOS error: " -#define VERSION "version 1.00.08 - September 26, 2003" +#define VERSION "version 1.00.08a" #include "powernow-k8.h" #ifdef CONFIG_PREEMPT @@ -44,10 +44,11 @@ static u32 rvo; /* ramp voltage offset, from PSB */ static u32 irt; /* isochronous relief time, from PSB */ static u32 vidmvs; /* usable value calculated from mvs, from PSB */ -struct pst_s *ppst; /* array of p states, valid for this part */ static u32 currvid; /* keep track of the current fid / vid */ static u32 currfid; +static struct cpufreq_frequency_table *powernow_table; + /* The PSB table supplied by BIOS allows for the definition of the number of p-states that can be used when running on a/c, and the number of p-states @@ -71,30 +72,12 @@ static u32 batps; /* limit on the number of p states when on battery */ /* - set by BIOS in the PSB/PST */ -static struct cpufreq_driver cpufreq_amd64_driver = { - .verify = powernowk8_verify, - .target = powernowk8_target, - .init = powernowk8_cpu_init, - .name = "cpufreq-amd64", - .owner = THIS_MODULE, -}; - -#define SEARCH_UP 1 -#define SEARCH_DOWN 0 - -/* Return a frequency in MHz, given an input fid */ -u32 -find_freq_from_fid(u32 fid) + /* Return a frequency in MHz, given an input fid */ +static u32 find_freq_from_fid(u32 fid) { - return 800 + (fid * 100); + return 800 + (fid * 100); } -/* Return a fid matching an input frequency in MHz */ -static u32 -find_fid_from_freq(u32 freq) -{ - return (freq - 800) / 100; -} /* Return the vco fid for an input fid */ static u32 @@ -107,56 +90,27 @@ } } -/* Sort the fid/vid frequency table into ascending order by fid. The spec */ -/* implies that it will be sorted by BIOS, but, it only implies it, and I */ -/* prefer not to trust when I can check. */ -/* Yes, it is a simple bubble sort, but the PST is really small, so the */ -/* choice of algorithm is pretty irrelevant. */ -static inline void -sort_pst(struct pst_s *ppst, u32 numpstates) -{ - u32 i; - u8 tempfid; - u8 tempvid; - int swaps = 1; - - while (swaps) { - swaps = 0; - for (i = 0; i < (numpstates - 1); i++) { - if (ppst[i].fid > ppst[i + 1].fid) { - swaps = 1; - tempfid = ppst[i].fid; - tempvid = ppst[i].vid; - ppst[i].fid = ppst[i + 1].fid; - ppst[i].vid = ppst[i + 1].vid; - ppst[i + 1].fid = tempfid; - ppst[i + 1].vid = tempvid; - } - } - } - - return; -} - -/* Return 1 if the pending bit is set. Unless we are actually just told the */ -/* processor to transition a state, seeing this bit set is really bad news. */ +/* + * Return 1 if the pending bit is set. Unless we are actually just told the + * processor to transition a state, seeing this bit set is really bad news. + */ static inline int pending_bit_stuck(void) { - u32 lo; - u32 hi; + u32 lo, hi; rdmsr(MSR_FIDVID_STATUS, lo, hi); return lo & MSR_S_LO_CHANGE_PENDING ? 1 : 0; } -/* Update the global current fid / vid values from the status msr. Returns 1 */ -/* on error. */ +/* + * Update the global current fid / vid values from the status msr. Returns 1 + * on error. + */ static int query_current_values_with_pending_wait(void) { - u32 lo; - u32 hi; + u32 lo, hi; u32 i = 0; lo = MSR_S_LO_CHANGE_PENDING; @@ -271,9 +225,11 @@ return 0; } -/* Reduce the vid by the max of step or reqvid. */ -/* Decreasing vid codes represent increasing voltages : */ -/* vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. */ +/* + * Reduce the vid by the max of step or reqvid. + * Decreasing vid codes represent increasing voltages: + * vid of 0 is 1.550V, vid of 0x1e is 0.800V, vid of 0x1f is off. + */ static int decrease_vid_code_by_step(u32 reqvid, u32 step) { @@ -316,8 +272,10 @@ return 0; } -/* Phase 1 - core voltage transition ... setup appropriate voltage for the */ -/* fid transition. */ +/* + * Phase 1 - core voltage transition ... setup appropriate voltage for the + * fid transition. + */ static inline int core_voltage_pre_transition(u32 reqvid) { @@ -500,7 +458,9 @@ } if (c->x86_vendor != X86_VENDOR_AMD) { +#ifdef MODULE printk(KERN_INFO PFX "Not an AMD processor\n"); +#endif return 0; } @@ -533,20 +493,59 @@ return 0; } - printk(KERN_INFO PFX "Found AMD Athlon 64 / Opteron processor " - "supporting p-state transitions\n"); - + printk(KERN_INFO PFX "Found AMD64 processor supporting PowerNow (" VERSION ")\n"); return 1; } +static int check_pst_table(struct pst_s *pst, u8 maxvid) +{ + unsigned int j; + u8 lastfid = 0xFF; + + for (j = 0; j < numps; j++) { + if (pst[j].vid > LEAST_VID) { + printk(KERN_ERR PFX "vid %d invalid : 0x%x\n", j, pst[j].vid); + return -EINVAL; + } + if (pst[j].vid < rvo) { /* vid + rvo >= 0 */ + printk(KERN_ERR PFX + "BIOS error - 0 vid exceeded with pstate %d\n", + j); + return -ENODEV; + } + if (pst[j].vid < maxvid + rvo) { /* vid + rvo >= maxvid */ + printk(KERN_ERR PFX + "BIOS error - maxvid exceeded with pstate %d\n", + j); + return -ENODEV; + } + if ((pst[j].fid > MAX_FID) + || (pst[j].fid & 1) + || (pst[j].fid < HI_FID_TABLE_BOTTOM)){ + printk(KERN_ERR PFX "fid %d invalid : 0x%x\n", j, pst[j].fid); + return -EINVAL; + } + if (pst[j].fid < lastfid) + lastfid = pst[j].fid; + } + if (lastfid & 1) { + printk(KERN_ERR PFX "lastfid invalid\n"); + return -EINVAL; + } + if (lastfid > LO_FID_TABLE_TOP) { + printk(KERN_INFO PFX "first fid not from lo freq table\n"); + } + + return 0; +} + /* Find and validate the PSB/PST table in BIOS. */ static inline int find_psb_table(void) { struct psb_s *psb; struct pst_s *pst; - unsigned i, j; - u32 lastfid; + unsigned int i, j; u32 mvs; u8 maxvid; @@ -573,33 +572,19 @@ } vstable = psb->voltagestabilizationtime; - printk(KERN_INFO PFX "voltage stable time: %d (units 20us)\n", - vstable); - dprintk(KERN_DEBUG PFX "flags2: 0x%x\n", psb->flags2); rvo = psb->flags2 & 3; irt = ((psb->flags2) >> 2) & 3; mvs = ((psb->flags2) >> 4) & 3; vidmvs = 1 << mvs; batps = ((psb->flags2) >> 6) & 3; - printk(KERN_INFO PFX "p states on battery: %d ", batps); - switch (batps) { - case 0: - printk("- all available\n"); - break; - case 1: - printk("- only the minimum\n"); - break; - case 2: - printk("- only the 2 lowest\n"); - break; - case 3: - printk("- only the 3 lowest\n"); - break; - } - printk(KERN_INFO PFX "ramp voltage offset: %d\n", rvo); - printk(KERN_INFO PFX "isochronous relief time: %d\n", irt); - printk(KERN_INFO PFX "maximum voltage step: %d\n", mvs); + + printk(KERN_INFO PFX "voltage stable in %d usec", vstable * 20); + if (batps) + printk(", only %d lowest states on battery", batps); + printk(", ramp voltage offset: %d", rvo); + printk(", isochronous relief time: %d", irt); + printk(", maximum voltage step: %d\n", mvs); dprintk(KERN_DEBUG PFX "numpst: 0x%x\n", psb->numpst); if (psb->numpst != 1) { @@ -610,14 +595,13 @@ dprintk(KERN_DEBUG PFX "cpuid: 0x%x\n", psb->cpuid); plllock = psb->plllocktime; - printk(KERN_INFO PFX "pll lock time: 0x%x\n", plllock); + printk(KERN_INFO PFX "pll lock time: 0x%x, ", plllock); maxvid = psb->maxvid; - printk(KERN_INFO PFX "maxfid: 0x%x\n", psb->maxfid); - printk(KERN_INFO PFX "maxvid: 0x%x\n", maxvid); + printk("maxfid 0x%x (%d MHz), maxvid 0x%x\n", + psb->maxfid, find_freq_from_fid(psb->maxfid), maxvid); numps = psb->numpstates; - printk(KERN_INFO PFX "numpstates: 0x%x\n", numps); if (numps < 2) { printk(KERN_ERR BFX "no p states to transition\n"); return -ENODEV; @@ -636,78 +620,41 @@ "%d p-states\n", numps); } - if ((numps <= 1) || (batps <= 1)) { + if (numps <= 1) { printk(KERN_ERR PFX "only 1 p-state to transition\n"); return -ENODEV; } - ppst = kmalloc(sizeof (struct pst_s) * numps, GFP_KERNEL); - if (!ppst) { - printk(KERN_ERR PFX "ppst memory alloc failure\n"); - return -ENOMEM; - } - pst = (struct pst_s *) (psb + 1); - for (j = 0; j < numps; j++) { - ppst[j].fid = pst[j].fid; - ppst[j].vid = pst[j].vid; - printk(KERN_INFO PFX - " %d : fid 0x%x, vid 0x%x\n", j, - ppst[j].fid, ppst[j].vid); - } - sort_pst(ppst, numps); - - lastfid = ppst[0].fid; - if (lastfid > LO_FID_TABLE_TOP) - printk(KERN_INFO BFX "first fid not in lo freq tbl\n"); - - if ((lastfid > MAX_FID) || (lastfid & 1) || (ppst[0].vid > LEAST_VID)) { - printk(KERN_ERR BFX "first fid/vid bad (0x%x - 0x%x)\n", - lastfid, ppst[0].vid); - kfree(ppst); - return -ENODEV; - } + if (check_pst_table(pst, maxvid)) + return -EINVAL; - for (j = 1; j < numps; j++) { - if ((lastfid >= ppst[j].fid) - || (ppst[j].fid & 1) - || (ppst[j].fid < HI_FID_TABLE_BOTTOM) - || (ppst[j].fid > MAX_FID) - || (ppst[j].vid > LEAST_VID)) { - printk(KERN_ERR BFX - "invalid fid/vid in pst(%x %x)\n", - ppst[j].fid, ppst[j].vid); - kfree(ppst); - return -ENODEV; - } - lastfid = ppst[j].fid; + powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) * (numps + 1)), GFP_KERNEL); + if (!powernow_table) { + printk(KERN_ERR PFX "powernow_table memory alloc failure\n"); + return -ENOMEM; } for (j = 0; j < numps; j++) { - if (ppst[j].vid < rvo) { /* vid+rvo >= 0 */ - printk(KERN_ERR BFX - "0 vid exceeded with pstate %d\n", j); - kfree(ppst); - return -ENODEV; - } - if (ppst[j].vid < maxvid+rvo) { /* vid+rvo >= maxvid */ - printk(KERN_ERR BFX - "maxvid exceeded with pstate %d\n", j); - kfree(ppst); - return -ENODEV; - } + printk(KERN_INFO PFX " %d : fid 0x%x (%d MHz), vid 0x%x\n", j, + pst[j].fid, find_freq_from_fid(pst[j].fid), pst[j].vid); + powernow_table[j].index = pst[j].fid; /* lower 8 bits */ + powernow_table[j].index |= (pst[j].vid << 8); /* upper 8 bits */ + powernow_table[j].frequency = find_freq_from_fid(pst[j].fid); } + powernow_table[numps].frequency = CPUFREQ_TABLE_END; + powernow_table[numps].index = 0; if (query_current_values_with_pending_wait()) { - kfree(ppst); + kfree(powernow_table); return -EIO; } - printk(KERN_INFO PFX "currfid 0x%x, currvid 0x%x\n", - currfid, currvid); + printk(KERN_INFO PFX "currfid 0x%x (%d MHz), currvid 0x%x\n", + currfid, find_freq_from_fid(currfid), currvid); for (j = 0; j < numps; j++) - if ((ppst[j].fid==currfid) && (ppst[j].vid==currvid)) + if ((pst[j].fid==currfid) && (pst[j].vid==currvid)) return 0; printk(KERN_ERR BFX "currfid/vid do not match PST, ignoring\n"); @@ -718,112 +665,22 @@ return -ENODEV; } -/* Converts a frequency (that might not necessarily be a multiple of 200) */ -/* to a fid. */ -static u32 -find_closest_fid(u32 freq, int searchup) -{ - if (searchup == SEARCH_UP) - freq += MIN_FREQ_RESOLUTION - 1; - - freq = (freq / MIN_FREQ_RESOLUTION) * MIN_FREQ_RESOLUTION; - - if (freq < MIN_FREQ) - freq = MIN_FREQ; - else if (freq > MAX_FREQ) - freq = MAX_FREQ; - - return find_fid_from_freq(freq); -} - -static int -find_match(u32 * ptargfreq, u32 * pmin, u32 * pmax, int searchup, u32 * pfid, - u32 * pvid) -{ - u32 availpstates = batps; - u32 targfid = find_closest_fid(*ptargfreq, searchup); - u32 minfid = find_closest_fid(*pmin, SEARCH_DOWN); - u32 maxfid = find_closest_fid(*pmax, SEARCH_UP); - u32 minidx = 0; - u32 maxidx = availpstates - 1; - u32 targidx = 0xffffffff; - int i; - - dprintk(KERN_DEBUG PFX "find match: freq %d MHz, min %d, max %d\n", - *ptargfreq, *pmin, *pmax); - - /* Restrict values to the frequency choices in the PST */ - if (minfid < ppst[0].fid) - minfid = ppst[0].fid; - if (maxfid > ppst[maxidx].fid) - maxfid = ppst[maxidx].fid; - - /* Find appropriate PST index for the minimim fid */ - for (i = 0; i < (int) availpstates; i++) { - if (minfid >= ppst[i].fid) - minidx = i; - } - - /* Find appropriate PST index for the maximum fid */ - for (i = availpstates - 1; i >= 0; i--) { - if (maxfid <= ppst[i].fid) - maxidx = i; - } - - if (minidx > maxidx) - maxidx = minidx; - - /* Frequency ids are now constrained by limits matching PST entries */ - minfid = ppst[minidx].fid; - maxfid = ppst[maxidx].fid; - - /* Limit the target frequency to these limits */ - if (targfid < minfid) - targfid = minfid; - else if (targfid > maxfid) - targfid = maxfid; - - /* Find the best target index into the PST, contrained by the range */ - if (searchup == SEARCH_UP) { - for (i = maxidx; i >= (int) minidx; i--) { - if (targfid <= ppst[i].fid) - targidx = i; - } - } else { - for (i = minidx; i <= (int) maxidx; i++) { - if (targfid >= ppst[i].fid) - targidx = i; - } - } - - if (targidx == 0xffffffff) { - printk(KERN_ERR PFX "could not find target\n"); - return 1; - } - - *pmin = find_freq_from_fid(minfid); - *pmax = find_freq_from_fid(maxfid); - *ptargfreq = find_freq_from_fid(ppst[targidx].fid); - - if (pfid) - *pfid = ppst[targidx].fid; - if (pvid) - *pvid = ppst[targidx].vid; - - return 0; -} - /* Take a frequency, and issue the fid/vid transition command */ static inline int -transition_frequency(u32 * preq, u32 * pmin, u32 * pmax, u32 searchup) +transition_frequency(unsigned int index) { u32 fid; u32 vid; int res; struct cpufreq_freqs freqs; - if (find_match(preq, pmin, pmax, searchup, &fid, &vid)) - return 1; + /* fid are the lower 8 bits of the index we stored into + * the cpufreq frequency table in find_psb_table, vid are + * the upper 8 bits. + */ + + fid = powernow_table[index].index & 0xFF; + vid = (powernow_table[index].index & 0xFF00) >> 8; dprintk(KERN_DEBUG PFX "table matched fid 0x%x, giving vid 0x%x\n", fid, vid); @@ -867,14 +724,7 @@ { u32 checkfid = currfid; u32 checkvid = currvid; - u32 reqfreq = targfreq / 1000; - u32 minfreq = pol->min / 1000; - u32 maxfreq = pol->max / 1000; - - if (ppst == 0) { - printk(KERN_ERR PFX "targ: ppst 0\n"); - return -ENODEV; - } + unsigned int newstate; if (pending_bit_stuck()) { printk(KERN_ERR PFX "drv targ fail: change pending bit set\n"); @@ -896,9 +746,10 @@ checkfid, currfid, checkvid, currvid); } - if (transition_frequency(&reqfreq, &minfreq, &maxfreq, - relation == - CPUFREQ_RELATION_H ? SEARCH_UP : SEARCH_DOWN)) + if (cpufreq_frequency_table_target(pol, powernow_table, targfreq, relation, &newstate)) + return -EINVAL; + + if (transition_frequency(newstate)) { printk(KERN_ERR PFX "transition frequency failed\n"); return 1; @@ -913,36 +764,12 @@ static int powernowk8_verify(struct cpufreq_policy *pol) { - u32 min = pol->min / 1000; - u32 max = pol->max / 1000; - u32 targ = min; - int res; - - if (ppst == 0) { - printk(KERN_ERR PFX "verify - ppst 0\n"); - return -ENODEV; - } - if (pending_bit_stuck()) { printk(KERN_ERR PFX "failing verify, change pending bit set\n"); return -EIO; } - dprintk(KERN_DEBUG PFX - "ver: cpu%d, min %d, max %d, cur %d, pol %d\n", pol->cpu, - pol->min, pol->max, pol->cur, pol->policy); - - if (pol->cpu != 0) { - printk(KERN_ERR PFX "verify - cpu not 0\n"); - return -ENODEV; - } - - res = find_match(&targ, &min, &max, SEARCH_DOWN, 0, 0); - if (!res) { - pol->min = min * 1000; - pol->max = max * 1000; - } - return res; + return cpufreq_frequency_table_verify(pol, powernow_table); } /* per CPU init entry point to the driver */ @@ -968,10 +795,11 @@ dprintk(KERN_DEBUG PFX "policy current frequency %d kHz\n", pol->cur); /* min/max the cpu is capable of */ - pol->cpuinfo.min_freq = 1000 * find_freq_from_fid(ppst[0].fid); - pol->cpuinfo.max_freq = 1000 * find_freq_from_fid(ppst[numps-1].fid); - pol->min = 1000 * find_freq_from_fid(ppst[0].fid); - pol->max = 1000 * find_freq_from_fid(ppst[batps - 1].fid); + if (cpufreq_frequency_table_cpuinfo(pol, powernow_table)) { + printk(KERN_ERR PFX "invalid powernow_table\n"); + kfree(powernow_table); + return -EINVAL; + } printk(KERN_INFO PFX "cpu_init done, current fid 0x%x, vid 0x%x\n", currfid, currvid); @@ -979,14 +807,33 @@ return 0; } +static int __exit powernowk8_cpu_exit (struct cpufreq_policy *pol) +{ + if (pol->cpu != 0) + return -EINVAL; + + if (powernow_table) + kfree(powernow_table); + + return 0; +} + +static struct cpufreq_driver cpufreq_amd64_driver = { + .verify = powernowk8_verify, + .target = powernowk8_target, + .init = powernowk8_cpu_init, + .exit = powernowk8_cpu_exit, + .name = "powernow-k8", + .owner = THIS_MODULE, +}; + + /* driver entry point for init */ static int __init powernowk8_init(void) { int rc; - printk(KERN_INFO PFX VERSION "\n"); - if (check_supported_cpu() == 0) return -ENODEV; @@ -996,7 +843,6 @@ if (pending_bit_stuck()) { printk(KERN_ERR PFX "powernowk8_init fail, change pending bit set\n"); - kfree(ppst); return -EIO; } @@ -1010,7 +856,6 @@ dprintk(KERN_INFO PFX "powernowk8_exit\n"); cpufreq_unregister_driver(&cpufreq_amd64_driver); - kfree(ppst); } MODULE_AUTHOR("Paul Devriendt "); diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k8.h linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/powernow-k8.h --- linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/powernow-k8.h 2004-02-14 19:30:59.000000000 -0800 @@ -120,7 +120,3 @@ static inline int core_voltage_pre_transition(u32 reqvid); static inline int core_voltage_post_transition(u32 reqvid); static inline int core_frequency_transition(u32 reqfid); -static int powernowk8_verify(struct cpufreq_policy *pol); -static int powernowk8_target(struct cpufreq_policy *pol, unsigned targfreq, - unsigned relation); -static int __init powernowk8_cpu_init(struct cpufreq_policy *pol); diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c --- linux-2.6.3-rc2/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c 2004-02-03 19:44:33.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/cpufreq/speedstep-lib.c 2004-02-14 19:30:59.000000000 -0800 @@ -207,17 +207,55 @@ if (c->x86_model != 2) return 0; - if ((c->x86_mask != 4) && /* B-stepping [M-P4-M] */ - (c->x86_mask != 7) && /* C-stepping [M-P4-M] */ - (c->x86_mask != 9)) /* D-stepping [M-P4-M or M-P4/533] */ - return 0; - ebx = cpuid_ebx(0x00000001); ebx &= 0x000000FF; - if ((ebx != 0x0e) && (ebx != 0x0f)) - return 0; - return SPEEDSTEP_PROCESSOR_P4M; + dprintk(KERN_INFO "ebx value is %x, x86_mask is %x\n", ebx, c->86_mask); + + switch (c->x86_mask) { + case 4: + /* + * B-stepping [M-P4-M] + * sample has ebx = 0x0f, production has 0x0e. + */ + if ((ebx == 0x0e) || (ebx == 0x0f)) + return SPEEDSTEP_PROCESSOR_P4M; + break; + case 7: + /* + * C-stepping [M-P4-M] + * needs to have ebx=0x0e, else it's a celeron: + * cf. 25130917.pdf / page 7, footnote 5 even + * though 25072120.pdf / page 7 doesn't say + * samples are only of B-stepping... + */ + if (ebx == 0x0e) + return SPEEDSTEP_PROCESSOR_P4M; + break; + case 9: + /* + * D-stepping [M-P4-M or M-P4/533] + * + * this is totally strange: CPUID 0x0F29 is + * used by M-P4-M, M-P4/533 and(!) Celeron CPUs. + * The latter need to be sorted out as they don't + * support speedstep. + * Celerons with CPUID 0x0F29 may have either + * ebx=0x8 or 0xf -- 25130917.pdf doesn't say anything + * specific. + * M-P4-Ms may have either ebx=0xe or 0xf [see above] + * M-P4/533 have either ebx=0xe or 0xf. [25317607.pdf] + * So, how to distinguish all those processors with + * ebx=0xf? I don't know. Sort them out, and wait + * for someone to complain. + */ + if (ebx == 0x0e) + return SPEEDSTEP_PROCESSOR_P4M; + break; + default: + break; + } + return 0; } switch (c->x86_model) { diff -urN linux-2.6.3-rc2/arch/i386/kernel/cpu/intel.c linux-2.6.3-rc3/arch/i386/kernel/cpu/intel.c --- linux-2.6.3-rc2/arch/i386/kernel/cpu/intel.c 2004-02-03 19:43:32.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/cpu/intel.c 2004-02-14 19:30:59.000000000 -0800 @@ -296,12 +296,8 @@ } else if (smp_num_siblings > 1 ) { index_lsb = 0; index_msb = 31; - /* - * At this point we only support two siblings per - * processor package. - */ -#define NR_SIBLINGS 2 - if (smp_num_siblings != NR_SIBLINGS) { + + if (smp_num_siblings > NR_CPUS) { printk(KERN_WARNING "CPU: Unsupported number of the siblings %d", smp_num_siblings); smp_num_siblings = 1; goto too_many_siblings; diff -urN linux-2.6.3-rc2/arch/i386/kernel/mpparse.c linux-2.6.3-rc3/arch/i386/kernel/mpparse.c --- linux-2.6.3-rc2/arch/i386/kernel/mpparse.c 2004-02-14 19:30:50.000000000 -0800 +++ linux-2.6.3-rc3/arch/i386/kernel/mpparse.c 2004-02-14 19:30:59.000000000 -0800 @@ -634,7 +634,7 @@ /* * ACPI may be used to obtain the entire SMP configuration or just to - * enumerate/configure processors (CONFIG_ACPI_HT). Note that + * enumerate/configure processors (CONFIG_ACPI_BOOT). Note that * ACPI supports both logical (e.g. Hyper-Threading) and physical * processors, where MPS only supports physical. */ @@ -940,7 +940,7 @@ * erroneously sets the trigger to level, resulting in a HUGE * increase of timer interrupts! */ - if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3)) + if ((bus_irq == 0) && (trigger == 3)) trigger = 1; intsrc.mpc_type = MP_INTSRC; @@ -961,7 +961,7 @@ * Otherwise create a new entry (e.g. global_irq == 2). */ for (i = 0; i < mp_irq_entries; i++) { - if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) + if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) && (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) { mp_irqs[i] = intsrc; found = 1; @@ -1008,9 +1008,10 @@ */ for (i = 0; i < 16; i++) { - if (i == 2) continue; /* Don't connect IRQ2 */ + if (i == 2) + continue; /* Don't connect IRQ2 */ - intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT; /* 8259A to #0 */ + intsrc.mpc_irqtype = mp_INT; intsrc.mpc_srcbusirq = i; /* Identity mapped */ intsrc.mpc_dstirq = i; diff -urN linux-2.6.3-rc2/arch/ia64/defconfig linux-2.6.3-rc3/arch/ia64/defconfig --- linux-2.6.3-rc2/arch/ia64/defconfig 2004-02-14 19:30:50.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/defconfig 2004-02-14 19:30:59.000000000 -0800 @@ -48,13 +48,14 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_TIME_INTERPOLATION=y +CONFIG_EFI=y # CONFIG_ITANIUM is not set CONFIG_MCKINLEY=y # CONFIG_IA64_GENERIC is not set # CONFIG_IA64_DIG is not set -# CONFIG_IA64_HP_SIM is not set CONFIG_IA64_HP_ZX1=y # CONFIG_IA64_SGI_SN2 is not set +# CONFIG_IA64_HP_SIM is not set # CONFIG_IA64_PAGE_SIZE_4KB is not set # CONFIG_IA64_PAGE_SIZE_8KB is not set CONFIG_IA64_PAGE_SIZE_16KB=y @@ -80,15 +81,14 @@ # CONFIG_HUGETLB_PAGE_SIZE_256KB is not set # CONFIG_IA64_PAL_IDLE is not set CONFIG_SMP=y +CONFIG_NR_CPUS=16 # CONFIG_PREEMPT is not set +CONFIG_HAVE_DEC_LOCK=y CONFIG_IA32_SUPPORT=y CONFIG_COMPAT=y -CONFIG_HAVE_DEC_LOCK=y CONFIG_PERFMON=y CONFIG_IA64_PALINFO=y -CONFIG_EFI=y CONFIG_EFI_VARS=y -CONFIG_NR_CPUS=16 CONFIG_BINFMT_ELF=y CONFIG_BINFMT_MISC=y @@ -140,7 +140,6 @@ # # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -179,6 +178,7 @@ # # IDE chipset support/bugfixes # +# CONFIG_IDE_GENERIC is not set CONFIG_BLK_DEV_IDEPCI=y CONFIG_IDEPCI_SHARE_IRQ=y # CONFIG_BLK_DEV_OFFBOARD is not set @@ -223,7 +223,6 @@ # # I2O device support # -# CONFIG_I2O is not set # # Multi-device support (RAID and LVM) @@ -234,6 +233,7 @@ CONFIG_MD_RAID0=m CONFIG_MD_RAID1=m CONFIG_MD_RAID5=m +# CONFIG_MD_RAID6 is not set CONFIG_MD_MULTIPATH=m CONFIG_BLK_DEV_DM=m CONFIG_DM_IOCTL_V4=y @@ -303,9 +303,15 @@ # CONFIG_SCSI_QLOGIC_ISP is not set # CONFIG_SCSI_QLOGIC_FC is not set CONFIG_SCSI_QLOGIC_1280=y +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set # CONFIG_SCSI_DC395x is not set # CONFIG_SCSI_DC390T is not set -# CONFIG_SCSI_NSP32 is not set # CONFIG_SCSI_DEBUG is not set # @@ -414,6 +420,7 @@ # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set CONFIG_EEPRO100=y # CONFIG_EEPRO100_PIO is not set @@ -539,8 +546,8 @@ # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y -CONFIG_SERIAL_8250_ACPI=y CONFIG_SERIAL_8250_HCDP=y +CONFIG_SERIAL_8250_ACPI=y CONFIG_SERIAL_8250_NR_UARTS=4 # CONFIG_SERIAL_8250_EXTENDED is not set @@ -553,24 +560,6 @@ CONFIG_UNIX98_PTY_COUNT=256 # -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Algorithms -# - -# -# I2C Hardware Bus support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# # Mice # # CONFIG_BUSMOUSE is not set @@ -610,6 +599,11 @@ # CONFIG_RAW_DRIVER is not set # +# I2C support +# +# CONFIG_I2C is not set + +# # Multimedia devices # # CONFIG_VIDEO_DEV is not set @@ -789,6 +783,7 @@ # CONFIG_FB_ATY is not set # CONFIG_FB_SIS is not set # CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set # CONFIG_FB_3DFX is not set # CONFIG_FB_VOODOO1 is not set # CONFIG_FB_TRIDENT is not set @@ -844,6 +839,7 @@ # # CONFIG_SND_ALI5451 is not set # CONFIG_SND_AZT3328 is not set +# CONFIG_SND_BT87X is not set # CONFIG_SND_CS46XX is not set # CONFIG_SND_CS4281 is not set # CONFIG_SND_EMU10K1 is not set @@ -927,7 +923,6 @@ # USB Imaging devices # # CONFIG_USB_MDC800 is not set -# CONFIG_USB_SCANNER is not set # CONFIG_USB_MICROTEK is not set # CONFIG_USB_HPUSBSCSI is not set @@ -961,12 +956,19 @@ # # USB Miscellaneous drivers # +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set # CONFIG_USB_TIGL is not set # CONFIG_USB_AUERSWALD is not set # CONFIG_USB_RIO500 is not set # CONFIG_USB_LEGOTOWER is not set # CONFIG_USB_BRLVGER is not set # CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set + +# +# USB Gadget Support +# # CONFIG_USB_GADGET is not set # @@ -988,10 +990,6 @@ CONFIG_IA64_PRINT_HAZARDS=y # CONFIG_DISABLE_VHPT is not set CONFIG_MAGIC_SYSRQ=y -CONFIG_IA64_EARLY_PRINTK=y -CONFIG_IA64_EARLY_PRINTK_UART=y -CONFIG_IA64_EARLY_PRINTK_UART_BASE=0xff5e0000 -CONFIG_IA64_EARLY_PRINTK_VGA=y # CONFIG_DEBUG_SLAB is not set # CONFIG_DEBUG_SPINLOCK is not set # CONFIG_DEBUG_SPINLOCK_SLEEP is not set diff -urN linux-2.6.3-rc2/arch/ia64/hp/common/sba_iommu.c linux-2.6.3-rc3/arch/ia64/hp/common/sba_iommu.c --- linux-2.6.3-rc2/arch/ia64/hp/common/sba_iommu.c 2004-02-03 19:43:13.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/hp/common/sba_iommu.c 2004-02-14 19:30:59.000000000 -0800 @@ -57,11 +57,21 @@ ** There's potentially a conflict in the bio merge code with us ** advertising an iommu, but then bypassing it. Since I/O MMU bypassing ** appears to give more performance than bio-level virtual merging, we'll -** do the former for now. +** do the former for now. NOTE: BYPASS_SG also needs to be undef'd to +** completely restrict DMA to the IOMMU. */ #define ALLOW_IOV_BYPASS /* +** This option specifically allows/disallows bypassing scatterlists with +** multiple entries. Coalescing these entries can allow better DMA streaming +** and in some cases shows better performance than entirely bypassing the +** IOMMU. Performance increase on the order of 1-2% sequential output/input +** using bonnie++ on a RAID0 MD device (sym2 & mpt). +*/ +#undef ALLOW_IOV_BYPASS_SG + +/* ** If a device prefetches beyond the end of a valid pdir entry, it will cause ** a hard failure, ie. MCA. Version 3.0 and later of the zx1 LBA should ** disconnect on 4k boundaries and prevent such issues. If the device is @@ -75,7 +85,10 @@ #define ENABLE_MARK_CLEAN /* -** The number of debug flags is a clue - this code is fragile. +** The number of debug flags is a clue - this code is fragile. NOTE: since +** tightening the use of res_lock the resource bitmap and actual pdir are no +** longer guaranteed to stay in sync. The sanity checking code isn't going to +** like that. */ #undef DEBUG_SBA_INIT #undef DEBUG_SBA_RUN @@ -140,9 +153,7 @@ ** allocated and free'd/purged at a time might make this ** less interesting). */ -#define DELAYED_RESOURCE_CNT 16 - -#define DEFAULT_DMA_HINT_REG 0 +#define DELAYED_RESOURCE_CNT 64 #define ZX1_IOC_ID ((PCI_DEVICE_ID_HP_ZX1_IOC << 16) | PCI_VENDOR_ID_HP) #define REO_IOC_ID ((PCI_DEVICE_ID_HP_REO_IOC << 16) | PCI_VENDOR_ID_HP) @@ -187,14 +198,15 @@ unsigned long imask; /* pdir IOV Space mask */ unsigned long *res_hint; /* next avail IOVP - circular search */ - spinlock_t res_lock; - unsigned long hint_mask_pdir; /* bits used for DMA hints */ + unsigned long dma_mask; + spinlock_t res_lock; /* protects the resource bitmap, but must be held when */ + /* clearing pdir to prevent races with allocations. */ unsigned int res_bitshift; /* from the RIGHT! */ unsigned int res_size; /* size of resource map in bytes */ - unsigned int hint_shift_pdir; - unsigned long dma_mask; #if DELAYED_RESOURCE_CNT > 0 - int saved_cnt; + spinlock_t saved_lock; /* may want to try to get this on a separate cacheline */ + /* than res_lock for bigger systems. */ + int saved_cnt; struct sba_dma_pair { dma_addr_t iova; size_t size; @@ -221,6 +233,9 @@ static struct ioc *ioc_list; static int reserve_sba_gart = 1; +static SBA_INLINE void sba_mark_invalid(struct ioc *, dma_addr_t, size_t); +static SBA_INLINE void sba_free_range(struct ioc *, dma_addr_t, size_t); + #define sba_sg_address(sg) (page_address((sg)->page) + (sg)->offset) #ifdef FULL_VALID_PDIR @@ -405,7 +420,7 @@ #define PAGES_PER_RANGE 1 /* could increase this to 4 or 8 if needed */ /* Convert from IOVP to IOVA and vice versa. */ -#define SBA_IOVA(ioc,iovp,offset,hint_reg) ((ioc->ibase) | (iovp) | (offset)) +#define SBA_IOVA(ioc,iovp,offset) ((ioc->ibase) | (iovp) | (offset)) #define SBA_IOVP(ioc,iova) ((iova) & ~(ioc->ibase)) #define PDIR_ENTRY_SIZE sizeof(u64) @@ -453,20 +468,25 @@ ASSERT(((unsigned long) ioc->res_hint & (sizeof(unsigned long) - 1UL)) == 0); ASSERT(res_ptr < res_end); - if (bits_wanted > (BITS_PER_LONG/2)) { - /* Search word at a time - no mask needed */ - for(; res_ptr < res_end; ++res_ptr) { - if (*res_ptr == 0) { - *res_ptr = RESMAP_MASK(bits_wanted); + + if (likely(bits_wanted == 1)) { + unsigned int bitshiftcnt; + for(; res_ptr < res_end ; res_ptr++) { + if (likely(*res_ptr != ~0UL)) { + bitshiftcnt = ffz(*res_ptr); + *res_ptr |= (1UL << bitshiftcnt); pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); pide <<= 3; /* convert to bit address */ - break; + pide += bitshiftcnt; + ioc->res_bitshift = bitshiftcnt + bits_wanted; + goto found_it; } } - /* point to the next word on next pass */ - res_ptr++; - ioc->res_bitshift = 0; - } else { + goto not_found; + + } + + if (likely(bits_wanted <= BITS_PER_LONG/2)) { /* ** Search the resource bit map on well-aligned values. ** "o" is the alignment. @@ -475,45 +495,72 @@ */ unsigned long o = 1 << get_iovp_order(bits_wanted << iovp_shift); uint bitshiftcnt = ROUNDUP(ioc->res_bitshift, o); - unsigned long mask; + unsigned long mask, base_mask; - if (bitshiftcnt >= BITS_PER_LONG) { - bitshiftcnt = 0; - res_ptr++; - } - mask = RESMAP_MASK(bits_wanted) << bitshiftcnt; + base_mask = RESMAP_MASK(bits_wanted); + mask = base_mask << bitshiftcnt; DBG_RES("%s() o %ld %p", __FUNCTION__, o, res_ptr); - while(res_ptr < res_end) + for(; res_ptr < res_end ; res_ptr++) { DBG_RES(" %p %lx %lx\n", res_ptr, mask, *res_ptr); ASSERT(0 != mask); - if(0 == ((*res_ptr) & mask)) { - *res_ptr |= mask; /* mark resources busy! */ - pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); - pide <<= 3; /* convert to bit address */ - pide += bitshiftcnt; - break; - } - mask <<= o; - bitshiftcnt += o; - if (0 == mask) { - mask = RESMAP_MASK(bits_wanted); - bitshiftcnt=0; - res_ptr++; + for (; mask ; mask <<= o, bitshiftcnt += o) { + if(0 == ((*res_ptr) & mask)) { + *res_ptr |= mask; /* mark resources busy! */ + pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); + pide <<= 3; /* convert to bit address */ + pide += bitshiftcnt; + ioc->res_bitshift = bitshiftcnt + bits_wanted; + goto found_it; + } } + + bitshiftcnt = 0; + mask = base_mask; + } - /* look in the same word on the next pass */ - ioc->res_bitshift = bitshiftcnt + bits_wanted; - } - /* wrapped ? */ - if (res_end <= res_ptr) { - ioc->res_hint = (unsigned long *) ioc->res_map; - ioc->res_bitshift = 0; } else { - ioc->res_hint = res_ptr; + int qwords, bits, i; + unsigned long *end; + + qwords = bits_wanted >> 6; /* /64 */ + bits = bits_wanted - (qwords * BITS_PER_LONG); + + end = res_end - qwords; + + for (; res_ptr < end; res_ptr++) { + for (i = 0 ; i < qwords ; i++) { + if (res_ptr[i] != 0) + goto next_ptr; + } + if (bits && res_ptr[i] && (__ffs(res_ptr[i]) < bits)) + continue; + + /* Found it, mark it */ + for (i = 0 ; i < qwords ; i++) + res_ptr[i] = ~0UL; + res_ptr[i] |= RESMAP_MASK(bits); + + pide = ((unsigned long)res_ptr - (unsigned long)ioc->res_map); + pide <<= 3; /* convert to bit address */ + res_ptr += qwords; + ioc->res_bitshift = bits; + goto found_it; +next_ptr: + ; + } } + +not_found: + prefetch(ioc->res_map); + ioc->res_hint = (unsigned long *) ioc->res_map; + ioc->res_bitshift = 0; + return (pide); + +found_it: + ioc->res_hint = res_ptr; return (pide); } @@ -531,26 +578,67 @@ { unsigned int pages_needed = size >> iovp_shift; #ifdef PDIR_SEARCH_TIMING - unsigned long itc_start = ia64_get_itc(); + unsigned long itc_start; #endif unsigned long pide; + unsigned long flags; ASSERT(pages_needed); - ASSERT(pages_needed <= BITS_PER_LONG); ASSERT(0 == (size & ~iovp_mask)); + spin_lock_irqsave(&ioc->res_lock, flags); + +#ifdef PDIR_SEARCH_TIMING + itc_start = ia64_get_itc(); +#endif /* ** "seek and ye shall find"...praying never hurts either... */ - pide = sba_search_bitmap(ioc, pages_needed); - if (pide >= (ioc->res_size << 3)) { + if (unlikely(pide >= (ioc->res_size << 3))) { pide = sba_search_bitmap(ioc, pages_needed); - if (pide >= (ioc->res_size << 3)) + if (unlikely(pide >= (ioc->res_size << 3))) { +#if DELAYED_RESOURCE_CNT > 0 + /* + ** With delayed resource freeing, we can give this one more shot. We're + ** getting close to being in trouble here, so do what we can to make this + ** one count. + */ + spin_lock(&ioc->saved_lock); + if (ioc->saved_cnt > 0) { + struct sba_dma_pair *d; + int cnt = ioc->saved_cnt; + + d = &(ioc->saved[ioc->saved_cnt]); + + while (cnt--) { + sba_mark_invalid(ioc, d->iova, d->size); + sba_free_range(ioc, d->iova, d->size); + d--; + } + ioc->saved_cnt = 0; + READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ + } + spin_unlock(&ioc->saved_lock); + + pide = sba_search_bitmap(ioc, pages_needed); + if (unlikely(pide >= (ioc->res_size << 3))) + panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", + ioc->ioc_hpa); +#else panic(__FILE__ ": I/O MMU @ %p is out of mapping resources\n", ioc->ioc_hpa); +#endif + } } +#ifdef PDIR_SEARCH_TIMING + ioc->avg_search[ioc->avg_idx++] = (ia64_get_itc() - itc_start) / pages_needed; + ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1; +#endif + + prefetchw(&(ioc->pdir_base[pide])); + #ifdef ASSERT_PDIR_SANITY /* verify the first enable bit is clear */ if(0x00 != ((u8 *) ioc->pdir_base)[pide*PDIR_ENTRY_SIZE + 7]) { @@ -563,10 +651,7 @@ (uint) ((unsigned long) ioc->res_hint - (unsigned long) ioc->res_map), ioc->res_bitshift ); -#ifdef PDIR_SEARCH_TIMING - ioc->avg_search[ioc->avg_idx++] = ia64_get_itc() - itc_start; - ioc->avg_idx &= SBA_SEARCH_SAMPLE - 1; -#endif + spin_unlock_irqrestore(&ioc->res_lock, flags); return (pide); } @@ -587,22 +672,33 @@ unsigned int pide = PDIR_INDEX(iovp); unsigned int ridx = pide >> 3; /* convert bit to byte address */ unsigned long *res_ptr = (unsigned long *) &((ioc)->res_map[ridx & ~RESMAP_IDX_MASK]); - int bits_not_wanted = size >> iovp_shift; + unsigned long m; - /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */ - unsigned long m = RESMAP_MASK(bits_not_wanted) << (pide & (BITS_PER_LONG - 1)); + for (; bits_not_wanted > 0 ; res_ptr++) { + + if (unlikely(bits_not_wanted > BITS_PER_LONG)) { + + /* these mappings start 64bit aligned */ + *res_ptr = 0UL; + bits_not_wanted -= BITS_PER_LONG; + pide += BITS_PER_LONG; - DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", - __FUNCTION__, (uint) iova, size, - bits_not_wanted, m, pide, res_ptr, *res_ptr); - - ASSERT(m != 0); - ASSERT(bits_not_wanted); - ASSERT((bits_not_wanted * iovp_size) <= DMA_CHUNK_SIZE); - ASSERT(bits_not_wanted <= BITS_PER_LONG); - ASSERT((*res_ptr & m) == m); /* verify same bits are set */ - *res_ptr &= ~m; + } else { + + /* 3-bits "bit" address plus 2 (or 3) bits for "byte" == bit in word */ + m = RESMAP_MASK(bits_not_wanted) << (pide & (BITS_PER_LONG - 1)); + bits_not_wanted = 0; + + DBG_RES("%s( ,%x,%x) %x/%lx %x %p %lx\n", __FUNCTION__, (uint) iova, size, + bits_not_wanted, m, pide, res_ptr, *res_ptr); + + ASSERT(m != 0); + ASSERT(bits_not_wanted); + ASSERT((*res_ptr & m) == m); /* verify same bits are set */ + *res_ptr &= ~m; + } + } } @@ -612,9 +708,6 @@ * ***************************************************************/ -#define SBA_DMA_HINT(ioc, val) ((val) << (ioc)->hint_shift_pdir) - - /** * sba_io_pdir_entry - fill in one IO PDIR entry * @pdir_ptr: pointer to IO PDIR entry @@ -764,32 +857,36 @@ sba_map_single(struct device *dev, void *addr, size_t size, int dir) { struct ioc *ioc; - unsigned long flags; dma_addr_t iovp; dma_addr_t offset; u64 *pdir_start; int pide; +#ifdef ASSERT_PDIR_SANITY + unsigned long flags; +#endif #ifdef ALLOW_IOV_BYPASS unsigned long pci_addr = virt_to_phys(addr); #endif - ioc = GET_IOC(dev); - ASSERT(ioc); - #ifdef ALLOW_IOV_BYPASS + ASSERT(to_pci_dev(dev)->dma_mask); /* ** Check if the PCI device can DMA to ptr... if so, just return ptr */ - if (dev && dev->dma_mask && (pci_addr & ~*dev->dma_mask) == 0) { + if (likely((pci_addr & ~to_pci_dev(dev)->dma_mask) == 0)) { /* ** Device is bit capable of DMA'ing to the buffer... ** just return the PCI address of ptr */ DBG_BYPASS("sba_map_single() bypass mask/addr: 0x%lx/0x%lx\n", - *dev->dma_mask, pci_addr); + to_pci_dev(dev)->dma_mask, pci_addr); return pci_addr; } #endif + ioc = GET_IOC(dev); + ASSERT(ioc); + + prefetch(ioc->res_hint); ASSERT(size > 0); ASSERT(size <= DMA_CHUNK_SIZE); @@ -800,13 +897,15 @@ /* round up to nearest iovp_size */ size = (size + offset + ~iovp_mask) & iovp_mask; - spin_lock_irqsave(&ioc->res_lock, flags); #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); if (sba_check_pdir(ioc,"Check before sba_map_single()")) panic("Sanity check failed"); + spin_unlock_irqrestore(&ioc->res_lock, flags); #endif pide = sba_alloc_range(ioc, size); + iovp = (dma_addr_t) pide << iovp_shift; DBG_RUN("%s() 0x%p -> 0x%lx\n", @@ -829,10 +928,11 @@ /* form complete address */ #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); sba_check_pdir(ioc,"Check after sba_map_single()"); -#endif spin_unlock_irqrestore(&ioc->res_lock, flags); - return SBA_IOVA(ioc, iovp, offset, DEFAULT_DMA_HINT_REG); +#endif + return SBA_IOVA(ioc, iovp, offset); } /** @@ -857,7 +957,7 @@ ASSERT(ioc); #ifdef ALLOW_IOV_BYPASS - if ((iova & ioc->imask) != ioc->ibase) { + if (likely((iova & ioc->imask) != ioc->ibase)) { /* ** Address does not fall w/in IOVA, must be bypassing */ @@ -880,14 +980,15 @@ size += offset; size = ROUNDUP(size, iovp_size); - spin_lock_irqsave(&ioc->res_lock, flags); #if DELAYED_RESOURCE_CNT > 0 + spin_lock_irqsave(&ioc->saved_lock, flags); d = &(ioc->saved[ioc->saved_cnt]); d->iova = iova; d->size = size; - if (++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT) { + if (unlikely(++(ioc->saved_cnt) >= DELAYED_RESOURCE_CNT)) { int cnt = ioc->saved_cnt; + spin_lock(&ioc->res_lock); while (cnt--) { sba_mark_invalid(ioc, d->iova, d->size); sba_free_range(ioc, d->iova, d->size); @@ -895,11 +996,15 @@ } ioc->saved_cnt = 0; READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ + spin_unlock(&ioc->res_lock); } + spin_unlock_irqrestore(&ioc->saved_lock, flags); #else /* DELAYED_RESOURCE_CNT == 0 */ + spin_lock_irqsave(&ioc->res_lock, flags); sba_mark_invalid(ioc, iova, size); sba_free_range(ioc, iova, size); READ_REG(ioc->ioc_hpa+IOC_PCOM); /* flush purges */ + spin_unlock_irqrestore(&ioc->res_lock, flags); #endif /* DELAYED_RESOURCE_CNT == 0 */ #ifdef ENABLE_MARK_CLEAN if (dir == DMA_FROM_DEVICE) { @@ -925,16 +1030,6 @@ } } #endif - spin_unlock_irqrestore(&ioc->res_lock, flags); - - /* XXX REVISIT for 2.5 Linux - need syncdma for zero-copy support. - ** For Astro based systems this isn't a big deal WRT performance. - ** As long as 2.4 kernels copyin/copyout data from/to userspace, - ** we don't need the syncdma. The issue here is I/O MMU cachelines - ** are *not* coherent in all cases. May be hwrev dependent. - ** Need to investigate more. - asm volatile("syncdma"); - */ } @@ -953,18 +1048,33 @@ void *addr; addr = (void *) __get_free_pages(flags, get_order(size)); - if (!addr) + if (unlikely(!addr)) return NULL; + memset(addr, 0, size); + *dma_handle = virt_to_phys(addr); + +#ifdef ALLOW_IOV_BYPASS + ASSERT(to_pci_dev(dev)->consistent_dma_mask); /* - * REVISIT: if sba_map_single starts needing more than dma_mask from the - * device, this needs to be updated. + ** Check if the PCI device can DMA to ptr... if so, just return ptr + */ + if (likely((*dma_handle & ~to_pci_dev(dev)->consistent_dma_mask) == 0)) { + DBG_BYPASS("sba_alloc_coherent() bypass mask/addr: 0x%lx/0x%lx\n", + to_pci_dev(dev)->consistent_dma_mask, *dma_handle); + + return addr; + } +#endif + + /* + * If device can't bypass or bypass is disabled, pass the 32bit fake + * device to map single to get an iova mapping. */ ioc = GET_IOC(dev); ASSERT(ioc); *dma_handle = sba_map_single(&ioc->sac_only_dev->dev, addr, size, 0); - memset(addr, 0, size); return addr; } @@ -1232,8 +1342,10 @@ { struct ioc *ioc; int coalesced, filled = 0; +#ifdef ASSERT_PDIR_SANITY unsigned long flags; -#ifdef ALLOW_IOV_BYPASS +#endif +#ifdef ALLOW_IOV_BYPASS_SG struct scatterlist *sg; #endif @@ -1241,8 +1353,9 @@ ioc = GET_IOC(dev); ASSERT(ioc); -#ifdef ALLOW_IOV_BYPASS - if (dev && dev->dma_mask && (ioc->dma_mask & ~*dev->dma_mask) == 0) { +#ifdef ALLOW_IOV_BYPASS_SG + ASSERT(to_pci_dev(dev)->dma_mask); + if (likely((ioc->dma_mask & ~to_pci_dev(dev)->dma_mask) == 0)) { for (sg = sglist ; filled < nents ; filled++, sg++){ sg->dma_length = sg->length; sg->dma_address = virt_to_phys(sba_sg_address(sg)); @@ -1253,21 +1366,22 @@ /* Fast path single entry scatterlists. */ if (nents == 1) { sglist->dma_length = sglist->length; - sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, - dir); + sglist->dma_address = sba_map_single(dev, sba_sg_address(sglist), sglist->length, dir); return 1; } - spin_lock_irqsave(&ioc->res_lock, flags); - #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); if (sba_check_pdir(ioc,"Check before sba_map_sg()")) { sba_dump_sg(ioc, sglist, nents); panic("Check before sba_map_sg()"); } + spin_unlock_irqrestore(&ioc->res_lock, flags); #endif + prefetch(ioc->res_hint); + /* ** First coalesce the chunks and allocate I/O pdir space ** @@ -1289,14 +1403,14 @@ filled = sba_fill_pdir(ioc, sglist, nents); #ifdef ASSERT_PDIR_SANITY + spin_lock_irqsave(&ioc->res_lock, flags); if (sba_check_pdir(ioc,"Check after sba_map_sg()")) { sba_dump_sg(ioc, sglist, nents); panic("Check after sba_map_sg()\n"); } -#endif - spin_unlock_irqrestore(&ioc->res_lock, flags); +#endif ASSERT(coalesced == filled); DBG_RUN_SG("%s() DONE %d mappings\n", __FUNCTION__, filled); @@ -1316,18 +1430,18 @@ */ void sba_unmap_sg (struct device *dev, struct scatterlist *sglist, int nents, int dir) { - struct ioc *ioc; #ifdef ASSERT_PDIR_SANITY + struct ioc *ioc; unsigned long flags; #endif DBG_RUN_SG("%s() START %d entries, %p,%x\n", __FUNCTION__, nents, sba_sg_address(sglist), sglist->length); +#ifdef ASSERT_PDIR_SANITY ioc = GET_IOC(dev); ASSERT(ioc); -#ifdef ASSERT_PDIR_SANITY spin_lock_irqsave(&ioc->res_lock, flags); sba_check_pdir(ioc,"Check before sba_unmap_sg()"); spin_unlock_irqrestore(&ioc->res_lock, flags); @@ -1478,6 +1592,9 @@ ioc_resource_init(struct ioc *ioc) { spin_lock_init(&ioc->res_lock); +#if DELAYED_RESOURCE_CNT > 0 + spin_lock_init(&ioc->saved_lock); +#endif /* resource map size dictated by pdir_size */ ioc->res_size = ioc->pdir_size / PDIR_ENTRY_SIZE; /* entries */ @@ -1689,13 +1806,13 @@ seq_printf(s, "Hewlett Packard %s IOC rev %d.%d\n", ioc->name, ((ioc->rev >> 4) & 0xF), (ioc->rev & 0xF)); - seq_printf(s, "IOVA size : %d MB\n", ioc->iov_size/(1024*1024)); + seq_printf(s, "IOVA size : %ld MB\n", ((ioc->pdir_size >> 3) * iovp_size)/(1024*1024)); seq_printf(s, "IOVA page size : %ld kb\n", iovp_size/1024); for (i = 0; i < (ioc->res_size / sizeof(unsigned long)); ++i, ++res_ptr) used += hweight64(*res_ptr); - seq_printf(s, "PDIR size : %d entries\n", ioc->res_size << 3); + seq_printf(s, "PDIR size : %d entries\n", ioc->pdir_size >> 3); seq_printf(s, "PDIR used : %d entries\n", used); #ifdef PDIR_SEARCH_TIMING @@ -1708,7 +1825,7 @@ if (ioc->avg_search[i] < min) min = ioc->avg_search[i]; } avg /= SBA_SEARCH_SAMPLE; - seq_printf(s, "Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles)\n", + seq_printf(s, "Bitmap search : %ld/%ld/%ld (min/avg/max CPU Cycles/IOVA page)\n", min, avg, max); } #endif diff -urN linux-2.6.3-rc2/arch/ia64/kernel/acpi.c linux-2.6.3-rc3/arch/ia64/kernel/acpi.c --- linux-2.6.3-rc2/arch/ia64/kernel/acpi.c 2004-02-14 19:30:50.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/acpi.c 2004-02-14 19:30:59.000000000 -0800 @@ -589,7 +589,7 @@ smp_boot_data.cpu_count = available_cpus; smp_build_cpu_map(); -# ifdef CONFIG_NUMA +# ifdef CONFIG_ACPI_NUMA if (srat_num_cpus == 0) { int cpu, i = 1; for (cpu = 0; cpu < smp_boot_data.cpu_count; cpu++) diff -urN linux-2.6.3-rc2/arch/ia64/kernel/efivars.c linux-2.6.3-rc3/arch/ia64/kernel/efivars.c --- linux-2.6.3-rc2/arch/ia64/kernel/efivars.c 2004-02-03 19:43:45.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/efivars.c 2004-02-14 19:30:59.000000000 -0800 @@ -29,9 +29,12 @@ * * Changelog: * + * 10 Feb 2004 - Stephane Eranian + * Provide FPSWA version number via /proc/efi/fpswa + * * 10 Dec 2002 - Matt Domsch * fix locking per Peter Chubb's findings - * + * * 25 Mar 2002 - Matt Domsch * move uuid_unparse() to include/asm-ia64/efi.h:efi_guid_unparse() * @@ -70,6 +73,7 @@ #include #include +#include #include MODULE_AUTHOR("Matt Domsch "); @@ -407,6 +411,37 @@ .read = efi_systab_read, }; +static ssize_t +efi_fpswa_read (struct file *file, char *buffer, size_t count, loff_t *ppos) +{ + ssize_t size, length; + char str[32]; + void *data; + + snprintf(str, sizeof(str), "revision=%u.%u\n", + fpswa_interface->revision >> 16, fpswa_interface->revision & 0xffff); + + length = strlen(str); + + if (*ppos >= length) + return 0; + + data = str + file->f_pos; + size = length - file->f_pos; + if (size > count) + size = count; + if (copy_to_user(buffer, data, size)) + return -EFAULT; + + *ppos += size; + return size; +} + +static struct proc_dir_entry *efi_fpswa_entry; +static struct file_operations efi_fpswa_fops = { + .read = efi_fpswa_read, +}; + static int __init efivars_init(void) { @@ -429,6 +464,12 @@ if (efi_systab_entry) efi_systab_entry->proc_fops = &efi_systab_fops; + if (fpswa_interface) { + efi_fpswa_entry = create_proc_entry("fpswa", S_IRUGO, efi_dir); + if (efi_fpswa_entry) + efi_fpswa_entry->proc_fops = &efi_fpswa_fops; + } + efi_vars_dir = proc_mkdir("vars", efi_dir); /* Per EFI spec, the maximum storage allocated for both diff -urN linux-2.6.3-rc2/arch/ia64/kernel/irq.c linux-2.6.3-rc3/arch/ia64/kernel/irq.c --- linux-2.6.3-rc2/arch/ia64/kernel/irq.c 2004-02-03 19:44:30.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/irq.c 2004-02-14 19:30:59.000000000 -0800 @@ -465,8 +465,6 @@ desc->handler->ack(irq); action_ret = handle_IRQ_event(irq, regs, desc->action); desc->handler->end(irq); - if (!noirqdebug) - note_interrupt(irq, desc, action_ret); } else { spin_lock(&desc->lock); desc->handler->ack(irq); diff -urN linux-2.6.3-rc2/arch/ia64/kernel/mca.c linux-2.6.3-rc3/arch/ia64/kernel/mca.c --- linux-2.6.3-rc2/arch/ia64/kernel/mca.c 2004-02-03 19:43:46.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/mca.c 2004-02-14 19:30:59.000000000 -0800 @@ -18,7 +18,7 @@ * Copyright (C) 2000 Intel * Copyright (C) Chuck Fleckenstein (cfleck@co.intel.com) * - * Copyright (C) 1999 Silicon Graphics, Inc. + * Copyright (C) 1999, 2004 Silicon Graphics, Inc. * Copyright (C) Vijay Chander(vijay@engr.sgi.com) * * 03/04/15 D. Mosberger Added INIT backtrace support. @@ -40,6 +40,14 @@ * 2003-12-08 Keith Owens * smp_call_function() must not be called from interrupt context (can * deadlock on tasklist_lock). Use keventd to call smp_call_function(). + * + * 2004-02-01 Keith Owens + * Avoid deadlock when using printk() for MCA and INIT records. + * Delete all record printing code, moved to salinfo_decode in user space. + * Mark variables and functions static where possible. + * Delete dead variables and functions. + * Reorder to remove the need for forward declarations and to consolidate + * related code. */ #include #include @@ -68,14 +76,18 @@ #include #include -#undef MCA_PRT_XTRA_DATA +#if defined(IA64_MCA_DEBUG_INFO) +# define IA64_MCA_DEBUG(fmt...) printk(fmt) +#else +# define IA64_MCA_DEBUG(fmt...) +#endif typedef struct ia64_fptr { unsigned long fp; unsigned long gp; } ia64_fptr_t; -ia64_mc_info_t ia64_mc_info; +/* Used by mca_asm.S */ ia64_mca_sal_to_os_state_t ia64_sal_to_os_handoff_state; ia64_mca_os_to_sal_state_t ia64_os_to_sal_handoff_state; u64 ia64_mca_proc_state_dump[512]; @@ -83,56 +95,17 @@ u64 ia64_mca_stackframe[32]; u64 ia64_mca_bspstore[1024]; u64 ia64_init_stack[KERNEL_STACK_SIZE/8] __attribute__((aligned(16))); -u64 ia64_os_mca_recovery_successful; u64 ia64_mca_serialize; -static void ia64_mca_wakeup_ipi_wait(void); -static void ia64_mca_wakeup(int cpu); -static void ia64_mca_wakeup_all(void); -static void ia64_log_init(int); + +/* In mca_asm.S */ extern void ia64_monarch_init_handler (void); extern void ia64_slave_init_handler (void); -static u64 ia64_log_get(int sal_info_type, u8 **buffer); -extern struct hw_interrupt_type irq_type_iosapic_level; - -struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS]; - -static struct irqaction cmci_irqaction = { - .handler = ia64_mca_cmc_int_handler, - .flags = SA_INTERRUPT, - .name = "cmc_hndlr" -}; - -static struct irqaction cmcp_irqaction = { - .handler = ia64_mca_cmc_int_caller, - .flags = SA_INTERRUPT, - .name = "cmc_poll" -}; - -static struct irqaction mca_rdzv_irqaction = { - .handler = ia64_mca_rendez_int_handler, - .flags = SA_INTERRUPT, - .name = "mca_rdzv" -}; -static struct irqaction mca_wkup_irqaction = { - .handler = ia64_mca_wakeup_int_handler, - .flags = SA_INTERRUPT, - .name = "mca_wkup" -}; +static ia64_mc_info_t ia64_mc_info; -#ifdef CONFIG_ACPI -static struct irqaction mca_cpe_irqaction = { - .handler = ia64_mca_cpe_int_handler, - .flags = SA_INTERRUPT, - .name = "cpe_hndlr" -}; +extern struct hw_interrupt_type irq_type_iosapic_level; -static struct irqaction mca_cpep_irqaction = { - .handler = ia64_mca_cpe_int_caller, - .flags = SA_INTERRUPT, - .name = "cpe_poll" -}; -#endif /* CONFIG_ACPI */ +struct ia64_mca_tlb_info ia64_mca_tlb_list[NR_CPUS]; #define MAX_CPE_POLL_INTERVAL (15*60*HZ) /* 15 minutes */ #define MIN_CPE_POLL_INTERVAL (2*60*HZ) /* 2 minutes */ @@ -156,65 +129,157 @@ */ static int cpe_poll_enabled = 1; -extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size); +extern void salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe); + +/* + * IA64_MCA log support + */ +#define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */ +#define IA64_MAX_LOG_TYPES 4 /* MCA, INIT, CMC, CPE */ + +typedef struct ia64_state_log_s +{ + spinlock_t isl_lock; + int isl_index; + unsigned long isl_count; + ia64_err_rec_t *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */ +} ia64_state_log_t; + +static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; + +#define IA64_LOG_ALLOCATE(it, size) \ + {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \ + (ia64_err_rec_t *)alloc_bootmem(size); \ + ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \ + (ia64_err_rec_t *)alloc_bootmem(size);} +#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock) +#define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s) +#define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s) +#define IA64_LOG_NEXT_INDEX(it) ia64_state_log[it].isl_index +#define IA64_LOG_CURR_INDEX(it) 1 - ia64_state_log[it].isl_index +#define IA64_LOG_INDEX_INC(it) \ + {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \ + ia64_state_log[it].isl_count++;} +#define IA64_LOG_INDEX_DEC(it) \ + ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index +#define IA64_LOG_NEXT_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)])) +#define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])) +#define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count + +/* + * ia64_log_init + * Reset the OS ia64 log buffer + * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) + * Outputs : None + */ +static void +ia64_log_init(int sal_info_type) +{ + u64 max_size = 0; + + IA64_LOG_NEXT_INDEX(sal_info_type) = 0; + IA64_LOG_LOCK_INIT(sal_info_type); + + // SAL will tell us the maximum size of any error record of this type + max_size = ia64_sal_get_state_info_size(sal_info_type); + if (!max_size) + /* alloc_bootmem() doesn't like zero-sized allocations! */ + return; + + // set up OS data structures to hold error info + IA64_LOG_ALLOCATE(sal_info_type, max_size); + memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size); + memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size); +} + +/* + * ia64_log_get + * + * Get the current MCA log from SAL and copy it into the OS log buffer. + * + * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) + * irq_safe whether you can use printk at this point + * Outputs : size (total record length) + * *buffer (ptr to error record) + * + */ +static u64 +ia64_log_get(int sal_info_type, u8 **buffer, int irq_safe) +{ + sal_log_record_header_t *log_buffer; + u64 total_len = 0; + int s; + + IA64_LOG_LOCK(sal_info_type); + + /* Get the process state information */ + log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type); + + total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer); + + if (total_len) { + IA64_LOG_INDEX_INC(sal_info_type); + IA64_LOG_UNLOCK(sal_info_type); + if (irq_safe) { + IA64_MCA_DEBUG("%s: SAL error record type %d retrieved. " + "Record length = %ld\n", __FUNCTION__, sal_info_type, total_len); + } + *buffer = (u8 *) log_buffer; + return total_len; + } else { + IA64_LOG_UNLOCK(sal_info_type); + return 0; + } +} /* * ia64_mca_log_sal_error_record * - * This function retrieves a specified error record type from SAL, - * wakes up any processes waiting for error records, and sends it to - * the system log. + * This function retrieves a specified error record type from SAL + * and wakes up any processes waiting for error records. * * Inputs : sal_info_type (Type of error record MCA/CMC/CPE/INIT) - * Outputs : platform error status */ -int -ia64_mca_log_sal_error_record(int sal_info_type, int called_from_init) +static void +ia64_mca_log_sal_error_record(int sal_info_type) { u8 *buffer; u64 size; - int platform_err; + int irq_safe = sal_info_type != SAL_INFO_TYPE_MCA && sal_info_type != SAL_INFO_TYPE_INIT; + static const char * const rec_name[] = { "MCA", "INIT", "CMC", "CPE" }; - size = ia64_log_get(sal_info_type, &buffer); + size = ia64_log_get(sal_info_type, &buffer, irq_safe); if (!size) - return 0; + return; - /* TODO: - * 1. analyze error logs to determine recoverability - * 2. perform error recovery procedures, if applicable - * 3. set ia64_os_mca_recovery_successful flag, if applicable - */ + salinfo_log_wakeup(sal_info_type, buffer, size, irq_safe); + + if (irq_safe) + printk(KERN_INFO "CPU %d: SAL log contains %s error record\n", + smp_processor_id(), + sal_info_type < ARRAY_SIZE(rec_name) ? rec_name[sal_info_type] : "UNKNOWN"); - salinfo_log_wakeup(sal_info_type, buffer, size); - platform_err = ia64_log_print(sal_info_type, (prfunc_t)printk); /* Clear logs from corrected errors in case there's no user-level logger */ if (sal_info_type == SAL_INFO_TYPE_CPE || sal_info_type == SAL_INFO_TYPE_CMC) ia64_sal_clear_state_info(sal_info_type); - - return platform_err; } /* * platform dependent error handling */ #ifndef PLATFORM_MCA_HANDLERS -void -mca_handler_platform (void) -{ - -} -irqreturn_t +static irqreturn_t ia64_mca_cpe_int_handler (int cpe_irq, void *arg, struct pt_regs *ptregs) { - IA64_MCA_DEBUG("ia64_mca_cpe_int_handler: received interrupt. CPU:%d vector = %#x\n", - smp_processor_id(), cpe_irq); + IA64_MCA_DEBUG("%s: received interrupt. CPU:%d vector = %#x\n", + __FUNCTION__, smp_processor_id(), cpe_irq); /* SAL spec states this should run w/ interrupts enabled */ local_irq_enable(); /* Get the CMC error record and log it */ - ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE, 0); + ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE); return IRQ_HANDLED; } @@ -356,7 +421,7 @@ PUT_NAT_BIT(sw->caller_unat, &pt->r30); PUT_NAT_BIT(sw->caller_unat, &pt->r31); } -void +static void init_handler_platform (pal_min_state_area_t *ms, struct pt_regs *pt, struct switch_stack *sw) { @@ -403,48 +468,6 @@ while (1); /* hang city if no debugger */ } -/* - * ia64_mca_init_platform - * - * External entry for platform specific MCA initialization. - * - * Inputs - * None - * - * Outputs - * None - */ -void -ia64_mca_init_platform (void) -{ - -} - -/* - * ia64_mca_check_errors - * - * External entry to check for error records which may have been posted by SAL - * for a prior failure which resulted in a machine shutdown before an the - * error could be logged. This function must be called after the filesystem - * is initialized. - * - * Inputs : None - * - * Outputs : None - */ -int -ia64_mca_check_errors (void) -{ - /* - * If there is an MCA error record pending, get it and log it. - */ - ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 1); - - return 0; -} - -device_initcall(ia64_mca_check_errors); - #ifdef CONFIG_ACPI /* * ia64_mca_register_cpev @@ -465,13 +488,13 @@ isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_CPE_INT, SAL_MC_PARAM_MECHANISM_INT, cpev, 0, 0); if (isrv.status) { - printk(KERN_ERR "ia64_mca_platform_init: failed to register Corrected " - "Platform Error interrupt vector with SAL.\n"); + printk(KERN_ERR "Failed to register Corrected Platform " + "Error interrupt vector with SAL (status %ld)\n", isrv.status); return; } - IA64_MCA_DEBUG("ia64_mca_platform_init: corrected platform error " - "vector %#x setup and enabled\n", cpev); + IA64_MCA_DEBUG("%s: corrected platform error " + "vector %#x setup and enabled\n", __FUNCTION__, cpev); } #endif /* CONFIG_ACPI */ @@ -499,12 +522,12 @@ cmcv.cmcv_vector = IA64_CMC_VECTOR; ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval); - IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d corrected " + IA64_MCA_DEBUG("%s: CPU %d corrected " "machine check vector %#x setup and enabled.\n", - smp_processor_id(), IA64_CMC_VECTOR); + __FUNCTION__, smp_processor_id(), IA64_CMC_VECTOR); - IA64_MCA_DEBUG("ia64_mca_platform_init: CPU %d CMCV = %#016lx\n", - smp_processor_id(), ia64_getreg(_IA64_REG_CR_CMCV)); + IA64_MCA_DEBUG("%s: CPU %d CMCV = %#016lx\n", + __FUNCTION__, smp_processor_id(), ia64_getreg(_IA64_REG_CR_CMCV)); } /* @@ -519,7 +542,7 @@ * Outputs * None */ -void +static void ia64_mca_cmc_vector_disable (void *dummy) { cmcv_reg_t cmcv; @@ -529,9 +552,9 @@ cmcv.cmcv_mask = 1; /* Mask/disable interrupt */ ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval) - IA64_MCA_DEBUG("ia64_mca_cmc_vector_disable: CPU %d corrected " + IA64_MCA_DEBUG("%s: CPU %d corrected " "machine check vector %#x disabled.\n", - smp_processor_id(), cmcv.cmcv_vector); + __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector); } /* @@ -546,7 +569,7 @@ * Outputs * None */ -void +static void ia64_mca_cmc_vector_enable (void *dummy) { cmcv_reg_t cmcv; @@ -556,63 +579,9 @@ cmcv.cmcv_mask = 0; /* Unmask/enable interrupt */ ia64_setreg(_IA64_REG_CR_CMCV, cmcv.cmcv_regval) - IA64_MCA_DEBUG("ia64_mca_cmc_vector_enable: CPU %d corrected " + IA64_MCA_DEBUG("%s: CPU %d corrected " "machine check vector %#x enabled.\n", - smp_processor_id(), cmcv.cmcv_vector); -} - - -#if defined(MCA_TEST) - -sal_log_processor_info_t slpi_buf; - -void -mca_test(void) -{ - slpi_buf.valid.psi_static_struct = 1; - slpi_buf.valid.num_cache_check = 1; - slpi_buf.valid.num_tlb_check = 1; - slpi_buf.valid.num_bus_check = 1; - slpi_buf.valid.processor_static_info.minstate = 1; - slpi_buf.valid.processor_static_info.br = 1; - slpi_buf.valid.processor_static_info.cr = 1; - slpi_buf.valid.processor_static_info.ar = 1; - slpi_buf.valid.processor_static_info.rr = 1; - slpi_buf.valid.processor_static_info.fr = 1; - - ia64_os_mca_dispatch(); -} - -#endif /* #if defined(MCA_TEST) */ - - -/* - * verify_guid - * - * Compares a test guid to a target guid and returns result. - * - * Inputs - * test_guid * (ptr to guid to be verified) - * target_guid * (ptr to standard guid to be verified against) - * - * Outputs - * 0 (test verifies against target) - * non-zero (test guid does not verify) - */ -static int -verify_guid (efi_guid_t *test, efi_guid_t *target) -{ - int rc; -#ifdef IA64_MCA_DEBUG_INFO - char out[40]; -#endif - - if ((rc = efi_guidcmp(*test, *target))) { - IA64_MCA_DEBUG(KERN_DEBUG - "verify_guid: invalid GUID = %s\n", - efi_guid_unparse(test, out)); - } - return rc; + __FUNCTION__, smp_processor_id(), cmcv.cmcv_vector); } /* @@ -640,224 +609,39 @@ } /* - * ia64_mca_init - * - * Do all the system level mca specific initialization. - * - * 1. Register spinloop and wakeup request interrupt vectors - * - * 2. Register OS_MCA handler entry point - * - * 3. Register OS_INIT handler entry point - * - * 4. Initialize MCA/CMC/INIT related log buffers maintained by the OS. + * ia64_mca_wakeup_ipi_wait * - * Note that this initialization is done very early before some kernel - * services are available. + * Wait for the inter-cpu interrupt to be sent by the + * monarch processor once it is done with handling the + * MCA. * * Inputs : None - * * Outputs : None */ -void __init -ia64_mca_init(void) +static void +ia64_mca_wakeup_ipi_wait(void) { - ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler; - ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler; - ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch; - int i; - s64 rc; - struct ia64_sal_retval isrv; - u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ + int irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6); + int irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f); + u64 irr = 0; - IA64_MCA_DEBUG("ia64_mca_init: begin\n"); - - /* initialize recovery success indicator */ - ia64_os_mca_recovery_successful = 0; - - /* Clear the Rendez checkin flag for all cpus */ - for(i = 0 ; i < NR_CPUS; i++) - ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; - - /* - * Register the rendezvous spinloop and wakeup mechanism with SAL - */ - - /* Register the rendezvous interrupt vector with SAL */ - while (1) { - isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT, - SAL_MC_PARAM_MECHANISM_INT, - IA64_MCA_RENDEZ_VECTOR, - timeout, - SAL_MC_PARAM_RZ_ALWAYS); - rc = isrv.status; - if (rc == 0) - break; - if (rc == -2) { - printk(KERN_INFO "ia64_mca_init: increasing MCA rendezvous timeout from " - "%ld to %ld\n", timeout, isrv.v0); - timeout = isrv.v0; - continue; - } - printk(KERN_ERR "ia64_mca_init: Failed to register rendezvous interrupt " - "with SAL. rc = %ld\n", rc); - return; - } - - /* Register the wakeup interrupt vector with SAL */ - isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP, - SAL_MC_PARAM_MECHANISM_INT, - IA64_MCA_WAKEUP_VECTOR, - 0, 0); - rc = isrv.status; - if (rc) { - printk(KERN_ERR "ia64_mca_init: Failed to register wakeup interrupt with SAL. " - "rc = %ld\n", rc); - return; - } - - IA64_MCA_DEBUG("ia64_mca_init: registered mca rendezvous spinloop and wakeup mech.\n"); - - ia64_mc_info.imi_mca_handler = ia64_tpa(mca_hldlr_ptr->fp); - /* - * XXX - disable SAL checksum by setting size to 0; should be - * ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch); - */ - ia64_mc_info.imi_mca_handler_size = 0; - - /* Register the os mca handler with SAL */ - if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, - ia64_mc_info.imi_mca_handler, - ia64_tpa(mca_hldlr_ptr->gp), - ia64_mc_info.imi_mca_handler_size, - 0, 0, 0))) - { - printk(KERN_ERR "ia64_mca_init: Failed to register os mca handler with SAL. " - "rc = %ld\n", rc); - return; - } - - IA64_MCA_DEBUG("ia64_mca_init: registered os mca handler with SAL at 0x%lx, gp = 0x%lx\n", - ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp)); - - /* - * XXX - disable SAL checksum by setting size to 0, should be - * IA64_INIT_HANDLER_SIZE - */ - ia64_mc_info.imi_monarch_init_handler = ia64_tpa(mon_init_ptr->fp); - ia64_mc_info.imi_monarch_init_handler_size = 0; - ia64_mc_info.imi_slave_init_handler = ia64_tpa(slave_init_ptr->fp); - ia64_mc_info.imi_slave_init_handler_size = 0; - - IA64_MCA_DEBUG("ia64_mca_init: os init handler at %lx\n", - ia64_mc_info.imi_monarch_init_handler); - - /* Register the os init handler with SAL */ - if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, - ia64_mc_info.imi_monarch_init_handler, - ia64_tpa(ia64_getreg(_IA64_REG_GP)), - ia64_mc_info.imi_monarch_init_handler_size, - ia64_mc_info.imi_slave_init_handler, - ia64_tpa(ia64_getreg(_IA64_REG_GP)), - ia64_mc_info.imi_slave_init_handler_size))) - { - printk(KERN_ERR "ia64_mca_init: Failed to register m/s init handlers with SAL. " - "rc = %ld\n", rc); - return; - } - - IA64_MCA_DEBUG("ia64_mca_init: registered os init handler with SAL\n"); - - /* - * Configure the CMCI/P vector and handler. Interrupts for CMC are - * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c). - */ - register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction); - register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction); - ia64_mca_cmc_vector_setup(); /* Setup vector on BSP & enable */ - - /* Setup the MCA rendezvous interrupt vector */ - register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction); - - /* Setup the MCA wakeup interrupt vector */ - register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); - -#ifdef CONFIG_ACPI - /* Setup the CPE interrupt vector */ - { - irq_desc_t *desc; - unsigned int irq; - int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI); - - if (cpev >= 0) { - for (irq = 0; irq < NR_IRQS; ++irq) - if (irq_to_vector(irq) == cpev) { - desc = irq_descp(irq); - desc->status |= IRQ_PER_CPU; - desc->handler = &irq_type_iosapic_level; - setup_irq(irq, &mca_cpe_irqaction); - } - ia64_mca_register_cpev(cpev); - } - } -#endif - - /* Initialize the areas set aside by the OS to buffer the - * platform/processor error states for MCA/INIT/CMC - * handling. - */ - ia64_log_init(SAL_INFO_TYPE_MCA); - ia64_log_init(SAL_INFO_TYPE_INIT); - ia64_log_init(SAL_INFO_TYPE_CMC); - ia64_log_init(SAL_INFO_TYPE_CPE); - -#if defined(MCA_TEST) - mca_test(); -#endif /* #if defined(MCA_TEST) */ - - printk(KERN_INFO "Mca related initialization done\n"); - - /* commented out because this is done elsewhere */ -#if 0 - /* Do post-failure MCA error logging */ - ia64_mca_check_errors(); -#endif -} - -/* - * ia64_mca_wakeup_ipi_wait - * - * Wait for the inter-cpu interrupt to be sent by the - * monarch processor once it is done with handling the - * MCA. - * - * Inputs : None - * Outputs : None - */ -void -ia64_mca_wakeup_ipi_wait(void) -{ - int irr_num = (IA64_MCA_WAKEUP_VECTOR >> 6); - int irr_bit = (IA64_MCA_WAKEUP_VECTOR & 0x3f); - u64 irr = 0; - - do { - switch(irr_num) { - case 0: - irr = ia64_getreg(_IA64_REG_CR_IRR0); - break; - case 1: - irr = ia64_getreg(_IA64_REG_CR_IRR1); - break; - case 2: - irr = ia64_getreg(_IA64_REG_CR_IRR2); - break; - case 3: - irr = ia64_getreg(_IA64_REG_CR_IRR3); - break; - } - } while (!(irr & (1UL << irr_bit))) ; -} + do { + switch(irr_num) { + case 0: + irr = ia64_getreg(_IA64_REG_CR_IRR0); + break; + case 1: + irr = ia64_getreg(_IA64_REG_CR_IRR1); + break; + case 2: + irr = ia64_getreg(_IA64_REG_CR_IRR2); + break; + case 3: + irr = ia64_getreg(_IA64_REG_CR_IRR3); + break; + } + } while (!(irr & (1UL << irr_bit))) ; +} /* * ia64_mca_wakeup @@ -868,7 +652,7 @@ * Inputs : cpuid * Outputs : None */ -void +static void ia64_mca_wakeup(int cpu) { platform_send_ipi(cpu, IA64_MCA_WAKEUP_VECTOR, IA64_IPI_DM_INT, 0); @@ -884,7 +668,7 @@ * Inputs : None * Outputs : None */ -void +static void ia64_mca_wakeup_all(void) { int cpu; @@ -909,7 +693,7 @@ * Inputs : None * Outputs : None */ -irqreturn_t +static irqreturn_t ia64_mca_rendez_int_handler(int rendez_irq, void *arg, struct pt_regs *ptregs) { unsigned long flags; @@ -935,7 +719,6 @@ return IRQ_HANDLED; } - /* * ia64_mca_wakeup_int_handler * @@ -951,7 +734,7 @@ * Outputs : None * */ -irqreturn_t +static irqreturn_t ia64_mca_wakeup_int_handler(int wakeup_irq, void *arg, struct pt_regs *ptregs) { return IRQ_HANDLED; @@ -971,11 +754,9 @@ * Outputs : None */ -void -ia64_return_to_sal_check(void) +static void +ia64_return_to_sal_check(int recover) { - pal_processor_state_info_t *psp = (pal_processor_state_info_t *) - &ia64_sal_to_os_handoff_state.proc_state_param; /* Copy over some relevant stuff from the sal_to_os_mca_handoff * so that it can be used at the time of os_mca_to_sal_handoff @@ -986,15 +767,10 @@ ia64_os_to_sal_handoff_state.imots_sal_check_ra = ia64_sal_to_os_handoff_state.imsto_sal_check_ra; - /* - * Did we correct the error? At the moment the only error that - * we fix is a TLB error, if any other kind of error occurred - * we must reboot. - */ - if (psp->cc == 1 && psp->bc == 1 && psp->rc == 1 && psp->uc == 1) - ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT; - else + if (recover) ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_CORRECTED; + else + ia64_os_to_sal_handoff_state.imots_os_status = IA64_MCA_COLD_BOOT; /* Default = tell SAL to return to same context */ ia64_os_to_sal_handoff_state.imots_context = IA64_MCA_SAME_CONTEXT; @@ -1023,16 +799,12 @@ void ia64_mca_ucmc_handler(void) { - int platform_err = 0; + pal_processor_state_info_t *psp = (pal_processor_state_info_t *) + &ia64_sal_to_os_handoff_state.proc_state_param; + int recover = psp->tc && !(psp->cc || psp->bc || psp->rc || psp->uc); /* Get the MCA error record and log it */ - platform_err = ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA, 0); - - /* - * Do Platform-specific mca error handling if required. - */ - if (platform_err) - mca_handler_platform(); + ia64_mca_log_sal_error_record(SAL_INFO_TYPE_MCA); /* * Wakeup all the processors which are spinning in the rendezvous @@ -1041,7 +813,7 @@ ia64_mca_wakeup_all(); /* Return to SAL */ - ia64_return_to_sal_check(); + ia64_return_to_sal_check(recover); } static DECLARE_WORK(cmc_disable_work, ia64_mca_cmc_vector_disable_keventd, NULL); @@ -1062,21 +834,21 @@ * Outputs * None */ -irqreturn_t +static irqreturn_t ia64_mca_cmc_int_handler(int cmc_irq, void *arg, struct pt_regs *ptregs) { static unsigned long cmc_history[CMC_HISTORY_LENGTH]; static int index; static spinlock_t cmc_history_lock = SPIN_LOCK_UNLOCKED; - IA64_MCA_DEBUG("ia64_mca_cmc_int_handler: received interrupt vector = %#x on CPU %d\n", - cmc_irq, smp_processor_id()); + IA64_MCA_DEBUG("%s: received interrupt vector = %#x on CPU %d\n", + __FUNCTION__, cmc_irq, smp_processor_id()); /* SAL spec states this should run w/ interrupts enabled */ local_irq_enable(); /* Get the CMC error record and log it */ - ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC, 0); + ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CMC); spin_lock(&cmc_history_lock); if (!cmc_polling_enabled) { @@ -1100,7 +872,7 @@ * make sure there's a log somewhere that indicates * something is generating more than we can handle. */ - printk(KERN_WARNING "%s: WARNING: Switching to polling CMC handler, error records may be lost\n", __FUNCTION__); + printk(KERN_WARNING "WARNING: Switching to polling CMC handler; error records may be lost\n"); mod_timer(&cmc_poll_timer, jiffies + CMC_POLL_INTERVAL); @@ -1117,41 +889,6 @@ } /* - * IA64_MCA log support - */ -#define IA64_MAX_LOGS 2 /* Double-buffering for nested MCAs */ -#define IA64_MAX_LOG_TYPES 4 /* MCA, INIT, CMC, CPE */ - -typedef struct ia64_state_log_s -{ - spinlock_t isl_lock; - int isl_index; - unsigned long isl_count; - ia64_err_rec_t *isl_log[IA64_MAX_LOGS]; /* need space to store header + error log */ -} ia64_state_log_t; - -static ia64_state_log_t ia64_state_log[IA64_MAX_LOG_TYPES]; - -#define IA64_LOG_ALLOCATE(it, size) \ - {ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)] = \ - (ia64_err_rec_t *)alloc_bootmem(size); \ - ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)] = \ - (ia64_err_rec_t *)alloc_bootmem(size);} -#define IA64_LOG_LOCK_INIT(it) spin_lock_init(&ia64_state_log[it].isl_lock) -#define IA64_LOG_LOCK(it) spin_lock_irqsave(&ia64_state_log[it].isl_lock, s) -#define IA64_LOG_UNLOCK(it) spin_unlock_irqrestore(&ia64_state_log[it].isl_lock,s) -#define IA64_LOG_NEXT_INDEX(it) ia64_state_log[it].isl_index -#define IA64_LOG_CURR_INDEX(it) 1 - ia64_state_log[it].isl_index -#define IA64_LOG_INDEX_INC(it) \ - {ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index; \ - ia64_state_log[it].isl_count++;} -#define IA64_LOG_INDEX_DEC(it) \ - ia64_state_log[it].isl_index = 1 - ia64_state_log[it].isl_index -#define IA64_LOG_NEXT_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_NEXT_INDEX(it)])) -#define IA64_LOG_CURR_BUFFER(it) (void *)((ia64_state_log[it].isl_log[IA64_LOG_CURR_INDEX(it)])) -#define IA64_LOG_COUNT(it) ia64_state_log[it].isl_count - -/* * ia64_mca_cmc_int_caller * * Triggered by sw interrupt from CMC polling routine. Calls @@ -1165,7 +902,7 @@ * Outputs * handled */ -irqreturn_t +static irqreturn_t ia64_mca_cmc_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; @@ -1184,10 +921,10 @@ if (cpuid < NR_CPUS) { platform_send_ipi(cpuid, IA64_CMCP_VECTOR, IA64_IPI_DM_INT, 0); } else { - /* If no log recored, switch out of polling mode */ + /* If no log record, switch out of polling mode */ if (start_count == IA64_LOG_COUNT(SAL_INFO_TYPE_CMC)) { - printk(KERN_WARNING "%s: Returning to interrupt driven CMC handler\n", __FUNCTION__); + printk(KERN_WARNING "Returning to interrupt driven CMC handler\n"); schedule_work(&cmc_enable_work); cmc_polling_enabled = 0; @@ -1232,7 +969,7 @@ * Outputs * handled */ -irqreturn_t +static irqreturn_t ia64_mca_cpe_int_caller(int cpe_irq, void *arg, struct pt_regs *ptregs) { static int start_count = -1; @@ -1286,41 +1023,6 @@ } /* - * ia64_mca_late_init - * - * Opportunity to setup things that require initialization later - * than ia64_mca_init. Setup a timer to poll for CPEs if the - * platform doesn't support an interrupt driven mechanism. - * - * Inputs : None - * Outputs : Status - */ -static int __init -ia64_mca_late_init(void) -{ - init_timer(&cmc_poll_timer); - cmc_poll_timer.function = ia64_mca_cmc_poll; - - /* Reset to the correct state */ - cmc_polling_enabled = 0; - - init_timer(&cpe_poll_timer); - cpe_poll_timer.function = ia64_mca_cpe_poll; - -#ifdef CONFIG_ACPI - /* If platform doesn't support CPEI, get the timer going. */ - if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) { - register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); - ia64_mca_cpe_poll(0UL); - } -#endif - - return 0; -} - -device_initcall(ia64_mca_late_init); - -/* * C portion of the OS INIT handler * * Called from ia64_monarch_init_handler @@ -1337,6 +1039,8 @@ { pal_min_state_area_t *ms; + oops_in_progress = 1; /* avoid deadlock in printk, but it makes recovery dodgy */ + printk(KERN_INFO "Entered OS INIT handler. PSP=%lx\n", ia64_sal_to_os_handoff_state.proc_state_param); @@ -1350,1083 +1054,256 @@ init_handler_platform(ms, pt, sw); /* call platform specific routines */ } -/* - * ia64_log_prt_guid - * - * Print a formatted GUID. - * - * Inputs : p_guid (ptr to the GUID) - * prfunc (print function) - * Outputs : None - * - */ -void -ia64_log_prt_guid (efi_guid_t *p_guid, prfunc_t prfunc) -{ - char out[40]; - printk(KERN_DEBUG "GUID = %s\n", efi_guid_unparse(p_guid, out)); -} - -static void -ia64_log_hexdump(unsigned char *p, unsigned long n_ch, prfunc_t prfunc) +static int __init +ia64_mca_disable_cpe_polling(char *str) { - unsigned long i; - int j; - - if (!p) - return; - - for (i = 0; i < n_ch;) { - prfunc("%p ", (void *)p); - for (j = 0; (j < 16) && (i < n_ch); i++, j++, p++) { - prfunc("%02x ", *p); - } - prfunc("\n"); - } + cpe_poll_enabled = 0; + return 1; } -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL +__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling); -static void -ia64_log_prt_record_header (sal_log_record_header_t *rh, prfunc_t prfunc) -{ - prfunc("SAL RECORD HEADER: Record buffer = %p, header size = %ld\n", - (void *)rh, sizeof(sal_log_record_header_t)); - ia64_log_hexdump((unsigned char *)rh, sizeof(sal_log_record_header_t), - (prfunc_t)prfunc); - prfunc("Total record length = %d\n", rh->len); - ia64_log_prt_guid(&rh->platform_guid, prfunc); - prfunc("End of SAL RECORD HEADER\n"); -} +static struct irqaction cmci_irqaction = { + .handler = ia64_mca_cmc_int_handler, + .flags = SA_INTERRUPT, + .name = "cmc_hndlr" +}; -static void -ia64_log_prt_section_header (sal_log_section_hdr_t *sh, prfunc_t prfunc) -{ - prfunc("SAL SECTION HEADER: Record buffer = %p, header size = %ld\n", - (void *)sh, sizeof(sal_log_section_hdr_t)); - ia64_log_hexdump((unsigned char *)sh, sizeof(sal_log_section_hdr_t), - (prfunc_t)prfunc); - prfunc("Length of section & header = %d\n", sh->len); - ia64_log_prt_guid(&sh->guid, prfunc); - prfunc("End of SAL SECTION HEADER\n"); -} -#endif // MCA_PRT_XTRA_DATA for test only @FVL +static struct irqaction cmcp_irqaction = { + .handler = ia64_mca_cmc_int_caller, + .flags = SA_INTERRUPT, + .name = "cmc_poll" +}; -/* - * ia64_log_init - * Reset the OS ia64 log buffer - * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) - * Outputs : None - */ -void -ia64_log_init(int sal_info_type) -{ - u64 max_size = 0; +static struct irqaction mca_rdzv_irqaction = { + .handler = ia64_mca_rendez_int_handler, + .flags = SA_INTERRUPT, + .name = "mca_rdzv" +}; - IA64_LOG_NEXT_INDEX(sal_info_type) = 0; - IA64_LOG_LOCK_INIT(sal_info_type); +static struct irqaction mca_wkup_irqaction = { + .handler = ia64_mca_wakeup_int_handler, + .flags = SA_INTERRUPT, + .name = "mca_wkup" +}; - // SAL will tell us the maximum size of any error record of this type - max_size = ia64_sal_get_state_info_size(sal_info_type); - if (!max_size) - /* alloc_bootmem() doesn't like zero-sized allocations! */ - return; +#ifdef CONFIG_ACPI +static struct irqaction mca_cpe_irqaction = { + .handler = ia64_mca_cpe_int_handler, + .flags = SA_INTERRUPT, + .name = "cpe_hndlr" +}; - // set up OS data structures to hold error info - IA64_LOG_ALLOCATE(sal_info_type, max_size); - memset(IA64_LOG_CURR_BUFFER(sal_info_type), 0, max_size); - memset(IA64_LOG_NEXT_BUFFER(sal_info_type), 0, max_size); -} +static struct irqaction mca_cpep_irqaction = { + .handler = ia64_mca_cpe_int_caller, + .flags = SA_INTERRUPT, + .name = "cpe_poll" +}; +#endif /* CONFIG_ACPI */ /* - * ia64_log_get + * ia64_mca_init * - * Get the current MCA log from SAL and copy it into the OS log buffer. + * Do all the system level mca specific initialization. * - * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) - * Outputs : size (total record length) - * *buffer (ptr to error record) + * 1. Register spinloop and wakeup request interrupt vectors * - */ -static u64 -ia64_log_get(int sal_info_type, u8 **buffer) -{ - sal_log_record_header_t *log_buffer; - u64 total_len = 0; - int s; - - IA64_LOG_LOCK(sal_info_type); - - /* Get the process state information */ - log_buffer = IA64_LOG_NEXT_BUFFER(sal_info_type); - - total_len = ia64_sal_get_state_info(sal_info_type, (u64 *)log_buffer); - - if (total_len) { - IA64_LOG_INDEX_INC(sal_info_type); - IA64_LOG_UNLOCK(sal_info_type); - IA64_MCA_DEBUG("ia64_log_get: SAL error record type %d retrieved. " - "Record length = %ld\n", sal_info_type, total_len); - *buffer = (u8 *) log_buffer; - return total_len; - } else { - IA64_LOG_UNLOCK(sal_info_type); - return 0; - } -} - -/* - * ia64_log_prt_oem_data + * 2. Register OS_MCA handler entry point * - * Print OEM specific data if included. + * 3. Register OS_INIT handler entry point * - * Inputs : header_len (length passed in section header) - * sect_len (default length of section type) - * p_data (ptr to data) - * prfunc (print function) - * Outputs : None + * 4. Initialize MCA/CMC/INIT related log buffers maintained by the OS. * - */ -void -ia64_log_prt_oem_data (int header_len, int sect_len, u8 *p_data, prfunc_t prfunc) -{ - int oem_data_len, i; - - if ((oem_data_len = header_len - sect_len) > 0) { - prfunc(" OEM Specific Data:"); - for (i = 0; i < oem_data_len; i++, p_data++) - prfunc(" %02x", *p_data); - } - prfunc("\n"); -} - -/* - * ia64_log_rec_header_print + * Note that this initialization is done very early before some kernel + * services are available. * - * Log info from the SAL error record header. + * Inputs : None * - * Inputs : lh * (ptr to SAL log error record header) - * prfunc (fn ptr of log output function to use) * Outputs : None */ -void -ia64_log_rec_header_print (sal_log_record_header_t *lh, prfunc_t prfunc) -{ - prfunc("+Err Record ID: %ld SAL Rev: %2x.%02x\n", lh->id, - lh->revision.major, lh->revision.minor); - prfunc("+Time: %02x/%02x/%02x%02x %02x:%02x:%02x Severity %d\n", - lh->timestamp.slh_month, lh->timestamp.slh_day, - lh->timestamp.slh_century, lh->timestamp.slh_year, - lh->timestamp.slh_hour, lh->timestamp.slh_minute, - lh->timestamp.slh_second, lh->severity); -} - -/* - * ia64_log_processor_regs_print - * Print the contents of the saved processor register(s) in the format - * [] - * - * Inputs : regs (Register save buffer) - * reg_num (# of registers) - * reg_class (application/banked/control/bank1_general) - * reg_prefix (ar/br/cr/b1_gr) - * Outputs : None - * - */ -void -ia64_log_processor_regs_print(u64 *regs, - int reg_num, - char *reg_class, - char *reg_prefix, - prfunc_t prfunc) -{ - int i; - - prfunc("+%s Registers\n", reg_class); - for (i = 0; i < reg_num; i++) - prfunc("+ %s[%d] 0x%lx\n", reg_prefix, i, regs[i]); -} - -/* - * ia64_log_processor_fp_regs_print - * Print the contents of the saved floating page register(s) in the format - * [] - * - * Inputs: ia64_fpreg (Register save buffer) - * reg_num (# of registers) - * reg_class (application/banked/control/bank1_general) - * reg_prefix (ar/br/cr/b1_gr) - * Outputs: None - * - */ -void -ia64_log_processor_fp_regs_print (struct ia64_fpreg *regs, - int reg_num, - char *reg_class, - char *reg_prefix, - prfunc_t prfunc) +void __init +ia64_mca_init(void) { + ia64_fptr_t *mon_init_ptr = (ia64_fptr_t *)ia64_monarch_init_handler; + ia64_fptr_t *slave_init_ptr = (ia64_fptr_t *)ia64_slave_init_handler; + ia64_fptr_t *mca_hldlr_ptr = (ia64_fptr_t *)ia64_os_mca_dispatch; int i; + s64 rc; + struct ia64_sal_retval isrv; + u64 timeout = IA64_MCA_RENDEZ_TIMEOUT; /* platform specific */ - prfunc("+%s Registers\n", reg_class); - for (i = 0; i < reg_num; i++) - prfunc("+ %s[%d] 0x%lx%016lx\n", reg_prefix, i, regs[i].u.bits[1], - regs[i].u.bits[0]); -} - -static char *pal_mesi_state[] = { - "Invalid", - "Shared", - "Exclusive", - "Modified", - "Reserved1", - "Reserved2", - "Reserved3", - "Reserved4" -}; - -static char *pal_cache_op[] = { - "Unknown", - "Move in", - "Cast out", - "Coherency check", - "Internal", - "Instruction fetch", - "Implicit Writeback", - "Reserved" -}; - -/* - * ia64_log_cache_check_info_print - * Display the machine check information related to cache error(s). - * Inputs: i (Multiple errors are logged, i - index of logged error) - * cc_info * (Ptr to cache check info logged by the PAL and later - * captured by the SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_cache_check_info_print (int i, - sal_log_mod_error_info_t *cache_check_info, - prfunc_t prfunc) -{ - pal_cache_check_info_t *info; - u64 target_addr; - - if (!cache_check_info->valid.check_info) { - IA64_MCA_DEBUG("ia64_mca_log_print: invalid cache_check_info[%d]\n",i); - return; /* If check info data not valid, skip it */ - } - - info = (pal_cache_check_info_t *)&cache_check_info->check_info; - target_addr = cache_check_info->target_identifier; - - prfunc("+ Cache check info[%d]\n+", i); - prfunc(" Level: L%d,",info->level); - if (info->mv) - prfunc(" Mesi: %s,",pal_mesi_state[info->mesi]); - prfunc(" Index: %d,", info->index); - if (info->ic) - prfunc(" Cache: Instruction,"); - if (info->dc) - prfunc(" Cache: Data,"); - if (info->tl) - prfunc(" Line: Tag,"); - if (info->dl) - prfunc(" Line: Data,"); - prfunc(" Operation: %s,", pal_cache_op[info->op]); - if (info->wiv) - prfunc(" Way: %d,", info->way); - if (cache_check_info->valid.target_identifier) - /* Hope target address is saved in target_identifier */ - if (info->tv) - prfunc(" Target Addr: 0x%lx,", target_addr); - if (info->mcc) - prfunc(" MC: Corrected"); - prfunc("\n"); -} - -/* - * ia64_log_tlb_check_info_print - * Display the machine check information related to tlb error(s). - * Inputs: i (Multiple errors are logged, i - index of logged error) - * tlb_info * (Ptr to machine check info logged by the PAL and later - * captured by the SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_tlb_check_info_print (int i, - sal_log_mod_error_info_t *tlb_check_info, - prfunc_t prfunc) - -{ - pal_tlb_check_info_t *info; - - if (!tlb_check_info->valid.check_info) { - IA64_MCA_DEBUG("ia64_mca_log_print: invalid tlb_check_info[%d]\n", i); - return; /* If check info data not valid, skip it */ - } - - info = (pal_tlb_check_info_t *)&tlb_check_info->check_info; - - prfunc("+ TLB Check Info [%d]\n+", i); - if (info->itc) - prfunc(" Failure: Instruction Translation Cache"); - if (info->dtc) - prfunc(" Failure: Data Translation Cache"); - if (info->itr) { - prfunc(" Failure: Instruction Translation Register"); - prfunc(" ,Slot: %ld", info->tr_slot); - } - if (info->dtr) { - prfunc(" Failure: Data Translation Register"); - prfunc(" ,Slot: %ld", info->tr_slot); - } - if (info->mcc) - prfunc(" ,MC: Corrected"); - prfunc("\n"); -} - -/* - * ia64_log_bus_check_info_print - * Display the machine check information related to bus error(s). - * Inputs: i (Multiple errors are logged, i - index of logged error) - * bus_info * (Ptr to machine check info logged by the PAL and later - * captured by the SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_bus_check_info_print (int i, - sal_log_mod_error_info_t *bus_check_info, - prfunc_t prfunc) -{ - pal_bus_check_info_t *info; - u64 req_addr; /* Address of the requestor of the transaction */ - u64 resp_addr; /* Address of the responder of the transaction */ - u64 targ_addr; /* Address where the data was to be delivered to */ - /* or obtained from */ - - if (!bus_check_info->valid.check_info) { - IA64_MCA_DEBUG("ia64_mca_log_print: invalid bus_check_info[%d]\n", i); - return; /* If check info data not valid, skip it */ - } - - info = (pal_bus_check_info_t *)&bus_check_info->check_info; - req_addr = bus_check_info->requestor_identifier; - resp_addr = bus_check_info->responder_identifier; - targ_addr = bus_check_info->target_identifier; - - prfunc("+ BUS Check Info [%d]\n+", i); - prfunc(" Status Info: %d", info->bsi); - prfunc(" ,Severity: %d", info->sev); - prfunc(" ,Transaction Type: %d", info->type); - prfunc(" ,Transaction Size: %d", info->size); - if (info->cc) - prfunc(" ,Cache-cache-transfer"); - if (info->ib) - prfunc(" ,Error: Internal"); - if (info->eb) - prfunc(" ,Error: External"); - if (info->mcc) - prfunc(" ,MC: Corrected"); - if (info->tv) - prfunc(" ,Target Address: 0x%lx", targ_addr); - if (info->rq) - prfunc(" ,Requestor Address: 0x%lx", req_addr); - if (info->tv) - prfunc(" ,Responder Address: 0x%lx", resp_addr); - prfunc("\n"); -} + IA64_MCA_DEBUG("%s: begin\n", __FUNCTION__); -/* - * ia64_log_mem_dev_err_info_print - * - * Format and log the platform memory device error record section data. - * - * Inputs: mem_dev_err_info * (Ptr to memory device error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_mem_dev_err_info_print (sal_log_mem_dev_err_info_t *mdei, - prfunc_t prfunc) -{ - prfunc("+ Mem Error Detail: "); + /* Clear the Rendez checkin flag for all cpus */ + for(i = 0 ; i < NR_CPUS; i++) + ia64_mc_info.imi_rendez_checkin[i] = IA64_MCA_RENDEZ_CHECKIN_NOTDONE; - if (mdei->valid.error_status) - prfunc(" Error Status: %#lx,", mdei->error_status); - if (mdei->valid.physical_addr) - prfunc(" Physical Address: %#lx,", mdei->physical_addr); - if (mdei->valid.addr_mask) - prfunc(" Address Mask: %#lx,", mdei->addr_mask); - if (mdei->valid.node) - prfunc(" Node: %d,", mdei->node); - if (mdei->valid.card) - prfunc(" Card: %d,", mdei->card); - if (mdei->valid.module) - prfunc(" Module: %d,", mdei->module); - if (mdei->valid.bank) - prfunc(" Bank: %d,", mdei->bank); - if (mdei->valid.device) - prfunc(" Device: %d,", mdei->device); - if (mdei->valid.row) - prfunc(" Row: %d,", mdei->row); - if (mdei->valid.column) - prfunc(" Column: %d,", mdei->column); - if (mdei->valid.bit_position) - prfunc(" Bit Position: %d,", mdei->bit_position); - if (mdei->valid.target_id) - prfunc(" ,Target Address: %#lx,", mdei->target_id); - if (mdei->valid.requestor_id) - prfunc(" ,Requestor Address: %#lx,", mdei->requestor_id); - if (mdei->valid.responder_id) - prfunc(" ,Responder Address: %#lx,", mdei->responder_id); - if (mdei->valid.bus_spec_data) - prfunc(" Bus Specific Data: %#lx,", mdei->bus_spec_data); - prfunc("\n"); - - if (mdei->valid.oem_id) { - u8 *p_data = &(mdei->oem_id[0]); - int i; - - prfunc(" OEM Memory Controller ID:"); - for (i = 0; i < 16; i++, p_data++) - prfunc(" %02x", *p_data); - prfunc("\n"); - } + /* + * Register the rendezvous spinloop and wakeup mechanism with SAL + */ - if (mdei->valid.oem_data) { - platform_mem_dev_err_print((int)mdei->header.len, - (int)sizeof(sal_log_mem_dev_err_info_t) - 1, - &(mdei->oem_data[0]), prfunc); + /* Register the rendezvous interrupt vector with SAL */ + while (1) { + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_INT, + SAL_MC_PARAM_MECHANISM_INT, + IA64_MCA_RENDEZ_VECTOR, + timeout, + SAL_MC_PARAM_RZ_ALWAYS); + rc = isrv.status; + if (rc == 0) + break; + if (rc == -2) { + printk(KERN_INFO "Increasing MCA rendezvous timeout from " + "%ld to %ld milliseconds\n", timeout, isrv.v0); + timeout = isrv.v0; + continue; + } + printk(KERN_ERR "Failed to register rendezvous interrupt " + "with SAL (status %ld)\n", rc); + return; } -} -/* - * ia64_log_sel_dev_err_info_print - * - * Format and log the platform SEL device error record section data. - * - * Inputs: sel_dev_err_info * (Ptr to the SEL device error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_sel_dev_err_info_print (sal_log_sel_dev_err_info_t *sdei, - prfunc_t prfunc) -{ - int i; - - prfunc("+ SEL Device Error Detail: "); - - if (sdei->valid.record_id) - prfunc(" Record ID: %#x", sdei->record_id); - if (sdei->valid.record_type) - prfunc(" Record Type: %#x", sdei->record_type); - prfunc(" Time Stamp: "); - for (i = 0; i < 4; i++) - prfunc("%1d", sdei->timestamp[i]); - if (sdei->valid.generator_id) - prfunc(" Generator ID: %#x", sdei->generator_id); - if (sdei->valid.evm_rev) - prfunc(" Message Format Version: %#x", sdei->evm_rev); - if (sdei->valid.sensor_type) - prfunc(" Sensor Type: %#x", sdei->sensor_type); - if (sdei->valid.sensor_num) - prfunc(" Sensor Number: %#x", sdei->sensor_num); - if (sdei->valid.event_dir) - prfunc(" Event Direction Type: %#x", sdei->event_dir); - if (sdei->valid.event_data1) - prfunc(" Data1: %#x", sdei->event_data1); - if (sdei->valid.event_data2) - prfunc(" Data2: %#x", sdei->event_data2); - if (sdei->valid.event_data3) - prfunc(" Data3: %#x", sdei->event_data3); - prfunc("\n"); - -} - -/* - * ia64_log_pci_bus_err_info_print - * - * Format and log the platform PCI bus error record section data. - * - * Inputs: pci_bus_err_info * (Ptr to the PCI bus error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_pci_bus_err_info_print (sal_log_pci_bus_err_info_t *pbei, - prfunc_t prfunc) -{ - prfunc("+ PCI Bus Error Detail: "); - - if (pbei->valid.err_status) - prfunc(" Error Status: %#lx", pbei->err_status); - if (pbei->valid.err_type) - prfunc(" Error Type: %#x", pbei->err_type); - if (pbei->valid.bus_id) - prfunc(" Bus ID: %#x", pbei->bus_id); - if (pbei->valid.bus_address) - prfunc(" Bus Address: %#lx", pbei->bus_address); - if (pbei->valid.bus_data) - prfunc(" Bus Data: %#lx", pbei->bus_data); - if (pbei->valid.bus_cmd) - prfunc(" Bus Command: %#lx", pbei->bus_cmd); - if (pbei->valid.requestor_id) - prfunc(" Requestor ID: %#lx", pbei->requestor_id); - if (pbei->valid.responder_id) - prfunc(" Responder ID: %#lx", pbei->responder_id); - if (pbei->valid.target_id) - prfunc(" Target ID: %#lx", pbei->target_id); - if (pbei->valid.oem_data) - prfunc("\n"); - - if (pbei->valid.oem_data) { - platform_pci_bus_err_print((int)pbei->header.len, - (int)sizeof(sal_log_pci_bus_err_info_t) - 1, - &(pbei->oem_data[0]), prfunc); + /* Register the wakeup interrupt vector with SAL */ + isrv = ia64_sal_mc_set_params(SAL_MC_PARAM_RENDEZ_WAKEUP, + SAL_MC_PARAM_MECHANISM_INT, + IA64_MCA_WAKEUP_VECTOR, + 0, 0); + rc = isrv.status; + if (rc) { + printk(KERN_ERR "Failed to register wakeup interrupt with SAL " + "(status %ld)\n", rc); + return; } -} - -/* - * ia64_log_smbios_dev_err_info_print - * - * Format and log the platform SMBIOS device error record section data. - * - * Inputs: smbios_dev_err_info * (Ptr to the SMBIOS device error record - * section returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_smbios_dev_err_info_print (sal_log_smbios_dev_err_info_t *sdei, - prfunc_t prfunc) -{ - u8 i; - prfunc("+ SMBIOS Device Error Detail: "); + IA64_MCA_DEBUG("%s: registered MCA rendezvous spinloop and wakeup mech.\n", __FUNCTION__); - if (sdei->valid.event_type) - prfunc(" Event Type: %#x", sdei->event_type); - if (sdei->valid.time_stamp) { - prfunc(" Time Stamp: "); - for (i = 0; i < 6; i++) - prfunc("%d", sdei->time_stamp[i]); - } - if ((sdei->valid.data) && (sdei->valid.length)) { - prfunc(" Data: "); - for (i = 0; i < sdei->length; i++) - prfunc(" %02x", sdei->data[i]); - } - prfunc("\n"); -} + ia64_mc_info.imi_mca_handler = ia64_tpa(mca_hldlr_ptr->fp); + /* + * XXX - disable SAL checksum by setting size to 0; should be + * ia64_tpa(ia64_os_mca_dispatch_end) - ia64_tpa(ia64_os_mca_dispatch); + */ + ia64_mc_info.imi_mca_handler_size = 0; -/* - * ia64_log_pci_comp_err_info_print - * - * Format and log the platform PCI component error record section data. - * - * Inputs: pci_comp_err_info * (Ptr to the PCI component error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_pci_comp_err_info_print(sal_log_pci_comp_err_info_t *pcei, - prfunc_t prfunc) -{ - u32 n_mem_regs, n_io_regs; - u64 i, n_pci_data; - u64 *p_reg_data; - u8 *p_oem_data; - - prfunc("+ PCI Component Error Detail: "); - - if (pcei->valid.err_status) - prfunc(" Error Status: %#lx\n", pcei->err_status); - if (pcei->valid.comp_info) - prfunc(" Component Info: Vendor Id = %#x, Device Id = %#x," - " Class Code = %#x, Seg/Bus/Dev/Func = %d/%d/%d/%d\n", - pcei->comp_info.vendor_id, pcei->comp_info.device_id, - pcei->comp_info.class_code, pcei->comp_info.seg_num, - pcei->comp_info.bus_num, pcei->comp_info.dev_num, - pcei->comp_info.func_num); - - n_mem_regs = (pcei->valid.num_mem_regs) ? pcei->num_mem_regs : 0; - n_io_regs = (pcei->valid.num_io_regs) ? pcei->num_io_regs : 0; - p_reg_data = &(pcei->reg_data_pairs[0]); - p_oem_data = (u8 *)p_reg_data + - (n_mem_regs + n_io_regs) * 2 * sizeof(u64); - n_pci_data = p_oem_data - (u8 *)pcei; - - if (n_pci_data > pcei->header.len) { - prfunc(" Invalid PCI Component Error Record format: length = %ld, " - " Size PCI Data = %d, Num Mem-Map/IO-Map Regs = %ld/%ld\n", - pcei->header.len, n_pci_data, n_mem_regs, n_io_regs); + /* Register the os mca handler with SAL */ + if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_MCA, + ia64_mc_info.imi_mca_handler, + ia64_tpa(mca_hldlr_ptr->gp), + ia64_mc_info.imi_mca_handler_size, + 0, 0, 0))) + { + printk(KERN_ERR "Failed to register OS MCA handler with SAL " + "(status %ld)\n", rc); return; } - if (n_mem_regs) { - prfunc(" Memory Mapped Registers\n Address \tValue\n"); - for (i = 0; i < pcei->num_mem_regs; i++) { - prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]); - p_reg_data += 2; - } - } - if (n_io_regs) { - prfunc(" I/O Mapped Registers\n Address \tValue\n"); - for (i = 0; i < pcei->num_io_regs; i++) { - prfunc(" %#lx %#lx\n", p_reg_data[0], p_reg_data[1]); - p_reg_data += 2; - } - } - if (pcei->valid.oem_data) { - platform_pci_comp_err_print((int)pcei->header.len, n_pci_data, - p_oem_data, prfunc); - prfunc("\n"); - } -} - -/* - * ia64_log_plat_specific_err_info_print - * - * Format and log the platform specifie error record section data. - * - * Inputs: sel_dev_err_info * (Ptr to the platform specific error record - * section returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_plat_specific_err_info_print (sal_log_plat_specific_err_info_t *psei, - prfunc_t prfunc) -{ - prfunc("+ Platform Specific Error Detail: "); + IA64_MCA_DEBUG("%s: registered OS MCA handler with SAL at 0x%lx, gp = 0x%lx\n", __FUNCTION__, + ia64_mc_info.imi_mca_handler, ia64_tpa(mca_hldlr_ptr->gp)); - if (psei->valid.err_status) - prfunc(" Error Status: %#lx", psei->err_status); - if (psei->valid.guid) { - prfunc(" GUID: "); - ia64_log_prt_guid(&psei->guid, prfunc); - } - if (psei->valid.oem_data) { - platform_plat_specific_err_print((int) psei->header.len, - (char *) psei->oem_data - (char *) psei, - &psei->oem_data[0], prfunc); - } - prfunc("\n"); -} + /* + * XXX - disable SAL checksum by setting size to 0, should be + * size of the actual init handler in mca_asm.S. + */ + ia64_mc_info.imi_monarch_init_handler = ia64_tpa(mon_init_ptr->fp); + ia64_mc_info.imi_monarch_init_handler_size = 0; + ia64_mc_info.imi_slave_init_handler = ia64_tpa(slave_init_ptr->fp); + ia64_mc_info.imi_slave_init_handler_size = 0; -/* - * ia64_log_host_ctlr_err_info_print - * - * Format and log the platform host controller error record section data. - * - * Inputs: host_ctlr_err_info * (Ptr to the host controller error record - * section returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_host_ctlr_err_info_print (sal_log_host_ctlr_err_info_t *hcei, - prfunc_t prfunc) -{ - prfunc("+ Host Controller Error Detail: "); + IA64_MCA_DEBUG("%s: OS INIT handler at %lx\n", __FUNCTION__, + ia64_mc_info.imi_monarch_init_handler); - if (hcei->valid.err_status) - prfunc(" Error Status: %#lx", hcei->err_status); - if (hcei->valid.requestor_id) - prfunc(" Requestor ID: %#lx", hcei->requestor_id); - if (hcei->valid.responder_id) - prfunc(" Responder ID: %#lx", hcei->responder_id); - if (hcei->valid.target_id) - prfunc(" Target ID: %#lx", hcei->target_id); - if (hcei->valid.bus_spec_data) - prfunc(" Bus Specific Data: %#lx", hcei->bus_spec_data); - if (hcei->valid.oem_data) { - platform_host_ctlr_err_print((int)hcei->header.len, - (int)sizeof(sal_log_host_ctlr_err_info_t) - 1, - &(hcei->oem_data[0]), prfunc); + /* Register the os init handler with SAL */ + if ((rc = ia64_sal_set_vectors(SAL_VECTOR_OS_INIT, + ia64_mc_info.imi_monarch_init_handler, + ia64_tpa(ia64_getreg(_IA64_REG_GP)), + ia64_mc_info.imi_monarch_init_handler_size, + ia64_mc_info.imi_slave_init_handler, + ia64_tpa(ia64_getreg(_IA64_REG_GP)), + ia64_mc_info.imi_slave_init_handler_size))) + { + printk(KERN_ERR "Failed to register m/s INIT handlers with SAL " + "(status %ld)\n", rc); + return; } - prfunc("\n"); -} -/* - * ia64_log_plat_bus_err_info_print - * - * Format and log the platform bus error record section data. - * - * Inputs: plat_bus_err_info * (Ptr to the platform bus error record section - * returned by SAL) - * prfunc (fn ptr of print function to be used for output) - * Outputs: None - */ -void -ia64_log_plat_bus_err_info_print (sal_log_plat_bus_err_info_t *pbei, - prfunc_t prfunc) -{ - prfunc("+ Platform Bus Error Detail: "); + IA64_MCA_DEBUG("%s: registered OS INIT handler with SAL\n", __FUNCTION__); - if (pbei->valid.err_status) - prfunc(" Error Status: %#lx", pbei->err_status); - if (pbei->valid.requestor_id) - prfunc(" Requestor ID: %#lx", pbei->requestor_id); - if (pbei->valid.responder_id) - prfunc(" Responder ID: %#lx", pbei->responder_id); - if (pbei->valid.target_id) - prfunc(" Target ID: %#lx", pbei->target_id); - if (pbei->valid.bus_spec_data) - prfunc(" Bus Specific Data: %#lx", pbei->bus_spec_data); - if (pbei->valid.oem_data) { - platform_plat_bus_err_print((int)pbei->header.len, - (int)sizeof(sal_log_plat_bus_err_info_t) - 1, - &(pbei->oem_data[0]), prfunc); - } - prfunc("\n"); -} + /* + * Configure the CMCI/P vector and handler. Interrupts for CMC are + * per-processor, so AP CMC interrupts are setup in smp_callin() (smpboot.c). + */ + register_percpu_irq(IA64_CMC_VECTOR, &cmci_irqaction); + register_percpu_irq(IA64_CMCP_VECTOR, &cmcp_irqaction); + ia64_mca_cmc_vector_setup(); /* Setup vector on BSP & enable */ -/* - * ia64_log_proc_dev_err_info_print - * - * Display the processor device error record. - * - * Inputs: sal_log_processor_info_t * (Ptr to processor device error record - * section body). - * prfunc (fn ptr of print function to be used - * for output). - * Outputs: None - */ -void -ia64_log_proc_dev_err_info_print (sal_log_processor_info_t *slpi, - prfunc_t prfunc) -{ -#ifdef MCA_PRT_XTRA_DATA - size_t d_len = slpi->header.len - sizeof(sal_log_section_hdr_t); -#endif - sal_processor_static_info_t *spsi; - int i; - sal_log_mod_error_info_t *p_data; + /* Setup the MCA rendezvous interrupt vector */ + register_percpu_irq(IA64_MCA_RENDEZ_VECTOR, &mca_rdzv_irqaction); - prfunc("+Processor Device Error Info Section\n"); + /* Setup the MCA wakeup interrupt vector */ + register_percpu_irq(IA64_MCA_WAKEUP_VECTOR, &mca_wkup_irqaction); -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL +#ifdef CONFIG_ACPI + /* Setup the CPE interrupt vector */ { - char *p_data = (char *)&slpi->valid; + irq_desc_t *desc; + unsigned int irq; + int cpev = acpi_request_vector(ACPI_INTERRUPT_CPEI); - prfunc("SAL_PROC_DEV_ERR SECTION DATA: Data buffer = %p, " - "Data size = %ld\n", (void *)p_data, d_len); - ia64_log_hexdump(p_data, d_len, prfunc); - prfunc("End of SAL_PROC_DEV_ERR SECTION DATA\n"); + if (cpev >= 0) { + for (irq = 0; irq < NR_IRQS; ++irq) + if (irq_to_vector(irq) == cpev) { + desc = irq_descp(irq); + desc->status |= IRQ_PER_CPU; + desc->handler = &irq_type_iosapic_level; + setup_irq(irq, &mca_cpe_irqaction); + } + ia64_mca_register_cpev(cpev); + } } -#endif // MCA_PRT_XTRA_DATA for test only @FVL - - if (slpi->valid.proc_error_map) - prfunc(" Processor Error Map: %#lx\n", slpi->proc_error_map); - - if (slpi->valid.proc_state_param) - prfunc(" Processor State Param: %#lx\n", slpi->proc_state_parameter); - - if (slpi->valid.proc_cr_lid) - prfunc(" Processor LID: %#lx\n", slpi->proc_cr_lid); +#endif - /* - * Note: March 2001 SAL spec states that if the number of elements in any - * of the MOD_ERROR_INFO_STRUCT arrays is zero, the entire array is - * absent. Also, current implementations only allocate space for number of - * elements used. So we walk the data pointer from here on. + /* Initialize the areas set aside by the OS to buffer the + * platform/processor error states for MCA/INIT/CMC + * handling. */ - p_data = &slpi->info[0]; - - /* Print the cache check information if any*/ - for (i = 0 ; i < slpi->valid.num_cache_check; i++, p_data++) - ia64_log_cache_check_info_print(i, p_data, prfunc); - - /* Print the tlb check information if any*/ - for (i = 0 ; i < slpi->valid.num_tlb_check; i++, p_data++) - ia64_log_tlb_check_info_print(i, p_data, prfunc); - - /* Print the bus check information if any*/ - for (i = 0 ; i < slpi->valid.num_bus_check; i++, p_data++) - ia64_log_bus_check_info_print(i, p_data, prfunc); - - /* Print the reg file check information if any*/ - for (i = 0 ; i < slpi->valid.num_reg_file_check; i++, p_data++) - ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t), - prfunc); /* Just hex dump for now */ - - /* Print the ms check information if any*/ - for (i = 0 ; i < slpi->valid.num_ms_check; i++, p_data++) - ia64_log_hexdump((u8 *)p_data, sizeof(sal_log_mod_error_info_t), - prfunc); /* Just hex dump for now */ - - /* Print CPUID registers if any*/ - if (slpi->valid.cpuid_info) { - u64 *p = (u64 *)p_data; - - prfunc(" CPUID Regs: %#lx %#lx %#lx %#lx\n", p[0], p[1], p[2], p[3]); - p_data++; - } + ia64_log_init(SAL_INFO_TYPE_MCA); + ia64_log_init(SAL_INFO_TYPE_INIT); + ia64_log_init(SAL_INFO_TYPE_CMC); + ia64_log_init(SAL_INFO_TYPE_CPE); - /* Print processor static info if any */ - if (slpi->valid.psi_static_struct) { - spsi = (sal_processor_static_info_t *)p_data; - - /* Print branch register contents if valid */ - if (spsi->valid.br) - ia64_log_processor_regs_print(spsi->br, 8, "Branch", "br", - prfunc); - - /* Print control register contents if valid */ - if (spsi->valid.cr) - ia64_log_processor_regs_print(spsi->cr, 128, "Control", "cr", - prfunc); - - /* Print application register contents if valid */ - if (spsi->valid.ar) - ia64_log_processor_regs_print(spsi->ar, 128, "Application", - "ar", prfunc); - - /* Print region register contents if valid */ - if (spsi->valid.rr) - ia64_log_processor_regs_print(spsi->rr, 8, "Region", "rr", - prfunc); - - /* Print floating-point register contents if valid */ - if (spsi->valid.fr) - ia64_log_processor_fp_regs_print(spsi->fr, 128, "Floating-point", "fr", - prfunc); - } + printk(KERN_INFO "MCA related initialization done\n"); } /* - * ia64_log_processor_info_print + * ia64_mca_late_init * - * Display the processor-specific information logged by PAL as a part - * of MCA or INIT or CMC. + * Opportunity to setup things that require initialization later + * than ia64_mca_init. Setup a timer to poll for CPEs if the + * platform doesn't support an interrupt driven mechanism. * - * Inputs : lh (Pointer of the sal log header which specifies the - * format of SAL state info as specified by the SAL spec). - * prfunc (fn ptr of print function to be used for output). - * Outputs : None + * Inputs : None + * Outputs : Status */ -void -ia64_log_processor_info_print(sal_log_record_header_t *lh, prfunc_t prfunc) +static int __init +ia64_mca_late_init(void) { - sal_log_section_hdr_t *slsh; - int n_sects; - u32 ercd_pos; - - if (!lh) - return; - -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_record_header(lh, prfunc); -#endif // MCA_PRT_XTRA_DATA for test only @FVL - - if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) { - IA64_MCA_DEBUG("ia64_mca_log_print: " - "truncated SAL CMC error record. len = %d\n", - lh->len); - return; - } - - /* Print record header info */ - ia64_log_rec_header_print(lh, prfunc); - - for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) { - /* point to next section header */ - slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos); - -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_section_header(slsh, prfunc); -#endif // MCA_PRT_XTRA_DATA for test only @FVL - - if (verify_guid(&slsh->guid, &(SAL_PROC_DEV_ERR_SECT_GUID))) { - IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n"); - continue; - } - - /* - * Now process processor device error record section - */ - ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, printk); - } - - IA64_MCA_DEBUG("ia64_mca_log_print: " - "found %d sections in SAL CMC error record. len = %d\n", - n_sects, lh->len); - if (!n_sects) { - prfunc("No Processor Device Error Info Section found\n"); - return; - } -} - -/* - * ia64_log_platform_info_print - * - * Format and Log the SAL Platform Error Record. - * - * Inputs : lh (Pointer to the sal error record header with format - * specified by the SAL spec). - * prfunc (fn ptr of log output function to use) - * Outputs : platform error status - */ -int -ia64_log_platform_info_print (sal_log_record_header_t *lh, prfunc_t prfunc) -{ - sal_log_section_hdr_t *slsh; - int n_sects; - u32 ercd_pos; - int platform_err = 0; - - if (!lh) - return platform_err; - -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_record_header(lh, prfunc); -#endif // MCA_PRT_XTRA_DATA for test only @FVL - - if ((ercd_pos = sizeof(sal_log_record_header_t)) >= lh->len) { - IA64_MCA_DEBUG("ia64_mca_log_print: " - "truncated SAL error record. len = %d\n", - lh->len); - return platform_err; - } - - /* Print record header info */ - ia64_log_rec_header_print(lh, prfunc); - - for (n_sects = 0; (ercd_pos < lh->len); n_sects++, ercd_pos += slsh->len) { - /* point to next section header */ - slsh = (sal_log_section_hdr_t *)((char *)lh + ercd_pos); - -#ifdef MCA_PRT_XTRA_DATA // for test only @FVL - ia64_log_prt_section_header(slsh, prfunc); - - if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) != 0) { - size_t d_len = slsh->len - sizeof(sal_log_section_hdr_t); - char *p_data = (char *)&((sal_log_mem_dev_err_info_t *)slsh)->valid; - - prfunc("Start of Platform Err Data Section: Data buffer = %p, " - "Data size = %ld\n", (void *)p_data, d_len); - ia64_log_hexdump(p_data, d_len, prfunc); - prfunc("End of Platform Err Data Section\n"); - } -#endif // MCA_PRT_XTRA_DATA for test only @FVL + init_timer(&cmc_poll_timer); + cmc_poll_timer.function = ia64_mca_cmc_poll; - /* - * Now process CPE error record section - */ - if (efi_guidcmp(slsh->guid, SAL_PROC_DEV_ERR_SECT_GUID) == 0) { - ia64_log_proc_dev_err_info_print((sal_log_processor_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_MEM_DEV_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Memory Device Error Info Section\n"); - ia64_log_mem_dev_err_info_print((sal_log_mem_dev_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SEL_DEV_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform SEL Device Error Info Section\n"); - ia64_log_sel_dev_err_info_print((sal_log_sel_dev_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_BUS_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform PCI Bus Error Info Section\n"); - ia64_log_pci_bus_err_info_print((sal_log_pci_bus_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SMBIOS_DEV_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform SMBIOS Device Error Info Section\n"); - ia64_log_smbios_dev_err_info_print((sal_log_smbios_dev_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_PCI_COMP_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform PCI Component Error Info Section\n"); - ia64_log_pci_comp_err_info_print((sal_log_pci_comp_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_SPECIFIC_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Specific Error Info Section\n"); - ia64_log_plat_specific_err_info_print((sal_log_plat_specific_err_info_t *) - slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_HOST_CTLR_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Host Controller Error Info Section\n"); - ia64_log_host_ctlr_err_info_print((sal_log_host_ctlr_err_info_t *)slsh, - prfunc); - } else if (efi_guidcmp(slsh->guid, SAL_PLAT_BUS_ERR_SECT_GUID) == 0) { - platform_err = 1; - prfunc("+Platform Bus Error Info Section\n"); - ia64_log_plat_bus_err_info_print((sal_log_plat_bus_err_info_t *)slsh, - prfunc); - } else { - IA64_MCA_DEBUG("ia64_mca_log_print: unsupported record section\n"); - continue; - } - } + /* Reset to the correct state */ + cmc_polling_enabled = 0; - IA64_MCA_DEBUG("ia64_mca_log_print: found %d sections in SAL error record. len = %d\n", - n_sects, lh->len); - if (!n_sects) { - prfunc("No Platform Error Info Sections found\n"); - return platform_err; - } - return platform_err; -} + init_timer(&cpe_poll_timer); + cpe_poll_timer.function = ia64_mca_cpe_poll; -/* - * ia64_log_print - * - * Displays the contents of the OS error log information - * - * Inputs : info_type (SAL_INFO_TYPE_{MCA,INIT,CMC,CPE}) - * prfunc (fn ptr of log output function to use) - * Outputs : platform error status - */ -int -ia64_log_print(int sal_info_type, prfunc_t prfunc) -{ - int platform_err = 0; - - switch(sal_info_type) { - case SAL_INFO_TYPE_MCA: - prfunc("+CPU %d: SAL log contains MCA error record\n", smp_processor_id()); - ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - break; - case SAL_INFO_TYPE_INIT: - prfunc("+CPU %d: SAL log contains INIT error record\n", smp_processor_id()); - ia64_log_rec_header_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - break; - case SAL_INFO_TYPE_CMC: - prfunc("+BEGIN HARDWARE ERROR STATE AT CMC\n"); - ia64_log_processor_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - prfunc("+END HARDWARE ERROR STATE AT CMC\n"); - break; - case SAL_INFO_TYPE_CPE: - prfunc("+BEGIN HARDWARE ERROR STATE AT CPE\n"); - ia64_log_platform_info_print(IA64_LOG_CURR_BUFFER(sal_info_type), prfunc); - prfunc("+END HARDWARE ERROR STATE AT CPE\n"); - break; - default: - prfunc("+MCA UNKNOWN ERROR LOG (UNIMPLEMENTED)\n"); - break; +#ifdef CONFIG_ACPI + /* If platform doesn't support CPEI, get the timer going. */ + if (acpi_request_vector(ACPI_INTERRUPT_CPEI) < 0 && cpe_poll_enabled) { + register_percpu_irq(IA64_CPEP_VECTOR, &mca_cpep_irqaction); + ia64_mca_cpe_poll(0UL); } - return platform_err; -} +#endif -static int __init -ia64_mca_disable_cpe_polling(char *str) -{ - cpe_poll_enabled = 0; - return 1; + return 0; } -__setup("disable_cpe_poll", ia64_mca_disable_cpe_polling); +device_initcall(ia64_mca_late_init); diff -urN linux-2.6.3-rc2/arch/ia64/kernel/salinfo.c linux-2.6.3-rc3/arch/ia64/kernel/salinfo.c --- linux-2.6.3-rc2/arch/ia64/kernel/salinfo.c 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/salinfo.c 2004-02-14 19:30:59.000000000 -0800 @@ -16,6 +16,9 @@ * Cache the record across multi-block reads from user space. * Support > 64 cpus. * Delete module_exit and MOD_INC/DEC_COUNT, salinfo cannot be a module. + * + * Jan 28 2004 kaos@sgi.com + * Periodically check for outstanding MCA or INIT records. */ #include @@ -23,6 +26,7 @@ #include #include #include +#include #include #include @@ -179,6 +183,8 @@ /* This routine is invoked in interrupt context. Note: mca.c enables * interrupts before calling this code for CMC/CPE. MCA and INIT events are * not irq safe, do not call any routines that use spinlocks, they may deadlock. + * MCA and INIT records are recorded, a timer event will look for any + * outstanding events and wake up the user space code. * * The buffer passed from mca.c points to the output from ia64_log_get. This is * a persistent buffer but its contents can change between the interrupt and @@ -186,12 +192,12 @@ * changes. */ void -salinfo_log_wakeup(int type, u8 *buffer, u64 size) +salinfo_log_wakeup(int type, u8 *buffer, u64 size, int irqsafe) { struct salinfo_data *data = salinfo_data + type; struct salinfo_data_saved *data_saved; unsigned long flags = 0; - int i, irqsafe = type != SAL_INFO_TYPE_MCA && type != SAL_INFO_TYPE_INIT; + int i; int saved_size = ARRAY_SIZE(data->data_saved); BUG_ON(type >= ARRAY_SIZE(salinfo_log_name)); @@ -224,6 +230,35 @@ } } +/* Check for outstanding MCA/INIT records every 5 minutes (arbitrary) */ +#define SALINFO_TIMER_DELAY (5*60*HZ) +static struct timer_list salinfo_timer; + +static void +salinfo_timeout_check(struct salinfo_data *data) +{ + int i; + if (!data->open) + return; + for (i = 0; i < NR_CPUS; ++i) { + if (test_bit(i, &data->cpu_event)) { + /* double up() is not a problem, user space will see no + * records for the additional "events". + */ + up(&data->sem); + } + } +} + +static void +salinfo_timeout (unsigned long arg) +{ + salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_MCA); + salinfo_timeout_check(salinfo_data + SAL_INFO_TYPE_INIT); + salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY; + add_timer(&salinfo_timer); +} + static int salinfo_event_open(struct inode *inode, struct file *file) { @@ -563,6 +598,11 @@ *sdir++ = salinfo_dir; + init_timer(&salinfo_timer); + salinfo_timer.expires = jiffies + SALINFO_TIMER_DELAY; + salinfo_timer.function = &salinfo_timeout; + add_timer(&salinfo_timer); + return 0; } diff -urN linux-2.6.3-rc2/arch/ia64/kernel/smp.c linux-2.6.3-rc3/arch/ia64/kernel/smp.c --- linux-2.6.3-rc2/arch/ia64/kernel/smp.c 2004-02-03 19:45:03.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/smp.c 2004-02-14 19:30:59.000000000 -0800 @@ -18,10 +18,6 @@ * 10/13/00 Goutham Rao Updated smp_call_function and * smp_call_function_single to resend IPI on timeouts */ -#define __KERNEL_SYSCALLS__ - -#include - #include #include #include diff -urN linux-2.6.3-rc2/arch/ia64/kernel/smpboot.c linux-2.6.3-rc3/arch/ia64/kernel/smpboot.c --- linux-2.6.3-rc2/arch/ia64/kernel/smpboot.c 2004-02-03 19:43:19.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/smpboot.c 2004-02-14 19:30:59.000000000 -0800 @@ -10,10 +10,6 @@ * smp_boot_cpus()/smp_commence() is replaced by * smp_prepare_cpus()/__cpu_up()/smp_cpus_done(). */ - - -#define __KERNEL_SYSCALLS__ - #include #include @@ -77,7 +73,6 @@ extern void start_ap (void); extern unsigned long ia64_iobase; -int cpucount; task_t *task_for_booting_cpu; /* Bitmask of currently online CPUs */ @@ -307,7 +302,6 @@ #ifdef CONFIG_IA64_MCA ia64_mca_cmc_vector_setup(); /* Setup vector on AP & enable */ - ia64_mca_check_errors(); /* For post-failure MCA error logging */ #endif #ifdef CONFIG_PERFMON diff -urN linux-2.6.3-rc2/arch/ia64/kernel/traps.c linux-2.6.3-rc3/arch/ia64/kernel/traps.c --- linux-2.6.3-rc2/arch/ia64/kernel/traps.c 2004-02-03 19:44:54.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/traps.c 2004-02-14 19:30:59.000000000 -0800 @@ -46,21 +46,14 @@ extern spinlock_t timerlist_lock; -static fpswa_interface_t *fpswa_interface; +fpswa_interface_t *fpswa_interface; void __init trap_init (void) { - int major = 0, minor = 0; - - if (ia64_boot_param->fpswa) { + if (ia64_boot_param->fpswa) /* FPSWA fixup: make the interface pointer a kernel virtual address: */ fpswa_interface = __va(ia64_boot_param->fpswa); - major = fpswa_interface->revision >> 16; - minor = fpswa_interface->revision & 0xffff; - } - printk(KERN_INFO "fpswa interface at %lx (rev %d.%d)\n", - ia64_boot_param->fpswa, major, minor); } /* diff -urN linux-2.6.3-rc2/arch/ia64/kernel/unaligned.c linux-2.6.3-rc3/arch/ia64/kernel/unaligned.c --- linux-2.6.3-rc2/arch/ia64/kernel/unaligned.c 2004-02-03 19:44:35.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/kernel/unaligned.c 2004-02-14 19:30:59.000000000 -0800 @@ -740,6 +740,7 @@ emulate_load_int (unsigned long ifa, load_store_t ld, struct pt_regs *regs) { unsigned int len = 1 << ld.x6_sz; + unsigned long val = 0; /* * r0, as target, doesn't need to be checked because Illegal Instruction @@ -750,21 +751,18 @@ */ /* - * ldX.a we don't try to emulate anything but we must invalidate the ALAT entry. + * ldX.a we will emulate load and also invalidate the ALAT entry. * See comment below for explanation on how we handle ldX.a */ - if (ld.x6_op != 0x2) { - unsigned long val = 0; - if (len != 2 && len != 4 && len != 8) { - DPRINT("unknown size: x6=%d\n", ld.x6_sz); - return -1; - } - /* this assumes little-endian byte-order: */ - if (copy_from_user(&val, (void *) ifa, len)) - return -1; - setreg(ld.r1, val, 0, regs); + if (len != 2 && len != 4 && len != 8) { + DPRINT("unknown size: x6=%d\n", ld.x6_sz); + return -1; } + /* this assumes little-endian byte-order: */ + if (copy_from_user(&val, (void *) ifa, len)) + return -1; + setreg(ld.r1, val, 0, regs); /* * check for updates on any kind of loads @@ -817,7 +815,7 @@ * store & shift to temporary; * r1=temporary * - * So int this case, you would get the right value is r1 but the wrong info in + * So in this case, you would get the right value is r1 but the wrong info in * the ALAT. Notice that you could do it in reverse to finish with address 3 * but you would still get the size wrong. To get the size right, one needs to * execute exactly the same kind of load. You could do it from a aligned @@ -826,9 +824,12 @@ * So no matter what, it is not possible to emulate an advanced load * correctly. But is that really critical ? * + * We will always convert ld.a into a normal load with ALAT invalidated. This + * will enable compiler to do optimization where certain code path after ld.a + * is not required to have ld.c/chk.a, e.g., code path with no intervening stores. * - * Now one has to look at how ld.a is used, one must either do a ld.c.* or - * chck.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no + * If there is a store after the advanced load, one must either do a ld.c.* or + * chk.a.* to reuse the value stored in the ALAT. Both can "fail" (meaning no * entry found in ALAT), and that's perfectly ok because: * * - ld.c.*, if the entry is not present a normal load is executed @@ -836,19 +837,8 @@ * * In either case, the load can be potentially retried in another form. * - * So it's okay NOT to do any actual load on an unaligned ld.a. However the ALAT - * must be invalidated for the register (so that's chck.a.*,ld.c.* don't pick up - * a stale entry later) The register base update MUST also be performed. - * - * Now what is the content of the register and its NaT bit in the case we don't - * do the load ? EAS2.4, says (in case an actual load is needed) - * - * - r1 = [r3], Nat = 0 if succeeds - * - r1 = 0 Nat = 0 if trying to access non-speculative memory - * - * For us, there is nothing to do, because both ld.c.* and chk.a.* are going to - * retry and thus eventually reload the register thereby changing Nat and - * register content. + * ALAT must be invalidated for the register (so that chk.a or ld.c don't pick + * up a stale entry later). The register base update MUST also be performed. */ /* diff -urN linux-2.6.3-rc2/arch/ia64/lib/io.c linux-2.6.3-rc3/arch/ia64/lib/io.c --- linux-2.6.3-rc2/arch/ia64/lib/io.c 2004-02-14 19:30:50.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/lib/io.c 2004-02-14 19:30:59.000000000 -0800 @@ -9,13 +9,13 @@ * This needs to be optimized. */ void -__ia64_memcpy_fromio (void * to, unsigned long from, long count) +__ia64_memcpy_fromio (void *to, unsigned long from, long count) { + char *dst = to; + while (count) { count--; - *(char *) to = readb(from); - ((char *) to)++; - from++; + *dst++ = readb(from++); } } EXPORT_SYMBOL(__ia64_memcpy_fromio); @@ -25,13 +25,13 @@ * This needs to be optimized. */ void -__ia64_memcpy_toio (unsigned long to, void * from, long count) +__ia64_memcpy_toio (unsigned long to, void *from, long count) { + char *src = from; + while (count) { count--; - writeb(*(char *) from, to); - ((char *) from)++; - to++; + writeb(*src++, to++); } } EXPORT_SYMBOL(__ia64_memcpy_toio); diff -urN linux-2.6.3-rc2/arch/ia64/scripts/toolchain-flags linux-2.6.3-rc3/arch/ia64/scripts/toolchain-flags --- linux-2.6.3-rc2/arch/ia64/scripts/toolchain-flags 2004-02-03 19:44:55.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/scripts/toolchain-flags 2004-02-14 19:30:59.000000000 -0800 @@ -5,9 +5,14 @@ CPPFLAGS="" CC=$1 OBJDUMP=$2 +READELF=$3 dir=$(dirname $0) tmp=${TMPDIR:-/tmp} out=$tmp/out$$ + +# Check whether cross-segment segment-relative relocs work fine. We need +# that for building the gate DSO: + $CC -nostdlib -static -Wl,-T$dir/check-segrel.lds $dir/check-segrel.S -o $out res=$($OBJDUMP --full --section .rodata $out | fgrep 000 | cut -f3 -d' ') rm -f $out @@ -20,6 +25,16 @@ EOF fi +# Check whether .align inside a function works as expected. + +$CC -c $dir/check-text-align.S -o $out +$READELF -u $out | fgrep -q 'prologue(rlen=12)' +res=$? +rm -f $out +if [ $res -eq 0 ]; then + CPPFLAGS="$CPPFLAGS -DHAVE_WORKING_TEXT_ALIGN" +fi + if ! $CC -c $dir/check-model.c -o $out 2>&1 | grep __model__ | grep -q attrib then CPPFLAGS="$CPPFLAGS -DHAVE_MODEL_SMALL_ATTRIBUTE" diff -urN linux-2.6.3-rc2/arch/ia64/sn/kernel/mca.c linux-2.6.3-rc3/arch/ia64/sn/kernel/mca.c --- linux-2.6.3-rc2/arch/ia64/sn/kernel/mca.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/sn/kernel/mca.c 2004-02-14 19:30:59.000000000 -0800 @@ -68,20 +68,6 @@ } - -/* - * ia64_sn2_platform_plat_specific_err_print - * - * Called by the MCA handler to log platform-specific errors. - */ -void -ia64_sn2_platform_plat_specific_err_print(int header_len, int sect_len, u8 *p_data, prfunc_t prfunc) -{ - ia64_sn_plat_specific_err_print(print_hook, p_data - sect_len); -} - - - static void sn_cpei_handler(int irq, void *devid, struct pt_regs *regs) { diff -urN linux-2.6.3-rc2/arch/ia64/sn/kernel/setup.c linux-2.6.3-rc3/arch/ia64/sn/kernel/setup.c --- linux-2.6.3-rc2/arch/ia64/sn/kernel/setup.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/sn/kernel/setup.c 2004-02-14 19:30:59.000000000 -0800 @@ -71,6 +71,8 @@ short physical_node_map[MAX_PHYSNODE_ID]; +EXPORT_SYMBOL(physical_node_map); + int numionodes; /* * This is the address of the RRegs in the HSpace of the global diff -urN linux-2.6.3-rc2/arch/ia64/sn/kernel/sn2/cache.c linux-2.6.3-rc3/arch/ia64/sn/kernel/sn2/cache.c --- linux-2.6.3-rc2/arch/ia64/sn/kernel/sn2/cache.c 2004-02-03 19:45:09.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/sn/kernel/sn2/cache.c 2004-02-14 19:30:59.000000000 -0800 @@ -6,7 +6,7 @@ * Copyright (C) 2001-2003 Silicon Graphics, Inc. All rights reserved. * */ - +#include #include /** diff -urN linux-2.6.3-rc2/arch/ia64/sn/kernel/sn2/sn2_smp.c linux-2.6.3-rc3/arch/ia64/sn/kernel/sn2/sn2_smp.c --- linux-2.6.3-rc2/arch/ia64/sn/kernel/sn2/sn2_smp.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ia64/sn/kernel/sn2/sn2_smp.c 2004-02-14 19:30:59.000000000 -0800 @@ -5,7 +5,7 @@ * License. See the file "COPYING" in the main directory of this archive * for more details. * - * Copyright (C) 2000-2003 Silicon Graphics, Inc. All rights reserved. + * Copyright (C) 2000-2004 Silicon Graphics, Inc. All rights reserved. */ #include @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include #include @@ -67,14 +69,56 @@ * * Purges the translation caches of all processors of the given virtual address * range. + * + * Note: + * - cpu_vm_mask is a bit mask that indicates which cpus have loaded the context. + * - cpu_vm_mask is converted into a nodemask of the nodes containing the + * cpus in cpu_vm_mask. + * - if only one bit is set in cpu_vm_mask & it is the current cpu, + * then only the local TLB needs to be flushed. This flushing can be done + * using ptc.l. This is the common case & avoids the global spinlock. + * - if multiple cpus have loaded the context, then flushing has to be + * done with ptc.g/MMRs under protection of the global ptc_lock. */ void sn2_global_tlb_purge (unsigned long start, unsigned long end, unsigned long nbits) { - int cnode, mycnode, nasid, flushed=0; + int i, cnode, mynasid, cpu, lcpu=0, nasid, flushed=0; volatile unsigned long *ptc0, *ptc1; unsigned long flags=0, data0, data1; + struct mm_struct *mm=current->active_mm; + short nasids[NR_NODES], nix; + DECLARE_BITMAP(nodes_flushed, NR_NODES); + + CLEAR_BITMAP(nodes_flushed, NR_NODES); + + i = 0; + + for_each_cpu_mask(cpu, mm->cpu_vm_mask) { + cnode = cpu_to_node(cpu); + __set_bit(cnode, nodes_flushed); + lcpu = cpu; + i++; + } + + preempt_disable(); + + if (likely(i == 1 && lcpu == smp_processor_id())) { + do { + ia64_ptcl(start, nbits<<2); + start += (1UL << nbits); + } while (start < end); + ia64_srlz_i(); + preempt_enable(); + return; + } + + nix = 0; + for (cnode=find_first_bit(&nodes_flushed, NR_NODES); cnode < NR_NODES; + cnode=find_next_bit(&nodes_flushed, NR_NODES, ++cnode)) + nasids[nix++] = cnodeid_to_nasid(cnode); + data0 = (1UL< - in the kernel source. - - The watchdog is usually used together with the watchdog daemon - which is available from - . This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. - - If unsure, say N. - -config WATCHDOG_NOWAYOUT - bool "Disable watchdog shutdown on close" - depends on WATCHDOG - help - The default watchdog behaviour (which you get if you say N here) is - to stop the timer if the process managing it closes the file - /dev/watchdog. It's always remotely possible that this process might - get killed. If you say Y here, the watchdog cannot be stopped once - it has been started. - -config SOFT_WATCHDOG - bool "Software watchdog" - depends on WATCHDOG - help - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - To compile this driver as a module, choose M here: the - module will be called softdog. +source "drivers/char/watchdog/Kconfig" config GEN_RTC tristate "Generic /dev/rtc emulation" if !SUN3 diff -urN linux-2.6.3-rc2/arch/ppc/Kconfig linux-2.6.3-rc3/arch/ppc/Kconfig --- linux-2.6.3-rc2/arch/ppc/Kconfig 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/Kconfig 2004-02-14 19:30:59.000000000 -0800 @@ -592,6 +592,11 @@ depends on PPC_MULTIPLATFORM default y +config PPC_PMAC64 + bool + depends on PPC_PMAC && POWER4 + default y + config PPC_PREP bool depends on PPC_MULTIPLATFORM @@ -604,7 +609,7 @@ config PPC_GEN550 bool - depends on SANDPOINT || MCPN765 + depends on SANDPOINT || MCPN765 || SPRUCE default y config FORCE diff -urN linux-2.6.3-rc2/arch/ppc/boot/common/bootinfo.c linux-2.6.3-rc3/arch/ppc/boot/common/bootinfo.c --- linux-2.6.3-rc2/arch/ppc/boot/common/bootinfo.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/boot/common/bootinfo.c 2004-02-14 19:30:59.000000000 -0800 @@ -0,0 +1,70 @@ +/* + * arch/ppc/common/bootinfo.c + * + * General bootinfo record utilities + * Author: Randy Vinson + * + * 2002 (c) MontaVista Software, Inc. This file is licensed under the terms + * of the GNU General Public License version 2. This program is licensed + * "as is" without any warranty of any kind, whether express or implied. + */ + +#include +#include +#include + +#include "nonstdio.h" + +static struct bi_record * birec = NULL; + +static struct bi_record * +__bootinfo_build(struct bi_record *rec, unsigned long tag, unsigned long size, + void *data) +{ + /* set the tag */ + rec->tag = tag; + + /* if the caller has any data, copy it */ + if (size) + memcpy(rec->data, (char *)data, size); + + /* set the record size */ + rec->size = sizeof(struct bi_record) + size; + + /* advance to the next available space */ + rec = (struct bi_record *)((unsigned long)rec + rec->size); + + return rec; +} + +void +bootinfo_init(struct bi_record *rec) +{ + + /* save start of birec area */ + birec = rec; + + /* create an empty list */ + rec = __bootinfo_build(rec, BI_FIRST, 0, NULL); + (void) __bootinfo_build(rec, BI_LAST, 0, NULL); + +} + +void +bootinfo_append(unsigned long tag, unsigned long size, void * data) +{ + + struct bi_record *rec = birec; + + /* paranoia */ + if ((rec == NULL) || (rec->tag != BI_FIRST)) + return; + + /* find the last entry in the list */ + while (rec->tag != BI_LAST) + rec = (struct bi_record *)((ulong)rec + rec->size); + + /* overlay BI_LAST record with new one and tag on a new BI_LAST */ + rec = __bootinfo_build(rec, tag, size, data); + (void) __bootinfo_build(rec, BI_LAST, 0, NULL); +} diff -urN linux-2.6.3-rc2/arch/ppc/boot/simple/Makefile linux-2.6.3-rc3/arch/ppc/boot/simple/Makefile --- linux-2.6.3-rc2/arch/ppc/boot/simple/Makefile 2004-02-03 19:43:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/boot/simple/Makefile 2004-02-14 19:30:59.000000000 -0800 @@ -30,7 +30,7 @@ # Normally, we use the 'misc.c' file for decompress_kernel and # whatnot. Sometimes we need to override this however. -misc-y := misc.o +misc-y := misc.o ../common/bootinfo.o # Normally, we have our images end in .elf, but something we want to # change this. @@ -103,7 +103,7 @@ zimageinitrd-$(CONFIG_SPRUCE) := zImage.initrd-TREE end-$(CONFIG_SPRUCE) := spruce entrypoint-$(CONFIG_SPRUCE) := 0x00800000 - misc-$(CONFIG_SPRUCE) := misc-spruce.o + misc-$(CONFIG_SPRUCE) += misc-spruce.o # SMP images should have a '.smp' suffix. end-$(CONFIG_SMP) += .smp diff -urN linux-2.6.3-rc2/arch/ppc/boot/simple/misc-spruce.c linux-2.6.3-rc3/arch/ppc/boot/simple/misc-spruce.c --- linux-2.6.3-rc2/arch/ppc/boot/simple/misc-spruce.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/boot/simple/misc-spruce.c 2004-02-14 19:30:59.000000000 -0800 @@ -15,55 +15,19 @@ */ #include -#include #include #include -#include -#include #include -#include "zlib.h" +extern unsigned long decompress_kernel(unsigned long load_addr, int num_words, + unsigned long cksum); /* Define some important locations of the Spruce. */ #define SPRUCE_PCI_CONFIG_ADDR 0xfec00000 #define SPRUCE_PCI_CONFIG_DATA 0xfec00004 #define SPRUCE_ISA_IO_BASE 0xf8000000 -unsigned long com_port; - -char *avail_ram; -char *end_avail; - -/* The linker tells us where the image is. */ -extern char __image_begin, __image_end; -extern char __ramdisk_begin, __ramdisk_end; -extern char _end[]; - -#ifdef CONFIG_CMDLINE -#define CMDLINE CONFIG_CMDLINE -#else -#define CMDLINE "" -#endif -char cmd_preset[] = CMDLINE; -char cmd_buf[256]; -char *cmd_line = cmd_buf; - -unsigned long initrd_size = 0; - -char *zimage_start; -int zimage_size; - -extern void udelay(long); -extern void puts(const char *); -extern void putc(const char c); -extern void puthex(unsigned long val); -extern int getc(void); -extern int tstc(void); -extern void gunzip(void *, int, unsigned char *, int *); - -extern unsigned long serial_init(int chan, void *ignored); - /* PCI configuration space access routines. */ unsigned int *pci_config_address = (unsigned int *)SPRUCE_PCI_CONFIG_ADDR; unsigned char *pci_config_data = (unsigned char *)SPRUCE_PCI_CONFIG_DATA; @@ -146,45 +110,16 @@ #define MEM_B2EA 0x60 unsigned long -load_kernel(unsigned long load_addr, int num_words, unsigned long cksum) +get_mem_size(void) { - int timer = 0; - char *cp, ch; - int loop; - int csr0; - int csr_id; - int *mem_addr = (int *)0xff500008; - int *mem_data = (int *)0xff50000c; - int mem_size = 0; + unsigned long mem_size = 0; unsigned long mem_mben; unsigned long mem_type; unsigned long mem_start; unsigned long mem_end; - int *pif_addr = (int *)0xff500000; - int *pif_data = (int *)0xff500004; - int pci_devfn; - int found_multi = 0; - unsigned short vendor; - unsigned short device; - unsigned short command; - unsigned char header_type; - unsigned int bar0; - -#ifdef CONFIG_SERIAL_8250_CONSOLE - /* Initialize the serial console port */ - com_port = serial_init(0, NULL); -#endif - - /* - * Gah, these firmware guys need to learn that hardware - * byte swapping is evil! Disable all hardware byte - * swapping so it doesn't hurt anyone. - */ - *pif_addr = PLBMIFOPT; - asm("sync"); - *pif_data = 0x00000000; - asm("sync"); + volatile int *mem_addr = (int *)0xff500008; + volatile int *mem_data = (int *)0xff50000c; /* Get the size of memory from the memory controller. */ *mem_addr = MEM_MBEN; @@ -235,6 +170,33 @@ mem_size += mem_end - mem_start + 0x100000; } + return mem_size; +} + +unsigned long +load_kernel(unsigned long load_addr, int num_words, unsigned long cksum) +{ + int csr0; + int csr_id; + int pci_devfn; + int found_multi = 0; + unsigned short vendor; + unsigned short device; + unsigned short command; + unsigned char header_type; + unsigned int bar0; + volatile int *pif_addr = (int *)0xff500000; + volatile int *pif_data = (int *)0xff500004; + + /* + * Gah, these firmware guys need to learn that hardware + * byte swapping is evil! Disable all hardware byte + * swapping so it doesn't hurt anyone. + */ + *pif_addr = PLBMIFOPT; + asm("sync"); + *pif_data = 0x00000000; + asm("sync"); /* Search out and turn off the PcNet ethernet boot device. */ for (pci_devfn = 1; pci_devfn < 0xff; pci_devfn++) { @@ -310,134 +272,5 @@ } } - /* assume the chunk below 8M is free */ - end_avail = (char *)0x00800000; - - /* - * We link ourself to 0x00800000. When we run, we relocate - * ourselves there. So we just need __image_begin for the - * start. -- Tom - */ - zimage_start = (char *)(unsigned long)(&__image_begin); - zimage_size = (unsigned long)(&__image_end) - - (unsigned long)(&__image_begin); - - initrd_size = (unsigned long)(&__ramdisk_end) - - (unsigned long)(&__ramdisk_begin); - - /* - * The zImage and initrd will be between start and _end, so they've - * already been moved once. We're good to go now. -- Tom - */ - avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); - puts("zimage at: "); puthex((unsigned long)zimage_start); - puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); - puts("\n"); - - if ( initrd_size ) { - puts("initrd at: "); - puthex((unsigned long)(&__ramdisk_begin)); - puts(" "); puthex((unsigned long)(&__ramdisk_end));puts("\n"); - } - - avail_ram = (char *)0x00400000; - end_avail = (char *)0x00800000; - puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); - puthex((unsigned long)end_avail); puts("\n"); - - /* Display standard Linux/PPC boot prompt for kernel args */ - puts("\nLinux/PPC load: "); - cp = cmd_line; - memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); - while ( *cp ) putc(*cp++); - while (timer++ < 5*1000) { - if (tstc()) { - while ((ch = getc()) != '\n' && ch != '\r') { - if (ch == '\b') { - if (cp != cmd_line) { - cp--; - puts("\b \b"); - } - } else { - *cp++ = ch; - putc(ch); - } - } - break; /* Exit 'timer' loop */ - } - udelay(1000); /* 1 msec */ - } - *cp = 0; - puts("\n"); - - puts("Uncompressing Linux..."); - - gunzip(0, 0x400000, zimage_start, &zimage_size); - - puts("done.\n"); - - { - struct bi_record *rec; - unsigned long initrd_loc; - unsigned long rec_loc = _ALIGN((unsigned long)(zimage_size) + - (1 << 20) - 1, (1 << 20)); - rec = (struct bi_record *)rec_loc; - - /* We need to make sure that the initrd and bi_recs do not - * overlap. */ - if ( initrd_size ) { - initrd_loc = (unsigned long)(&__ramdisk_begin); - /* If the bi_recs are in the middle of the current - * initrd, move the initrd to the next MB - * boundary. */ - if ((rec_loc > initrd_loc) && - ((initrd_loc + initrd_size) - > rec_loc)) { - initrd_loc = _ALIGN((unsigned long)(zimage_size) - + (2 << 20) - 1, (2 << 20)); - memmove((void *)initrd_loc, &__ramdisk_begin, - initrd_size); - puts("initrd moved: "); puthex(initrd_loc); - puts(" "); puthex(initrd_loc + initrd_size); - puts("\n"); - } - } - - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_BOOTLOADER_ID; - memcpy( (void *)rec->data, "spruceboot", 11); - rec->size = sizeof(struct bi_record) + 10 + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_MEMSIZE; - rec->data[0] = mem_size; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - rec->tag = BI_CMD_LINE; - memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); - rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; - rec = (struct bi_record *)((ulong)rec + rec->size); - - if ( initrd_size ) { - rec->tag = BI_INITRD; - rec->data[0] = initrd_loc; - rec->data[1] = initrd_size; - rec->size = sizeof(struct bi_record) + 2 * - sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + - rec->size); - } - - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - } - - puts("Now booting the kernel\n"); - - return 0; + return decompress_kernel(load_addr, num_words, cksum); } diff -urN linux-2.6.3-rc2/arch/ppc/boot/simple/misc.c linux-2.6.3-rc3/arch/ppc/boot/simple/misc.c --- linux-2.6.3-rc2/arch/ppc/boot/simple/misc.c 2004-02-03 19:44:19.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/boot/simple/misc.c 2004-02-14 19:30:59.000000000 -0800 @@ -1,5 +1,5 @@ /* - * arch/ppc/common/misc-simple.c + * arch/ppc/simple/misc.c * * Misc. bootloader code for many machines. This assumes you have are using * a 6xx/7xx/74xx CPU in your machine. This assumes the chunk of memory @@ -46,6 +46,15 @@ #define HAS_KEYB 0 #endif +/* Will / Can the user give input? + * Val Henson has requested that Gemini doesn't wait for the + * user to edit the cmdline or not. + */ +#if (defined(CONFIG_SERIAL_8250_CONSOLE) || defined(CONFIG_VGA_CONSOLE)) \ + && !defined(CONFIG_GEMINI) +#define INTERACTIVE_CONSOLE 1 +#endif + char *avail_ram; char *end_avail; char *zimage_start; @@ -66,19 +75,28 @@ extern unsigned long start; extern int CRT_tstc(void); -extern unsigned long get_mem_size(void); extern unsigned long serial_init(int chan, void *ignored); extern void serial_close(unsigned long com_port); extern void gunzip(void *, int, unsigned char *, int *); extern void serial_fixups(void); +/* Allow get_mem_size to be hooked into. This is the default. */ +unsigned long __attribute__ ((weak)) +get_mem_size(void) +{ + return 0; +} + struct bi_record * decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum) { +#ifdef INTERACTIVE_CONSOLE int timer = 0; - char *cp, ch; + char ch; +#endif + char *cp; struct bi_record *rec; - unsigned long TotalMemory = 0, rec_loc, initrd_loc; + unsigned long initrd_loc, TotalMemory = 0; serial_fixups(); com_port = serial_init(0, NULL); @@ -93,13 +111,11 @@ __asm__ __volatile__("eieio"); #endif -#if defined(CONFIG_LOPEC) || defined(CONFIG_PAL4) /* * Call get_mem_size(), which is memory controller dependent, * and we must have the correct file linked in here. */ TotalMemory = get_mem_size(); -#endif /* assume the chunk below 8M is free */ end_avail = (char *)0x00800000; @@ -170,9 +186,11 @@ memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); while ( *cp ) putc(*cp++); -#ifndef CONFIG_GEMINI - /* Val Henson has requested that Gemini doesn't wait for the - * user to edit the cmdline or not. */ +#ifdef INTERACTIVE_CONSOLE + /* + * If they have a console, allow them to edit the command line. + * Otherwise, don't bother wasting the five seconds. + */ while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { @@ -205,16 +223,13 @@ gunzip(0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); - /* - * Create bi_recs for cmd_line and initrds - */ - rec_loc = _ALIGN((unsigned long)(zimage_size) + - (1 << 20) - 1, (1 << 20)); - rec = (struct bi_record *)rec_loc; + /* get the bi_rec address */ + rec = bootinfo_addr(zimage_size); /* We need to make sure that the initrd and bi_recs do not * overlap. */ if ( initrd_size ) { + unsigned long rec_loc = (unsigned long) rec; initrd_loc = (unsigned long)(&__ramdisk_begin); /* If the bi_recs are in the middle of the current * initrd, move the initrd to the next MB @@ -231,39 +246,25 @@ } } - rec->tag = BI_FIRST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - - if ( TotalMemory ) { - rec->tag = BI_MEMSIZE; - rec->data[0] = TotalMemory; - rec->size = sizeof(struct bi_record) + sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + rec->size); - } + bootinfo_init(rec); + if ( TotalMemory ) + bootinfo_append(BI_MEMSIZE, sizeof(int), (void*)&TotalMemory); - rec->tag = BI_CMD_LINE; - memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); - rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; - rec = (struct bi_record *)((unsigned long)rec + rec->size); + bootinfo_append(BI_CMD_LINE, strlen(cmd_line)+1, (void*)cmd_line); - if ( initrd_size ) { - rec->tag = BI_INITRD; - rec->data[0] = initrd_loc; - rec->data[1] = initrd_size; - rec->size = sizeof(struct bi_record) + 2 * - sizeof(unsigned long); - rec = (struct bi_record *)((unsigned long)rec + - rec->size); - } + /* add a bi_rec for the initrd if it exists */ + if (initrd_size) { + unsigned long initrd[2]; - rec->tag = BI_LAST; - rec->size = sizeof(struct bi_record); - rec = (struct bi_record *)((unsigned long)rec + rec->size); + initrd[0] = initrd_loc; + initrd[1] = initrd_size; + + bootinfo_append(BI_INITRD, sizeof(initrd), &initrd); + } puts("Now booting the kernel\n"); serial_close(com_port); - return (struct bi_record *)rec_loc; + return rec; } /* Allow decompress_kernel to be hooked into. This is the default. */ diff -urN linux-2.6.3-rc2/arch/ppc/configs/spruce_defconfig linux-2.6.3-rc3/arch/ppc/configs/spruce_defconfig --- linux-2.6.3-rc2/arch/ppc/configs/spruce_defconfig 2004-02-03 19:43:12.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/configs/spruce_defconfig 2004-02-14 19:30:59.000000000 -0800 @@ -4,11 +4,17 @@ CONFIG_MMU=y CONFIG_RWSEM_XCHGADD_ALGORITHM=y CONFIG_HAVE_DEC_LOCK=y +CONFIG_PPC=y +CONFIG_PPC32=y +CONFIG_GENERIC_NVRAM=y # # Code maturity level options # CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y # # General setup @@ -18,9 +24,15 @@ # CONFIG_BSD_PROCESS_ACCT is not set CONFIG_SYSCTL=y CONFIG_LOG_BUF_SHIFT=14 -# CONFIG_EMBEDDED is not set +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y CONFIG_FUTEX=y CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -33,24 +45,25 @@ CONFIG_KMOD=y # -# Platform support +# Processor # -CONFIG_PPC=y -CONFIG_PPC32=y CONFIG_6xx=y # CONFIG_40x is not set +# CONFIG_44x is not set # CONFIG_POWER3 is not set +# CONFIG_POWER4 is not set # CONFIG_8xx is not set +# CONFIG_ALTIVEC is not set +# CONFIG_TAU is not set +# CONFIG_CPU_FREQ is not set +CONFIG_PPC_STD_MMU=y # -# IBM 4xx options +# Platform options # -# CONFIG_8260 is not set -CONFIG_GENERIC_ISA_DMA=y -CONFIG_PPC_STD_MMU=y # CONFIG_PPC_MULTIPLATFORM is not set # CONFIG_APUS is not set -# CONFIG_WILLOW_2 is not set +# CONFIG_WILLOW is not set # CONFIG_PCORE is not set # CONFIG_POWERPMC250 is not set # CONFIG_EV64260 is not set @@ -66,36 +79,32 @@ # CONFIG_K2 is not set # CONFIG_PAL4 is not set # CONFIG_GEMINI is not set -# CONFIG_SPRUCE_BAUD_33M is not set +# CONFIG_EST8260 is not set +# CONFIG_SBS8260 is not set +# CONFIG_RPX6 is not set +# CONFIG_TQM8260 is not set +CONFIG_PPC_GEN550=y +CONFIG_SPRUCE_BAUD_33M=y # CONFIG_SMP is not set # CONFIG_PREEMPT is not set -# CONFIG_ALTIVEC is not set -# CONFIG_TAU is not set -# CONFIG_CPU_FREQ is not set +# CONFIG_HIGHMEM is not set +CONFIG_KERNEL_ELF=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_CMDLINE_BOOL=y +CONFIG_CMDLINE="ip=on" # -# General setup +# Bus options # -# CONFIG_HIGHMEM is not set +CONFIG_GENERIC_ISA_DMA=y CONFIG_PCI=y CONFIG_PCI_DOMAINS=y -CONFIG_KCORE_ELF=y -CONFIG_BINFMT_ELF=y -CONFIG_KERNEL_ELF=y -# CONFIG_BINFMT_MISC is not set CONFIG_PCI_LEGACY_PROC=y # CONFIG_PCI_NAMES is not set # CONFIG_HOTPLUG is not set # -# Parallel port support -# -# CONFIG_PARPORT is not set -# CONFIG_PPC601_SYNC_FIX is not set -CONFIG_CMDLINE_BOOL=y -CONFIG_CMDLINE="ip=on" - -# # Advanced setup # # CONFIG_ADVANCED_OPTIONS is not set @@ -110,14 +119,26 @@ CONFIG_BOOT_LOAD=0x00800000 # +# Device Drivers +# + +# +# Generic Driver Options +# + +# # Memory Technology Devices (MTD) # # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# # Plug and Play support # -# CONFIG_PNP is not set # # Block devices @@ -131,21 +152,22 @@ # CONFIG_BLK_DEV_NBD is not set # CONFIG_BLK_DEV_RAM is not set # CONFIG_BLK_DEV_INITRD is not set +# CONFIG_LBD is not set # -# Multi-device support (RAID and LVM) +# ATA/ATAPI/MFM/RLL support # -# CONFIG_MD is not set +# CONFIG_IDE is not set # -# ATA/IDE/MFM/RLL support +# SCSI device support # -# CONFIG_IDE is not set +# CONFIG_SCSI is not set # -# SCSI support +# Multi-device support (RAID and LVM) # -# CONFIG_SCSI is not set +# CONFIG_MD is not set # # Fusion MPT device support @@ -162,6 +184,10 @@ # CONFIG_I2O is not set # +# Macintosh device drivers +# + +# # Networking support # CONFIG_NET=y @@ -172,7 +198,6 @@ CONFIG_PACKET=y # CONFIG_PACKET_MMAP is not set # CONFIG_NETLINK_DEV is not set -# CONFIG_NETFILTER is not set CONFIG_UNIX=y # CONFIG_NET_KEY is not set CONFIG_INET=y @@ -191,7 +216,9 @@ # CONFIG_INET_ESP is not set # CONFIG_INET_IPCOMP is not set # CONFIG_IPV6 is not set -# CONFIG_XFRM_USER is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set # # SCTP Configuration (EXPERIMENTAL) @@ -200,9 +227,9 @@ # CONFIG_IP_SCTP is not set # CONFIG_ATM is not set # CONFIG_VLAN_8021Q is not set -# CONFIG_LLC is not set -# CONFIG_DECNET is not set -# CONFIG_BRIDGE is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set # CONFIG_X25 is not set # CONFIG_LAPB is not set # CONFIG_NET_DIVERT is not set @@ -230,13 +257,13 @@ # CONFIG_BONDING is not set # CONFIG_EQUALIZER is not set # CONFIG_TUN is not set -# CONFIG_ETHERTAP is not set # # Ethernet (10 or 100Mbit) # CONFIG_NET_ETHERNET=y CONFIG_MII=y +CONFIG_CRC32=y # CONFIG_OAKNET is not set # CONFIG_HAPPYMEAL is not set # CONFIG_SUNGEM is not set @@ -252,6 +279,7 @@ # CONFIG_AMD8111_ETH is not set # CONFIG_ADAPTEC_STARFIRE is not set # CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set # CONFIG_DGRS is not set # CONFIG_EEPRO100 is not set # CONFIG_E100 is not set @@ -276,6 +304,7 @@ # CONFIG_HAMACHI is not set # CONFIG_YELLOWFIN is not set # CONFIG_R8169 is not set +# CONFIG_SIS190 is not set # CONFIG_SK98LIN is not set # CONFIG_TIGON3 is not set @@ -294,8 +323,9 @@ # CONFIG_NET_RADIO is not set # -# Token Ring devices (depends on LLC=y) +# Token Ring devices # +# CONFIG_TR is not set # CONFIG_RCPCI is not set # CONFIG_SHAPER is not set @@ -315,19 +345,19 @@ # CONFIG_IRDA is not set # -# ISDN subsystem +# Bluetooth support # -# CONFIG_ISDN_BOOL is not set +# CONFIG_BT is not set # -# Graphics support +# ISDN subsystem # -# CONFIG_FB is not set +# CONFIG_ISDN_BOOL is not set # -# Old CD-ROM drivers (not SCSI, not IDE) +# Telephony Support # -# CONFIG_CD_NO_IDESCSI is not set +# CONFIG_PHONE is not set # # Input device support @@ -347,18 +377,16 @@ CONFIG_SERIO_I8042=y CONFIG_SERIO_SERPORT=y # CONFIG_SERIO_CT82C710 is not set +CONFIG_SERIO_PCIPS2=y # # Input Device Drivers # # -# Macintosh device drivers -# - -# # Character devices # +# CONFIG_VT is not set # CONFIG_SERIAL_NONSTANDARD is not set # @@ -366,6 +394,7 @@ # CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=2 # CONFIG_SERIAL_8250_EXTENDED is not set # @@ -377,20 +406,6 @@ CONFIG_UNIX98_PTY_COUNT=256 # -# I2C support -# -# CONFIG_I2C is not set - -# -# I2C Hardware Sensors Mainboard support -# - -# -# I2C Hardware Sensors Chip support -# -# CONFIG_I2C_SENSOR is not set - -# # Mice # # CONFIG_BUSMOUSE is not set @@ -419,7 +434,11 @@ # CONFIG_AGP is not set # CONFIG_DRM is not set # CONFIG_RAW_DRIVER is not set -# CONFIG_HANGCHECK_TIMER is not set + +# +# I2C support +# +# CONFIG_I2C is not set # # Multimedia devices @@ -432,6 +451,26 @@ # CONFIG_DVB is not set # +# Graphics support +# +# CONFIG_FB is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# # File systems # CONFIG_EXT2_FS=y @@ -470,10 +509,12 @@ # Pseudo filesystems # CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y # CONFIG_DEVFS_FS is not set CONFIG_DEVPTS_FS=y # CONFIG_DEVPTS_FS_XATTR is not set -# CONFIG_TMPFS is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLB_PAGE is not set CONFIG_RAMFS=y # @@ -498,6 +539,7 @@ CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set # CONFIG_NFS_V4 is not set +# CONFIG_NFS_DIRECTIO is not set # CONFIG_NFSD is not set CONFIG_ROOT_NFS=y CONFIG_LOCKD=y @@ -518,31 +560,19 @@ CONFIG_MSDOS_PARTITION=y # -# Sound -# -# CONFIG_SOUND is not set - -# -# USB support +# Native Language Support # -# CONFIG_USB is not set -# CONFIG_USB_GADGET is not set - -# -# Bluetooth support -# -# CONFIG_BT is not set +# CONFIG_NLS is not set # # Library routines # -# CONFIG_CRC32 is not set # # Kernel hacking # # CONFIG_DEBUG_KERNEL is not set -# CONFIG_KALLSYMS is not set +# CONFIG_SERIAL_TEXT_DEBUG is not set # # Security options diff -urN linux-2.6.3-rc2/arch/ppc/kernel/entry.S linux-2.6.3-rc3/arch/ppc/kernel/entry.S --- linux-2.6.3-rc2/arch/ppc/kernel/entry.S 2004-02-03 19:44:33.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/kernel/entry.S 2004-02-14 19:30:59.000000000 -0800 @@ -689,8 +689,8 @@ mtspr SPRN_ESR,r10 lwz r11,_NIP(r1) lwz r12,_MSR(r1) - mtspr SRR2,r11 - mtspr SRR3,r12 + mtspr CSRR0,r11 + mtspr CSRR1,r12 lwz r9,GPR9(r1) lwz r12,GPR12(r1) lwz r10,crit_sprg0@l(0) diff -urN linux-2.6.3-rc2/arch/ppc/kernel/head_44x.S linux-2.6.3-rc3/arch/ppc/kernel/head_44x.S --- linux-2.6.3-rc2/arch/ppc/kernel/head_44x.S 2004-02-03 19:43:32.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/kernel/head_44x.S 2004-02-14 19:30:59.000000000 -0800 @@ -90,14 +90,9 @@ * Invalidate all entries but the one we are using. */ /* Load our current PID->MMUCR TID and MSR IS->MMUCR STS */ - mfspr r3,SPRN_MMUCR /* Get MMUCR */ - lis r4,PPC44x_MMUCR_STS@h - ori r4,r4,PPC44x_MMUCR_TID@l /* Create mask */ - andc r3,r3,r4 /* Clear out TID/STS bits */ - mfspr r4,SPRN_PID /* Get PID */ - or r3,r3,r4 /* Set TID bits */ - mfmsr r5 /* Get MSR */ - andi. r5,r5,MSR_IS@l /* TS=1? */ + mfspr r3,SPRN_PID /* Get PID */ + mfmsr r4 /* Get MSR */ + andi. r4,r4,MSR_IS@l /* TS=1? */ beq wmmucr /* If not, leave STS=0 */ oris r3,r3,PPC44x_MMUCR_STS@h /* Set STS=1 */ wmmucr: mtspr SPRN_MMUCR,r3 /* Put MMUCR */ @@ -117,7 +112,7 @@ isync /* If so, context change */ /* - * Configure and load pinned entries into TLB slots 62 and 63. + * Configure and load pinned entry into TLB slot 63. */ lis r3,KERNELBASE@h /* Load the kernel virtual address */ @@ -131,17 +126,14 @@ mtspr SPRN_PID,r0 sync - /* Load the kernel TID = 0 */ - mfspr r5,SPRN_MMUCR - lis r6, PPC44x_MMUCR_TID@h - ori r6,r6,PPC44x_MMUCR_TID@l - andc r5,r5,r6 + /* Initialize MMUCR */ + li r5,0 mtspr SPRN_MMUCR,r5 sync /* pageid fields */ clrrwi r3,r3,10 /* Mask off the effective page number */ - ori r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M)) + ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M /* xlat fields */ clrrwi r4,r4,10 /* Mask off the real page number */ @@ -152,7 +144,7 @@ li r5,0 ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G) - li r0,62 /* TLB slot 62 */ + li r0,63 /* TLB slot 63 */ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ @@ -174,14 +166,7 @@ tlbwe r6,r23,PPC44x_TLB_PAGEID sync -4: ori r3,r3,PPC44x_TLB_TS /* TS = 1 */ - - li r0,63 /* TLB slot 63 */ - - tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ - tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ - tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ - +4: #ifdef CONFIG_SERIAL_TEXT_DEBUG /* * Add temporary UART mapping for early debug. This @@ -191,7 +176,7 @@ */ /* pageid fields */ lis r3,0xe000 - ori r3,r3,(PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M)) + ori r3,r3,PPC44x_TLB_VALID | PPC44x_TLB_256M /* xlat fields */ lis r4,0x4000 /* RPN is 0x40000000 */ @@ -201,7 +186,7 @@ li r5,0 ori r5,r5,(PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_I | PPC44x_TLB_G) - li r0,60 /* TLB slot 60 */ + li r0,1 /* TLB slot 1 */ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ @@ -209,15 +194,15 @@ ori r3,r3,PPC44x_TLB_TS /* Translation state 1 */ - li r0,61 /* TLB slot 61 */ + li r0,1 /* TLB slot 1 */ tlbwe r3,r0,PPC44x_TLB_PAGEID /* Load the pageid fields */ tlbwe r4,r0,PPC44x_TLB_XLAT /* Load the translation fields */ tlbwe r5,r0,PPC44x_TLB_ATTRIB /* Load the attrib/access fields */ -#endif /* CONFIG_SERIAL_TEXT_DEBUG */ /* Force context change */ isync +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ /* Establish the interrupt vector offsets */ SET_IVOR(0, CriticalInput); @@ -493,10 +478,8 @@ lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l - mfspr r12,SPRN_MMUCR /* Set TID to 0 */ - li r13,PPC44x_MMUCR_TID@l - andc r12,r12,r13 - mtspr SPRN_MMUCR,r12 + mfspr r12,SPRN_MMUCR + rlwinm r12,r12,0,0,23 /* Clear TID */ b 4f @@ -505,19 +488,14 @@ mfspr r11,SPRG3 lwz r11,PGDIR(r11) - /* Load MMUCR with our PID and STS= */ - mfspr r12,SPRN_MMUCR /* Get MMUCR */ - lis r13,PPC44x_MMUCR_STS@h - ori r13,r13,PPC44x_MMUCR_TID@l /* Create mask */ - andc r12,r12,r13 /* Clear out TID/STS bits */ - mfspr r13,SPRN_PID /* Get PID */ - or r12,r12,r13 /* Set TID bits */ - mfspr r14,SPRN_SRR1 /* Get SRR1 */ - andi. r14,r14,MSR_IS@l /* TS=1? */ - beq 4f /* If not, leave STS=0 */ - oris r12,r12,PPC44x_MMUCR_STS@h /* Set STS=1 */ - mtspr SPRN_MMUCR,r12 + /* Load PID into MMUCR TID */ + mfspr r12,SPRN_MMUCR /* Get MMUCR */ + mfspr r13,SPRN_PID /* Get PID */ + rlwimi r12,r13,0,24,31 /* Set TID */ + 4: + mtspr SPRN_MMUCR,r12 + rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ lwzx r11, r12, r11 /* Get pgd/pmd entry */ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ @@ -534,22 +512,24 @@ ori r11, r11, _PAGE_DIRTY|_PAGE_ACCESSED|_PAGE_HWWRITE stw r11, 4(r12) /* Update Linux page table */ - /* FIXME: Staticly setting some permissions */ - li r13, 0x003f /* Set UX,UW,UR,SX,SW,SR */ - andi. r11,r11,0xffff /* Clear MS 16 bits */ - /* FIXME: Force attributes */ - ori r11,r11, 0x0100 /* Set G */ - /* FIXME: Already set in PTE */ + li r13, PPC44x_TLB_SR@l /* Set SR */ + rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */ + rlwimi r13, r11, 0, 30, 30 /* SW = _PAGE_RW */ + rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */ + rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ + rlwimi r12, r11, 29, 30, 30 /* (_PAGE_USER>>3)->r12 */ + and r12, r12, r11 /* HWEXEC/RW & USER */ + rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */ + rlwimi r13, r12, 3, 27, 27 /* UW = RW & USER */ + rlwimi r11,r13,0,26,31 /* Insert static perms */ - lis r13,0xffff - ori r13,r13,0x0fff /* Set U0-U3 mask */ - and r11,r11,r13 /* Clear U0-U3 */ + rlwinm r11,r11,0,20,15 /* Clear U0-U3 */ /* find the TLB index that caused the fault. It has to be here. */ tlbsx r14, 0, r10 - tlbwe r11, r14, PPC44x_TLB_ATTRIB /* Write ATTRIB */ + tlbwe r11, r14, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. */ @@ -651,10 +631,8 @@ lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l - mfspr r12,SPRN_MMUCR /* Set TID to 0 */ - li r13,PPC44x_MMUCR_TID@l - andc r12,r12,r13 - mtspr SPRN_MMUCR,r12 + mfspr r12,SPRN_MMUCR + rlwinm r12,r12,0,0,23 /* Clear TID */ b 4f @@ -664,12 +642,13 @@ lwz r11,PGDIR(r11) /* Load PID into MMUCR TID */ - li r13,PPC44x_MMUCR_TID@l /* Create mask */ - andc r12,r12,r13 /* Clear out TID/STS bits */ - mfspr r13,SPRN_PID /* Get PID */ - or r12,r12,r13 - mtspr SPRN_MMUCR,r12 + mfspr r12,SPRN_MMUCR + mfspr r13,SPRN_PID /* Get PID */ + rlwimi r12,r13,0,24,31 /* Set TID */ + 4: + mtspr SPRN_MMUCR,r12 + rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ lwzx r11, r12, r11 /* Get pgd/pmd entry */ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ @@ -723,10 +702,8 @@ lis r11, swapper_pg_dir@h ori r11, r11, swapper_pg_dir@l - mfspr r12,SPRN_MMUCR /* Set TID to 0 */ - li r13,PPC44x_MMUCR_TID@l - andc r12,r12,r13 - mtspr SPRN_MMUCR,r12 + mfspr r12,SPRN_MMUCR + rlwinm r12,r12,0,0,23 /* Clear TID */ b 4f @@ -736,13 +713,13 @@ lwz r11,PGDIR(r11) /* Load PID into MMUCR TID */ - li r13,PPC44x_MMUCR_TID@l /* Create mask */ - andc r12,r13,r13 /* Clear out TID/STS bits */ - mfspr r13,SPRN_PID /* Get PID */ - or r12,r12,r13 - mtspr SPRN_MMUCR,r12 + mfspr r12,SPRN_MMUCR + mfspr r13,SPRN_PID /* Get PID */ + rlwimi r12,r13,0,24,31 /* Set TID */ 4: + mtspr SPRN_MMUCR,r12 + rlwinm r12, r10, 13, 19, 29 /* Compute pgdir/pmd offset */ lwzx r11, r12, r11 /* Get pgd/pmd entry */ rlwinm. r12, r11, 0, 0, 20 /* Extract pt base address */ @@ -880,60 +857,43 @@ */ /* Load the next available TLB index */ - lis r13, tlb_44x_index@h - ori r13, r13, tlb_44x_index@l - lwz r14, 0(r13) + lis r13, tlb_44x_index@ha + lwz r14, tlb_44x_index@l(r13) /* Load the TLB high watermark */ - lis r13, tlb_44x_hwater@h - ori r13, r13, tlb_44x_hwater@l - lwz r11, 0(r13) - + lwz r11, tlb_44x_hwater@l(r13) /* Increment, rollover, and store TLB index */ addi r14, r14, 1 - cmpw 0, r14, r11 /* reserve entries 62-63 for kernel */ + cmpw 0, r14, r11 /* reserve entries */ ble 7f li r14, 0 7: - /* Load the next available TLB index */ - lis r13, tlb_44x_index@h - ori r13, r13, tlb_44x_index@l - stw r14, 0(r13) + /* Store the next available TLB index */ + stw r14, tlb_44x_index@l(r13) -6: lwz r13, 0(r12) /* Get MS word of PTE */ lwz r11, 4(r12) /* Get LS word of PTE */ rlwimi r13, r11, 0, 0 , 19 /* Insert RPN */ tlbwe r13, r14, PPC44x_TLB_XLAT /* Write XLAT */ /* - * Create PAGEID. This is the faulting address plus - * a set of static bits. The static bits are page - * size and valid. Bits 20 and 21 should be zero - * for a page size of 4KB. - */ - li r12, 0x0210 /* Set size and valid */ - mfspr r13, SPRN_SRR1 /* Get SRR1 */ - andi. r13, r13, MSR_IS@l - beq 7f - ori r12, r12, PPC44x_TLB_TS@l /* Set TS=1 */ -7: rlwimi r10, r12, 0, 20, 31 /* Insert statics */ + * Create PAGEID. This is the faulting address, + * page size, and valid flag. + */ + li r12, PPC44x_TLB_VALID | PPC44x_TLB_4K + rlwimi r10, r12, 0, 20, 31 /* Insert valid and page size */ tlbwe r10, r14, PPC44x_TLB_PAGEID /* Write PAGEID */ - /* FIXME: Staticly setting some permissions */ - li r13, 0x002d /* Set UX,UR,SX,SR */ - andi. r11, r11, 0xffff /* Clear MS 16 bits */ - andi. r12, r11, 0x0002 /* _PAGE_HWWRITE? */ - beq 8f - ori r13, r13, 0x0002 /* Set SW */ - /* FIXME: Force attributes */ -8: ori r11, r11, 0x0100 /* Set G */ - /* FIXME: Already set in PTE */ - rlwimi r11, r13, 0, 26, 31 /* Insert static perms */ + li r13, PPC44x_TLB_SR@l /* Set SR */ + rlwimi r13, r11, 0, 30, 30 /* Set SW = _PAGE_RW */ + rlwimi r13, r11, 29, 29, 29 /* SX = _PAGE_HWEXEC */ + rlwimi r13, r11, 29, 28, 28 /* UR = _PAGE_USER */ + rlwimi r12, r11, 31, 26, 26 /* (_PAGE_USER>>1)->r12 */ + and r12, r12, r11 /* HWEXEC & USER */ + rlwimi r13, r12, 0, 26, 26 /* UX = HWEXEC & USER */ - lis r13,0xffff - ori r13,r13,0x0fff /* Set U0-U3 mask */ - and r11,r11,r13 /* Clear U0-U3 */ + rlwimi r11, r13, 0, 26, 31 /* Insert static perms */ + rlwinm r11, r11, 0, 20, 15 /* Clear U0-U3 */ tlbwe r11, r14, PPC44x_TLB_ATTRIB /* Write ATTRIB */ /* Done...restore registers and get out of here. diff -urN linux-2.6.3-rc2/arch/ppc/kernel/misc.S linux-2.6.3-rc3/arch/ppc/kernel/misc.S --- linux-2.6.3-rc2/arch/ppc/kernel/misc.S 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/kernel/misc.S 2004-02-14 19:30:59.000000000 -0800 @@ -406,17 +406,18 @@ tlbia isync /* Flush shadow TLB */ #elif defined(CONFIG_44x) - lis r3,0 + li r3,0 sync -1: - tlbwe r3,r3,PPC44x_TLB_PAGEID - addi r3,r3,1 + /* Load high watermark */ - lis r4,tlb_44x_hwater@h - ori r4,r4,tlb_44x_hwater@l - lwz r5,0(r4) + lis r4,tlb_44x_hwater@ha + lwz r5,tlb_44x_hwater@l(r4) + +1: tlbwe r3,r3,PPC44x_TLB_PAGEID + addi r3,r3,1 cmpw 0,r3,r5 ble 1b + isync #else /* !(CONFIG_40x || CONFIG_44x) */ #if defined(CONFIG_SMP) @@ -470,17 +471,10 @@ isync 10: #elif defined(CONFIG_44x) - mfspr r4,SPRN_MMUCR /* Get MMUCR */ - lis r5,PPC44x_MMUCR_STS@h - ori r5,r5,PPC44x_MMUCR_TID@l /* Create mask */ - andc r4,r4,r5 /* Clear out TID/STS bits */ + mfspr r4,SPRN_MMUCR mfspr r5,SPRN_PID /* Get PID */ - or r4,r4,r5 /* Set TID bits */ - mfmsr r6 /* Get MSR */ - andi. r6,r6,MSR_IS@l /* TS=1? */ - beq 11f /* If not, leave STS=0 */ - oris r4,r4,PPC44x_MMUCR_STS@h /* Set STS=1 */ -11: mtspr SPRN_MMUCR, r4 /* Put MMUCR */ + rlwimi r4,r5,0,24,31 /* Set TID */ + mtspr SPRN_MMUCR,r4 tlbsx. r3, 0, r3 bne 10f diff -urN linux-2.6.3-rc2/arch/ppc/kernel/pci.c linux-2.6.3-rc3/arch/ppc/kernel/pci.c --- linux-2.6.3-rc2/arch/ppc/kernel/pci.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/kernel/pci.c 2004-02-14 19:30:59.000000000 -0800 @@ -1022,8 +1022,31 @@ prom_add_property(find_path_device("/"), of_prop); } } + +static ssize_t pci_show_devspec(struct device *dev, char *buf) +{ + struct pci_dev *pdev; + struct device_node *np; + + pdev = to_pci_dev (dev); + np = pci_device_to_OF_node(pdev); + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); + #endif /* CONFIG_PPC_OF */ +/* Add sysfs properties */ +void pcibios_add_platform_entries(struct pci_dev *pdev) +{ +#ifdef CONFIG_PPC_OF + device_create_file(&pdev->dev, &dev_attr_devspec); +#endif /* CONFIG_PPC_OF */ +} + + #ifdef CONFIG_PPC_PMAC /* * This set of routines checks for PCI<->PCI bridges that have closed diff -urN linux-2.6.3-rc2/arch/ppc/mm/44x_mmu.c linux-2.6.3-rc3/arch/ppc/mm/44x_mmu.c --- linux-2.6.3-rc2/arch/ppc/mm/44x_mmu.c 2004-02-03 19:44:03.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/mm/44x_mmu.c 2004-02-14 19:30:59.000000000 -0800 @@ -64,7 +64,7 @@ * Just needed it declared someplace. */ unsigned int tlb_44x_index = 0; -unsigned int tlb_44x_hwater = 61; +unsigned int tlb_44x_hwater = 62; /* * "Pins" a 256MB TLB entry in AS0 for kernel lowmem @@ -85,7 +85,7 @@ tlbwe %0,%3,%8" : : "r" (attrib), "r" (phys), "r" (virt), "r" (slot), - "i" (PPC44x_TLB_VALID | PPC44x_TLB_PAGESZ(PPC44x_PAGESZ_256M)), + "i" (PPC44x_TLB_VALID | PPC44x_TLB_256M), "i" (PPC44x_TLB_SW | PPC44x_TLB_SR | PPC44x_TLB_SX | PPC44x_TLB_G), "i" (PPC44x_TLB_PAGEID), "i" (PPC44x_TLB_XLAT), diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/Kconfig linux-2.6.3-rc3/arch/ppc/platforms/4xx/Kconfig --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/Kconfig 2004-02-03 19:43:11.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/Kconfig 2004-02-14 19:30:59.000000000 -0800 @@ -13,48 +13,43 @@ config ASH bool "Ash" - -config BEECH - bool "Beech" - -config CEDAR - bool "Cedar" + help + This option enables support for the IBM NP405H evaluation board. config CPCI405 bool "CPCI405" + help + This option enables support for the CPCI405 board. config EP405 bool "EP405/EP405PC" + help + This option enables support for the EP405/EP405PC boards. config OAK bool "Oak" help - Select Oak if you have an IBM 403GCX "Oak" Evaluation Board. - - Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board. - - More information on these boards is available at: - . - -config REDWOOD_4 - bool "Redwood-4" + This option enables support for the IBM 403GCX evaluation board. config REDWOOD_5 bool "Redwood-5" + help + This option enables support for the IBM STB04 evaluation board. config REDWOOD_6 bool "Redwood-6" + help + This option enables support for the IBM STBx25xx evaluation board. config SYCAMORE bool "Sycamore" - -config TIVO - bool "Tivo" + help + This option enables support for the IBM PPC405GPr evaluation board. config WALNUT bool "Walnut" help - Select Walnut if you have an IBM 405GP "Walnut" Evaluation Board. + This option enables support for the IBM PPC405GP evaluation board. endchoice @@ -120,12 +115,6 @@ depends on 40x && !405GPR default y - -config PIN_TLB - bool - depends on 44x - default y - config BOOKE bool depends on 44x @@ -133,7 +122,7 @@ config IBM_OCP bool - depends on ASH || BEECH || CEDAR || CPCI405 || EBONY || EP405 || OCOTEA || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || CPCI405 || EBONY || EP405 || OCOTEA || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y config IBM_EMAC4 @@ -141,19 +130,14 @@ depends on 440GX default y -config NP405L - bool - depends on CEDAR - default y - config BIOS_FIXUP bool - depends on CEDAR || EP405 || SYCAMORE || WALNUT + depends on EP405 || SYCAMORE || WALNUT default y config 403GCX bool - depends OAK || TIVO + depends OAK default y config 405GP @@ -165,13 +149,9 @@ bool depends on SYCAMORE -config 405LP - bool - depends on CEDAR - config STB03xxx bool - depends on REDWOOD_5 || REDWOOD_4 || REDWOOD_6 + depends on REDWOOD_5 || REDWOOD_6 default y config EMBEDDEDBOOT @@ -181,13 +161,9 @@ config IBM_OPENBIOS bool - depends on ASH || BEECH || CEDAR || REDWOOD_4 || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT + depends on ASH || REDWOOD_5 || REDWOOD_6 || SYCAMORE || WALNUT default y -config 405_DMA - bool "Blue Logic DMA" - depends on 40x - config PM bool "Power Management support (EXPERIMENTAL)" depends on 4xx && EXPERIMENTAL diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/Makefile linux-2.6.3-rc3/arch/ppc/platforms/4xx/Makefile --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/Makefile 2004-02-03 19:44:33.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/Makefile 2004-02-14 19:30:59.000000000 -0800 @@ -2,27 +2,20 @@ # Makefile for the PowerPC 4xx linux kernel. obj-$(CONFIG_ASH) += ash.o -obj-$(CONFIG_BEECH) += beech.o -obj-$(CONFIG_CEDAR) += cedar.o obj-$(CONFIG_CPCI405) += cpci405.o obj-$(CONFIG_EBONY) += ebony.o obj-$(CONFIG_EP405) += ep405.o obj-$(CONFIG_OAK) += oak.o obj-$(CONFIG_OCOTEA) += ocotea.o -obj-$(CONFIG_REDWOOD_4) += redwood.o obj-$(CONFIG_REDWOOD_5) += redwood5.o obj-$(CONFIG_REDWOOD_6) += redwood6.o obj-$(CONFIG_SYCAMORE) += sycamore.o obj-$(CONFIG_WALNUT) += walnut.o -obj-$(CONFIG_NP405L) += ibmnp405l.o obj-$(CONFIG_405GP) += ibm405gp.o -obj-$(CONFIG_REDWOOD_4) += ibmstb3.o obj-$(CONFIG_REDWOOD_5) += ibmstb4.o obj-$(CONFIG_NP405H) += ibmnp405h.o obj-$(CONFIG_REDWOOD_6) += ibmstbx25.o -obj-$(CONFIG_NP4GS3) += ibmnp4gs.o -obj-$(CONFIG_405LP) += ibm405lp.o obj-$(CONFIG_EBONY) += ibm440gp.o obj-$(CONFIG_OCOTEA) += ibm440gx.o obj-$(CONFIG_405GPR) += ibm405gpr.o diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/beech.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/beech.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/beech.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/beech.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,251 +0,0 @@ -/* - * arch/ppc/platforms/beech.c Platform setup for the IBM Beech board - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Copyright (C) 2002, International Business Machines Corporation - * All Rights Reserved - * - * Bishop Brock - * IBM Research, Austin Center for Low-Power Computing - * bcbrock@us.ibm.com - * March, 2002 - * - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -static void beech_ebc_setup(void); -static void beech_fpga_setup(void); - -/* - Beech board physical memory map: - - Main Memory (Initialized by the BIOS) - ======================================================================= - - SDRAM (64 MB) 0x00000000 - 0x04000000 - - OPB Space: (Mapped virtual = physical in ppc4xx_setup.c) - ======================================================================= - - UART0 0xEF600300 - UART1 0xEF600400 - IIC 0xEF600500 - OPB Arbiter 0xEF600600 - GPIO Controller 0xEF600700 - CODEC Interface 0xEF600900 - Touch Panel Controller 0xEF600A00 - DES Controller 0xEF600B00 - - - EBC Space: (Mapped virtual = physical in ppc4xx_map_io(); EBC setup - for PCMCIA left to 4xx_pccf) - Space EBC Bank Physical Addresses EBC Base Address - ========================================================================= - - PCMCIA (32 MB) x F0000000 - F1FFFFFF F0000000 - - Expansion 2 F8000000 - F8FFFFFF F8000000 - Linux Flash (16 MB) F9000000 - F9FFFFFF - - NVRAM (32 KB) 1 FFE00000 - FFE07FFF FFE00000 - - - Ethernet(I/O) 1 FFE20300 - FFE2030F FFE00000 - (MEM) FFE40000 - FFE40FFF - - FPGA_REG_4 1 FFE60000 - FFE60000 FFE00000 - FPGA_REG_0 1 FFE80000 - FFE80000 FFE00000 - FPGA_REG_1 1 FFEA0000 - FFEA0000 FFE00000 - FPGA_REG_2 1 FFEC0000 - FFEC0000 FFE00000 - FPGA_REG_3 1 FFEE0000 - FFEE0000 FFE00000 - - SRAM (512 KB) 0 FFF00000 - FFF7FFFF FFF00000 - - Boot Flash (512 KB) 0 FFF80000 - FFFFFFFF FFF00000 - - ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - - NB: On Beech 1, address ranges for Bank 2 were reversed - -*/ - -void __init -beech_setup_arch(void) -{ - ppc4xx_setup_arch(); - - TODC_INIT(TODC_TYPE_DCR146818, NULL, NULL, NULL, 8); - - /* Set up Beech FPGA. */ - - beech_fpga_setup(); -} - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - ppc4xx_init(r3, r4, r5, r6, r7); - - ppc_md.setup_arch = beech_setup_arch; - -#ifdef CONFIG_PPC_RTC - ppc_md.time_init = todc_time_init; - ppc_md.set_rtc_time = todc_set_rtc_time; - ppc_md.get_rtc_time = todc_get_rtc_time; - ppc_md.nvram_read_val = todc_dcr146818_read_val; - ppc_md.nvram_write_val = todc_dcr146818_write_val; -#endif - /* Disable the LCD controller, which may have been left on by the - BIOS. Then do initialization of the EBC. */ - - mtdcri(DCRN_LCD0, DER, 0); - beech_ebc_setup(); -} - -/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - + Non-standard board support follows - +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ - -/**************************************************************************** - * EBC Setup - ****************************************************************************/ - -/* The EBC is set up for Beech. This may simply replicate the setup already - done by the IBM BIOS for Beech (possibly with some address map changes), or - may be the first initialization if the board is booting from another BIOS. - Virtually all that is required to boot Linux on Beech is that the BIOS - enable the memory controller, load a Linux image from flash, and run it. - - For optimal dynamic frequency scaling the EBC settings will also vary as the - frequency varies. -*/ - -static void __init -beech_ebc_setup(void) -{ - ebc0_bnap_t ap; - ebc0_bncr_t cr; - - /* Set EBC bank 0 for the SRAM and boot flash. - - Access parameters assume 120ns AMD flash @ 66.66 MHz maximum bus - speed = 8 cycle access with 2 turnaround cycles (30 ns). - - These parameters will work for the SRAM as well, which is a 70 ns - part. - - NB: IBM BIOS sets this bank to burst, however bursting will never - happen in Linux because this region is mapped non-cacheable and - guarded, so it is set non-burst here. */ - - cr.reg = (BEECH_BANK0_PADDR & 0xfff00000) | - (mfdcri(DCRN_EBC0, BnCR(0)) & EBC0_BnCR_MASK); - cr.fields.bs = BEECH_BANK0_EBC_SIZE; - cr.fields.bu = EBC0_BnCR_BU_RW; - cr.fields.bw = EBC0_BnCR_BW_16; - mtdcri(DCRN_EBC0, BnCR(0), cr.reg); - - ap.reg = mfdcri(DCRN_EBC0, BnAP(0)) & EBC0_BnAP_MASK; - ap.fields.twt = 8; - ap.fields.th = 2; - mtdcri(DCRN_EBC0, BnAP(0), ap.reg); - - /* EBC bank 1 is used for many purposes: NVRAM, Ethernet, and FPGA - registers. This is a 1 MB, 16-bit bank. The access parameters must - handle the worst case of all of the devices. - - The Ethernet chip needs 20 ns setup of the addresses to the I/O - write signal (generated from the chip select), a minimum 150 ns - cycle, and 30 ns of turnaround. These settings will work for the - other devices as well. - */ - - cr.reg = (BEECH_BANK1_PADDR & 0xfff00000) | - (mfdcri(DCRN_EBC0, BnCR(1)) & EBC0_BnCR_MASK); - cr.fields.bs = BEECH_BANK1_EBC_SIZE; - cr.fields.bu = EBC0_BnCR_BU_RW; - cr.fields.bw = EBC0_BnCR_BW_16; - mtdcri(DCRN_EBC0, BnCR(1), cr.reg); - - ap.reg = mfdcri(DCRN_EBC0, BnAP(1)) & EBC0_BnAP_MASK; - ap.fields.twt = 10; - ap.fields.csn = 2; - ap.fields.th = 2; - mtdcri(DCRN_EBC0, BnAP(1), ap.reg); - - /* Set EBC bank 2 for the big (Linux) flash. There is 16 MB of flash, - but the CPLD decodes a 32 MB region. - - Access parameters assume 90ns AMD flash @ 66.66 MHz maximum bus - speed = 6 cycle access with 2 turnaround cycles (30 ns). - - NB: IBM BIOS sets this bank to burst, however bursting will never - happen in Linux because this region is mapped non-cacheable and - guarded, so it is set non-burst here. */ - - cr.reg = (BEECH_BANK2_PADDR & 0xfff00000) | - (mfdcri(DCRN_EBC0, BnCR(2)) & EBC0_BnCR_MASK); - cr.fields.bs = BEECH_BANK2_EBC_SIZE; - cr.fields.bu = EBC0_BnCR_BU_RW; - cr.fields.bw = EBC0_BnCR_BW_8; - mtdcri(DCRN_EBC0, BnCR(2), cr.reg); - - ap.reg = mfdcri(DCRN_EBC0, BnAP(2)) & EBC0_BnAP_MASK; - ap.fields.twt = 6; - ap.fields.th = 2; - mtdcri(DCRN_EBC0, BnAP(2), ap.reg); -} - -/**************************************************************************** - * FPGA Setup - ****************************************************************************/ - -/* The Beech FPGA is set up for Linux. */ - -static void __init -beech_fpga_setup(void) -{ - volatile u8 *fpga_reg_2; - - fpga_reg_2 = (volatile u8 *) - ioremap(BEECH_FPGA_REG_2_PADDR, BEECH_FPGA_REG_2_SIZE); - - /* Set RTS/CTS mode for UART 1 */ - - *fpga_reg_2 |= FPGA_REG_2_DEFAULT_UART1_N; -} - -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/beech.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/beech.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/beech.h 2004-02-03 19:44:34.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/beech.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,202 +0,0 @@ -/* - * include/asm-ppc/platforms/beech.h Platform definitions for the IBM Beech - * board - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Copyright (C) 2002, International Business Machines Corporation - * All Rights Reserved. - * - * Bishop Brock - * IBM Research, Austin Center for Low-Power Computing - * bcbrock@us.ibm.com - * March, 2002 - * - */ - -#ifdef __KERNEL__ -#ifndef __ASM_BEECH_H__ -#define __ASM_BEECH_H__ - -#include - -#ifndef __ASSEMBLY__ - -/* - * Data structure defining board information maintained by the standard boot - * ROM on the IBM Beech board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned long bi_tbfreq; /* Frequency of SysTmrClk */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned long sysclock_period; /* SysClk period in ns */ - unsigned long sys_speed; /* SysCLk frequency in Hz */ - unsigned long bi_intfreq; /* Processor speed, in Hz */ - unsigned long vco_speed; /* PLL VCO speed, in Hz */ - unsigned long bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned long opb_speed; /* OPB Bus speed, in Hz */ - unsigned long ebc_speed; /* EBC Bus speed, in Hz */ -} bd_t; - -/* See beech.c for a concise diagram of the Beech physical memory map. */ - -#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000) -#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR -#define PPC4xx_ONB_IO_SIZE ((uint)4*1024) - -/* EBC Bank 0 controls the boot flash and SRAM */ - -#define BEECH_BANK0_PADDR ((uint)0xfff00000) -#define BEECH_BANK0_EBC_SIZE EBC0_BnCR_BS_1MB - -#define BEECH_SRAM_PADDR BEECH_BANK0_PADDR -#define BEECH_SRAM_SIZE ((uint)(512 * 1024)) - -#define BEECH_BOOTFLASH_PADDR (BEECH_BANK0_PADDR + (512 * 1024)) -#define BEECH_BOOTFLASH_SIZE ((uint)(512 * 1024)) - -/* EBC bank 1 controls the NVRAM, Ethernet and CPLD registers. The different - areas are mapped in as small an area as possible to help catch any kernel - addressing errors. - - NVRAM is improperly connected on Beech Pass 1. Only every other location is - accessible. This is a 32 KB NVRAM. - - The Ethernet chip maps 13 address lines. We only map the "I/O" space used by - the current driver. - - The FPGA "registers" are decoded on 128 KB boundarys. Each is mapped in a - separate page. */ - -#define BEECH_BANK1_PADDR ((uint)0xffe00000) -#define BEECH_BANK1_EBC_SIZE EBC0_BnCR_BS_1MB - -#define BEECH_NVRAM_PADDR BEECH_BANK1_PADDR -#define BEECH_NVRAM_SIZE ((uint) (32 * 1024)) - -#define BEECH_ETHERNET_PADDR (BEECH_BANK1_PADDR + 0x00020000) -#define BEECH_ETHERNET_SIZE ((uint) (8 * 1024)) - -#define BEECH_FPGA_REG_0_PADDR (BEECH_BANK1_PADDR + 0x00080000) -#define BEECH_FPGA_REG_0_SIZE PAGE_SIZE - -#define BEECH_FPGA_REG_1_PADDR (BEECH_BANK1_PADDR + 0x000A0000) -#define BEECH_FPGA_REG_1_SIZE PAGE_SIZE - -#define BEECH_FPGA_REG_2_PADDR (BEECH_BANK1_PADDR + 0x000C0000) -#define BEECH_FPGA_REG_2_SIZE PAGE_SIZE - -#define BEECH_FPGA_REG_3_PADDR (BEECH_BANK1_PADDR + 0x000E0000) -#define BEECH_FPGA_REG_3_SIZE PAGE_SIZE - -#define BEECH_FPGA_REG_4_PADDR (BEECH_BANK1_PADDR + 0x00060000) -#define BEECH_FPGA_REG_4_SIZE PAGE_SIZE - -/* FPGA Register Bits (From IBM BIOS) [ May not be valid for Beech Pass 1 ]*/ - -#define FPGA_REG_0_FLASH_N 0x01 -#define FPGA_REG_0_FLASH_ONBD_N 0x02 -#define FPGA_REG_0_HITA_TOSH_N 0x04 /* New in Pass 2 */ -#define FPGA_REG_0_STAT_OC 0x20 -#define FPGA_REG_0_AC_SOURCE_SEL_N 0x40 -#define FPGA_REG_0_AC_ACTIVE_N 0x80 - -#define FPGA_REG_1_USB_ACTIVE 0x01 /* New in Pass 2 */ -#define FPGA_REG_1_CLK_VARIABLE 0x02 -#define FPGA_REG_1_CLK_TEST 0x04 -#define FPGA_REG_1_CLK_SS 0x08 -#define FPGA_REG_1_EXT_IRQ_N 0x10 -#define FPGA_REG_1_SMI_MODE_N 0x20 -#define FPGA_REG_1_BATT_LOW_N 0x40 -#define FPGA_REG_1_PCMCIA_PWR_FAULT_N 0x80 - -#define FPGA_REG_2_DEFAULT_UART1_N 0x01 -#define FPGA_REG_2_EN_1_8V_PLL_N 0x02 -#define FPGA_REG_2_PC_BUF_EN_N 0x08 -#define FPGA_REG_2_CODEC_RESET_N 0x10 /* New in Pass 2 */ -#define FPGA_REG_2_TP_JSTICK_N 0x20 /* New in Pass 2 */ - -#define FPGA_REG_3_GAS_GAUGE_IO 0x01 - -#define FPGA_REG_4_SDRAM_CLK3_ENAB 0x01 -#define FPGA_REG_4_SDRAM_CLK2_ENAB 0x02 -#define FPGA_REG_4_SDRAM_CLK1_ENAB 0x04 -#define FPGA_REG_4_SDRAM_CLK0_ENAB 0x08 -#define FPGA_REG_4_PCMCIA_5V 0x10 /* New in Pass 2 */ -#define FPGA_REG_4_IRQ3 0x20 /* New in Pass 2 */ - -/* EBC Bank 2 contains the 16 MB "Linux" flash. The FPGA decodes a 32 MB - bank. The lower 16 MB are available for expansion devices. The upper 16 MB - are used for the "Linux" flash. - - Partitioning information is for the benefit of the MTD driver. See - drivers/mtd/maps/ibm4xx.c. We currently allocate the lower 1 MB for a - kernel, and the other 15 MB for a filesystem. - -*/ - -/* Bank 2 mappings changed between Beech Pass 1 and Pass 2 */ - -#ifdef CONFIG_BEECH_PASS1 -#define BEECH_BIGFLASH_OFFSET 0 -#else -#define BEECH_BIGFLASH_OFFSET (16 * 1024 * 1024) -#endif - -#define BEECH_BANK2_PADDR ((uint)0xf8000000) -#define BEECH_BANK2_EBC_SIZE EBC0_BnCR_BS_32MB - -#define BEECH_BIGFLASH_PADDR (BEECH_BANK2_PADDR + BEECH_BIGFLASH_OFFSET) -#define BEECH_BIGFLASH_SIZE (16 * 1024 * 1024) - -#define BEECH_KERNEL_OFFSET 0 -#define BEECH_KERNEL_SIZE (1 * 1024 * 1024) - -#define BEECH_FREE_AREA_OFFSET BEECH_KERNEL_SIZE -#define BEECH_FREE_AREA_SIZE (BEECH_BIGFLASH_SIZE - BEECH_KERNEL_SIZE) - -/* The PCMCIA controller driver 4xx_pccf.c is responsible for the EBC setup of - PCMCIA. Externally, EBC bank selects 3..7 take on PCMCIA functions when - PCMCIA is enabled. */ - -#define BEECH_PCMCIA_PADDR ((uint)0xf0000000) -#define BEECH_PCMCIA_SIZE ((uint)(32 * 1024 * 1024)) - -/* We do not currently support the internal clock mode for the UART. This - limits the minimum OPB frequency to just over 2X the UART oscillator - frequency. At OPB frequencies less than this the serial port will not - function due to the way that SerClk is sampled. */ - -#define PPC4xx_SERCLK_FREQ 11059200 -#define BASE_BAUD (PPC4xx_SERCLK_FREQ / 16) - -#define PPC4xx_MACHINE_NAME "IBM 405LP Beech" - -/**************************************************************************** - * Non-standard board support follows - ****************************************************************************/ - -extern int beech_sram_free(void *p); -extern int ibm405lp_set_pixclk(unsigned pixclk_low, unsigned pixclk_high); -extern void *beech_sram_alloc(size_t size); - -#endif /* !__ASSEMBLY__ */ -#endif /* __ASM_BEECH_H__ */ -#endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/cedar.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/cedar.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/cedar.c 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/cedar.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,90 +0,0 @@ -/* - * arch/ppc/platforms/4xx/cedar.c - * - * Support for the IBM NP405L ceder eval board - * - * Author: Armin Kuster - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ -#include -#include -#include -#include - -#include -#include - -void *cedar_rtc_base; - -void __init -cedar_setup_arch(void) -{ - bd_t *bip = &__res; - - /* RTC step for the walnut */ - cedar_rtc_base = (void *) CEDAR_RTC_VADDR; - TODC_INIT(TODC_TYPE_DS1743, cedar_rtc_base, cedar_rtc_base, - cedar_rtc_base, 8); - -#ifdef CONFIG_DEBUG_BRINGUP - printk("\n"); - printk("machine\t: %s\n", PPC4xx_MACHINE_NAME); - printk("\n"); - printk("bi_s_version\t %s\n", bip->bi_s_version); - printk("bi_r_version\t %s\n", bip->bi_r_version); - printk("bi_memsize\t 0x%8.8x\t %dMBytes\n", bip->bi_memsize, - bip->bi_memsize / (1024 * 1000)); - printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 0, - bip->bi_enetaddr[0][0], bip->bi_enetaddr[0][1], - bip->bi_enetaddr[0][2], bip->bi_enetaddr[0][3], - bip->bi_enetaddr[0][4], bip->bi_enetaddr[0][5]); - - printk("bi_enetaddr %d\t %2.2x%2.2x%2.2x-%2.2x%2.2x%2.2x\n", 1, - bip->bi_enetaddr[1][0], bip->bi_enetaddr[1][1], - bip->bi_enetaddr[1][2], bip->bi_enetaddr[1][3], - bip->bi_enetaddr[1][4], bip->bi_enetaddr[1][5]); - - printk("bi_intfreq\t 0x%8.8x\t clock:\t %dMhz\n", - bip->bi_intfreq, bip->bi_intfreq / 1000000); - - printk("bi_busfreq\t 0x%8.8x\t plb bus clock:\t %dMHz\n", - bip->bi_busfreq, bip->bi_busfreq / 1000000); - printk("bi_pci_busfreq\t 0x%8.8x\t pci bus clock:\t %dMHz\n", - bip->bi_pci_busfreq, bip->bi_pci_busfreq / 1000000); - - printk("\n"); -#endif - - /* Identify the system */ - printk - ("IBM Cedar port (C) 2002 MontaVista Software, Inc. (source@mvista.com)\n"); - -} - -void __init -cedar_map_io(void) -{ - ppc4xx_map_io(); - io_block_mapping(CEDAR_RTC_VADDR, - CEDAR_RTC_PADDR, CEDAR_RTC_SIZE, _PAGE_IO); -} - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - ppc4xx_init(r3, r4, r5, r6, r7); - - ppc_md.setup_arch = cedar_setup_arch; - ppc_md.setup_io_mappings = cedar_map_io; - - ppc_md.time_init = todc_time_init; - ppc_md.set_rtc_time = todc_set_rtc_time; - ppc_md.get_rtc_time = todc_get_rtc_time; - ppc_md.nvram_read_val = todc_direct_read_val; - ppc_md.nvram_write_val = todc_direct_write_val; -} diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/cedar.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/cedar.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/cedar.h 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/cedar.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,68 +0,0 @@ -/* - * arch/ppc/platforms/4xx/cedar.h - * - * Macros, definitions, and data structures specific to the IBM PowerPC - * Cedar eval board. - * - * Author: Armin Kuster - * - * 2000 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_CEDAR_H__ -#define __ASM_CEDAR_H__ -#include - -#ifndef __ASSEMBLY__ -/* - * Data structure defining board information maintained by the boot - * ROM on IBM's "Cedar" evaluation board. An effort has been made to - * keep the field names consistent with the 8xx 'bd_t' board info - * structures. - */ - -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned char bi_enetaddr[2][6]; /* Local Ethernet MAC address */ - unsigned char bi_pci_mac[6]; - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* PLB Bus speed, in Hz */ - unsigned int bi_pci_busfreq; /* PCI speed in Hz */ -} bd_t; - -/* Some 4xx parts use a different timebase frequency from the internal clock. -*/ -#define bi_tbfreq bi_intfreq - -/* Memory map for the IBM "Cedar" NP405 evaluation board. - */ - -extern void *cedar_rtc_base; -#define CEDAR_RTC_PADDR ((uint)0xf0000000) -#define CEDAR_RTC_VADDR CEDAR_RTC_PADDR -#define CEDAR_RTC_SIZE ((uint)8*1024) - -/* Early initialization address mapping for block_io. - * Standard 405GP map. - */ -#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000) -#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR -#define PPC4xx_ONB_IO_SIZE ((uint)4*1024) - -#ifdef CONFIG_PPC405GP_INTERNAL_CLOCK -#define BASE_BAUD 201600 -#else -#define BASE_BAUD 691200 -#endif - -#define PPC4xx_MACHINE_NAME "IBM NP405L Cedar" - -#endif /* !__ASSEMBLY__ */ -#endif /* __ASM_CEDAR_H__ */ -#endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibm405lp.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibm405lp.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibm405lp.c 2004-02-03 19:43:31.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibm405lp.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,266 +0,0 @@ -/* - * arch/ppc/platforms/ibm405lp.c 405LP-specific code - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Copyright (C) 2002, International Business Machines Corporation - * All Rights Reserved. - * - * Bishop Brock - * IBM Research, Austin Center for Low-Power Computing - * bcbrock@us.ibm.com - * March, 2002 - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct ocp_def core_ocp[] __initdata = { - {OCP_VENDOR_IBM, OCP_FUNC_OPB, OPB0_BASE, OCP_IRQ_NA, OCP_CPM_NA}, - {OCP_VENDOR_IBM, OCP_FUNC_16550, UART0_IO_BASE, UART0_INT,IBM_CPM_UART0}, - {OCP_VENDOR_IBM, OCP_FUNC_16550, UART1_IO_BASE, UART1_INT, IBM_CPM_UART1}, - {OCP_VENDOR_IBM, OCP_FUNC_IIC, IIC0_BASE, IIC0_IRQ, IBM_CPM_IIC0}, - {OCP_VENDOR_IBM, OCP_FUNC_GPIO, GPIO0_BASE, OCP_IRQ_NA, IBM_CPM_GPIO0}, - {OCP_VENDOR_INVALID, OCP_FUNC_INVALID, 0x0, OCP_IRQ_NA, OCP_CPM_NA}, -}; - -#ifdef CONFIG_PM -/* Set up the 405LP clock and power management unit for aggressive power - management. - - Briefly, there are 3 CPM "classes": - - Class 1 - Either completely asleep or awake. The "force" state is - equivalent to the "enabled" state. Many Class 1 units are - critical system components and are never power managed. - - Class 2 - Can be enabled for power management, where sleep requests are - made by the peripheral, typically after an inactivity timeout. - When sleeping, critical interfaces remain active, and - awaken the unit whenever it is targeted with a transaction. - - Class 3 - Can be enabled for power management, where sleep requests are - made by the CPM. Power management for these units typically - will require intelligence in a device driver. - - In the current implementation, the "force" bits are only used on Class 1 - devices, and only when the associated driver has the intelligence necessary - to "unforce" the power management state. A previous scheme, which tried to - enable power management based on whether a particular driver was compiled - with the kernel, caused many problems and is never used here. - - Class 2 devices with timeouts are normally initialized for the most - aggressive values. There is no power management benefit of "forcing" Class - 2 devices over letting their inactivity timeouts take effect. Therefore, - after being set up here, Class 2 device drivers don't need to worry about - CPM. - - No Class 3 devices are handled yet. */ - -void __init -ibm405lp_setup_cpm(void) -{ - u32 force = 0; - u32 enable = 0; - dma0_slp_t dma0_slp; - dcp0_cfg_t dcp0_cfg; - ebc0_cfg_t ebc0_cfg; - sdram0_cfg_t sdram0_cfg; - sdram0_pmit_t sdram0_pmit; - sla0_slpmd_t sla0_slpmd; - - /* Initialize the CPM state */ - - mtdcr(DCRN_CPMFR, force); - mtdcr(DCRN_CPMER, enable); - - /* IIC - Class 3 - Not handled yet. The driver should at least be able - to force/unforce itself. */ - - /* CPU - class 2 - There doesn't appear to be a timeout associated with - this, and the exact function is not documented anywhere. It saves a - lot of power, though. I assume this gates core clocks when the CPU - core is asleep, and probably adds a couple of cycles of latency when - the CPU core wakes up. */ - - enable |= IBM_CPM_CPU; - - /* DMA - class 2. Set for the minimum timeout, which is 32 cycles. */ - - dma0_slp.reg = mfdcr(DCRN_SLP); - dma0_slp.fields.sme = 1; - dma0_slp.fields.idu = 0; - mtdcr(DCRN_SLP, dma0_slp.reg); - enable |= IBM_CPM_DMA; - - /* BRG - Class 2. Seems to crash the system when enabled in 405LP Pass - 1 - - DCP (CodePack) - Class 2. The semantics of the sleep delay are not - documented. We'll use 32 (what the heck). */ - - dcp0_cfg.reg = mfdcri(DCRN_DCP0, CFG); - dcp0_cfg.fields.slen = 1; - dcp0_cfg.fields.sldy = 32; - mtdcri(DCRN_DCP0, CFG, dcp0_cfg.reg); - enable |= IBM_CPM_DCP; - - /* EBC - Class 2. Set for minimum timeout, which is 32 cycles. [ I - think this is 32. It may be 64. I don't trust the documentation. ] - */ - - ebc0_cfg.reg = mfdcri(DCRN_EBC0, CFG); - ebc0_cfg.fields.pme = 1; - ebc0_cfg.fields.pmt = 1; - mtdcri(DCRN_EBC0, CFG, ebc0_cfg.reg); - enable |= IBM_CPM_EBC; - - /* SDRAM - Class 2. Set for the minimum 32-cycle timeout. - - The documentation on this core is clear - waking a sleeping SDRAM - controller takes 2 PLB cycles, which is added to the latency of the - memory operation. If someone can prove that this is affecting - performance we can easily back this off. */ - - sdram0_cfg.reg = mfdcri(DCRN_SDRAM0, CFG); - sdram0_cfg.fields.pme = 1; - mtdcri(DCRN_SDRAM0, CFG, sdram0_cfg.reg); - - sdram0_pmit.reg = mfdcri(DCRN_SDRAM0, PMIT); - sdram0_pmit.fields.cnt = 0; - mtdcri(DCRN_SDRAM0, PMIT, sdram0_pmit.reg); - - enable |= IBM_CPM_SDRAM0; - - /* PLB - Class 2. Seems to crash the system when enabled in 405LP Pass - 1. - - GPIO - Class 1. This unit is used for many things, and no single - driver controls all GPIO. It's best left unmanaged (it doesn't use - much power anyway). NB: 405LP Pass 1 erratum - forcing PM on GPIO - kills the TPC. - - UART0 - Class 1 - UART1 - Class 1 - - Someone should work on the serial port drivers to enable PM support - for them. Any takers? - - UIC - Class 1 - CPU_TMRCLK - Class 1 - - These system resources are never power managed. */ - - /* SLA - Class 2. Set for the minimum 32-cycle timeout. */ - - sla0_slpmd.reg = mfdcri(DCRN_SLA0, SLPMD); - sla0_slpmd.fields.slen = 1; - sla0_slpmd.fields.slcr = 0; - mtdcri(DCRN_SLA0, SLPMD, sla0_slpmd.reg); - enable |= IBM_CPM_SLA; - - /* CSI - Class 1. - TPC - Class 1. - TDES - Class 1. - - The drivers for these units are power-aware, and manage the device - properly. By default these units are forced off at boot. */ - - force |= IBM_CPM_CSI; - force |= IBM_CPM_TPC; - force |= IBM_CPM_TDES; - - /* Set the CPM state */ - - mtdcr(DCRN_CPMFR, force); - mtdcr(DCRN_CPMER, enable); -} -#endif - -/* This routine is included here because the framebuffer driver needs a way to - tell the system the Pixel clock frequency it needs, regardless of whether - run-time frequency scaling is configured. A hook and a couple of global - variables are always present and will be used by the RTVFS driver if it is - loaded. - - Pixel clock setting is kind of a hack, as the frequency steps available from - the PLB/PixClk divider may be too large to guarantee that we'll hit within - the given limits. We never set the frequency above the upper bound, but due - to quantization may need to set the frequency below the lower bound. So far - it works OK for the panels we've tried. - - In general, the choice of a system clock frequency should be made with - consideration of the LCD panel to be attached, to guarantee a good clock - divider for the Pixel clock regardless of frequency scaling. - - Clock frequencies are in KHz. If pixclk_min or pixclk_max are zero, we set - the lowest possible frequency to conserve energy. */ - -int (*set_pixclk_hook) (unsigned pixclk_min, unsigned pixclk_max) = NULL; -unsigned last_pixclk_min = 0; -unsigned last_pixclk_max = 0; - -EXPORT_SYMBOL(set_pixclk_hook); -EXPORT_SYMBOL(last_pixclk_min); -EXPORT_SYMBOL(last_pixclk_max); - -int -ibm405lp_set_pixclk(unsigned pixclk_min, unsigned pixclk_max) -{ - unsigned divider; - bd_t *bip = (bd_t *) __res; - unsigned plb_khz = bip->bi_busfreq / 1000; - cpc0_cgcr1_t cgcr1; - - if (set_pixclk_hook) { - return (set_pixclk_hook) (pixclk_min, pixclk_max); - } else { - if ((pixclk_min == 0) || (pixclk_max == 0)) - divider = CPC0_DIV_MAX; - else { - divider = plb_khz / pixclk_min; - if (divider == 0) - divider = 1; - if ((divider < CPC0_DIV_MAX) && - ((plb_khz / divider) > pixclk_max)) - divider++; - } - - cgcr1.reg = mfdcr(DCRN_CPC0_CGCR1); - cgcr1.fields.ppxl = CPC0_DIV_ENCODE(divider); - mtdcr(DCRN_CPC0_CGCR1, cgcr1.reg); - - last_pixclk_min = pixclk_min; - last_pixclk_max = pixclk_max; - return 0; - } -} diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibm405lp.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibm405lp.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibm405lp.h 2004-02-03 19:44:21.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibm405lp.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,900 +0,0 @@ -/* - * include/asm-ppc/platforms/ibm405lp.h 405LP-specific definitions - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Copyright (C) 2002, International Business Machines Corporation - * All Rights Reserved. - * - * Bishop Brock - * IBM Research, Austin Center for Low-Power Computing - * bcbrock@us.ibm.com - * March, 2002 - * - */ - -#ifdef __KERNEL__ -#ifndef __ASM_IBM405LP_H__ -#define __ASM_IBM405LP_H__ - -#include -#include - -/* Machine-specific register naming for the 4xx processors is a mess. It seems - that everyone had a different idea on how to prefix/abbreviate/configure the - DCR numbers and MMIO addresses. I'm no different! For the 405LP we have - defined all of the DCRs and MMIO address consistently with their names as - documented in the official IBM hardware manual for the processor. - - DCRs are all given a DCRN_ prefix, which seems to be the most - common consistent naming scheme in old code (although the official IBM DCR - names are so unique that there's really little need for the DCRN_). - - At the end of the DCR defines several synonyms are defined for backwards - compatibility, but all new code specific to the 405LP uses the consistent - names. - - Version 07/24/02 1.1 - Armin - added default pm define -*/ - -/***************************************************************************** - * Directly accessed DCRs - *****************************************************************************/ - -/* DCRs used for Indirect Access */ - -#define DCRN_SDRAM0_CFGADDR 0x010 /* Memory Ctlr. DCR Address Register */ -#define DCRN_SDRAM0_CFGDATA 0x011 /* Memory Ctlr. DCR Data Register */ -#define DCRN_EBC0_CFGADDR 0x012 /* Peripheral Ctlr. DCR Address Register */ -#define DCRN_EBC0_CFGDATA 0x013 /* Peripheral Ctlr. DCR Data Register */ -#define DCRN_SLA0_CFGADDR 0x0e0 /* Speech Label Accel. DCR Address Reg. */ -#define DCRN_SLA0_CFGDATA 0x0e1 /* Speech Label Accel. DCR Data Reg. */ -#define DCRN_LCD0_CFGADDR 0x3c8 /* LCD Ctlr. DCR Address Reg. */ -#define DCRN_LCD0_CFGDATA 0x3c9 /* LCD Ctlr. DCR Data Reg. */ - -/* On-chip Buses */ - -#define DCRN_PLB0_BESR 0x084 /* PLB Bus Error Status Register */ -#define DCRN_PLB0_BEAR 0x086 /* PLB Bus Error Address Register */ -#define DCRN_PLB0_ACR 0x087 /* PLB Arbiter Control Register */ -#define DCRN_POB0_BESR0 0x0a0 /* PLB to OPB Bus Error Status Register 0 */ -#define DCRN_POB0_BEAR 0x0a2 /* PLB to OPB Bus Error Address Register */ -#define DCRN_POB0_BESR1 0x0a4 /* PLB to OPB Bus Error Status Register 1 */ - -/* Clocking and Chip Control */ - -#define DCRN_CPC0_PLLMR 0x0b0 /* PLL Mode Register */ -#define DCRN_CPC0_CGCR0 0x0b1 /* Clock Generation Control Register 0 */ -#define DCRN_CPC0_CGCR1 0x0b2 /* Clock Generation Control Register 1 */ -#define DCRN_CPC0_CR0 0x0b5 /* Chip Control Register 0 */ -#define DCRN_CHCR0 DCRN_CPC0_CR0 -#define DCRN_CPC0_CR1 0x0b4 /* Chip Control Register 1 */ -#define DCRN_CPC0_PLBAPR 0x0b6 /* PLB Arbiter Priority Register */ -#define DCRN_CPC0_JTAGID 0x0b7 /* JTAG ID Register */ - -/* Clock and Power Management */ - -#define DCRN_CPMSR_BASE 0x0b8 /* CPM Status Register */ -#define DCRN_CPMFR_BASE 0x0ba /* CPM Force Register */ - -/* Universal Interrupt Controller */ - -#define DCRN_UIC0_SR 0x0c0 /* UIC Status Register */ -#define DCRN_UIC0_ER 0x0c2 /* UIC Enable Register */ -#define DCRN_UIC0_CR 0x0c3 /* UIC Critical Register */ -#define DCRN_UIC0_PR 0x0c4 /* UIC Polarity Register */ -#define DCRN_UIC0_TR 0x0c5 /* UIC Triggering Register */ -#define DCRN_UIC0_MSR 0x0c6 /* UIC Masked Status Register */ -#define DCRN_UIC0_VR 0x0c7 /* UIC Vector Register */ -#define DCRN_UIC0_VCR 0x0c8 /* UIC Vector Configuration Register */ - -/* Real-time Clock */ - -#define DCRN_RTC0_SEC 0x140 /* RTC Seconds Register */ -#define DCRN_RTC0_SECAL 0x141 /* RTC Seconds Alarm Register */ -#define DCRN_RTC0_MIN 0x142 /* RTC Minutes Register */ -#define DCRN_RTC0_MINAL 0x143 /* RTC Minutes Alarm Register */ -#define DCRN_RTC0_HR 0x144 /* RTC Hours Register */ -#define DCRN_RTC0_HRAL 0x145 /* RTC Hours Alarm Register */ -#define DCRN_RTC0_DOW 0x146 /* RTC Day of Week Register */ -#define DCRN_RTC0_DOM 0x147 /* RTC Date of Month Register */ -#define DCRN_RTC0_MONTH 0x148 /* RTC Month Register */ -#define DCRN_RTC0_YEAR 0x149 /* RTC Year Register */ -#define DCRN_RTC0_CR0 0x14a /* RTC "A" Register */ -#define DCRN_RTC0_CR1 0x14b /* RTC "B" Register */ -#define DCRN_RTC0_CR2 0x14c /* RTC "C" Register */ -#define DCRN_RTC0_CR3 0x14d /* RTC "D" Register */ -#define DCRN_RTC0_CEN 0x14e /* RTC Century Register */ -#define DCRN_RTC0_WRAP 0x150 /* RTC Wrapper */ - -/* Advanced Power Management Controller */ - -#define DCRN_APM0_ISR 0x160 /* APM Interrupt Status Register */ -#define DCRN_APM0_IER 0x162 /* APM Interrupt Enable Register */ -#define DCRN_APM0_IPR 0x163 /* APM Interrupt Polarity Register */ -#define DCRN_APM0_ITR 0x164 /* APM Interrupt Trigger Register */ -#define DCRN_APM0_CFG 0x165 /* APM Configuration Register */ -#define DCRN_APM0_SR 0x166 /* APM Status Register */ -#define DCRN_APM0_ID 0x167 /* APM Revision ID Register */ - -/* Triple DES Controller */ - -#define DCRN_TDES0_ADDR 0x180 /* TDES OPB Slave Base Address */ -#define DCRN_TDES0_CFG 0x181 /* TDES OPB Slave Configuration */ -#define DCRN_TDES0_STAT 0x182 /* TDES Status */ -#define DCRN_TDES0_ID 0x183 /* TDES Core ID */ - -/* LCD Controller */ - -#define DCRN_LCD0_CFG 0x3c0 /* LCD Configuration Register */ -#define DCRN_LCD0_ICR 0x3c1 /* LCD Interrupt Control Register */ -#define DCRN_LCD0_ISR 0x3c2 /* LCD Interrupt Status Register */ -#define DCRN_LCD0_IMR 0x3c3 /* LCD Interrupt Mask Register */ - -/***************************************************************************** - * Indirectly accessed DCRs. Note that unlike direct-access DCRs whose numbers - * must be hard-coded into the instruction, indirect-access DCR numbers can be - * computed. - *****************************************************************************/ - -/* Offsets for SDRAM Controler Registers */ - -#define DCRN_SDRAM0_BESR0 0x00 /* Bus Error Syndrome Register 0 */ -#define DCRN_SDRAM0_BESR1 0x08 /* Bus Error Syndrome Register 1 */ -#define DCRN_SDRAM0_BEAR 0x10 /* Bus Error Address Register */ -#define DCRN_SDRAM0_CFG 0x20 /* Memory Controller Options 1 */ -#define DCRN_SDRAM0_STATUS 0x24 /* SDRAM controller status */ -#define DCRN_SDRAM0_RTR 0x30 /* Refresh Timer Register */ -#define DCRN_SDRAM0_PMIT 0x34 /* Power Management Idle Timer */ -#define DCRN_SDRAM0_B0CR 0x40 /* Memory Bank 0 Configuration */ -#define DCRN_SDRAM0_B1CR 0x44 /* Memory Bank 1 Configuration */ -#define DCRN_SDRAM0_B2CR 0x48 /* Memory Bank 2 Configuration */ -#define DCRN_SDRAM0_B3CR 0x4c /* Memory Bank 3 Configuration */ -#define DCRN_SDRAM0_TR 0x80 /* Sdram Timing Register 1 */ -#define DCRN_SDRAM0_ECCCFG 0x94 /* ECC Configuration */ -#define DCRN_SDRAM0_ECCESR 0x98 /* ECC Error Status Register */ - -#define SDRAM0_BANKS 4 -#define DCRN_SDRAM0_BnCR(bank) (0x40 + (4 * (bank))) - -/* Offsets for External Bus Controller Registers */ - -#define DCRN_EBC0_B0CR 0x00 /* Peripheral Bank 0 Configuration Register */ -#define DCRN_EBC0_B1CR 0x01 /* Peripheral Bank 1 Configuration Register */ -#define DCRN_EBC0_B2CR 0x02 /* Peripheral Bank 2 Configuration Register */ -#define DCRN_EBC0_B3CR 0x03 /* Peripheral Bank 3 Configuration Register */ -#define DCRN_EBC0_B4CR 0x04 /* Peripheral Bank 4 Configuration Register */ -#define DCRN_EBC0_B5CR 0x05 /* Peripheral Bank 5 Configuration Register */ -#define DCRN_EBC0_B6CR 0x06 /* Peripheral Bank 6 Configuration Register */ -#define DCRN_EBC0_B7CR 0x07 /* Peripheral Bank 7 Configuration Register */ -#define DCRN_EBC0_B0AP 0x10 /* Peripheral Bank 0 Access Parameters */ -#define DCRN_EBC0_B1AP 0x11 /* Peripheral Bank 1 Access Parameters */ -#define DCRN_EBC0_B2AP 0x12 /* Peripheral Bank 2 Access Parameters */ -#define DCRN_EBC0_B3AP 0x13 /* Peripheral Bank 3 Access Parameters */ -#define DCRN_EBC0_B4AP 0x14 /* Peripheral Bank 4 Access Parameters */ -#define DCRN_EBC0_B5AP 0x15 /* Peripheral Bank 5 Access Parameters */ -#define DCRN_EBC0_B6AP 0x16 /* Peripheral Bank 6 Access Parameters */ -#define DCRN_EBC0_B7AP 0x17 /* Peripheral Bank 7 Access Parameters */ -#define DCRN_EBC0_BEAR 0x20 /* Periperal Bus Error Address Register */ -#define DCRN_EBC0_BESR0 0x21 /* Peripheral Bus Error Status Register 0 */ -#define DCRN_EBC0_BESR1 0x22 /* Peripheral Bus Error Status Register 0 */ -#define DCRN_EBC0_CFG 0x23 /* External Peripheral Control Register */ - -#define EBC0_BANKS 8 -#define DCRN_EBC0_BnCR(bank) (bank) -#define DCRN_EBC0_BnAP(bank) (0x10 + (bank)) - -/* Offsets for LCD Controller DCRs */ - -#define DCRN_LCD0_DER 0x80010000 /* Display Enable Regsiter */ -#define DCRN_LCD0_DCFG 0x80010010 /* Display Configuration Register */ -#define DCRN_LCD0_DSR 0x80010040 /* Display Status Register */ -#define DCRN_LCD0_FRDR 0x80010080 /* Dither and Frame Rate Modulation Reg. */ -#define DCRN_LCD0_SDR 0x800100c0 /* Signal Delay Register */ -#define DCRN_LCD0_ADSR 0x80010100 /* Active Display Size Register */ -#define DCRN_LCD0_TDSR 0x80010104 /* Total Display Size Register */ -#define DCRN_LCD0_FPLCR 0x80010140 /* FPLINE Control Register */ -#define DCRN_LCD0_FPLOR 0x80010144 /* FPLINE Offset Register */ -#define DCRN_LCD0_FPFCR 0x80010148 /* FPFRAME Control Register */ -#define DCRN_LCD0_FPFOR 0x8001014c /* FPFRAME Control Register */ -#define DCRN_LCD0_FPSCR 0x80010150 /* FPSHIFT Control Register */ -#define DCRN_LCD0_FPDRR 0x80010158 /* FPDRDY Control Register */ -#define DCRN_LCD0_FPDCR 0x80010160 /* FPDATA Control Register */ -#define DCRN_LCD0_PFBFR 0x80010800 /* Pixel and Frame Buffer Format Reg. */ -#define DCRN_LCD0_PFR 0x80011000 /* Pixel Format Register */ -#define DCRN_LCD0_FBBAR 0x80011008 /* Frame Buffer Base Address Register */ -#define DCRN_LCD0_STRIDE 0x8001100c /* Stride Register */ -#define DCRN_LCD0_PAR 0x80011800 /* Palette Access Registers Base */ -#define DCRN_LCD0_CER 0x80012000 /* Cursor Enable Register */ -#define DCRN_LCD0_CBAR 0x80012008 /* Cursor Base Address Register */ -#define DCRN_LCD0_CLR 0x8001200c /* Cursor Location Register */ -#define DCRN_LCD0_CC0R 0x80012010 /* Cursor Color 0 */ -#define DCRN_LCD0_CC1R 0x80012014 /* Cursor Color 1 */ - -#define LCD0_PAR_REGS 256 -#define DCRN_LCD0_PARn(n) (DCRN_LCD0_PAR + (4 * (n))) - -/* Offsets for Decompression Controller DCRs */ - -#define DCRN_DCP0_ITOR0 0x00 /* Index Table Origin Register 0 */ -#define DCRN_DCP0_ITOR1 0x01 /* Index Table Origin Register 1 */ -#define DCRN_DCP0_ITOR2 0x02 /* Index Table Origin Register 2 */ -#define DCRN_DCP0_ITOR3 0x03 /* Index Table Origin Register 3 */ -#define DCRN_DCP0_ADDR0 0x04 /* Address Decode Definition Register 0 */ -#define DCRN_DCP0_ADDR1 0x05 /* Address Decode Definition Register 1 */ -#define DCRN_DCP0_CFG 0x40 /* Decompression Controller Cfg. Register */ -#define DCRN_DCP0_ID 0x41 /* Decompression Controller ID Register */ -#define DCRN_DCP0_VER 0x42 /* Decompression Controller Version Register */ -#define DCRN_DCP0_PLBBEAR 0x50 /* Bus Error Address Register (PLB) */ -#define DCRN_DCP0_MEMBEAR 0x51 /* Bus Error Address Register (EBC/SDRAM) */ -#define DCRN_DCP0_ESR 0x52 /* Bus Error Status Register 0 (Masters 0-3) */ - -#define DCRN_DCP0_RAMn(n) (0x400 + (n)) /* Decompression Decode Table Entries - 0x400-0x5FF Low 16-bit decode table - 0x600-0x7FF High 16-bit decode table - */ - -/* Offsets for Speech Label Accelerator DCRs */ - -#define DCRN_SLA0_CR 0x00 /* SLA Control Register */ -#define DCRN_SLA0_SR 0x01 /* SLA Status Register */ -#define DCRN_SLA0_BESR 0x02 /* SLA Bus Error Status Register */ -#define DCRN_SLA0_BEAR 0x03 /* SLA Bus Error Address Register */ -#define DCRN_SLA0_UADDR 0x04 /* SLA PLB Upper Address Register */ -#define DCRN_SLA0_GMBA 0x05 /* SLA General Indirect Memory Base Address */ -#define DCRN_SLA0_GMLL 0x06 /* SLA General Indirect Memory Link List */ -#define DCRN_SLA0_AMBA 0x07 /* SLA Atom Memory Base Address Register */ -#define DCRN_SLA0_ACBA 0x08 /* SLA Accumulator Base Address Register */ -#define DCRN_SLA0_DIBA 0x09 /* SLA Done Indication Base Address Register */ -#define DCRN_SLA0_GPOFF 0x0A /* SLA General Indirect Pass Offset Register */ -#define DCRN_SLA0_SLPMD 0x0B /* SLA Sleep Mode Control Register */ -#define DCRN_SLA0_ID 0x0C /* SLA ID Register */ -#define DCRN_SLA0_GMLLR 0x0D /* SLA General Indirect Memory Link List Reset */ - -#define DCRN_DMA0_BASE 0x100 -#define DCRN_DMA1_BASE 0x108 -#define DCRN_DMA2_BASE 0x110 -#define DCRN_DMA3_BASE 0x118 -#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ -#define DCRN_DMASR_BASE 0x120 -#define DCRN_EBC_BASE 0x012 -#define DCRN_DCP0_BASE 0x014 -#define DCRN_UIC0_BASE 0x0C0 - -#define UIC0 DCRN_UIC0_BASE - -#undef NR_UICS -#define NR_UICS 1 - -/* More memory-mapped I/O bases, etc., esp. for OCP, that should be moved - elsewhere. */ - -#define IIC0_BASE 0xEF600500 -#define OPB0_BASE 0xEF600600 -#define GPIO0_BASE 0xEF600700 - -#define IIC0_IRQ 2 - -/**************************************************************************** - * MMIO Addresses - ***************************************************************************/ - -/* Touch Panel/PWM Controller */ - -#define TPC0_IO_BASE 0xef600a00 - -#define TPC_CR 0x00 /* TPC Command Register */ -#define TPC_PCRX 0x04 /* TPC Precharge Count Register X1 */ -#define TPC_DCRX 0x08 /* TPC Discharge Count Register X1 */ -#define TPC_PCRY 0x0c /* TPC Precharge Count Register Y1 */ -#define TPC_DCRY 0x10 /* TPC Discharge Count Register Y1 */ -#define TPC_RRX 0x14 /* TPC Read Register X1 */ -#define TPC_RRY 0x18 /* TPC Read Register Y1 */ -#define TPC_SRX 0x1c /* TPC Status Register X1 */ -#define TPC_SRY 0x20 /* TPC Status Register Y1 */ - -/* Triple-DES Controller */ - -#define TDES0_IO_BASE 0xef600b00 - -/***************************************************************************** - * CPM bits for the 405LP. - *****************************************************************************/ - -#define CPM_BITMASK(i) (((unsigned)0x80000000) >> i) - -#define IBM_CPM_IIC0 CPM_BITMASK(0) /* IIC Interface */ -#define IBM_CPM_CPU CPM_BITMASK(1) /* Processor Core */ -#define IBM_CPM_DMA CPM_BITMASK(3) /* DMA Controller */ -#define IBM_CPM_OPB CPM_BITMASK(4) /* PLB to OPB Bridge */ -#define IBM_CPM_DCP CPM_BITMASK(5) /* CodePack */ -#define IBM_CPM_EBC CPM_BITMASK(6) /* ROM/SRAM Peripheral Controller */ -#define IBM_CPM_SDRAM0 CPM_BITMASK(7) /* SDRAM memory controller */ -#define IBM_CPM_PLB CPM_BITMASK(8) /* PLB bus arbiter */ -#define IBM_CPM_GPIO0 CPM_BITMASK(9) /* General Purpose IO (??) */ -#define IBM_CPM_UART0 CPM_BITMASK(10) /* Serial Port 0 */ -#define IBM_CPM_UART1 CPM_BITMASK(11) /* Serial Port 1 */ -#define IBM_CPM_UIC CPM_BITMASK(12) /* Universal Interrupt Controller */ -#define IBM_CPM_TMRCLK CPM_BITMASK(13) /* CPU Timers */ -#define IBM_CPM_SLA CPM_BITMASK(14) /* Speech Label Accelerator */ -#define IBM_CPM_CSI CPM_BITMASK(15) /* CODEC Serial Interface */ -#define IBM_CPM_TPC CPM_BITMASK(16) /* Touch Panel Controller */ -#define IBM_CPM_TDES CPM_BITMASK(18) /* Triple DES */ - -#define DFLT_IBM4xx_PM 0 /* for now until we get a better hable on this one - armin */ - -/***************************************************************************** - * UIC IRQ ordinals for the 405LP. IRQ bit names are as documented in the - * 405LP manual (except for reserved fields). Backwards-compatible synonyms - * appear at the end. - *****************************************************************************/ - -#define UIC_IRQ_U0 0 /* UART0 */ -#define UIC_IRQ_U1 1 /* UART1 */ -#define UIC_IRQ_IIC 2 /* IIC */ -#define UIC_IRQ_EM 3 /* EBC ??? */ -#define UIC_IRQ_IRQ4 4 /* Reserved */ -#define UIC_IRQ_D0 5 /* DMA Channel 0 */ -#define UIC_IRQ_D1 6 /* DMA Channel 1 */ -#define UIC_IRQ_D2 7 /* DMA Channel 2 */ -#define UIC_IRQ_D3 8 /* DMA Channel 3 */ -#define UIC_IRQ_IRQ9 9 /* Reserved */ -#define UIC_IRQ_IRQ10 10 /* Reserved */ -#define UIC_IRQ_IRQ11 11 /* Reserved */ -#define UIC_IRQ_IRQ12 12 /* Reserved */ -#define UIC_IRQ_IRQ13 13 /* Reserved */ -#define UIC_IRQ_IRQ14 14 /* Reserved */ -#define UIC_IRQ_IRQ15 15 /* Reserved */ -#define UIC_IRQ_IRQ16 16 /* Reserved */ -#define UIC_IRQ_EC 17 /* ECC Correctable Error ??? */ -#define UIC_IRQ_TPX 18 /* Touch Panel X */ -#define UIC_IRQ_TPY 19 /* Touch Panel Y */ -#define UIC_IRQ_SLA 20 /* SLA Interrupt */ -#define UIC_IRQ_CSI 21 /* CSI Interrupt */ -#define UIC_IRQ_LCD 22 /* LCD Interrupt */ -#define UIC_IRQ_RTC 23 /* RTC Interrupt */ -#define UIC_IRQ_APM 24 /* APM Interrupt */ -#define UIC_IRQ_EIR0 25 /* External IRQ 0 */ -#define UIC_IRQ_EIR1 26 /* External IRQ 1 */ -#define UIC_IRQ_EIR2 27 /* External IRQ 2 */ -#define UIC_IRQ_EIR3 28 /* External IRQ 3 */ -#define UIC_IRQ_EIR4 29 /* External IRQ 4 */ -#define UIC_IRQ_EIR5 30 /* External IRQ 5 */ -#define UIC_IRQ_EIR6 31 /* External IRQ 6 */ - -/***************************************************************************** - * Serial port definitions - *****************************************************************************/ - -#ifdef CONFIG_SERIAL_MANY_PORTS -#define RS_TABLE_SIZE 64 -#else -#define RS_TABLE_SIZE 4 -#endif - -#define UART0_INT UIC_IRQ_U0 -#define UART1_INT UIC_IRQ_U1 -#define UART0_IO_BASE 0xEF600300 -#define UART1_IO_BASE 0xEF600400 - -#define STD_UART_OP(num) \ - { 0, BASE_BAUD, 0, UART##num##_INT, \ - (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base:(u8 *) UART##num##_IO_BASE, \ - io_type: SERIAL_IO_MEM}, - -#if defined(CONFIG_UART0_TTYS0) -#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE -#define SERIAL_PORT_DFNS \ - STD_UART_OP(0) \ - STD_UART_OP(1) -#endif - -#if defined(CONFIG_UART0_TTYS1) -#define SERIAL_DEBUG_IO_BASE UART1_IO_BASE -#define SERIAL_PORT_DFNS \ - STD_UART_OP(1) \ - STD_UART_OP(0) -#endif - -#ifndef __ASSEMBLY__ - -#include -#include - -/**************************************************************************** - * DCR type structures and field definitions for DCRs manipulated by the 405LP - * Linux port - ****************************************************************************/ - -/* APM0_CFG - APM Configuration Register */ - -typedef union { - u32 reg; - struct { - unsigned int rsvd:17; - unsigned int isp:1; /* Initiate Sleep */ - unsigned int ewt:1; /* Enable Watchdog Timer */ - unsigned int sm:2; /* Sleep Mode */ - unsigned int iica:3; /* I2C Address (low-order 3 bits) */ - unsigned int psc:1; /* Power Select Control */ - unsigned int cdiv:6; /* IIC Clock Divider */ - unsigned int v:1; /* Valid bit */ - } fields; -} apm0_cfg_t; - -#define APM0_CFG_MASK 0xffff8000 /* AND to clear all non-reserved fields */ - -/* APM0_SR - APM Status Register */ - -typedef union { - u32 reg; - struct { - unsigned int rsvd:17; - unsigned int cdet:1; /* Clock Detect */ - unsigned int en:1; /* APM Enable Indicator */ - unsigned int rset:1; /* Processor Reset by APM? */ - unsigned int pfr:1; /* Power Fail Reset? */ - unsigned int rsrt:1; /* Restart Successful? */ - unsigned int sdwn:1; /* Shutdown Complete */ - unsigned int errc:8; /* Error Code */ - unsigned int v:1; /* Valid Bit */ - } fields; -} apm0_sr_t; - -#define APM0_SR_MASK 0xffff8000 /* AND to clear all non-reserved fields */ - -/* APM0_IER -- APM Interrupt Enable Register - APM0_IPR -- APM Interrupt Polarity Register - APM0_ISR -- APM Interrupt Status Register - APM0_ITR -- APM Interrupt Trigger Register - - The interrupts are also accessed via standard interrupt numbers: - - 59 : Wake-up Input 0 - 60 : Wake-up Input 1 - 61 : Wake-up Input 2 - 62 : Real-Time Clock Interrupt -*/ - -typedef union { - u32 reg; - struct { - unsigned int rsvd:27; - unsigned int wi0e:1; - unsigned int wi1e:1; - unsigned int wi2e:1; - unsigned int cie:1; - unsigned int v:1; - } fields; -} apm0_ier_t; - -typedef union { - u32 reg; - struct { - unsigned int rsvd:27; - unsigned int wi0p:1; - unsigned int wi1p:1; - unsigned int wi2p:1; - unsigned int cip:1; - unsigned int v:1; - } fields; -} apm0_ipr_t; - -typedef union { - u32 reg; - struct { - unsigned int rsvd:27; - unsigned int wi0s:1; - unsigned int wi1s:1; - unsigned int wi2s:1; - unsigned int cis:1; - unsigned int v:1; - } fields; -} apm0_isr_t; - -typedef union { - u32 reg; - struct { - unsigned int rsvd:27; - unsigned int wi0t:1; - unsigned int wi1t:1; - unsigned int wi2t:1; - unsigned int cit:1; - unsigned int v:1; - } fields; -} apm0_itr_t; - -#define APM0_IER_MASK 0xffffffe0 /* AND to clear all non-reserved fields */ -#define APM0_IPR_MASK 0xffffffe0 /* AND to clear all non-reserved fields */ -#define APM0_ISR_MASK 0xffffffe0 /* AND to clear all non-reserved fields */ -#define APM0_ITR_MASK 0xffffffe0 /* AND to clear all non-reserved fields */ - -/* CPC0_PLLMR - PLL Mode Register */ - -typedef union { - u32 reg; - struct { - unsigned int pmul:5; /* PLL Multiplier */ - unsigned int pdiv:5; /* PLL Divider */ - unsigned int tun:10; /* PLL Tuning Control */ - unsigned int db2:1; /* Divide VCO by 2 Select */ - unsigned int csel:2; /* PLL Clock Output Select */ - unsigned int rsvd:8; /* Reserved */ - unsigned int v:1; /* Valid bit */ - } fields; -} cpc0_pllmr_t; - -#define CPC0_PLLMR_MASK 0x000001fe /* AND to clear all non-reserved fields */ -#define CPC0_PLLMR_RTVFS_MASK CPC0_PLLMR_MASK /* All bits controlled by RTVFS */ - -/* The PLL multiplier/divider are always multiples of 4. */ - -#define CPC0_PLLMR_MULDIV_ENCODE(n) ((((unsigned)(n)) / 4) - 1) -#define CPC0_PLLMR_MULDIV_DECODE(n) (((n) + 1) * 4) -#define CPC0_PLLMR_MULDIV_MAX 128 - -#define CPC0_PLLMR_TUN_HIGH 0x200 /* High-band tuning */ -#define CPC0_PLLMR_TUN_LOW 0x000 /* Low-band tuning */ - -#define CPC0_PLLMR_CSEL_REFCLK 0 /* System Reference Clock */ -#define CPC0_PLLMR_CSEL_PLLVCO 1 /* PLL VCO */ -#define CPC0_PLLMR_CSEL_RTC 2 /* RTC */ -#define CPC0_PLLMR_CSEL_EBCPLB5 3 /* EBC-PLB divisor is 5 ??? */ - -/* CPC0_CGCR0 - Clock Generation and Control Register 0 */ - -typedef union { - u32 reg; - struct { - unsigned int pcp:5; /* Proc. Core/PLB Clock Divisor */ - unsigned int pcsc:5; /* Proc. Core/SysClkOut Divisor */ - unsigned int pcu:5; /* Proc. Core/UARTSerClk Clock Div. */ - unsigned int u0cs:1; /* UART0 Clock Select */ - unsigned int u1cs:1; /* UART1 Clock Select */ - unsigned int scsel:2; /* SysClkOut Select */ - unsigned int rsvd:13; /* Reserved */ - } fields; -} cpc0_cgcr0_t; - -#define CPC0_CGCR0_MASK 0x00001fff /* AND to clear all non-reserved fields */ -#define CPC0_CGCR0_RTVFS_MASK 0x0001ffff /* AND to clear all rtvfs-modified - fields */ - -#define CPC0_CGCR0_SCSEL_OFF 0 /* SysClkOut driven low (low power) */ -#define CPC0_CGCR0_SCSEL_CPU 1 /* Select CPU clock as SysClkOut */ -#define CPC0_CGCR0_SCSEL_PLB 2 /* SysClkOut is PLB Sample Cycle */ -#define CPC0_CGCR0_SCSEL_OPB 3 /* SysClkOut is OPB Sample Cycle */ - -/* CPC0_CGCR1 - Clock Generation and Control Register 1 */ - -typedef union { - u32 reg; - struct { - unsigned int po:5; /* PLB/OPB Clock Divisor */ - unsigned int pext:5; /* PLB/External Clock Divisor */ - unsigned int ppxl:5; /* PLB/LCD Pixel Clock Divisor */ - unsigned int csel:2; /* PerClk Select */ - unsigned int rsvd:15; /* Reserved */ - } fields; -} cpc0_cgcr1_t; - -#define CPC0_CGCR1_MASK 0x00007fff /* AND to clear all non-reserved fields */ -#define CPC0_CGCR1_RTVFS_MASK 0x0001ffff /* AND to clear all rtvfs-modified - fields */ - -/* 5-bit clock dividers are directly encoded, except that an encoding of 0 - indicates divide-by-32. */ - -#define CPC0_DIV_MAX 32 -#define CPC0_DIV_VALID(n) (((n) > 0) && ((n) <= CPC0_DIV_MAX)) -#define CPC0_DIV_ENCODE(n) (((unsigned)(n) >= CPC0_DIV_MAX) ? 0 : (unsigned)(n)) -#define CPC0_DIV_DECODE(n) (((n) == 0) ? CPC0_DIV_MAX : (n)) - -#define CPC0_CGCR1_CSEL_OFF 0 /* PerClk driven low (low power) */ -#define CPC0_CGCR1_CSEL_PERCLK 1 /* Select PerClk */ -#define CPC0_CGCR1_CSEL_PLBCLK 2 /* Select PLB clock */ -#define CPC0_CGCR1_CSEL_OPBCLK 3 /* Select OPB clock */ - -/* CPC0_CR0 - Chip Control Register 0 */ - -typedef union { - u32 reg; - struct { - unsigned int rsvd0:7; /* Reserved */ - unsigned int ssr:1; /* SDRAM Self-Refresh on Sleep Req. */ - unsigned int gpms:2; /* GPIO Pin Muxing Select */ - unsigned int u0pms:2; /* UART0 Pin Muxing Select */ - unsigned int u1pms:2; /* UART1 Pin Muxing Select */ - unsigned int ipms:2; /* IIC Pin Muxing Select */ - unsigned int cpms:2; /* CSI Pin Muxing Select */ - unsigned int tpms:2; /* TPC Pin Muxing Select */ - unsigned int irpms:2; /* IRQ Pin Muxing Select */ - unsigned int pcmd:1; /* PCMCIA Mode Disable */ - unsigned int u0dte:1; /* UART0 DMA Transmit Channel Enable */ - unsigned int u0rde:1; /* UART0 DMA Receive Channel Enable */ - unsigned int u0dce:1; /* UART0 DMA CLear on Enable */ - unsigned int rsvd1:6; /* Reserved */ - } fields; -} cpc0_cr0_t; - -#define CPC0_CR0_MASK 0xfe00003f /* AND to clear all non-reserved fields */ - -/* CPC0_CR1 - Chip Control Register 1 */ - -typedef union { - u32 reg; - struct { - unsigned int rsvd0:28; /* Reserved */ - unsigned int tbsed:1; /* TB. Src. in Edge Detect Mode */ - unsigned int edmd:1; /* TB. Src. Edge Detect Mode Disable */ - unsigned int rsvd1:2; /* Reserved */ - } fields; -} cpc0_cr1_t; - -#define CPC0_CR1_MASK 0xfffffff3 /* AND to clear all non-reserved fields */ - -/* DCP0_CFG - DCP Configuration Register */ - -typedef union { - u32 reg; - struct { - unsigned int rsvd0:18; - unsigned int sldy:10; /* Sleep Delay */ - unsigned int slen:1; /* Sleep Enable */ - unsigned int cdb:1; /* Clear Decompression Buffer */ - unsigned int rsvd1:1; - unsigned int ikb:1; /* Enable Decompression */ - } fields; -} dcp0_cfg_t; - -#define DCP0_CFG_MASK 0xffffc002 /* AND to clear all non-reserved fields */ - -/* DMA0_SLP - DMA Sleep Mode Register */ - -typedef union { - u32 reg; - struct { - unsigned idu:5; /* Idle Timer Upper */ - unsigned rsvd0:5; - unsigned sme:1; /* Sleep Mode Enable */ - unsigned rsvd1:21; - } fields; -} dma0_slp_t; - -#define DMA0_SLP_MASK 0x07dfffff /* AND to clear all non-reserved fields */ - -/* EBC0_BnAP - EBC Bank Access Parameters */ - -typedef union { - u32 reg; - struct { - unsigned bme:1; /* Burst Mode Enable */ - unsigned twt:8; /* Transfer Wait (non-burst) */ - unsigned rsvd0:3; - unsigned csn:2; /* Chip Select On Timing */ - unsigned oen:2; /* Output Enable On Timing */ - unsigned wbn:2; /* Write Byte Enable On Timing */ - unsigned wbf:2; /* Write Byte Enable Off Timing */ - unsigned th:3; /* Transfer Hold */ - unsigned re:1; /* Ready Enable */ - unsigned sor:1; /* Sample On Ready */ - unsigned bem:1; /* Byte Enable Mode */ - unsigned pen:1; /* Parity Enable */ - unsigned rsvd1:5; - } fields; -} ebc0_bnap_t; - -#define EBC0_BnAP_MASK 0x0070001f /* AND to clear all non-reserved fields */ - -/* EBC0_BnCR - EBC Bank Configuration Registers */ - -typedef union { - u32 reg; - struct { - unsigned bas:12; /* Base Address */ - unsigned bs:3; /* Bank Size */ - unsigned bu:2; /* Bank Usage */ - unsigned bw:2; /* Bank Width */ - unsigned rsvd:13; - } fields; -} ebc0_bncr_t; - -#define EBC0_BnCR_MASK 0x00001fff /* AND to clear all non-reserved fields */ - -#define EBC0_BnCR_BS_1MB 0 -#define EBC0_BnCR_BS_2MB 1 -#define EBC0_BnCR_BS_4MB 2 -#define EBC0_BnCR_BS_8MB 3 -#define EBC0_BnCR_BS_16MB 4 -#define EBC0_BnCR_BS_32MB 5 -#define EBC0_BnCR_BS_64MB 6 -#define EBC0_BnCR_BS_128MB 7 - -#define EBC0_BnCR_BU_R 1 -#define EBC0_BnCR_BU_W 2 -#define EBC0_BnCR_BU_RW 3 - -#define EBC0_BnCR_BW_8 0 -#define EBC0_BnCR_BW_16 1 -#define EBC0_BnCR_BW_32 2 - -/* EBC0_CFG -EBC Configuration Register */ - -typedef union { - u32 reg; - struct { - unsigned ebtc:1; /* External Bus Three State Control */ - unsigned ptd:1; /* Device-paced Time-out Disable */ - unsigned rtc:3; /* Ready Timeout Count */ - unsigned rsvd0:4; - unsigned cstc:1; /* Chip Select Three State Control */ - unsigned bpf:2; /* Burst Prefetch */ - unsigned rsvd1:2; - unsigned pme:1; /* Power Management Enable */ - unsigned pmt:5; /* Power Management Timer */ - unsigned rsvd2:12; - } fields; -} ebc0_cfg_t; - -#define EBC0_CFG_MASK 0x078c0fff /* AND to clear all non-reserved fields */ - -#define EBC0_CFG_RTC_16 0 -#define EBC0_CFG_RTC_32 1 -#define EBC0_CFG_RTC_64 2 -#define EBC0_CFG_RTC_128 3 -#define EBC0_CFG_RTC_256 4 -#define EBC0_CFG_RTC_512 5 -#define EBC0_CFG_RTC_1024 6 -#define EBC0_CFG_RTC_2048 7 - -/* SDRAM0_CFG - SDRAM Controller Configuration Register */ - -typedef union { - u32 reg; - struct { - unsigned int dce:1; /* SDRAM Controller Enable */ - unsigned int sre:1; /* Self-Refresh Enable */ - unsigned int pme:1; /* Power Management Enable */ - unsigned int rsvd0:1; - unsigned int regen:1; /* Registered Memory Enable */ - unsigned int drw:2; /* SDRAM Width */ - unsigned int brpf:2; /* Burst Read Prefetch Granularity */ - unsigned int rsvd1:1; - unsigned int emdulr:1; /* Enable Memory Data Unless Read */ - unsigned int rsvd2:21; - } fields; -} sdram0_cfg_t; - -#define SDRAM0_CFG_MASK 0x106fffff /* AND to clear all non-reserved fields */ - -#define SDRAM0_CFG_BRPF_16 1 -#define SDRAM0_CFG_BRPF_32 2 - -/* SDRAM0_PMIT - SDRAM Power Management Idle Timer */ - -typedef union { - u32 reg; - struct { - unsigned int cnt:5; /* Cycle Count Before Sleep Request */ - unsigned int rsvd:27; - } fields; -} sdram0_pmit_t; - -#define SDRAM0_PMIT_MASK 0x07ffffff /* AND to clear all non-reserved fields */ - -/* SDRAM0_RTR - Refresh timer register */ - -typedef union { - u32 reg; - struct { - unsigned rsvd0:2; - unsigned iv:11; - unsigned rsvd1:19; - } fields; -} sdram0_rtr_t; - -#define SDRAM0_RTR_MASK 0xc007ffff /* AND to clear non-reserved fields */ -#define SDRAM0_RTR_RTVFS_MASK SDRAM0_RTR_MASK - -#define SDRAM0_RTR_IV(n) (((n) & 0x3ff8) >> 2) - -/* SDRAM0_TR - SDRAM Timing Register */ - -typedef union { - u32 reg; - struct { - unsigned int rsvd0:7; - unsigned int casl:2; /* CAS Latency */ - unsigned int rsvd1:3; - unsigned int pta:2; /* Precharge-to-activate */ - unsigned int ctp:2; /* Read/Write to Precharge */ - unsigned int ldf:2; /* Command Leadoff */ - unsigned int rsvd2:9; - unsigned int rfta:3; /* Refresh-to-Activate */ - unsigned int rcd:2; /* RAS-CAS Delay */ - } fields; -} sdram0_tr_t; - -#define SDRAM0_TR_MASK 0xfe703fe0 /* AND to clear non-reserved fields */ -#define SDRAM0_TR_RTVFS_MASK SDRAM0_TR_MASK - -#define SDRAM0_TR_ENCODE(n) ((n) - 1) -#define SDRAM0_TR_ENCODE_RFTA(n) ((n) - 4) - -/* SLA0_SLPMD - SLA Sleep Mode Control Register */ - -typedef union { - u32 reg; - struct { - unsigned slcr:5; /* Sleep Counter */ - unsigned rsvd0:5; - unsigned slen:1; /* Sleep Mode Enable */ - unsigned rsvd1:21; - } fields; -} sla0_slpmd_t; - -#define SLA0_SLPMD_MASK 0x07dfffff /* AND to clear all non-reserved fields */ - -/* Several direct-write DCRs on the 405LP have an interlock requirement, - implemented by a "valid" bit in the low-order bit. This routine handles the - handshaking for these registers, by - - 1) Rewriting the current value with the valid bit clear; - 2) Rewriting the new value with the valid bit clear; - 3) Rewriting the new value with the valid bit set. - - The mask is a mask with 1s in every reserved bit position. - - NB: This routine always writes the register with the valid bit set, - regardless of the valid bit setting in the 'new' parameter. - - Unfortunately this must be a macro to work (due to mtdcr()). - - Note that for APM registers, it takes multiple RTC clock cycles for the DCR - writes to take effect. Any time delays after writes to APM are the - resonsibility of the caller. -*/ - -#define mtdcr_interlock(dcrn, new, mask) \ -do { \ - u32 __old, __new; \ - \ - __old = mfdcr(dcrn); \ - mtdcr(dcrn, __old & 0xfffffffe); \ - __new = ((__old & (mask)) | ((new) & ~(mask))) & 0xfffffffe; \ - mtdcr(dcrn, __new); \ - mtdcr(dcrn, __new | 1); \ -} while (0) - -/**************************************************************************** - * Power Managament Routines - ****************************************************************************/ - -int ibm405lp_set_pixclk(unsigned pixclk_min, unsigned pixclk_max); - -void ibm405lp_reset_sdram(u32 new_rtr, u32 new_tr); - -extern int (*set_pixclk_hook) (unsigned pixclk_min, unsigned pixclk_max); -extern unsigned last_pixclk_min; -extern unsigned last_pixclk_max; - -#endif /* __ASSEMBLY__ */ - -#include - -#endif /* __ASM_IBM405LP_H__ */ -#endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp405l.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp405l.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp405l.c 2004-02-03 19:43:15.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp405l.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,31 +0,0 @@ -/* - * arch/ppc/platforms/4xx/ibmnp405l.c - * - * Author: Armin Kuster - * - * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include -#include - -struct ocp_def core_ocp[] = { - {UART, UART0_IO_BASE, UART0_INT, IBM_CPM_UART0}, - {UART, UART1_IO_BASE, UART1_INT, IBM_CPM_UART1}, - {IIC, IIC0_BASE, IIC0_IRQ, IBM_CPM_IIC0}, - {GPIO, GPIO0_BASE, OCP_IRQ_NA, IBM_CPM_GPIO0}, - {OPB, OPB0_BASE, OCP_IRQ_NA, IBM_CPM_OPB}, - {EMAC, EMAC0_BASE, BL_MAC_ETH0, IBM_CPM_EMAC0}, - {EMAC, EMAC1_BASE, BL_MAC_ETH1, IBM_CPM_EMAC1}, - {ZMII, ZMII0_BASE, OCP_IRQ_NA, OCP_CPM_NA}, - {OCP_NULL_TYPE, 0x0, OCP_IRQ_NA, OCP_CPM_NA}, - -}; diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp405l.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp405l.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp405l.h 2004-02-03 19:43:42.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp405l.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,133 +0,0 @@ -/* - * arch/ppc/platforms/4xx/ibmnp405l.h - * - * Author: Armin Kuster - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_IBMNP405L_H__ -#define __ASM_IBMNP405L_H__ - -#include - -/* serial port defines */ -#define RS_TABLE_SIZE 2 - -#define UART0_INT 0 -#define UART1_INT 1 - -#define UART0_IO_BASE 0xEF600300 -#define UART1_IO_BASE 0xEF600400 -#define IIC0_BASE 0xEF600500 -#define OPB0_BASE 0xEF600600 -#define GPIO0_BASE 0xEF600700 -#define EMAC0_BASE 0xEF600800 -#define EMAC1_BASE 0xEF600900 -#define ZMII0_BASE 0xEF600C10 -#define BL_MAC_WOL 41 /* WOL */ -#define BL_MAL_SERR 45 /* MAL SERR */ -#define BL_MAL_TXDE 46 /* MAL TXDE */ -#define BL_MAL_RXDE 47 /* MAL RXDE */ -#define BL_MAL_TXEOB 17 /* MAL TX EOB */ -#define BL_MAL_RXEOB 18 /* MAL RX EOB */ -#define BL_MAC_ETH0 37 /* MAC */ -#define BL_MAC_ETH1 38 /* MAC */ - -#define EMAC_NUMS 2 - -#define IIC0_IRQ 2 - -#undef NR_UICS -#define NR_UICS 2 -#define UIC_CASCADE_MASK 0x0003 /* bits 30 & 31 */ - -#define BD_EMAC_ADDR(e,i) bi_enetaddr[e][i] - -#define STD_UART_OP(num) \ - { 0, BASE_BAUD, 0, UART##num##_INT, \ - (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base:(u8 *) UART##num##_IO_BASE, \ - io_type: SERIAL_IO_MEM}, - -#if defined(CONFIG_UART0_TTYS0) -#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE -#define SERIAL_PORT_DFNS \ - STD_UART_OP(0) \ - STD_UART_OP(1) -#endif - -#if defined(CONFIG_UART0_TTYS1) -#define SERIAL_DEBUG_IO_BASE UART1_IO_BASE -#define SERIAL_PORT_DFNS \ - STD_UART_OP(1) \ - STD_UART_OP(0) -#endif - -/* DCR defines */ -/* ------------------------------------------------------------------------- */ - -#define DCRN_CHCR_BASE 0x0F1 -#define DCRN_CHPSR_BASE 0x0B4 -#define DCRN_CPMSR_BASE 0x0BA -#define DCRN_CPMFR_BASE 0x0B9 -#define DCRN_CPMER_BASE 0x0B8 - -#define IBM_CPM_EMAC0 0x00800000 /* on-chip ethernet MM unit */ -#define IBM_CPM_EMAC1 0x00100000 /* EMAC 1 MII */ -#define IBM_CPM_UIC1 0x00020000 /* Universal Interrupt Controller */ -#define IBM_CPM_UIC0 0x00010000 /* Universal Interrupt Controller */ -#define IBM_CPM_CPU 0x00008000 /* processor core */ -#define IBM_CPM_EBC 0x00004000 /* ROM/SRAM peripheral controller */ -#define IBM_CPM_SDRAM0 0x00002000 /* SDRAM memory controller */ -#define IBM_CPM_GPIO0 0x00001000 /* General Purpose IO (??) */ -#define IBM_CPM_HDLC 0x00000800 /* HDCL */ -#define IBM_CPM_TMRCLK 0x00000400 /* CPU timers */ -#define IBM_CPM_PLB 0x00000100 /* PLB bus arbiter */ -#define IBM_CPM_OPB 0x00000080 /* PLB to OPB bridge */ -#define IBM_CPM_DMA 0x00000040 /* DMA controller */ -#define IBM_CPM_IIC0 0x00000010 /* IIC interface */ -#define IBM_CPM_UART0 0x00000002 /* serial port 0 */ -#define IBM_CPM_UART1 0x00000001 /* serial port 1 */ -#define DFLT_IBM4xx_PM ~(IBM_CPM_UIC0 | IBM_CPM_UIC1 | IBM_CPM_CPU \ - | IBM_CPM_EBC | IBM_CPM_SDRAM0 | IBM_CPM_PLB \ - | IBM_CPM_OPB | IBM_CPM_TMRCLK | IBM_CPM_DMA \ - | IBM_CPM_EMAC0 | IBM_CPM_EMAC1) - -#define DCRN_DMA0_BASE 0x100 -#define DCRN_DMA1_BASE 0x108 -#define DCRN_DMA2_BASE 0x110 -#define DCRN_DMA3_BASE 0x118 -#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ -#define DCRN_DMASR_BASE 0x120 -#define DCRN_EBC_BASE 0x012 -#define DCRN_DCP0_BASE 0x014 -#define DCRN_MAL_BASE 0x180 -#define DCRN_MAL1_BASE 0x200 -#define DCRN_OCM0_BASE 0x018 -#define DCRN_PLB0_BASE 0x084 -#define DCRN_PLLMR_BASE 0x0F0 -#define DCRN_POB0_BASE 0x0A0 -#define DCRN_SDRAM0_BASE 0x010 -#define DCRN_UIC0_BASE 0x0C0 -#define DCRN_UIC1_BASE 0x0D0 -#define DCRN_CPC0_EPRCSR 0x0F3 - -#define UIC0_UIC1NC 30 /* UIC1 non-critical interrupt */ -#define UIC0_UIC1CR 31 /* UIC1 critical interrupt */ - -#define CHR1_CETE 0x00000004 /* CPU external timer enable */ -#define UIC0 DCRN_UIC0_BASE -#define UIC1 DCRN_UIC1_BASE - -#define SDRAM_CFG 0x20 -#define SDRAM0_ECCCFG 0x94 -#define SDRAM_NO_ECC 0x10000000 -#include - -#endif /* __ASM_IBMNP405L_H__ */ -#endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp4gs.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp4gs.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp4gs.c 2004-02-03 19:43:45.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp4gs.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,21 +0,0 @@ -/* - * arch/ppc/platforms/4xx/ibmnp4gs.c - * - * Author: Armin Kuster - * - * 2000-2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include "ibmnp4gs.h" -#include - -struct ocp_def core_ocp[] = { - {UART, UART0_IO_BASE, UART0_INT, IBM_CPM_UART0}, - {PCI, PCIL0_BASE, OCP_IRQ_NA, IBM_CPM_PCI}, - {OCP_NULL_TYPE, 0x0, OCP_IRQ_NA, OCP_CPM_NA}, - -}; diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp4gs.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp4gs.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmnp4gs.h 2004-02-03 19:43:57.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmnp4gs.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,149 +0,0 @@ -/* - * arch/ppc/platforms/4xx/ibmnp4gs.h - * - * Author: Armin Kuster - * - * 2002 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_IBMNP4GS_H__ -#define __ASM_IBMNP4GS_H__ - -#include -#include - -/* ibm405.h at bottom of this file */ - -/* PCI - * PCI Bridge config reg definitions - * see 17-19 of manual - */ - -#define PPC405_PCI_CONFIG_ADDR 0xeec00000 -#define PPC405_PCI_CONFIG_DATA 0xeec00004 - -#define PPC405_PCI_PHY_MEM_BASE 0x80000000 /* hose_a->pci_mem_offset */ - /* setbat */ -#define PPC405_PCI_MEM_BASE PPC405_PCI_PHY_MEM_BASE /* setbat */ -#define PPC405_PCI_PHY_IO_BASE 0xe8000000 /* setbat */ -#define PPC405_PCI_IO_BASE PPC405_PCI_PHY_IO_BASE /* setbat */ - -#define PPC405_PCI_LOWER_MEM 0x80000000 /* hose_a->mem_space.start */ -#define PPC405_PCI_UPPER_MEM 0xBfffffff /* hose_a->mem_space.end */ -#define PPC405_PCI_LOWER_IO 0x00000000 /* hose_a->io_space.start */ -#define PPC405_PCI_UPPER_IO 0x0000ffff /* hose_a->io_space.end */ - -#define PPC405_ISA_IO_BASE PPC405_PCI_IO_BASE - -#define PPC4xx_PCI_IO_PADDR ((uint)PPC405_PCI_PHY_IO_BASE) -#define PPC4xx_PCI_IO_VADDR PPC4xx_PCI_IO_PADDR -#define PPC4xx_PCI_IO_SIZE ((uint)64*1024) -#define PPC4xx_PCI_CFG_PADDR ((uint)PPC405_PCI_CONFIG_ADDR) -#define PPC4xx_PCI_CFG_VADDR PPC4xx_PCI_CFG_PADDR -#define PPC4xx_PCI_CFG_SIZE ((uint)4*1024) -#define PPC4xx_PCI_LCFG_PADDR ((uint)0xef400000) -#define PPC4xx_PCI_LCFG_VADDR PPC4xx_PCI_LCFG_PADDR -#define PPC4xx_PCI_LCFG_SIZE ((uint)4*1024) -#define PPC4xx_ONB_IO_PADDR ((uint)0xef600000) -#define PPC4xx_ONB_IO_VADDR PPC4xx_ONB_IO_PADDR -#define PPC4xx_ONB_IO_SIZE ((uint)4*1024) - -#define PCI_CONFIG_ADDR_MASK 0x7F000000 -#define PCI_CONFIG_CYCLE_ENABLE 0x80000000 -#define PCI_BASE_ADDRESS_2 0x18 /* 32 bits [htype 0 only] */ -#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 -#define PCI_CONFIG_ADDR_MASK 0x7F000000 -#define PCI_CONFIG_CYCLE_ENABLE 0x80000000 -#define PCI_BASE_ADDRESS_MEM_CARD1 0x80000000 -#define PCI_BASE_ADDRESS_MEM_CARD2 0x90000000 -#define PPC405_UART0_INT 1 -#define PPC_405RAINIER2_IO_PAGE ((void*)0xe8001000) -#define PPC_405RAINIER1_IO_PAGE ((void*)0xe8002000) -#define PPC405_UART0_IO_BASE 0x300 /* mostly use (rainier_io_page+0x300) */ -#define RAINIER_IO_PAGE_INTERPOSER_PADDR 0xe8000000 -#define RAINIER_IO_PAGE_INTERPOSER_VADDR RAINIER_IO_PAGE_INTERPOSER_PADDR -#define RAINIER_IO_PAGE_PCI_PADDR 0xeec00000 -#define RAINIER_IO_PAGE_PCI_VADDR RAINIER_IO_PAGE_PCI_PADDR - -/* serial port defines */ -#define RS_TABLE_SIZE 1 - -#define UART0_INT 1 - -#define PCIL0_BASE 0xEF400000 -#define UART0_IO_BASE PPC_405RAINIER1_IO_PAGE + PPC405_UART0_IO_BASE - -#define UART_NUMS 1 -#define BD_EMAC_ADDR(e,i) bi_enetaddr[i] - -#define STD_UART_OP(num) \ - { 0, BASE_BAUD, 0, UART##num##_INT, \ - (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base: (u8 *)UART##num##_IO_BASE, \ - io_type: SERIAL_IO_MEM}, - -#if defined(CONFIG_UART0_TTYS0) -#define SERIAL_PORT_DFNS \ - STD_UART_OP(0) -#endif - -/* DCR defines */ -#define DCRN_CHCR_BASE 0x0B1 -#define DCRN_CHPSR_BASE 0x0B4 -#define DCRN_CPMSR_BASE 0x0B8 -#define DCRN_CPMFR_BASE 0x0BA - -#define PSR_PLL_FWD_MASK 0xC0000000 -#define PSR_PLL_FDBACK_MASK 0x30000000 -#define PSR_PLL_TUNING_MASK 0x0E000000 -#define PSR_PLB_CPU_MASK 0x01800000 -#define PSR_OPB_PLB_MASK 0x00600000 -#define PSR_PCI_PLB_MASK 0x00180000 -#define PSR_EB_PLB_MASK 0x00060000 -#define PSR_ROM_WIDTH_MASK 0x00018000 -#define PSR_ROM_LOC 0x00004000 -#define PSR_PCI_ASYNC_EN 0x00001000 -#define PSR_PCI_ARBIT_EN 0x00000400 - -#define IBM_CPM_IIC0 0x80000000 /* IIC interface */ -#define IBM_CPM_PCI 0x40000000 /* PCI bridge */ -#define IBM_CPM_CPU 0x20000000 /* processor core */ -#define IBM_CPM_DMA 0x10000000 /* DMA controller */ -#define IBM_CPM_BRG 0x08000000 /* PLB to OPB bridge */ -#define IBM_CPM_DCP 0x04000000 /* CodePack */ -#define IBM_CPM_EBC 0x02000000 /* ROM/SRAM peripheral controller */ -#define IBM_CPM_SDRAM0 0x01000000 /* SDRAM memory controller */ -#define IBM_CPM_PLB 0x00800000 /* PLB bus arbiter */ -#define IBM_CPM_GPIO0 0x00400000 /* General Purpose IO (??) */ -#define IBM_CPM_UART0 0x00200000 /* serial port 0 */ -#define IBM_CPM_UART1 0x00100000 /* serial port 1 */ -#define IBM_CPM_UIC 0x00080000 /* Universal Interrupt Controller */ -#define IBM_CPM_TMRCLK 0x00040000 /* CPU timers */ - -#define DFLT_IBM4xx_PM 0 - -#define DCRN_DMA0_BASE 0x100 -#define DCRN_DMA1_BASE 0x108 -#define DCRN_DMA2_BASE 0x110 -#define DCRN_DMA3_BASE 0x118 -#define DCRNCAP_DMA_SG 1 /* have DMA scatter/gather capability */ -#define DCRN_DMASR_BASE 0x120 -#define DCRN_EBC_BASE 0x012 -#define DCRN_DCP0_BASE 0x014 -#define DCRN_MAL_BASE 0x180 -#define DCRN_OCM0_BASE 0x018 -#define DCRN_PLB0_BASE 0x084 -#define DCRN_PLLMR_BASE 0x0B0 -#define DCRN_POB0_BASE 0x0A0 -#define DCRN_SDRAM0_BASE 0x010 -#define DCRN_UIC0_BASE 0x0C0 -#define UIC0 DCRN_UIC0_BASE - -#include - -#endif /* __ASM_IBMNP4GS_H__ */ -#endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmstb3.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmstb3.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmstb3.c 2004-02-03 19:43:02.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmstb3.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,24 +0,0 @@ -/* - * arch/ppc/platforms/4xx/ibmstb3.c - * - * Author: Armin Kuster - * - * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include "ibmstb3.h" -#include - -struct ocp_def core_ocp[] = { - {UART, UART0_IO_BASE, UART0_INT, IBM_CPM_UART0}, - {IIC, IIC0_BASE, IIC0_IRQ, IBM_CPM_IIC0}, - {IIC, IIC1_BASE, IIC1_IRQ, IBM_CPM_IIC1}, - {GPIO, GPIO0_BASE, OCP_IRQ_NA, IBM_CPM_GPIO0}, - {OPB, OPB0_BASE, OCP_IRQ_NA, OCP_CPM_NA}, - {OCP_NULL_TYPE, 0x0, OCP_IRQ_NA, OCP_CPM_NA}, - -}; diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmstb3.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmstb3.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/ibmstb3.h 2004-02-03 19:44:40.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/ibmstb3.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,231 +0,0 @@ -/* - * arch/ppc/platforms/4xx/ibmstb3.h - * - * Authors: Armin Kuster , Tom Rini - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_IBMSTBX_H__ -#define __ASM_IBMSTBX_H__ - -#include -#include - -/* ibm405.h at bottom of this file */ - -/* - * Memory map for the IBM "Redwood-4" STB03xxx evaluation board. - * - * The STB03xxx internal i/o addresses don't work for us 1:1, - * so we need to map them at a well know virtual address. - * - * 4000 000x uart1 -> 0xe000 000x - * 4001 00xx ppu - * 4002 00xx smart card - * 4003 000x iic - * 4004 000x uart0 - * 4005 0xxx timer - * 4006 00xx gpio - * 4007 00xx smart card - * 400b 000x iic - * 400c 000x scp - * 400d 000x modem - */ - -#define STB03xxx_IO_BASE ((uint)0xe0000000) -#define PPC4xx_ONB_IO_PADDR ((uint)0x40000000) -#define PPC4xx_ONB_IO_VADDR STB03xxx_IO_BASE -#define PPC4xx_ONB_IO_SIZE ((uint)14*64*1024) - -/* Since we're into address mapping hacks, at least try to hide - * it under a macro..... - */ -#define STB03xxx_MAP_IO_ADDR(a) (((uint)(a) & 0x000fffff) + PPC4xx_ONB_IO_VADDR) - -#define RS_TABLE_SIZE 1 -#define UART0_INT 20 -#ifdef __BOOTER__ -#define UART0_IO_BASE 0x40040000 -#else -#define UART0_IO_BASE 0xe0040000 -#endif - - /* UART 0 is duped here so when the SICC is the default console - * then ttys1 is configured properly - armin - */ - -#define UART1_INT 20 -#ifdef __BOOTER__ -#define UART1_IO_BASE 0x40040000 -#else -#define UART1_IO_BASE 0xe0040000 -#endif - -/* need to make this work in scheme - armin */ - -#define SICC0_INTRX 21 -#define SICC0_INTTX 22 -#define SICC0_IO_BASE ((uint* )0x40000000) - -#define IDE0_BASE 0xf2100000 -#define REDWOOD_IDE_CTRL 0xf4100000 - -#define IIC0_BASE 0x40030000 -#define IIC1_BASE 0x400b0000 -#define OPB0_BASE 0x40010000 -#define GPIO0_BASE 0x40060000 -#define IIC0_IRQ 9 -#define IIC1_IRQ 10 -#define IIC_OWN 0x55 -#define IIC_CLOCK 50 -#define IDE0_IRQ 25 - -#define BD_EMAC_ADDR(e,i) bi_enetaddr[i] - -#define STD_UART_OP(num) \ - { 0, BASE_BAUD, 0, UART##num##_INT, \ - (ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST), \ - iomem_base: (u8 *)UART##num##_IO_BASE, \ - io_type: SERIAL_IO_MEM}, - -#if defined(CONFIG_UART0_TTYS0) -#define SERIAL_DEBUG_IO_BASE UART0_IO_BASE -#define SERIAL_PORT_DFNS \ - STD_UART_OP(0) -#endif - -#if defined(CONFIG_UART0_TTYS1) -#define SERIAL_DEBUG_IO_BASE UART1_IO_BASE -#define SERIAL_PORT_DFNS \ - STD_UART_OP(1) -#endif - -/* ------------------------------------------------------------------------- */ - -#define DCRN_DCRX_BASE 0x020 -#define DCRN_CIC_BASE 0x030 -#define DCRN_UIC0_BASE 0x040 -#define DCRN_PLB0_BASE 0x054 -#define DCRN_PLB1_BASE 0x064 -#define DCRN_EBIMC_BASE 0x070 -#define DCRN_POB0_BASE 0x0B0 - -#define DCRN_BE_BASE 0x090 -#define DCRN_DMA0_BASE 0x0C0 -#define DCRN_DMA1_BASE 0x0C8 -#define DCRN_DMA2_BASE 0x0D0 -#define DCRN_DMA3_BASE 0x0D8 -#define DCRNCAP_DMA_CC 1 /* have DMA chained count capability */ -#define DCRN_DMASR_BASE 0x0E0 - -#define DCRN_CPMFR_BASE 0x102 -#define DCRN_SCCR_BASE 0x120 -#define UIC0 DCRN_UIC0_BASE - -#define IBM_CPM_IIC0 0x80000000 /* IIC 0 interface */ -#define IBM_CPM_I1284 0x40000000 /* IEEE-1284 */ -#define IBM_CPM_IIC1 0x20000000 /* IIC 1 interface */ -#define IBM_CPM_CPU 0x10000000 /* PPC405B3 clock control */ -#define IBM_CPM_AUD 0x08000000 /* Audio Decoder */ -#define IBM_CPM_EBIU 0x04000000 /* External Bus Interface Unit */ -#define IBM_CPM_SDRAM1 0x02000000 /* SDRAM 1 memory controller */ -#define IBM_CPM_DMA 0x01000000 /* DMA controller */ -#define IBM_CPM_UART1 0x00100000 /* Serial 1 / Infrared */ -#define IBM_CPM_UART0 0x00080000 /* Serial 0 / 16550 */ -#define IBM_CPM_DCRX 0x00040000 /* DCR Extension */ -#define IBM_CPM_SC0 0x00020000 /* Smart Card 0 */ -#define IBM_CPM_SC1 0x00008000 /* Smart Card 1 */ -#define IBM_CPM_SDRAM0 0x00004000 /* SDRAM 0 memory controller */ -#define IBM_CPM_XPT54 0x00002000 /* Transport - 54 Mhz */ -#define IBM_CPM_CBS 0x00001000 /* Cross Bar Switch */ -#define IBM_CPM_GPT 0x00000800 /* GPTPWM */ -#define IBM_CPM_GPIO0 0x00000400 /* General Purpose IO 0 */ -#define IBM_CPM_DENC 0x00000200 /* Digital video Encoder */ -#define IBM_CPM_TMRCLK 0x00000100 /* CPU timers */ -#define IBM_CPM_XPT27 0x00000080 /* Transport - 27 Mhz */ -#define IBM_CPM_UIC 0x00000040 /* Universal Interrupt Controller */ -#define IBM_CPM_MSI 0x00000010 /* Modem Serial Interface (SSP) */ -#define IBM_CPM_UART2 0x00000008 /* Serial Control Port */ -#define IBM_CPM_DSCR 0x00000004 /* Descrambler */ -#define IBM_CPM_VID2 0x00000002 /* Video Decoder clock domain 2 */ - -#define DFLT_IBM4xx_PM ~(IBM_CPM_CPU | IBM_CPM_EBIU | IBM_CPM_SDRAM1 \ - | IBM_CPM_DMA | IBM_CPM_CBS | IBM_CPM_SDRAM0 \ - | IBM_CPM_XPT54 | IBM_CPM_TMRCLK | IBM_CPM_XPT27 \ - | IBM_CPM_UIC) - -#ifdef DCRN_CIC_BASE -#define DCRN_CICCR (DCRN_CIC_BASE + 0x0) /* CIC Control Register */ -#define DCRN_DMAS1 (DCRN_CIC_BASE + 0x1) /* DMA Select1 Register */ -#define DCRN_DMAS2 (DCRN_CIC_BASE + 0x2) /* DMA Select2 Register */ -#define DCRN_CICVCR (DCRN_CIC_BASE + 0x3) /* CIC Video COntro Register */ -#define DCRN_CICSEL3 (DCRN_CIC_BASE + 0x5) /* CIC Select 3 Register */ -#define DCRN_SGPO (DCRN_CIC_BASE + 0x6) /* CIC GPIO Output Register */ -#define DCRN_SGPOD (DCRN_CIC_BASE + 0x7) /* CIC GPIO OD Register */ -#define DCRN_SGPTC (DCRN_CIC_BASE + 0x8) /* CIC GPIO Tristate Ctrl Reg */ -#define DCRN_SGPI (DCRN_CIC_BASE + 0x9) /* CIC GPIO Input Reg */ -#endif - -#ifdef DCRN_DCRX_BASE -#define DCRN_DCRXICR (DCRN_DCRX_BASE + 0x0) /* Internal Control Register */ -#define DCRN_DCRXISR (DCRN_DCRX_BASE + 0x1) /* Internal Status Register */ -#define DCRN_DCRXECR (DCRN_DCRX_BASE + 0x2) /* External Control Register */ -#define DCRN_DCRXESR (DCRN_DCRX_BASE + 0x3) /* External Status Register */ -#define DCRN_DCRXTAR (DCRN_DCRX_BASE + 0x4) /* Target Address Register */ -#define DCRN_DCRXTDR (DCRN_DCRX_BASE + 0x5) /* Target Data Register */ -#define DCRN_DCRXIGR (DCRN_DCRX_BASE + 0x6) /* Interrupt Generation Register */ -#define DCRN_DCRXBCR (DCRN_DCRX_BASE + 0x7) /* Line Buffer Control Register */ -#endif - -#ifdef DCRN_EBC_BASE -#define DCRN_EBCCFGADR (DCRN_EBC_BASE + 0x0) /* Peripheral Controller Address */ -#define DCRN_EBCCFGDATA (DCRN_EBC_BASE + 0x1) /* Peripheral Controller Data */ -#endif - -#ifdef DCRN_EBIMC_BASE -#define DCRN_BRCRH0 (DCRN_EBIMC_BASE + 0x0) /* Bus Region Config High 0 */ -#define DCRN_BRCRH1 (DCRN_EBIMC_BASE + 0x1) /* Bus Region Config High 1 */ -#define DCRN_BRCRH2 (DCRN_EBIMC_BASE + 0x2) /* Bus Region Config High 2 */ -#define DCRN_BRCRH3 (DCRN_EBIMC_BASE + 0x3) /* Bus Region Config High 3 */ -#define DCRN_BRCRH4 (DCRN_EBIMC_BASE + 0x4) /* Bus Region Config High 4 */ -#define DCRN_BRCRH5 (DCRN_EBIMC_BASE + 0x5) /* Bus Region Config High 5 */ -#define DCRN_BRCRH6 (DCRN_EBIMC_BASE + 0x6) /* Bus Region Config High 6 */ -#define DCRN_BRCRH7 (DCRN_EBIMC_BASE + 0x7) /* Bus Region Config High 7 */ -#define DCRN_BRCR0 (DCRN_EBIMC_BASE + 0x10) /* BRC 0 */ -#define DCRN_BRCR1 (DCRN_EBIMC_BASE + 0x11) /* BRC 1 */ -#define DCRN_BRCR2 (DCRN_EBIMC_BASE + 0x12) /* BRC 2 */ -#define DCRN_BRCR3 (DCRN_EBIMC_BASE + 0x13) /* BRC 3 */ -#define DCRN_BRCR4 (DCRN_EBIMC_BASE + 0x14) /* BRC 4 */ -#define DCRN_BRCR5 (DCRN_EBIMC_BASE + 0x15) /* BRC 5 */ -#define DCRN_BRCR6 (DCRN_EBIMC_BASE + 0x16) /* BRC 6 */ -#define DCRN_BRCR7 (DCRN_EBIMC_BASE + 0x17) /* BRC 7 */ -#define DCRN_BEAR0 (DCRN_EBIMC_BASE + 0x20) /* Bus Error Address Register */ -#define DCRN_BESR0 (DCRN_EBIMC_BASE + 0x21) /* Bus Error Status Register */ -#define DCRN_BIUCR (DCRN_EBIMC_BASE + 0x2A) /* Bus Interfac Unit Ctrl Reg */ -#endif - -#ifdef DCRN_SCCR_BASE -#define DCRN_SCCR (DCRN_SCCR_BASE + 0x0) -#endif - -#ifdef DCRN_SDRAM0_BASE -#define DCRN_SDRAM0_CFGADDR (DCRN_SDRAM0_BASE + 0x0) /* Memory Controller Address */ -#define DCRN_SDRAM0_CFGDATA (DCRN_SDRAM0_BASE + 0x1) /* Memory Controller Data */ -#endif - -#ifdef DCRN_OCM0_BASE -#define DCRN_OCMISARC (DCRN_OCM0_BASE + 0x0) /* OCM Instr Side Addr Range Compare */ -#define DCRN_OCMISCR (DCRN_OCM0_BASE + 0x1) /* OCM Instr Side Control */ -#define DCRN_OCMDSARC (DCRN_OCM0_BASE + 0x2) /* OCM Data Side Addr Range Compare */ -#define DCRN_OCMDSCR (DCRN_OCM0_BASE + 0x3) /* OCM Data Side Control */ -#endif - -#include - -#endif /* __ASM_IBMSTBX_H__ */ -#endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/oak.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/oak.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/oak.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/oak.c 2004-02-14 19:30:59.000000000 -0800 @@ -0,0 +1,281 @@ +/* + * + * Copyright (c) 1999-2000 Grant Erickson + * + * Module name: oak.c + * + * Description: + * Architecture- / platform-specific boot-time initialization code for + * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original + * code by Gary Thomas, Cort Dougan , and Dan Malek + * . + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "oak.h" + +/* Function Prototypes */ + +extern void abort(void); + +/* Global Variables */ + +unsigned char __res[sizeof(bd_t)]; + + +/* + * void __init oak_init() + * + * Description: + * This routine... + * + * Input(s): + * r3 - Optional pointer to a board information structure. + * r4 - Optional pointer to the physical starting address of the init RAM + * disk. + * r5 - Optional pointer to the physical ending address of the init RAM + * disk. + * r6 - Optional pointer to the physical starting address of any kernel + * command-line parameters. + * r7 - Optional pointer to the physical ending address of any kernel + * command-line parameters. + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ +void __init +platform_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + parse_bootinfo(find_bootinfo()); + + /* + * If we were passed in a board information, copy it into the + * residual data area. + */ + if (r3) { + memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); + } + +#if defined(CONFIG_BLK_DEV_INITRD) + /* + * If the init RAM disk has been configured in, and there's a valid + * starting address for it, set it up. + */ + if (r4) { + initrd_start = r4 + KERNELBASE; + initrd_end = r5 + KERNELBASE; + } +#endif /* CONFIG_BLK_DEV_INITRD */ + + /* Copy the kernel command line arguments to a safe place. */ + + if (r6) { + *(char *)(r7 + KERNELBASE) = 0; + strcpy(cmd_line, (char *)(r6 + KERNELBASE)); + } + + /* Initialize machine-dependency vectors */ + + ppc_md.setup_arch = oak_setup_arch; + ppc_md.show_percpuinfo = oak_show_percpuinfo; + ppc_md.irq_canonicalize = NULL; + ppc_md.init_IRQ = oak_init_IRQ; + ppc_md.get_irq = oak_get_irq; + ppc_md.init = NULL; + + ppc_md.restart = oak_restart; + ppc_md.power_off = oak_power_off; + ppc_md.halt = oak_halt; + + ppc_md.time_init = oak_time_init; + ppc_md.set_rtc_time = oak_set_rtc_time; + ppc_md.get_rtc_time = oak_get_rtc_time; + ppc_md.calibrate_decr = oak_calibrate_decr; +} + +/* + * Document me. + */ +void __init +oak_setup_arch(void) +{ + /* XXX - Implement me */ +} + +/* + * int oak_show_percpuinfo() + * + * Description: + * This routine pretty-prints the platform's internal CPU and bus clock + * frequencies into the buffer for usage in /proc/cpuinfo. + * + * Input(s): + * *buffer - Buffer into which CPU and bus clock frequencies are to be + * printed. + * + * Output(s): + * *buffer - Buffer with the CPU and bus clock frequencies. + * + * Returns: + * The number of bytes copied into 'buffer' if OK, otherwise zero or less + * on error. + */ +int +oak_show_percpuinfo(struct seq_file *m, int i) +{ + bd_t *bp = (bd_t *)__res; + + seq_printf(m, "clock\t\t: %dMHz\n" + "bus clock\t\t: %dMHz\n", + bp->bi_intfreq / 1000000, + bp->bi_busfreq / 1000000); + + return 0; +} + +/* + * Document me. + */ +void __init +oak_init_IRQ(void) +{ + int i; + + ppc4xx_pic_init(); + + for (i = 0; i < NR_IRQS; i++) { + irq_desc[i].handler = ppc4xx_pic; + } + + return; +} + +/* + * Document me. + */ +int +oak_get_irq(struct pt_regs *regs) +{ + return (ppc4xx_pic_get_irq(regs)); +} + +/* + * Document me. + */ +void +oak_restart(char *cmd) +{ + abort(); +} + +/* + * Document me. + */ +void +oak_power_off(void) +{ + oak_restart(NULL); +} + +/* + * Document me. + */ +void +oak_halt(void) +{ + oak_restart(NULL); +} + +/* + * Document me. + */ +long __init +oak_time_init(void) +{ + /* XXX - Implement me */ + return 0; +} + +/* + * Document me. + */ +int __init +oak_set_rtc_time(unsigned long time) +{ + /* XXX - Implement me */ + + return (0); +} + +/* + * Document me. + */ +unsigned long __init +oak_get_rtc_time(void) +{ + /* XXX - Implement me */ + + return (0); +} + +/* + * void __init oak_calibrate_decr() + * + * Description: + * This routine retrieves the internal processor frequency from the board + * information structure, sets up the kernel timer decrementer based on + * that value, enables the 403 programmable interval timer (PIT) and sets + * it up for auto-reload. + * + * Input(s): + * N/A + * + * Output(s): + * N/A + * + * Returns: + * N/A + * + */ +void __init +oak_calibrate_decr(void) +{ + unsigned int freq; + bd_t *bip = (bd_t *)__res; + + freq = bip->bi_intfreq; + + decrementer_count = freq / HZ; + count_period_num = 1; + count_period_den = freq; + + /* Enable the PIT and set auto-reload of its value */ + + mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); + + /* Clear any pending timer interrupts */ + + mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); +} diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/oak.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/oak.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/oak.h 2004-02-03 19:44:18.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/oak.h 2004-02-14 19:30:59.000000000 -0800 @@ -60,6 +60,31 @@ unsigned int bi_busfreq; /* Bus speed, in Hz */ } bd_t; +#ifdef __cplusplus +extern "C" { +#endif + +extern void oak_init(unsigned long r3, + unsigned long ird_start, + unsigned long ird_end, + unsigned long cline_start, + unsigned long cline_end); +extern void oak_setup_arch(void); +extern int oak_setup_residual(char *buffer); +extern void oak_init_IRQ(void); +extern int oak_get_irq(struct pt_regs *regs); +extern void oak_restart(char *cmd); +extern void oak_power_off(void); +extern void oak_halt(void); +extern void oak_time_init(void); +extern int oak_set_rtc_time(unsigned long now); +extern unsigned long oak_get_rtc_time(void); +extern void oak_calibrate_decr(void); + +#ifdef __cplusplus +} +#endif + /* Some 4xx parts use a different timebase frequency from the internal clock. */ #define bi_tbfreq bi_intfreq diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/oak_setup.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/oak_setup.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/oak_setup.c 2004-02-03 19:44:18.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/oak_setup.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,281 +0,0 @@ -/* - * - * Copyright (c) 1999-2000 Grant Erickson - * - * Module name: oak_setup.c - * - * Description: - * Architecture- / platform-specific boot-time initialization code for - * the IBM PowerPC 403GCX "Oak" evaluation board. Adapted from original - * code by Gary Thomas, Cort Dougan , and Dan Malek - * . - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "oak_setup.h" - -/* Function Prototypes */ - -extern void abort(void); - -/* Global Variables */ - -unsigned char __res[sizeof(bd_t)]; - - -/* - * void __init oak_init() - * - * Description: - * This routine... - * - * Input(s): - * r3 - Optional pointer to a board information structure. - * r4 - Optional pointer to the physical starting address of the init RAM - * disk. - * r5 - Optional pointer to the physical ending address of the init RAM - * disk. - * r6 - Optional pointer to the physical starting address of any kernel - * command-line parameters. - * r7 - Optional pointer to the physical ending address of any kernel - * command-line parameters. - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - parse_bootinfo(find_bootinfo()); - - /* - * If we were passed in a board information, copy it into the - * residual data area. - */ - if (r3) { - memcpy((void *)__res, (void *)(r3 + KERNELBASE), sizeof(bd_t)); - } - -#if defined(CONFIG_BLK_DEV_INITRD) - /* - * If the init RAM disk has been configured in, and there's a valid - * starting address for it, set it up. - */ - if (r4) { - initrd_start = r4 + KERNELBASE; - initrd_end = r5 + KERNELBASE; - } -#endif /* CONFIG_BLK_DEV_INITRD */ - - /* Copy the kernel command line arguments to a safe place. */ - - if (r6) { - *(char *)(r7 + KERNELBASE) = 0; - strcpy(cmd_line, (char *)(r6 + KERNELBASE)); - } - - /* Initialize machine-dependency vectors */ - - ppc_md.setup_arch = oak_setup_arch; - ppc_md.show_percpuinfo = oak_show_percpuinfo; - ppc_md.irq_canonicalize = NULL; - ppc_md.init_IRQ = oak_init_IRQ; - ppc_md.get_irq = oak_get_irq; - ppc_md.init = NULL; - - ppc_md.restart = oak_restart; - ppc_md.power_off = oak_power_off; - ppc_md.halt = oak_halt; - - ppc_md.time_init = oak_time_init; - ppc_md.set_rtc_time = oak_set_rtc_time; - ppc_md.get_rtc_time = oak_get_rtc_time; - ppc_md.calibrate_decr = oak_calibrate_decr; -} - -/* - * Document me. - */ -void __init -oak_setup_arch(void) -{ - /* XXX - Implement me */ -} - -/* - * int oak_show_percpuinfo() - * - * Description: - * This routine pretty-prints the platform's internal CPU and bus clock - * frequencies into the buffer for usage in /proc/cpuinfo. - * - * Input(s): - * *buffer - Buffer into which CPU and bus clock frequencies are to be - * printed. - * - * Output(s): - * *buffer - Buffer with the CPU and bus clock frequencies. - * - * Returns: - * The number of bytes copied into 'buffer' if OK, otherwise zero or less - * on error. - */ -int -oak_show_percpuinfo(struct seq_file *m, int i) -{ - bd_t *bp = (bd_t *)__res; - - seq_printf(m, "clock\t\t: %dMHz\n" - "bus clock\t\t: %dMHz\n", - bp->bi_intfreq / 1000000, - bp->bi_busfreq / 1000000); - - return 0; -} - -/* - * Document me. - */ -void __init -oak_init_IRQ(void) -{ - int i; - - ppc4xx_pic_init(); - - for (i = 0; i < NR_IRQS; i++) { - irq_desc[i].handler = ppc4xx_pic; - } - - return; -} - -/* - * Document me. - */ -int -oak_get_irq(struct pt_regs *regs) -{ - return (ppc4xx_pic_get_irq(regs)); -} - -/* - * Document me. - */ -void -oak_restart(char *cmd) -{ - abort(); -} - -/* - * Document me. - */ -void -oak_power_off(void) -{ - oak_restart(NULL); -} - -/* - * Document me. - */ -void -oak_halt(void) -{ - oak_restart(NULL); -} - -/* - * Document me. - */ -long __init -oak_time_init(void) -{ - /* XXX - Implement me */ - return 0; -} - -/* - * Document me. - */ -int __init -oak_set_rtc_time(unsigned long time) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * Document me. - */ -unsigned long __init -oak_get_rtc_time(void) -{ - /* XXX - Implement me */ - - return (0); -} - -/* - * void __init oak_calibrate_decr() - * - * Description: - * This routine retrieves the internal processor frequency from the board - * information structure, sets up the kernel timer decrementer based on - * that value, enables the 403 programmable interval timer (PIT) and sets - * it up for auto-reload. - * - * Input(s): - * N/A - * - * Output(s): - * N/A - * - * Returns: - * N/A - * - */ -void __init -oak_calibrate_decr(void) -{ - unsigned int freq; - bd_t *bip = (bd_t *)__res; - - freq = bip->bi_intfreq; - - decrementer_count = freq / HZ; - count_period_num = 1; - count_period_den = freq; - - /* Enable the PIT and set auto-reload of its value */ - - mtspr(SPRN_TCR, TCR_PIE | TCR_ARE); - - /* Clear any pending timer interrupts */ - - mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_PIS | TSR_FIS); -} diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/redwood.c linux-2.6.3-rc3/arch/ppc/platforms/4xx/redwood.c --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/redwood.c 2004-02-03 19:44:21.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/redwood.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,74 +0,0 @@ -/* - * arch/ppc/platforms/4xx/redwood.c - * - * Author: Frank Rowand , or source@mvista.com - * - * 2000-2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#include -#include -#include -#include -#include -#include - -void __init -redwood_setup_arch(void) -{ - ppc4xx_setup_arch(); - -#ifdef CONFIG_IDE - void *xilinx, *xilinx_1, *xilinx_2; - unsigned short reg5; - - xilinx = ioremap(IDE_XLINUX_MUX_BASE, 0x10); - - /* init xilinx control registers - enable ide mux, clear reset bit */ - if (!xilinx) { - printk(KERN_CRIT - "redwood4_setup_arch() xilinx ioremap failed\n"); - return; - } - xilinx_1 = xilinx; - xilinx_2 = xilinx + 0xe; - - reg5 = readw(xilinx_1); - writeb(reg5 |= ~(0x8001), xilinx_1); - writeb(0, xilinx_2); - - udelay(10 * 1000); - - writeb(reg5 & 0x8001, xilinx_1); - writeb(0, xilinx_2); - - /* add RE & OEN to value set by boot rom */ - mtdcr(DCRN_BRCR3, 0x407cfffe); - -#endif - -} - -void __init -redwood_map_io(void) -{ - int i; - - ppc4xx_map_io(); - io_block_mapping(OAKNET_IO_VADDR, - OAKNET_IO_PADDR, OAKNET_IO_SIZE, _PAGE_IO); - -} - -void __init -platform_init(unsigned long r3, unsigned long r4, unsigned long r5, - unsigned long r6, unsigned long r7) -{ - ppc4xx_init(r3, r4, r5, r6, r7); - - ppc_md.setup_arch = redwood_setup_arch; - ppc_md.setup_io_mappings = redwood_map_io; -} diff -urN linux-2.6.3-rc2/arch/ppc/platforms/4xx/redwood.h linux-2.6.3-rc3/arch/ppc/platforms/4xx/redwood.h --- linux-2.6.3-rc2/arch/ppc/platforms/4xx/redwood.h 2004-02-03 19:45:13.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/4xx/redwood.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,57 +0,0 @@ -/* - * arch/ppc/platforms/4xx/redwood.h - * - * Macros, definitions, and data structures specific to the IBM PowerPC - * STB03xxx "Redwood" evaluation board. - * - * Author: Frank Rowand , or source@mvista.com - * - * 2001 (c) MontaVista, Software, Inc. This file is licensed under - * the terms of the GNU General Public License version 2. This program - * is licensed "as is" without any warranty of any kind, whether express - * or implied. - */ - -#ifdef __KERNEL__ -#ifndef __ASM_REDWOOD_H__ -#define __ASM_REDWOOD_H__ - -/* Redwoods have an STB03xxx or STB04xxx core */ -#include - -#ifndef __ASSEMBLY__ -typedef struct board_info { - unsigned char bi_s_version[4]; /* Version of this structure */ - unsigned char bi_r_version[30]; /* Version of the IBM ROM */ - unsigned int bi_memsize; /* DRAM installed, in bytes */ - unsigned int bi_dummy; /* field shouldn't exist */ - unsigned char bi_enetaddr[6]; /* Ethernet MAC address */ - unsigned int bi_intfreq; /* Processor speed, in Hz */ - unsigned int bi_busfreq; /* Bus speed, in Hz */ -} bd_t; -#define bi_tbfreq bi_intfreq - -#endif /* !__ASSEMBLY__ */ - -#define bi_tbfreq bi_intfreq -#define OAKNET_IO_PADDR ((uint)0xf2000000) -#define OAKNET_IO_VADDR OAKNET_IO_PADDR -#define OAKNET_IO_BASE OAKNET_IO_VADDR - -/* ftr revisit- io size was 0xffff in old-line, is 0x40 in oak.h */ -#define OAKNET_IO_SIZE 0xffff -#define OAKNET_INT 26 /* EXTINT1 */ - -#define IDE_XLINUX_MUX_BASE 0xf2040000 -#define IDE_DMA_ADDR 0xfce00000 - -#define _IO_BASE 0 -#define _ISA_MEM_BASE 0 -#define PCI_DRAM_OFFSET 0 - -#define BASE_BAUD (378000000 / 18 / 16) - -#define PPC4xx_MACHINE_NAME "IBM Redwood" - -#endif /* __ASM_REDWOOD_H__ */ -#endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/Makefile linux-2.6.3-rc3/arch/ppc/platforms/Makefile --- linux-2.6.3-rc2/arch/ppc/platforms/Makefile 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/Makefile 2004-02-14 19:30:59.000000000 -0800 @@ -20,7 +20,7 @@ pmac_feature.o pmac_pci.o pmac_sleep.o \ pmac_low_i2c.o obj-$(CONFIG_PPC_CHRP) += chrp_setup.o chrp_time.o chrp_pci.o -obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_time.o prep_setup.o +obj-$(CONFIG_PPC_PREP) += prep_pci.o prep_setup.o ifeq ($(CONFIG_PPC_PMAC),y) obj-$(CONFIG_NVRAM) += pmac_nvram.o obj-$(CONFIG_CPU_FREQ_PMAC) += pmac_cpufreq.o diff -urN linux-2.6.3-rc2/arch/ppc/platforms/pmac_feature.c linux-2.6.3-rc3/arch/ppc/platforms/pmac_feature.c --- linux-2.6.3-rc2/arch/ppc/platforms/pmac_feature.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/pmac_feature.c 2004-02-14 19:30:59.000000000 -0800 @@ -2239,7 +2239,7 @@ break; #else /* CONFIG_POWER4 */ case macio_keylargo2: - pmac_mb.model_id = PMAC_TYPE_POWERMAC_G5; + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; pmac_mb.model_name = "Unknown G5"; pmac_mb.features = g5_features; break; diff -urN linux-2.6.3-rc2/arch/ppc/platforms/prep_setup.c linux-2.6.3-rc3/arch/ppc/platforms/prep_setup.c --- linux-2.6.3-rc2/arch/ppc/platforms/prep_setup.c 2004-02-03 19:44:29.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/prep_setup.c 2004-02-14 19:30:59.000000000 -0800 @@ -58,16 +58,14 @@ #include #include #include +#include + +TODC_ALLOC(); unsigned char ucSystemType; unsigned char ucBoardRev; unsigned char ucBoardRevMaj, ucBoardRevMin; -extern unsigned long mc146818_get_rtc_time(void); -extern int mc146818_set_rtc_time(unsigned long nowtime); -extern unsigned long mk48t59_get_rtc_time(void); -extern int mk48t59_set_rtc_time(unsigned long nowtime); - extern unsigned char prep_nvram_read_val(int addr); extern void prep_nvram_write_val(int addr, unsigned char val); @@ -814,12 +812,12 @@ } /* - * Determine the decrementer frequency from the residual data - * This allows for a faster boot as we do not need to calibrate the - * decrementer against another clock. This is important for embedded systems. + * First, see if we can get this information from the residual data. + * This is important on some IBM PReP systems. If we cannot, we let the + * TODC code handle doing this. */ -static int __init -prep_res_calibrate_decr(void) +static void __init +prep_calibrate_decr(void) { #ifdef CONFIG_PREP_RESIDUAL unsigned long freq, divisor = 4; @@ -831,149 +829,9 @@ (freq/divisor)%1000000); tb_to_us = mulhwu_scale_factor(freq/divisor, 1000000); tb_ticks_per_jiffy = freq / HZ / divisor; - return 0; } else #endif - return 1; -} - -/* - * Uses the on-board timer to calibrate the on-chip decrementer register - * for prep systems. On the pmac the OF tells us what the frequency is - * but on prep we have to figure it out. - * -- Cort - */ -/* Done with 3 interrupts: the first one primes the cache and the - * 2 following ones measure the interval. The precision of the method - * is still doubtful due to the short interval sampled. - */ -static volatile int calibrate_steps __initdata = 3; -static unsigned tbstamp __initdata = 0; - -static irqreturn_t __init -prep_calibrate_decr_handler(int irq, void *dev, struct pt_regs *regs) -{ - unsigned long t, freq; - int step=--calibrate_steps; - - t = get_tbl(); - if (step > 0) { - tbstamp = t; - } else { - freq = (t - tbstamp)*HZ; - printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", - freq/1000000, freq%1000000); - tb_ticks_per_jiffy = freq / HZ; - tb_to_us = mulhwu_scale_factor(freq, 1000000); - } - return IRQ_HANDLED; -} - -static void __init -prep_calibrate_decr(void) -{ - int res; - - /* Try and get this from the residual data. */ - res = prep_res_calibrate_decr(); - - /* If we didn't get it from the residual data, try this. */ - if ( res ) { -#define TIMER0_COUNT 0x40 -#define TIMER_CONTROL 0x43 - /* set timer to periodic mode */ - outb_p(0x34,TIMER_CONTROL);/* binary, mode 2, LSB/MSB, ch 0 */ - /* set the clock to ~100 Hz */ - outb_p(LATCH & 0xff , TIMER0_COUNT); /* LSB */ - outb(LATCH >> 8 , TIMER0_COUNT); /* MSB */ - - if (request_irq(0, prep_calibrate_decr_handler, 0, "timer", NULL) != 0) - panic("Could not allocate timer IRQ!"); - local_irq_enable(); - /* wait for calibrate */ - while ( calibrate_steps ) - ; - local_irq_disable(); - free_irq( 0, NULL); - } -} - -static long __init -mk48t59_init(void) { - unsigned char tmp; - - tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); - if (tmp & MK48T59_RTC_CB_STOP) { - printk("Warning: RTC was stopped, date will be wrong.\n"); - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLB, - tmp & ~MK48T59_RTC_CB_STOP); - /* Low frequency crystal oscillators may take a very long - * time to startup and stabilize. For now just ignore the - * the issue, but attempting to calibrate the decrementer - * from the RTC just after this wakeup is likely to be very - * inaccurate. Firmware should not allow to load - * the OS with the clock stopped anyway... - */ - } - /* Ensure that the clock registers are updated */ - tmp = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - tmp &= ~(MK48T59_RTC_CA_READ | MK48T59_RTC_CA_WRITE); - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, tmp); - return 0; -} - -/* We use the NVRAM RTC to time a second to calibrate the decrementer, - * the RTC registers have just been set up in the right state by the - * preceding routine. - */ -static void __init -mk48t59_calibrate_decr(void) -{ - unsigned long freq; - unsigned long t1; - unsigned char save_control; - long i; - unsigned char sec; - - - /* Make sure the time is not stopped. */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLB); - - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control & (~MK48T59_RTC_CB_STOP))); - - /* Now make sure the read bit is off so the value will change. */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - save_control &= ~MK48T59_RTC_CA_READ; - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - - /* Read the seconds value to see when it changes. */ - sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - /* Actually this is bad for precision, we should have a loop in - * which we only read the seconds counter. nvram_read_val writes - * the address bytes on every call and this takes a lot of time. - * Perhaps an nvram_wait_change method returning a time - * stamp with a loop count as parameter would be the solution. - */ - for (i = 0 ; i < 1000000 ; i++) { /* may take up to 1 second... */ - t1 = get_tbl(); - if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) { - break; - } - } - - sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - for (i = 0 ; i < 1000000 ; i++) { /* Should take up 1 second... */ - freq = get_tbl()-t1; - if (ppc_md.nvram_read_val(MK48T59_RTC_SECONDS) != sec) - break; - } - - printk("time_init: decrementer frequency = %lu.%.6lu MHz\n", - freq/1000000, freq%1000000); - tb_ticks_per_jiffy = freq / HZ; - tb_to_us = mulhwu_scale_factor(freq, 1000000); + todc_calibrate_decr(); } static unsigned int __prep @@ -1163,18 +1021,19 @@ ppc_md.nvram_read_val = prep_nvram_read_val; ppc_md.nvram_write_val = prep_nvram_write_val; - ppc_md.time_init = NULL; + ppc_md.time_init = todc_time_init; if (_prep_type == _PREP_IBM) { - ppc_md.set_rtc_time = mc146818_set_rtc_time; - ppc_md.get_rtc_time = mc146818_get_rtc_time; - ppc_md.calibrate_decr = prep_calibrate_decr; + TODC_INIT(TODC_TYPE_MC146818, PREP_NVRAM_AS0, PREP_NVRAM_AS1, + PREP_NVRAM_DATA, 8); } else { - ppc_md.set_rtc_time = mk48t59_set_rtc_time; - ppc_md.get_rtc_time = mk48t59_get_rtc_time; - ppc_md.calibrate_decr = mk48t59_calibrate_decr; - ppc_md.time_init = mk48t59_init; + TODC_INIT(TODC_TYPE_MK48T59, PREP_NVRAM_AS0, PREP_NVRAM_AS1, + PREP_NVRAM_DATA, 8); } + ppc_md.calibrate_decr = prep_calibrate_decr; + ppc_md.set_rtc_time = todc_set_rtc_time; + ppc_md.get_rtc_time = todc_get_rtc_time; + ppc_md.setup_io_mappings = prep_map_io; #if defined(CONFIG_BLK_DEV_IDE) || defined(CONFIG_BLK_DEV_IDE_MODULE) diff -urN linux-2.6.3-rc2/arch/ppc/platforms/prep_time.c linux-2.6.3-rc3/arch/ppc/platforms/prep_time.c --- linux-2.6.3-rc2/arch/ppc/platforms/prep_time.c 2004-02-03 19:43:47.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/prep_time.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,225 +0,0 @@ -/* - * arch/ppc/platforms/prep_time.c - * - * Copyright (C) 1991, 1992, 1995 Linus Torvalds - * - * Adapted for PowerPC (PReP) by Gary Thomas - * Modified by Cort Dougan (cort@cs.nmt.edu). - * Copied and modified from arch/i386/kernel/time.c - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include - -extern spinlock_t rtc_lock; - -/* - * The motorola uses the m48t18 rtc (includes DS1643) whose registers - * are at a higher end of nvram (1ff8-1fff) than the ibm mc146818 - * rtc (ds1386) which has regs at addr 0-d). The intel gets - * past this because the bios emulates the mc146818. - * - * Why in the world did they have to use different clocks? - * - * Right now things are hacked to check which machine we're on then - * use the appropriate macro. This is very very ugly and I should - * probably have a function that checks which machine we're on then - * does things correctly transparently or a function pointer which - * is setup at boot time to use the correct addresses. - * -- Cort - */ - -/* - * Set the hardware clock. -- Cort - */ -__prep -int mc146818_set_rtc_time(unsigned long nowtime) -{ - unsigned char save_control, save_freq_select; - struct rtc_time tm; - - spin_lock(&rtc_lock); - to_tm(nowtime, &tm); - - /* tell the clock it's being set */ - save_control = CMOS_READ(RTC_CONTROL); - - CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); - - /* stop and reset prescaler */ - save_freq_select = CMOS_READ(RTC_FREQ_SELECT); - - CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); - - tm.tm_year = (tm.tm_year - 1900) % 100; - if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); - } - CMOS_WRITE(tm.tm_sec, RTC_SECONDS); - CMOS_WRITE(tm.tm_min, RTC_MINUTES); - CMOS_WRITE(tm.tm_hour, RTC_HOURS); - CMOS_WRITE(tm.tm_mon, RTC_MONTH); - CMOS_WRITE(tm.tm_mday, RTC_DAY_OF_MONTH); - CMOS_WRITE(tm.tm_year, RTC_YEAR); - - /* The following flags have to be released exactly in this order, - * otherwise the DS12887 (popular MC146818A clone with integrated - * battery and quartz) will not reset the oscillator and will not - * update precisely 500 ms later. You won't find this mentioned in - * the Dallas Semiconductor data sheets, but who believes data - * sheets anyway ... -- Markus Kuhn - */ - CMOS_WRITE(save_control, RTC_CONTROL); - CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); - spin_unlock(&rtc_lock); - - return 0; -} - -__prep -unsigned long mc146818_get_rtc_time(void) -{ - unsigned int year, mon, day, hour, min, sec; - int uip, i; - - /* The Linux interpretation of the CMOS clock register contents: - * When the Update-In-Progress (UIP) flag goes from 1 to 0, the - * RTC registers show the second which has precisely just started. - * Let's hope other operating systems interpret the RTC the same way. - */ - - /* Since the UIP flag is set for about 2.2 ms and the clock - * is typically written with a precision of 1 jiffy, trying - * to obtain a precision better than a few milliseconds is - * an illusion. Only consistency is interesting, this also - * allows to use the routine for /dev/rtc without a potential - * 1 second kernel busy loop triggered by any reader of /dev/rtc. - */ - - for ( i = 0; i<1000000; i++) { - uip = CMOS_READ(RTC_FREQ_SELECT); - sec = CMOS_READ(RTC_SECONDS); - min = CMOS_READ(RTC_MINUTES); - hour = CMOS_READ(RTC_HOURS); - day = CMOS_READ(RTC_DAY_OF_MONTH); - mon = CMOS_READ(RTC_MONTH); - year = CMOS_READ(RTC_YEAR); - uip |= CMOS_READ(RTC_FREQ_SELECT); - if ((uip & RTC_UIP)==0) break; - } - - if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) - || RTC_ALWAYS_BCD) - { - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - } - if ((year += 1900) < 1970) - year += 100; - return mktime(year, mon, day, hour, min, sec); -} - -__prep -int mk48t59_set_rtc_time(unsigned long nowtime) -{ - unsigned char save_control; - struct rtc_time tm; - - spin_lock(&rtc_lock); - to_tm(nowtime, &tm); - - /* tell the clock it's being written */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control | MK48T59_RTC_CA_WRITE)); - - tm.tm_year = (tm.tm_year - 1900) % 100; - BIN_TO_BCD(tm.tm_sec); - BIN_TO_BCD(tm.tm_min); - BIN_TO_BCD(tm.tm_hour); - BIN_TO_BCD(tm.tm_mon); - BIN_TO_BCD(tm.tm_mday); - BIN_TO_BCD(tm.tm_year); - - ppc_md.nvram_write_val(MK48T59_RTC_SECONDS, tm.tm_sec); - ppc_md.nvram_write_val(MK48T59_RTC_MINUTES, tm.tm_min); - ppc_md.nvram_write_val(MK48T59_RTC_HOURS, tm.tm_hour); - ppc_md.nvram_write_val(MK48T59_RTC_MONTH, tm.tm_mon); - ppc_md.nvram_write_val(MK48T59_RTC_DAY_OF_MONTH, tm.tm_mday); - ppc_md.nvram_write_val(MK48T59_RTC_YEAR, tm.tm_year); - - /* Turn off the write bit. */ - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - spin_unlock(&rtc_lock); - - return 0; -} - -__prep -unsigned long mk48t59_get_rtc_time(void) -{ - unsigned char save_control; - unsigned int year, mon, day, hour, min, sec; - - /* Simple: freeze the clock, read it and allow updates again */ - save_control = ppc_md.nvram_read_val(MK48T59_RTC_CONTROLA); - save_control &= ~MK48T59_RTC_CA_READ; - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - /* Set the register to read the value. */ - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, - (save_control | MK48T59_RTC_CA_READ)); - - sec = ppc_md.nvram_read_val(MK48T59_RTC_SECONDS); - min = ppc_md.nvram_read_val(MK48T59_RTC_MINUTES); - hour = ppc_md.nvram_read_val(MK48T59_RTC_HOURS); - day = ppc_md.nvram_read_val(MK48T59_RTC_DAY_OF_MONTH); - mon = ppc_md.nvram_read_val(MK48T59_RTC_MONTH); - year = ppc_md.nvram_read_val(MK48T59_RTC_YEAR); - - /* Let the time values change again. */ - ppc_md.nvram_write_val(MK48T59_RTC_CONTROLA, save_control); - - BCD_TO_BIN(sec); - BCD_TO_BIN(min); - BCD_TO_BIN(hour); - BCD_TO_BIN(day); - BCD_TO_BIN(mon); - BCD_TO_BIN(year); - - year = year + 1900; - if (year < 1970) { - year += 100; - } - - return mktime(year, mon, day, hour, min, sec); -} diff -urN linux-2.6.3-rc2/arch/ppc/platforms/spruce.h linux-2.6.3-rc3/arch/ppc/platforms/spruce.h --- linux-2.6.3-rc2/arch/ppc/platforms/spruce.h 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/spruce.h 2004-02-14 19:30:59.000000000 -0800 @@ -35,11 +35,37 @@ #define SPRUCE_MEM_SIZE 0x04000000 #define SPRUCE_BUS_SPEED 66666667 -#define SPRUCE_SERIAL_1_ADDR 0xff600300 -#define SPRUCE_SERIAL_2_ADDR 0xff600400 - #define SPRUCE_NVRAM_BASE_ADDR 0xff800000 #define SPRUCE_RTC_BASE_ADDR SPRUCE_NVRAM_BASE_ADDR +/* + * Serial port defines + */ +#define SPRUCE_FPGA_REG_A 0xff820000 +#define SPRUCE_UARTCLK_33M 0x02 +#define SPRUCE_UARTCLK_IS_33M(reg) (reg & SPRUCE_UARTCLK_33M) + +#define UART0_IO_BASE 0xff600300 +#define UART1_IO_BASE 0xff600400 + +#define RS_TABLE_SIZE 2 + +#define SPRUCE_BAUD_33M (33000000/64) +#define SPRUCE_BAUD_30M (30000000/64) +#define BASE_BAUD SPRUCE_BAUD_33M + +#define UART0_INT 3 +#define UART1_INT 4 + +#define STD_UART_OP(num) \ + { 0, BASE_BAUD, 0, UART##num##_INT, \ + ASYNC_BOOT_AUTOCONF, \ + iomem_base: UART##num##_IO_BASE, \ + io_type: SERIAL_IO_MEM}, + +#define SERIAL_PORT_DFNS \ + STD_UART_OP(0) \ + STD_UART_OP(1) + #endif /* __ASM_SPRUCE_H__ */ #endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc/platforms/spruce_setup.c linux-2.6.3-rc3/arch/ppc/platforms/spruce_setup.c --- linux-2.6.3-rc2/arch/ppc/platforms/spruce_setup.c 2004-02-03 19:43:11.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/platforms/spruce_setup.c 2004-02-14 19:30:59.000000000 -0800 @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include #include @@ -39,6 +42,7 @@ #include #include #include +#include #include @@ -103,6 +107,48 @@ return 0; } +static void __init +spruce_early_serial_map(void) +{ + u32 uart_clk; + struct uart_port serial_req; + + if (SPRUCE_UARTCLK_IS_33M(readb(SPRUCE_FPGA_REG_A))) + uart_clk = SPRUCE_BAUD_33M * 16; + else + uart_clk = SPRUCE_BAUD_30M * 16; + + /* Setup serial port access */ + memset(&serial_req, 0, sizeof(serial_req)); + serial_req.uartclk = uart_clk; + serial_req.irq = UART0_INT; + serial_req.flags = ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST; + serial_req.iotype = SERIAL_IO_MEM; + serial_req.membase = (u_char *)UART0_IO_BASE; + serial_req.regshift = 0; + +#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) + gen550_init(0, &serial_req); +#endif +#ifdef CONFIG_SERIAL_8250 + if (early_serial_setup(&serial_req) != 0) + printk("Early serial init of port 0 failed\n"); +#endif + + /* Assume early_serial_setup() doesn't modify serial_req */ + serial_req.line = 1; + serial_req.irq = UART1_INT; + serial_req.membase = (u_char *)UART1_IO_BASE; + +#if defined(CONFIG_KGDB) || defined(CONFIG_SERIAL_TEXT_DEBUG) + gen550_init(1, &serial_req); +#endif +#ifdef CONFIG_SERIAL_8250 + if (early_serial_setup(&serial_req) != 0) + printk("Early serial init of port 1 failed\n"); +#endif +} + TODC_ALLOC(); static void __init @@ -128,10 +174,11 @@ ROOT_DEV = Root_SDA1; #endif -#ifdef CONFIG_DUMMY_CONSOLE +#ifdef CONFIG_VT conswitchp = &dummy_con; #endif + /* Identify the system */ printk(KERN_INFO "System Identification: IBM Spruce\n"); printk(KERN_INFO "Port by MontaVista Software, Inc. (source@mvista.com)\n"); @@ -146,12 +193,12 @@ /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ __asm__ __volatile__ ("\n\ - lis 3,0xfff0 - ori 3,3,0x0100 - mtspr 26,3 - li 3,0 - mtspr 27,3 - rfi + lis 3,0xfff0 \n\ + ori 3,3,0x0100 \n\ + mtspr 26,3 \n\ + li 3,0 \n\ + mtspr 27,3 \n\ + rfi \n\ "); for(;;); } @@ -175,12 +222,27 @@ 0x08000000, _PAGE_IO); } +/* + * Set BAT 3 to map 0xf8000000 to end of physical memory space 1-to-1. + */ +static __inline__ void +spruce_set_bat(void) +{ + mb(); + mtspr(DBAT1U, 0xf8000ffe); + mtspr(DBAT1L, 0xf800002a); + mb(); +} + void __init platform_init(unsigned long r3, unsigned long r4, unsigned long r5, unsigned long r6, unsigned long r7) { parse_bootinfo(find_bootinfo()); + /* Map in board regs, etc. */ + spruce_set_bat(); + isa_io_base = SPRUCE_ISA_IO_BASE; pci_dram_offset = SPRUCE_PCI_SYS_MEM_BASE; @@ -202,4 +264,13 @@ ppc_md.nvram_read_val = todc_direct_read_val; ppc_md.nvram_write_val = todc_direct_write_val; + + spruce_early_serial_map(); + +#ifdef CONFIG_SERIAL_TEXT_DEBUG + ppc_md.progress = gen550_progress; +#endif /* CONFIG_SERIAL_TEXT_DEBUG */ +#ifdef CONFIG_KGDB + ppc_md.kgdb_map_scc = gen550_kgdb_map_scc; +#endif } diff -urN linux-2.6.3-rc2/arch/ppc/syslib/Makefile linux-2.6.3-rc3/arch/ppc/syslib/Makefile --- linux-2.6.3-rc2/arch/ppc/syslib/Makefile 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/syslib/Makefile 2004-02-14 19:30:59.000000000 -0800 @@ -33,7 +33,7 @@ obj-$(CONFIG_PPC_PMAC) += open_pic.o indirect_pci.o obj-$(CONFIG_POWER4) += open_pic2.o obj-$(CONFIG_PPC_CHRP) += open_pic.o indirect_pci.o i8259.o -obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o +obj-$(CONFIG_PPC_PREP) += open_pic.o indirect_pci.o i8259.o todc_time.o obj-$(CONFIG_ADIR) += i8259.o indirect_pci.o pci_auto.o \ todc_time.o obj-$(CONFIG_EBONY) += indirect_pci.o pci_auto.o todc_time.o diff -urN linux-2.6.3-rc2/arch/ppc/syslib/ppc4xx_setup.c linux-2.6.3-rc3/arch/ppc/syslib/ppc4xx_setup.c --- linux-2.6.3-rc2/arch/ppc/syslib/ppc4xx_setup.c 2004-02-03 19:43:04.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc/syslib/ppc4xx_setup.c 2004-02-14 19:30:59.000000000 -0800 @@ -170,7 +170,7 @@ unsigned int freq; bd_t *bip = &__res; -#if defined(CONFIG_WALNUT) || defined(CONFIG_CEDER)|| defined(CONFIG_ASH) || defined(CONFIG_SYCAMORE) +#if defined(CONFIG_WALNUT) || defined(CONFIG_ASH) || defined(CONFIG_SYCAMORE) /* Walnut boot rom sets DCR CHCR1 (aka CPC0_CR1) bit CETE to 1 */ mtdcr(DCRN_CHCR1, mfdcr(DCRN_CHCR1) & ~CHR1_CETE); #endif diff -urN linux-2.6.3-rc2/arch/ppc64/Kconfig linux-2.6.3-rc3/arch/ppc64/Kconfig --- linux-2.6.3-rc2/arch/ppc64/Kconfig 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/Kconfig 2004-02-14 19:30:59.000000000 -0800 @@ -60,7 +60,7 @@ bool "iSeries" config PPC_PSERIES - bool "pSeries" + bool "pSeries / PowerMac G5" endchoice @@ -72,6 +72,11 @@ bool default y +config PPC_OF + depends on PPC_PSERIES + bool + default y + # VMX is pSeries only for now until somebody writes the iSeries # exception vectors for it config ALTIVEC @@ -79,6 +84,23 @@ depends on PPC_PSERIES default y +config PPC_PMAC + depends on PPC_PSERIES + bool "Apple PowerMac G5 support" + select ADB_PMU + +config PPC_PMAC64 + bool + depends on PPC_PMAC + default y + +config BOOTX_TEXT + bool "Support for early boot text console" + depends PPC_OF + help + Say Y here to see progress messages from the boot firmware in text + mode. Requires an Open Firmware compatible video card. + config POWER4_ONLY bool "Optimize for POWER4" default n @@ -334,9 +356,16 @@ keys are documented in . Don't say Y unless you really know what this hack does. +config DEBUGGER + bool "Enable debugger hooks" + depends on DEBUG_KERNEL + help + Include in-kernel hooks for kernel debuggers. Unless you are + intending to debug the kernel, say N here. + config XMON bool "Include xmon kernel debugger" - depends on DEBUG_KERNEL + depends on DEBUGGER help Include in-kernel hooks for the xmon kernel monitor/debugger. Unless you are intending to debug the kernel, say N here. diff -urN linux-2.6.3-rc2/arch/ppc64/boot/prom.c linux-2.6.3-rc3/arch/ppc64/boot/prom.c --- linux-2.6.3-rc2/arch/ppc64/boot/prom.c 2004-02-03 19:44:28.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/boot/prom.c 2004-02-14 19:30:59.000000000 -0800 @@ -11,9 +11,6 @@ #include #include -#define BITS_PER_LONG 32 -#include - int (*prom)(void *); void *chosen_handle; @@ -28,6 +25,9 @@ void printk(char *fmt, ...); +/* there is no convenient header to get this from... -- paulus */ +extern unsigned long strlen(const char *); + int write(void *handle, void *ptr, int nb) { @@ -352,7 +352,7 @@ #define SPECIAL 32 /* 0x */ #define LARGE 64 /* use 'ABCDEF' instead of 'abcdef' */ -static char * number(char * str, long long num, int base, int size, int precision, int type) +static char * number(char * str, long num, int base, int size, int precision, int type) { char c,sign,tmp[66]; const char *digits="0123456789abcdefghijklmnopqrstuvwxyz"; @@ -388,8 +388,10 @@ i = 0; if (num == 0) tmp[i++]='0'; - else while (num != 0) - tmp[i++] = digits[do_div(num,base)]; + else while (num != 0) { + tmp[i++] = digits[num % base]; + num /= base; + } if (i > precision) precision = i; size -= precision; @@ -424,7 +426,7 @@ int vsprintf(char *buf, const char *fmt, va_list args) { int len; - unsigned long long num; + unsigned long num; int i, base; char * str; const char *s; @@ -575,9 +577,7 @@ --fmt; continue; } - if (qualifier == 'L') - num = va_arg(args, long long); - else if (qualifier == 'l') { + if (qualifier == 'l') { num = va_arg(args, unsigned long); if (flags & SIGN) num = (signed long) num; diff -urN linux-2.6.3-rc2/arch/ppc64/boot/zlib.c linux-2.6.3-rc3/arch/ppc64/boot/zlib.c --- linux-2.6.3-rc2/arch/ppc64/boot/zlib.c 2004-02-03 19:43:15.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/boot/zlib.c 2004-02-14 19:30:59.000000000 -0800 @@ -102,9 +102,8 @@ /* functions */ -#include +extern void *memcpy(void *, const void *, unsigned long); #define zmemcpy memcpy -#define zmemzero(dest, len) memset(dest, 0, len) /* Diagnostic functions */ #ifdef DEBUG_ZLIB diff -urN linux-2.6.3-rc2/arch/ppc64/configs/g5_defconfig linux-2.6.3-rc3/arch/ppc64/configs/g5_defconfig --- linux-2.6.3-rc2/arch/ppc64/configs/g5_defconfig 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/configs/g5_defconfig 2004-02-14 19:30:59.000000000 -0800 @@ -0,0 +1,1077 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_FRAME_POINTER=y +CONFIG_FORCE_MAX_ZONEORDER=13 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=17 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +CONFIG_MODULE_FORCE_UNLOAD=y +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Platform support +# +# CONFIG_PPC_ISERIES is not set +CONFIG_PPC_PSERIES=y +CONFIG_PPC=y +CONFIG_PPC64=y +CONFIG_PPC_OF=y +CONFIG_ALTIVEC=y +CONFIG_PPC_PMAC=y +CONFIG_PPC_PMAC64=y +CONFIG_BOOTX_TEXT=y +CONFIG_POWER4_ONLY=y +CONFIG_SMP=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_NR_CPUS=2 +# CONFIG_HMT is not set +CONFIG_DISCONTIGMEM=y +# CONFIG_NUMA is not set +# CONFIG_PPC_RTAS is not set +# CONFIG_LPARCFG is not set + +# +# General setup +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +CONFIG_HOTPLUG=y + +# +# PCMCIA/CardBus support +# +# CONFIG_PCMCIA is not set + +# +# PCI Hotplug Support +# +# CONFIG_HOTPLUG_PCI is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# +CONFIG_FW_LOADER=y + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=8192 +CONFIG_BLK_DEV_INITRD=y + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +CONFIG_BLK_DEV_IDECD=y +CONFIG_BLK_DEV_IDETAPE=y +CONFIG_BLK_DEV_IDEFLOPPY=y +# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +CONFIG_IDE_GENERIC=y +CONFIG_BLK_DEV_IDEPCI=y +# CONFIG_IDEPCI_SHARE_IRQ is not set +# CONFIG_BLK_DEV_OFFBOARD is not set +# CONFIG_BLK_DEV_GENERIC is not set +# CONFIG_BLK_DEV_OPTI621 is not set +# CONFIG_BLK_DEV_SL82C105 is not set +CONFIG_BLK_DEV_IDEDMA_PCI=y +# CONFIG_BLK_DEV_IDEDMA_FORCED is not set +CONFIG_IDEDMA_PCI_AUTO=y +# CONFIG_IDEDMA_ONLYDISK is not set +CONFIG_BLK_DEV_ADMA=y +# CONFIG_BLK_DEV_AEC62XX is not set +# CONFIG_BLK_DEV_ALI15X3 is not set +# CONFIG_BLK_DEV_AMD74XX is not set +# CONFIG_BLK_DEV_CMD64X is not set +# CONFIG_BLK_DEV_TRIFLEX is not set +# CONFIG_BLK_DEV_CY82C693 is not set +# CONFIG_BLK_DEV_CS5520 is not set +# CONFIG_BLK_DEV_CS5530 is not set +# CONFIG_BLK_DEV_HPT34X is not set +# CONFIG_BLK_DEV_HPT366 is not set +# CONFIG_BLK_DEV_SC1200 is not set +# CONFIG_BLK_DEV_PIIX is not set +# CONFIG_BLK_DEV_NS87415 is not set +# CONFIG_BLK_DEV_PDC202XX_OLD is not set +# CONFIG_BLK_DEV_PDC202XX_NEW is not set +# CONFIG_BLK_DEV_SVWKS is not set +# CONFIG_BLK_DEV_SIIMAGE is not set +# CONFIG_BLK_DEV_SLC90E66 is not set +# CONFIG_BLK_DEV_TRM290 is not set +# CONFIG_BLK_DEV_VIA82CXXX is not set +CONFIG_BLK_DEV_IDE_PMAC=y +CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y +CONFIG_BLK_DEV_IDEDMA_PMAC=y +# CONFIG_BLK_DEV_IDE_PMAC_BLINK is not set +CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO=y +CONFIG_BLK_DEV_IDEDMA=y +# CONFIG_IDEDMA_IVB is not set +CONFIG_IDEDMA_AUTO=y +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_REPORT_LUNS=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +CONFIG_SCSI_SATA=y +CONFIG_SCSI_SATA_SVW=y +# CONFIG_SCSI_ATA_PIIX is not set +# CONFIG_SCSI_SATA_PROMISE is not set +# CONFIG_SCSI_SATA_VIA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +# CONFIG_SCSI_QLA21XX is not set +# CONFIG_SCSI_QLA22XX is not set +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set +# CONFIG_SCSI_MESH is not set +# CONFIG_SCSI_MAC53C94 is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID5=y +# CONFIG_MD_RAID6 is not set +# CONFIG_MD_MULTIPATH is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_IOCTL_V4=y + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +CONFIG_IEEE1394=y + +# +# Subsystem Options +# +# CONFIG_IEEE1394_VERBOSEDEBUG is not set +CONFIG_IEEE1394_OUI_DB=y + +# +# Device Drivers +# +# CONFIG_IEEE1394_PCILYNX is not set +CONFIG_IEEE1394_OHCI1394=y + +# +# Protocol Drivers +# +CONFIG_IEEE1394_VIDEO1394=m +CONFIG_IEEE1394_SBP2=m +# CONFIG_IEEE1394_SBP2_PHYS_DMA is not set +CONFIG_IEEE1394_ETH1394=m +CONFIG_IEEE1394_DV1394=m +CONFIG_IEEE1394_RAWIO=y +# CONFIG_IEEE1394_CMP is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# +CONFIG_ADB_PMU=y +# CONFIG_PMAC_PBOOK is not set +# CONFIG_PMAC_BACKLIGHT is not set +# CONFIG_MAC_SERIAL is not set +CONFIG_ADB=y +# CONFIG_INPUT_ADBHID is not set +CONFIG_THERM_PM72=y + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +# CONFIG_XFRM_USER is not set + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +CONFIG_LLC=y +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_MACE is not set +# CONFIG_BMAC is not set +# CONFIG_OAKNET is not set +# CONFIG_HAPPYMEAL is not set +CONFIG_SUNGEM=y +# CONFIG_NET_VENDOR_3COM is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +# CONFIG_NET_PCI is not set + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=y +CONFIG_ACENIC_OMIT_TIGON_I=y +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +CONFIG_TIGON3=m + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +CONFIG_TR=y +CONFIG_IBMOL=y +# CONFIG_IBMLS is not set +# CONFIG_3C359 is not set +# CONFIG_TMS380TR is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +CONFIG_INPUT_JOYDEV=m +# CONFIG_INPUT_TSDEV is not set +CONFIG_INPUT_EVDEV=y +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +# CONFIG_KEYBOARD_ATKBD is not set +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +# CONFIG_MOUSE_PS2 is not set +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_PMACZILOG is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_HVC_CONSOLE=y + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +CONFIG_I2C=y +CONFIG_I2C_CHARDEV=y + +# +# I2C Algorithms +# +CONFIG_I2C_ALGOBIT=y +# CONFIG_I2C_ALGOPCF is not set + +# +# I2C Hardware Bus support +# +# CONFIG_I2C_ALI1535 is not set +# CONFIG_I2C_ALI15X3 is not set +# CONFIG_I2C_AMD756 is not set +# CONFIG_I2C_AMD8111 is not set +# CONFIG_I2C_ELV is not set +# CONFIG_I2C_I801 is not set +# CONFIG_I2C_I810 is not set +# CONFIG_I2C_ISA is not set +CONFIG_I2C_KEYWEST=y +# CONFIG_I2C_NFORCE2 is not set +# CONFIG_I2C_PARPORT_LIGHT is not set +# CONFIG_I2C_PROSAVAGE is not set +# CONFIG_I2C_SAVAGE4 is not set +# CONFIG_SCx200_ACB is not set +# CONFIG_I2C_SIS5595 is not set +# CONFIG_I2C_SIS630 is not set +# CONFIG_I2C_SIS96X is not set +# CONFIG_I2C_VELLEMAN is not set +# CONFIG_I2C_VIA is not set +# CONFIG_I2C_VIAPRO is not set +# CONFIG_I2C_VOODOO3 is not set + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set +# CONFIG_SENSORS_ADM1021 is not set +# CONFIG_SENSORS_ASB100 is not set +# CONFIG_SENSORS_EEPROM is not set +# CONFIG_SENSORS_FSCHER is not set +# CONFIG_SENSORS_GL518SM is not set +# CONFIG_SENSORS_IT87 is not set +# CONFIG_SENSORS_LM75 is not set +# CONFIG_SENSORS_LM78 is not set +# CONFIG_SENSORS_LM83 is not set +# CONFIG_SENSORS_LM85 is not set +# CONFIG_SENSORS_LM90 is not set +# CONFIG_SENSORS_VIA686A is not set +# CONFIG_SENSORS_W83781D is not set +# CONFIG_SENSORS_W83L785TS is not set +# CONFIG_I2C_DEBUG_CORE is not set +# CONFIG_I2C_DEBUG_BUS is not set +# CONFIG_I2C_DEBUG_CHIP is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CONTROL is not set +# CONFIG_FB_PLATINUM is not set +# CONFIG_FB_VALKYRIE is not set +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA16 is not set +CONFIG_FB_RIVA=y +# CONFIG_FB_MATROX is not set +# CONFIG_FB_RADEON_OLD is not set +CONFIG_FB_RADEON=y +CONFIG_FB_RADEON_I2C=y +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_PCI_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +CONFIG_USB=y +# CONFIG_USB_DEBUG is not set + +# +# Miscellaneous USB options +# +CONFIG_USB_DEVICEFS=y +# CONFIG_USB_BANDWIDTH is not set +# CONFIG_USB_DYNAMIC_MINORS is not set + +# +# USB Host Controller Drivers +# +CONFIG_USB_EHCI_HCD=y +CONFIG_USB_OHCI_HCD=y +# CONFIG_USB_UHCI_HCD is not set + +# +# USB Device Class drivers +# +# CONFIG_USB_BLUETOOTH_TTY is not set +CONFIG_USB_ACM=m +CONFIG_USB_PRINTER=m +CONFIG_USB_STORAGE=m +CONFIG_USB_STORAGE_DEBUG=y +CONFIG_USB_STORAGE_DATAFAB=y +CONFIG_USB_STORAGE_FREECOM=y +CONFIG_USB_STORAGE_ISD200=y +CONFIG_USB_STORAGE_DPCM=y +CONFIG_USB_STORAGE_HP8200e=y +CONFIG_USB_STORAGE_SDDR09=y +CONFIG_USB_STORAGE_SDDR55=y +CONFIG_USB_STORAGE_JUMPSHOT=y + +# +# USB Human Interface Devices (HID) +# +CONFIG_USB_HID=y +CONFIG_USB_HIDINPUT=y +CONFIG_HID_FF=y +CONFIG_HID_PID=y +CONFIG_LOGITECH_FF=y +CONFIG_THRUSTMASTER_FF=y +CONFIG_USB_HIDDEV=y +# CONFIG_USB_AIPTEK is not set +# CONFIG_USB_WACOM is not set +# CONFIG_USB_KBTAB is not set +# CONFIG_USB_POWERMATE is not set +# CONFIG_USB_XPAD is not set + +# +# USB Imaging devices +# +# CONFIG_USB_MDC800 is not set +# CONFIG_USB_MICROTEK is not set +# CONFIG_USB_HPUSBSCSI is not set + +# +# USB Multimedia devices +# +# CONFIG_USB_DABUSB is not set + +# +# Video4Linux support is needed for USB Multimedia device support +# + +# +# USB Network adaptors +# +# CONFIG_USB_CATC is not set +# CONFIG_USB_KAWETH is not set +# CONFIG_USB_PEGASUS is not set +# CONFIG_USB_RTL8150 is not set +CONFIG_USB_USBNET=m + +# +# USB Host-to-Host Cables +# +CONFIG_USB_AN2720=y +CONFIG_USB_BELKIN=y +CONFIG_USB_GENESYS=y +CONFIG_USB_NET1080=y +CONFIG_USB_PL2301=y + +# +# Intelligent USB Devices/Gadgets +# +CONFIG_USB_ARMLINUX=y +CONFIG_USB_EPSON2888=y +CONFIG_USB_ZAURUS=y +CONFIG_USB_CDCETHER=y + +# +# USB Network Adapters +# +CONFIG_USB_AX8817X=y + +# +# USB port drivers +# + +# +# USB Serial Converter support +# +CONFIG_USB_SERIAL=m +CONFIG_USB_SERIAL_GENERIC=y +CONFIG_USB_SERIAL_BELKIN=m +CONFIG_USB_SERIAL_DIGI_ACCELEPORT=m +CONFIG_USB_SERIAL_EMPEG=m +CONFIG_USB_SERIAL_FTDI_SIO=m +CONFIG_USB_SERIAL_VISOR=m +CONFIG_USB_SERIAL_IPAQ=m +CONFIG_USB_SERIAL_IR=m +CONFIG_USB_SERIAL_EDGEPORT=m +CONFIG_USB_SERIAL_EDGEPORT_TI=m +CONFIG_USB_SERIAL_KEYSPAN_PDA=m +CONFIG_USB_SERIAL_KEYSPAN=m +CONFIG_USB_SERIAL_KEYSPAN_MPR=y +CONFIG_USB_SERIAL_KEYSPAN_USA28=y +CONFIG_USB_SERIAL_KEYSPAN_USA28X=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XA=y +CONFIG_USB_SERIAL_KEYSPAN_USA28XB=y +CONFIG_USB_SERIAL_KEYSPAN_USA19=y +CONFIG_USB_SERIAL_KEYSPAN_USA18X=y +CONFIG_USB_SERIAL_KEYSPAN_USA19W=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QW=y +CONFIG_USB_SERIAL_KEYSPAN_USA19QI=y +CONFIG_USB_SERIAL_KEYSPAN_USA49W=y +CONFIG_USB_SERIAL_KEYSPAN_USA49WLC=y +CONFIG_USB_SERIAL_KLSI=m +CONFIG_USB_SERIAL_KOBIL_SCT=m +CONFIG_USB_SERIAL_MCT_U232=m +CONFIG_USB_SERIAL_PL2303=m +CONFIG_USB_SERIAL_SAFE=m +CONFIG_USB_SERIAL_SAFE_PADDED=y +CONFIG_USB_SERIAL_CYBERJACK=m +CONFIG_USB_SERIAL_XIRCOM=m +CONFIG_USB_SERIAL_OMNINET=m +CONFIG_USB_EZUSB=y + +# +# USB Miscellaneous drivers +# +# CONFIG_USB_EMI62 is not set +# CONFIG_USB_EMI26 is not set +# CONFIG_USB_TIGL is not set +# CONFIG_USB_AUERSWALD is not set +# CONFIG_USB_RIO500 is not set +# CONFIG_USB_LEGOTOWER is not set +# CONFIG_USB_BRLVGER is not set +# CONFIG_USB_LCD is not set +# CONFIG_USB_LED is not set +# CONFIG_USB_TEST is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +CONFIG_FS_POSIX_ACL=y +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +CONFIG_PARTITION_ADVANCED=y +# CONFIG_ACORN_PARTITION is not set +# CONFIG_OSF_PARTITION is not set +# CONFIG_AMIGA_PARTITION is not set +# CONFIG_ATARI_PARTITION is not set +CONFIG_MAC_PARTITION=y +# CONFIG_MSDOS_PARTITION is not set +# CONFIG_LDM_PARTITION is not set +# CONFIG_NEC98_PARTITION is not set +# CONFIG_SGI_PARTITION is not set +# CONFIG_ULTRIX_PARTITION is not set +# CONFIG_SUN_PARTITION is not set +# CONFIG_EFI_PARTITION is not set + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +# CONFIG_XMON is not set +# CONFIG_PPCDBG is not set +# CONFIG_DEBUG_INFO is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=m +CONFIG_ZLIB_DEFLATE=m diff -urN linux-2.6.3-rc2/arch/ppc64/configs/pSeries_defconfig linux-2.6.3-rc3/arch/ppc64/configs/pSeries_defconfig --- linux-2.6.3-rc2/arch/ppc64/configs/pSeries_defconfig 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/configs/pSeries_defconfig 2004-02-14 19:30:59.000000000 -0800 @@ -0,0 +1,783 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_64BIT=y +CONFIG_MMU=y +CONFIG_RWSEM_XCHGADD_ALGORITHM=y +CONFIG_GENERIC_ISA_DMA=y +CONFIG_HAVE_DEC_LOCK=y +CONFIG_EARLY_PRINTK=y +CONFIG_COMPAT=y +CONFIG_FRAME_POINTER=y +CONFIG_FORCE_MAX_ZONEORDER=13 + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y + +# +# General setup +# +CONFIG_SWAP=y +CONFIG_SYSVIPC=y +# CONFIG_BSD_PROCESS_ACCT is not set +CONFIG_SYSCTL=y +CONFIG_LOG_BUF_SHIFT=16 +CONFIG_IKCONFIG=y +CONFIG_IKCONFIG_PROC=y +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +CONFIG_MODULES=y +CONFIG_MODULE_UNLOAD=y +# CONFIG_MODULE_FORCE_UNLOAD is not set +CONFIG_OBSOLETE_MODPARM=y +# CONFIG_MODVERSIONS is not set +# CONFIG_KMOD is not set + +# +# Platform support +# +# CONFIG_PPC_ISERIES is not set +CONFIG_PPC_PSERIES=y +CONFIG_PPC=y +CONFIG_PPC64=y +CONFIG_PPC_OF=y +CONFIG_ALTIVEC=y +# CONFIG_PPC_PMAC is not set +# CONFIG_BOOTX_TEXT is not set +# CONFIG_POWER4_ONLY is not set +CONFIG_SMP=y +CONFIG_IRQ_ALL_CPUS=y +CONFIG_NR_CPUS=32 +# CONFIG_HMT is not set +# CONFIG_DISCONTIGMEM is not set +CONFIG_PPC_RTAS=y +CONFIG_RTAS_FLASH=m +CONFIG_SCANLOG=m +CONFIG_LPARCFG=y + +# +# General setup +# +CONFIG_PCI=y +CONFIG_PCI_DOMAINS=y +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_MISC is not set +CONFIG_PCI_LEGACY_PROC=y +CONFIG_PCI_NAMES=y +# CONFIG_HOTPLUG is not set +CONFIG_PROC_DEVICETREE=y +# CONFIG_CMDLINE_BOOL is not set + +# +# Device Drivers +# + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Plug and Play support +# + +# +# Block devices +# +CONFIG_BLK_DEV_FD=y +# CONFIG_BLK_CPQ_DA is not set +# CONFIG_BLK_CPQ_CISS_DA is not set +# CONFIG_BLK_DEV_DAC960 is not set +# CONFIG_BLK_DEV_UMEM is not set +CONFIG_BLK_DEV_LOOP=y +# CONFIG_BLK_DEV_CRYPTOLOOP is not set +CONFIG_BLK_DEV_NBD=m +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y + +# +# ATA/ATAPI/MFM/RLL support +# +# CONFIG_IDE is not set + +# +# SCSI device support +# +CONFIG_SCSI=y +CONFIG_SCSI_PROC_FS=y + +# +# SCSI support type (disk, tape, CD-ROM) +# +CONFIG_BLK_DEV_SD=y +CONFIG_CHR_DEV_ST=y +# CONFIG_CHR_DEV_OSST is not set +CONFIG_BLK_DEV_SR=y +CONFIG_BLK_DEV_SR_VENDOR=y +CONFIG_CHR_DEV_SG=y + +# +# Some SCSI devices (e.g. CD jukebox) support multiple LUNs +# +CONFIG_SCSI_MULTI_LUN=y +CONFIG_SCSI_REPORT_LUNS=y +CONFIG_SCSI_CONSTANTS=y +# CONFIG_SCSI_LOGGING is not set + +# +# SCSI low-level drivers +# +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_ACARD is not set +# CONFIG_SCSI_AACRAID is not set +# CONFIG_SCSI_AIC7XXX is not set +# CONFIG_SCSI_AIC7XXX_OLD is not set +# CONFIG_SCSI_AIC79XX is not set +# CONFIG_SCSI_ADVANSYS is not set +# CONFIG_SCSI_MEGARAID is not set +# CONFIG_SCSI_SATA is not set +# CONFIG_SCSI_BUSLOGIC is not set +# CONFIG_SCSI_CPQFCTS is not set +# CONFIG_SCSI_DMX3191D is not set +# CONFIG_SCSI_EATA is not set +# CONFIG_SCSI_EATA_PIO is not set +# CONFIG_SCSI_FUTURE_DOMAIN is not set +# CONFIG_SCSI_GDTH is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_INIA100 is not set +CONFIG_SCSI_SYM53C8XX_2=y +CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=0 +CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16 +CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64 +# CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set +# CONFIG_SCSI_QLOGIC_ISP is not set +# CONFIG_SCSI_QLOGIC_FC is not set +# CONFIG_SCSI_QLOGIC_1280 is not set +CONFIG_SCSI_QLA2XXX=y +CONFIG_SCSI_QLA21XX=y +CONFIG_SCSI_QLA22XX=y +# CONFIG_SCSI_QLA2300 is not set +# CONFIG_SCSI_QLA2322 is not set +# CONFIG_SCSI_QLA6312 is not set +# CONFIG_SCSI_QLA6322 is not set +# CONFIG_SCSI_DC395x is not set +# CONFIG_SCSI_DC390T is not set +# CONFIG_SCSI_DEBUG is not set + +# +# Multi-device support (RAID and LVM) +# +CONFIG_MD=y +CONFIG_BLK_DEV_MD=y +CONFIG_MD_LINEAR=y +CONFIG_MD_RAID0=y +CONFIG_MD_RAID1=y +CONFIG_MD_RAID5=y +# CONFIG_MD_RAID6 is not set +# CONFIG_MD_MULTIPATH is not set +CONFIG_BLK_DEV_DM=y +CONFIG_DM_IOCTL_V4=y + +# +# Fusion MPT device support +# +# CONFIG_FUSION is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# I2O device support +# + +# +# Macintosh device drivers +# + +# +# Networking support +# +CONFIG_NET=y + +# +# Networking options +# +CONFIG_PACKET=y +# CONFIG_PACKET_MMAP is not set +# CONFIG_NETLINK_DEV is not set +CONFIG_UNIX=y +CONFIG_NET_KEY=m +CONFIG_INET=y +CONFIG_IP_MULTICAST=y +# CONFIG_IP_ADVANCED_ROUTER is not set +# CONFIG_IP_PNP is not set +CONFIG_NET_IPIP=y +# CONFIG_NET_IPGRE is not set +# CONFIG_IP_MROUTE is not set +# CONFIG_ARPD is not set +CONFIG_INET_ECN=y +CONFIG_SYN_COOKIES=y +CONFIG_INET_AH=m +CONFIG_INET_ESP=m +CONFIG_INET_IPCOMP=m +# CONFIG_IPV6 is not set +# CONFIG_DECNET is not set +# CONFIG_BRIDGE is not set +# CONFIG_NETFILTER is not set +CONFIG_XFRM=y +CONFIG_XFRM_USER=m + +# +# SCTP Configuration (EXPERIMENTAL) +# +CONFIG_IPV6_SCTP__=y +# CONFIG_IP_SCTP is not set +# CONFIG_ATM is not set +# CONFIG_VLAN_8021Q is not set +# CONFIG_LLC2 is not set +# CONFIG_IPX is not set +# CONFIG_ATALK is not set +# CONFIG_X25 is not set +# CONFIG_LAPB is not set +# CONFIG_NET_DIVERT is not set +# CONFIG_ECONET is not set +# CONFIG_WAN_ROUTER is not set +# CONFIG_NET_FASTROUTE is not set +# CONFIG_NET_HW_FLOWCONTROL is not set + +# +# QoS and/or fair queueing +# +# CONFIG_NET_SCHED is not set + +# +# Network testing +# +# CONFIG_NET_PKTGEN is not set +CONFIG_NETDEVICES=y + +# +# ARCnet devices +# +# CONFIG_ARCNET is not set +CONFIG_DUMMY=m +CONFIG_BONDING=m +# CONFIG_EQUALIZER is not set +CONFIG_TUN=m + +# +# Ethernet (10 or 100Mbit) +# +CONFIG_NET_ETHERNET=y +CONFIG_MII=y +# CONFIG_OAKNET is not set +# CONFIG_HAPPYMEAL is not set +# CONFIG_SUNGEM is not set +CONFIG_NET_VENDOR_3COM=y +CONFIG_VORTEX=y +# CONFIG_TYPHOON is not set + +# +# Tulip family network device support +# +# CONFIG_NET_TULIP is not set +# CONFIG_HP100 is not set +CONFIG_NET_PCI=y +CONFIG_PCNET32=y +# CONFIG_AMD8111_ETH is not set +# CONFIG_ADAPTEC_STARFIRE is not set +# CONFIG_B44 is not set +# CONFIG_FORCEDETH is not set +# CONFIG_DGRS is not set +# CONFIG_EEPRO100 is not set +CONFIG_E100=y +# CONFIG_FEALNX is not set +# CONFIG_NATSEMI is not set +# CONFIG_NE2K_PCI is not set +# CONFIG_8139CP is not set +# CONFIG_8139TOO is not set +# CONFIG_SIS900 is not set +# CONFIG_EPIC100 is not set +# CONFIG_SUNDANCE is not set +# CONFIG_VIA_RHINE is not set + +# +# Ethernet (1000 Mbit) +# +CONFIG_ACENIC=y +CONFIG_ACENIC_OMIT_TIGON_I=y +# CONFIG_DL2K is not set +CONFIG_E1000=y +# CONFIG_E1000_NAPI is not set +# CONFIG_NS83820 is not set +# CONFIG_HAMACHI is not set +# CONFIG_YELLOWFIN is not set +# CONFIG_R8169 is not set +# CONFIG_SIS190 is not set +# CONFIG_SK98LIN is not set +# CONFIG_TIGON3 is not set + +# +# Ethernet (10000 Mbit) +# +# CONFIG_IXGB is not set +# CONFIG_FDDI is not set +# CONFIG_HIPPI is not set +CONFIG_PPP=m +# CONFIG_PPP_MULTILINK is not set +# CONFIG_PPP_FILTER is not set +CONFIG_PPP_ASYNC=m +CONFIG_PPP_SYNC_TTY=m +CONFIG_PPP_DEFLATE=m +CONFIG_PPP_BSDCOMP=m +CONFIG_PPPOE=m +# CONFIG_SLIP is not set + +# +# Wireless LAN (non-hamradio) +# +# CONFIG_NET_RADIO is not set + +# +# Token Ring devices +# +# CONFIG_TR is not set +# CONFIG_NET_FC is not set +# CONFIG_SHAPER is not set + +# +# Wan interfaces +# +# CONFIG_WAN is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# IrDA (infrared) support +# +# CONFIG_IRDA is not set + +# +# Bluetooth support +# +# CONFIG_BT is not set + +# +# ISDN subsystem +# +# CONFIG_ISDN_BOOL is not set + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set +# CONFIG_SERIO_PCIPS2 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +CONFIG_INPUT_MISC=y +CONFIG_INPUT_PCSPKR=y +# CONFIG_INPUT_UINPUT is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL_NONSTANDARD is not set + +# +# Serial drivers +# +CONFIG_SERIAL_8250=y +CONFIG_SERIAL_8250_CONSOLE=y +CONFIG_SERIAL_8250_NR_UARTS=4 +# CONFIG_SERIAL_8250_EXTENDED is not set + +# +# Non-8250 serial port support +# +CONFIG_SERIAL_CORE=y +CONFIG_SERIAL_CORE_CONSOLE=y +# CONFIG_SERIAL_PMACZILOG is not set +CONFIG_UNIX98_PTYS=y +CONFIG_UNIX98_PTY_COUNT=256 +CONFIG_HVC_CONSOLE=y + +# +# Mice +# +# CONFIG_BUSMOUSE is not set +# CONFIG_QIC02_TAPE is not set + +# +# IPMI +# +# CONFIG_IPMI_HANDLER is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_NVRAM is not set +# CONFIG_RTC is not set +# CONFIG_GEN_RTC is not set +# CONFIG_DTLK is not set +# CONFIG_R3964 is not set +# CONFIG_APPLICOM is not set + +# +# Ftape, the floppy tape device driver +# +# CONFIG_AGP is not set +# CONFIG_DRM is not set +CONFIG_RAW_DRIVER=y +CONFIG_MAX_RAW_DEVS=256 + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# +# CONFIG_DVB is not set + +# +# Graphics support +# +CONFIG_FB=y +# CONFIG_FB_CYBER2000 is not set +CONFIG_FB_OF=y +# CONFIG_FB_CT65550 is not set +# CONFIG_FB_IMSTT is not set +# CONFIG_FB_S3TRIO is not set +# CONFIG_FB_VGA16 is not set +# CONFIG_FB_RIVA is not set +CONFIG_FB_MATROX=y +CONFIG_FB_MATROX_MILLENIUM=y +CONFIG_FB_MATROX_MYSTIQUE=y +CONFIG_FB_MATROX_G450=y +CONFIG_FB_MATROX_G100=y +CONFIG_FB_MATROX_MULTIHEAD=y +# CONFIG_FB_RADEON is not set +# CONFIG_FB_ATY128 is not set +# CONFIG_FB_ATY is not set +# CONFIG_FB_SIS is not set +# CONFIG_FB_NEOMAGIC is not set +# CONFIG_FB_KYRO is not set +# CONFIG_FB_3DFX is not set +# CONFIG_FB_VOODOO1 is not set +# CONFIG_FB_TRIDENT is not set +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_PCI_CONSOLE=y +# CONFIG_FONTS is not set +CONFIG_FONT_8x8=y +CONFIG_FONT_8x16=y + +# +# Logo configuration +# +CONFIG_LOGO=y +CONFIG_LOGO_LINUX_MONO=y +CONFIG_LOGO_LINUX_VGA16=y +CONFIG_LOGO_LINUX_CLUT224=y + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB is not set + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +CONFIG_EXT2_FS_XATTR=y +CONFIG_EXT2_FS_POSIX_ACL=y +# CONFIG_EXT2_FS_SECURITY is not set +CONFIG_EXT3_FS=y +CONFIG_EXT3_FS_XATTR=y +CONFIG_EXT3_FS_POSIX_ACL=y +# CONFIG_EXT3_FS_SECURITY is not set +CONFIG_JBD=y +# CONFIG_JBD_DEBUG is not set +CONFIG_FS_MBCACHE=y +CONFIG_REISERFS_FS=y +# CONFIG_REISERFS_CHECK is not set +# CONFIG_REISERFS_PROC_INFO is not set +CONFIG_JFS_FS=y +CONFIG_JFS_POSIX_ACL=y +# CONFIG_JFS_DEBUG is not set +# CONFIG_JFS_STATISTICS is not set +CONFIG_FS_POSIX_ACL=y +CONFIG_XFS_FS=m +# CONFIG_XFS_RT is not set +# CONFIG_XFS_QUOTA is not set +# CONFIG_XFS_SECURITY is not set +CONFIG_XFS_POSIX_ACL=y +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +CONFIG_AUTOFS_FS=m +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +CONFIG_ISO9660_FS=y +# CONFIG_JOLIET is not set +# CONFIG_ZISOFS is not set +CONFIG_UDF_FS=m + +# +# DOS/FAT/NT Filesystems +# +CONFIG_FAT_FS=y +CONFIG_MSDOS_FS=y +CONFIG_VFAT_FS=y +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +# CONFIG_DEVFS_FS is not set +CONFIG_DEVPTS_FS=y +CONFIG_DEVPTS_FS_XATTR=y +# CONFIG_DEVPTS_FS_SECURITY is not set +CONFIG_TMPFS=y +CONFIG_HUGETLBFS=y +CONFIG_HUGETLB_PAGE=y +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +CONFIG_CRAMFS=y +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Network File Systems +# +CONFIG_NFS_FS=y +CONFIG_NFS_V3=y +CONFIG_NFS_V4=y +# CONFIG_NFS_DIRECTIO is not set +CONFIG_NFSD=y +CONFIG_NFSD_V3=y +CONFIG_NFSD_V4=y +CONFIG_NFSD_TCP=y +CONFIG_LOCKD=y +CONFIG_LOCKD_V4=y +CONFIG_EXPORTFS=y +CONFIG_SUNRPC=y +CONFIG_SUNRPC_GSS=m +CONFIG_RPCSEC_GSS_KRB5=m +# CONFIG_SMB_FS is not set +CONFIG_CIFS=m +# CONFIG_NCP_FS is not set +# CONFIG_CODA_FS is not set +# CONFIG_INTERMEZZO_FS is not set +# CONFIG_AFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +CONFIG_NLS=y +CONFIG_NLS_DEFAULT="iso8859-1" +# CONFIG_NLS_CODEPAGE_437 is not set +# CONFIG_NLS_CODEPAGE_737 is not set +# CONFIG_NLS_CODEPAGE_775 is not set +# CONFIG_NLS_CODEPAGE_850 is not set +# CONFIG_NLS_CODEPAGE_852 is not set +# CONFIG_NLS_CODEPAGE_855 is not set +# CONFIG_NLS_CODEPAGE_857 is not set +# CONFIG_NLS_CODEPAGE_860 is not set +# CONFIG_NLS_CODEPAGE_861 is not set +# CONFIG_NLS_CODEPAGE_862 is not set +# CONFIG_NLS_CODEPAGE_863 is not set +# CONFIG_NLS_CODEPAGE_864 is not set +# CONFIG_NLS_CODEPAGE_865 is not set +# CONFIG_NLS_CODEPAGE_866 is not set +# CONFIG_NLS_CODEPAGE_869 is not set +# CONFIG_NLS_CODEPAGE_936 is not set +# CONFIG_NLS_CODEPAGE_950 is not set +# CONFIG_NLS_CODEPAGE_932 is not set +# CONFIG_NLS_CODEPAGE_949 is not set +# CONFIG_NLS_CODEPAGE_874 is not set +# CONFIG_NLS_ISO8859_8 is not set +# CONFIG_NLS_CODEPAGE_1250 is not set +# CONFIG_NLS_CODEPAGE_1251 is not set +# CONFIG_NLS_ISO8859_1 is not set +# CONFIG_NLS_ISO8859_2 is not set +# CONFIG_NLS_ISO8859_3 is not set +# CONFIG_NLS_ISO8859_4 is not set +# CONFIG_NLS_ISO8859_5 is not set +# CONFIG_NLS_ISO8859_6 is not set +# CONFIG_NLS_ISO8859_7 is not set +# CONFIG_NLS_ISO8859_9 is not set +# CONFIG_NLS_ISO8859_13 is not set +# CONFIG_NLS_ISO8859_14 is not set +# CONFIG_NLS_ISO8859_15 is not set +# CONFIG_NLS_KOI8_R is not set +# CONFIG_NLS_KOI8_U is not set +# CONFIG_NLS_UTF8 is not set + +# +# Profiling support +# +CONFIG_PROFILING=y +CONFIG_OPROFILE=y + +# +# Kernel hacking +# +CONFIG_DEBUG_KERNEL=y +# CONFIG_DEBUG_SLAB is not set +CONFIG_MAGIC_SYSRQ=y +CONFIG_XMON=y +CONFIG_XMON_DEFAULT=y +# CONFIG_PPCDBG is not set +# CONFIG_DEBUG_INFO is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +CONFIG_CRYPTO=y +CONFIG_CRYPTO_HMAC=y +CONFIG_CRYPTO_NULL=m +CONFIG_CRYPTO_MD4=m +CONFIG_CRYPTO_MD5=m +CONFIG_CRYPTO_SHA1=m +CONFIG_CRYPTO_SHA256=m +CONFIG_CRYPTO_SHA512=m +CONFIG_CRYPTO_DES=m +CONFIG_CRYPTO_BLOWFISH=m +CONFIG_CRYPTO_TWOFISH=m +CONFIG_CRYPTO_SERPENT=m +CONFIG_CRYPTO_AES=m +CONFIG_CRYPTO_CAST5=m +CONFIG_CRYPTO_CAST6=m +CONFIG_CRYPTO_DEFLATE=m +CONFIG_CRYPTO_TEST=m + +# +# Library routines +# +CONFIG_CRC32=y +CONFIG_ZLIB_INFLATE=y +CONFIG_ZLIB_DEFLATE=m diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/Makefile linux-2.6.3-rc3/arch/ppc64/kernel/Makefile --- linux-2.6.3-rc2/arch/ppc64/kernel/Makefile 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/Makefile 2004-02-14 19:30:59.000000000 -0800 @@ -10,9 +10,11 @@ align.o semaphore.o bitops.o stab.o pacaData.o \ udbg.o binfmt_elf32.o sys_ppc32.o ioctl32.o \ ptrace32.o signal32.o pmc.o rtc.o init_task.o \ - lmb.o cputable.o + lmb.o cputable.o cpu_setup_power4.o idle_power4.o -obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o +obj-$(CONFIG_PPC_OF) += of_device.o + +obj-$(CONFIG_PCI) += pci.o pci_dn.o pci_dma.o pci_dma_direct.o ifdef CONFIG_PPC_ISERIES obj-$(CONFIG_PCI) += iSeries_pci.o iSeries_pci_reset.o \ @@ -27,7 +29,7 @@ proc_pmc.o obj-$(CONFIG_PPC_PSERIES) += pSeries_pci.o pSeries_lpar.o pSeries_hvCall.o \ - eeh.o nvram.o rtasd.o ras.o \ + eeh.o nvram.o pSeries_nvram.o rtasd.o ras.o \ open_pic.o xics.o pSeries_htab.o rtas.o \ chrp_setup.o i8259.o prom.o vio.o @@ -39,6 +41,14 @@ obj-$(CONFIG_SCANLOG) += scanlog.o obj-$(CONFIG_VIOPATH) += viopath.o obj-$(CONFIG_LPARCFG) += lparcfg.o -obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o +obj-$(CONFIG_HVC_CONSOLE) += hvconsole.o +obj-$(CONFIG_BOOTX_TEXT) += btext.o + +obj-$(CONFIG_PPC_PMAC) += pmac_setup.o pmac_feature.o pmac_pci.o \ + pmac_time.o pmac_nvram.o pmac_low_i2c.o \ + open_pic_u3.o +ifdef CONFIG_SMP +obj-$(CONFIG_PPC_PMAC) += pmac_smp.o smp-tbsync.o +endif CFLAGS_ioctl32.o += -Ifs/ diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/btext.c linux-2.6.3-rc3/arch/ppc64/kernel/btext.c --- linux-2.6.3-rc2/arch/ppc64/kernel/btext.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/btext.c 2004-02-14 19:30:59.000000000 -0800 @@ -0,0 +1,748 @@ +/* + * Procedures for drawing on the screen early on in the boot process. + * + * Benjamin Herrenschmidt + */ +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef NO_SCROLL + +#ifndef NO_SCROLL +static void scrollscreen(void); +#endif + +static void draw_byte(unsigned char c, long locX, long locY); +static void draw_byte_32(unsigned char *bits, unsigned int *base, int rb); +static void draw_byte_16(unsigned char *bits, unsigned int *base, int rb); +static void draw_byte_8(unsigned char *bits, unsigned int *base, int rb); + +static int g_loc_X; +static int g_loc_Y; +static int g_max_loc_X; +static int g_max_loc_Y; + +unsigned long disp_BAT[2] __initdata = {0, 0}; + +#define cmapsz (16*256) + +static unsigned char vga_font[cmapsz]; + +int boot_text_mapped; +int force_printk_to_btext = 0; + +boot_infos_t disp_bi; + +extern char *klimit; + +/* This function will enable the early boot text when doing OF booting. This + * way, xmon output should work too + */ +void __init btext_setup_display(int width, int height, int depth, int pitch, + unsigned long address) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y) = 0; + RELOC(g_max_loc_X) = width / 8; + RELOC(g_max_loc_Y) = height / 16; + bi->logicalDisplayBase = (unsigned char *)address; + bi->dispDeviceBase = (unsigned char *)address; + bi->dispDeviceRowBytes = pitch; + bi->dispDeviceDepth = depth; + bi->dispDeviceRect[0] = bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; + RELOC(boot_text_mapped) = 1; +} + +/* Here's a small text engine to use during early boot + * or for debugging purposes + * + * todo: + * + * - build some kind of vgacon with it to enable early printk + * - move to a separate file + * - add a few video driver hooks to keep in sync with display + * changes. + */ + +void map_boot_text(void) +{ + unsigned long base, offset, size; + boot_infos_t *bi = &disp_bi; + unsigned char *vbase; + + /* By default, we are no longer mapped */ + boot_text_mapped = 0; + if (bi->dispDeviceBase == 0) + return; + base = ((unsigned long) bi->dispDeviceBase) & 0xFFFFF000UL; + offset = ((unsigned long) bi->dispDeviceBase) - base; + size = bi->dispDeviceRowBytes * bi->dispDeviceRect[3] + offset + + bi->dispDeviceRect[0]; + vbase = __ioremap(base, size, _PAGE_NO_CACHE); + if (vbase == 0) + return; + bi->logicalDisplayBase = vbase + offset; + boot_text_mapped = 1; +} + +/* Calc the base address of a given point (x,y) */ +static unsigned char * calc_base(boot_infos_t *bi, int x, int y) +{ + unsigned char *base; + + base = bi->logicalDisplayBase; + if (base == 0) + base = bi->dispDeviceBase; + base += (x + bi->dispDeviceRect[0]) * (bi->dispDeviceDepth >> 3); + base += (y + bi->dispDeviceRect[1]) * bi->dispDeviceRowBytes; + return base; +} + +/* Adjust the display to a new resolution */ +void btext_update_display(unsigned long phys, int width, int height, + int depth, int pitch) +{ + boot_infos_t *bi = &disp_bi; + + if (bi->dispDeviceBase == 0) + return; + + /* check it's the same frame buffer (within 256MB) */ + if ((phys ^ (unsigned long)bi->dispDeviceBase) & 0xf0000000) + return; + + bi->dispDeviceBase = (__u8 *) phys; + bi->dispDeviceRect[0] = 0; + bi->dispDeviceRect[1] = 0; + bi->dispDeviceRect[2] = width; + bi->dispDeviceRect[3] = height; + bi->dispDeviceDepth = depth; + bi->dispDeviceRowBytes = pitch; + if (boot_text_mapped) { + iounmap(bi->logicalDisplayBase); + boot_text_mapped = 0; + } + map_boot_text(); + g_loc_X = 0; + g_loc_Y = 0; + g_max_loc_X = width / 8; + g_max_loc_Y = height / 16; +} + +void btext_clearscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + unsigned long *base = (unsigned long *)calc_base(bi, 0, 0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 3; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1]); i++) + { + unsigned long *ptr = base; + for(j=width; j; --j) + *(ptr++) = 0; + base += (bi->dispDeviceRowBytes >> 3); + } +} + +#ifndef NO_SCROLL +static void scrollscreen(void) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + unsigned long *src = (unsigned long *)calc_base(bi,0,16); + unsigned long *dst = (unsigned long *)calc_base(bi,0,0); + unsigned long width = ((bi->dispDeviceRect[2] - bi->dispDeviceRect[0]) * + (bi->dispDeviceDepth >> 3)) >> 3; + int i,j; + + for (i=0; i<(bi->dispDeviceRect[3] - bi->dispDeviceRect[1] - 16); i++) + { + unsigned long *src_ptr = src; + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = *(src_ptr++); + src += (bi->dispDeviceRowBytes >> 3); + dst += (bi->dispDeviceRowBytes >> 3); + } + for (i=0; i<16; i++) + { + unsigned long *dst_ptr = dst; + for(j=width; j; --j) + *(dst_ptr++) = 0; + dst += (bi->dispDeviceRowBytes >> 3); + } +} +#endif /* ndef NO_SCROLL */ + +void btext_drawchar(char c) +{ + unsigned long offset = reloc_offset(); + int cline = 0; +#ifdef NO_SCROLL + int x; +#endif + if (!RELOC(boot_text_mapped)) + return; + + switch (c) { + case '\b': + if (RELOC(g_loc_X) > 0) + --RELOC(g_loc_X); + break; + case '\t': + RELOC(g_loc_X) = (RELOC(g_loc_X) & -8) + 8; + break; + case '\r': + RELOC(g_loc_X) = 0; + break; + case '\n': + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + break; + default: + draw_byte(c, RELOC(g_loc_X)++, RELOC(g_loc_Y)); + } + if (RELOC(g_loc_X) >= RELOC(g_max_loc_X)) { + RELOC(g_loc_X) = 0; + RELOC(g_loc_Y)++; + cline = 1; + } +#ifndef NO_SCROLL + while (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) { + scrollscreen(); + RELOC(g_loc_Y)--; + } +#else + /* wrap around from bottom to top of screen so we don't + waste time scrolling each line. -- paulus. */ + if (RELOC(g_loc_Y) >= RELOC(g_max_loc_Y)) + RELOC(g_loc_Y) = 0; + if (cline) { + for (x = 0; x < RELOC(g_max_loc_X); ++x) + draw_byte(' ', x, RELOC(g_loc_Y)); + } +#endif +} + +void btext_drawstring(const char *c) +{ + unsigned long offset = reloc_offset(); + + if (!RELOC(boot_text_mapped)) + return; + while (*c) + btext_drawchar(*c++); +} + +void btext_drawhex(unsigned long v) +{ + unsigned long offset = reloc_offset(); + char *hex_table = RELOC("0123456789abcdef"); + + if (!RELOC(boot_text_mapped)) + return; + btext_drawchar(hex_table[(v >> 60) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 56) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 52) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 48) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 44) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 40) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 36) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 32) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 28) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 24) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 20) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 16) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 12) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 8) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 4) & 0x0000000FUL]); + btext_drawchar(hex_table[(v >> 0) & 0x0000000FUL]); + btext_drawchar(' '); +} + +static void draw_byte(unsigned char c, long locX, long locY) +{ + unsigned long offset = reloc_offset(); + boot_infos_t* bi = PTRRELOC(&disp_bi); + unsigned char *base = calc_base(bi, locX << 3, locY << 4); + unsigned char *font = PTRRELOC(&vga_font[((unsigned int)c) * 16]); + int rb = bi->dispDeviceRowBytes; + +#if 0 + switch(bi->dispDeviceDepth) { + case 24: + case 32: + draw_byte_32(font, (unsigned int *)base, rb); + break; + case 15: + case 16: + draw_byte_16(font, (unsigned int *)base, rb); + break; + case 8: + draw_byte_8(font, (unsigned int *)base, rb); + break; + } +#else + if(bi->dispDeviceDepth == 24 || + bi->dispDeviceDepth == 32) { + draw_byte_32(font, (unsigned int *)base, rb); + } else if(bi->dispDeviceDepth == 15 || + bi->dispDeviceDepth == 16) { + draw_byte_16(font, (unsigned int *)base, rb); + } else if(bi->dispDeviceDepth == 8) { + draw_byte_8(font, (unsigned int *)base, rb); + } +#endif +} + +static unsigned int expand_bits_8[16] = { + 0x00000000, + 0x000000ff, + 0x0000ff00, + 0x0000ffff, + 0x00ff0000, + 0x00ff00ff, + 0x00ffff00, + 0x00ffffff, + 0xff000000, + 0xff0000ff, + 0xff00ff00, + 0xff00ffff, + 0xffff0000, + 0xffff00ff, + 0xffffff00, + 0xffffffff +}; + +static unsigned int expand_bits_16[4] = { + 0x00000000, + 0x0000ffff, + 0xffff0000, + 0xffffffff +}; + + +static void draw_byte_32(unsigned char *font, unsigned int *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (-(bits >> 7) & fg) ^ bg; + base[1] = (-((bits >> 6) & 1) & fg) ^ bg; + base[2] = (-((bits >> 5) & 1) & fg) ^ bg; + base[3] = (-((bits >> 4) & 1) & fg) ^ bg; + base[4] = (-((bits >> 3) & 1) & fg) ^ bg; + base[5] = (-((bits >> 2) & 1) & fg) ^ bg; + base[6] = (-((bits >> 1) & 1) & fg) ^ bg; + base[7] = (-(bits & 1) & fg) ^ bg; + base = (unsigned int *) ((char *)base + rb); + } +} + +static void draw_byte_16(unsigned char *font, unsigned int *base, int rb) +{ + int l, bits; + int fg = 0xFFFFFFFFUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned int *eb = PTRRELOC((int *)expand_bits_16); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 6] & fg) ^ bg; + base[1] = (eb[(bits >> 4) & 3] & fg) ^ bg; + base[2] = (eb[(bits >> 2) & 3] & fg) ^ bg; + base[3] = (eb[bits & 3] & fg) ^ bg; + base = (unsigned int *) ((char *)base + rb); + } +} + +static void draw_byte_8(unsigned char *font, unsigned int *base, int rb) +{ + int l, bits; + int fg = 0x0F0F0F0FUL; + int bg = 0x00000000UL; + unsigned long offset = reloc_offset(); + unsigned int *eb = PTRRELOC((int *)expand_bits_8); + + for (l = 0; l < 16; ++l) + { + bits = *font++; + base[0] = (eb[bits >> 4] & fg) ^ bg; + base[1] = (eb[bits & 0xf] & fg) ^ bg; + base = (unsigned int *) ((char *)base + rb); + } +} + +static unsigned char vga_font[cmapsz] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xbd, +0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xff, +0xdb, 0xff, 0xff, 0xc3, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x6c, 0xfe, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x7c, 0xfe, +0x7c, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, +0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, +0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, +0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x1e, 0x0e, +0x1a, 0x32, 0x78, 0xcc, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x33, 0x3f, 0x30, 0x30, 0x30, +0x30, 0x70, 0xf0, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x63, +0x7f, 0x63, 0x63, 0x63, 0x63, 0x67, 0xe7, 0xe6, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfe, 0xf8, +0xf0, 0xe0, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x06, 0x0e, +0x1e, 0x3e, 0xfe, 0x3e, 0x1e, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, +0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xdb, +0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0x60, 0x38, 0x6c, 0xc6, 0xc6, 0x6c, 0x38, 0x0c, 0xc6, +0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0xfe, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, +0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, +0xc0, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x24, 0x66, 0xff, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x38, 0x7c, 0x7c, 0xfe, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x7c, +0x38, 0x38, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, +0x6c, 0xfe, 0x6c, 0x6c, 0x6c, 0xfe, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x7c, 0xc6, 0xc2, 0xc0, 0x7c, 0x06, 0x06, 0x86, 0xc6, 0x7c, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2, 0xc6, 0x0c, 0x18, +0x30, 0x60, 0xc6, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, +0x6c, 0x38, 0x76, 0xdc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x30, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x18, +0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x80, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xce, 0xde, 0xf6, 0xe6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0x06, 0x06, 0x3c, 0x06, 0x06, 0x06, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x1c, 0x3c, 0x6c, 0xcc, 0xfe, +0x0c, 0x0c, 0x0c, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xfc, 0x06, 0x06, 0x06, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x60, 0xc0, 0xc0, 0xfc, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0x06, 0x06, 0x0c, 0x18, +0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x06, 0x06, 0x0c, 0x78, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, +0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, +0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, +0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0x0c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xde, 0xde, +0xde, 0xdc, 0xc0, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x66, 0x66, 0x66, 0x66, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0xc2, 0xc0, 0xc0, 0xc0, +0xc0, 0xc2, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x6c, +0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x6c, 0xf8, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, 0x60, 0x62, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x66, 0x62, 0x68, 0x78, 0x68, +0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xde, 0xc6, 0xc6, 0x66, 0x3a, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x0c, +0x0c, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0xcc, 0x78, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xe6, 0x66, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0x66, 0xe6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x60, 0x60, 0x60, 0x60, 0x60, +0x60, 0x62, 0x66, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xe7, +0xff, 0xff, 0xdb, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, +0x66, 0x66, 0x7c, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, +0x0c, 0x0e, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, 0x66, 0x7c, 0x6c, +0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, +0xc6, 0x60, 0x38, 0x0c, 0x06, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xdb, 0x99, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xc3, 0xc3, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x66, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0x66, 0x3c, 0x18, 0x18, +0x3c, 0x66, 0xc3, 0xc3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xff, 0xc3, 0x86, 0x0c, 0x18, 0x30, 0x60, 0xc1, 0xc3, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, +0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, +0xc0, 0xe0, 0x70, 0x38, 0x1c, 0x0e, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, +0x30, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x78, 0x6c, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x0c, 0x0c, 0x3c, 0x6c, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xcc, 0x78, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x6c, 0x76, 0x66, 0x66, 0x66, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x18, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x06, 0x00, 0x0e, 0x06, 0x06, +0x06, 0x06, 0x06, 0x06, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0xe0, 0x60, +0x60, 0x66, 0x6c, 0x78, 0x78, 0x6c, 0x66, 0xe6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe6, 0xff, 0xdb, +0xdb, 0xdb, 0xdb, 0xdb, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x66, 0x66, +0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0x0c, 0x1e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xdc, 0x76, 0x66, 0x60, 0x60, 0x60, 0xf0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0x60, +0x38, 0x0c, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x30, +0x30, 0xfc, 0x30, 0x30, 0x30, 0x30, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0xc3, 0xc3, +0xc3, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc3, 0xc3, 0xc3, 0xdb, 0xdb, 0xff, 0x66, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0x3c, 0x66, 0xc3, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xfe, 0xcc, 0x18, 0x30, 0x60, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x18, +0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, +0xc6, 0xc6, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, +0xc2, 0xc0, 0xc0, 0xc0, 0xc2, 0x66, 0x3c, 0x0c, 0x06, 0x7c, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xcc, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, +0x00, 0x78, 0x0c, 0x7c, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x60, 0x60, 0x66, 0x3c, 0x0c, 0x06, +0x3c, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xfe, +0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0xc0, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x38, 0x18, 0x18, +0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x66, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x60, 0x30, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, +0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x38, 0x00, +0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x18, 0x30, 0x60, 0x00, 0xfe, 0x66, 0x60, 0x7c, 0x60, 0x60, 0x66, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, +0x7e, 0xd8, 0xdc, 0x77, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x6c, +0xcc, 0xcc, 0xfe, 0xcc, 0xcc, 0xcc, 0xcc, 0xce, 0x00, 0x00, 0x00, 0x00, +0x00, 0x10, 0x38, 0x6c, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x7c, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, +0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x30, 0x78, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, +0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, +0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7e, 0x06, 0x0c, 0x78, 0x00, +0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, +0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, +0xc3, 0xc0, 0xc0, 0xc0, 0xc3, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x38, 0x6c, 0x64, 0x60, 0xf0, 0x60, 0x60, 0x60, 0x60, 0xe6, 0xfc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc3, 0x66, 0x3c, 0x18, 0xff, 0x18, +0xff, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x66, 0x66, +0x7c, 0x62, 0x66, 0x6f, 0x66, 0x66, 0x66, 0xf3, 0x00, 0x00, 0x00, 0x00, +0x00, 0x0e, 0x1b, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, +0xd8, 0x70, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0x78, 0x0c, 0x7c, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, +0x00, 0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x18, 0x30, 0x60, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x60, 0x00, 0xcc, 0xcc, 0xcc, +0xcc, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, +0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00, +0x76, 0xdc, 0x00, 0xc6, 0xe6, 0xf6, 0xfe, 0xde, 0xce, 0xc6, 0xc6, 0xc6, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x6c, 0x6c, 0x3e, 0x00, 0x7e, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x30, 0x30, 0x00, 0x30, 0x30, 0x60, 0xc0, 0xc6, 0xc6, 0x7c, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc0, +0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0xfe, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, 0x60, 0xce, 0x9b, 0x06, +0x0c, 0x1f, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0xc2, 0xc6, 0xcc, 0x18, 0x30, +0x66, 0xce, 0x96, 0x3e, 0x06, 0x06, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, +0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, +0x6c, 0xd8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x44, 0x11, 0x44, +0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, 0x11, 0x44, +0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, +0x55, 0xaa, 0x55, 0xaa, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, +0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0xdd, 0x77, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x06, 0xf6, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x37, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xf7, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, +0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, +0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, +0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, +0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, +0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x76, 0xdc, 0xd8, 0xd8, 0xd8, 0xdc, 0x76, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x78, 0xcc, 0xcc, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xc6, 0xcc, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xc6, 0xc6, 0xc0, 0xc0, 0xc0, +0xc0, 0xc0, 0xc0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xfe, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0xfe, 0xc6, 0x60, 0x30, 0x18, 0x30, 0x60, 0xc6, 0xfe, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xd8, 0xd8, +0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x66, 0x66, 0x66, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xc0, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, +0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, +0x6c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x38, 0x6c, 0xc6, 0xc6, 0xc6, 0x6c, 0x6c, 0x6c, 0x6c, 0xee, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x18, 0x0c, 0x3e, 0x66, +0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x06, 0x7e, 0xdb, 0xdb, 0xf3, 0x7e, 0x60, 0xc0, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x30, 0x60, 0x60, 0x7c, 0x60, +0x60, 0x60, 0x30, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, +0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, 0x00, 0xfe, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, +0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, +0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1b, 0x1b, 0x1b, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, +0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0xd8, 0x70, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, +0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x6c, 0x6c, +0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, +0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x6c, 0x3c, 0x1c, 0x00, 0x00, 0x00, 0x00, +0x00, 0xd8, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xd8, 0x30, 0x60, 0xc8, 0xf8, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, +}; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/chrp_setup.c linux-2.6.3-rc3/arch/ppc64/kernel/chrp_setup.c --- linux-2.6.3-rc2/arch/ppc64/kernel/chrp_setup.c 2004-02-03 19:43:11.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/chrp_setup.c 2004-02-14 19:30:59.000000000 -0800 @@ -67,9 +67,10 @@ void chrp_progress(char *, unsigned short); -extern void openpic_init_IRQ(void); +extern void pSeries_init_openpic(void); extern void find_and_init_phbs(void); +extern void pSeries_final_fixup(void); extern void pSeries_get_boot_time(struct rtc_time *rtc_time); extern void pSeries_get_rtc_time(struct rtc_time *rtc_time); @@ -178,6 +179,10 @@ #ifdef CONFIG_DUMMY_CONSOLE conswitchp = &dummy_con; #endif + +#ifdef CONFIG_PPC_PSERIES + pSeries_nvram_init(); +#endif } void __init @@ -252,7 +257,7 @@ ppc_md.setup_residual = NULL; ppc_md.get_cpuinfo = chrp_get_cpuinfo; if(naca->interrupt_controller == IC_OPEN_PIC) { - ppc_md.init_IRQ = openpic_init_IRQ; + ppc_md.init_IRQ = pSeries_init_openpic; ppc_md.get_irq = openpic_get_irq; } else { ppc_md.init_IRQ = xics_init_IRQ; @@ -261,6 +266,8 @@ ppc_md.init = chrp_init2; + ppc_md.pcibios_fixup = pSeries_final_fixup; + ppc_md.restart = rtas_restart; ppc_md.power_off = rtas_power_off; ppc_md.halt = rtas_halt; @@ -272,9 +279,6 @@ ppc_md.progress = chrp_progress; - ppc_md.nvram_read = pSeries_nvram_read; - ppc_md.nvram_write = pSeries_nvram_write; - /* Build up the firmware_features bitmask field * using contents of device-tree/ibm,hypertas-functions. * Ultimately this functionality may be moved into prom.c prom_init(). diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/cpu_setup_power4.S linux-2.6.3-rc3/arch/ppc64/kernel/cpu_setup_power4.S --- linux-2.6.3-rc2/arch/ppc64/kernel/cpu_setup_power4.S 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/cpu_setup_power4.S 2004-02-14 19:30:59.000000000 -0800 @@ -0,0 +1,179 @@ +/* + * This file contains low level CPU setup functions. + * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +_GLOBAL(__power4_cpu_preinit) + /* + * On the PPC970, we have to turn off real-mode cache inhibit + * early, before we first turn the MMU off. + */ + mfspr r0,SPRN_PVR + srwi r0,r0,16 + cmpwi r0,0x39 + bnelr + + li r0,0 + sync + mtspr SPRN_HID4,r0 + isync + sync + mtspr SPRN_HID5,r0 + isync + + mfspr r0,SPRN_HID1 + li r11,0x1200 /* enable i-fetch cacheability */ + sldi r11,r11,44 /* and prefetch */ + or r0,r0,r11 + mtspr SPRN_HID1,r0 + mtspr SPRN_HID1,r0 + isync + li r0,0 + sync + mtspr SPRN_HIOR,0 /* Clear interrupt prefix */ + isync + blr + +_GLOBAL(__setup_cpu_power4) + blr + +_GLOBAL(__setup_cpu_ppc970) + mfspr r0,SPRN_HID0 + li r11,5 /* clear DOZE and SLEEP */ + rldimi r0,r11,52,8 /* set NAP and DPM */ + mtspr SPRN_HID0,r0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + mfspr r0,SPRN_HID0 + sync + isync + blr + +/* Definitions for the table use to save CPU states */ +#define CS_HID0 0 +#define CS_HID1 8 +#define CS_HID4 16 +#define CS_HID5 24 +#define CS_SIZE 32 + + .data + .balign L1_CACHE_BYTES,0 +cpu_state_storage: + .space CS_SIZE + .balign L1_CACHE_BYTES,0 + .text + +/* Called in normal context to backup CPU 0 state. This + * does not include cache settings. This function is also + * called for machine sleep. This does not include the MMU + * setup, BATs, etc... but rather the "special" registers + * like HID0, HID1, HID4, etc... + */ +_GLOBAL(__save_cpu_setup) + /* Some CR fields are volatile, we back it up all */ + mfcr r7 + + /* Get storage ptr */ + LOADADDR(r5,cpu_state_storage) + + /* We only deal with 970 for now */ + mfspr r0,SPRN_PVR + srwi r0,r0,16 + cmpwi r0,0x39 + bne 1f + + /* Save HID0,1,4 and 5 */ + mfspr r3,SPRN_HID0 + std r3,CS_HID0(r5) + mfspr r3,SPRN_HID1 + std r3,CS_HID1(r5) + mfspr r3,SPRN_HID4 + std r3,CS_HID4(r5) + mfspr r3,SPRN_HID5 + std r3,CS_HID5(r5) + +1: + mtcr r7 + blr + +/* Called with no MMU context (typically MSR:IR/DR off) to + * restore CPU state as backed up by the previous + * function. This does not include cache setting + */ +_GLOBAL(__restore_cpu_setup) + /* Get storage ptr (FIXME when using anton reloc as we + * are running with translation disabled here + */ + LOADADDR(r5,cpu_state_storage) + + /* We only deal with 970 for now */ + mfspr r0,SPRN_PVR + srwi r0,r0,16 + cmpwi r0,0x39 + bne 1f + + /* Clear interrupt prefix */ + li r0,0 + sync + mtspr SPRN_HIOR,0 + isync + + /* Restore HID0 */ + ld r3,CS_HID0(r5) + sync + isync + mtspr SPRN_HID0,r3 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + mfspr r3,SPRN_HID0 + sync + isync + + /* Restore HID1 */ + ld r3,CS_HID1(r5) + sync + isync + mtspr SPRN_HID1,r3 + mtspr SPRN_HID1,r3 + sync + isync + + /* Restore HID4 */ + ld r3,CS_HID4(r5) + sync + isync + mtspr SPRN_HID4,r3 + sync + isync + + /* Restore HID5 */ + ld r3,CS_HID5(r5) + sync + isync + mtspr SPRN_HID5,r3 + sync + isync +1: + blr + diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/cputable.c linux-2.6.3-rc3/arch/ppc64/kernel/cputable.c --- linux-2.6.3-rc2/arch/ppc64/kernel/cputable.c 2004-02-03 19:43:06.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/cputable.c 2004-02-14 19:30:59.000000000 -0800 @@ -30,6 +30,7 @@ */ extern void __setup_cpu_power3(unsigned long offset, struct cpu_spec* spec); extern void __setup_cpu_power4(unsigned long offset, struct cpu_spec* spec); +extern void __setup_cpu_ppc970(unsigned long offset, struct cpu_spec* spec); /* We only set the altivec features if the kernel was compiled with altivec @@ -119,10 +120,10 @@ { /* PPC970 */ 0xffff0000, 0x00390000, "PPC970", CPU_FTR_SPLIT_ID_CACHE | CPU_FTR_USE_TB | CPU_FTR_HPTE_TABLE | - CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP, + CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_ALTIVEC_COMP | CPU_FTR_CAN_NAP, COMMON_USER_PPC64 | PPC_FEATURE_HAS_ALTIVEC_COMP, 128, 128, - __setup_cpu_power4, + __setup_cpu_ppc970, COMMON_PPC64_FW }, { /* Power5 */ diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/head.S linux-2.6.3-rc3/arch/ppc64/kernel/head.S --- linux-2.6.3-rc2/arch/ppc64/kernel/head.S 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/head.S 2004-02-14 19:30:59.000000000 -0800 @@ -1320,6 +1320,16 @@ #endif #ifdef CONFIG_PPC_PSERIES + +_STATIC(mmu_off) + mfmsr r3 + andi. r0,r3,MSR_IR|MSR_DR + beqlr + andc r3,r3,r0 + mtspr SRR0,r4 + mtspr SRR1,r3 + sync + rfid _GLOBAL(__start_initialization_pSeries) mr r31,r3 /* save parameters */ mr r30,r4 @@ -1339,33 +1349,27 @@ /* Relocate the TOC from a virt addr to a real addr */ sub r2,r2,r3 - /* DRENG / PPPBBB Fix the following comment!!! -Peter */ - /* The following copies the first 0x100 bytes of code from the */ - /* load addr to physical addr 0x0. This code causes secondary */ - /* processors to spin until a flag in the PACA is set. This */ - /* is done at this time rather than with the entire kernel */ - /* relocation which is done below because we need to cause the */ - /* processors to spin on code that is not going to move while OF */ - /* is still alive. Although the spin code is not actually run on */ - /* a uniprocessor, we always do this copy. */ - SET_REG_TO_CONST(r4, KERNELBASE)/* Src addr */ - sub r4,r4,r3 /* current address of __start */ - /* the source addr */ - li r3,0 /* Dest addr */ - li r5,0x100 /* # bytes of memory to copy */ - li r6,0 /* Destination offset */ - bl .copy_and_flush /* copy the first 0x100 bytes */ - + /* Save parameters */ mr r3,r31 mr r4,r30 mr r5,r29 mr r6,r28 mr r7,r27 + /* Do all of the interaction with OF client interface */ bl .prom_init + mr r23,r3 /* Save phys address we are running at */ + + /* Setup some critical 970 SPRs before switching MMU off */ + bl .__power4_cpu_preinit li r24,0 /* cpu # */ + /* Switch off MMU if not already */ + LOADADDR(r4, .__after_prom_start - KERNELBASE) + add r4,r4,r23 + bl .mmu_off + /* * At this point, r3 contains the physical address we are running at, * returned by prom_init() @@ -1390,6 +1394,7 @@ li r3,0 /* target addr */ + // XXX FIXME: Use phys returned by OF (r23) sub r4,r27,r26 /* source addr */ /* current address of _start */ /* i.e. where we are running */ @@ -1425,7 +1430,7 @@ * * Note: this routine *only* clobbers r0, r6 and lr */ -_STATIC(copy_and_flush) +_GLOBAL(copy_and_flush) addi r5,r5,-8 addi r6,r6,-8 4: li r0,16 /* Use the least common */ @@ -1675,6 +1680,58 @@ #endif /* CONFIG_ALTIVEC */ #ifdef CONFIG_SMP +#ifdef CONFIG_PPC_PMAC +/* + * On PowerMac, secondary processors starts from the reset vector, which + * is temporarily turned into a call to one of the functions below. + */ + .section ".text"; + .align 2 ; + + .globl pmac_secondary_start_1 +pmac_secondary_start_1: + li r24, 1 + b .pmac_secondary_start + + .globl pmac_secondary_start_2 +pmac_secondary_start_2: + li r24, 2 + b .pmac_secondary_start + + .globl pmac_secondary_start_3 +pmac_secondary_start_3: + li r24, 3 + b .pmac_secondary_start + +_GLOBAL(pmac_secondary_start) + /* turn on 64-bit mode */ + bl .enable_64b_mode + isync + + /* Copy some CPU settings from CPU 0 */ + bl .__restore_cpu_setup + + /* pSeries do that early though I don't think we really need it */ + mfmsr r3 + ori r3,r3,MSR_RI + mtmsrd r3 /* RI on */ + + /* Set up a paca value for this processor. */ + LOADADDR(r4, paca) /* Get base vaddr of paca array */ + mulli r13,r24,PACA_SIZE /* Calculate vaddr of right paca */ + add r13,r13,r4 /* for this processor. */ + mtspr SPRG3,r13 /* Save vaddr of paca in SPRG3 */ + + /* Create a temp kernel stack for use before relocation is on. */ + mr r1,r13 + addi r1,r1,PACAGUARD + addi r1,r1,0x1000 + subi r1,r1,STACK_FRAME_OVERHEAD + + b .__secondary_start + +#endif /* CONFIG_PPC_PMAC */ + /* * This function is called after the master CPU has released the * secondary processors. The execution environment is relocation off. @@ -1870,6 +1927,12 @@ li r0,0 stdu r0,-STACK_FRAME_OVERHEAD(r1) + /* set up the TOC (physical address) */ + LOADADDR(r2,__toc_start) + addi r2,r2,0x4000 + addi r2,r2,0x4000 + sub r2,r2,r26 + LOADADDR(r3,cpu_specs) sub r3,r3,r26 LOADADDR(r4,cur_cpu_spec) @@ -1877,12 +1940,6 @@ mr r5,r26 bl .identify_cpu - /* set up the TOC (physical address) */ - LOADADDR(r2,__toc_start) - addi r2,r2,0x4000 - addi r2,r2,0x4000 - sub r2,r2,r26 - /* Get the pointer to the segment table which is used by */ /* stab_initialize */ LOADADDR(r27, boot_cpuid) @@ -1926,7 +1983,8 @@ li r3,SYSTEMCFG_PHYS_ADDR /* r3 = ptr to systemcfg */ lwz r3,PLATFORM(r3) /* r3 = platform flags */ - cmpldi r3,PLATFORM_PSERIES + /* Test if bit 0 is set (LPAR bit) */ + andi. r3,r3,0x1 bne 98f LOADADDR(r6,_SDR1) /* Only if NOT LPAR */ sub r6,r6,r26 @@ -1938,11 +1996,12 @@ mtspr SRR0,r3 mtspr SRR1,r4 rfid -#endif /* CONFIG_PPC_PSERIES */ - +#endif /* CONFIG_PPC_PSERIES */ + /* This is where all platforms converge execution */ _STATIC(start_here_common) - + /* relocation is on at this point */ + /* The following code sets up the SP and TOC now that we are */ /* running with translation enabled. */ @@ -2013,8 +2072,6 @@ _GLOBAL(__setup_cpu_power3) blr -_GLOBAL(__setup_cpu_power4) - blr _GLOBAL(hmt_init) #ifdef CONFIG_HMT diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/iSeries_pci.c linux-2.6.3-rc3/arch/ppc64/kernel/iSeries_pci.c --- linux-2.6.3-rc2/arch/ppc64/kernel/iSeries_pci.c 2004-02-03 19:45:02.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/iSeries_pci.c 2004-02-14 19:31:00.000000000 -0800 @@ -241,9 +241,9 @@ } /* - * pcibios_final_fixup(void) + * iSeries_pci_final_fixup(void) */ -void __init pcibios_final_fixup(void) +void __init iSeries_pci_final_fixup(void) { struct pci_dev *pdev = NULL; struct iSeries_Device_Node *node; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/iSeries_setup.c linux-2.6.3-rc3/arch/ppc64/kernel/iSeries_setup.c --- linux-2.6.3-rc2/arch/ppc64/kernel/iSeries_setup.c 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/iSeries_setup.c 2004-02-14 19:31:00.000000000 -0800 @@ -63,10 +63,11 @@ static void build_iSeries_Memory_Map(void); static void setup_iSeries_cache_sizes(void); static void iSeries_bolt_kernel(unsigned long saddr, unsigned long eaddr); -void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa, - pte_t *ptep, unsigned hpteflags, unsigned bolted); +extern void build_valid_hpte(unsigned long vsid, unsigned long ea, unsigned long pa, + pte_t *ptep, unsigned hpteflags, unsigned bolted); static void iSeries_setup_dprofile(void); -void iSeries_setup_arch(void); +extern void iSeries_setup_arch(void); +extern void iSeries_pci_final_fixup(void); /* Global Variables */ static unsigned long procFreqHz; @@ -318,6 +319,8 @@ ppc_md.get_irq = iSeries_get_irq; ppc_md.init = NULL; + ppc_md.pcibios_fixup = iSeries_pci_final_fixup; + ppc_md.restart = iSeries_restart; ppc_md.power_off = iSeries_power_off; ppc_md.halt = iSeries_halt; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/idle.c linux-2.6.3-rc3/arch/ppc64/kernel/idle.c --- linux-2.6.3-rc2/arch/ppc64/kernel/idle.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/idle.c 2004-02-14 19:31:00.000000000 -0800 @@ -42,6 +42,7 @@ extern long cede_processor(void); extern long poll_pending(void); +extern void power4_idle(void); int (*idle_loop)(void); @@ -279,6 +280,17 @@ return 0; } +int native_idle(void) +{ + while(1) { + if (!need_resched()) + power4_idle(); + if (need_resched()) + schedule(); + } + return 0; +} + int idle_setup(void) { #ifdef CONFIG_PPC_ISERIES @@ -297,6 +309,9 @@ printk("idle = default_idle\n"); idle_loop = default_idle; } + } else if (systemcfg->platform == PLATFORM_POWERMAC) { + printk("idle = native_idle\n"); + idle_loop = native_idle; } else { printk("idle_setup: unknown platform, use default_idle\n"); idle_loop = default_idle; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/idle_power4.S linux-2.6.3-rc3/arch/ppc64/kernel/idle_power4.S --- linux-2.6.3-rc2/arch/ppc64/kernel/idle_power4.S 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/idle_power4.S 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,79 @@ +/* + * This file contains the power_save function for 6xx & 7xxx CPUs + * rewritten in assembler + * + * Warning ! This code assumes that if your machine has a 750fx + * it will have PLL 1 set to low speed mode (used during NAP/DOZE). + * if this is not the case some additional changes will have to + * be done to check a runtime var (a bit like powersave-nap) + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + + .text + +/* + * Here is the power_save_6xx function. This could eventually be + * split into several functions & changing the function pointer + * depending on the various features. + */ +_GLOBAL(power4_idle) +BEGIN_FTR_SECTION + blr +END_FTR_SECTION_IFCLR(CPU_FTR_CAN_NAP) + /* We must dynamically check for the NAP feature as it + * can be cleared by CPU init after the fixups are done + */ + LOADBASE(r3,cur_cpu_spec) + ld r4,cur_cpu_spec@l(r3) + ld r4,CPU_SPEC_FEATURES(r4) + andi. r0,r4,CPU_FTR_CAN_NAP + beqlr + /* Now check if user or arch enabled NAP mode */ + LOADBASE(r3,powersave_nap) + lwz r4,powersave_nap@l(r3) + cmpi 0,r4,0 + beqlr + + /* Clear MSR:EE */ + mfmsr r7 + li r4,0 + ori r4,r4,MSR_EE + andc r0,r7,r4 + mtmsrd r0 + + /* Check current_thread_info()->flags */ + clrrdi r4,r1,THREAD_SHIFT + ld r4,TI_FLAGS(r4) + andi. r0,r4,_TIF_NEED_RESCHED + beq 1f + mtmsrd r7 /* out of line this ? */ + blr +1: + /* Go to NAP now */ +BEGIN_FTR_SECTION + DSSALL + sync +END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) + oris r7,r7,MSR_POW@h + sync + isync + mtmsrd r7 + isync + sync + blr + diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/misc.S linux-2.6.3-rc3/arch/ppc64/kernel/misc.S --- linux-2.6.3-rc2/arch/ppc64/kernel/misc.S 2004-02-03 19:44:30.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/misc.S 2004-02-14 19:31:00.000000000 -0800 @@ -763,7 +763,7 @@ .llong .sys_fstat64 .llong .sys32_pciconfig_read .llong .sys32_pciconfig_write - .llong .sys_ni_syscall /* 200 - old pciconfig_iobase */ + .llong .sys32_pciconfig_iobase /* 200 - pciconfig_iobase */ .llong .sys_ni_syscall /* reserved for MacOnLinux */ .llong .sys_getdents64 .llong .sys_pivot_root @@ -1022,7 +1022,7 @@ .llong .sys_ni_syscall /* 32bit only fstat64 */ .llong .sys_ni_syscall /* 32bit only pciconfig_read */ .llong .sys_ni_syscall /* 32bit only pciconfig_write */ - .llong .sys_ni_syscall /* 200 - old pciconfig_iobase */ + .llong .sys_ni_syscall /* 32bit only pciconfig_iobase */ .llong .sys_ni_syscall /* reserved for MacOnLinux */ .llong .sys_getdents64 .llong .sys_pivot_root diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/nvram.c linux-2.6.3-rc3/arch/ppc64/kernel/nvram.c --- linux-2.6.3-rc2/arch/ppc64/kernel/nvram.c 2004-02-03 19:43:07.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/nvram.c 2004-02-14 19:31:00.000000000 -0800 @@ -9,6 +9,10 @@ * /dev/nvram driver for PPC64 * * This perhaps should live in drivers/char + * + * TODO: Split the /dev/nvram part (that one can use + * drivers/char/generic_nvram.c) from the arch & partition + * parsing code. */ #include @@ -34,16 +38,10 @@ static int nvram_setup_partition(void); static int nvram_create_os_partition(void); static int nvram_remove_os_partition(void); -static unsigned char nvram_checksum(struct nvram_header *p); -static int nvram_write_header(struct nvram_partition * part); -static unsigned int nvram_size; -static unsigned int nvram_fetch, nvram_store; -static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ static struct nvram_partition * nvram_part; static long nvram_error_log_index = -1; static long nvram_error_log_size = 0; -static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; volatile int no_more_logging = 1; /* Until we initialize everything, * make sure we don't try logging @@ -58,12 +56,18 @@ static loff_t dev_nvram_llseek(struct file *file, loff_t offset, int origin) { + int size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + size = ppc_md.nvram_size(); + switch (origin) { case 1: offset += file->f_pos; break; case 2: - offset += nvram_size; + offset += size; break; } if (offset < 0) @@ -78,13 +82,18 @@ { ssize_t len; char *tmp_buffer; + int size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + size = ppc_md.nvram_size(); if (verify_area(VERIFY_WRITE, buf, count)) return -EFAULT; - if (*ppos >= nvram_size) + if (*ppos >= size) return 0; - if (count > nvram_size) - count = nvram_size; + if (count > size) + count = size; tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); if (!tmp_buffer) { @@ -113,13 +122,18 @@ { ssize_t len; char * tmp_buffer; + int size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + size = ppc_md.nvram_size(); if (verify_area(VERIFY_READ, buf, count)) return -EFAULT; - if (*ppos >= nvram_size) + if (*ppos >= size) return 0; - if (count > nvram_size) - count = nvram_size; + if (count > size) + count = size; tmp_buffer = (char *) kmalloc(count, GFP_KERNEL); if (!tmp_buffer) { @@ -145,6 +159,28 @@ static int dev_nvram_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + switch(cmd) { +#ifdef CONFIG_PPC_PMAC + case OBSOLETE_PMAC_NVRAM_GET_OFFSET: + printk(KERN_WARNING "nvram: Using obsolete PMAC_NVRAM_GET_OFFSET ioctl\n"); + case IOC_NVRAM_GET_OFFSET: { + int part, offset; + + if (systemcfg->platform != PLATFORM_POWERMAC) + return -EINVAL; + if (copy_from_user(&part, (void __user*)arg, sizeof(part)) != 0) + return -EFAULT; + if (part < pmac_nvram_OF || part > pmac_nvram_NR) + return -EINVAL; + offset = pmac_get_partition(part); + if (offset < 0) + return offset; + if (copy_to_user((void __user*)arg, &offset, sizeof(offset)) != 0) + return -EFAULT; + return 0; + } +#endif /* CONFIG_PPC_PMAC */ + } return -EINVAL; } @@ -162,259 +198,75 @@ &nvram_fops }; -ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) -{ - unsigned int i; - unsigned long len, done; - unsigned long flags; - char *p = buf; - - if (*index >= nvram_size) - return 0; - - i = *index; - if (i + count > nvram_size) - count = nvram_size - i; - - spin_lock_irqsave(&nvram_lock, flags); - - for (; count != 0; count -= len) { - len = count; - if (len > NVRW_CNT) - len = NVRW_CNT; - - if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf), - len) != 0) || len != done) { - spin_unlock_irqrestore(&nvram_lock, flags); - return -EIO; - } - - memcpy(p, nvram_buf, len); - p += len; - i += len; - } - spin_unlock_irqrestore(&nvram_lock, flags); +static void nvram_print_partitions(char * label) +{ + struct list_head * p; + struct nvram_partition * tmp_part; - *index = i; - return p - buf; + printk(KERN_WARNING "--------%s---------\n", label); + printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); + list_for_each(p, &nvram_part->partition) { + tmp_part = list_entry(p, struct nvram_partition, partition); + printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", + tmp_part->index, tmp_part->header.signature, + tmp_part->header.checksum, tmp_part->header.length, + tmp_part->header.name); + } } -ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index) -{ - unsigned int i; - unsigned long len, done; - unsigned long flags; - const char *p = buf; - - if (*index >= nvram_size) - return 0; - i = *index; - if (i + count > nvram_size) - count = nvram_size - i; - - spin_lock_irqsave(&nvram_lock, flags); - - for (; count != 0; count -= len) { - len = count; - if (len > NVRW_CNT) - len = NVRW_CNT; - - memcpy(nvram_buf, p, len); - - if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf), - len) != 0) || len != done) { - spin_unlock_irqrestore(&nvram_lock, flags); - return -EIO; - } - - p += len; - i += len; - } - spin_unlock_irqrestore(&nvram_lock, flags); - - *index = i; - return p - buf; -} - -int __init nvram_init(void) +static int nvram_write_header(struct nvram_partition * part) { - struct device_node *nvram; - unsigned int *nbytes_p, proplen; - int error; + loff_t tmp_index; int rc; - if ((nvram = of_find_node_by_type(NULL, "nvram")) != NULL) { - nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen); - if (nbytes_p && proplen == sizeof(unsigned int)) { - nvram_size = *nbytes_p; - } else { - return -EIO; - } - } - nvram_fetch = rtas_token("nvram-fetch"); - nvram_store = rtas_token("nvram-store"); - printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size); - of_node_put(nvram); - - rc = misc_register(&nvram_dev); - - /* If we don't know how big NVRAM is then we shouldn't touch - the nvram partitions */ - if (nvram == NULL) { - return rc; - } - - /* initialize our anchor for the nvram partition list */ - nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); - if (!nvram_part) { - printk(KERN_ERR "nvram_init: Failed kmalloc\n"); - return -ENOMEM; - } - INIT_LIST_HEAD(&nvram_part->partition); - - /* Get all the NVRAM partitions */ - error = nvram_scan_partitions(); - if (error) { - printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); - return error; - } - - if(nvram_setup_partition()) - printk(KERN_WARNING "nvram_init: Could not find nvram partition" - " for nvram buffered error logging.\n"); - -#ifdef DEBUG_NVRAM - nvram_print_partitions("NVRAM Partitions"); -#endif + tmp_index = part->index; + rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); - return rc; + return rc; } -void __exit nvram_cleanup(void) -{ - misc_deregister( &nvram_dev ); -} -static int nvram_scan_partitions(void) +static unsigned char nvram_checksum(struct nvram_header *p) { - loff_t cur_index = 0; - struct nvram_header phead; - struct nvram_partition * tmp_part; - unsigned char c_sum; - char * header; - long size; - - header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); - if (!header) { - printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n"); - return -ENOMEM; - } - - while (cur_index < nvram_size) { - - size = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index); - if (size != NVRAM_HEADER_LEN) { - printk(KERN_ERR "nvram_scan_partitions: Error parsing " - "nvram partitions\n"); - kfree(header); - return size; - } - - cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */ - - memcpy(&phead, header, NVRAM_HEADER_LEN); - - c_sum = nvram_checksum(&phead); - if (c_sum != phead.checksum) - printk(KERN_WARNING "WARNING: nvram partition checksum " - "was %02x, should be %02x!\n", phead.checksum, c_sum); - - tmp_part = (struct nvram_partition *) - kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); - if (!tmp_part) { - printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); - kfree(header); - return -ENOMEM; - } - - memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); - tmp_part->index = cur_index; - list_add_tail(&tmp_part->partition, &nvram_part->partition); - - cur_index += phead.length * NVRAM_BLOCK_LEN; - } + unsigned int c_sum, c_sum2; + unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ + c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5]; - kfree(header); - return 0; + /* The sum may have spilled into the 3rd byte. Fold it back. */ + c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff; + /* The sum cannot exceed 2 bytes. Fold it into a checksum */ + c_sum2 = (c_sum >> 8) + (c_sum << 8); + c_sum = ((c_sum + c_sum2) >> 8) & 0xff; + return c_sum; } -/* nvram_setup_partition - * - * This will setup the partition we need for buffering the - * error logs and cleanup partitions if needed. - * - * The general strategy is the following: - * 1.) If there is ppc64,linux partition large enough then use it. - * 2.) If there is not a ppc64,linux partition large enough, search - * for a free partition that is large enough. - * 3.) If there is not a free partition large enough remove - * _all_ OS partitions and consolidate the space. - * 4.) Will first try getting a chunk that will satisfy the maximum - * error log size (NVRAM_MAX_REQ). - * 5.) If the max chunk cannot be allocated then try finding a chunk - * that will satisfy the minum needed (NVRAM_MIN_REQ). + +/* + * Find an nvram partition, sig can be 0 for any + * partition or name can be NULL for any name, else + * tries to match both */ -static int nvram_setup_partition(void) +struct nvram_partition *nvram_find_partition(int sig, const char *name) { - struct list_head * p; struct nvram_partition * part; - int rc; + struct list_head * p; - /* see if we have an OS partition that meets our needs. - will try getting the max we need. If not we'll delete - partitions and try again. */ list_for_each(p, &nvram_part->partition) { part = list_entry(p, struct nvram_partition, partition); - if (part->header.signature != NVRAM_SIG_OS) - continue; - if (strcmp(part->header.name, "ppc64,linux")) + if (sig && part->header.signature != sig) continue; - - if (part->header.length >= NVRAM_MIN_REQ) { - /* found our partition */ - nvram_error_log_index = part->index + NVRAM_HEADER_LEN; - nvram_error_log_size = ((part->header.length - 1) * - NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); - return 0; - } - } - - /* try creating a partition with the free space we have */ - rc = nvram_create_os_partition(); - if (!rc) { - return 0; - } - - /* need to free up some space */ - rc = nvram_remove_os_partition(); - if (rc) { - return rc; - } - - /* create a partition in this new space */ - rc = nvram_create_os_partition(); - if (rc) { - printk(KERN_ERR "nvram_create_os_partition: Could not find a " - "NVRAM partition large enough\n"); - return rc; + if (name && 0 != strncmp(name, part->header.name, 12)) + continue; + return part; } - - return 0; + return NULL; } +EXPORT_SYMBOL(nvram_find_partition); + static int nvram_remove_os_partition(void) { @@ -572,22 +424,185 @@ } -void nvram_print_partitions(char * label) +/* nvram_setup_partition + * + * This will setup the partition we need for buffering the + * error logs and cleanup partitions if needed. + * + * The general strategy is the following: + * 1.) If there is ppc64,linux partition large enough then use it. + * 2.) If there is not a ppc64,linux partition large enough, search + * for a free partition that is large enough. + * 3.) If there is not a free partition large enough remove + * _all_ OS partitions and consolidate the space. + * 4.) Will first try getting a chunk that will satisfy the maximum + * error log size (NVRAM_MAX_REQ). + * 5.) If the max chunk cannot be allocated then try finding a chunk + * that will satisfy the minum needed (NVRAM_MIN_REQ). + */ +static int nvram_setup_partition(void) { struct list_head * p; + struct nvram_partition * part; + int rc; + + /* For now, we don't do any of this on pmac, until I + * have figured out if it's worth killing some unused stuffs + * in our nvram, as Apple defined partitions use pretty much + * all of the space + */ + if (systemcfg->platform == PLATFORM_POWERMAC) + return -ENOSPC; + + /* see if we have an OS partition that meets our needs. + will try getting the max we need. If not we'll delete + partitions and try again. */ + list_for_each(p, &nvram_part->partition) { + part = list_entry(p, struct nvram_partition, partition); + if (part->header.signature != NVRAM_SIG_OS) + continue; + + if (strcmp(part->header.name, "ppc64,linux")) + continue; + + if (part->header.length >= NVRAM_MIN_REQ) { + /* found our partition */ + nvram_error_log_index = part->index + NVRAM_HEADER_LEN; + nvram_error_log_size = ((part->header.length - 1) * + NVRAM_BLOCK_LEN) - sizeof(struct err_log_info); + return 0; + } + } + + /* try creating a partition with the free space we have */ + rc = nvram_create_os_partition(); + if (!rc) { + return 0; + } + + /* need to free up some space */ + rc = nvram_remove_os_partition(); + if (rc) { + return rc; + } + + /* create a partition in this new space */ + rc = nvram_create_os_partition(); + if (rc) { + printk(KERN_ERR "nvram_create_os_partition: Could not find a " + "NVRAM partition large enough\n"); + return rc; + } + + return 0; +} + + +static int nvram_scan_partitions(void) +{ + loff_t cur_index = 0; + struct nvram_header phead; struct nvram_partition * tmp_part; + unsigned char c_sum; + char * header; + long size; + int total_size; + + if (ppc_md.nvram_size == NULL) + return -ENODEV; + total_size = ppc_md.nvram_size(); - printk(KERN_WARNING "--------%s---------\n", label); - printk(KERN_WARNING "indx\t\tsig\tchks\tlen\tname\n"); - list_for_each(p, &nvram_part->partition) { - tmp_part = list_entry(p, struct nvram_partition, partition); - printk(KERN_WARNING "%d \t%02x\t%02x\t%d\t%s\n", - tmp_part->index, tmp_part->header.signature, - tmp_part->header.checksum, tmp_part->header.length, - tmp_part->header.name); + header = (char *) kmalloc(NVRAM_HEADER_LEN, GFP_KERNEL); + if (!header) { + printk(KERN_ERR "nvram_scan_partitions: Failed kmalloc\n"); + return -ENOMEM; + } + + while (cur_index < total_size) { + + size = ppc_md.nvram_read(header, NVRAM_HEADER_LEN, &cur_index); + if (size != NVRAM_HEADER_LEN) { + printk(KERN_ERR "nvram_scan_partitions: Error parsing " + "nvram partitions\n"); + kfree(header); + return size; + } + + cur_index -= NVRAM_HEADER_LEN; /* nvram_read will advance us */ + + memcpy(&phead, header, NVRAM_HEADER_LEN); + + c_sum = nvram_checksum(&phead); + if (c_sum != phead.checksum) + printk(KERN_WARNING "WARNING: nvram partition checksum " + "was %02x, should be %02x!\n", phead.checksum, c_sum); + + tmp_part = (struct nvram_partition *) + kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + if (!tmp_part) { + printk(KERN_ERR "nvram_scan_partitions: kmalloc failed\n"); + kfree(header); + return -ENOMEM; + } + + memcpy(&tmp_part->header, &phead, NVRAM_HEADER_LEN); + tmp_part->index = cur_index; + list_add_tail(&tmp_part->partition, &nvram_part->partition); + + cur_index += phead.length * NVRAM_BLOCK_LEN; } + + kfree(header); + return 0; } +static int __init nvram_init(void) +{ + int error; + int rc; + + if (ppc_md.nvram_size == NULL || ppc_md.nvram_size() <= 0) + return -ENODEV; + + rc = misc_register(&nvram_dev); + if (rc != 0) { + printk(KERN_ERR "nvram_init: failed to register device\n"); + return rc; + } + + /* initialize our anchor for the nvram partition list */ + nvram_part = (struct nvram_partition *) kmalloc(sizeof(struct nvram_partition), GFP_KERNEL); + if (!nvram_part) { + printk(KERN_ERR "nvram_init: Failed kmalloc\n"); + return -ENOMEM; + } + INIT_LIST_HEAD(&nvram_part->partition); + + /* Get all the NVRAM partitions */ + error = nvram_scan_partitions(); + if (error) { + printk(KERN_ERR "nvram_init: Failed nvram_scan_partitions\n"); + return error; + } + + if(nvram_setup_partition()) + printk(KERN_WARNING "nvram_init: Could not find nvram partition" + " for nvram buffered error logging.\n"); + +#ifdef DEBUG_NVRAM + nvram_print_partitions("NVRAM Partitions"); +#endif + + return rc; +} + +void __exit nvram_cleanup(void) +{ + misc_deregister( &nvram_dev ); +} + + + /* nvram_write_error_log * * We need to buffer the error logs into nvram to ensure that we have @@ -711,30 +726,6 @@ return 0; } -static int nvram_write_header(struct nvram_partition * part) -{ - loff_t tmp_index; - int rc; - - tmp_index = part->index; - rc = ppc_md.nvram_write((char *)&part->header, NVRAM_HEADER_LEN, &tmp_index); - - return rc; -} - -static unsigned char nvram_checksum(struct nvram_header *p) -{ - unsigned int c_sum, c_sum2; - unsigned short *sp = (unsigned short *)p->name; /* assume 6 shorts */ - c_sum = p->signature + p->length + sp[0] + sp[1] + sp[2] + sp[3] + sp[4] + sp[5]; - - /* The sum may have spilled into the 3rd byte. Fold it back. */ - c_sum = ((c_sum & 0xffff) + (c_sum >> 16)) & 0xffff; - /* The sum cannot exceed 2 bytes. Fold it into a checksum */ - c_sum2 = (c_sum >> 8) + (c_sum << 8); - c_sum = ((c_sum + c_sum2) >> 8) & 0xff; - return c_sum; -} module_init(nvram_init); module_exit(nvram_cleanup); diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/of_device.c linux-2.6.3-rc3/arch/ppc64/kernel/of_device.c --- linux-2.6.3-rc2/arch/ppc64/kernel/of_device.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/of_device.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,272 @@ +#include +#include +#include +#include +#include +#include +#include + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_match * of_match_device(const struct of_match *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + while (matches->name || matches->type || matches->compatible) { + int match = 1; + if (matches->name && matches->name != OF_ANY_MATCH) + match &= dev->node->name + && !strcmp(matches->name, dev->node->name); + if (matches->type && matches->type != OF_ANY_MATCH) + match &= dev->node->type + && !strcmp(matches->type, dev->node->type); + if (matches->compatible && matches->compatible != OF_ANY_MATCH) + match &= device_is_compatible(dev->node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * of_drv = to_of_platform_driver(drv); + const struct of_match * matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} + + +static int of_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_match *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_device_remove(struct device *dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_device_suspend(struct device *dev, u32 state) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_device_resume(struct device * dev) +{ + struct of_device * of_dev = to_of_device(dev); + struct of_platform_driver * drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +struct bus_type of_platform_bus_type = { + .name = "of_platform", + .match = of_platform_bus_match, + .suspend = of_device_suspend, + .resume = of_device_resume, +}; + +static int __init of_bus_driver_init(void) +{ + return bus_register(&of_platform_bus_type); +} + +postcore_initcall(of_bus_driver_init); + +int of_register_driver(struct of_platform_driver *drv) +{ + int count = 0; + + /* initialize common driver fields */ + drv->driver.name = drv->name; + drv->driver.bus = &of_platform_bus_type; + drv->driver.probe = of_device_probe; + drv->driver.remove = of_device_remove; + + /* register with core */ + count = driver_register(&drv->driver); + return count ? count : 1; +} + +void of_unregister_driver(struct of_platform_driver *drv) +{ + driver_unregister(&drv->driver); +} + + +static ssize_t dev_show_devspec(struct device *dev, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + kfree(ofdev); +} + +int of_device_register(struct of_device *ofdev) +{ + int rc; + struct of_device **odprop; + + BUG_ON(ofdev->node == NULL); + + odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL); + if (!odprop) { + struct property *new_prop; + + new_prop = kmalloc(sizeof(struct property) + sizeof(struct of_device *), + GFP_KERNEL); + if (new_prop == NULL) + return -ENOMEM; + new_prop->name = "linux,device"; + new_prop->length = sizeof(sizeof(struct of_device *)); + new_prop->value = (unsigned char *)&new_prop[1]; + odprop = (struct of_device **)new_prop->value; + *odprop = NULL; + prom_add_property(ofdev->node, new_prop); + } + *odprop = ofdev; + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + device_create_file(&ofdev->dev, &dev_attr_devspec); + + return 0; +} + +void of_device_unregister(struct of_device *ofdev) +{ + struct of_device **odprop; + + device_remove_file(&ofdev->dev, &dev_attr_devspec); + + odprop = (struct of_device **)get_property(ofdev->node, "linux,device", NULL); + if (odprop) + *odprop = NULL; + + device_unregister(&ofdev->dev); +} + +struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id) +{ + struct of_device *dev; + u32 *reg; + + dev = kmalloc(sizeof(*dev), GFP_KERNEL); + if (!dev) + return NULL; + memset(dev, 0, sizeof(*dev)); + + dev->node = np; + dev->dma_mask = 0xffffffffUL; + dev->dev.dma_mask = &dev->dma_mask; + dev->dev.parent = NULL; + dev->dev.bus = &of_platform_bus_type; + dev->dev.release = of_release_dev; + + reg = (u32 *)get_property(np, "reg", NULL); + strlcpy(dev->dev.bus_id, bus_id, BUS_ID_SIZE); + + if (of_device_register(dev) != 0) { + kfree(dev); + return NULL; + } + + return dev; +} + +EXPORT_SYMBOL(of_match_device); +EXPORT_SYMBOL(of_platform_bus_type); +EXPORT_SYMBOL(of_register_driver); +EXPORT_SYMBOL(of_unregister_driver); +EXPORT_SYMBOL(of_device_register); +EXPORT_SYMBOL(of_device_unregister); +EXPORT_SYMBOL(of_dev_get); +EXPORT_SYMBOL(of_dev_put); +EXPORT_SYMBOL(of_platform_device_create); +EXPORT_SYMBOL(of_release_dev); diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/open_pic.c linux-2.6.3-rc3/arch/ppc64/kernel/open_pic.c --- linux-2.6.3-rc2/arch/ppc64/kernel/open_pic.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/open_pic.c 2004-02-14 19:31:00.000000000 -0800 @@ -34,7 +34,42 @@ u_int OpenPIC_NumInitSenses __initdata = 0; u_char *OpenPIC_InitSenses __initdata = NULL; -void find_ISUs(void); +/* + * Local (static) OpenPIC Operations + */ + + +/* Global Operations */ +static void openpic_reset(void); +static void openpic_enable_8259_pass_through(void); +static void openpic_disable_8259_pass_through(void); +static u_int openpic_irq(void); +static void openpic_eoi(void); +static u_int openpic_get_priority(void); +static void openpic_set_priority(u_int pri); +static u_int openpic_get_spurious(void); +static void openpic_set_spurious(u_int vector); + +#ifdef CONFIG_SMP +/* Interprocessor Interrupts */ +static void openpic_initipi(u_int ipi, u_int pri, u_int vector); +static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, + struct pt_regs *regs); +#endif + +/* Timer Interrupts */ +static void openpic_inittimer(u_int timer, u_int pri, u_int vector); +static void openpic_maptimer(u_int timer, u_int cpumask); + +/* Interrupt Sources */ +static void openpic_enable_irq(u_int irq); +static void openpic_disable_irq(u_int irq); +static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity, + int is_level); +static void openpic_mapirq(u_int irq, u_int cpumask); +static void openpic_set_sense(u_int irq, int sense); + +static void find_ISUs(void); static u_int NumProcessors; static u_int NumSources; @@ -130,7 +165,7 @@ #define GET_ISU(source) ISU[(source) >> 4][(source) & 0xf] -void __init openpic_init_IRQ(void) +void __init pSeries_init_openpic(void) { struct device_node *np; int i; @@ -359,9 +394,12 @@ } /* Init all external sources */ - for (i = 1; i < NumSources; i++) { + for (i = 0; i < NumSources; i++) { int pri, sense; + /* skip cascade if any */ + if (offset && i == 0) + continue; /* the bootloader may have left it enabled (bad !) */ openpic_disable_irq(i+offset); @@ -396,6 +434,9 @@ */ static int __init openpic_setup_i8259(void) { + if (systemcfg->platform == PLATFORM_POWERMAC) + return 0; + if (naca->interrupt_controller == IC_OPEN_PIC) { /* Initialize the cascade */ if (request_irq(NUM_8259_INTERRUPTS, no_action, SA_INTERRUPT, @@ -419,6 +460,14 @@ void find_ISUs(void) { + /* For PowerMac, setup ISUs on base openpic */ + if (systemcfg->platform == PLATFORM_POWERMAC) { + int i; + for (i=0; i<128; i+=0x10) { + ISU[i>>4] = &((struct OpenPIC *)OpenPIC_Addr)->Source[i]; + NumISUs++; + } + } /* Use /interrupt-controller/reg and * /interrupt-controller/interrupt-ranges from OF device tree * the ISU array is setup in chrp_pci.c in ibm_add_bridges @@ -429,11 +478,22 @@ /* basically each ISU is a bus, and this assumes that * open_pic_isu_count interrupts per bus are possible * ISU == Interrupt Source + * + * On G5, we keep the original NumSources provided by the controller, + * it's below 128, so we have room to stuff the IPIs and timers like darwin + * does. We put the spurrious vector up at 0xff though. */ - NumSources = NumISUs * 0x10; - openpic_vec_ipi = NumSources + open_pic_irq_offset; - openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI; - openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS; + if (systemcfg->platform == PLATFORM_POWERMAC) { + openpic_vec_ipi = NumSources; + openpic_vec_timer = openpic_vec_ipi + 4; + openpic_vec_spurious = 0xff; + } else { + NumSources = NumISUs * 0x10; + + openpic_vec_ipi = NumSources + open_pic_irq_offset; + openpic_vec_timer = openpic_vec_ipi + OPENPIC_NUM_IPI; + openpic_vec_spurious = openpic_vec_timer + OPENPIC_NUM_TIMERS; + } } static inline void openpic_reset(void) @@ -585,9 +645,9 @@ request_irq(openpic_vec_ipi+1, openpic_ipi_action, SA_INTERRUPT, "IPI1 (reschedule)", 0); request_irq(openpic_vec_ipi+2, openpic_ipi_action, SA_INTERRUPT, - "IPI2 (invalidate tlb)", 0); + "IPI2 (unused)", 0); request_irq(openpic_vec_ipi+3, openpic_ipi_action, SA_INTERRUPT, - "IPI3 (xmon break)", 0); + "IPI3 (debugger break)", 0); for ( i = 0; i < OPENPIC_NUM_IPI ; i++ ) openpic_enable_ipi(openpic_vec_ipi+i); @@ -767,8 +827,7 @@ static void openpic_end_irq(unsigned int irq_nr) { - if ((irq_desc[irq_nr].status & IRQ_LEVEL) != 0) - openpic_eoi(); + openpic_eoi(); } static void openpic_set_affinity(unsigned int irq_nr, cpumask_t cpumask) @@ -807,9 +866,7 @@ int irq = openpic_irq(); - /* Management of the cascade should be moved out of here */ - if (open_pic_irq_offset && irq == open_pic_irq_offset) - { + if (open_pic_irq_offset && irq == open_pic_irq_offset) { /* * This magic address generates a PCI IACK cycle. */ diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/open_pic.h linux-2.6.3-rc3/arch/ppc64/kernel/open_pic.h --- linux-2.6.3-rc2/arch/ppc64/kernel/open_pic.h 2004-02-03 19:43:11.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/open_pic.h 2004-02-14 19:31:00.000000000 -0800 @@ -40,6 +40,8 @@ extern inline int openpic_to_irq(int irq) { + if (systemcfg->platform == PLATFORM_POWERMAC) + return irq; return irq += NUM_8259_INTERRUPTS; } /*extern int open_pic_irq_offset;*/ diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/open_pic_defs.h linux-2.6.3-rc3/arch/ppc64/kernel/open_pic_defs.h --- linux-2.6.3-rc2/arch/ppc64/kernel/open_pic_defs.h 2004-02-03 19:44:03.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/open_pic_defs.h 2004-02-14 19:31:00.000000000 -0800 @@ -279,40 +279,6 @@ #define Vector_Priority _Vector_Priority.Reg #define Destination _Destination.Reg -/* - * Local (static) OpenPIC Operations - */ - - -/* Global Operations */ -static void openpic_reset(void); -static void openpic_enable_8259_pass_through(void); -static void openpic_disable_8259_pass_through(void); -static u_int openpic_irq(void); -static void openpic_eoi(void); -static u_int openpic_get_priority(void); -static void openpic_set_priority(u_int pri); -static u_int openpic_get_spurious(void); -static void openpic_set_spurious(u_int vector); - -#ifdef CONFIG_SMP -/* Interprocessor Interrupts */ -static void openpic_initipi(u_int ipi, u_int pri, u_int vector); -static irqreturn_t openpic_ipi_action(int cpl, void *dev_id, - struct pt_regs *regs); -#endif - -/* Timer Interrupts */ -static void openpic_inittimer(u_int timer, u_int pri, u_int vector); -static void openpic_maptimer(u_int timer, u_int cpumask); - -/* Interrupt Sources */ -static void openpic_enable_irq(u_int irq); -static void openpic_disable_irq(u_int irq); -static void openpic_initirq(u_int irq, u_int pri, u_int vector, int polarity, - int is_level); -static void openpic_mapirq(u_int irq, u_int cpumask); -static void openpic_set_sense(u_int irq, int sense); #endif /* __KERNEL__ */ diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/open_pic_u3.c linux-2.6.3-rc3/arch/ppc64/kernel/open_pic_u3.c --- linux-2.6.3-rc2/arch/ppc64/kernel/open_pic_u3.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/open_pic_u3.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,348 @@ +/* + * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling + * + * Copyright (C) 1997 Geert Uytterhoeven + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "open_pic.h" +#include "open_pic_defs.h" + +void* OpenPIC2_Addr; +static volatile struct OpenPIC *OpenPIC2 = NULL; + +extern u_int OpenPIC_NumInitSenses; +extern u_char *OpenPIC_InitSenses; + +static u_int NumSources; +static int NumISUs; +static int open_pic2_irq_offset; + +static OpenPIC_SourcePtr ISU2[OPENPIC_MAX_ISU]; + +unsigned int openpic2_vec_spurious; + +/* + * Accesses to the current processor's openpic registers + * U3 secondary openpic has only one output + */ +#define THIS_CPU Processor[0] +#define DECL_THIS_CPU +#define CHECK_THIS_CPU + +#define GET_ISU(source) ISU2[(source) >> 4][(source) & 0xf] + +static inline u_int openpic2_read(volatile u_int *addr) +{ + u_int val; + + val = in_be32(addr); + return val; +} + +static inline void openpic2_write(volatile u_int *addr, u_int val) +{ + out_be32(addr, val); +} + +static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask) +{ + u_int val = openpic2_read(addr); + return val & mask; +} + +static inline void openpic2_writefield(volatile u_int *addr, u_int mask, + u_int field) +{ + u_int val = openpic2_read(addr); + openpic2_write(addr, (val & ~mask) | (field & mask)); +} + +static inline void openpic2_clearfield(volatile u_int *addr, u_int mask) +{ + openpic2_writefield(addr, mask, 0); +} + +static inline void openpic2_setfield(volatile u_int *addr, u_int mask) +{ + openpic2_writefield(addr, mask, mask); +} + +static void openpic2_safe_writefield(volatile u_int *addr, u_int mask, + u_int field) +{ + unsigned int loops = 100000; + + openpic2_setfield(addr, OPENPIC_MASK); + while (openpic2_read(addr) & OPENPIC_ACTIVITY) { + if (!loops--) { + printk(KERN_ERR "openpic2_safe_writefield timeout\n"); + break; + } + } + openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK); +} + + +static inline void openpic2_reset(void) +{ + openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, + OPENPIC_CONFIG_RESET); +} + +static void openpic2_disable_8259_pass_through(void) +{ + openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, + OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE); +} + +/* + * Find out the current interrupt + */ +static u_int openpic2_irq(void) +{ + u_int vec; + DECL_THIS_CPU; + CHECK_THIS_CPU; + vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge, + OPENPIC_VECTOR_MASK); + return vec; +} + +static void openpic2_eoi(void) +{ + DECL_THIS_CPU; + CHECK_THIS_CPU; + openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0); + /* Handle PCI write posting */ + (void)openpic2_read(&OpenPIC2->THIS_CPU.EOI); +} + + +static inline u_int openpic2_get_priority(void) +{ + DECL_THIS_CPU; + CHECK_THIS_CPU; + return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK); +} + +static void openpic2_set_priority(u_int pri) +{ + DECL_THIS_CPU; + CHECK_THIS_CPU; + openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority, + OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri); +} + +/* + * Get/set the spurious vector + */ +static inline u_int openpic2_get_spurious(void) +{ + return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector, + OPENPIC_VECTOR_MASK); +} + +static void openpic2_set_spurious(u_int vec) +{ + openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK, + vec); +} + +/* + * Enable/disable an external interrupt source + * + * Externally called, irq is an offseted system-wide interrupt number + */ +static void openpic2_enable_irq(u_int irq) +{ + unsigned int loops = 100000; + + openpic2_clearfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK); + /* make sure mask gets to controller before we return to user */ + do { + if (!loops--) { + printk(KERN_ERR "openpic_enable_irq timeout\n"); + break; + } + + mb(); /* sync is probably useless here */ + } while(openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, + OPENPIC_MASK)); +} + +static void openpic2_disable_irq(u_int irq) +{ + u32 vp; + unsigned int loops = 100000; + + openpic2_setfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, + OPENPIC_MASK); + /* make sure mask gets to controller before we return to user */ + do { + if (!loops--) { + printk(KERN_ERR "openpic_disable_irq timeout\n"); + break; + } + + mb(); /* sync is probably useless here */ + vp = openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, + OPENPIC_MASK | OPENPIC_ACTIVITY); + } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK)); +} + +/* + * Initialize an interrupt source (and disable it!) + * + * irq: OpenPIC interrupt number + * pri: interrupt source priority + * vec: the vector it will produce + * pol: polarity (1 for positive, 0 for negative) + * sense: 1 for level, 0 for edge + */ +static void openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense) +{ + openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority, + OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | + OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK, + (pri << OPENPIC_PRIORITY_SHIFT) | vec | + (pol ? OPENPIC_POLARITY_POSITIVE : + OPENPIC_POLARITY_NEGATIVE) | + (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE)); +} + +/* + * Map an interrupt source to one or more CPUs + */ +static void openpic2_mapirq(u_int irq, u_int physmask) +{ + openpic2_write(&GET_ISU(irq).Destination, physmask); +} + +/* + * Set the sense for an interrupt source (and disable it!) + * + * sense: 1 for level, 0 for edge + */ +static inline void openpic2_set_sense(u_int irq, int sense) +{ + openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority, + OPENPIC_SENSE_LEVEL, + (sense ? OPENPIC_SENSE_LEVEL : 0)); +} + +static void openpic2_end_irq(unsigned int irq_nr) +{ + openpic2_eoi(); +} + +int openpic2_get_irq(struct pt_regs *regs) +{ + int irq = openpic2_irq(); + + if (irq == openpic2_vec_spurious) + return -1; + return irq + open_pic2_irq_offset; +} + +struct hw_interrupt_type open_pic2 = { + " OpenPIC2 ", + NULL, + NULL, + openpic2_enable_irq, + openpic2_disable_irq, + NULL, + openpic2_end_irq, +}; + +void __init openpic2_init(int offset) +{ + u_int t, i; + const char *version; + + if (!OpenPIC2_Addr) { + printk(KERN_INFO "No OpenPIC2 found !\n"); + return; + } + OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr; + + ppc64_boot_msg(0x20, "OpenPic U3 Init"); + + t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0); + switch (t & OPENPIC_FEATURE_VERSION_MASK) { + case 1: + version = "1.0"; + break; + case 2: + version = "1.2"; + break; + case 3: + version = "1.3"; + break; + default: + version = "?"; + break; + } + printk(KERN_INFO "OpenPIC (U3) Version %s\n", version); + + open_pic2_irq_offset = offset; + + for (i=0; i<128; i+=0x10) { + ISU2[i>>4] = &((struct OpenPIC *)OpenPIC2_Addr)->Source[i]; + NumISUs++; + } + NumSources = NumISUs * 0x10; + openpic2_vec_spurious = NumSources; + + openpic2_set_priority(0xf); + + /* Init all external sources */ + for (i = 0; i < NumSources; i++) { + int pri, sense; + + /* the bootloader may have left it enabled (bad !) */ + openpic2_disable_irq(i+offset); + + pri = 8; + sense = (i < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[i]: 1; + if (sense) + irq_desc[i+offset].status = IRQ_LEVEL; + + /* Enabled, Priority 8 or 9 */ + openpic2_initirq(i, pri, i, !sense, sense); + /* Processor 0 */ + openpic2_mapirq(i, 0x1); + } + + /* Init descriptors */ + for (i = offset; i < NumSources + offset; i++) + irq_desc[i].handler = &open_pic2; + + /* Initialize the spurious interrupt */ + openpic2_set_spurious(openpic2_vec_spurious); + + openpic2_set_priority(0); + openpic2_disable_8259_pass_through(); + + ppc64_boot_msg(0x25, "OpenPic2 Done"); +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pSeries_nvram.c linux-2.6.3-rc3/arch/ppc64/kernel/pSeries_nvram.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pSeries_nvram.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pSeries_nvram.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,150 @@ +/* + * c 2001 PPC 64 Team, IBM Corp + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * /dev/nvram driver for PPC64 + * + * This perhaps should live in drivers/char + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static unsigned int nvram_size; +static unsigned int nvram_fetch, nvram_store; +static char nvram_buf[NVRW_CNT]; /* assume this is in the first 4GB */ +static spinlock_t nvram_lock = SPIN_LOCK_UNLOCKED; + + +static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index) +{ + unsigned int i; + unsigned long len, done; + unsigned long flags; + char *p = buf; + + if (nvram_size == 0 || nvram_fetch) + return -ENODEV; + + if (*index >= nvram_size) + return 0; + + i = *index; + if (i + count > nvram_size) + count = nvram_size - i; + + spin_lock_irqsave(&nvram_lock, flags); + + for (; count != 0; count -= len) { + len = count; + if (len > NVRW_CNT) + len = NVRW_CNT; + + if ((rtas_call(nvram_fetch, 3, 2, &done, i, __pa(nvram_buf), + len) != 0) || len != done) { + spin_unlock_irqrestore(&nvram_lock, flags); + return -EIO; + } + + memcpy(p, nvram_buf, len); + + p += len; + i += len; + } + + spin_unlock_irqrestore(&nvram_lock, flags); + + *index = i; + return p - buf; +} + +static ssize_t pSeries_nvram_write(char *buf, size_t count, loff_t *index) +{ + unsigned int i; + unsigned long len, done; + unsigned long flags; + const char *p = buf; + + if (nvram_size == 0 || nvram_store) + return -ENODEV; + + if (*index >= nvram_size) + return 0; + + i = *index; + if (i + count > nvram_size) + count = nvram_size - i; + + spin_lock_irqsave(&nvram_lock, flags); + + for (; count != 0; count -= len) { + len = count; + if (len > NVRW_CNT) + len = NVRW_CNT; + + memcpy(nvram_buf, p, len); + + if ((rtas_call(nvram_store, 3, 2, &done, i, __pa(nvram_buf), + len) != 0) || len != done) { + spin_unlock_irqrestore(&nvram_lock, flags); + return -EIO; + } + + p += len; + i += len; + } + spin_unlock_irqrestore(&nvram_lock, flags); + + *index = i; + return p - buf; +} + +static ssize_t pSeries_nvram_get_size(void) +{ + return nvram_size ? nvram_size : -ENODEV; +} + +int __init pSeries_nvram_init(void) +{ + struct device_node *nvram; + unsigned int *nbytes_p, proplen; + + nvram = of_find_node_by_type(NULL, "nvram"); + if (nvram == NULL) + return -ENODEV; + + nbytes_p = (unsigned int *)get_property(nvram, "#bytes", &proplen); + if (nbytes_p == NULL || proplen != sizeof(unsigned int)) + return -EIO; + + nvram_size = *nbytes_p; + + nvram_fetch = rtas_token("nvram-fetch"); + nvram_store = rtas_token("nvram-store"); + printk(KERN_INFO "PPC64 nvram contains %d bytes\n", nvram_size); + of_node_put(nvram); + + ppc_md.nvram_read = pSeries_nvram_read; + ppc_md.nvram_write = pSeries_nvram_write; + ppc_md.nvram_size = pSeries_nvram_get_size; + + return 0; +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pSeries_pci.c linux-2.6.3-rc3/arch/ppc64/kernel/pSeries_pci.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pSeries_pci.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pSeries_pci.c 2004-02-14 19:31:00.000000000 -0800 @@ -687,7 +687,7 @@ extern void chrp_request_regions(void); -void __init pcibios_final_fixup(void) +void __init pSeries_final_fixup(void) { struct pci_dev *dev = NULL; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pci.c linux-2.6.3-rc3/arch/ppc64/kernel/pci.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pci.c 2004-02-03 19:44:28.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pci.c 2004-02-14 19:31:00.000000000 -0800 @@ -34,6 +34,7 @@ #include #include #include +#include #include "pci.h" @@ -58,21 +59,32 @@ void pcibios_final_fixup(void); static void fixup_broken_pcnet32(struct pci_dev* dev); static void fixup_windbond_82c105(struct pci_dev* dev); +extern void fixup_k2_sata(struct pci_dev* dev); void iSeries_pcibios_init(void); struct pci_controller *hose_head; struct pci_controller **hose_tail = &hose_head; +struct pci_dma_ops pci_dma_ops; +EXPORT_SYMBOL(pci_dma_ops); + int global_phb_number; /* Global phb counter */ /* Cached ISA bridge dev. */ struct pci_dev *ppc64_isabridge_dev = NULL; struct pci_fixup pcibios_fixups[] = { - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, fixup_broken_pcnet32 }, - { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, fixup_windbond_82c105 }, - { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, pcibios_name_device }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_TRIDENT, PCI_ANY_ID, + fixup_broken_pcnet32 }, + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_WINBOND, PCI_DEVICE_ID_WINBOND_82C105, + fixup_windbond_82c105 }, + { PCI_FIXUP_HEADER, PCI_ANY_ID, PCI_ANY_ID, + pcibios_name_device }, +#ifdef CONFIG_PPC_PMAC + { PCI_FIXUP_HEADER, PCI_VENDOR_ID_SERVERWORKS, 0x0240, + fixup_k2_sata }, +#endif { 0 } }; @@ -250,6 +262,9 @@ case phb_type_winnipeg: model = "PHB WP"; break; + case phb_type_apple: + model = "PHB APPLE"; + break; default: model = "PHB UK"; break; @@ -332,8 +347,9 @@ pci_assign_unassigned_resources(); #endif - /* Call machine dependent fixup */ - pcibios_final_fixup(); + /* Call machine dependent final fixup */ + if (ppc_md.pcibios_fixup) + ppc_md.pcibios_fixup(); /* Cache the location of the ISA bridge (if we have one) */ ppc64_isabridge_dev = pci_find_class(PCI_CLASS_BRIDGE_ISA << 8, NULL); @@ -540,3 +556,25 @@ return ret; } + +#ifdef CONFIG_PPC_PSERIES +static ssize_t pci_show_devspec(struct device *dev, char *buf) +{ + struct pci_dev *pdev; + struct device_node *np; + + pdev = to_pci_dev (dev); + np = pci_device_to_OF_node(pdev); + if (np == NULL || np->full_name == NULL) + return 0; + return sprintf(buf, "%s", np->full_name); +} +static DEVICE_ATTR(devspec, S_IRUGO, pci_show_devspec, NULL); +#endif /* CONFIG_PPC_PSERIES */ + +void pcibios_add_platform_entries(struct pci_dev *pdev) +{ +#ifdef CONFIG_PPC_PSERIES + device_create_file(&pdev->dev, &dev_attr_devspec); +#endif /* CONFIG_PPC_PSERIES */ +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pci_dma.c linux-2.6.3-rc3/arch/ppc64/kernel/pci_dma.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pci_dma.c 2004-02-03 19:43:57.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pci_dma.c 2004-02-14 19:31:00.000000000 -0800 @@ -1002,7 +1002,7 @@ * Returns the virtual address of the buffer and sets dma_handle * to the dma address (tce) of the first page. */ -void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, +static void *tce_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle) { struct TceTable * tbl; @@ -1055,7 +1055,7 @@ return ret; } -void pci_free_consistent(struct pci_dev *hwdev, size_t size, +static void tce_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle) { struct TceTable * tbl; @@ -1089,7 +1089,7 @@ * need not be page aligned, the dma_addr_t returned will point to the same * byte within the page as vaddr. */ -dma_addr_t pci_map_single(struct pci_dev *hwdev, void *vaddr, +static dma_addr_t tce_map_single(struct pci_dev *hwdev, void *vaddr, size_t size, int direction ) { struct TceTable * tbl; @@ -1124,7 +1124,7 @@ return dma_handle; } -void pci_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction ) +static void tce_unmap_single( struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction ) { struct TceTable * tbl; unsigned order, nPages; @@ -1354,7 +1354,7 @@ return dmaAddr; } -int pci_map_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction ) +static int tce_map_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction ) { struct TceTable * tbl; unsigned numTces; @@ -1389,7 +1389,7 @@ return num_dma; } -void pci_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int direction ) +static void tce_unmap_sg( struct pci_dev *hwdev, struct scatterlist *sg, int nelms, int direction ) { struct TceTable * tbl; unsigned order, numTces, i; @@ -1430,7 +1430,7 @@ } #else -int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, +static int tce_map_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { int i; @@ -1448,7 +1448,7 @@ return nelems; } -void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, +static void tce_unmap_sg(struct pci_dev *pdev, struct scatterlist *sglist, int nelems, int direction) { while (nelems--) { @@ -1465,7 +1465,15 @@ { ppc_md.tce_build = tce_build_pSeries; ppc_md.tce_free_one = tce_free_one_pSeries; + + pci_dma_ops.pci_alloc_consistent = tce_alloc_consistent; + pci_dma_ops.pci_free_consistent = tce_free_consistent; + pci_dma_ops.pci_map_single = tce_map_single; + pci_dma_ops.pci_unmap_single = tce_unmap_single; + pci_dma_ops.pci_map_sg = tce_map_sg; + pci_dma_ops.pci_unmap_sg = tce_unmap_sg; } + #endif #ifdef CONFIG_PPC_ISERIES @@ -1473,5 +1481,12 @@ { ppc_md.tce_build = tce_build_iSeries; ppc_md.tce_free_one = tce_free_one_iSeries; + + pci_dma_ops.pci_alloc_consistent = tce_alloc_consistent; + pci_dma_ops.pci_free_consistent = tce_free_consistent; + pci_dma_ops.pci_map_single = tce_map_single; + pci_dma_ops.pci_unmap_single = tce_unmap_single; + pci_dma_ops.pci_map_sg = tce_map_sg; + pci_dma_ops.pci_unmap_sg = tce_unmap_sg; } #endif diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pci_dma_direct.c linux-2.6.3-rc3/arch/ppc64/kernel/pci_dma_direct.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pci_dma_direct.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pci_dma_direct.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,88 @@ +/* + * Support for DMA from PCI devices to main memory on + * machines without an iommu or with directly addressable + * RAM (typically a pmac with 2Gb of RAM or less) + * + * Copyright (C) 2003 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "pci.h" + +static void *pci_direct_alloc_consistent(struct pci_dev *hwdev, size_t size, + dma_addr_t *dma_handle) +{ + void *ret; + + ret = (void *)__get_free_pages(GFP_ATOMIC, get_order(size)); + if (ret != NULL) { + memset(ret, 0, size); + *dma_handle = virt_to_absolute((unsigned long)ret); + } + return ret; +} + +static void pci_direct_free_consistent(struct pci_dev *hwdev, size_t size, + void *vaddr, dma_addr_t dma_handle) +{ + free_pages((unsigned long)vaddr, get_order(size)); +} + +static dma_addr_t pci_direct_map_single(struct pci_dev *hwdev, void *ptr, + size_t size, int direction) +{ + return virt_to_absolute((unsigned long)ptr); +} + +static void pci_direct_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, + size_t size, int direction) +{ +} + +static int pci_direct_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ + int i; + + for (i = 0; i < nents; i++, sg++) { + sg->dma_address = page_to_phys(sg->page) + sg->offset; + sg->dma_length = sg->length; + } + + return nents; +} + +static void pci_direct_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, + int nents, int direction) +{ +} + +void __init pci_dma_init_direct(void) +{ + pci_dma_ops.pci_alloc_consistent = pci_direct_alloc_consistent; + pci_dma_ops.pci_free_consistent = pci_direct_free_consistent; + pci_dma_ops.pci_map_single = pci_direct_map_single; + pci_dma_ops.pci_unmap_single = pci_direct_unmap_single; + pci_dma_ops.pci_map_sg = pci_direct_map_sg; + pci_dma_ops.pci_unmap_sg = pci_direct_unmap_sg; +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pci_dn.c linux-2.6.3-rc3/arch/ppc64/kernel/pci_dn.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pci_dn.c 2004-02-03 19:45:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pci_dn.c 2004-02-14 19:31:00.000000000 -0800 @@ -181,6 +181,7 @@ } return dn; } +EXPORT_SYMBOL(fetch_dev_dn); /****************************************************************** diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac.h linux-2.6.3-rc3/arch/ppc64/kernel/pmac.h --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac.h 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,32 @@ +#ifndef __PMAC_H__ +#define __PMAC_H__ + +#include +#include + +/* + * Declaration for the various functions exported by the + * pmac_* files. Mostly for use by pmac_setup + */ + +extern void pmac_get_boot_time(struct rtc_time *tm); +extern void pmac_get_rtc_time(struct rtc_time *tm); +extern int pmac_set_rtc_time(struct rtc_time *tm); +extern void pmac_read_rtc_time(void); +extern void pmac_calibrate_decr(void); + +extern void pmac_pcibios_fixup(void); +extern void pmac_pci_init(void); +extern void pmac_setup_pci_dma(void); +extern void fixup_k2_sata(struct pci_dev* dev); +extern void pmac_check_ht_link(void); + +extern void pmac_setup_smp(void); + +extern unsigned long pmac_ide_get_base(int index); +extern void pmac_ide_init_hwif_ports(hw_regs_t *hw, + unsigned long data_port, unsigned long ctrl_port, int *irq); + +extern void pmac_nvram_init(void); + +#endif /* __PMAC_H__ */ diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac_feature.c linux-2.6.3-rc3/arch/ppc64/kernel/pmac_feature.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac_feature.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac_feature.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,654 @@ +/* + * arch/ppc/platforms/pmac_feature.c + * + * Copyright (C) 1996-2001 Paul Mackerras (paulus@cs.anu.edu.au) + * Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * TODO: + * + * - Replace mdelay with some schedule loop if possible + * - Shorten some obfuscated delays on some routines (like modem + * power) + * - Refcount some clocks (see darwin) + * - Split split split... + * + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG_FEATURE + +#ifdef DEBUG_FEATURE +#define DBG(fmt,...) printk(KERN_DEBUG fmt) +#else +#define DBG(fmt,...) +#endif + +/* + * We use a single global lock to protect accesses. Each driver has + * to take care of its own locking + */ +static spinlock_t feature_lock __pmacdata = SPIN_LOCK_UNLOCKED; + +#define LOCK(flags) spin_lock_irqsave(&feature_lock, flags); +#define UNLOCK(flags) spin_unlock_irqrestore(&feature_lock, flags); + + +/* + * Instance of some macio stuffs + */ +struct macio_chip macio_chips[MAX_MACIO_CHIPS] __pmacdata; + +struct macio_chip* __pmac +macio_find(struct device_node* child, int type) +{ + while(child) { + int i; + + for (i=0; i < MAX_MACIO_CHIPS && macio_chips[i].of_node; i++) + if (child == macio_chips[i].of_node && + (!type || macio_chips[i].type == type)) + return &macio_chips[i]; + child = child->parent; + } + return NULL; +} + +static const char* macio_names[] __pmacdata = +{ + "Unknown", + "Grand Central", + "OHare", + "OHareII", + "Heathrow", + "Gatwick", + "Paddington", + "Keylargo", + "Pangea", + "Intrepid", + "K2" +}; + + + +/* + * Uninorth reg. access. Note that Uni-N regs are big endian + */ + +#define UN_REG(r) (uninorth_base + ((r) >> 2)) +#define UN_IN(r) (in_be32(UN_REG(r))) +#define UN_OUT(r,v) (out_be32(UN_REG(r), (v))) +#define UN_BIS(r,v) (UN_OUT((r), UN_IN(r) | (v))) +#define UN_BIC(r,v) (UN_OUT((r), UN_IN(r) & ~(v))) + +static struct device_node* uninorth_node __pmacdata; +static u32* uninorth_base __pmacdata; +static u32 uninorth_rev __pmacdata; +static void *u3_ht; + +extern struct pci_dev *k2_skiplist[2]; + +/* + * For each motherboard family, we have a table of functions pointers + * that handle the various features. + */ + +typedef long (*feature_call)(struct device_node* node, long param, long value); + +struct feature_table_entry { + unsigned int selector; + feature_call function; +}; + +struct pmac_mb_def +{ + const char* model_string; + const char* model_name; + int model_id; + struct feature_table_entry* features; + unsigned long board_flags; +}; +static struct pmac_mb_def pmac_mb __pmacdata; + +/* + * Here are the chip specific feature functions + */ + + +static long __pmac g5_read_gpio(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + + return MACIO_IN8(param); +} + + +static long __pmac g5_write_gpio(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + + MACIO_OUT8(param, (u8)(value & 0xff)); + return 0; +} + +static long __pmac g5_gmac_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + unsigned long flags; + struct pci_dev *pdev = NULL; + + if (node == NULL) + return -ENODEV; + + /* XXX FIXME: We should fix pci_device_from_OF_node here, and + * get to a real pci_dev or we'll get into trouble with PCI + * domains the day we get overlapping numbers (like if we ever + * decide to show the HT root. + * Note that we only get the slot when value is 0. This is called + * early during boot with value 1 to enable all devices, at which + * point, we don't yet have probed pci_find_slot, so it would fail + * to look for the slot at this point. + */ + if (!value) + pdev = pci_find_slot(node->busno, node->devfn); + + LOCK(flags); + if (value) { + MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); + mb(); + k2_skiplist[0] = NULL; + } else { + k2_skiplist[0] = pdev; + mb(); + MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_GMAC_CLK_ENABLE); + } + + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long __pmac g5_fw_enable(struct device_node* node, long param, long value) +{ + struct macio_chip* macio = &macio_chips[0]; + unsigned long flags; + struct pci_dev *pdev = NULL; + + /* XXX FIXME: We should fix pci_device_from_OF_node here, and + * get to a real pci_dev or we'll get into trouble with PCI + * domains the day we get overlapping numbers (like if we ever + * decide to show the HT root + * Note that we only get the slot when value is 0. This is called + * early during boot with value 1 to enable all devices, at which + * point, we don't yet have probed pci_find_slot, so it would fail + * to look for the slot at this point. + */ + if (node == NULL) + return -ENODEV; + + if (!value) + pdev = pci_find_slot(node->busno, node->devfn); + + LOCK(flags); + if (value) { + MACIO_BIS(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); + mb(); + k2_skiplist[1] = NULL; + } else { + k2_skiplist[0] = pdev; + mb(); + MACIO_BIC(KEYLARGO_FCR1, K2_FCR1_FW_CLK_ENABLE); + } + + UNLOCK(flags); + mdelay(1); + + return 0; +} + +static long __pmac g5_mpic_enable(struct device_node* node, long param, long value) +{ + unsigned long flags; + + if (node->parent == NULL || strcmp(node->parent->name, "u3")) + return 0; + + LOCK(flags); + UN_BIS(U3_TOGGLE_REG, U3_MPIC_RESET | U3_MPIC_OUTPUT_ENABLE); + UNLOCK(flags); + + return 0; +} + +#ifdef CONFIG_SMP +static long __pmac g5_reset_cpu(struct device_node* node, long param, long value) +{ + unsigned int reset_io = 0; + unsigned long flags; + struct macio_chip* macio; + struct device_node* np; + + macio = &macio_chips[0]; + if (macio->type != macio_keylargo2) + return -ENODEV; + + np = find_path_device("/cpus"); + if (np == NULL) + return -ENODEV; + for (np = np->child; np != NULL; np = np->sibling) { + u32* num = (u32 *)get_property(np, "reg", NULL); + u32* rst = (u32 *)get_property(np, "soft-reset", NULL); + if (num == NULL || rst == NULL) + continue; + if (param == *num) { + reset_io = *rst; + break; + } + } + if (np == NULL || reset_io == 0) + return -ENODEV; + + LOCK(flags); + MACIO_OUT8(reset_io, KEYLARGO_GPIO_OUTPUT_ENABLE); + (void)MACIO_IN8(reset_io); + udelay(1); + MACIO_OUT8(reset_io, 0); + (void)MACIO_IN8(reset_io); + UNLOCK(flags); + + return 0; +} +#endif /* CONFIG_SMP */ + +/* + * This can be called from pmac_smp so isn't static + * + * This takes the second CPU off the bus on dual CPU machines + * running UP + */ +void __pmac g5_phy_disable_cpu1(void) +{ + UN_OUT(U3_API_PHY_CONFIG_1, 0); +} + +static long __pmac generic_get_mb_info(struct device_node* node, long param, long value) +{ + switch(param) { + case PMAC_MB_INFO_MODEL: + return pmac_mb.model_id; + case PMAC_MB_INFO_FLAGS: + return pmac_mb.board_flags; + case PMAC_MB_INFO_NAME: + /* hack hack hack... but should work */ + *((const char **)value) = pmac_mb.model_name; + return 0; + } + return -EINVAL; +} + + +/* + * Table definitions + */ + +/* Used on any machine + */ +static struct feature_table_entry any_features[] __pmacdata = { + { PMAC_FTR_GET_MB_INFO, generic_get_mb_info }, + { 0, NULL } +}; + +/* G5 features + */ +static struct feature_table_entry g5_features[] __pmacdata = { + { PMAC_FTR_GMAC_ENABLE, g5_gmac_enable }, + { PMAC_FTR_1394_ENABLE, g5_fw_enable }, + { PMAC_FTR_ENABLE_MPIC, g5_mpic_enable }, + { PMAC_FTR_READ_GPIO, g5_read_gpio }, + { PMAC_FTR_WRITE_GPIO, g5_write_gpio }, +#ifdef CONFIG_SMP + { PMAC_FTR_RESET_CPU, g5_reset_cpu }, +#endif /* CONFIG_SMP */ + { 0, NULL } +}; + +static struct pmac_mb_def pmac_mb_defs[] __pmacdata = { + { "PowerMac7,2", "PowerMac G5", + PMAC_TYPE_POWERMAC_G5, g5_features, + 0, + }, +}; + +/* + * The toplevel feature_call callback + */ +long __pmac pmac_do_feature_call(unsigned int selector, ...) +{ + struct device_node* node; + long param, value; + int i; + feature_call func = NULL; + va_list args; + + if (pmac_mb.features) + for (i=0; pmac_mb.features[i].function; i++) + if (pmac_mb.features[i].selector == selector) { + func = pmac_mb.features[i].function; + break; + } + if (!func) + for (i=0; any_features[i].function; i++) + if (any_features[i].selector == selector) { + func = any_features[i].function; + break; + } + if (!func) + return -ENODEV; + + va_start(args, selector); + node = (struct device_node*)va_arg(args, void*); + param = va_arg(args, long); + value = va_arg(args, long); + va_end(args); + + return func(node, param, value); +} + +static int __init probe_motherboard(void) +{ + int i; + struct macio_chip* macio = &macio_chips[0]; + const char* model = NULL; + struct device_node *dt; + + /* Lookup known motherboard type in device-tree. First try an + * exact match on the "model" property, then try a "compatible" + * match is none is found. + */ + dt = find_devices("device-tree"); + if (dt != NULL) + model = (const char *) get_property(dt, "model", NULL); + for(i=0; model && i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { + if (strcmp(model, pmac_mb_defs[i].model_string) == 0) { + pmac_mb = pmac_mb_defs[i]; + goto found; + } + } + for(i=0; i<(sizeof(pmac_mb_defs)/sizeof(struct pmac_mb_def)); i++) { + if (machine_is_compatible(pmac_mb_defs[i].model_string)) { + pmac_mb = pmac_mb_defs[i]; + goto found; + } + } + + /* Fallback to selection depending on mac-io chip type */ + switch(macio->type) { + case macio_keylargo2: + pmac_mb.model_id = PMAC_TYPE_UNKNOWN_K2; + pmac_mb.model_name = "Unknown K2-based"; + pmac_mb.features = g5_features; + + default: + return -ENODEV; + } +found: + /* Check for "mobile" machine */ + if (model && (strncmp(model, "PowerBook", 9) == 0 + || strncmp(model, "iBook", 5) == 0)) + pmac_mb.board_flags |= PMAC_MB_MOBILE; + + + printk(KERN_INFO "PowerMac motherboard: %s\n", pmac_mb.model_name); + return 0; +} + +/* Initialize the Core99 UniNorth host bridge and memory controller + */ +static void __init probe_uninorth(void) +{ + uninorth_node = of_find_node_by_name(NULL, "u3"); + if (uninorth_node && uninorth_node->n_addrs > 0) { + /* Small hack until I figure out if parsing in prom.c is correct. I should + * get rid of those pre-parsed junk anyway + */ + unsigned long address = uninorth_node->addrs[0].address; + uninorth_base = ioremap(address, 0x40000); + uninorth_rev = in_be32(UN_REG(UNI_N_VERSION)); + u3_ht = ioremap(address + U3_HT_CONFIG_BASE, 0x1000); + } else + uninorth_node = NULL; + + if (!uninorth_node) + return; + + printk(KERN_INFO "Found U3 memory controller & host bridge, revision: %d\n", + uninorth_rev); + printk(KERN_INFO "Mapped at 0x%08lx\n", (unsigned long)uninorth_base); + +} + +static void __init probe_one_macio(const char* name, const char* compat, int type) +{ + struct device_node* node; + int i; + volatile u32* base; + u32* revp; + + node = find_devices(name); + if (!node || !node->n_addrs) + return; + if (compat) + do { + if (device_is_compatible(node, compat)) + break; + node = node->next; + } while (node); + if (!node) + return; + for(i=0; i= MAX_MACIO_CHIPS) { + printk(KERN_ERR "pmac_feature: Please increase MAX_MACIO_CHIPS !\n"); + printk(KERN_ERR "pmac_feature: %s skipped\n", node->full_name); + return; + } + base = (volatile u32*)ioremap(node->addrs[0].address, node->addrs[0].size); + if (!base) { + printk(KERN_ERR "pmac_feature: Can't map mac-io chip !\n"); + return; + } + if (type == macio_keylargo) { + u32* did = (u32 *)get_property(node, "device-id", NULL); + if (*did == 0x00000025) + type = macio_pangea; + if (*did == 0x0000003e) + type = macio_intrepid; + } + macio_chips[i].of_node = node; + macio_chips[i].type = type; + macio_chips[i].base = base; + macio_chips[i].flags = MACIO_FLAG_SCCB_ON | MACIO_FLAG_SCCB_ON; + macio_chips[i].name = macio_names[type]; + revp = (u32 *)get_property(node, "revision-id", NULL); + if (revp) + macio_chips[i].rev = *revp; + printk(KERN_INFO "Found a %s mac-io controller, rev: %d, mapped at 0x%p\n", + macio_names[type], macio_chips[i].rev, macio_chips[i].base); +} + +static int __init +probe_macios(void) +{ + probe_one_macio("mac-io", "K2-Keylargo", macio_keylargo2); + + macio_chips[0].lbus.index = 0; + macio_chips[1].lbus.index = 1; + + return (macio_chips[0].of_node == NULL) ? -ENODEV : 0; +} + +static void __init +set_initial_features(void) +{ + struct device_node *np; + + if (macio_chips[0].type == macio_keylargo2) { +#ifndef CONFIG_SMP + /* On SMP machines running UP, we have the second CPU eating + * bus cycles. We need to take it off the bus. This is done + * from pmac_smp for SMP kernels running on one CPU + */ + np = of_find_node_by_type(NULL, "cpu"); + if (np != NULL) + np = of_find_node_by_type(np, "cpu"); + if (np != NULL) { + g5_phy_disable_cpu1(); + of_node_put(np); + } +#endif /* CONFIG_SMP */ + /* Enable GMAC for now for PCI probing. It will be disabled + * later on after PCI probe + */ + np = of_find_node_by_name(NULL, "ethernet"); + while(np) { + if (device_is_compatible(np, "K2-GMAC")) + g5_gmac_enable(np, 0, 1); + np = of_find_node_by_name(np, "ethernet"); + } + + /* Enable FW before PCI probe. Will be disabled later on + * Note: We should have a batter way to check that we are + * dealing with uninorth internal cell and not a PCI cell + * on the external PCI. The code below works though. + */ + np = of_find_node_by_name(NULL, "firewire"); + while(np) { + if (device_is_compatible(np, "pci106b,5811")) { + macio_chips[0].flags |= MACIO_FLAG_FW_SUPPORTED; + g5_fw_enable(np, 0, 1); + } + np = of_find_node_by_name(np, "firewire"); + } + } +} + +void __init +pmac_feature_init(void) +{ + /* Detect the UniNorth memory controller */ + probe_uninorth(); + + /* Probe mac-io controllers */ + if (probe_macios()) { + printk(KERN_WARNING "No mac-io chip found\n"); + return; + } + + /* Setup low-level i2c stuffs */ + pmac_init_low_i2c(); + + /* Probe machine type */ + if (probe_motherboard()) + printk(KERN_WARNING "Unknown PowerMac !\n"); + + /* Set some initial features (turn off some chips that will + * be later turned on) + */ + set_initial_features(); +} + +int __init pmac_feature_late_init(void) +{ +#if 0 + struct device_node* np; + + /* Request some resources late */ + if (uninorth_node) + request_OF_resource(uninorth_node, 0, NULL); + np = find_devices("hammerhead"); + if (np) + request_OF_resource(np, 0, NULL); + np = find_devices("interrupt-controller"); + if (np) + request_OF_resource(np, 0, NULL); +#endif + return 0; +} + +device_initcall(pmac_feature_late_init); + + +static void dump_HT_speeds(char *name, u32 cfg, u32 frq) +{ + int freqs[16] = { 200,300,400,500,600,800,1000,0,0,0,0,0,0,0,0,0 }; + int bits[8] = { 8,16,0,32,2,4,0,0 }; + int freq = (frq >> 8) & 0xf; + + if (freqs[freq] == 0) + printk("%s: Unknown HT link frequency %x\n", name, freq); + else + printk("%s: %d MHz on main link, (%d in / %d out) bits width\n", + name, freqs[freq], + bits[(cfg >> 28) & 0x7], bits[(cfg >> 24) & 0x7]); +} + +void __init pmac_check_ht_link(void) +{ +#if 0 /* Disabled for now */ + u32 ufreq, freq, ucfg, cfg; + struct device_node *pcix_node; + u8 px_bus, px_devfn; + struct pci_controller *px_hose; + + (void)in_be32(u3_ht + U3_HT_LINK_COMMAND); + ucfg = cfg = in_be32(u3_ht + U3_HT_LINK_CONFIG); + ufreq = freq = in_be32(u3_ht + U3_HT_LINK_FREQ); + dump_HT_speeds("U3 HyperTransport", cfg, freq); + + pcix_node = of_find_compatible_node(NULL, "pci", "pci-x"); + if (pcix_node == NULL) { + printk("No PCI-X bridge found\n"); + return; + } + px_hose = pcix_node->phb; + px_bus = pcix_node->busno; + px_devfn = pcix_node->devfn; + + early_read_config_dword(px_hose, px_bus, px_devfn, 0xc4, &cfg); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xcc, &freq); + dump_HT_speeds("PCI-X HT Uplink", cfg, freq); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xc8, &cfg); + early_read_config_dword(px_hose, px_bus, px_devfn, 0xd0, &freq); + dump_HT_speeds("PCI-X HT Downlink", cfg, freq); +#endif +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac_low_i2c.c linux-2.6.3-rc3/arch/ppc64/kernel/pmac_low_i2c.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac_low_i2c.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac_low_i2c.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,513 @@ +/* + * arch/ppc/platforms/pmac_low_i2c.c + * + * Copyright (C) 2003 Ben. Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * This file contains some low-level i2c access routines that + * need to be used by various bits of the PowerMac platform code + * at times where the real asynchronous & interrupt driven driver + * cannot be used. The API borrows some semantics from the darwin + * driver in order to ease the implementation of the platform + * properties parser + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LOW_I2C_HOST 4 + +#if 1 +#define DBG(x...) do {\ + printk(KERN_DEBUG "KW:" x); \ + } while(0) +#else +#define DBGG(x...) +#endif + +struct low_i2c_host; + +typedef int (*low_i2c_func_t)(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len); + +struct low_i2c_host +{ + struct device_node *np; /* OF device node */ + struct semaphore mutex; /* Access mutex for use by i2c-keywest */ + low_i2c_func_t func; /* Access function */ + int is_open : 1; /* Poor man's access control */ + int mode; /* Current mode */ + int channel; /* Current channel */ + int num_channels; /* Number of channels */ + unsigned long base; /* For keywest-i2c, base address */ + int bsteps; /* And register stepping */ + int speed; /* And speed */ +}; + +static struct low_i2c_host low_i2c_hosts[MAX_LOW_I2C_HOST]; + +/* No locking is necessary on allocation, we are running way before + * anything can race with us + */ +static struct low_i2c_host *find_low_i2c_host(struct device_node *np) +{ + int i; + + for (i = 0; i < MAX_LOW_I2C_HOST; i++) + if (low_i2c_hosts[i].np == np) + return &low_i2c_hosts[i]; + return NULL; +} + +/* + * + * i2c-keywest implementation (UniNorth, U2, U3, Keylargo's) + * + */ + +/* + * Keywest i2c definitions borrowed from drivers/i2c/i2c-keywest.h, + * should be moved somewhere in include/asm-ppc/ + */ +/* Register indices */ +typedef enum { + reg_mode = 0, + reg_control, + reg_status, + reg_isr, + reg_ier, + reg_addr, + reg_subaddr, + reg_data +} reg_t; + + +/* Mode register */ +#define KW_I2C_MODE_100KHZ 0x00 +#define KW_I2C_MODE_50KHZ 0x01 +#define KW_I2C_MODE_25KHZ 0x02 +#define KW_I2C_MODE_DUMB 0x00 +#define KW_I2C_MODE_STANDARD 0x04 +#define KW_I2C_MODE_STANDARDSUB 0x08 +#define KW_I2C_MODE_COMBINED 0x0C +#define KW_I2C_MODE_MODE_MASK 0x0C +#define KW_I2C_MODE_CHAN_MASK 0xF0 + +/* Control register */ +#define KW_I2C_CTL_AAK 0x01 +#define KW_I2C_CTL_XADDR 0x02 +#define KW_I2C_CTL_STOP 0x04 +#define KW_I2C_CTL_START 0x08 + +/* Status register */ +#define KW_I2C_STAT_BUSY 0x01 +#define KW_I2C_STAT_LAST_AAK 0x02 +#define KW_I2C_STAT_LAST_RW 0x04 +#define KW_I2C_STAT_SDA 0x08 +#define KW_I2C_STAT_SCL 0x10 + +/* IER & ISR registers */ +#define KW_I2C_IRQ_DATA 0x01 +#define KW_I2C_IRQ_ADDR 0x02 +#define KW_I2C_IRQ_STOP 0x04 +#define KW_I2C_IRQ_START 0x08 +#define KW_I2C_IRQ_MASK 0x0F + +/* State machine states */ +enum { + state_idle, + state_addr, + state_read, + state_write, + state_stop, + state_dead +}; + +#define WRONG_STATE(name) do {\ + printk(KERN_DEBUG "KW: wrong state. Got %s, state: %s (isr: %02x)\n", \ + name, __kw_state_names[state], isr); \ + } while(0) + +static const char *__kw_state_names[] = { + "state_idle", + "state_addr", + "state_read", + "state_write", + "state_stop", + "state_dead" +}; + +static inline u8 __kw_read_reg(struct low_i2c_host *host, reg_t reg) +{ + return in_8(((volatile u8 *)host->base) + + (((unsigned)reg) << host->bsteps)); +} + +static inline void __kw_write_reg(struct low_i2c_host *host, reg_t reg, u8 val) +{ + out_8(((volatile u8 *)host->base) + + (((unsigned)reg) << host->bsteps), val); + (void)__kw_read_reg(host, reg_subaddr); +} + +#define kw_write_reg(reg, val) __kw_write_reg(host, reg, val) +#define kw_read_reg(reg) __kw_read_reg(host, reg) + + +/* Don't schedule, the g5 fan controller is too + * timing sensitive + */ +static u8 kw_wait_interrupt(struct low_i2c_host* host) +{ + int i; + u8 isr; + + for (i = 0; i < 200000; i++) { + isr = kw_read_reg(reg_isr) & KW_I2C_IRQ_MASK; + if (isr != 0) + return isr; + udelay(1); + } + return isr; +} + +static int kw_handle_interrupt(struct low_i2c_host *host, int state, int rw, int *rc, u8 **data, int *len, u8 isr) +{ + u8 ack; + + if (isr == 0) { + if (state != state_stop) { + DBG("KW: Timeout !\n"); + *rc = -EIO; + goto stop; + } + if (state == state_stop) { + ack = kw_read_reg(reg_status); + if (!(ack & KW_I2C_STAT_BUSY)) { + state = state_idle; + kw_write_reg(reg_ier, 0x00); + } + } + return state; + } + + if (isr & KW_I2C_IRQ_ADDR) { + ack = kw_read_reg(reg_status); + if (state != state_addr) { + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); + WRONG_STATE("KW_I2C_IRQ_ADDR"); + *rc = -EIO; + goto stop; + } + if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { + *rc = -ENODEV; + DBG("KW: NAK on address\n"); + return state_stop; + } else { + if (rw) { + state = state_read; + if (*len > 1) + kw_write_reg(reg_control, KW_I2C_CTL_AAK); + } else { + state = state_write; + kw_write_reg(reg_data, **data); + (*data)++; (*len)--; + } + } + kw_write_reg(reg_isr, KW_I2C_IRQ_ADDR); + } + + if (isr & KW_I2C_IRQ_DATA) { + if (state == state_read) { + **data = kw_read_reg(reg_data); + (*data)++; (*len)--; + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + if ((*len) == 0) + state = state_stop; + else if ((*len) == 1) + kw_write_reg(reg_control, 0); + } else if (state == state_write) { + ack = kw_read_reg(reg_status); + if ((ack & KW_I2C_STAT_LAST_AAK) == 0) { + DBG("KW: nack on data write\n"); + *rc = -EIO; + goto stop; + } else if (*len) { + kw_write_reg(reg_data, **data); + (*data)++; (*len)--; + } else { + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + state = state_stop; + *rc = 0; + } + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + } else { + kw_write_reg(reg_isr, KW_I2C_IRQ_DATA); + WRONG_STATE("KW_I2C_IRQ_DATA"); + if (state != state_stop) { + *rc = -EIO; + goto stop; + } + } + } + + if (isr & KW_I2C_IRQ_STOP) { + kw_write_reg(reg_isr, KW_I2C_IRQ_STOP); + if (state != state_stop) { + WRONG_STATE("KW_I2C_IRQ_STOP"); + *rc = -EIO; + } + return state_idle; + } + + if (isr & KW_I2C_IRQ_START) + kw_write_reg(reg_isr, KW_I2C_IRQ_START); + + return state; + + stop: + kw_write_reg(reg_control, KW_I2C_CTL_STOP); + return state_stop; +} + +static int keywest_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 subaddr, u8 *data, int len) +{ + u8 mode_reg = host->speed; + int state = state_addr; + int rc = 0; + + /* Setup mode & subaddress if any */ + switch(host->mode) { + case pmac_low_i2c_mode_dumb: + printk(KERN_ERR "low_i2c: Dumb mode not supported !\n"); + return -EINVAL; + case pmac_low_i2c_mode_std: + mode_reg |= KW_I2C_MODE_STANDARD; + break; + case pmac_low_i2c_mode_stdsub: + mode_reg |= KW_I2C_MODE_STANDARDSUB; + kw_write_reg(reg_subaddr, subaddr); + break; + case pmac_low_i2c_mode_combined: + mode_reg |= KW_I2C_MODE_COMBINED; + kw_write_reg(reg_subaddr, subaddr); + break; + } + + /* Setup channel & clear pending irqs */ + kw_write_reg(reg_isr, kw_read_reg(reg_isr)); + kw_write_reg(reg_mode, mode_reg | (host->channel << 4)); + kw_write_reg(reg_status, 0); + + /* Set up address and r/w bit */ + kw_write_reg(reg_addr, addr); + + /* Start sending address & disable interrupt*/ + kw_write_reg(reg_ier, 0 /*KW_I2C_IRQ_MASK*/); + kw_write_reg(reg_control, KW_I2C_CTL_XADDR); + + /* State machine, to turn into an interrupt handler */ + while(state != state_idle) { + u8 isr = kw_wait_interrupt(host); + state = kw_handle_interrupt(host, state, addr & 1, &rc, &data, &len, isr); + } + + return rc; +} + +static void keywest_low_i2c_add(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(NULL); + unsigned long *psteps, *prate, steps, aoffset = 0; + struct device_node *parent; + + if (host == NULL) { + printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", + np->full_name); + return; + } + memset(host, 0, sizeof(*host)); + + init_MUTEX(&host->mutex); + host->np = of_node_get(np); + psteps = (unsigned long *)get_property(np, "AAPL,address-step", NULL); + steps = psteps ? (*psteps) : 0x10; + for (host->bsteps = 0; (steps & 0x01) == 0; host->bsteps++) + steps >>= 1; + parent = of_get_parent(np); + host->num_channels = 1; + if (parent && parent->name[0] == 'u') { + host->num_channels = 2; + aoffset = 3; + } + /* Select interface rate */ + host->speed = KW_I2C_MODE_100KHZ; + prate = (unsigned long *)get_property(np, "AAPL,i2c-rate", NULL); + if (prate) switch(*prate) { + case 100: + host->speed = KW_I2C_MODE_100KHZ; + break; + case 50: + host->speed = KW_I2C_MODE_50KHZ; + break; + case 25: + host->speed = KW_I2C_MODE_25KHZ; + break; + } + host->mode = pmac_low_i2c_mode_std; + host->base = (unsigned long)ioremap(np->addrs[0].address + aoffset, + np->addrs[0].size); + host->func = keywest_low_i2c_func; +} + +/* + * + * PMU implementation + * + */ + + +#ifdef CONFIG_ADB_PMU + +static int pmu_low_i2c_func(struct low_i2c_host *host, u8 addr, u8 sub, u8 *data, int len) +{ + // TODO + return -ENODEV; +} + +static void pmu_low_i2c_add(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(NULL); + + if (host == NULL) { + printk(KERN_ERR "low_i2c: Can't allocate host for %s\n", + np->full_name); + return; + } + memset(host, 0, sizeof(*host)); + + init_MUTEX(&host->mutex); + host->np = of_node_get(np); + host->num_channels = 3; + host->mode = pmac_low_i2c_mode_std; + host->func = pmu_low_i2c_func; +} + +#endif /* CONFIG_ADB_PMU */ + +void __init pmac_init_low_i2c(void) +{ + struct device_node *np; + + /* Probe keywest-i2c busses */ + np = of_find_compatible_node(NULL, "i2c", "keywest-i2c"); + while(np) { + keywest_low_i2c_add(np); + np = of_find_compatible_node(np, "i2c", "keywest-i2c"); + } + +#ifdef CONFIG_ADB_PMU + /* Probe PMU busses */ + np = of_find_node_by_name(NULL, "via-pmu"); + if (np) + pmu_low_i2c_add(np); +#endif /* CONFIG_ADB_PMU */ + + /* TODO: Add CUDA support as well */ +} + +int pmac_low_i2c_lock(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + down(&host->mutex); + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_lock); + +int pmac_low_i2c_unlock(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + up(&host->mutex); + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_unlock); + + +int pmac_low_i2c_open(struct device_node *np, int channel) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + + if (channel >= host->num_channels) + return -EINVAL; + + down(&host->mutex); + host->is_open = 1; + host->channel = channel; + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_open); + +int pmac_low_i2c_close(struct device_node *np) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + + host->is_open = 0; + up(&host->mutex); + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_close); + +int pmac_low_i2c_setmode(struct device_node *np, int mode) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + WARN_ON(!host->is_open); + host->mode = mode; + + return 0; +} +EXPORT_SYMBOL(pmac_low_i2c_setmode); + +int pmac_low_i2c_xfer(struct device_node *np, u8 addrdir, u8 subaddr, u8 *data, int len) +{ + struct low_i2c_host *host = find_low_i2c_host(np); + + if (!host) + return -ENODEV; + WARN_ON(!host->is_open); + + return host->func(host, addrdir, subaddr, data, len); +} +EXPORT_SYMBOL(pmac_low_i2c_xfer); + diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac_nvram.c linux-2.6.3-rc3/arch/ppc64/kernel/pmac_nvram.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac_nvram.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac_nvram.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,495 @@ +/* + * arch/ppc/platforms/pmac_nvram.c + * + * Copyright (C) 2002 Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + * Todo: - add support for the OF persistent properties + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +#define NVRAM_SIZE 0x2000 /* 8kB of non-volatile RAM */ + +#define CORE99_SIGNATURE 0x5a +#define CORE99_ADLER_START 0x14 + +/* On Core99, nvram is either a sharp, a micron or an AMD flash */ +#define SM_FLASH_STATUS_DONE 0x80 +#define SM_FLASH_STATUS_ERR 0x38 + +#define SM_FLASH_CMD_ERASE_CONFIRM 0xd0 +#define SM_FLASH_CMD_ERASE_SETUP 0x20 +#define SM_FLASH_CMD_RESET 0xff +#define SM_FLASH_CMD_WRITE_SETUP 0x40 +#define SM_FLASH_CMD_CLEAR_STATUS 0x50 +#define SM_FLASH_CMD_READ_STATUS 0x70 + +/* CHRP NVRAM header */ +struct chrp_header { + u8 signature; + u8 cksum; + u16 len; + char name[12]; + u8 data[0]; +}; + +struct core99_header { + struct chrp_header hdr; + u32 adler; + u32 generation; + u32 reserved[2]; +}; + +/* + * Read and write the non-volatile RAM on PowerMacs and CHRP machines. + */ +static volatile unsigned char *nvram_data; +static int core99_bank = 0; +// XXX Turn that into a sem +static spinlock_t nv_lock = SPIN_LOCK_UNLOCKED; + +extern int system_running; + +static int (*core99_write_bank)(int bank, u8* datas); +static int (*core99_erase_bank)(int bank); + +static char *nvram_image __pmacdata; + + +static ssize_t __pmac core99_nvram_read(char *buf, size_t count, loff_t *index) +{ + int i; + + if (nvram_image == NULL) + return -ENODEV; + if (*index > NVRAM_SIZE) + return 0; + + i = *index; + if (i + count > NVRAM_SIZE) + count = NVRAM_SIZE - i; + + memcpy(buf, &nvram_image[i], count); + *index = i + count; + return count; +} + +static ssize_t __pmac core99_nvram_write(char *buf, size_t count, loff_t *index) +{ + int i; + + if (nvram_image == NULL) + return -ENODEV; + if (*index > NVRAM_SIZE) + return 0; + + i = *index; + if (i + count > NVRAM_SIZE) + count = NVRAM_SIZE - i; + + memcpy(&nvram_image[i], buf, count); + *index = i + count; + return count; +} + +static ssize_t __pmac core99_nvram_size(void) +{ + if (nvram_image == NULL) + return -ENODEV; + return NVRAM_SIZE; +} + +static u8 __pmac chrp_checksum(struct chrp_header* hdr) +{ + u8 *ptr; + u16 sum = hdr->signature; + for (ptr = (u8 *)&hdr->len; ptr < hdr->data; ptr++) + sum += *ptr; + while (sum > 0xFF) + sum = (sum & 0xFF) + (sum>>8); + return sum; +} + +static u32 __pmac core99_calc_adler(u8 *buffer) +{ + int cnt; + u32 low, high; + + buffer += CORE99_ADLER_START; + low = 1; + high = 0; + for (cnt=0; cnt<(NVRAM_SIZE-CORE99_ADLER_START); cnt++) { + if ((cnt % 5000) == 0) { + high %= 65521UL; + high %= 65521UL; + } + low += buffer[cnt]; + high += low; + } + low %= 65521UL; + high %= 65521UL; + + return (high << 16) | low; +} + +static u32 __pmac core99_check(u8* datas) +{ + struct core99_header* hdr99 = (struct core99_header*)datas; + + if (hdr99->hdr.signature != CORE99_SIGNATURE) { + DBG("Invalid signature\n"); + return 0; + } + if (hdr99->hdr.cksum != chrp_checksum(&hdr99->hdr)) { + DBG("Invalid checksum\n"); + return 0; + } + if (hdr99->adler != core99_calc_adler(datas)) { + DBG("Invalid adler\n"); + return 0; + } + return hdr99->generation; +} + +static int __pmac sm_erase_bank(int bank) +{ + int stat, i; + unsigned long timeout; + + u8* base = (u8 *)nvram_data + core99_bank*NVRAM_SIZE; + + DBG("nvram: Sharp/Micron Erasing bank %d...\n", bank); + + out_8(base, SM_FLASH_CMD_ERASE_SETUP); + out_8(base, SM_FLASH_CMD_ERASE_CONFIRM); + timeout = 0; + do { + if (++timeout > 1000000) { + printk(KERN_ERR "nvram: Sharp/Miron flash erase timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: Sharp/Micron flash write timeout !\n"); + break; + } + out_8(base, SM_FLASH_CMD_READ_STATUS); + stat = in_8(base); + } while (!(stat & SM_FLASH_STATUS_DONE)); + if (!(stat & SM_FLASH_STATUS_DONE)) + break; + } + out_8(base, SM_FLASH_CMD_CLEAR_STATUS); + out_8(base, SM_FLASH_CMD_RESET); + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash erase timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + + for (i=0; i 1000000) { + printk(KERN_ERR "nvram: AMD flash write timeout !\n"); + break; + } + stat = in_8(base) ^ in_8(base); + } while (stat != 0); + if (stat != 0) + break; + } + + /* Reset */ + out_8(base, 0xf0); + udelay(1); + + for (i=0; igeneration++; + 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) + if (core99_erase_bank(core99_bank)) { + printk("nvram: Error erasing bank %d\n", core99_bank); + goto bail; + } + if (core99_write_bank) + if (core99_write_bank(core99_bank, nvram_image)) + printk("nvram: Error writing bank %d\n", core99_bank); + bail: + spin_unlock_irqrestore(&nv_lock, flags); + + return 0; +} + +int __init pmac_nvram_init(void) +{ + struct device_node *dp; + u32 gen_bank0, gen_bank1; + int i; + + dp = find_devices("nvram"); + if (dp == NULL) { + printk(KERN_ERR "Can't find NVRAM device\n"); + return -ENODEV; + } + if (!device_is_compatible(dp, "nvram,flash")) { + printk(KERN_ERR "Incompatible type of NVRAM\n"); + return -ENXIO; + } + + nvram_image = alloc_bootmem(NVRAM_SIZE); + if (nvram_image == NULL) { + printk(KERN_ERR "nvram: can't allocate ram image\n"); + return -ENOMEM; + } + nvram_data = ioremap(dp->addrs[0].address, NVRAM_SIZE*2); + + DBG("nvram: Checking bank 0...\n"); + + gen_bank0 = core99_check((u8 *)nvram_data); + gen_bank1 = core99_check((u8 *)nvram_data + NVRAM_SIZE); + core99_bank = (gen_bank0 < gen_bank1) ? 1 : 0; + + DBG("nvram: gen0=%d, gen1=%d\n", gen_bank0, gen_bank1); + DBG("nvram: Active bank is: %d\n", core99_bank); + + for (i=0; iindex; +} + +u8 __pmac pmac_xpram_read(int xpaddr) +{ + int offset = pmac_get_partition(pmac_nvram_XPRAM); + loff_t index; + u8 buf; + ssize_t count; + + if (offset < 0 || xpaddr < 0 || xpaddr > 0x100) + return 0xff; + index = offset + xpaddr; + + count = ppc_md.nvram_read(&buf, 1, &index); + if (count != 1) + return 0xff; + return buf; +} + +void __pmac pmac_xpram_write(int xpaddr, u8 data) +{ + int offset = pmac_get_partition(pmac_nvram_XPRAM); + loff_t index; + u8 buf; + + if (offset < 0 || xpaddr < 0 || xpaddr > 0x100) + return; + index = offset + xpaddr; + buf = data; + + ppc_md.nvram_write(&buf, 1, &index); +} + +EXPORT_SYMBOL(pmac_get_partition); +EXPORT_SYMBOL(pmac_xpram_read); +EXPORT_SYMBOL(pmac_xpram_write); diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac_pci.c linux-2.6.3-rc3/arch/ppc64/kernel/pmac_pci.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac_pci.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac_pci.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,755 @@ +/* + * Support for PCI bridges found on Power Macintoshes. + * At present the "bandit" and "chaos" bridges are supported. + * Fortunately you access configuration space in the same + * way with either bridge. + * + * Copyright (C) 2003 Benjamin Herrenschmuidt (benh@kernel.crashing.org) + * Copyright (C) 1997 Paul Mackerras (paulus@samba.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "pci.h" +#include "pmac.h" + +#define DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +extern int pci_probe_only; +extern int pci_read_irq_line(struct pci_dev *pci_dev); + +/* XXX Could be per-controller, but I don't think we risk anything by + * assuming we won't have both UniNorth and Bandit */ +static int has_uninorth; +static struct pci_controller *u3_agp; +u8 pci_cache_line_size; +struct pci_dev *k2_skiplist[2]; + +static int __init fixup_one_level_bus_range(struct device_node *node, int higher) +{ + for (; node != 0;node = node->sibling) { + int * bus_range; + unsigned int *class_code; + int len; + + /* For PCI<->PCI bridges or CardBus bridges, we go down */ + class_code = (unsigned int *) get_property(node, "class-code", 0); + if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI && + (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) + continue; + bus_range = (int *) get_property(node, "bus-range", &len); + if (bus_range != NULL && len > 2 * sizeof(int)) { + if (bus_range[1] > higher) + higher = bus_range[1]; + } + higher = fixup_one_level_bus_range(node->child, higher); + } + return higher; +} + +/* This routine fixes the "bus-range" property of all bridges in the + * system since they tend to have their "last" member wrong on macs + * + * Note that the bus numbers manipulated here are OF bus numbers, they + * are not Linux bus numbers. + */ +static void __init fixup_bus_range(struct device_node *bridge) +{ + int * bus_range; + int len; + + /* Lookup the "bus-range" property for the hose */ + bus_range = (int *) get_property(bridge, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s\n", + bridge->full_name); + return; + } + bus_range[1] = fixup_one_level_bus_range(bridge->child, bus_range[1]); +} + +/* + * Apple MacRISC (U3, UniNorth, Bandit, Chaos) PCI controllers. + * + * The "Bandit" version is present in all early PCI PowerMacs, + * and up to the first ones using Grackle. Some machines may + * have 2 bandit controllers (2 PCI busses). + * + * "Chaos" is used in some "Bandit"-type machines as a bridge + * for the separate display bus. It is accessed the same + * way as bandit, but cannot be probed for devices. It therefore + * has its own config access functions. + * + * The "UniNorth" version is present in all Core99 machines + * (iBook, G4, new IMacs, and all the recent Apple machines). + * It contains 3 controllers in one ASIC. + * + * The U3 is the bridge used on G5 machines. It contains on + * AGP bus which is dealt with the old UniNorth access routines + * and an HyperTransport bus which uses its own set of access + * functions. + */ + +#define MACRISC_CFA0(devfn, off) \ + ((1 << (unsigned long)PCI_SLOT(dev_fn)) \ + | (((unsigned long)PCI_FUNC(dev_fn)) << 8) \ + | (((unsigned long)(off)) & 0xFCUL)) + +#define MACRISC_CFA1(bus, devfn, off) \ + ((((unsigned long)(bus)) << 16) \ + |(((unsigned long)(devfn)) << 8) \ + |(((unsigned long)(off)) & 0xFCUL) \ + |1UL) + +static unsigned long __pmac macrisc_cfg_access(struct pci_controller* hose, + u8 bus, u8 dev_fn, u8 offset) +{ + unsigned int caddr; + + if (bus == hose->first_busno) { + if (dev_fn < (11 << 3)) + return 0; + caddr = MACRISC_CFA0(dev_fn, offset); + } else + caddr = MACRISC_CFA1(bus, dev_fn, offset); + + /* Uninorth will return garbage if we don't read back the value ! */ + do { + out_le32(hose->cfg_addr, caddr); + } while (in_le32(hose->cfg_addr) != caddr); + + offset &= has_uninorth ? 0x07 : 0x03; + return ((unsigned long)hose->cfg_data) + offset; +} + +static int __pmac macrisc_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 *val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + int i; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ + for (i=0; i<2; i++) + if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && + k2_skiplist[i]->devfn == devfn) { + switch (len) { + case 1: + *val = 0xff; break; + case 2: + *val = 0xffff; break; + default: + *val = 0xfffffffful; break; + } + return PCIBIOS_SUCCESSFUL; + } + + addr = macrisc_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8((u8 *)addr); + break; + case 2: + *val = in_le16((u16 *)addr); + break; + default: + *val = in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int __pmac macrisc_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + int i; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * When a device in K2 is powered down, we die on config + * cycle accesses. Fix that here. + */ + for (i=0; i<2; i++) + if (k2_skiplist[i] && k2_skiplist[i]->bus == bus && + k2_skiplist[i]->devfn == devfn) + return PCIBIOS_SUCCESSFUL; + + addr = macrisc_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + out_8((u8 *)addr, val); + (void) in_8((u8 *)addr); + break; + case 2: + out_le16((u16 *)addr, val); + (void) in_le16((u16 *)addr); + break; + default: + out_le32((u32 *)addr, val); + (void) in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops macrisc_pci_ops = +{ + macrisc_read_config, + macrisc_write_config +}; + +/* + * These versions of U3 HyperTransport config space access ops do not + * implement self-view of the HT host yet + */ + +#define U3_HT_CFA0(devfn, off) \ + ((((unsigned long)devfn) << 8) | offset) +#define U3_HT_CFA1(bus, devfn, off) \ + (U3_HT_CFA0(devfn, off) \ + + (((unsigned long)bus) << 16) \ + + 0x01000000UL) + +static unsigned long __pmac u3_ht_cfg_access(struct pci_controller* hose, + u8 bus, u8 devfn, u8 offset) +{ + if (bus == hose->first_busno) { + /* For now, we don't self probe U3 HT bridge */ + if (PCI_FUNC(devfn) != 0 || PCI_SLOT(devfn) > 7 || + PCI_SLOT(devfn) < 1) + return 0; + return ((unsigned long)hose->cfg_data) + U3_HT_CFA0(devfn, offset); + } else + return ((unsigned long)hose->cfg_data) + U3_HT_CFA1(bus, devfn, offset); +} + +static int __pmac u3_ht_read_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 *val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + *val = in_8((u8 *)addr); + break; + case 2: + *val = in_le16((u16 *)addr); + break; + default: + *val = in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static int __pmac u3_ht_write_config(struct pci_bus *bus, unsigned int devfn, + int offset, int len, u32 val) +{ + struct pci_controller *hose; + struct device_node *busdn; + unsigned long addr; + + if (bus->self) + busdn = pci_device_to_OF_node(bus->self); + else + busdn = bus->sysdata; /* must be a phb */ + if (busdn == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + hose = busdn->phb; + if (hose == NULL) + return PCIBIOS_DEVICE_NOT_FOUND; + + addr = u3_ht_cfg_access(hose, bus->number, devfn, offset); + if (!addr) + return PCIBIOS_DEVICE_NOT_FOUND; + /* + * Note: the caller has already checked that offset is + * suitably aligned and that len is 1, 2 or 4. + */ + switch (len) { + case 1: + out_8((u8 *)addr, val); + (void) in_8((u8 *)addr); + break; + case 2: + out_le16((u16 *)addr, val); + (void) in_le16((u16 *)addr); + break; + default: + out_le32((u32 *)addr, val); + (void) in_le32((u32 *)addr); + break; + } + return PCIBIOS_SUCCESSFUL; +} + +static struct pci_ops u3_ht_pci_ops = +{ + u3_ht_read_config, + u3_ht_write_config +}; + +static void __init setup_u3_agp(struct pci_controller* hose) +{ + /* On G5, we move AGP up to high bus number so we don't need + * to reassign bus numbers for HT. If we ever have P2P bridges + * on AGP, we'll have to move pci_assign_all_busses to the + * pci_controller structure so we enable it for AGP and not for + * HT childs. + * We hard code the address because of the different size of + * the reg address cell, we shall fix that by killing struct + * reg_property and using some accessor functions instead + */ + hose->first_busno = 0xf0; + hose->last_busno = 0xff; + has_uninorth = 1; + hose->ops = ¯isc_pci_ops; + hose->cfg_addr = ioremap(0xf0000000 + 0x800000, 0x1000); + hose->cfg_data = ioremap(0xf0000000 + 0xc00000, 0x1000); + + u3_agp = hose; +} + +static void __init setup_u3_ht(struct pci_controller* hose) +{ + struct device_node *np = (struct device_node *)hose->arch_data; + int i, cur; + + hose->ops = &u3_ht_pci_ops; + + /* We hard code the address because of the different size of + * the reg address cell, we shall fix that by killing struct + * reg_property and using some accessor functions instead + */ + hose->cfg_data = (volatile unsigned char *)ioremap(0xf2000000, 0x02000000); + + /* + * /ht node doesn't expose a "ranges" property, so we "remove" regions that + * have been allocated to AGP. So far, this version of the code doesn't assign + * any of the 0xfxxxxxxx "fine" memory regions to /ht. + * We need to fix that sooner or later by either parsing all child "ranges" + * properties or figuring out the U3 address space decoding logic and + * then read it's configuration register (if any). + */ + hose->io_base_phys = 0xf4000000 + 0x00400000; + hose->io_base_virt = ioremap(hose->io_base_phys, 0x00400000); + isa_io_base = pci_io_base = (unsigned long) hose->io_base_virt; + hose->io_resource.name = np->full_name; + hose->io_resource.start = 0; + hose->io_resource.end = 0x003fffff; + hose->io_resource.flags = IORESOURCE_IO; + hose->pci_mem_offset = 0; + hose->first_busno = 0; + hose->last_busno = 0xef; + hose->mem_resources[0].name = np->full_name; + hose->mem_resources[0].start = 0x80000000; + hose->mem_resources[0].end = 0xefffffff; + hose->mem_resources[0].flags = IORESOURCE_MEM; + + if (u3_agp == NULL) { + DBG("U3 has no AGP, using full resource range\n"); + return; + } + + /* We "remove" the AGP resources from the resources allocated to HT, that + * is we create "holes". However, that code does assumptions that so far + * happen to be true (cross fingers...), typically that resources in the + * AGP node are properly ordered + */ + cur = 0; + for (i=0; i<3; i++) { + struct resource *res = &u3_agp->mem_resources[i]; + if (res->flags != IORESOURCE_MEM) + continue; + /* We don't care about "fine" resources */ + if (res->start >= 0xf0000000) + continue; + /* Check if it's just a matter of "shrinking" us in one direction */ + if (hose->mem_resources[cur].start == res->start) { + DBG("U3/HT: shrink start of %d, %08lx -> %08lx\n", + cur, hose->mem_resources[cur].start, res->end + 1); + hose->mem_resources[cur].start = res->end + 1; + continue; + } + if (hose->mem_resources[cur].end == res->end) { + DBG("U3/HT: shrink end of %d, %08lx -> %08lx\n", + cur, hose->mem_resources[cur].end, res->start - 1); + hose->mem_resources[cur].end = res->start - 1; + continue; + } + /* No, it's not the case, we need a hole */ + if (cur == 2) { + /* not enough resources for a hole, we drop part of the range */ + printk(KERN_WARNING "Running out of resources for /ht host !\n"); + hose->mem_resources[cur].end = res->start - 1; + continue; + } + cur++; + DBG("U3/HT: hole, %d end at %08lx, %d start at %08lx\n", + cur-1, res->start - 1, cur, res->end + 1); + hose->mem_resources[cur].name = np->full_name; + hose->mem_resources[cur].flags = IORESOURCE_MEM; + hose->mem_resources[cur].start = res->end + 1; + hose->mem_resources[cur].end = hose->mem_resources[cur-1].end; + hose->mem_resources[cur-1].end = res->start - 1; + } +} + +static void __init pmac_process_bridge_OF_ranges(struct pci_controller *hose, + struct device_node *dev, int primary) +{ + static unsigned int static_lc_ranges[2024]; + unsigned int *dt_ranges, *lc_ranges, *ranges, *prev; + unsigned int size; + int rlen = 0, orig_rlen; + int memno = 0; + struct resource *res; + int np, na = prom_n_addr_cells(dev); + + np = na + 5; + + /* First we try to merge ranges to fix a problem with some pmacs + * that can have more than 3 ranges, fortunately using contiguous + * addresses -- BenH + */ + dt_ranges = (unsigned int *) get_property(dev, "ranges", &rlen); + if (!dt_ranges) + return; + /* lc_ranges = (unsigned int *) alloc_bootmem(rlen);*/ + lc_ranges = static_lc_ranges; + if (!lc_ranges) + return; /* what can we do here ? */ + memcpy(lc_ranges, dt_ranges, rlen); + orig_rlen = rlen; + + /* Let's work on a copy of the "ranges" property instead of damaging + * the device-tree image in memory + */ + ranges = lc_ranges; + prev = NULL; + while ((rlen -= np * sizeof(unsigned int)) >= 0) { + if (prev) { + if (prev[0] == ranges[0] && prev[1] == ranges[1] && + (prev[2] + prev[na+4]) == ranges[2] && + (prev[na+2] + prev[na+4]) == ranges[na+2]) { + prev[na+4] += ranges[na+4]; + ranges[0] = 0; + ranges += np; + continue; + } + } + prev = ranges; + ranges += np; + } + + /* + * The ranges property is laid out as an array of elements, + * each of which comprises: + * cells 0 - 2: a PCI address + * cells 3 or 3+4: a CPU physical address + * (size depending on dev->n_addr_cells) + * cells 4+5 or 5+6: the size of the range + */ + ranges = lc_ranges; + rlen = orig_rlen; + while (ranges && (rlen -= np * sizeof(unsigned int)) >= 0) { + res = NULL; + size = ranges[na+4]; + switch (ranges[0] >> 24) { + case 1: /* I/O space */ + if (ranges[2] != 0) + break; + hose->io_base_phys = ranges[na+2]; + /* limit I/O space to 16MB */ + if (size > 0x01000000) + size = 0x01000000; + hose->io_base_virt = ioremap(ranges[na+2], size); + if (primary) + isa_io_base = (unsigned long) hose->io_base_virt; + res = &hose->io_resource; + res->flags = IORESOURCE_IO; + res->start = ranges[2]; + break; + case 2: /* memory space */ + memno = 0; + if (ranges[1] == 0 && ranges[2] == 0 + && ranges[na+4] <= (16 << 20)) { + /* 1st 16MB, i.e. ISA memory area */ +#if 0 + if (primary) + isa_mem_base = ranges[na+2]; +#endif + memno = 1; + } + while (memno < 3 && hose->mem_resources[memno].flags) + ++memno; + if (memno == 0) + hose->pci_mem_offset = ranges[na+2] - ranges[2]; + if (memno < 3) { + res = &hose->mem_resources[memno]; + res->flags = IORESOURCE_MEM; + res->start = ranges[na+2]; + } + break; + } + if (res != NULL) { + res->name = dev->full_name; + res->end = res->start + size - 1; + res->parent = NULL; + res->sibling = NULL; + res->child = NULL; + } + ranges += np; + } +} + +/* + * We assume that if we have a G3 powermac, we have one bridge called + * "pci" (a MPC106) and no bandit or chaos bridges, and contrariwise, + * if we have one or more bandit or chaos bridges, we don't have a MPC106. + */ +static int __init add_bridge(struct device_node *dev) +{ + int len; + struct pci_controller *hose; + char* disp_name; + int *bus_range; + int primary = 1; + struct property *of_prop; + + DBG("Adding PCI host bridge %s\n", dev->full_name); + + bus_range = (int *) get_property(dev, "bus-range", &len); + if (bus_range == NULL || len < 2 * sizeof(int)) { + printk(KERN_WARNING "Can't get bus-range for %s, assume bus 0\n", + dev->full_name); + } + + hose = pci_alloc_pci_controller(phb_type_apple); + if (!hose) + return -ENOMEM; + hose->arch_data = dev; + hose->first_busno = bus_range ? bus_range[0] : 0; + hose->last_busno = bus_range ? bus_range[1] : 0xff; + + of_prop = (struct property *)alloc_bootmem(sizeof(struct property) + + sizeof(hose->global_number)); + if (of_prop) { + memset(of_prop, 0, sizeof(struct property)); + of_prop->name = "linux,pci-domain"; + of_prop->length = sizeof(hose->global_number); + of_prop->value = (unsigned char *)&of_prop[1]; + memcpy(of_prop->value, &hose->global_number, sizeof(hose->global_number)); + prom_add_property(dev, of_prop); + } + + disp_name = NULL; + if (device_is_compatible(dev, "u3-agp")) { + setup_u3_agp(hose); + disp_name = "U3-AGP"; + primary = 0; + } else if (device_is_compatible(dev, "u3-ht")) { + setup_u3_ht(hose); + disp_name = "U3-HT"; + primary = 1; + } + printk(KERN_INFO "Found %s PCI host bridge. Firmware bus number: %d->%d\n", + disp_name, hose->first_busno, hose->last_busno); + + /* Interpret the "ranges" property */ + /* This also maps the I/O region and sets isa_io/mem_base */ + pmac_process_bridge_OF_ranges(hose, dev, primary); + + /* Fixup "bus-range" OF property */ + fixup_bus_range(dev); + + return 0; +} + + +void __init pmac_pcibios_fixup(void) +{ + struct pci_dev *dev = NULL; + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) + pci_read_irq_line(dev); + + pci_fix_bus_sysdata(); +} + +static void __init pmac_fixup_phb_resources(void) +{ + struct pci_controller *hose; + + for (hose = hose_head; hose; hose = hose->next) { + unsigned long offset = (unsigned long)hose->io_base_virt - pci_io_base; + hose->io_resource.start += offset; + hose->io_resource.end += offset; + printk(KERN_INFO "PCI Host %d, io start: %lx; io end: %lx\n", + hose->global_number, + hose->io_resource.start, hose->io_resource.end); + } +} + +void __init pmac_pci_init(void) +{ + struct device_node *np, *root; + struct device_node *ht = NULL; + + /* Probe root PCI hosts, that is on U3 the AGP host and the + * HyperTransport host. That one is actually "kept" around + * and actually added last as it's resource management relies + * on the AGP resources to have been setup first + */ + root = of_find_node_by_path("/"); + if (root == NULL) { + printk(KERN_CRIT "pmac_find_bridges: can't find root of device tree\n"); + return; + } + for (np = NULL; (np = of_get_next_child(root, np)) != NULL;) { + if (np->name == NULL) + continue; + if (strcmp(np->name, "pci") == 0) { + if (add_bridge(np) == 0) + of_node_get(np); + } + if (strcmp(np->name, "ht") == 0) { + of_node_get(np); + ht = np; + } + } + of_node_put(root); + + /* Now setup the HyperTransport host if we found any + */ + if (ht && add_bridge(ht) != 0) + of_node_put(ht); + + /* Fixup the IO resources on our host bridges as the common code + * does it only for childs of the host bridges + */ + pmac_fixup_phb_resources(); + + /* Setup the linkage between OF nodes and PHBs */ + pci_devs_phb_init(); + + pmac_check_ht_link(); + + /* Tell pci.c to use the common resource allocation mecanism */ + pci_probe_only = 0; + + /* HT don't do more than 64 bytes transfers. FIXME: Deal with + * the exception of U3/AGP (hook into pci_set_mwi) + */ + pci_cache_line_size = 16; /* 64 bytes */ +} + +/* + * Disable second function on K2-SATA, it's broken + * and disable IO BARs on first one + */ +void fixup_k2_sata(struct pci_dev* dev) +{ + int i; + u16 cmd; + + if (PCI_FUNC(dev->devfn) > 0) { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY); + pci_write_config_word(dev, PCI_COMMAND, cmd); + for (i = 0; i < 6; i++) { + dev->resource[i].start = dev->resource[i].end = 0; + dev->resource[i].flags = 0; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); + } + } else { + pci_read_config_word(dev, PCI_COMMAND, &cmd); + cmd &= ~PCI_COMMAND_IO; + pci_write_config_word(dev, PCI_COMMAND, cmd); + for (i = 0; i < 5; i++) { + dev->resource[i].start = dev->resource[i].end = 0; + dev->resource[i].flags = 0; + pci_write_config_dword(dev, PCI_BASE_ADDRESS_0 + 4 * i, 0); + } + } +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac_setup.c linux-2.6.3-rc3/arch/ppc64/kernel/pmac_setup.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac_setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac_setup.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,504 @@ +/* + * arch/ppc/platforms/setup.c + * + * PowerPC version + * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) + * + * Adapted for Power Macintosh by Paul Mackerras + * Copyright (C) 1996 Paul Mackerras (paulus@cs.anu.edu.au) + * + * Derived from "arch/alpha/kernel/setup.c" + * Copyright (C) 1995 Linus Torvalds + * + * Maintained by Benjamin Herrenschmidt (benh@kernel.crashing.org) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +/* + * bootup setup stuff.. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pmac.h" + +extern char saved_command_line[]; +static int current_root_goodness = -1; +#define DEFAULT_ROOT_DEVICE Root_SDA1 /* sda1 - slightly silly choice */ + +extern int powersave_nap; +int sccdbg; + +extern void udbg_init_scc(struct device_node *np); + +#ifdef CONFIG_BOOTX_TEXT +void pmac_progress(char *s, unsigned short hex); +#endif + +void __pmac pmac_show_cpuinfo(struct seq_file *m) +{ + struct device_node *np; + char *pp; + int plen; + char* mbname; + int mbmodel = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, + PMAC_MB_INFO_MODEL, 0); + unsigned int mbflags = pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, + PMAC_MB_INFO_FLAGS, 0); + + if (pmac_call_feature(PMAC_FTR_GET_MB_INFO, NULL, PMAC_MB_INFO_NAME, + (long)&mbname) != 0) + mbname = "Unknown"; + + /* find motherboard type */ + seq_printf(m, "machine\t\t: "); + np = find_devices("device-tree"); + if (np != NULL) { + pp = (char *) get_property(np, "model", NULL); + if (pp != NULL) + seq_printf(m, "%s\n", pp); + else + seq_printf(m, "PowerMac\n"); + pp = (char *) get_property(np, "compatible", &plen); + if (pp != NULL) { + seq_printf(m, "motherboard\t:"); + while (plen > 0) { + int l = strlen(pp) + 1; + seq_printf(m, " %s", pp); + plen -= l; + pp += l; + } + seq_printf(m, "\n"); + } + } else + seq_printf(m, "PowerMac\n"); + + /* print parsed model */ + seq_printf(m, "detected as\t: %d (%s)\n", mbmodel, mbname); + seq_printf(m, "pmac flags\t: %08x\n", mbflags); + seq_printf(m, "memory\t\t: %luMB\n", lmb_phys_mem_size() >> 20); + + /* Checks "l2cr-value" property in the registry */ + np = find_devices("cpus"); + if (np == 0) + np = find_type_devices("cpu"); + if (np != 0) { + unsigned int *l2cr = (unsigned int *) + get_property(np, "l2cr-value", NULL); + if (l2cr != 0) { + seq_printf(m, "l2cr override\t: 0x%x\n", *l2cr); + } + } + + /* Indicate newworld */ + seq_printf(m, "pmac-generation\t: NewWorld\n"); +} + + +void __init pmac_setup_arch(void) +{ + struct device_node *cpu; + int *fp; + unsigned long pvr; + + pvr = PVR_VER(mfspr(PVR)); + + /* Set loops_per_jiffy to a half-way reasonable value, + for use until calibrate_delay gets called. */ + cpu = find_type_devices("cpu"); + if (cpu != 0) { + fp = (int *) get_property(cpu, "clock-frequency", NULL); + if (fp != 0) { + if (pvr == 4 || pvr >= 8) + /* 604, G3, G4 etc. */ + loops_per_jiffy = *fp / HZ; + else + /* 601, 603, etc. */ + loops_per_jiffy = *fp / (2*HZ); + } else + loops_per_jiffy = 50000000 / HZ; + } + + /* We can NAP */ + powersave_nap = 1; + + /* Initialize the PMU */ + find_via_pmu(); + + /* Init NVRAM access */ + pmac_nvram_init(); + + /* Setup SMP callback */ +#ifdef CONFIG_SMP + pmac_setup_smp(); +#endif + /* Setup the PCI DMA to "direct" for now, until we have proper + * DART support and can deal with more than 2Gb of RAM + */ + pci_dma_init_direct(); + + /* Lookup PCI hosts */ + pmac_pci_init(); + +#ifdef CONFIG_DUMMY_CONSOLE + conswitchp = &dummy_con; +#endif +} + +extern char *bootpath; +extern char *bootdevice; +void *boot_host; +int boot_target; +int boot_part; +extern dev_t boot_dev; + +#ifdef CONFIG_SCSI +void __init note_scsi_host(struct device_node *node, void *host) +{ + int l; + char *p; + + l = strlen(node->full_name); + if (bootpath != NULL && bootdevice != NULL + && strncmp(node->full_name, bootdevice, l) == 0 + && (bootdevice[l] == '/' || bootdevice[l] == 0)) { + boot_host = host; + /* + * There's a bug in OF 1.0.5. (Why am I not surprised.) + * If you pass a path like scsi/sd@1:0 to canon, it returns + * something like /bandit@F2000000/gc@10/53c94@10000/sd@0,0 + * That is, the scsi target number doesn't get preserved. + * So we pick the target number out of bootpath and use that. + */ + p = strstr(bootpath, "/sd@"); + if (p != NULL) { + p += 4; + boot_target = simple_strtoul(p, NULL, 10); + p = strchr(p, ':'); + if (p != NULL) + boot_part = simple_strtoul(p + 1, NULL, 10); + } + } +} +#endif + +#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) +static dev_t __init find_ide_boot(void) +{ + char *p; + int n; + dev_t __init pmac_find_ide_boot(char *bootdevice, int n); + + if (bootdevice == NULL) + return 0; + p = strrchr(bootdevice, '/'); + if (p == NULL) + return 0; + n = p - bootdevice; + + return pmac_find_ide_boot(bootdevice, n); +} +#endif /* CONFIG_BLK_DEV_IDE && CONFIG_BLK_DEV_IDE_PMAC */ + +void __init find_boot_device(void) +{ +#if defined(CONFIG_BLK_DEV_IDE) && defined(CONFIG_BLK_DEV_IDE_PMAC) + boot_dev = find_ide_boot(); +#endif +} + +static int initializing = 1; + +static int pmac_late_init(void) +{ + initializing = 0; + return 0; +} + +late_initcall(pmac_late_init); + +/* can't be __init - can be called whenever a disk is first accessed */ +void __pmac note_bootable_part(dev_t dev, int part, int goodness) +{ + static int found_boot = 0; + char *p; + + if (!initializing) + return; + if ((goodness <= current_root_goodness) && + ROOT_DEV != DEFAULT_ROOT_DEVICE) + return; + p = strstr(saved_command_line, "root="); + if (p != NULL && (p == saved_command_line || p[-1] == ' ')) + return; + + if (!found_boot) { + find_boot_device(); + found_boot = 1; + } + if (!boot_dev || dev == boot_dev) { + ROOT_DEV = dev + part; + boot_dev = 0; + current_root_goodness = goodness; + } +} + +void __pmac pmac_restart(char *cmd) +{ + pmu_restart(); +} + +void __pmac pmac_power_off(void) +{ + pmu_shutdown(); +} + +void __pmac pmac_halt(void) +{ + pmac_power_off(); +} + +#ifdef CONFIG_BOOTX_TEXT +static int dummy_getc_poll(void) +{ + return -1; +} + +static unsigned char dummy_getc(void) +{ + return 0; +} + +static void btext_putc(unsigned char c) +{ + btext_drawchar(c); +} +#endif /* CONFIG_BOOTX_TEXT */ + +/* + * Early initialization. + * Relocation is on but do not reference unbolted pages + * Also, device-tree hasn't been "finished", so don't muck with + * it too much + */ +void __init pmac_init_early(void) +{ + hpte_init_pSeries(); + +#ifdef CONFIG_BOOTX_TEXT + ppc_md.udbg_putc = btext_putc; + ppc_md.udbg_getc = dummy_getc; + ppc_md.udbg_getc_poll = dummy_getc_poll; +#endif /* CONFIG_BOOTX_TEXT */ +} + +extern void* OpenPIC_Addr; +extern void* OpenPIC2_Addr; +extern u_int OpenPIC_NumInitSenses; +extern u_char *OpenPIC_InitSenses; +extern void openpic_init(int main_pic, int offset, unsigned char* chrp_ack, + int programmer_switch_irq); +extern void openpic2_init(int offset); +extern int openpic_get_irq(struct pt_regs *regs); +extern int openpic2_get_irq(struct pt_regs *regs); + +static int pmac_cascade_irq = -1; + +static irqreturn_t pmac_u3_do_cascade(int cpl, void *dev_id, struct pt_regs *regs) +{ + int irq; + + for (;;) { + irq = openpic2_get_irq(regs); + if (irq == -1) + break; + ppc_irq_dispatch_handler(regs, irq); + } + return IRQ_HANDLED; +} + +static __init void pmac_init_IRQ(void) +{ + struct device_node *irqctrler = NULL; + struct device_node *irqctrler2 = NULL; + struct device_node *np = NULL; + + /* We first try to detect Apple's new Core99 chipset, since mac-io + * is quite different on those machines and contains an IBM MPIC2. + */ + while ((np = of_find_node_by_type(np, "open-pic")) != NULL) { + struct device_node *parent = of_get_parent(np); + if (parent && !strcmp(parent->name, "u3")) + irqctrler2 = of_node_get(np); + else + irqctrler = of_node_get(np); + of_node_put(parent); + } + if (irqctrler != NULL && irqctrler->n_addrs > 0) { + unsigned char senses[128]; + + printk(KERN_INFO "PowerMac using OpenPIC irq controller at 0x%08x\n", + (unsigned int)irqctrler->addrs[0].address); + + prom_get_irq_senses(senses, 0, 128); + OpenPIC_InitSenses = senses; + OpenPIC_NumInitSenses = 128; + OpenPIC_Addr = ioremap(irqctrler->addrs[0].address, + irqctrler->addrs[0].size); + openpic_init(1, 0, NULL, -1); + + if (irqctrler2 != NULL && irqctrler2->n_intrs > 0 && + irqctrler2->n_addrs > 0) { + printk(KERN_INFO "Slave OpenPIC at 0x%08x hooked on IRQ %d\n", + (u32)irqctrler2->addrs[0].address, + irqctrler2->intrs[0].line); + pmac_call_feature(PMAC_FTR_ENABLE_MPIC, irqctrler2, 0, 0); + OpenPIC2_Addr = ioremap(irqctrler2->addrs[0].address, + irqctrler2->addrs[0].size); + prom_get_irq_senses(senses, 128, 128 + 128); + OpenPIC_InitSenses = senses; + OpenPIC_NumInitSenses = 128; + openpic2_init(128); + pmac_cascade_irq = irqctrler2->intrs[0].line; + } + } + of_node_put(irqctrler); + of_node_put(irqctrler2); +} + +/* We cannot do request_irq too early ... Right now, we get the + * cascade as a core_initcall, which should be fine for our needs + */ +static int __init pmac_irq_cascade_init(void) +{ + if (request_irq(pmac_cascade_irq, pmac_u3_do_cascade, 0, + "U3->K2 Cascade", NULL)) + printk(KERN_ERR "Unable to get OpenPIC IRQ for cascade\n"); + return 0; +} + +core_initcall(pmac_irq_cascade_init); + +void __init pmac_init(unsigned long r3, unsigned long r4, unsigned long r5, + unsigned long r6, unsigned long r7) +{ + /* Probe motherboard chipset */ + pmac_feature_init(); + + /* Init SCC */ + if (strstr(cmd_line, "sccdbg")) { + sccdbg = 1; + udbg_init_scc(NULL); + } + + /* Fill up the machine description */ + ppc_md.setup_arch = pmac_setup_arch; + ppc_md.get_cpuinfo = pmac_show_cpuinfo; + + ppc_md.init_IRQ = pmac_init_IRQ; + ppc_md.get_irq = openpic_get_irq; + + ppc_md.pcibios_fixup = pmac_pcibios_fixup; + + ppc_md.restart = pmac_restart; + ppc_md.power_off = pmac_power_off; + ppc_md.halt = pmac_halt; + + ppc_md.get_boot_time = pmac_get_boot_time; + ppc_md.set_rtc_time = pmac_set_rtc_time; + ppc_md.get_rtc_time = pmac_get_rtc_time; + ppc_md.calibrate_decr = pmac_calibrate_decr; + + ppc_md.feature_call = pmac_do_feature_call; + + +#ifdef CONFIG_BOOTX_TEXT + ppc_md.progress = pmac_progress; +#endif /* CONFIG_BOOTX_TEXT */ + + if (ppc_md.progress) ppc_md.progress("pmac_init(): exit", 0); + +} + +#ifdef CONFIG_BOOTX_TEXT +void __init pmac_progress(char *s, unsigned short hex) +{ + if (sccdbg) { + udbg_puts(s); + udbg_putc('\n'); + } + else if (boot_text_mapped) { + btext_drawstring(s); + btext_drawchar('\n'); + } +} +#endif /* CONFIG_BOOTX_TEXT */ + +static int __init pmac_declare_of_platform_devices(void) +{ + struct device_node *np; + + np = find_devices("u3"); + if (np) { + for (np = np->child; np != NULL; np = np->sibling) + if (strncmp(np->name, "i2c", 3) == 0) { + of_platform_device_create(np, "u3-i2c"); + break; + } + } + + return 0; +} + +device_initcall(pmac_declare_of_platform_devices); diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac_smp.c linux-2.6.3-rc3/arch/ppc64/kernel/pmac_smp.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac_smp.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac_smp.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,174 @@ +/* + * SMP support for power macintosh. + * + * We support both the old "powersurge" SMP architecture + * and the current Core99 (G4 PowerMac) machines. + * + * Note that we don't support the very first rev. of + * Apple/DayStar 2 CPUs board, the one with the funky + * watchdog. Hopefully, none of these should be there except + * maybe internally to Apple. I should probably still add some + * code to detect this card though and disable SMP. --BenH. + * + * Support Macintosh G4 SMP by Troy Benjegerdes (hozer@drgw.net) + * and Ben Herrenschmidt . + * + * Support for DayStar quad CPU cards + * Copyright (C) XLR8, Inc. 1994-2000 + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#define __KERNEL_SYSCALLS__ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "open_pic.h" + +extern void pmac_secondary_start_1(void); +extern void pmac_secondary_start_2(void); +extern void pmac_secondary_start_3(void); + +extern void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait); + +extern struct smp_ops_t *smp_ops; + +static int __init smp_core99_probe(void) +{ + struct device_node *cpus; + int ncpus = 1; + + /* Maybe use systemconfiguration here ? */ + if (ppc_md.progress) ppc_md.progress("smp_core99_probe", 0x345); + cpus = find_type_devices("cpu"); + if (cpus == NULL) + return 0; + + while ((cpus = cpus->next) != NULL) + ++ncpus; + + printk(KERN_INFO "PowerMac SMP probe found %d cpus\n", ncpus); + + if (ncpus > 1) + openpic_request_IPIs(); + + return ncpus; +} + +static void __init smp_core99_kick_cpu(int nr) +{ + int save_vector; + unsigned long new_vector; + unsigned long flags; + volatile unsigned int *vector + = ((volatile unsigned int *)(KERNELBASE+0x100)); + + if (nr < 1 || nr > 3) + return; + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu", 0x346); + + local_irq_save(flags); + local_irq_disable(); + + /* Save reset vector */ + save_vector = *vector; + + /* Setup fake reset vector that does + * b .pmac_secondary_start - KERNELBASE + */ + switch(nr) { + case 1: + new_vector = (unsigned long)pmac_secondary_start_1; + break; + case 2: + new_vector = (unsigned long)pmac_secondary_start_2; + break; + case 3: + new_vector = (unsigned long)pmac_secondary_start_3; + break; + } + *vector = 0x48000002 + (new_vector - KERNELBASE); + + /* flush data cache and inval instruction cache */ + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + /* Put some life in our friend */ + pmac_call_feature(PMAC_FTR_RESET_CPU, NULL, nr, 0); + paca[nr].xProcStart = 1; + + /* FIXME: We wait a bit for the CPU to take the exception, I should + * instead wait for the entry code to set something for me. Well, + * ideally, all that crap will be done in prom.c and the CPU left + * in a RAM-based wait loop like CHRP. + */ + mdelay(1); + + /* Restore our exception vector */ + *vector = save_vector; + flush_icache_range((unsigned long) vector, (unsigned long) vector + 4); + + local_irq_restore(flags); + if (ppc_md.progress) ppc_md.progress("smp_core99_kick_cpu done", 0x347); +} + +static void __init smp_core99_setup_cpu(int cpu_nr) +{ + /* Setup openpic */ + do_openpic_setup_cpu(); + + if (cpu_nr == 0) { + extern void g5_phy_disable_cpu1(void); + + /* If we didn't start the second CPU, we must take + * it off the bus + */ + if (num_online_cpus() < 2) + g5_phy_disable_cpu1(); + if (ppc_md.progress) ppc_md.progress("core99_setup_cpu 0 done", 0x349); + } +} + +extern void smp_generic_give_timebase(void); +extern void smp_generic_take_timebase(void); + +struct smp_ops_t core99_smp_ops __pmacdata = { + .message_pass = smp_openpic_message_pass, + .probe = smp_core99_probe, + .kick_cpu = smp_core99_kick_cpu, + .setup_cpu = smp_core99_setup_cpu, + .give_timebase = smp_generic_give_timebase, + .take_timebase = smp_generic_take_timebase, +}; + +void __init pmac_setup_smp(void) +{ + smp_ops = &core99_smp_ops; +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/pmac_time.c linux-2.6.3-rc3/arch/ppc64/kernel/pmac_time.c --- linux-2.6.3-rc2/arch/ppc64/kernel/pmac_time.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/pmac_time.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,157 @@ +/* + * Support for periodic interrupts (100 per second) and for getting + * the current time from the RTC on Power Macintoshes. + * + * We use the decrementer register for our periodic interrupts. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996 Paul Mackerras. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#undef DEBUG + +#ifdef DEBUG +#define DBG(x...) printk(x) +#else +#define DBG(x...) +#endif + +extern void setup_default_decr(void); + +/* Apparently the RTC stores seconds since 1 Jan 1904 */ +#define RTC_OFFSET 2082844800 + +/* + * Calibrate the decrementer frequency with the VIA timer 1. + */ +#define VIA_TIMER_FREQ_6 4700000 /* time 1 frequency * 6 */ + +extern struct timezone sys_tz; +extern void to_tm(int tim, struct rtc_time * tm); + +void __pmac pmac_get_rtc_time(struct rtc_time *tm) +{ + struct adb_request req; + unsigned int now; + + /* Get the time from the RTC */ + if (pmu_request(&req, NULL, 1, PMU_READ_RTC) < 0) + return; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 4) + printk(KERN_ERR "pmac_get_rtc_time: got %d byte reply\n", + req.reply_len); + now = (req.reply[0] << 24) + (req.reply[1] << 16) + + (req.reply[2] << 8) + req.reply[3]; + DBG("get: %u -> %u\n", (int)now, (int)(now - RTC_OFFSET)); + now -= RTC_OFFSET; + + to_tm(now, tm); + tm->tm_year -= 1900; + tm->tm_mon -= 1; + + DBG("-> tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n", + tm->tm_mday, tm->tm_mon, tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); +} + +int __pmac pmac_set_rtc_time(struct rtc_time *tm) +{ + struct adb_request req; + unsigned int nowtime; + + DBG("set: tm_mday: %d, tm_mon: %d, tm_year: %d, %d:%02d:%02d\n", + tm->tm_mday, tm->tm_mon, tm->tm_year, + tm->tm_hour, tm->tm_min, tm->tm_sec); + + nowtime = mktime(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, + tm->tm_hour, tm->tm_min, tm->tm_sec); + DBG("-> %u -> %u\n", (int)nowtime, (int)(nowtime + RTC_OFFSET)); + nowtime += RTC_OFFSET; + + if (pmu_request(&req, NULL, 5, PMU_SET_RTC, + nowtime >> 24, nowtime >> 16, nowtime >> 8, nowtime) < 0) + return 0; + while (!req.complete) + pmu_poll(); + if (req.reply_len != 0) + printk(KERN_ERR "pmac_set_rtc_time: got %d byte reply\n", + req.reply_len); + return 1; +} + +void __init pmac_get_boot_time(struct rtc_time *tm) +{ + pmac_get_rtc_time(tm); + +#ifdef disabled__CONFIG_NVRAM + s32 delta = 0; + int dst; + + delta = ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x9)) << 16; + delta |= ((s32)pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xa)) << 8; + delta |= pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0xb); + if (delta & 0x00800000UL) + delta |= 0xFF000000UL; + dst = ((pmac_xpram_read(PMAC_XPRAM_MACHINE_LOC + 0x8) & 0x80) != 0); + printk("GMT Delta read from XPRAM: %d minutes, DST: %s\n", delta/60, + dst ? "on" : "off"); +#endif +} + +/* + * Query the OF and get the decr frequency. + * This was taken from the pmac time_init() when merging the prep/pmac + * time functions. + */ +void __init pmac_calibrate_decr(void) +{ + struct device_node *cpu; + unsigned int freq, *fp; + struct div_result divres; + + /* + * The cpu node should have a timebase-frequency property + * to tell us the rate at which the decrementer counts. + */ + cpu = find_type_devices("cpu"); + if (cpu == 0) + panic("can't find cpu node in time_init"); + fp = (unsigned int *) get_property(cpu, "timebase-frequency", NULL); + if (fp == 0) + panic("can't get cpu timebase frequency"); + freq = *fp; + printk("time_init: decrementer frequency = %u.%.6u MHz\n", + freq/1000000, freq%1000000); + tb_ticks_per_jiffy = freq / HZ; + tb_ticks_per_sec = tb_ticks_per_jiffy * HZ; + tb_ticks_per_usec = freq / 1000000; + tb_to_us = mulhwu_scale_factor(freq, 1000000); + div128_by_32( 1024*1024, 0, tb_ticks_per_sec, &divres ); + tb_to_xs = divres.result_low; + + setup_default_decr(); +} + diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/ppc_ksyms.c linux-2.6.3-rc3/arch/ppc64/kernel/ppc_ksyms.c --- linux-2.6.3-rc2/arch/ppc64/kernel/ppc_ksyms.c 2004-02-03 19:43:17.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/ppc_ksyms.c 2004-02-14 19:31:00.000000000 -0800 @@ -93,6 +93,8 @@ EXPORT_SYMBOL(__strncpy_from_user); EXPORT_SYMBOL(__strnlen_user); +EXPORT_SYMBOL(clear_user_page); + #ifdef CONFIG_MSCHUNKS EXPORT_SYMBOL(msChunks); #endif @@ -204,25 +206,6 @@ EXPORT_SYMBOL(irq_desc); EXPORT_SYMBOL(get_wchan); EXPORT_SYMBOL(console_drivers); -#ifdef CONFIG_XMON -EXPORT_SYMBOL(xmon); -#endif - -#ifdef CONFIG_DEBUG_KERNEL -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); -#endif EXPORT_SYMBOL(tb_ticks_per_usec); EXPORT_SYMBOL(paca); diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/process.c linux-2.6.3-rc3/arch/ppc64/kernel/process.c --- linux-2.6.3-rc2/arch/ppc64/kernel/process.c 2004-02-03 19:43:57.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/process.c 2004-02-14 19:31:00.000000000 -0800 @@ -194,8 +194,8 @@ regs->msr&MSR_DR ? 1 : 0); if (regs->trap == 0x300 || regs->trap == 0x380 || regs->trap == 0x600) printk("DAR: %016lx, DSISR: %016lx\n", regs->dar, regs->dsisr); - printk("TASK = %p[%d] '%s' ", - current, current->pid, current->comm); + printk("TASK: %p[%d] '%s' THREAD: %p", + current, current->pid, current->comm, current->thread_info); #ifdef CONFIG_SMP printk(" CPU: %d", smp_processor_id()); @@ -217,6 +217,8 @@ */ printk("NIP [%016lx] ", regs->nip); print_symbol("%s\n", regs->nip); + printk("LR [%016lx] ", regs->link); + print_symbol("%s\n", regs->link); show_stack(current, (unsigned long *)regs->gpr[1]); } diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/prom.c linux-2.6.3-rc3/arch/ppc64/kernel/prom.c --- linux-2.6.3-rc2/arch/ppc64/kernel/prom.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/prom.c 2004-02-14 19:31:00.000000000 -0800 @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include "open_pic.h" @@ -115,24 +117,15 @@ static interpret_func interpret_pci_props; static interpret_func interpret_isa_props; static interpret_func interpret_root_props; +static interpret_func interpret_dbdma_props; +static interpret_func interpret_macio_props; #ifndef FB_MAX /* avoid pulling in all of the fb stuff */ #define FB_MAX 8 #endif - -struct prom_t prom = { - 0, /* entry */ - 0, /* chosen */ - 0, /* cpu */ - 0, /* stdout */ - 0, /* disp_node */ - {0,0,0,{0},NULL}, /* args */ - 0, /* version */ - 32, /* encode_phys_size */ - 0 /* bi_rec pointer */ -}; - +/* prom structure */ +struct prom_t prom; char *prom_display_paths[FB_MAX] __initdata = { 0, }; unsigned int prom_num_displays = 0; @@ -140,7 +133,6 @@ extern struct rtas_t rtas; extern unsigned long klimit; -extern unsigned long embedded_sysmap_end; extern struct lmb lmb; #define MAX_PHB 16 * 3 // 16 Towers * 3 PHBs/tower @@ -189,6 +181,8 @@ extern unsigned long reloc_offset(void); extern void enter_prom(void *dummy,...); +extern void copy_and_flush(unsigned long dest, unsigned long src, + unsigned long size, unsigned long offset); extern char cmd_line[512]; /* XXX */ unsigned long dev_tree_size; @@ -341,9 +335,14 @@ RELOC("d-cache-size"), &size, sizeof(size)); - call_prom(RELOC("getprop"), 4, 1, node, - RELOC("d-cache-line-size"), - &lsize, sizeof(lsize)); + if (_systemcfg->platform == PLATFORM_POWERMAC) + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("d-cache-block-size"), + &lsize, sizeof(lsize)); + else + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("d-cache-line-size"), + &lsize, sizeof(lsize)); _systemcfg->dCacheL1Size = size; _systemcfg->dCacheL1LineSize = lsize; @@ -354,9 +353,14 @@ RELOC("i-cache-size"), &size, sizeof(size)); - call_prom(RELOC("getprop"), 4, 1, node, - RELOC("i-cache-line-size"), - &lsize, sizeof(lsize)); + if (_systemcfg->platform == PLATFORM_POWERMAC) + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("i-cache-block-size"), + &lsize, sizeof(lsize)); + else + call_prom(RELOC("getprop"), 4, 1, node, + RELOC("i-cache-line-size"), + &lsize, sizeof(lsize)); _systemcfg->iCacheL1Size = size; _systemcfg->iCacheL1LineSize = lsize; @@ -377,6 +381,8 @@ struct isa_reg_property reg; union pci_range ranges; + if (_systemcfg->platform == PLATFORM_POWERMAC) + continue; type[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("ibm,aix-loc"), type, sizeof(type)); @@ -407,24 +413,27 @@ } } - _naca->interrupt_controller = IC_INVALID; - for (node = 0; prom_next_node(&node); ) { - type[0] = 0; - call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"), - type, sizeof(type)); - if (strcmp(type, RELOC("interrupt-controller"))) { - continue; - } - call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"), - type, sizeof(type)); - if (strstr(type, RELOC("open-pic"))) { - _naca->interrupt_controller = IC_OPEN_PIC; - } else if (strstr(type, RELOC("ppc-xicp"))) { - _naca->interrupt_controller = IC_PPC_XIC; - } else { - prom_print(RELOC("prom: failed to recognize interrupt-controller\n")); + if (_systemcfg->platform == PLATFORM_POWERMAC) + _naca->interrupt_controller = IC_OPEN_PIC; + else { + _naca->interrupt_controller = IC_INVALID; + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("name"), + type, sizeof(type)); + if (strcmp(type, RELOC("interrupt-controller"))) + continue; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("compatible"), + type, sizeof(type)); + if (strstr(type, RELOC("open-pic"))) + _naca->interrupt_controller = IC_OPEN_PIC; + else if (strstr(type, RELOC("ppc-xicp"))) + _naca->interrupt_controller = IC_PPC_XIC; + else + prom_print(RELOC("prom: failed to recognize" + " interrupt-controller\n")); + break; } - break; } if (_naca->interrupt_controller == IC_INVALID) { @@ -438,7 +447,8 @@ _systemcfg->physicalMemorySize = lmb_phys_mem_size(); - if (_systemcfg->platform == PLATFORM_PSERIES) { + if (_systemcfg->platform == PLATFORM_PSERIES || + _systemcfg->platform == PLATFORM_POWERMAC) { unsigned long rnd_mem_size, pteg_count; /* round mem_size up to next power of 2 */ @@ -517,12 +527,19 @@ char type[64]; unsigned long i, offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); + struct systemcfg *_systemcfg = RELOC(systemcfg); union lmb_reg_property reg; unsigned long lmb_base, lmb_size; unsigned long num_regs, bytes_per_reg = (_prom->encode_phys_size*2)/8; lmb_init(); + /* XXX Quick HACK. Proper fix is to drop those structures and properly use + * #address-cells. PowerMac has #size-cell set to 1 and #address-cells to 2 + */ + if (_systemcfg->platform == PLATFORM_POWERMAC) + bytes_per_reg = 12; + for (node = 0; prom_next_node(&node); ) { type[0] = 0; call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), @@ -535,7 +552,15 @@ ®, sizeof(reg)) / bytes_per_reg; for (i=0; i < num_regs ;i++) { - if (_prom->encode_phys_size == 32) { + if (_systemcfg->platform == PLATFORM_POWERMAC) { + lmb_base = ((unsigned long)reg.addrPM[i].address_hi) << 32; + lmb_base |= (unsigned long)reg.addrPM[i].address_lo; + lmb_size = reg.addrPM[i].size; + if (lmb_base > 0x80000000ull) { + prom_print(RELOC("Skipping memory above 2Gb for now, not yet supported\n")); + continue; + } + } else if (_prom->encode_phys_size == 32) { lmb_base = reg.addr32[i].address; lmb_size = reg.addr32[i].size; } else { @@ -920,19 +945,47 @@ struct paca_struct *_xPaca = PTRRELOC(&paca[0]); struct prom_t *_prom = PTRRELOC(&prom); + /* On pmac, we just fill out the various global bitmasks and + * arrays indicating our CPUs are here, they are actually started + * later on from pmac_smp + */ + if (_systemcfg->platform == PLATFORM_POWERMAC) { + for (node = 0; prom_next_node(&node); ) { + type[0] = 0; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("device_type"), + type, sizeof(type)); + if (strcmp(type, RELOC("cpu")) != 0) + continue; + reg = -1; + call_prom(RELOC("getprop"), 4, 1, node, RELOC("reg"), + ®, sizeof(reg)); + _xPaca[cpuid].xHwProcNum = reg; + +#ifdef CONFIG_SMP + cpu_set(cpuid, RELOC(cpu_available_map)); + cpu_set(cpuid, RELOC(cpu_possible_map)); + cpu_set(cpuid, RELOC(cpu_present_at_boot)); + if (reg == 0) + cpu_set(cpuid, RELOC(cpu_online_map)); +#endif /* CONFIG_SMP */ + cpuid++; + } + return; + } + /* Initially, we must have one active CPU. */ _systemcfg->processorCount = 1; #ifdef DEBUG_PROM prom_print(RELOC("prom_hold_cpus: start...\n")); prom_print(RELOC(" 1) spinloop = 0x")); - prom_print_hex(spinloop); + prom_print_hex((unsigned long)spinloop); prom_print_nl(); prom_print(RELOC(" 1) *spinloop = 0x")); prom_print_hex(*spinloop); prom_print_nl(); prom_print(RELOC(" 1) acknowledge = 0x")); - prom_print_hex(acknowledge); + prom_print_hex((unsigned long)acknowledge); prom_print_nl(); prom_print(RELOC(" 1) *acknowledge = 0x")); prom_print_hex(*acknowledge); @@ -1210,6 +1263,144 @@ _naca->smt_state = my_smt_enabled; } + +#ifdef CONFIG_BOOTX_TEXT + +/* This function will enable the early boot text when doing OF booting. This + * way, xmon output should work too + */ +static void __init setup_disp_fake_bi(ihandle dp) +{ + int width = 640, height = 480, depth = 8, pitch; + unsigned address; + struct pci_reg_property addrs[8]; + int i, naddrs; + char name[64]; + unsigned long offset = reloc_offset(); + char *getprop = RELOC("getprop"); + + prom_print(RELOC("Initializing fake screen: ")); + + memset(name, 0, sizeof(name)); + call_prom(getprop, 4, 1, dp, RELOC("name"), name, sizeof(name)); + name[sizeof(name)-1] = 0; + prom_print(name); + prom_print(RELOC("\n")); + call_prom(getprop, 4, 1, dp, RELOC("width"), &width, sizeof(width)); + call_prom(getprop, 4, 1, dp, RELOC("height"), &height, sizeof(height)); + call_prom(getprop, 4, 1, dp, RELOC("depth"), &depth, sizeof(depth)); + pitch = width * ((depth + 7) / 8); + call_prom(getprop, 4, 1, dp, RELOC("linebytes"), + &pitch, sizeof(pitch)); + if (pitch == 1) + pitch = 0x1000; /* for strange IBM display */ + address = 0; + + prom_print(RELOC("width ")); + prom_print_hex(width); + prom_print(RELOC(" height ")); + prom_print_hex(height); + prom_print(RELOC(" depth ")); + prom_print_hex(depth); + prom_print(RELOC(" linebytes ")); + prom_print_hex(pitch); + prom_print(RELOC("\n")); + + + call_prom(getprop, 4, 1, dp, RELOC("address"), + &address, sizeof(address)); + if (address == 0) { + /* look for an assigned address with a size of >= 1MB */ + naddrs = (int) call_prom(getprop, 4, 1, dp, + RELOC("assigned-addresses"), + addrs, sizeof(addrs)); + naddrs /= sizeof(struct pci_reg_property); + for (i = 0; i < naddrs; ++i) { + if (addrs[i].size_lo >= (1 << 20)) { + address = addrs[i].addr.a_lo; + /* use the BE aperture if possible */ + if (addrs[i].size_lo >= (16 << 20)) + address += (8 << 20); + break; + } + } + if (address == 0) { + prom_print(RELOC("Failed to get address of frame buffer\n")); + return; + } + } + btext_setup_display(width, height, depth, pitch, address); + prom_print(RELOC("Addr of fb: ")); + prom_print_hex(address); + prom_print_nl(); + RELOC(boot_text_mapped) = 0; +} +#endif /* CONFIG_BOOTX_TEXT */ + +static void __init prom_init_client_services(unsigned long pp) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + + /* Get a handle to the prom entry point before anything else */ + _prom->entry = pp; + + /* Init default value for phys size */ + _prom->encode_phys_size = 32; + + /* get a handle for the stdout device */ + _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1, + RELOC("/chosen")); + if ((long)_prom->chosen <= 0) + prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */ + + /* get device tree root */ + _prom->root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/")); + if ((long)_prom->root <= 0) + prom_panic(RELOC("cannot find device tree root")); /* msg won't be printed :( */ +} + +static void __init prom_init_stdout(void) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + u32 val; + + if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, + RELOC("stdout"), &val, + sizeof(val)) <= 0) + prom_panic(RELOC("cannot find stdout")); + + _prom->stdout = (ihandle)(unsigned long)val; +} + +static int __init prom_find_machine_type(void) +{ + unsigned long offset = reloc_offset(); + struct prom_t *_prom = PTRRELOC(&prom); + char compat[256]; + int len, i = 0; + + len = (int)(long)call_prom(RELOC("getprop"), 4, 1, _prom->root, + RELOC("compatible"), + compat, sizeof(compat)-1); + if (len > 0) { + compat[len] = 0; + while (i < len) { + char *p = &compat[i]; + int sl = strlen(p); + if (sl == 0) + break; + if (strstr(p, RELOC("Power Macintosh")) || + strstr(p, RELOC("MacRISC4"))) + return PLATFORM_POWERMAC; + i += sl + 1; + } + } + /* Default to pSeries */ + return PLATFORM_PSERIES; +} + /* * We enter here early on, when the Open Firmware prom is still * handling exceptions and the MMU hash table for us. @@ -1220,7 +1411,7 @@ unsigned long r6, unsigned long r7) { unsigned long mem; - ihandle prom_root, prom_cpu; + ihandle prom_cpu; phandle cpu_pkg; unsigned long offset = reloc_offset(); long l; @@ -1239,36 +1430,27 @@ RELOC(systemcfg) = _systemcfg = (struct systemcfg *)(SYSTEMCFG_VIRT_ADDR - offset); RELOC(naca) = (struct naca_struct *)(NACA_VIRT_ADDR - offset); - /* Default machine type. */ - _systemcfg->platform = PLATFORM_PSERIES; + /* Init interface to Open Firmware and pickup bi-recs */ + prom_init_client_services(pp); -#if 0 - /* Reset klimit to take into account the embedded system map */ - if (RELOC(embedded_sysmap_end)) - RELOC(klimit) = __va(PAGE_ALIGN(RELOC(embedded_sysmap_end))); -#endif + /* Init prom stdout device */ + prom_init_stdout(); - /* Get a handle to the prom entry point before anything else */ - _prom->entry = pp; + /* check out if we have bi_recs */ _prom->bi_recs = prom_bi_rec_verify((struct bi_record *)r6); - if ( _prom->bi_recs != NULL ) { - RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + _prom->bi_recs->data[1]); - } - - /* First get a handle for the stdout device */ - _prom->chosen = (ihandle)call_prom(RELOC("finddevice"), 1, 1, - RELOC("/chosen")); + if ( _prom->bi_recs != NULL ) + RELOC(klimit) = PTRUNRELOC((unsigned long)_prom->bi_recs + + _prom->bi_recs->data[1]); - if ((long)_prom->chosen <= 0) - prom_panic(RELOC("cannot find chosen")); /* msg won't be printed :( */ + /* Default machine type. */ + _systemcfg->platform = prom_find_machine_type(); - if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, - RELOC("stdout"), &getprop_rval, - sizeof(getprop_rval)) <= 0) - prom_panic(RELOC("cannot find stdout")); - _prom->stdout = (ihandle)(unsigned long)getprop_rval; + /* On pSeries, copy the CPU hold code */ + if (_systemcfg->platform == PLATFORM_PSERIES) + copy_and_flush(0, KERNELBASE - offset, 0x100, 0); + /* Start storing things at klimit */ mem = RELOC(klimit) - offset; /* Get the full OF pathname of the stdout device */ @@ -1279,13 +1461,10 @@ mem += strlen(p) + 1; getprop_rval = 1; - prom_root = (ihandle)call_prom(RELOC("finddevice"), 1, 1, RELOC("/")); - if (prom_root != (ihandle)-1) { - call_prom(RELOC("getprop"), 4, 1, - prom_root, RELOC("#size-cells"), - &getprop_rval, sizeof(getprop_rval)); - } - _prom->encode_phys_size = (getprop_rval==1) ? 32 : 64; + call_prom(RELOC("getprop"), 4, 1, + _prom->root, RELOC("#size-cells"), + &getprop_rval, sizeof(getprop_rval)); + _prom->encode_phys_size = (getprop_rval == 1) ? 32 : 64; /* Determine which cpu is actually running right _now_ */ if ((long)call_prom(RELOC("getprop"), 4, 1, _prom->chosen, @@ -1324,13 +1503,24 @@ mem = DOUBLEWORD_ALIGN(mem + strlen(d) + 1); } + RELOC(cmd_line[0]) = 0; + if ((long)_prom->chosen > 0) { + call_prom(RELOC("getprop"), 4, 1, _prom->chosen, + RELOC("bootargs"), p, sizeof(cmd_line)); + if (p != NULL && p[0] != 0) + strncpy(RELOC(cmd_line), p, sizeof(cmd_line)); + } + RELOC(cmd_line[sizeof(cmd_line) - 1]) = 0; + + mem = prom_initialize_lmb(mem); mem = prom_bi_rec_reserve(mem); mem = check_display(mem); - prom_instantiate_rtas(); + if (_systemcfg->platform != PLATFORM_POWERMAC) + prom_instantiate_rtas(); /* Initialize some system info into the Naca early... */ mem = prom_initialize_naca(mem); @@ -1341,7 +1531,7 @@ * following, regardless of whether we have an SMP * kernel or not. */ - prom_hold_cpus(mem); + prom_hold_cpus(mem); #ifdef DEBUG_PROM prom_print(RELOC("copying OF device tree...\n")); @@ -1355,6 +1545,13 @@ if (_systemcfg->platform == PLATFORM_PSERIES) prom_initialize_tce_table(); +#ifdef CONFIG_BOOTX_TEXT + if(_prom->disp_node) { + prom_print(RELOC("Setting up bi display...\n")); + setup_disp_fake_bi(_prom->disp_node); + } +#endif /* CONFIG_BOOTX_TEXT */ + prom_print(RELOC("Calling quiesce ...\n")); call_prom(RELOC("quiesce"), 0, 0); phys = KERNELBASE - offset; @@ -1471,6 +1668,10 @@ RELOC(prom_display_paths[i]) = PTRUNRELOC(path); if (RELOC(prom_num_displays) >= FB_MAX) break; + /* XXX Temporary workaround: only open the first display so we don't + * lose debug output + */ + break; } return DOUBLEWORD_ALIGN(mem); } @@ -1684,9 +1885,9 @@ np->type = get_property(np, "device_type", 0); /* get the device addresses and interrupts */ - if (ifunc != NULL) { - mem_start = ifunc(np, mem_start, naddrc, nsizec); - } + if (ifunc != NULL) + mem_start = ifunc(np, mem_start, naddrc, nsizec); + mem_start = finish_node_interrupts(np, mem_start); /* Look for #address-cells and #size-cells properties. */ @@ -1700,7 +1901,6 @@ /* the f50 sets the name to 'display' and 'compatible' to what we * expect for the name -- Cort */ - ifunc = NULL; if (!strcmp(np->name, "display")) np->name = get_property(np, "compatible", 0); @@ -1710,8 +1910,19 @@ ifunc = NULL; else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) ifunc = interpret_pci_props; + else if (!strcmp(np->type, "dbdma")) + ifunc = interpret_dbdma_props; + else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) + ifunc = interpret_macio_props; else if (!strcmp(np->type, "isa")) ifunc = interpret_isa_props; + else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3")) + ifunc = interpret_root_props; + else if (!((ifunc == interpret_dbdma_props + || ifunc == interpret_macio_props) + && (!strcmp(np->type, "escc") + || !strcmp(np->type, "media-bay")))) + ifunc = NULL; for (child = np->child; child != NULL; child = child->sibling) mem_start = finish_node(child, mem_start, ifunc, @@ -1888,6 +2099,12 @@ if (n <= 0) continue; np->intrs[i].line = openpic_to_irq(virt_irq_create_mapping(irq[0])); + /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ + if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { + char *name = get_property(ic->parent, "name", NULL); + if (name && !strcmp(name, "u3")) + np->intrs[i].line += 128; + } if (n > 1) np->intrs[i].sense = irq[1]; if (n > 2) { @@ -1960,6 +2177,78 @@ } static unsigned long __init +interpret_dbdma_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) +{ + struct reg_property32 *rp; + struct address_range *adr; + unsigned long base_address; + int i, l; + struct device_node *db; + + base_address = 0; + for (db = np->parent; db != NULL; db = db->parent) { + if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) { + base_address = db->addrs[0].address; + break; + } + } + + rp = (struct reg_property32 *) get_property(np, "reg", &l); + if (rp != 0 && l >= sizeof(struct reg_property32)) { + i = 0; + adr = (struct address_range *) mem_start; + while ((l -= sizeof(struct reg_property32)) >= 0) { + adr[i].space = 2; + adr[i].address = rp[i].address + base_address; + adr[i].size = rp[i].size; + ++i; + } + np->addrs = adr; + np->n_addrs = i; + mem_start += i * sizeof(struct address_range); + } + + return mem_start; +} + +static unsigned long __init +interpret_macio_props(struct device_node *np, unsigned long mem_start, + int naddrc, int nsizec) +{ + struct reg_property32 *rp; + struct address_range *adr; + unsigned long base_address; + int i, l; + struct device_node *db; + + base_address = 0; + for (db = np->parent; db != NULL; db = db->parent) { + if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) { + base_address = db->addrs[0].address; + break; + } + } + + rp = (struct reg_property32 *) get_property(np, "reg", &l); + if (rp != 0 && l >= sizeof(struct reg_property32)) { + i = 0; + adr = (struct address_range *) mem_start; + while ((l -= sizeof(struct reg_property32)) >= 0) { + adr[i].space = 2; + adr[i].address = rp[i].address + base_address; + adr[i].size = rp[i].size; + ++i; + } + np->addrs = adr; + np->n_addrs = i; + mem_start += i * sizeof(struct address_range); + } + + return mem_start; +} + +static unsigned long __init interpret_isa_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec) { @@ -2207,6 +2496,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_node_by_name); /** * of_find_node_by_type - Find a node by its "device_type" property @@ -2270,6 +2560,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_compatible_node); /** * of_find_node_by_path - Find a node matching a full OF path @@ -2290,6 +2581,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_node_by_path); /** * of_find_all_nodes - Get next node in global list @@ -2313,6 +2605,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_find_all_nodes); /** * of_get_parent - Get a node's parent if any @@ -2333,6 +2626,7 @@ read_unlock(&devtree_lock); return np; } +EXPORT_SYMBOL(of_get_parent); /** * of_get_next_child - Iterate a node childs @@ -2357,6 +2651,7 @@ read_unlock(&devtree_lock); return next; } +EXPORT_SYMBOL(of_get_next_child); /** * of_node_get - Increment refcount of a node @@ -2373,6 +2668,7 @@ } return NULL; } +EXPORT_SYMBOL(of_node_get); /** * of_node_put - Decrement refcount of a node @@ -2396,6 +2692,7 @@ else atomic_dec(&node->_users); } +EXPORT_SYMBOL(of_node_put); /** * of_node_cleanup - release a dynamically allocated node @@ -2653,6 +2950,12 @@ goto out; } + /* We don't support that function on PowerMac, at least + * not yet + */ + if (systemcfg->platform == PLATFORM_POWERMAC) + return -ENODEV; + /* do the work of interpret_pci_props */ if (parent->type && !strcmp(parent->type, "pci")) { struct address_range *adr; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/setup.c linux-2.6.3-rc3/arch/ppc64/kernel/setup.c --- linux-2.6.3-rc2/arch/ppc64/kernel/setup.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/setup.c 2004-02-14 19:31:00.000000000 -0800 @@ -40,6 +40,9 @@ #include #include #include +#include +#include +#include extern unsigned long klimit; /* extern void *stab; */ @@ -54,10 +57,17 @@ unsigned long r6, unsigned long r7); +extern void pmac_init(unsigned long r3, + unsigned long r4, + unsigned long r5, + unsigned long r6, + unsigned long r7); + extern void iSeries_init( void ); extern void iSeries_init_early( void ); extern void pSeries_init_early( void ); extern void pSeriesLP_init_early(void); +extern void pmac_init_early(void); extern void mm_init_ppc64( void ); extern void pseries_secondary_smp_init(unsigned long); extern int idle_setup(void); @@ -68,9 +78,7 @@ unsigned long decr_overclock_set = 0; unsigned long decr_overclock_proc0_set = 0; -#ifdef CONFIG_XMON -extern void xmon_map_scc(void); -#endif +int powersave_nap; char saved_command_line[256]; unsigned char aux_device_present; @@ -148,15 +156,11 @@ unsigned long r6, unsigned long r7) { #ifdef CONFIG_PPC_PSERIES - unsigned int ret, i; + unsigned int ret, i; #endif #ifdef CONFIG_XMON_DEFAULT - debugger = xmon; - debugger_bpt = xmon_bpt; - debugger_sstep = xmon_sstep; - debugger_iabr_match = xmon_iabr_match; - debugger_dabr_match = xmon_dabr_match; + xmon_init(); #endif #ifdef CONFIG_PPC_ISERIES @@ -188,9 +192,25 @@ #endif parse_bootinfo(); break; +#endif /* CONFIG_PPC_PSERIES */ +#ifdef CONFIG_PPC_PMAC + case PLATFORM_POWERMAC: + pmac_init_early(); +#ifdef CONFIG_BLK_DEV_INITRD + initrd_start = initrd_end = 0; #endif + parse_bootinfo(); +#endif /* CONFIG_PPC_PMAC */ } +#ifdef CONFIG_BOOTX_TEXT + map_boot_text(); + if (systemcfg->platform == PLATFORM_POWERMAC) { + early_console_initialized = 1; + register_console(&udbg_console); + } +#endif /* CONFIG_BOOTX_TEXT */ + #ifdef CONFIG_PPC_PSERIES if (systemcfg->platform & PLATFORM_PSERIES) { early_console_initialized = 1; @@ -206,14 +226,23 @@ rtas_call(rtas_token("start-cpu"), 3, 1, (void *)&ret, get_hard_smp_processor_id(i), - *((unsigned long *)pseries_secondary_smp_init), i); + *((unsigned long *)pseries_secondary_smp_init), + i); cpu_set(i, cpu_possible_map); systemcfg->processorCount++; } } -#endif } -#endif +#endif /* CONFIG_SMP */ +#endif /* CONFIG_PPC_PSERIES */ + +#ifdef CONFIG_PPC_PMAC + if (systemcfg->platform == PLATFORM_POWERMAC) { + finish_device_tree(); + pmac_init(r3, r4, r5, r6, r7); + } +#endif /* CONFIG_PPC_PMAC */ + /* Finish initializing the hash table (do the dynamic * patching for the fast-path hashtable.S code) */ @@ -226,7 +255,7 @@ printk("naca->pftSize = 0x%lx\n", naca->pftSize); printk("naca->debug_switch = 0x%lx\n", naca->debug_switch); printk("naca->interrupt_controller = 0x%ld\n", naca->interrupt_controller); - printk("systemcfg = 0x%p\n", systemcfg); + printk("systemcfg = 0x%p\n", systemcfg); printk("systemcfg->processorCount = 0x%lx\n", systemcfg->processorCount); printk("systemcfg->physicalMemorySize = 0x%lx\n", systemcfg->physicalMemorySize); printk("systemcfg->dCacheL1LineSize = 0x%x\n", systemcfg->dCacheL1LineSize); @@ -261,6 +290,8 @@ void machine_restart(char *cmd) { + if (ppc_md.nvram_sync) + ppc_md.nvram_sync(); ppc_md.restart(cmd); } @@ -268,6 +299,8 @@ void machine_power_off(void) { + if (ppc_md.nvram_sync) + ppc_md.nvram_sync(); ppc_md.power_off(); } @@ -275,6 +308,8 @@ void machine_halt(void) { + if (ppc_md.nvram_sync) + ppc_md.nvram_sync(); ppc_md.halt(); } @@ -559,13 +594,15 @@ calibrate_delay = ppc64_calibrate_delay; ppc64_boot_msg(0x12, "Setup Arch"); + #ifdef CONFIG_XMON - xmon_map_scc(); - if (strstr(cmd_line, "xmon")) - xmon(0); + if (strstr(cmd_line, "xmon")) { + /* ensure xmon is enabled */ + xmon_init(); + debugger(0); + } #endif /* CONFIG_XMON */ - /* * Set cache line size based on type of cpu as a default. * Systems with OF can look in the properties on the cpu node(s) diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/smp-tbsync.c linux-2.6.3-rc3/arch/ppc64/kernel/smp-tbsync.c --- linux-2.6.3-rc2/arch/ppc64/kernel/smp-tbsync.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/smp-tbsync.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,179 @@ +/* + * Smp timebase synchronization for ppc. + * + * Copyright (C) 2003 Samuel Rydh (samuel@ibrium.se) + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define NUM_ITER 300 + +enum { + kExit=0, kSetAndTest, kTest +}; + +static struct { + volatile long tb; + volatile long mark; + volatile int cmd; + volatile int handshake; + int filler[3]; + + volatile int ack; + int filler2[7]; + + volatile int race_result; +} *tbsync; + +static volatile int running; + +static void __devinit +enter_contest( long mark, long add ) +{ + while( (long)(mftb() - mark) < 0 ) + tbsync->race_result = add; +} + +void __devinit +smp_generic_take_timebase( void ) +{ + int cmd; + long tb; + + local_irq_disable(); + while( !running ) + ; + rmb(); + + for( ;; ) { + tbsync->ack = 1; + while( !tbsync->handshake ) + ; + rmb(); + + cmd = tbsync->cmd; + tb = tbsync->tb; + tbsync->ack = 0; + if( cmd == kExit ) + return; + + if( cmd == kSetAndTest ) { + while( tbsync->handshake ) + ; + asm volatile ("mttbl %0" :: "r" (tb & 0xfffffffful) ); + asm volatile ("mttbu %0" :: "r" (tb >> 32) ); + } else { + while( tbsync->handshake ) + ; + } + enter_contest( tbsync->mark, -1 ); + } + local_irq_enable(); +} + +static int __devinit +start_contest( int cmd, long offset, long num ) +{ + int i, score=0; + long tb, mark; + + tbsync->cmd = cmd; + + local_irq_disable(); + for( i=-3; itb = tb + offset; + tbsync->mark = mark = tb + 400; + + wmb(); + + tbsync->handshake = 1; + while( tbsync->ack ) + ; + + while( (long)(mftb() - tb) <= 0 ) + ; + tbsync->handshake = 0; + enter_contest( mark, 1 ); + + while( !tbsync->ack ) + ; + + if ((tbsync->tb ^ (long)mftb()) & 0x8000000000000000ul) + continue; + if( i++ > 0 ) + score += tbsync->race_result; + } + local_irq_enable(); + return score; +} + +void __devinit +smp_generic_give_timebase( void ) +{ + int i, score, score2, old, min=0, max=5000, offset=1000; + + printk("Synchronizing timebase\n"); + + /* if this fails then this kernel won't work anyway... */ + tbsync = kmalloc( sizeof(*tbsync), GFP_KERNEL ); + memset( tbsync, 0, sizeof(*tbsync) ); + mb(); + running = 1; + + while( !tbsync->ack ) + ; + + printk("Got ack\n"); + + /* binary search */ + for( old=-1 ; old != offset ; offset=(min+max)/2 ) { + score = start_contest( kSetAndTest, offset, NUM_ITER ); + + printk("score %d, offset %d\n", score, offset ); + + if( score > 0 ) + max = offset; + else + min = offset; + old = offset; + } + score = start_contest( kSetAndTest, min, NUM_ITER ); + score2 = start_contest( kSetAndTest, max, NUM_ITER ); + + printk( "Min %d (score %d), Max %d (score %d)\n", min, score, max, score2 ); + score = abs( score ); + score2 = abs( score2 ); + offset = (score < score2) ? min : max; + + /* guard against inaccurate mttb */ + for( i=0; i<10; i++ ) { + start_contest( kSetAndTest, offset, NUM_ITER/10 ); + + if( (score2=start_contest(kTest, offset, NUM_ITER)) < 0 ) + score2 = -score2; + if( score2 <= score || score2 < 20 ) + break; + } + printk("Final offset: %d (%d/%d)\n", offset, score2, NUM_ITER ); + + /* exiting */ + tbsync->cmd = kExit; + wmb(); + tbsync->handshake = 1; + while( tbsync->ack ) + ; + tbsync->handshake = 0; + kfree( tbsync ); + tbsync = NULL; + running = 0; +} diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/smp.c linux-2.6.3-rc3/arch/ppc64/kernel/smp.c --- linux-2.6.3-rc2/arch/ppc64/kernel/smp.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/smp.c 2004-02-14 19:31:00.000000000 -0800 @@ -49,6 +49,7 @@ #include #include #include +#include int smp_threads_ready; unsigned long cache_decay_ticks; @@ -62,7 +63,7 @@ EXPORT_SYMBOL(cpu_online_map); EXPORT_SYMBOL(cpu_possible_map); -static struct smp_ops_t *smp_ops; +struct smp_ops_t *smp_ops; static volatile unsigned int cpu_callin_map[NR_CPUS]; @@ -76,13 +77,8 @@ #define smp_message_pass(t,m,d,w) smp_ops->message_pass((t),(m),(d),(w)) -static inline void set_tb(unsigned int upper, unsigned int lower) -{ - mttbl(0); - mttbu(upper); - mttbl(lower); -} - +/* Low level assembly function used to backup CPU 0 state */ +extern void __save_cpu_setup(void); #ifdef CONFIG_PPC_ISERIES static unsigned long iSeries_smp_message[NR_CPUS]; @@ -182,21 +178,23 @@ { } +static struct smp_ops_t iSeries_smp_ops = { + .message_pass = smp_iSeries_message_pass, + .probe = smp_iSeries_probe, + .kick_cpu = smp_iSeries_kick_cpu, + .setup_cpu = smp_iSeries_setup_cpu, +}; + /* This is called very early. */ void __init smp_init_iSeries(void) { - smp_ops = &ppc_md.smp_ops; - smp_ops->message_pass = smp_iSeries_message_pass; - smp_ops->probe = smp_iSeries_probe; - smp_ops->kick_cpu = smp_iSeries_kick_cpu; - smp_ops->setup_cpu = smp_iSeries_setup_cpu; + smp_ops = &iSeries_smp_ops; systemcfg->processorCount = smp_iSeries_numProcs(); } #endif #ifdef CONFIG_PPC_PSERIES -static void -smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) +void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait) { /* make sure we're sending something that translates to an IPI */ if ( msg > 0x3 ){ @@ -240,8 +238,7 @@ do_openpic_setup_cpu(); } -static void -smp_kick_cpu(int nr) +static void smp_pSeries_kick_cpu(int nr) { /* Verify we have a Paca for processor nr */ if ( ( nr <= 0 ) || @@ -290,8 +287,7 @@ register_vpa(flags, cpu, __pa((unsigned long)&(paca[cpu].xLpPaca))); } -static void -smp_xics_message_pass(int target, int msg, unsigned long data, int wait) +static void smp_xics_message_pass(int target, int msg, unsigned long data, int wait) { int i; @@ -358,27 +354,34 @@ spin_unlock(&timebase_lock); } +static struct smp_ops_t pSeries_openpic_smp_ops = { + .message_pass = smp_openpic_message_pass, + .probe = smp_openpic_probe, + .kick_cpu = smp_pSeries_kick_cpu, + .setup_cpu = smp_openpic_setup_cpu, +}; + +static struct smp_ops_t pSeries_xics_smp_ops = { + .message_pass = smp_xics_message_pass, + .probe = smp_xics_probe, + .kick_cpu = smp_pSeries_kick_cpu, + .setup_cpu = smp_xics_setup_cpu, +}; + /* This is called very early */ void __init smp_init_pSeries(void) { - smp_ops = &ppc_md.smp_ops; - if (naca->interrupt_controller == IC_OPEN_PIC) { - smp_ops->message_pass = smp_openpic_message_pass; - smp_ops->probe = smp_openpic_probe; - smp_ops->setup_cpu = smp_openpic_setup_cpu; - } else { - smp_ops->message_pass = smp_xics_message_pass; - smp_ops->probe = smp_xics_probe; - smp_ops->setup_cpu = smp_xics_setup_cpu; - } + if (naca->interrupt_controller == IC_OPEN_PIC) + smp_ops = &pSeries_openpic_smp_ops; + else + smp_ops = &pSeries_xics_smp_ops; + /* Non-lpar has additional take/give timebase */ if (systemcfg->platform == PLATFORM_PSERIES) { smp_ops->give_timebase = pSeries_give_timebase; smp_ops->take_timebase = pSeries_take_timebase; } - - smp_ops->kick_cpu = smp_kick_cpu; } #endif @@ -392,7 +395,7 @@ void smp_message_recv(int msg, struct pt_regs *regs) { - switch( msg ) { + switch(msg) { case PPC_MSG_CALL_FUNCTION: smp_call_function_interrupt(); break; @@ -405,11 +408,11 @@ /* spare */ break; #endif -#ifdef CONFIG_XMON - case PPC_MSG_XMON_BREAK: - xmon(regs); +#ifdef CONFIG_DEBUGGER + case PPC_MSG_DEBUGGER_BREAK: + debugger(regs); break; -#endif /* CONFIG_XMON */ +#endif default: printk("SMP %d: smp_message_recv(): unknown msg %d\n", smp_processor_id(), msg); @@ -422,12 +425,12 @@ smp_message_pass(cpu, PPC_MSG_RESCHEDULE, 0, 0); } -#ifdef CONFIG_XMON -void smp_send_xmon_break(int cpu) +#ifdef CONFIG_DEBUGGER +void smp_send_debugger_break(int cpu) { - smp_message_pass(cpu, PPC_MSG_XMON_BREAK, 0, 0); + smp_message_pass(cpu, PPC_MSG_DEBUGGER_BREAK, 0, 0); } -#endif /* CONFIG_XMON */ +#endif static void stop_this_cpu(void *dummy) { @@ -505,10 +508,7 @@ printk("smp_call_function on cpu %d: other cpus not " "responding (%d)\n", smp_processor_id(), atomic_read(&data.started)); -#ifdef CONFIG_DEBUG_KERNEL - if (debugger) - debugger(0); -#endif + debugger(0); goto out; } } @@ -523,10 +523,7 @@ smp_processor_id(), atomic_read(&data.finished), atomic_read(&data.started)); -#ifdef CONFIG_DEBUG_KERNEL - if (debugger) - debugger(0); -#endif + debugger(0); goto out; } } @@ -613,6 +610,10 @@ #endif max_cpus = smp_ops->probe(); + + /* Backup CPU 0 state if necessary */ + __save_cpu_setup(); + smp_space_timers(max_cpus); } diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/sys_ppc32.c linux-2.6.3-rc3/arch/ppc64/kernel/sys_ppc32.c --- linux-2.6.3-rc2/arch/ppc64/kernel/sys_ppc32.c 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/sys_ppc32.c 2004-02-14 19:31:00.000000000 -0800 @@ -76,6 +76,8 @@ #include #include +#include "pci.h" + typedef ssize_t (*io_fn_t)(struct file *, char *, size_t, loff_t *); typedef ssize_t (*iov_fn_t)(struct file *, const struct iovec *, unsigned long, loff_t *); @@ -2210,7 +2212,7 @@ extern asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, unsigned long off, - unsigned long len, unsigned char *buf); + unsigned long len, unsigned char *buf); asmlinkage int sys32_pciconfig_write(u32 bus, u32 dfn, u32 off, u32 len, u32 ubuf) { @@ -2221,6 +2223,64 @@ (unsigned char *)AA(ubuf)); } +#define IOBASE_BRIDGE_NUMBER 0 +#define IOBASE_MEMORY 1 +#define IOBASE_IO 2 +#define IOBASE_ISA_IO 3 +#define IOBASE_ISA_MEM 4 + +asmlinkage int sys32_pciconfig_iobase(u32 which, u32 in_bus, u32 in_devfn) +{ + struct pci_controller* hose; + struct list_head *ln; + struct pci_bus *bus = NULL; + struct device_node *hose_node; + + /* Argh ! Please forgive me for that hack, but that's the + * simplest way to get existing XFree to not lockup on some + * G5 machines... So when something asks for bus 0 io base + * (bus 0 is HT root), we return the AGP one instead. + */ +#ifdef CONFIG_PPC_PMAC + if (systemcfg->platform == PLATFORM_POWERMAC && + machine_is_compatible("MacRISC4")) + if (in_bus == 0) + in_bus = 0xf0; +#endif /* CONFIG_PPC_PMAC */ + + /* That syscall isn't quite compatible with PCI domains, but it's + * used on pre-domains setup. We return the first match + */ + + for (ln = pci_root_buses.next; ln != &pci_root_buses; ln = ln->next) { + bus = pci_bus_b(ln); + if (in_bus >= bus->number && in_bus < (bus->number + bus->subordinate)) + break; + bus = NULL; + } + if (bus == NULL || bus->sysdata == NULL) + return -ENODEV; + + hose_node = (struct device_node *)bus->sysdata; + hose = hose_node->phb; + + switch (which) { + case IOBASE_BRIDGE_NUMBER: + return (long)hose->first_busno; + case IOBASE_MEMORY: + return (long)hose->pci_mem_offset; + case IOBASE_IO: + return (long)hose->io_base_phys; + case IOBASE_ISA_IO: + return (long)isa_io_base; + case IOBASE_ISA_MEM: + return -EINVAL; + } + + return -EOPNOTSUPP; +} + + extern asmlinkage int sys_newuname(struct new_utsname * name); asmlinkage int ppc64_newuname(struct new_utsname * name) diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/traps.c linux-2.6.3-rc3/arch/ppc64/kernel/traps.c --- linux-2.6.3-rc2/arch/ppc64/kernel/traps.c 2004-02-03 19:43:48.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/traps.c 2004-02-14 19:31:00.000000000 -0800 @@ -45,13 +45,20 @@ extern int fwnmi_active; #endif -#ifdef CONFIG_DEBUG_KERNEL -void (*debugger)(struct pt_regs *regs); -int (*debugger_bpt)(struct pt_regs *regs); -int (*debugger_sstep)(struct pt_regs *regs); -int (*debugger_iabr_match)(struct pt_regs *regs); -int (*debugger_dabr_match)(struct pt_regs *regs); -void (*debugger_fault_handler)(struct pt_regs *regs); +#ifdef CONFIG_DEBUGGER +int (*__debugger)(struct pt_regs *regs); +int (*__debugger_bpt)(struct pt_regs *regs); +int (*__debugger_sstep)(struct pt_regs *regs); +int (*__debugger_iabr_match)(struct pt_regs *regs); +int (*__debugger_dabr_match)(struct pt_regs *regs); +int (*__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); #endif /* @@ -88,10 +95,8 @@ _exception(int signr, siginfo_t *info, struct pt_regs *regs) { if (!user_mode(regs)) { -#ifdef CONFIG_DEBUG_KERNEL - if (debugger) - debugger(regs); -#endif + if (debugger(regs)) + return; die("Exception in kernel mode\n", regs, signr); } @@ -146,12 +151,8 @@ } #endif -#ifdef CONFIG_DEBUG_KERNEL - if (debugger) - debugger(regs); - else -#endif - panic("System Reset"); + if (!debugger(regs)) + die("System Reset", regs, 0); /* Must die if the interrupt is not recoverable */ if (!(regs->msr & MSR_RI)) @@ -228,23 +229,12 @@ } #endif -#ifdef CONFIG_DEBUG_KERNEL - if (debugger_fault_handler) { - debugger_fault_handler(regs); + if (debugger_fault_handler(regs)) return; - } - if (debugger) - debugger(regs); -#endif - console_verbose(); - spin_lock_irq(&die_lock); - bust_spinlocks(1); - printk("Machine check in kernel mode.\n"); - printk("Caused by (from SRR1=%lx): ", regs->msr); - show_regs(regs); - bust_spinlocks(0); - spin_unlock_irq(&die_lock); - panic("Unrecoverable Machine Check"); + if (debugger(regs)) + return; + + die("Machine check in kernel mode", regs, 0); } void @@ -267,10 +257,8 @@ { siginfo_t info; -#ifdef CONFIG_DEBUG_KERNEL - if (debugger_iabr_match && debugger_iabr_match(regs)) + if (debugger_iabr_match(regs)) return; -#endif info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; @@ -372,6 +360,9 @@ { siginfo_t info; + if (debugger_fault_handler(regs)) + return; + if (regs->msr & 0x100000) { /* IEEE FP exception */ @@ -387,10 +378,9 @@ } else if (regs->msr & 0x20000) { /* trap exception */ -#ifdef CONFIG_DEBUG_KERNEL - if (debugger_bpt && debugger_bpt(regs)) + if (debugger_bpt(regs)) return; -#endif + if (check_bug_trap(regs)) { regs->nip += 4; return; @@ -414,17 +404,13 @@ void KernelFPUnavailableException(struct pt_regs *regs) { - printk("Illegal floating point used in kernel (task=0x%p, " - "pc=0x%016lx, trap=0x%lx)\n", current, regs->nip, regs->trap); - panic("Unrecoverable FP Unavailable Exception in Kernel"); + die("Unrecoverable FP Unavailable Exception in Kernel", regs, 0); } void KernelAltivecUnavailableException(struct pt_regs *regs) { - printk("Illegal VMX/Altivec used in kernel (task=0x%p, " - "pc=0x%016lx, trap=0x%lx)\n", current, regs->nip, regs->trap); - panic("Unrecoverable VMX/Altivec Unavailable Exception in Kernel"); + die("Unrecoverable VMX/Altivec Unavailable Exception in Kernel", regs, 0); } void @@ -434,10 +420,9 @@ regs->msr &= ~MSR_SE; /* Turn off 'trace' bit */ -#ifdef CONFIG_DEBUG_KERNEL - if (debugger_sstep && debugger_sstep(regs)) + if (debugger_sstep(regs)) return; -#endif + info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_TRACE; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/udbg.c linux-2.6.3-rc3/arch/ppc64/kernel/udbg.c --- linux-2.6.3-rc2/arch/ppc64/kernel/udbg.c 2004-02-03 19:43:07.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/udbg.c 2004-02-14 19:31:00.000000000 -0800 @@ -22,6 +22,9 @@ #include #include #include +#include +#include +#include struct NS16550 { /* this struct must be packed */ @@ -69,6 +72,61 @@ } } +#ifdef CONFIG_PPC_PMAC + +#define SCC_TXRDY 4 +#define SCC_RXRDY 1 + +static volatile u8 *sccc, *sccd; + +static unsigned char scc_inittab[] = { + 13, 0, /* set baud rate divisor */ + 12, 0, + 14, 1, /* baud rate gen enable, src=rtxc */ + 11, 0x50, /* clocks = br gen */ + 5, 0xea, /* tx 8 bits, assert DTR & RTS */ + 4, 0x46, /* x16 clock, 1 stop */ + 3, 0xc1, /* rx enable, 8 bits */ +}; + +void +udbg_init_scc(struct device_node *np) +{ + unsigned long addr; + int i, x; + + if (np == NULL) + np = of_find_node_by_name(NULL, "escc"); + if (np == NULL) + return; + + /* Lock-enable the SCC channel */ + pmac_call_feature(PMAC_FTR_SCC_ENABLE, np, PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1); + + /* Setup for 57600 8N1 */ + addr = np->addrs[0].address + 0x20; + sccc = (volatile u8 *) ioremap(addr & PAGE_MASK, PAGE_SIZE) ; + sccc += addr & ~PAGE_MASK; + sccd = sccc + 0x10; + + for (i = 20000; i != 0; --i) + x = *sccc; eieio(); + *sccc = 9; eieio(); /* reset A or B side */ + *sccc = 0xc0; eieio(); + for (i = 0; i < sizeof(scc_inittab); ++i) { + *sccc = scc_inittab[i]; + eieio(); + } + + ppc_md.udbg_putc = udbg_putc; + ppc_md.udbg_getc = udbg_getc; + ppc_md.udbg_getc_poll = udbg_getc_poll; + + udbg_puts("Hello World !\n"); +} + +#endif /* CONFIG_PPC_PMAC */ + void udbg_putc(unsigned char c) { @@ -83,6 +141,16 @@ udbg_comport->thr = '\r'; eieio(); } } +#ifdef CONFIG_PPC_PMAC + else if (sccc) { + while ((*sccc & SCC_TXRDY) == 0) + eieio(); + *sccd = c; + eieio(); + if (c == '\n') + udbg_putc('\r'); + } +#endif /* CONFIG_PPC_PMAC */ } int udbg_getc_poll(void) @@ -93,6 +161,15 @@ else return -1; } +#ifdef CONFIG_PPC_PMAC + else if (sccc) { + eieio(); + if ((*sccc & SCC_RXRDY) != 0) + return *sccd; + else + return -1; + } +#endif /* CONFIG_PPC_PMAC */ return -1; } @@ -104,6 +181,14 @@ /* wait for char */; return udbg_comport->rbr; } +#ifdef CONFIG_PPC_PMAC + else if (sccc) { + eieio(); + while ((*sccc & SCC_RXRDY) == 0) + eieio(); + return *sccd; + } +#endif /* CONFIG_PPC_PMAC */ return 0; } @@ -149,6 +234,8 @@ do { c = ppc_md.udbg_getc(); } while (c == 0x11 || c == 0x13); + if (c == 0) + break; *p++ = c; } return i; diff -urN linux-2.6.3-rc2/arch/ppc64/kernel/xics.c linux-2.6.3-rc3/arch/ppc64/kernel/xics.c --- linux-2.6.3-rc2/arch/ppc64/kernel/xics.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/kernel/xics.c 2004-02-14 19:31:00.000000000 -0800 @@ -353,11 +353,11 @@ smp_message_recv(PPC_MSG_MIGRATE_TASK, regs); } #endif -#ifdef CONFIG_XMON - if (test_and_clear_bit(PPC_MSG_XMON_BREAK, +#ifdef CONFIG_DEBUGGER + if (test_and_clear_bit(PPC_MSG_DEBUGGER_BREAK, &xics_ipi_message[cpu].value)) { mb(); - smp_message_recv(PPC_MSG_XMON_BREAK, regs); + smp_message_recv(PPC_MSG_DEBUGGER_BREAK, regs); } #endif } diff -urN linux-2.6.3-rc2/arch/ppc64/mm/fault.c linux-2.6.3-rc3/arch/ppc64/mm/fault.c --- linux-2.6.3-rc2/arch/ppc64/mm/fault.c 2004-02-03 19:44:15.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/mm/fault.c 2004-02-14 19:31:00.000000000 -0800 @@ -37,12 +37,6 @@ #include #include -#include - -#ifdef CONFIG_DEBUG_KERNEL -int debugger_kernel_faults = 1; -#endif - void bad_page_fault(struct pt_regs *, unsigned long, int); /* @@ -60,13 +54,10 @@ unsigned long code = SEGV_MAPERR; unsigned long is_write = error_code & 0x02000000; -#ifdef CONFIG_DEBUG_KERNEL - if (debugger_fault_handler && (regs->trap == 0x300 || - regs->trap == 0x380)) { - debugger_fault_handler(regs); - return; + if (regs->trap == 0x300 || regs->trap == 0x380) { + if (debugger_fault_handler(regs)) + return; } -#endif /* On a kernel SLB miss we can only check for a valid exception entry */ if (!user_mode(regs) && (regs->trap == 0x380)) { @@ -74,13 +65,10 @@ return; } -#ifdef CONFIG_DEBUG_KERNEL if (error_code & 0x00400000) { - /* DABR match */ if (debugger_dabr_match(regs)) return; } -#endif if (in_atomic() || mm == NULL) { bad_page_fault(regs, address, SIGSEGV); @@ -149,11 +137,6 @@ info.si_errno = 0; info.si_code = code; info.si_addr = (void *) address; -#ifdef CONFIG_XMON - ifppcdebug(PPCDBG_SIGNALXMON) - PPCDBG_ENTER_DEBUGGER_REGS(regs); -#endif - force_sig_info(SIGSEGV, &info, current); return; } @@ -207,9 +190,7 @@ } /* kernel has accessed a bad area */ -#ifdef CONFIG_DEBUG_KERNEL - if (debugger_kernel_faults) - debugger(regs); -#endif + if (debugger(regs)) + return; die("Kernel access of bad area", regs, sig); } diff -urN linux-2.6.3-rc2/arch/ppc64/mm/hash_low.S linux-2.6.3-rc3/arch/ppc64/mm/hash_low.S --- linux-2.6.3-rc2/arch/ppc64/mm/hash_low.S 2004-02-03 19:44:27.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/mm/hash_low.S 2004-02-14 19:31:00.000000000 -0800 @@ -95,7 +95,7 @@ /* Write the linux PTE atomically (setting busy) */ stdcx. r30,0,r6 bne- 1b - + isync /* Step 2: * diff -urN linux-2.6.3-rc2/arch/ppc64/mm/hash_utils.c linux-2.6.3-rc3/arch/ppc64/mm/hash_utils.c --- linux-2.6.3-rc2/arch/ppc64/mm/hash_utils.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/mm/hash_utils.c 2004-02-14 19:31:00.000000000 -0800 @@ -140,7 +140,8 @@ htab_data.htab_num_ptegs = pteg_count; htab_data.htab_hash_mask = pteg_count - 1; - if (systemcfg->platform == PLATFORM_PSERIES) { + if (systemcfg->platform == PLATFORM_PSERIES || + systemcfg->platform == PLATFORM_POWERMAC) { /* Find storage for the HPT. Must be contiguous in * the absolute address space. */ diff -urN linux-2.6.3-rc2/arch/ppc64/mm/init.c linux-2.6.3-rc3/arch/ppc64/mm/init.c --- linux-2.6.3-rc2/arch/ppc64/mm/init.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/mm/init.c 2004-02-14 19:31:00.000000000 -0800 @@ -59,6 +59,7 @@ #include #include #include +#include #ifdef CONFIG_PPC_ISERIES #include @@ -691,11 +692,7 @@ bootmap_pages = bootmem_bootmap_pages(total_pages); start = (unsigned long)__a2p(lmb_alloc(bootmap_pages<> PAGE_SHIFT, total_pages); diff -urN linux-2.6.3-rc2/arch/ppc64/xmon/privinst.h linux-2.6.3-rc3/arch/ppc64/xmon/privinst.h --- linux-2.6.3-rc2/arch/ppc64/xmon/privinst.h 2004-02-03 19:43:15.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/xmon/privinst.h 2004-02-14 19:31:00.000000000 -0800 @@ -43,39 +43,12 @@ GSETSPR(275, sprg3) GSETSPR(282, ear) GSETSPR(287, pvr) -GSETSPR(528, bat0u) -GSETSPR(529, bat0l) -GSETSPR(530, bat1u) -GSETSPR(531, bat1l) -GSETSPR(532, bat2u) -GSETSPR(533, bat2l) -GSETSPR(534, bat3u) -GSETSPR(535, bat3l) GSETSPR(1008, hid0) GSETSPR(1009, hid1) GSETSPR(1010, iabr) GSETSPR(1013, dabr) GSETSPR(1023, pir) -static inline int get_sr(int n) -{ - int ret; - -#if 0 - // DRENG does not assemble - asm (" mfsrin %0,%1" : "=r" (ret) : "r" (n << 28)); -#endif - return ret; -} - -static inline void set_sr(int n, int val) -{ -#if 0 - // DRENG does not assemble - asm ("mtsrin %0,%1" : : "r" (val), "r" (n << 28)); -#endif -} - static inline void store_inst(void *p) { asm volatile ("dcbst 0,%0; sync; icbi 0,%0; isync" : : "r" (p)); @@ -90,4 +63,3 @@ { asm volatile ("dcbi 0,%0; icbi 0,%0" : : "r" (p)); } - diff -urN linux-2.6.3-rc2/arch/ppc64/xmon/start.c linux-2.6.3-rc3/arch/ppc64/xmon/start.c --- linux-2.6.3-rc2/arch/ppc64/xmon/start.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/xmon/start.c 2004-02-14 19:31:00.000000000 -0800 @@ -11,31 +11,23 @@ #include #include #include +#include #include #include #include #include #include #include - -extern void xmon_printf(const char *fmt, ...); - -#define TB_SPEED 25000000 - -static inline unsigned int readtb(void) -{ - unsigned int ret; - - asm volatile("mftb %0" : "=r" (ret) :); - return ret; -} +#include #ifdef CONFIG_MAGIC_SYSRQ static void sysrq_handle_xmon(int key, struct pt_regs *pt_regs, struct tty_struct *tty) { - xmon(pt_regs); + /* ensure xmon is enabled */ + xmon_init(); + debugger(pt_regs); } static struct sysrq_key_op sysrq_xmon_op = @@ -45,16 +37,13 @@ .action_msg = "Entering xmon\n", }; -#endif /* CONFIG_MAGIC_SYSRQ */ - -void -xmon_map_scc(void) +static int __init setup_xmon_sysrq(void) { -#ifdef CONFIG_MAGIC_SYSRQ - /* This maybe isn't the best place to register sysrq 'x' */ __sysrq_put_key_op('x', &sysrq_xmon_op); -#endif /* CONFIG_MAGIC_SYSRQ */ + return 0; } +__initcall(setup_xmon_sysrq); +#endif /* CONFIG_MAGIC_SYSRQ */ int xmon_write(void *handle, void *ptr, int nb) @@ -62,8 +51,6 @@ return udbg_write(ptr, nb); } -int xmon_wants_key; - int xmon_read(void *handle, void *ptr, int nb) { @@ -80,11 +67,6 @@ void *xmon_stdout; void *xmon_stderr; -void -xmon_init(void) -{ -} - int xmon_putc(int c, void *f) { diff -urN linux-2.6.3-rc2/arch/ppc64/xmon/xmon.c linux-2.6.3-rc3/arch/ppc64/xmon/xmon.c --- linux-2.6.3-rc2/arch/ppc64/xmon/xmon.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/ppc64/xmon/xmon.c 2004-02-14 19:31:00.000000000 -0800 @@ -73,11 +73,10 @@ static unsigned bpinstr = 0x7fe00008; /* trap */ /* Prototypes */ -extern void (*debugger_fault_handler)(struct pt_regs *); static int cmds(struct pt_regs *); static int mread(unsigned long, void *, int); static int mwrite(unsigned long, void *, int); -static void handle_fault(struct pt_regs *); +static int handle_fault(struct pt_regs *); static void byterev(unsigned char *, int); static void memex(void); static int bsesc(void); @@ -115,10 +114,7 @@ #endif /* CONFIG_SMP */ static void csum(void); static void bootcmds(void); -static void mem_translate(void); -static void mem_check(void); -static void mem_find_real(void); -static void mem_find_vsid(void); +void dump_segments(void); static void debug_trace(void); @@ -149,7 +145,15 @@ b show breakpoints\n\ bd set data breakpoint\n\ bi set instruction breakpoint\n\ - bc clear breakpoint\n\ + bc clear breakpoint\n" +#ifdef CONFIG_SMP + "\ + c print cpus stopped in xmon\n\ + ci send xmon interrupt to all other cpus\n\ + c# try to switch to cpu number h (in hex)\n" +#endif + "\ + C checksum\n\ d dump bytes\n\ di dump instructions\n\ df dump float values\n\ @@ -162,7 +166,6 @@ md compare two blocks of memory\n\ ml locate a block of memory\n\ mz zero a block of memory\n\ - mx translation information for an effective address\n\ mi show information about memory allocation\n\ p show the task list\n\ r print registers\n\ @@ -171,7 +174,14 @@ t print backtrace\n\ T Enable/Disable PPCDBG flags\n\ x exit monitor\n\ -"; + u dump segment table or SLB\n\ + ? help\n" +#ifndef CONFIG_PPC_ISERIES + "\ + zr reboot\n\ + zh halt\n" +#endif +; static int xmon_trace[NR_CPUS]; #define SSTEP 1 /* stepping because of 's' command */ @@ -224,7 +234,7 @@ #endif } -void +int xmon(struct pt_regs *excp) { struct pt_regs regs; @@ -308,6 +318,7 @@ #endif /* CONFIG_SMP */ remove_bpts(); disable_surveillance(); + printf("press ? for help "); cmd = cmds(excp); if (cmd == 's') { xmon_trace[smp_processor_id()] = SSTEP; @@ -330,17 +341,8 @@ cpu_clear(smp_processor_id(), cpus_in_xmon); #endif /* CONFIG_SMP */ set_msrd(msr); /* restore interrupt enable */ -} -void -xmon_irq(int irq, void *d, struct pt_regs *regs) -{ - unsigned long flags; - local_save_flags(flags); - local_irq_disable(); - printf("Keyboard interrupt\n"); - xmon(regs); - local_irq_restore(flags); + return 0; } int @@ -524,18 +526,6 @@ case 'z': memzcan(); break; - case 'x': - mem_translate(); - break; - case 'c': - mem_check(); - break; - case 'f': - mem_find_real(); - break; - case 'e': - mem_find_vsid(); - break; case 'i': show_mem(); break; @@ -587,11 +577,16 @@ cpu_cmd(); break; #endif /* CONFIG_SMP */ +#ifndef CONFIG_PPC_ISERIES case 'z': bootcmds(); +#endif case 'T': debug_trace(); break; + case 'u': + dump_segments(); + break; default: printf("Unrecognized command: "); do { @@ -633,7 +628,7 @@ printf("stopping all cpus\n"); /* interrupt other cpu(s) */ cpu = MSG_ALL_BUT_SELF; - smp_send_xmon_break(cpu); + smp_send_debugger_break(cpu); return; } termch = cmd; @@ -847,7 +842,8 @@ break; } - if (!(systemcfg->platform & PLATFORM_PSERIES)) { + if (systemcfg->platform != PLATFORM_POWERMAC && + !(systemcfg->platform & PLATFORM_PSERIES)) { printf("Not supported for this platform\n"); break; } @@ -1056,14 +1052,23 @@ termch = 0; nflush = 1; scanhex(&nflush); - nflush = (nflush + 31) / 32; - if (cmd != 'i') { - for (; nflush > 0; --nflush, adrs += 0x20) - cflush((void *) adrs); - } else { - for (; nflush > 0; --nflush, adrs += 0x20) - cinval((void *) adrs); + nflush = (nflush + L1_CACHE_BYTES - 1) / L1_CACHE_BYTES; + if (setjmp(bus_error_jmp) == 0) { + __debugger_fault_handler = handle_fault; + sync(); + + if (cmd != 'i') { + for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) + cflush((void *) adrs); + } else { + for (; nflush > 0; --nflush, adrs += L1_CACHE_BYTES) + cinval((void *) adrs); + } + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); } + __debugger_fault_handler = 0; } unsigned long @@ -1072,6 +1077,7 @@ unsigned int instrs[2]; unsigned long (*code)(void); unsigned long opd[3]; + unsigned long ret = -1UL; instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6); instrs[1] = 0x4e800020; @@ -1082,7 +1088,22 @@ store_inst(instrs+1); code = (unsigned long (*)(void)) opd; - return code(); + if (setjmp(bus_error_jmp) == 0) { + __debugger_fault_handler = handle_fault; + sync(); + + ret = code(); + + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + } else { + printf("*** Error reading spr %x\n", n); + } + + __debugger_fault_handler = 0; + + return ret; } void @@ -1101,7 +1122,20 @@ store_inst(instrs+1); code = (unsigned long (*)(unsigned long)) opd; - code(val); + if (setjmp(bus_error_jmp) == 0) { + __debugger_fault_handler = handle_fault; + sync(); + + code(val); + + sync(); + /* wait a little while to see if we get a machine check */ + __delay(200); + } else { + printf("*** Error writing spr %x\n", n); + } + + __debugger_fault_handler = 0; } static unsigned long regno; @@ -1111,11 +1145,14 @@ void super_regs() { - int i, cmd; + int cmd; unsigned long val; - struct paca_struct* ptrPaca = NULL; - struct ItLpPaca* ptrLpPaca = NULL; - struct ItLpRegSave* ptrLpRegSave = NULL; +#ifdef CONFIG_PPC_ISERIES + int i; + struct paca_struct *ptrPaca = NULL; + struct ItLpPaca *ptrLpPaca = NULL; + struct ItLpRegSave *ptrLpRegSave = NULL; +#endif cmd = skipbl(); if (cmd == '\n') { @@ -1129,10 +1166,7 @@ printf("sp = %.16lx sprg3= %.16lx\n", sp, get_sprg3()); printf("toc = %.16lx dar = %.16lx\n", toc, get_dar()); printf("srr0 = %.16lx srr1 = %.16lx\n", get_srr0(), get_srr1()); - printf("asr = %.16lx\n", mfasr()); - for (i = 0; i < 8; ++i) - printf("sr%.2ld = %.16lx sr%.2ld = %.16lx\n", i, get_sr(i), i+8, get_sr(i+8)); - +#ifdef CONFIG_PPC_ISERIES // Dump out relevant Paca data areas. printf("Paca: \n"); ptrPaca = get_paca(); @@ -1148,7 +1182,8 @@ printf(" Saved Sprg0=%.16lx Saved Sprg1=%.16lx \n", ptrLpRegSave->xSPRG0, ptrLpRegSave->xSPRG0); printf(" Saved Sprg2=%.16lx Saved Sprg3=%.16lx \n", ptrLpRegSave->xSPRG2, ptrLpRegSave->xSPRG3); printf(" Saved Msr =%.16lx Saved Nia =%.16lx \n", ptrLpRegSave->xMSR, ptrLpRegSave->xNIA); - +#endif + return; } @@ -1162,11 +1197,6 @@ case 'r': printf("spr %lx = %lx\n", regno, read_spr(regno)); break; - case 's': - val = get_sr(regno); - scanhex(&val); - set_sr(regno, val); - break; case 'm': val = get_msr(); scanhex(&val); @@ -1184,7 +1214,7 @@ n = 0; if (setjmp(bus_error_jmp) == 0) { - debugger_fault_handler = handle_fault; + __debugger_fault_handler = handle_fault; sync(); p = (char *)adrs; q = (char *)buf; @@ -1209,7 +1239,7 @@ __delay(200); n = size; } - debugger_fault_handler = 0; + __debugger_fault_handler = 0; return n; } @@ -1221,7 +1251,7 @@ n = 0; if (setjmp(bus_error_jmp) == 0) { - debugger_fault_handler = handle_fault; + __debugger_fault_handler = handle_fault; sync(); p = (char *) adrs; q = (char *) buf; @@ -1248,14 +1278,14 @@ } else { printf("*** Error writing address %x\n", adrs + n); } - debugger_fault_handler = 0; + __debugger_fault_handler = 0; return n; } static int fault_type; static char *fault_chars[] = { "--", "**", "##" }; -static void +static int handle_fault(struct pt_regs *regs) { switch (regs->trap) { @@ -1271,6 +1301,8 @@ } longjmp(bus_error_jmp, 1); + + return 0; } #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t)) @@ -1884,7 +1916,7 @@ char namebuf[128]; if (setjmp(bus_error_jmp) == 0) { - debugger_fault_handler = handle_fault; + __debugger_fault_handler = handle_fault; sync(); name = kallsyms_lookup(address, &size, &offset, &modname, namebuf); @@ -1895,7 +1927,7 @@ name = "symbol lookup failed"; } - debugger_fault_handler = 0; + __debugger_fault_handler = 0; if (!name) { char addrstr[sizeof("0x%lx") + (BITS_PER_LONG*3/10)]; @@ -1923,240 +1955,8 @@ } } -void -mem_translate() +static void debug_trace(void) { - int c; - unsigned long ea, va, vsid, vpn, page, hpteg_slot_primary, hpteg_slot_secondary, primary_hash, i, *steg, esid, stabl; - HPTE * hpte; - struct mm_struct * mm; - pte_t *ptep = NULL; - void * pgdir; - - c = inchar(); - if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') - termch = c; - scanhex((void *)&ea); - - if ((ea >= KRANGE_START) && (ea <= (KRANGE_START + (1UL<<60)))) { - ptep = 0; - vsid = get_kernel_vsid(ea); - va = ( vsid << 28 ) | ( ea & 0x0fffffff ); - } else { - // if in vmalloc range, use the vmalloc page directory - if ( ( ea >= VMALLOC_START ) && ( ea <= VMALLOC_END ) ) { - mm = &init_mm; - vsid = get_kernel_vsid( ea ); - } - // if in ioremap range, use the ioremap page directory - else if ( ( ea >= IMALLOC_START ) && ( ea <= IMALLOC_END ) ) { - mm = &ioremap_mm; - vsid = get_kernel_vsid( ea ); - } - // if in user range, use the current task's page directory - else if ( ( ea >= USER_START ) && ( ea <= USER_END ) ) { - mm = current->mm; - vsid = get_vsid(mm->context, ea ); - } - pgdir = mm->pgd; - va = ( vsid << 28 ) | ( ea & 0x0fffffff ); - ptep = find_linux_pte( pgdir, ea ); - } - - vpn = ((vsid << 28) | (((ea) & 0xFFFF000))) >> 12; - page = vpn & 0xffff; - esid = (ea >> 28) & 0xFFFFFFFFF; - - // Search the primary group for an available slot - primary_hash = ( vsid & 0x7fffffffff ) ^ page; - hpteg_slot_primary = ( primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP; - hpteg_slot_secondary = ( ~primary_hash & htab_data.htab_hash_mask ) * HPTES_PER_GROUP; - - printf("ea : %.16lx\n", ea); - printf("esid : %.16lx\n", esid); - printf("vsid : %.16lx\n", vsid); - - printf("\nSoftware Page Table\n-------------------\n"); - printf("ptep : %.16lx\n", ((unsigned long *)ptep)); - if(ptep) { - printf("*ptep : %.16lx\n", *((unsigned long *)ptep)); - } - - hpte = htab_data.htab + hpteg_slot_primary; - printf("\nHardware Page Table\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("slot primary : %.16lx\n", hpteg_slot_primary); - printf("slot secondary : %.16lx\n", hpteg_slot_secondary); - printf("\nPrimary Group\n"); - for (i=0; i<8; ++i) { - if ( hpte->dw0.dw0.v != 0 ) { - printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1); - printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n", - (hpte->dw0.dw0.avpn)>>5, - (hpte->dw0.dw0.avpn) & 0x1f, - (hpte->dw0.dw0.h)); - printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn)); - printf(" pp: %.1lx \n", - ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp)); - printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n", - ((hpte->dw1.dw1.w)<<4)| - ((hpte->dw1.dw1.i)<<3)| - ((hpte->dw1.dw1.m)<<2)| - ((hpte->dw1.dw1.g)<<1)| - ((hpte->dw1.dw1.n)<<0), - hpte->dw1.dw1.r, hpte->dw1.dw1.c); - } - hpte++; - } - - printf("\nSecondary Group\n"); - // Search the secondary group - hpte = htab_data.htab + hpteg_slot_secondary; - for (i=0; i<8; ++i) { - if(hpte->dw0.dw0.v) { - printf("%d: (hpte)%.16lx %.16lx\n", i, hpte->dw0.dword0, hpte->dw1.dword1); - printf(" vsid: %.13lx api: %.2lx hash: %.1lx\n", - (hpte->dw0.dw0.avpn)>>5, - (hpte->dw0.dw0.avpn) & 0x1f, - (hpte->dw0.dw0.h)); - printf(" rpn: %.13lx \n", (hpte->dw1.dw1.rpn)); - printf(" pp: %.1lx \n", - ((hpte->dw1.dw1.pp0)<<2)|(hpte->dw1.dw1.pp)); - printf(" wimgn: %.2lx reference: %.1lx change: %.1lx\n", - ((hpte->dw1.dw1.w)<<4)| - ((hpte->dw1.dw1.i)<<3)| - ((hpte->dw1.dw1.m)<<2)| - ((hpte->dw1.dw1.g)<<1)| - ((hpte->dw1.dw1.n)<<0), - hpte->dw1.dw1.r, hpte->dw1.dw1.c); - } - hpte++; - } - - printf("\nHardware Segment Table\n-----------------------\n"); - stabl = (unsigned long)(KERNELBASE+(_ASR&0xFFFFFFFFFFFFFFFE)); - steg = (unsigned long *)((stabl) | ((esid & 0x1f) << 7)); - - printf("stab base : %.16lx\n", stabl); - printf("slot : %.16lx\n", steg); - - for (i=0; i<8; ++i) { - printf("%d: (ste) %.16lx %.16lx\n", i, - *((unsigned long *)(steg+i*2)),*((unsigned long *)(steg+i*2+1)) ); - } -} - -void mem_check() -{ - unsigned long htab_size_bytes; - unsigned long htab_end; - unsigned long last_rpn; - HPTE *hpte1, *hpte2; - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; - last_rpn = 0xfffff; - - printf("\nHardware Page Table Check\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - -#if 1 - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - if ( hpte1->dw1.dw1.rpn <= last_rpn ) { - for(hpte2 = hpte1+1; hpte2 < (HPTE *)htab_end; hpte2++) { - if ( hpte2->dw0.dw0.v != 0 ) { - if(hpte1->dw1.dw1.rpn == hpte2->dw1.dw1.rpn) { - printf(" Duplicate rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" hpte1: %16.16lx *hpte1: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - printf(" hpte2: %16.16lx *hpte2: %16.16lx %16.16lx\n", - hpte2, hpte2->dw0.dword0, hpte2->dw1.dword1); - } - } - } - } else { - printf(" Bogus rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" hpte: %16.16lx *hpte: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - } - } - } -#endif - printf("\nDone -------------------\n"); -} - -void mem_find_real() -{ - unsigned long htab_size_bytes; - unsigned long htab_end; - unsigned long last_rpn; - HPTE *hpte1; - unsigned long pa, rpn; - int c; - - c = inchar(); - if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') - termch = c; - scanhex((void *)&pa); - rpn = pa >> 12; - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - // last_rpn = (naca->physicalMemorySize-1) >> PAGE_SHIFT; - last_rpn = 0xfffff; - - printf("\nMem Find RPN\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - if ( hpte1->dw1.dw1.rpn == rpn ) { - printf(" Found rpn: %.13lx \n", (hpte1->dw1.dw1.rpn)); - printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - } - } - } - printf("\nDone -------------------\n"); -} - -void mem_find_vsid() -{ - unsigned long htab_size_bytes; - unsigned long htab_end; - HPTE *hpte1; - unsigned long vsid; - int c; - - c = inchar(); - if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n') - termch = c; - scanhex((void *)&vsid); - - htab_size_bytes = htab_data.htab_num_ptegs * 128; // 128B / PTEG - htab_end = (unsigned long)htab_data.htab + htab_size_bytes; - - printf("\nMem Find VSID\n-------------------\n"); - printf("htab base : %.16lx\n", htab_data.htab); - printf("htab size : %.16lx\n", htab_size_bytes); - - for(hpte1 = htab_data.htab; hpte1 < (HPTE *)htab_end; hpte1++) { - if ( hpte1->dw0.dw0.v != 0 ) { - if ( ((hpte1->dw0.dw0.avpn)>>5) == vsid ) { - printf(" Found vsid: %.16lx \n", ((hpte1->dw0.dw0.avpn) >> 5)); - printf(" hpte: %16.16lx *hpte1: %16.16lx %16.16lx\n", - hpte1, hpte1->dw0.dword0, hpte1->dw1.dword1); - } - } - } - printf("\nDone -------------------\n"); -} - -static void debug_trace(void) { unsigned long val, cmd, on; cmd = skipbl(); @@ -2203,3 +2003,56 @@ cmd = skipbl(); } } + +static void dump_slb(void) +{ + int i; + unsigned long tmp; + + printf("SLB contents of cpu %d\n", smp_processor_id()); + + for (i = 0; i < naca->slb_size; i++) { + asm volatile("slbmfee %0,%1" : "=r" (tmp) : "r" (i)); + printf("%02d %016lx ", i, tmp); + + asm volatile("slbmfev %0,%1" : "=r" (tmp) : "r" (i)); + printf("%016lx\n", tmp); + } +} + +static void dump_stab(void) +{ + int i; + unsigned long *tmp = (unsigned long *)get_paca()->xStab_data.virt; + + printf("Segment table contents of cpu %d\n", smp_processor_id()); + + for (i = 0; i < PAGE_SIZE/16; i++) { + unsigned long a, b; + + a = *tmp++; + b = *tmp++; + + if (a || b) { + printf("%03d %016lx ", i, a); + printf("%016lx\n", b); + } + } +} + +void xmon_init(void) +{ + __debugger = xmon; + __debugger_bpt = xmon_bpt; + __debugger_sstep = xmon_sstep; + __debugger_iabr_match = xmon_iabr_match; + __debugger_dabr_match = xmon_dabr_match; +} + +void dump_segments(void) +{ + if (cur_cpu_spec->cpu_features & CPU_FTR_SLB) + dump_slb(); + else + dump_stab(); +} diff -urN linux-2.6.3-rc2/arch/sh/Kconfig linux-2.6.3-rc3/arch/sh/Kconfig --- linux-2.6.3-rc2/arch/sh/Kconfig 2004-02-03 19:45:02.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/Kconfig 2004-02-14 19:31:00.000000000 -0800 @@ -940,61 +940,7 @@ ) solves this problem, or you can get the "mconv2" utility from . - -menu "Watchdog Cards" - -config WATCHDOG - bool "Watchdog Timer Support" - ---help--- - If you say Y here (and to one of the following options) and create a - character special file /dev/watchdog with major number 10 and minor - number 130 using mknod ("man mknod"), you will get a watchdog, i.e.: - subsequently opening the file and then failing to write to it for - longer than 1 minute will result in rebooting the machine. This - could be useful for a networked machine that needs to come back - online as fast as possible after a lock-up. There's both a watchdog - implementation entirely in software (which can sometimes fail to - reboot the machine) and a driver for hardware watchdog boards, which - are more robust and can also keep track of the temperature inside - your computer. For details, read - in the kernel source. - - The watchdog is usually used together with the watchdog daemon - which is available from - . This daemon can - also monitor NFS connections and can reboot the machine when the process - table is full. - - If unsure, say N. - -config WATCHDOG_NOWAYOUT - bool "Disable watchdog shutdown on close" - depends on WATCHDOG - help - The default watchdog behaviour (which you get if you say N here) is - to stop the timer if the process managing it closes the file - /dev/watchdog. It's always remotely possible that this process might - get killed. If you say Y here, the watchdog cannot be stopped once - it has been started. - -config SH_WDT - tristate "SuperH Watchdog" - depends on WATCHDOG - help - This driver adds watchdog support for the integrated watchdog in the - SuperH processors. If you have one of these processors and wish - to have watchdog support enabled, say Y, otherwise say N. - - As a side note, saying Y here will automatically boost HZ to 1000 - so that the timer has a chance to clear the overflow counter. On - slower systems (such as the SH-2 and SH-3) this will likely yield - some performance issues. As such, the WDT should be avoided here - unless it is absolutely necessary. - - To compile this driver as a module, choose M here: the - module will be called shwdt. - -endmenu +source "drivers/char/watchdog/Kconfig" config RTC tristate "Enhanced Real Time Clock Support" diff -urN linux-2.6.3-rc2/arch/sh/boards/hp6xx/hp680/Makefile linux-2.6.3-rc3/arch/sh/boards/hp6xx/hp680/Makefile --- linux-2.6.3-rc2/arch/sh/boards/hp6xx/hp680/Makefile 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/boards/hp6xx/hp680/Makefile 2004-02-14 19:31:00.000000000 -0800 @@ -6,5 +6,5 @@ # unless it's something special (ie not a .c file). # -obj-y := mach.o +obj-y := mach.o setup.o diff -urN linux-2.6.3-rc2/arch/sh/boards/hp6xx/hp680/mach.c linux-2.6.3-rc3/arch/sh/boards/hp6xx/hp680/mach.c --- linux-2.6.3-rc2/arch/sh/boards/hp6xx/hp680/mach.c 2004-02-03 19:44:59.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/boards/hp6xx/hp680/mach.c 2004-02-14 19:31:00.000000000 -0800 @@ -17,6 +17,7 @@ #include #include +#include #include struct sh_machine_vector mv_hp680 __initmv = { diff -urN linux-2.6.3-rc2/arch/sh/boards/hp6xx/hp680/setup.c linux-2.6.3-rc3/arch/sh/boards/hp6xx/hp680/setup.c --- linux-2.6.3-rc2/arch/sh/boards/hp6xx/hp680/setup.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/boards/hp6xx/hp680/setup.c 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,27 @@ +/* + * linux/arch/sh/boards/hp6xx/hp680/setup.c + * + * Copyright (C) 2002 Andriy Skulysh + * + * May be copied or modified under the terms of the GNU General Public + * License. See linux/COPYING for more information. + * + * Setup code for an HP680 (internal peripherials only) + */ + +#include +#include +#include + +const char *get_system_type(void) +{ + return "HP680"; +} + +int __init platform_setup(void) +{ + __set_io_port_base(CONFIG_HD64461_IOBASE - HD64461_STBCR); + + return 0; +} + diff -urN linux-2.6.3-rc2/arch/sh/cchips/hd6446x/hd64461/io.c linux-2.6.3-rc3/arch/sh/cchips/hd6446x/hd64461/io.c --- linux-2.6.3-rc2/arch/sh/cchips/hd6446x/hd64461/io.c 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/cchips/hd6446x/hd64461/io.c 2004-02-14 19:31:00.000000000 -0800 @@ -1,5 +1,5 @@ /* - * $Id: io.c,v 1.4 2003/08/03 03:05:10 lethal Exp $ + * $Id: io.c,v 1.5 2004/02/01 19:46:04 lethal Exp $ * Copyright (C) 2000 YAEGASHI Takeshi * Typical I/O routines for HD64461 system. */ @@ -99,3 +99,44 @@ *(volatile unsigned long*)PORT2ADDR(port) = b; } +void hd64461_insb(unsigned long port, void *buffer, unsigned long count) +{ + volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port); + unsigned char *buf=buffer; + while(count--) *buf++=*addr; +} + +void hd64461_insw(unsigned long port, void *buffer, unsigned long count) +{ + volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port); + unsigned short *buf=buffer; + while(count--) *buf++=*addr; +} + +void hd64461_insl(unsigned long port, void *buffer, unsigned long count) +{ + volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port); + unsigned long *buf=buffer; + while(count--) *buf++=*addr; +} + +void hd64461_outsb(unsigned long port, const void *buffer, unsigned long count) +{ + volatile unsigned char* addr=(volatile unsigned char*)PORT2ADDR(port); + const unsigned char *buf=buffer; + while(count--) *addr=*buf++; +} + +void hd64461_outsw(unsigned long port, const void *buffer, unsigned long count) +{ + volatile unsigned short* addr=(volatile unsigned short*)PORT2ADDR(port); + const unsigned short *buf=buffer; + while(count--) *addr=*buf++; +} + +void hd64461_outsl(unsigned long port, const void *buffer, unsigned long count) +{ + volatile unsigned long* addr=(volatile unsigned long*)PORT2ADDR(port); + const unsigned long *buf=buffer; + while(count--) *addr=*buf++; +} diff -urN linux-2.6.3-rc2/arch/sh/configs/defconfig-hp680 linux-2.6.3-rc3/arch/sh/configs/defconfig-hp680 --- linux-2.6.3-rc2/arch/sh/configs/defconfig-hp680 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/configs/defconfig-hp680 2004-02-14 19:31:00.000000000 -0800 @@ -0,0 +1,428 @@ +# +# Automatically generated make config: don't edit +# +CONFIG_SUPERH=y +CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y + +# +# Code maturity level options +# +CONFIG_EXPERIMENTAL=y +# CONFIG_CLEAN_COMPILE is not set +# CONFIG_STANDALONE is not set +CONFIG_BROKEN=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +# CONFIG_EMBEDDED is not set +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set + +# +# Loadable module support +# +# CONFIG_MODULES is not set + +# +# System type +# +# CONFIG_SH_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SYSTEMH is not set +# CONFIG_SH_STB1_HARP is not set +# CONFIG_SH_STB1_OVERDRIVE is not set +# CONFIG_SH_HP620 is not set +CONFIG_SH_HP680=y +# CONFIG_SH_HP690 is not set +# CONFIG_SH_CQREEK is not set +# CONFIG_SH_DMIDA is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_CAT68701 is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_SH2000 is not set +# CONFIG_SH_ADX is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SECUREEDGE5410 is not set +# CONFIG_SH_UNKNOWN is not set +# CONFIG_CPU_SH2 is not set +CONFIG_CPU_SH3=y +# CONFIG_CPU_SH4 is not set +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7300 is not set +# CONFIG_CPU_SUBTYPE_SH7707 is not set +# CONFIG_CPU_SUBTYPE_SH7708 is not set +CONFIG_CPU_SUBTYPE_SH7709=y +# CONFIG_CPU_SUBTYPE_SH7750 is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +CONFIG_MMU=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x00400000 +CONFIG_MEMORY_SET=y +# CONFIG_MEMORY_OVERRIDE is not set +CONFIG_SH_RTC=y +# CONFIG_SH_DSP is not set +CONFIG_SH_HP600=y +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 +CONFIG_CPU_LITTLE_ENDIAN=y +# CONFIG_PREEMPT is not set +# CONFIG_UBC_WAKEUP is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set +# CONFIG_SMP is not set +CONFIG_SH_PCLK_FREQ=1193182 +# CONFIG_CPU_FREQ is not set +# CONFIG_SH_DMA is not set +CONFIG_HD64461=y +# CONFIG_HD64465 is not set +CONFIG_HD64461_IRQ=36 +CONFIG_HD64461_ENABLER=y + +# +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) +# +# CONFIG_PCI is not set +# CONFIG_HOTPLUG is not set + +# +# Executable file formats +# +CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_FLAT is not set +# CONFIG_BINFMT_MISC is not set + +# +# Generic Driver Options +# + +# +# Memory Technology Devices (MTD) +# +# CONFIG_MTD is not set + +# +# Parallel port support +# +# CONFIG_PARPORT is not set + +# +# Block devices +# +# CONFIG_BLK_DEV_FD is not set +# CONFIG_BLK_DEV_LOOP is not set +CONFIG_BLK_DEV_RAM=y +CONFIG_BLK_DEV_RAM_SIZE=4096 +CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set + +# +# ATA/ATAPI/MFM/RLL support +# +CONFIG_IDE=y +CONFIG_BLK_DEV_IDE=y + +# +# Please see Documentation/ide.txt for help/info on IDE drives +# +CONFIG_BLK_DEV_IDEDISK=y +# CONFIG_IDEDISK_MULTI_MODE is not set +# CONFIG_IDEDISK_STROKE is not set +# CONFIG_BLK_DEV_IDECD is not set +# CONFIG_BLK_DEV_IDETAPE is not set +# CONFIG_BLK_DEV_IDEFLOPPY is not set +# CONFIG_IDE_TASK_IOCTL is not set +# CONFIG_IDE_TASKFILE_IO is not set + +# +# IDE chipset support/bugfixes +# +# CONFIG_BLK_DEV_IDEDMA is not set +# CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set + +# +# SCSI device support +# +# CONFIG_SCSI is not set + +# +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# IEEE 1394 (FireWire) support (EXPERIMENTAL) +# +# CONFIG_IEEE1394 is not set + +# +# Networking support +# +# CONFIG_NET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +# CONFIG_SERIO_I8042 is not set +# CONFIG_SERIO_SERPORT is not set +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +# CONFIG_INPUT_KEYBOARD is not set +# CONFIG_INPUT_MOUSE is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# +# Character devices +# +CONFIG_VT=y +CONFIG_VT_CONSOLE=y +CONFIG_HW_CONSOLE=y +# CONFIG_SERIAL is not set +CONFIG_SH_SCI=y +# CONFIG_SERIAL_CONSOLE is not set + +# +# Unix 98 PTY support +# +# CONFIG_UNIX98_PTYS is not set +# CONFIG_PSMOUSE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SH_SCI is not set + +# +# I2C support +# +# CONFIG_I2C is not set + +# +# I2C Algorithms +# + +# +# I2C Hardware Bus support +# + +# +# I2C Hardware Sensors Chip support +# +# CONFIG_I2C_SENSOR is not set + +# +# File systems +# +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set +# CONFIG_QUOTA is not set +# CONFIG_AUTOFS_FS is not set +# CONFIG_AUTOFS4_FS is not set + +# +# CD-ROM/DVD Filesystems +# +# CONFIG_ISO9660_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set +# CONFIG_NTFS_FS is not set + +# +# Pseudo filesystems +# +CONFIG_PROC_FS=y +CONFIG_PROC_KCORE=y +CONFIG_DEVFS_FS=y +CONFIG_DEVFS_MOUNT=y +# CONFIG_DEVFS_DEBUG is not set +# CONFIG_TMPFS is not set +# CONFIG_HUGETLBFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_ADFS_FS is not set +# CONFIG_AFFS_FS is not set +# CONFIG_HFS_FS is not set +# CONFIG_BEFS_FS is not set +# CONFIG_BFS_FS is not set +# CONFIG_EFS_FS is not set +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set +# CONFIG_QNX4FS_FS is not set +# CONFIG_SYSV_FS is not set +# CONFIG_UFS_FS is not set + +# +# Partition Types +# +# CONFIG_PARTITION_ADVANCED is not set +CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# +# CONFIG_NLS is not set + +# +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# + +# +# Graphics support +# +CONFIG_FB=y +# CONFIG_FB_E1355 is not set +CONFIG_FB_HIT=y +# CONFIG_FB_VIRTUAL is not set + +# +# Console display driver support +# +# CONFIG_VGA_CONSOLE is not set +# CONFIG_MDA_CONSOLE is not set +CONFIG_DUMMY_CONSOLE=y +CONFIG_FRAMEBUFFER_CONSOLE=y +CONFIG_PCI_CONSOLE=y +CONFIG_FONTS=y +# CONFIG_FONT_8x8 is not set +# CONFIG_FONT_8x16 is not set +# CONFIG_FONT_6x11 is not set +CONFIG_FONT_PEARL_8x8=y +# CONFIG_FONT_ACORN_8x8 is not set +# CONFIG_FONT_MINI_4x6 is not set +# CONFIG_FONT_SUN8x16 is not set +# CONFIG_FONT_SUN12x22 is not set + +# +# Logo configuration +# +# CONFIG_LOGO is not set + +# +# Sound +# +# CONFIG_SOUND is not set + +# +# USB support +# +# CONFIG_USB_GADGET is not set + +# +# Profiling support +# +# CONFIG_PROFILING is not set + +# +# Kernel hacking +# +# CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set +# CONFIG_SH_STANDARD_BIOS is not set +# CONFIG_KGDB is not set +# CONFIG_FRAME_POINTER is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -urN linux-2.6.3-rc2/arch/sh/defconfig linux-2.6.3-rc3/arch/sh/defconfig --- linux-2.6.3-rc2/arch/sh/defconfig 2004-02-03 19:43:55.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/defconfig 2004-02-14 19:31:00.000000000 -0800 @@ -3,11 +3,33 @@ # CONFIG_SUPERH=y CONFIG_UID16=y +CONFIG_RWSEM_GENERIC_SPINLOCK=y # # Code maturity level options # # CONFIG_EXPERIMENTAL is not set +CONFIG_CLEAN_COMPILE=y +CONFIG_STANDALONE=y +CONFIG_BROKEN_ON_SMP=y + +# +# General setup +# +CONFIG_SWAP=y +# CONFIG_SYSVIPC is not set +# CONFIG_BSD_PROCESS_ACCT is not set +# CONFIG_SYSCTL is not set +CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_IKCONFIG is not set +CONFIG_EMBEDDED=y +CONFIG_KALLSYMS=y +CONFIG_FUTEX=y +CONFIG_EPOLL=y +CONFIG_IOSCHED_NOOP=y +CONFIG_IOSCHED_AS=y +CONFIG_IOSCHED_DEADLINE=y +# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set # # Loadable module support @@ -15,44 +37,78 @@ # CONFIG_MODULES is not set # -# Processor type and features +# System type # # CONFIG_SH_SOLUTION_ENGINE is not set -# CONFIG_SH_OVERDRIVE is not set -# CONFIG_SH_HP600 is not set -# CONFIG_SH_UNKNOWN is not set +# CONFIG_SH_7751_SOLUTION_ENGINE is not set +# CONFIG_SH_7751_SYSTEMH is not set +# CONFIG_SH_STB1_HARP is not set +# CONFIG_SH_STB1_OVERDRIVE is not set +# CONFIG_SH_HP620 is not set +# CONFIG_SH_HP680 is not set +# CONFIG_SH_HP690 is not set +# CONFIG_SH_CQREEK is not set +# CONFIG_SH_DMIDA is not set +# CONFIG_SH_EC3104 is not set +# CONFIG_SH_SATURN is not set +# CONFIG_SH_DREAMCAST is not set +# CONFIG_SH_CAT68701 is not set +# CONFIG_SH_BIGSUR is not set +# CONFIG_SH_SH2000 is not set +# CONFIG_SH_ADX is not set +# CONFIG_SH_MPC1211 is not set +# CONFIG_SH_SECUREEDGE5410 is not set +CONFIG_SH_UNKNOWN=y +# CONFIG_CPU_SH2 is not set +CONFIG_CPU_SH3=y +# CONFIG_CPU_SH4 is not set +# CONFIG_CPU_SUBTYPE_SH7604 is not set +# CONFIG_CPU_SUBTYPE_SH7300 is not set # CONFIG_CPU_SUBTYPE_SH7707 is not set CONFIG_CPU_SUBTYPE_SH7708=y # CONFIG_CPU_SUBTYPE_SH7709 is not set # CONFIG_CPU_SUBTYPE_SH7750 is not set -CONFIG_CPU_SH3=y -# CONFIG_CPU_SH4 is not set +# CONFIG_CPU_SUBTYPE_SH7751 is not set +# CONFIG_CPU_SUBTYPE_SH7760 is not set +# CONFIG_CPU_SUBTYPE_ST40STB1 is not set +CONFIG_MMU=y +# CONFIG_CMDLINE_BOOL is not set +CONFIG_MEMORY_START=0x0c000000 +CONFIG_MEMORY_SIZE=0x00400000 +# CONFIG_MEMORY_OVERRIDE is not set +CONFIG_CF_ENABLER=y +# CONFIG_CF_AREA5 is not set +CONFIG_CF_AREA6=y +CONFIG_CF_BASE_ADDR=0xb8000000 +CONFIG_SH_RTC=y +CONFIG_SH_DSP=y +CONFIG_ZERO_PAGE_OFFSET=0x00001000 +CONFIG_BOOT_LINK_OFFSET=0x00800000 CONFIG_CPU_LITTLE_ENDIAN=y -CONFIG_MEMORY_START=0c000000 +# CONFIG_UBC_WAKEUP is not set +# CONFIG_SH_WRITETHROUGH is not set +# CONFIG_SH_OCRAM is not set +# CONFIG_SMP is not set +CONFIG_SH_PCLK_FREQ=1193182 +# CONFIG_CPU_FREQ is not set +# CONFIG_SH_DMA is not set # -# General setup +# Bus options (PCI, PCMCIA, EISA, MCA, ISA) # -# CONFIG_ISA is not set -# CONFIG_SBUS is not set -# CONFIG_NET is not set -CONFIG_CF_ENABLER=y -# CONFIG_HD64461 is not set # CONFIG_PCI is not set # CONFIG_HOTPLUG is not set -# CONFIG_PCMCIA is not set -# CONFIG_SYSVIPC is not set -# CONFIG_BSD_PROCESS_ACCT is not set -# CONFIG_SYSCTL is not set -CONFIG_KCORE_ELF=y -# CONFIG_KCORE_AOUT is not set + +# +# Executable file formats +# CONFIG_BINFMT_ELF=y +# CONFIG_BINFMT_FLAT is not set # CONFIG_BINFMT_MISC is not set # -# Parallel port support +# Generic Driver Options # -# CONFIG_PARPORT is not set # # Memory Technology Devices (MTD) @@ -60,63 +116,117 @@ # CONFIG_MTD is not set # +# Parallel port support +# +# CONFIG_PARPORT is not set + +# # Block devices # # CONFIG_BLK_DEV_FD is not set -# CONFIG_BLK_DEV_XD is not set -# CONFIG_PARIDE is not set -# CONFIG_BLK_CPQ_DA is not set -# CONFIG_BLK_DEV_DAC960 is not set # CONFIG_BLK_DEV_LOOP is not set -# CONFIG_BLK_DEV_NBD is not set -# CONFIG_BLK_DEV_LVM is not set -# CONFIG_BLK_DEV_MD is not set -# CONFIG_MD_LINEAR is not set -# CONFIG_MD_RAID0 is not set -# CONFIG_MD_RAID1 is not set -# CONFIG_MD_RAID5 is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=4096 CONFIG_BLK_DEV_INITRD=y +# CONFIG_LBD is not set # -# ATA/IDE/MFM/RLL support +# ATA/ATAPI/MFM/RLL support # CONFIG_IDE=y - -# -# IDE, ATA and ATAPI Block devices -# CONFIG_BLK_DEV_IDE=y # # Please see Documentation/ide.txt for help/info on IDE drives # -# CONFIG_BLK_DEV_HD_IDE is not set -# CONFIG_BLK_DEV_HD is not set CONFIG_BLK_DEV_IDEDISK=y # CONFIG_IDEDISK_MULTI_MODE is not set -# CONFIG_BLK_DEV_IDECS is not set +# CONFIG_IDEDISK_STROKE is not set # CONFIG_BLK_DEV_IDECD is not set -# CONFIG_BLK_DEV_IDETAPE is not set # CONFIG_BLK_DEV_IDEFLOPPY is not set -# CONFIG_BLK_DEV_IDESCSI is not set +# CONFIG_IDE_TASK_IOCTL is not set # # IDE chipset support/bugfixes # -# CONFIG_BLK_DEV_CMD640 is not set -# CONFIG_BLK_DEV_CMD640_ENHANCED is not set -# CONFIG_BLK_DEV_ISAPNP is not set -# CONFIG_IDE_CHIPSETS is not set +CONFIG_IDE_GENERIC=y +# CONFIG_BLK_DEV_IDEDMA is not set # CONFIG_IDEDMA_AUTO is not set +# CONFIG_DMA_NONPCI is not set +# CONFIG_BLK_DEV_HD is not set # -# SCSI support +# SCSI device support # # CONFIG_SCSI is not set # +# Multi-device support (RAID and LVM) +# +# CONFIG_MD is not set + +# +# Networking support +# +# CONFIG_NET is not set + +# +# Amateur Radio support +# +# CONFIG_HAMRADIO is not set + +# +# ISDN subsystem +# + +# +# Telephony Support +# +# CONFIG_PHONE is not set + +# +# Input device support +# +CONFIG_INPUT=y + +# +# Userland interfaces +# +CONFIG_INPUT_MOUSEDEV=y +CONFIG_INPUT_MOUSEDEV_PSAUX=y +CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 +CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 +# CONFIG_INPUT_JOYDEV is not set +# CONFIG_INPUT_TSDEV is not set +# CONFIG_INPUT_EVDEV is not set +# CONFIG_INPUT_EVBUG is not set + +# +# Input I/O drivers +# +# CONFIG_GAMEPORT is not set +CONFIG_SOUND_GAMEPORT=y +CONFIG_SERIO=y +CONFIG_SERIO_I8042=y +CONFIG_SERIO_SERPORT=y +# CONFIG_SERIO_CT82C710 is not set + +# +# Input Device Drivers +# +CONFIG_INPUT_KEYBOARD=y +CONFIG_KEYBOARD_ATKBD=y +# CONFIG_KEYBOARD_SUNKBD is not set +# CONFIG_KEYBOARD_XTKBD is not set +# CONFIG_KEYBOARD_NEWTON is not set +CONFIG_INPUT_MOUSE=y +CONFIG_MOUSE_PS2=y +# CONFIG_MOUSE_SERIAL is not set +# CONFIG_INPUT_JOYSTICK is not set +# CONFIG_INPUT_TOUCHSCREEN is not set +# CONFIG_INPUT_MISC is not set + +# # Character devices # # CONFIG_VT is not set @@ -125,69 +235,139 @@ CONFIG_SERIAL_CONSOLE=y # -# Unix 98 PTY support +# Unix98 PTY support # # CONFIG_UNIX98_PTYS is not set -# CONFIG_HEARTBEAT is not set +# CONFIG_PSMOUSE is not set + +# +# Watchdog Cards +# +# CONFIG_WATCHDOG is not set +# CONFIG_RTC is not set + +# +# Serial drivers +# +# CONFIG_SERIAL_8250 is not set + +# +# Non-8250 serial port support +# +# CONFIG_SERIAL_SH_SCI is not set + +# +# I2C support +# +# CONFIG_I2C is not set # # File systems # +CONFIG_EXT2_FS=y +# CONFIG_EXT2_FS_XATTR is not set +# CONFIG_EXT3_FS is not set +# CONFIG_JBD is not set +# CONFIG_REISERFS_FS is not set +# CONFIG_JFS_FS is not set +# CONFIG_XFS_FS is not set +# CONFIG_MINIX_FS is not set +# CONFIG_ROMFS_FS is not set # CONFIG_QUOTA is not set # CONFIG_AUTOFS_FS is not set # CONFIG_AUTOFS4_FS is not set -# CONFIG_ADFS_FS is not set -# CONFIG_ADFS_FS_RW is not set -# CONFIG_AFFS_FS is not set -# CONFIG_HFS_FS is not set -# CONFIG_BFS_FS is not set -# CONFIG_FAT_FS is not set -# CONFIG_MSDOS_FS is not set -# CONFIG_UMSDOS_FS is not set -# CONFIG_VFAT_FS is not set -# CONFIG_EFS_FS is not set -# CONFIG_JFFS_FS is not set -# CONFIG_CRAMFS is not set -# CONFIG_RAMFS is not set + +# +# CD-ROM/DVD Filesystems +# # CONFIG_ISO9660_FS is not set -# CONFIG_JOLIET is not set -# CONFIG_MINIX_FS is not set +# CONFIG_UDF_FS is not set + +# +# DOS/FAT/NT Filesystems +# +# CONFIG_FAT_FS is not set # CONFIG_NTFS_FS is not set -# CONFIG_NTFS_DEBUG is not set -# CONFIG_NTFS_RW is not set -# CONFIG_HPFS_FS is not set + +# +# Pseudo filesystems +# CONFIG_PROC_FS=y -# CONFIG_DEVFS_FS is not set -# CONFIG_DEVFS_MOUNT is not set -# CONFIG_DEVFS_DEBUG is not set -# CONFIG_DEVPTS_FS is not set +CONFIG_PROC_KCORE=y +# CONFIG_TMPFS is not set +# CONFIG_HUGETLB_PAGE is not set +CONFIG_RAMFS=y + +# +# Miscellaneous filesystems +# +# CONFIG_CRAMFS is not set +# CONFIG_VXFS_FS is not set +# CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set -# CONFIG_QNX4FS_RW is not set -# CONFIG_ROMFS_FS is not set -CONFIG_EXT2_FS=y # CONFIG_SYSV_FS is not set -# CONFIG_SYSV_FS_WRITE is not set -# CONFIG_UDF_FS is not set -# CONFIG_UDF_RW is not set # CONFIG_UFS_FS is not set -# CONFIG_UFS_FS_WRITE is not set -# CONFIG_NCPFS_NLS is not set # # Partition Types # # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y + +# +# Native Language Support +# # CONFIG_NLS is not set # +# Multimedia devices +# +# CONFIG_VIDEO_DEV is not set + +# +# Digital Video Broadcasting Devices +# + +# +# Graphics support +# +# CONFIG_FB is not set + +# # Sound # # CONFIG_SOUND is not set # +# USB support +# + +# +# USB Gadget Support +# +# CONFIG_USB_GADGET is not set + +# # Kernel hacking # # CONFIG_MAGIC_SYSRQ is not set +# CONFIG_DEBUG_SPINLOCK is not set CONFIG_SH_STANDARD_BIOS=y CONFIG_SH_EARLY_PRINTK=y +# CONFIG_KGDB is not set +# CONFIG_FRAME_POINTER is not set + +# +# Security options +# +# CONFIG_SECURITY is not set + +# +# Cryptographic options +# +# CONFIG_CRYPTO is not set + +# +# Library routines +# +# CONFIG_CRC32 is not set diff -urN linux-2.6.3-rc2/arch/sh/kernel/cpu/init.c linux-2.6.3-rc3/arch/sh/kernel/cpu/init.c --- linux-2.6.3-rc2/arch/sh/kernel/cpu/init.c 2004-02-03 19:45:13.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/kernel/cpu/init.c 2004-02-14 19:31:00.000000000 -0800 @@ -180,7 +180,7 @@ if (fpu_disabled) { printk("FPU Disabled\n"); cpu_data->flags &= ~CPU_HAS_FPU; - release_fpu(); + disable_fpu(); } /* FPU initialization */ diff -urN linux-2.6.3-rc2/arch/sh/kernel/cpu/rtc.c linux-2.6.3-rc3/arch/sh/kernel/cpu/rtc.c --- linux-2.6.3-rc2/arch/sh/kernel/cpu/rtc.c 2004-02-03 19:44:03.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/kernel/cpu/rtc.c 2004-02-14 19:31:00.000000000 -0800 @@ -23,10 +23,12 @@ void sh_rtc_gettimeofday(struct timespec *ts) { - unsigned int sec128, sec, min, hr, wk, day, mon, yr, yr100; + unsigned int sec128, sec, sec2, min, hr, wk, day, mon, yr, yr100, cf_bit; + unsigned long flags; again: do { + local_irq_save(flags); ctrl_outb(0, RCR1); /* Clear CF-bit */ sec128 = ctrl_inb(R64CNT); sec = ctrl_inb(RSECCNT); @@ -43,15 +45,10 @@ yr = ctrl_inb(RYRCNT); yr100 = (yr == 0x99) ? 0x19 : 0x20; #endif - } while ((ctrl_inb(RCR1) & RCR1_CF) != 0); - -#if RTC_BIT_INVERTED != 0 - /* Work around to avoid reading incorrect value. */ - if (sec128 == RTC_BIT_INVERTED) { - schedule_timeout(1); - goto again; - } -#endif + sec2 = ctrl_inb(R64CNT); + cf_bit = ctrl_inb(RCR1) & RCR1_CF; + local_irq_restore(flags); + } while (cf_bit != 0 || ((sec128 ^ sec2) & RTC_BIT_INVERTED) != 0); BCD_TO_BIN(yr100); BCD_TO_BIN(yr); @@ -65,6 +62,7 @@ hr > 23 || min > 59 || sec > 59) { printk(KERN_ERR "SH RTC: invalid value, resetting to 1 Jan 2000\n"); + local_irq_save(flags); ctrl_outb(RCR2_RESET, RCR2); /* Reset & Stop */ ctrl_outb(0, RSECCNT); ctrl_outb(0, RMINCNT); @@ -99,7 +97,9 @@ { int retval = 0; int real_seconds, real_minutes, cmos_minutes; + unsigned long flags; + local_irq_save(flags); ctrl_outb(RCR2_RESET, RCR2); /* Reset pre-scaler & stop RTC */ cmos_minutes = ctrl_inb(RMINCNT); @@ -130,6 +130,7 @@ } ctrl_outb(RCR2_RTCEN|RCR2_START, RCR2); /* Start RTC */ + local_irq_restore(flags); return retval; } diff -urN linux-2.6.3-rc2/arch/sh/kernel/cpu/sh4/fpu.c linux-2.6.3-rc3/arch/sh/kernel/cpu/sh4/fpu.c --- linux-2.6.3-rc2/arch/sh/kernel/cpu/sh4/fpu.c 2004-02-03 19:43:32.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/kernel/cpu/sh4/fpu.c 2004-02-14 19:31:00.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: fpu.c,v 1.3 2003/09/23 23:15:44 lethal Exp $ +/* $Id: fpu.c,v 1.4 2004/01/13 05:52:11 kkojima Exp $ * * linux/arch/sh/kernel/fpu.c * @@ -31,11 +31,15 @@ * Assume called with FPU enabled (SR.FD=0). */ void -save_fpu(struct task_struct *tsk) +save_fpu(struct task_struct *tsk, struct pt_regs *regs) { + unsigned long dummy; + + clear_tsk_thread_flag(tsk, TIF_USEDFPU); + enable_fpu(); asm volatile("sts.l fpul, @-%0\n\t" "sts.l fpscr, @-%0\n\t" - "lds %1, fpscr\n\t" + "lds %2, fpscr\n\t" "frchg\n\t" "fmov.s fr15, @-%0\n\t" "fmov.s fr14, @-%0\n\t" @@ -70,21 +74,24 @@ "fmov.s fr2, @-%0\n\t" "fmov.s fr1, @-%0\n\t" "fmov.s fr0, @-%0\n\t" - "lds %2, fpscr\n\t" - : /* no output */ - : "r" ((char *)(&tsk->thread.fpu.hard.status)), + "lds %3, fpscr\n\t" + : "=r" (dummy) + : "0" ((char *)(&tsk->thread.fpu.hard.status)), "r" (FPSCR_RCHG), "r" (FPSCR_INIT) : "memory"); - clear_tsk_thread_flag(tsk, TIF_USEDFPU); - release_fpu(); + disable_fpu(); + release_fpu(regs); } static void restore_fpu(struct task_struct *tsk) { - asm volatile("lds %1, fpscr\n\t" + unsigned long dummy; + + enable_fpu(); + asm volatile("lds %2, fpscr\n\t" "fmov.s @%0+, fr0\n\t" "fmov.s @%0+, fr1\n\t" "fmov.s @%0+, fr2\n\t" @@ -121,9 +128,10 @@ "frchg\n\t" "lds.l @%0+, fpscr\n\t" "lds.l @%0+, fpul\n\t" - : /* no output */ - : "r" (&tsk->thread.fpu), "r" (FPSCR_RCHG) + : "=r" (dummy) + : "0" (&tsk->thread.fpu), "r" (FPSCR_RCHG) : "memory"); + disable_fpu(); } /* @@ -135,6 +143,7 @@ static void fpu_init(void) { + enable_fpu(); asm volatile("lds %0, fpul\n\t" "lds %1, fpscr\n\t" "fsts fpul, fr0\n\t" @@ -174,6 +183,7 @@ "lds %2, fpscr\n\t" : /* no output */ : "r" (0), "r" (FPSCR_RCHG), "r" (FPSCR_INIT)); + disable_fpu(); } /** @@ -262,14 +272,14 @@ if ((finsn & 0xf1ff) == 0xf0ad) { /* fcnvsd */ struct task_struct *tsk = current; - save_fpu(tsk); + save_fpu(tsk, regs); if ((tsk->thread.fpu.hard.fpscr & (1 << 17))) { /* FPU error */ denormal_to_double (&tsk->thread.fpu.hard, (finsn >> 8) & 0xf); tsk->thread.fpu.hard.fpscr &= ~(FPSCR_CAUSE_MASK | FPSCR_FLAG_MASK); - grab_fpu(); + grab_fpu(regs); restore_fpu(tsk); set_tsk_thread_flag(tsk, TIF_USEDFPU); } else { @@ -295,7 +305,7 @@ return; regs.pc += 2; - save_fpu(tsk); + save_fpu(tsk, ®s); tsk->thread.trap_no = 11; tsk->thread.error_code = 0; force_sig(SIGFPE, tsk); @@ -307,7 +317,7 @@ { struct task_struct *tsk = current; - grab_fpu(); + grab_fpu(®s); if (!user_mode(®s)) { printk(KERN_ERR "BUG: FPU is used in kernel mode.\n"); return; diff -urN linux-2.6.3-rc2/arch/sh/kernel/entry.S linux-2.6.3-rc3/arch/sh/kernel/entry.S --- linux-2.6.3-rc2/arch/sh/kernel/entry.S 2004-02-03 19:43:42.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/kernel/entry.S 2004-02-14 19:31:00.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: entry.S,v 1.33 2003/11/22 15:39:51 lethal Exp $ +/* $Id: entry.S,v 1.34 2004/01/13 05:52:11 kkojima Exp $ * * linux/arch/sh/entry.S * @@ -351,18 +351,22 @@ GET_THREAD_INFO(r8) #ifdef CONFIG_PREEMPT + bra resume_userspace + nop ENTRY(resume_kernel) mov.l @(TI_PRE_COUNT,r8), r0 ! current_thread_info->preempt_count tst r0, r0 - bf restore_all + bf noresched need_resched: mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags tst #_TIF_NEED_RESCHED, r0 ! need_resched set? - bt restore_all + bt noresched - stc sr, r0 ! interrupts disabled? - tst #0xf0, r0 - bf restore_all + mov #OFF_SR, r0 + mov.l @(r0,r15), r0 ! get status register + and #0xf0, r0 ! interrupts off (exception path)? + cmp/eq #0xf0, r0 + bt noresched mov.l 1f, r0 mov.l r0, @(TI_PRE_COUNT,r8) @@ -375,7 +379,10 @@ mov.l r0, @(TI_PRE_COUNT,r8) CLI() - bra need_resched + bra need_resched + nop +noresched: + bra restore_all nop .align 2 @@ -525,7 +532,7 @@ ! Is the trap argument >= 0x20? (TRA will be >= 0x80) mov #0x7f, r9 cmp/hi r9, r8 - bt/s debug_trap + bt/s 0f mov #OFF_TRA, r9 add r15, r9 ! @@ -543,6 +550,10 @@ bra resume_userspace mov.l r0, @(OFF_R0,r15) ! Return value ! +0: + bra debug_trap + nop + ! good_system_call: ! Good syscall number mov.l @(TI_FLAGS,r8), r8 mov #_TIF_SYSCALL_TRACE, r10 @@ -632,12 +643,8 @@ ! ! Calculate new SR value mov k3, k2 ! original SR value - mov.l 8f, k1 - stc sr, k0 - and k1, k0 ! Get current FD-bit mov.l 9f, k1 and k1, k2 ! Mask orignal SR value - or k0, k2 ! Inherit current FD-bit ! mov k3, k0 ! Calculate IMASK-bits shlr2 k0 @@ -668,8 +675,7 @@ 4: .long do_syscall_trace 5: .long 0x00001000 ! DSP 7: .long 0x30000000 -8: .long 0x00008000 ! FD -9: .long 0xffff7f0f ! ~(IMASK+FD) +9: __INV_IMASK: .long 0xffffff0f ! ~(IMASK) @@ -838,7 +844,7 @@ .align 2 1: .long 0x00001000 ! DSP=1 -2: .long 0x000000f0 ! FD=0, IMASK=15 +2: .long 0x000080f0 ! FD=1, IMASK=15 3: .long 0xcfffffff ! RB=0, BL=0 4: .long exception_handling_table diff -urN linux-2.6.3-rc2/arch/sh/kernel/irq.c linux-2.6.3-rc3/arch/sh/kernel/irq.c --- linux-2.6.3-rc2/arch/sh/kernel/irq.c 2004-02-03 19:43:42.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/kernel/irq.c 2004-02-14 19:31:00.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: irq.c,v 1.19 2004/01/10 01:25:32 lethal Exp $ +/* $Id: irq.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $ * * linux/arch/sh/kernel/irq.c * @@ -318,6 +318,16 @@ irq_enter(); +#ifdef CONFIG_PREEMPT + /* + * At this point we're now about to actually call handlers, + * and interrupts might get reenabled during them... bump + * preempt_count to prevent any preemption while the handler + * called here is pending... + */ + preempt_disable(); +#endif + /* Get IRQ number */ asm volatile("stc r2_bank, %0\n\t" "shlr2 %0\n\t" @@ -393,6 +403,15 @@ irq_exit(); +#ifdef CONFIG_PREEMPT + /* + * We're done with the handlers, interrupts should be + * currently disabled; decrement preempt_count now so + * as we return preemption may be allowed... + */ + preempt_enable_no_resched(); +#endif + return 1; } diff -urN linux-2.6.3-rc2/arch/sh/kernel/process.c linux-2.6.3-rc3/arch/sh/kernel/process.c --- linux-2.6.3-rc2/arch/sh/kernel/process.c 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/kernel/process.c 2004-02-14 19:31:00.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: process.c,v 1.24 2003/11/28 23:05:43 kkojima Exp $ +/* $Id: process.c,v 1.25 2004/01/13 05:52:11 kkojima Exp $ * * linux/arch/sh/kernel/process.c * @@ -174,9 +174,13 @@ { #if defined(CONFIG_CPU_SH4) struct task_struct *tsk = current; + struct pt_regs *regs = (struct pt_regs *) + ((unsigned long)tsk->thread_info + + THREAD_SIZE - sizeof(struct pt_regs) + - sizeof(unsigned long)); /* Forget lazy FPU state */ - clear_fpu(tsk); + clear_fpu(tsk, regs); tsk->used_math = 0; #endif } @@ -196,7 +200,7 @@ fpvalid = tsk->used_math; if (fpvalid) { - unlazy_fpu(tsk); + unlazy_fpu(tsk, regs); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } #endif @@ -212,7 +216,8 @@ struct pt_regs ptregs; ptregs = *(struct pt_regs *) - ((unsigned long)tsk->thread_info+THREAD_SIZE - sizeof(ptregs) + ((unsigned long)tsk->thread_info + THREAD_SIZE + - sizeof(struct pt_regs) #ifdef CONFIG_SH_DSP - sizeof(struct pt_dspregs) #endif @@ -230,7 +235,11 @@ #if defined(CONFIG_CPU_SH4) fpvalid = tsk->used_math; if (fpvalid) { - unlazy_fpu(tsk); + struct pt_regs *regs = (struct pt_regs *) + ((unsigned long)tsk->thread_info + + THREAD_SIZE - sizeof(struct pt_regs) + - sizeof(unsigned long)); + unlazy_fpu(tsk, regs); memcpy(fpu, &tsk->thread.fpu.hard, sizeof(*fpu)); } #endif @@ -257,13 +266,12 @@ if (user_mode(regs)) { childregs->regs[15] = usp; } else { - childregs->regs[15] = (unsigned long)p->thread_info+THREAD_SIZE; + childregs->regs[15] = (unsigned long)p->thread_info + THREAD_SIZE; } if (clone_flags & CLONE_SETTLS) { childregs->gbr = childregs->regs[0]; } childregs->regs[0] = 0; /* Set return value for child */ - childregs->sr |= SR_FD; /* Invalidate FPU flag */ p->set_child_tid = p->clear_child_tid = NULL; p->thread.sp = (unsigned long) childregs; @@ -275,7 +283,7 @@ { struct task_struct *tsk = current; - unlazy_fpu(tsk); + unlazy_fpu(tsk, regs); p->thread.fpu = tsk->thread.fpu; p->used_math = tsk->used_math; clear_ti_thread_flag(p->thread_info, TIF_USEDFPU); @@ -332,8 +340,39 @@ struct task_struct *__switch_to(struct task_struct *prev, struct task_struct *next) { #if defined(CONFIG_CPU_SH4) - unlazy_fpu(prev); + struct pt_regs *regs = (struct pt_regs *) + ((unsigned long)prev->thread_info + + THREAD_SIZE - sizeof(struct pt_regs) + - sizeof(unsigned long)); + unlazy_fpu(prev, regs); #endif + +#ifdef CONFIG_PREEMPT + { + unsigned long flags; + struct pt_regs *regs; + + local_irq_save(flags); + regs = (struct pt_regs *) + ((unsigned long)prev->thread_info + + THREAD_SIZE - sizeof(struct pt_regs) +#ifdef CONFIG_SH_DSP + - sizeof(struct pt_dspregs) +#endif + - sizeof(unsigned long)); + if (user_mode(regs) && regs->regs[15] >= 0xc0000000) { + int offset = (int)regs->regs[15]; + + /* Reset stack pointer: clear critical region mark */ + regs->regs[15] = regs->regs[1]; + if (regs->pc < regs->regs[0]) + /* Go to rewind point */ + regs->pc = regs->regs[0] + offset; + } + local_irq_restore(flags); + } +#endif + /* * Restore the kernel mode register * k7 (r7_bank1) diff -urN linux-2.6.3-rc2/arch/sh/kernel/signal.c linux-2.6.3-rc3/arch/sh/kernel/signal.c --- linux-2.6.3-rc2/arch/sh/kernel/signal.c 2004-02-03 19:45:13.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/kernel/signal.c 2004-02-14 19:31:00.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: signal.c,v 1.19 2003/10/13 07:21:19 lethal Exp $ +/* $Id: signal.c,v 1.20 2004/01/13 05:52:11 kkojima Exp $ * * linux/arch/sh/kernel/signal.c * @@ -168,7 +168,8 @@ sizeof(long)*(16*2+2)); } -static inline int save_sigcontext_fpu(struct sigcontext __user *sc) +static inline int save_sigcontext_fpu(struct sigcontext __user *sc, + struct pt_regs *regs) { struct task_struct *tsk = current; @@ -187,7 +188,7 @@ */ tsk->used_math = 0; - unlazy_fpu(tsk); + unlazy_fpu(tsk, regs); return __copy_to_user(&sc->sc_fpregs[0], &tsk->thread.fpu.hard, sizeof(long)*(16*2+2)); } @@ -218,7 +219,7 @@ struct task_struct *tsk = current; regs->sr |= SR_FD; /* Release FPU */ - clear_fpu(tsk); + clear_fpu(tsk, regs); tsk->used_math = 0; __get_user (owned_fp, &sc->sc_ownedfp); if (owned_fp) @@ -326,7 +327,7 @@ #undef COPY #ifdef CONFIG_CPU_SH4 - err |= save_sigcontext_fpu(sc); + err |= save_sigcontext_fpu(sc, regs); #endif /* non-iBCS2 extensions.. */ @@ -521,9 +522,13 @@ case -ERESTARTNOINTR: regs->pc -= 2; } -#ifndef CONFIG_PREEMPT } else { /* gUSA handling */ +#ifdef CONFIG_PREEMPT + unsigned long flags; + + local_irq_save(flags); +#endif if (regs->regs[15] >= 0xc0000000) { int offset = (int)regs->regs[15]; @@ -533,6 +538,8 @@ /* Go to rewind point #1 */ regs->pc = regs->regs[0] + offset - 2; } +#ifdef CONFIG_PREEMPT + local_irq_restore(flags); #endif } diff -urN linux-2.6.3-rc2/arch/sh/mm/cache-sh3.c linux-2.6.3-rc3/arch/sh/mm/cache-sh3.c --- linux-2.6.3-rc2/arch/sh/mm/cache-sh3.c 2004-02-03 19:43:07.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/mm/cache-sh3.c 2004-02-14 19:31:00.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: cache-sh3.c,v 1.7 2003/08/28 16:16:09 lethal Exp $ +/* $Id: cache-sh3.c,v 1.8 2004/02/01 16:26:27 lethal Exp $ * * linux/arch/sh/mm/cache-sh3.c * @@ -21,8 +21,7 @@ #include #include -static int __init -detect_cpu_and_cache_system(void) +int __init detect_cpu_and_cache_system(void) { unsigned long addr0, addr1, data0, data1, data2, data3; diff -urN linux-2.6.3-rc2/arch/sh/mm/fault.c linux-2.6.3-rc3/arch/sh/mm/fault.c --- linux-2.6.3-rc2/arch/sh/mm/fault.c 2004-02-03 19:43:32.000000000 -0800 +++ linux-2.6.3-rc3/arch/sh/mm/fault.c 2004-02-14 19:31:00.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: fault.c,v 1.13 2003/08/11 11:44:50 lethal Exp $ +/* $Id: fault.c,v 1.14 2004/01/13 05:52:11 kkojima Exp $ * * linux/arch/sh/mm/fault.c * Copyright (C) 1999 Niibe Yutaka @@ -242,7 +242,12 @@ * So, we need to flush the entry by ourselves. */ - __flush_tlb_page(get_asid(), address&PAGE_MASK); + { + unsigned long flags; + local_irq_save(flags); + __flush_tlb_page(get_asid(), address&PAGE_MASK); + local_irq_restore(flags); + } #endif set_pte(pte, entry); diff -urN linux-2.6.3-rc2/arch/sparc/Kconfig linux-2.6.3-rc3/arch/sparc/Kconfig --- linux-2.6.3-rc2/arch/sparc/Kconfig 2004-02-03 19:43:02.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc/Kconfig 2004-02-14 19:31:00.000000000 -0800 @@ -376,20 +376,7 @@ source "drivers/usb/Kconfig" -menu "Watchdog" - -config SOFT_WATCHDOG - tristate "Software watchdog" - help - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - To compile this driver as a module, choose M here: the - module will be called softdog. - -endmenu - +source "drivers/char/watchdog/Kconfig" menu "Kernel hacking" diff -urN linux-2.6.3-rc2/arch/sparc/kernel/irq.c linux-2.6.3-rc3/arch/sparc/kernel/irq.c --- linux-2.6.3-rc2/arch/sparc/kernel/irq.c 2004-02-03 19:43:07.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc/kernel/irq.c 2004-02-14 19:31:00.000000000 -0800 @@ -52,6 +52,66 @@ /* Used to protect the IRQ action lists */ spinlock_t irq_action_lock = SPIN_LOCK_UNLOCKED; +#ifdef CONFIG_SMP +#define SMP_NOP2 "nop; nop;\n\t" +#define SMP_NOP3 "nop; nop; nop;\n\t" +#else +#define SMP_NOP2 +#define SMP_NOP3 +#endif /* SMP */ +unsigned long __local_irq_save(void) +{ + unsigned long retval; + unsigned long tmp; + + __asm__ __volatile__( + "rd %%psr, %0\n\t" + SMP_NOP3 /* Sun4m + Cypress + SMP bug */ + "or %0, %2, %1\n\t" + "wr %1, 0, %%psr\n\t" + "nop; nop; nop\n" + : "=&r" (retval), "=r" (tmp) + : "i" (PSR_PIL) + : "memory"); + + return retval; +} + +void local_irq_enable(void) +{ + unsigned long tmp; + + __asm__ __volatile__( + "rd %%psr, %0\n\t" + SMP_NOP3 /* Sun4m + Cypress + SMP bug */ + "andn %0, %1, %0\n\t" + "wr %0, 0, %%psr\n\t" + "nop; nop; nop\n" + : "=&r" (tmp) + : "i" (PSR_PIL) + : "memory"); +} + +void local_irq_restore(unsigned long old_psr) +{ + unsigned long tmp; + + __asm__ __volatile__( + "rd %%psr, %0\n\t" + "and %2, %1, %2\n\t" + SMP_NOP2 /* Sun4m + Cypress + SMP bug */ + "andn %0, %1, %0\n\t" + "wr %0, %2, %%psr\n\t" + "nop; nop; nop\n" + : "=&r" (tmp) + : "i" (PSR_PIL), "r" (old_psr) + : "memory"); +} + +EXPORT_SYMBOL(__local_irq_save); +EXPORT_SYMBOL(local_irq_enable); +EXPORT_SYMBOL(local_irq_restore); + /* * Dave Redman (djhr@tadpole.co.uk) * diff -urN linux-2.6.3-rc2/arch/sparc/kernel/process.c linux-2.6.3-rc3/arch/sparc/kernel/process.c --- linux-2.6.3-rc2/arch/sparc/kernel/process.c 2004-02-03 19:43:12.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc/kernel/process.c 2004-02-14 19:31:00.000000000 -0800 @@ -148,11 +148,12 @@ extern void (*prom_palette)(int); +/* XXX cli/sti -> local_irq_xxx here, check this works once SMP is fixed. */ void machine_halt(void) { - sti(); + local_irq_enable(); mdelay(8); - cli(); + local_irq_disable(); if (!serial_console && prom_palette) prom_palette (1); prom_halt(); @@ -165,9 +166,9 @@ { char *p; - sti(); + local_irq_enable(); mdelay(8); - cli(); + local_irq_disable(); p = strchr (reboot_command, '\n'); if (p) *p = 0; diff -urN linux-2.6.3-rc2/arch/sparc/kernel/semaphore.c linux-2.6.3-rc3/arch/sparc/kernel/semaphore.c --- linux-2.6.3-rc2/arch/sparc/kernel/semaphore.c 2004-02-03 19:44:53.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc/kernel/semaphore.c 2004-02-14 19:31:00.000000000 -0800 @@ -61,7 +61,7 @@ * Add "everybody else" into it. They aren't * playing, because we own the spinlock. */ - if (!atomic_add_negative(sleepers - 1, &sem->count)) { + if (!atomic24_add_negative(sleepers - 1, &sem->count)) { sem->sleepers = 0; break; } @@ -101,7 +101,7 @@ if (signal_pending(current)) { retval = -EINTR; sem->sleepers = 0; - atomic_add(sleepers, &sem->count); + atomic24_add(sleepers, &sem->count); break; } @@ -111,7 +111,7 @@ * "-1" is because we're still hoping to get * the lock. */ - if (!atomic_add_negative(sleepers - 1, &sem->count)) { + if (!atomic24_add_negative(sleepers - 1, &sem->count)) { sem->sleepers = 0; break; } @@ -146,7 +146,7 @@ * Add "everybody else" and us into it. They aren't * playing, because we own the spinlock. */ - if (!atomic_add_negative(sleepers, &sem->count)) + if (!atomic24_add_negative(sleepers, &sem->count)) wake_up(&sem->wait); spin_unlock_irqrestore(&semaphore_lock, flags); diff -urN linux-2.6.3-rc2/arch/sparc/kernel/smp.c linux-2.6.3-rc3/arch/sparc/kernel/smp.c --- linux-2.6.3-rc2/arch/sparc/kernel/smp.c 2004-02-03 19:43:34.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc/kernel/smp.c 2004-02-14 19:31:00.000000000 -0800 @@ -56,6 +56,9 @@ volatile int __cpu_number_map[NR_CPUS]; volatile int __cpu_logical_map[NR_CPUS]; cycles_t cacheflush_time = 0; /* XXX */ +spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = { + [0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED +}; /* The only guaranteed locking primitive available on all Sparc * processors is 'ldstub [%reg + immediate], %dest_reg' which atomically diff -urN linux-2.6.3-rc2/arch/sparc/kernel/sparc_ksyms.c linux-2.6.3-rc3/arch/sparc/kernel/sparc_ksyms.c --- linux-2.6.3-rc2/arch/sparc/kernel/sparc_ksyms.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc/kernel/sparc_ksyms.c 2004-02-14 19:31:00.000000000 -0800 @@ -86,8 +86,8 @@ extern void dump_thread(struct pt_regs *, struct user *); /* Private functions with odd calling conventions. */ -extern void ___atomic_add(void); -extern void ___atomic_sub(void); +extern void ___atomic24_add(void); +extern void ___atomic24_sub(void); extern void ___set_bit(void); extern void ___clear_bit(void); extern void ___change_bit(void); @@ -147,8 +147,8 @@ EXPORT_SYMBOL(phys_base); /* Atomic operations. */ -EXPORT_SYMBOL(___atomic_add); -EXPORT_SYMBOL(___atomic_sub); +EXPORT_SYMBOL(___atomic24_add); +EXPORT_SYMBOL(___atomic24_sub); /* Bit operations. */ EXPORT_SYMBOL(___set_bit); @@ -159,10 +159,6 @@ /* IRQ implementation. */ EXPORT_SYMBOL(global_irq_holder); EXPORT_SYMBOL(synchronize_irq); -EXPORT_SYMBOL(__global_cli); -EXPORT_SYMBOL(__global_sti); -EXPORT_SYMBOL(__global_save_flags); -EXPORT_SYMBOL(__global_restore_flags); /* Misc SMP information */ EXPORT_SYMBOL(__cpu_number_map); diff -urN linux-2.6.3-rc2/arch/sparc/lib/atomic.S linux-2.6.3-rc3/arch/sparc/lib/atomic.S --- linux-2.6.3-rc2/arch/sparc/lib/atomic.S 2004-02-03 19:43:57.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc/lib/atomic.S 2004-02-14 19:31:00.000000000 -0800 @@ -45,8 +45,8 @@ /* Read asm-sparc/atomic.h carefully to understand how this works for SMP. * Really, some things here for SMP are overly clever, go read the header. */ - .globl ___atomic_add -___atomic_add: + .globl ___atomic24_add +___atomic24_add: rd %psr, %g3 ! Keep the code small, old way was stupid nop; nop; nop; ! Let the bits set or %g3, PSR_PIL, %g7 ! Disable interrupts @@ -56,13 +56,13 @@ 1: ldstub [%g1 + 3], %g7 ! Spin on the byte lock for SMP. orcc %g7, 0x0, %g0 ! Did we get it? bne 1b ! Nope... - ld [%g1], %g7 ! Load locked atomic_t + ld [%g1], %g7 ! Load locked atomic24_t sra %g7, 8, %g7 ! Get signed 24-bit integer add %g7, %g2, %g2 ! Add in argument - sll %g2, 8, %g7 ! Transpose back to atomic_t + sll %g2, 8, %g7 ! Transpose back to atomic24_t st %g7, [%g1] ! Clever: This releases the lock as well. #else - ld [%g1], %g7 ! Load locked atomic_t + ld [%g1], %g7 ! Load locked atomic24_t add %g7, %g2, %g2 ! Add in argument st %g2, [%g1] ! Store it back #endif @@ -71,8 +71,8 @@ jmpl %o7, %g0 ! NOTE: not + 8, see callers in atomic.h mov %g4, %o7 ! Restore %o7 - .globl ___atomic_sub -___atomic_sub: + .globl ___atomic24_sub +___atomic24_sub: rd %psr, %g3 ! Keep the code small, old way was stupid nop; nop; nop; ! Let the bits set or %g3, PSR_PIL, %g7 ! Disable interrupts @@ -82,13 +82,13 @@ 1: ldstub [%g1 + 3], %g7 ! Spin on the byte lock for SMP. orcc %g7, 0x0, %g0 ! Did we get it? bne 1b ! Nope... - ld [%g1], %g7 ! Load locked atomic_t + ld [%g1], %g7 ! Load locked atomic24_t sra %g7, 8, %g7 ! Get signed 24-bit integer sub %g7, %g2, %g2 ! Subtract argument - sll %g2, 8, %g7 ! Transpose back to atomic_t + sll %g2, 8, %g7 ! Transpose back to atomic24_t st %g7, [%g1] ! Clever: This releases the lock as well #else - ld [%g1], %g7 ! Load locked atomic_t + ld [%g1], %g7 ! Load locked atomic24_t sub %g7, %g2, %g2 ! Subtract argument st %g2, [%g1] ! Store it back #endif diff -urN linux-2.6.3-rc2/arch/sparc64/Kconfig linux-2.6.3-rc3/arch/sparc64/Kconfig --- linux-2.6.3-rc2/arch/sparc64/Kconfig 2004-02-03 19:44:30.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc64/Kconfig 2004-02-14 19:31:00.000000000 -0800 @@ -639,20 +639,7 @@ source "drivers/usb/Kconfig" - -menu "Watchdog" - -config SOFT_WATCHDOG - tristate "Software watchdog" - help - A software monitoring watchdog. This will fail to reboot your system - from some situations that the hardware watchdog will recover - from. Equally it's a lot cheaper to install. - - To compile this driver as a module, choose M here: the - module will be called softdog. - -endmenu +source "drivers/char/watchdog/Kconfig" source "arch/sparc64/oprofile/Kconfig" diff -urN linux-2.6.3-rc2/arch/sparc64/lib/VIScopy.S linux-2.6.3-rc3/arch/sparc64/lib/VIScopy.S --- linux-2.6.3-rc2/arch/sparc64/lib/VIScopy.S 2004-02-03 19:43:11.000000000 -0800 +++ linux-2.6.3-rc3/arch/sparc64/lib/VIScopy.S 2004-02-14 19:31:00.000000000 -0800 @@ -120,7 +120,6 @@ #define EXVIS2(x,y) EXVISN(x,y,2) #define EXVIS3(x,y) EXVISN(x,y,3) #define EXVIS4(x,y) EXVISN(x,y,4) -#define EXVIS5(x,y) EXVISN(x,y,5) #define FREG_FROB(f1, f2, f3, f4, f5, f6, f7, f8, f9) \ faligndata %f1, %f2, %f48; \ @@ -135,7 +134,7 @@ #define MAIN_LOOP_CHUNK(src, dest, fdest, fsrc, len, jmptgt) \ EXVIS(LDBLK [%src] ASIBLK, %fdest); \ ASI_SETDST_BLK \ - EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ + EXVIS(STBLK %fsrc, [%dest] ASIBLK); \ add %src, 0x40, %src; \ subcc %len, 0x40, %len; \ be,pn %xcc, jmptgt; \ @@ -156,14 +155,14 @@ #ifdef __KERNEL__ #define STORE_JUMP(dest, fsrc, target) \ srl asi_dest, 3, %g5; \ - EXVIS3(STBLK %fsrc, [%dest] ASIBLK); \ + EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ xor asi_dest, ASI_BLK_XOR1, asi_dest;\ add %dest, 0x40, %dest; \ xor asi_dest, %g5, asi_dest; \ ba,pt %xcc, target; #else #define STORE_JUMP(dest, fsrc, target) \ - EXVIS3(STBLK %fsrc, [%dest] ASIBLK); \ + EXVIS2(STBLK %fsrc, [%dest] ASIBLK); \ add %dest, 0x40, %dest; \ ba,pt %xcc, target; #endif @@ -182,7 +181,7 @@ subcc %left, 8, %left; \ bl,pn %xcc, vis_out; \ faligndata %f0, %f1, %f48; \ - EXVIS4(STDF %f48, [%dest] ASINORMAL); \ + EXVIS3(STDF %f48, [%dest] ASINORMAL); \ add %dest, 8, %dest; #define UNEVEN_VISCHUNK_LAST(dest, f0, f1, left) \ @@ -675,21 +674,21 @@ xor asi_src, %g5, asi_src ! IEU0 Group #endif vis_slk:ASI_SETSRC_NOBLK ! LSU Group - EXVIS4(LDDF [%o1] ASINORMAL, %f2) ! Load Group + EXVIS3(LDDF [%o1] ASINORMAL, %f2) ! Load Group add %o1, 8, %o1 ! IEU0 subcc %g3, 8, %g3 ! IEU1 ASI_SETDST_NOBLK ! LSU Group faligndata %f0, %f2, %f8 ! GRU Group - EXVIS5(STDF %f8, [%o0] ASINORMAL) ! Store + EXVIS4(STDF %f8, [%o0] ASINORMAL) ! Store bl,pn %xcc, vis_out_slp ! CTI add %o0, 8, %o0 ! IEU0 Group ASI_SETSRC_NOBLK ! LSU Group - EXVIS4(LDDF [%o1] ASINORMAL, %f0) ! Load Group + EXVIS3(LDDF [%o1] ASINORMAL, %f0) ! Load Group add %o1, 8, %o1 ! IEU0 subcc %g3, 8, %g3 ! IEU1 ASI_SETDST_NOBLK ! LSU Group faligndata %f2, %f0, %f8 ! GRU Group - EXVIS5(STDF %f8, [%o0] ASINORMAL) ! Store + EXVIS4(STDF %f8, [%o0] ASINORMAL) ! Store bge,pt %xcc, vis_slk ! CTI add %o0, 8, %o0 ! IEU0 Group vis_out_slp: @@ -1138,20 +1137,18 @@ sub %g7, %g2, %g7 ba,pt %xcc, VIScopyfixup_ret add %g7, %o2, %o1 -VIScopyfixup_vis3: - sub %o2, 0x80, %o2 VIScopyfixup_vis2: - add %o2, 0x40, %o2 + sub %o2, 0x40, %o2 VIScopyfixup_vis0: add %o2, 0x80, %o2 VIScopyfixup_vis1: add %g7, %g3, %g7 ba,pt %xcc, VIScopyfixup_ret add %o2, %g7, %o1 -VIScopyfixup_vis5: - add %g3, 8, %g3 VIScopyfixup_vis4: add %g3, 8, %g3 +VIScopyfixup_vis3: + add %g3, 8, %g3 ba,pt %xcc, VIScopyfixup_ret add %o2, %g3, %o1 #endif diff -urN linux-2.6.3-rc2/arch/x86_64/kernel/acpi/boot.c linux-2.6.3-rc3/arch/x86_64/kernel/acpi/boot.c --- linux-2.6.3-rc2/arch/x86_64/kernel/acpi/boot.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/x86_64/kernel/acpi/boot.c 2004-02-14 19:31:01.000000000 -0800 @@ -120,6 +120,11 @@ acpi_table_print_madt_entry(header); + /* no utility in registering a disabled processor */ + if (processor->flags.enabled == 0) + return 0; + + mp_register_lapic ( processor->id, /* APIC ID */ processor->flags.enabled); /* Enabled? */ diff -urN linux-2.6.3-rc2/arch/x86_64/kernel/mpparse.c linux-2.6.3-rc3/arch/x86_64/kernel/mpparse.c --- linux-2.6.3-rc2/arch/x86_64/kernel/mpparse.c 2004-02-03 19:43:39.000000000 -0800 +++ linux-2.6.3-rc3/arch/x86_64/kernel/mpparse.c 2004-02-14 19:31:01.000000000 -0800 @@ -487,7 +487,7 @@ /* * ACPI may be used to obtain the entire SMP configuration or just to - * enumerate/configure processors (CONFIG_ACPI_HT_ONLY). Note that + * enumerate/configure processors (CONFIG_ACPI_BOOT). Note that * ACPI supports both logical (e.g. Hyper-Threading) and physical * processors, where MPS only supports physical. */ @@ -787,7 +787,7 @@ * erroneously sets the trigger to level, resulting in a HUGE * increase of timer interrupts! */ - if ((bus_irq == 0) && (global_irq == 2) && (trigger == 3)) + if ((bus_irq == 0) && (trigger == 3)) trigger = 1; intsrc.mpc_type = MP_INTSRC; @@ -808,8 +808,8 @@ * Otherwise create a new entry (e.g. global_irq == 2). */ for (i = 0; i < mp_irq_entries; i++) { - if ((mp_irqs[i].mpc_dstapic == intsrc.mpc_dstapic) - && (mp_irqs[i].mpc_dstirq == intsrc.mpc_dstirq)) { + if ((mp_irqs[i].mpc_srcbus == intsrc.mpc_srcbus) + && (mp_irqs[i].mpc_srcbusirq == intsrc.mpc_srcbusirq)) { mp_irqs[i] = intsrc; found = 1; break; @@ -855,9 +855,10 @@ */ for (i = 0; i < 16; i++) { - if (i == 2) continue; /* Don't connect IRQ2 */ + if (i == 2) + continue; /* Don't connect IRQ2 */ - intsrc.mpc_irqtype = i ? mp_INT : mp_ExtINT; /* 8259A to #0 */ + intsrc.mpc_irqtype = mp_INT; intsrc.mpc_srcbusirq = i; /* Identity mapped */ intsrc.mpc_dstirq = i; diff -urN linux-2.6.3-rc2/arch/x86_64/kernel/sys_x86_64.c linux-2.6.3-rc3/arch/x86_64/kernel/sys_x86_64.c --- linux-2.6.3-rc2/arch/x86_64/kernel/sys_x86_64.c 2004-02-14 19:30:51.000000000 -0800 +++ linux-2.6.3-rc3/arch/x86_64/kernel/sys_x86_64.c 2004-02-14 19:31:01.000000000 -0800 @@ -110,8 +110,8 @@ if (end - len >= addr && (!vma || addr + len <= vma->vm_start)) return addr; - } else - addr = mm->free_area_cache; + } + addr = mm->free_area_cache; if (addr < begin) addr = begin; start_addr = addr; diff -urN linux-2.6.3-rc2/drivers/acpi/Kconfig linux-2.6.3-rc3/drivers/acpi/Kconfig --- linux-2.6.3-rc2/drivers/acpi/Kconfig 2004-02-03 19:45:04.000000000 -0800 +++ linux-2.6.3-rc3/drivers/acpi/Kconfig 2004-02-14 19:31:02.000000000 -0800 @@ -143,7 +143,7 @@ bool "NUMA support" depends on ACPI_INTERPRETER depends on NUMA - depends on !X86_64 + depends on IA64 default y if IA64_GENERIC || IA64_SGI_SN2 config ACPI_ASUS diff -urN linux-2.6.3-rc2/drivers/acpi/numa.c linux-2.6.3-rc3/drivers/acpi/numa.c --- linux-2.6.3-rc2/drivers/acpi/numa.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/acpi/numa.c 2004-02-14 19:31:02.000000000 -0800 @@ -172,7 +172,7 @@ NR_CPUS); result = acpi_table_parse_srat(ACPI_SRAT_MEMORY_AFFINITY, acpi_parse_memory_affinity, - NR_MEMBLKS); + NR_NODE_MEMBLKS); // IA64 specific } else { /* FIXME */ printk("Warning: acpi_table_parse(ACPI_SRAT) returned %d!\n",result); diff -urN linux-2.6.3-rc2/drivers/acpi/processor.c linux-2.6.3-rc3/drivers/acpi/processor.c --- linux-2.6.3-rc2/drivers/acpi/processor.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/acpi/processor.c 2004-02-14 19:31:02.000000000 -0800 @@ -1022,7 +1022,7 @@ (u32) px->status)); if (!px->core_frequency) { - ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "core_frequency is 0\n")); + ACPI_DEBUG_PRINT((ACPI_DB_ERROR, "Invalid _PSS data: freq is zero\n")); result = -EFAULT; kfree(pr->performance->states); goto end; @@ -1607,7 +1607,7 @@ static int acpi_thermal_cpufreq_increase(unsigned int cpu) { - if (!cpu_has_cpufreq) + if (!cpu_has_cpufreq(cpu)) return -ENODEV; if (cpufreq_thermal_reduction_pctg[cpu] < 60) { @@ -1622,7 +1622,7 @@ static int acpi_thermal_cpufreq_decrease(unsigned int cpu) { - if (!cpu_has_cpufreq) + if (!cpu_has_cpufreq(cpu)) return -ENODEV; if (cpufreq_thermal_reduction_pctg[cpu] >= 20) { diff -urN linux-2.6.3-rc2/drivers/atm/he.c linux-2.6.3-rc3/drivers/atm/he.c --- linux-2.6.3-rc2/drivers/atm/he.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/atm/he.c 2004-02-14 19:31:02.000000000 -0800 @@ -177,9 +177,7 @@ unsigned flags) { he_writel(he_dev, val, CON_DAT); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, CON_DAT); -#endif + (void) he_readl(he_dev, CON_DAT); /* flush posted writes */ he_writel(he_dev, flags | CON_CTL_WRITE | CON_CTL_ADDR(addr), CON_CTL); while (he_readl(he_dev, CON_CTL) & CON_CTL_BUSY); } @@ -1950,9 +1948,6 @@ he_writel(he_dev, RBRQ_MASK(he_dev->rbrq_head), G0_RBRQ_H + (group * 16)); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, G0_RBRQ_H + (group * 16)); -#endif } return pdus_assembled; @@ -2045,9 +2040,6 @@ he_writel(he_dev, TBRQ_MASK(he_dev->tbrq_head), G0_TBRQ_H + (group * 16)); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, G0_TBRQ_H + (group * 16)); -#endif } } @@ -2075,12 +2067,8 @@ ++moved; } - if (moved) { + if (moved) he_writel(he_dev, RBPL_MASK(he_dev->rbpl_tail), G0_RBPL_T); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, G0_RBPL_T); -#endif - } } #ifdef USE_RBPS @@ -2107,12 +2095,8 @@ ++moved; } - if (moved) { + if (moved) he_writel(he_dev, RBPS_MASK(he_dev->rbps_tail), G0_RBPS_T); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, G0_RBPS_T); -#endif - } } #endif /* USE_RBPS */ @@ -2209,7 +2193,7 @@ IRQ_SIZE(CONFIG_IRQ_SIZE) | IRQ_THRESH(CONFIG_IRQ_THRESH) | IRQ_TAIL(he_dev->irq_tail), IRQ0_HEAD); - (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata */ + (void) he_readl(he_dev, INT_FIFO); /* 8.1.2 controller errata; flush posted writes */ } #ifdef USE_TASKLET spin_unlock_irqrestore(&he_dev->global_lock, flags); @@ -2250,11 +2234,8 @@ #else he_tasklet((unsigned long) he_dev); #endif - he_writel(he_dev, INT_CLEAR_A, INT_FIFO); - /* clear interrupt */ -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, INT_FIFO); -#endif + he_writel(he_dev, INT_CLEAR_A, INT_FIFO); /* clear interrupt */ + (void) he_readl(he_dev, INT_FIFO); /* flush posted writes */ } spin_unlock_irqrestore(&he_dev->global_lock, flags); return IRQ_RETVAL(handled); @@ -2323,9 +2304,7 @@ he_dev->tpdrq_tail = new_tail; he_writel(he_dev, TPDRQ_MASK(he_dev->tpdrq_tail), TPDRQ_T); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, TPDRQ_T); -#endif + (void) he_readl(he_dev, TPDRQ_T); /* flush posted writes */ } static int @@ -2475,9 +2454,7 @@ he_writel_tsr12(he_dev, 0x0, cid); he_writel_tsr13(he_dev, 0x0, cid); he_writel_tsr14(he_dev, 0x0, cid); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl_tsr0(he_dev, cid); -#endif + (void) he_readl_tsr0(he_dev, cid); /* flush posted writes */ spin_unlock_irqrestore(&he_dev->global_lock, flags); } @@ -2531,9 +2508,7 @@ the open/closed indication in rsr0 */ he_writel_rsr0(he_dev, rsr0 | RSR0_START_PDU | RSR0_OPEN_CONN | aal, cid); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl_rsr0(he_dev, cid); -#endif + (void) he_readl_rsr0(he_dev, cid); /* flush posted writes */ spin_unlock_irqrestore(&he_dev->global_lock, flags); } @@ -2587,9 +2562,7 @@ set_current_state(TASK_UNINTERRUPTIBLE); he_writel_rsr0(he_dev, RSR0_CLOSE_CONN, cid); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl_rsr0(he_dev, cid); -#endif + (void) he_readl_rsr0(he_dev, cid); /* flush posted writes */ he_writel_mbox(he_dev, cid, RXCON_CLOSE); spin_unlock_irqrestore(&he_dev->global_lock, flags); @@ -2638,9 +2611,6 @@ spin_lock_irqsave(&he_dev->global_lock, flags); he_writel_tsr4_upper(he_dev, TSR4_FLUSH_CONN, cid); /* also clears TSR4_SESSION_ENDED */ -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl_tsr4(he_dev, cid); -#endif switch (vcc->qos.txtp.traffic_class) { case ATM_UBR: @@ -2652,6 +2622,7 @@ he_writel_tsr14_upper(he_dev, TSR14_DELETE, cid); break; } + (void) he_readl_tsr4(he_dev, cid); /* flush posted writes */ tpd = __alloc_tpd(he_dev); if (tpd == NULL) { @@ -2904,9 +2875,7 @@ spin_lock_irqsave(&he_dev->global_lock, flags); he_writel(he_dev, val, FRAMER + (addr*4)); -#ifdef CONFIG_IA64_SGI_SN2 - (void) he_readl(he_dev, FRAMER + (addr*4)); -#endif + (void) he_readl(he_dev, FRAMER + (addr*4)); /* flush posted writes */ spin_unlock_irqrestore(&he_dev->global_lock, flags); } diff -urN linux-2.6.3-rc2/drivers/base/bus.c linux-2.6.3-rc3/drivers/base/bus.c --- linux-2.6.3-rc2/drivers/base/bus.c 2004-02-03 19:43:19.000000000 -0800 +++ linux-2.6.3-rc3/drivers/base/bus.c 2004-02-14 19:31:02.000000000 -0800 @@ -158,17 +158,19 @@ int bus_for_each_dev(struct bus_type * bus, struct device * start, void * data, int (*fn)(struct device *, void *)) { - struct list_head * head, * entry; + struct device *dev; + struct list_head * head; int error = 0; if (!(bus = get_bus(bus))) return -EINVAL; - head = start ? &start->bus_list : &bus->devices.list; + head = &bus->devices.list; + dev = list_prepare_entry(start, head, bus_list); down_read(&bus->subsys.rwsem); - list_for_each(entry,head) { - struct device * dev = get_device(to_dev(entry)); + list_for_each_entry_continue(dev, head, bus_list) { + get_device(dev); error = fn(dev,data); put_device(dev); if (error) @@ -202,17 +204,19 @@ int bus_for_each_drv(struct bus_type * bus, struct device_driver * start, void * data, int (*fn)(struct device_driver *, void *)) { - struct list_head * head, * entry; + struct list_head * head; + struct device_driver *drv; int error = 0; if(!(bus = get_bus(bus))) return -EINVAL; - head = start ? &start->kobj.entry : &bus->drivers.list; + head = &bus->drivers.list; + drv = list_prepare_entry(start, head, kobj.entry); down_read(&bus->subsys.rwsem); - list_for_each(entry,head) { - struct device_driver * drv = get_driver(to_drv(entry)); + list_for_each_entry_continue(drv, head, kobj.entry) { + get_driver(drv); error = fn(drv,data); put_driver(drv); if(error) diff -urN linux-2.6.3-rc2/drivers/cdrom/cdrom.c linux-2.6.3-rc3/drivers/cdrom/cdrom.c --- linux-2.6.3-rc2/drivers/cdrom/cdrom.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/cdrom/cdrom.c 2004-02-14 19:31:02.000000000 -0800 @@ -2766,13 +2766,13 @@ for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_DVD_RAM) != 0); - pos += sprintf(info+pos, "\nCan read MRW:"); + pos += sprintf(info+pos, "\nCan read MRW:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW) != 0); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW) != 0); - pos += sprintf(info+pos, "\nCan write MRW:"); + pos += sprintf(info+pos, "\nCan write MRW:\t"); for (cdi=topCdromPtr;cdi!=NULL;cdi=cdi->next) - pos += sprintf(info+pos, "\t\t%d", CDROM_CAN(CDC_MRW_W) != 0); + pos += sprintf(info+pos, "\t%d", CDROM_CAN(CDC_MRW_W) != 0); strcpy(info+pos,"\n\n"); diff -urN linux-2.6.3-rc2/drivers/char/sh-sci.c linux-2.6.3-rc3/drivers/char/sh-sci.c --- linux-2.6.3-rc2/drivers/char/sh-sci.c 2004-02-03 19:44:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/sh-sci.c 2004-02-14 19:31:02.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: sh-sci.c,v 1.15 2003/10/13 07:21:19 lethal Exp $ +/* $Id: sh-sci.c,v 1.16 2004/02/10 17:04:17 lethal Exp $ * * linux/drivers/char/sh-sci.c * @@ -7,6 +7,7 @@ * Copyright (C) 2000 Sugioka Toshinobu * Modified to support multiple serial ports. Stuart Menefy (May 2000). * Modified to support SH7760 SCIF. Paul Mundt (Oct 2003). + * Modified to support H8/300 Series. Yoshinori Sato (Feb 2004). * * TTY code is based on sx.c (Specialix SX driver) by: * @@ -337,6 +338,7 @@ NULL }; +#if !defined(__H8300H__) && !defined(__H8300S__) #if defined(SCI_ONLY) || defined(SCI_AND_SCIF) static void sci_init_pins_sci(struct sci_port* port, unsigned int cflag) { @@ -403,6 +405,32 @@ #endif #endif /* SCIF_ONLY || SCI_AND_SCIF */ +#else /* !defined(__H8300H__) && !defined(__H8300S__) */ +static void sci_init_pins_sci(struct sci_port* port, unsigned int cflag) +{ + int ch = (port->base - SMR0) >> 3; + /* set DDR regs */ + H8300_GPIO_DDR(h8300_sci_pins[ch].port,h8300_sci_pins[ch].rx,H8300_GPIO_INPUT); + H8300_GPIO_DDR(h8300_sci_pins[ch].port,h8300_sci_pins[ch].tx,H8300_GPIO_OUTPUT); + /* tx mark output*/ + H8300_SCI_DR(ch) |= h8300_sci_pins[ch].tx; +} + +#if defined(__H8300S__) +enum {sci_disable,sci_enable}; + +static void h8300_sci_enable(struct sci_port* port, unsigned int ctrl) +{ + volatile unsigned char *mstpcrl=(volatile unsigned char *)MSTPCRL; + int ch = (port->base - SMR0) >> 3; + unsigned char mask = 1 << (ch+1); + if (ctrl == sci_disable) + *mstpcrl |= mask; + else + *mstpcrl &= ~mask; +} +#endif +#endif static void sci_setsignals(struct sci_port *port, int dtr, int rts) { @@ -487,9 +515,11 @@ sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ +#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); } +#endif smr_val = sci_in(port, SCSMR) & 3; if ((cflag & CSIZE) == CS7) @@ -559,11 +589,15 @@ while (1) { count = port->gs.xmit_cnt; +#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { txroom = 16 - (sci_in(port, SCFDR)>>8); } else { txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0; } +#else + txroom = (sci_in(port, SCxSR) & SCI_TDRE)?1:0; +#endif if (count > txroom) count = txroom; @@ -600,10 +634,12 @@ ctrl &= ~SCI_CTRL_FLAGS_TIE; port->gs.flags &= ~GS_TX_INTEN; } else { +#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { sci_in(port, SCxSR); /* Dummy read */ sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port)); } +#endif ctrl |= SCI_CTRL_FLAGS_TIE; } sci_out(port, SCSCR, ctrl); @@ -627,11 +663,15 @@ tty = port->gs.tty; while (1) { +#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { count = sci_in(port, SCFDR)&0x001f; } else { count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0; } +#else + count = (sci_in(port, SCxSR)&SCxSR_RDxF(port))?1:0; +#endif /* Don't copy more bytes than there is room for in the buffer */ if (tty->flip.count + count > TTY_FLIPBUF_SIZE) @@ -861,6 +901,7 @@ return IRQ_HANDLED; } +#if !defined(SCI_ONLY) static irqreturn_t sci_br_interrupt(int irq, void *ptr, struct pt_regs *regs) { struct sci_port *port = ptr; @@ -871,6 +912,7 @@ return IRQ_HANDLED; } +#endif static void do_softint(void *private_) { @@ -955,11 +997,15 @@ { struct sci_port *port = ptr; +#if !defined(SCI_ONLY) if (port->type == PORT_SCIF) { return (sci_in(port, SCFDR) >> 8) + ((sci_in(port, SCxSR) & SCxSR_TEND(port))? 0: 1); } else { return (sci_in(port, SCxSR) & SCxSR_TEND(port))? 0: 1; } +#else + return (sci_in(port, SCxSR) & SCxSR_TEND(port))? 0: 1; +#endif } static void sci_shutdown_port(void * ptr) @@ -970,6 +1016,9 @@ if (port->gs.tty && port->gs.tty->termios->c_cflag & HUPCL) sci_setsignals(port, 0, 0); sci_free_irq(port); +#if defined(__H8300S__) + h8300_sci_enable(port,sci_disable); +#endif } /* ********************************************************************** * @@ -996,6 +1045,10 @@ port->event = 0; INIT_WORK(&port->tqueue, do_softint, port); +#if defined(__H8300S__) + h8300_sci_enable(port,sci_enable); +#endif + /* * Start up serial port */ @@ -1282,12 +1335,17 @@ static int sci_request_irq(struct sci_port *port) { int i; +#if !defined(SCI_ONLY) irqreturn_t (*handlers[4])(int irq, void *p, struct pt_regs *regs) = { sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt, sci_br_interrupt, }; - - for (i=0; i<4; i++) { +#else + void (*handlers[3])(int irq, void *ptr, struct pt_regs *regs) = { + sci_er_interrupt, sci_rx_interrupt, sci_tx_interrupt, + }; +#endif + for (i=0; i<(sizeof(handlers)/sizeof(handlers[0])); i++) { if (!port->irqs[i]) continue; if (request_irq(port->irqs[i], handlers[i], SA_INTERRUPT, "sci", port)) { @@ -1432,6 +1490,9 @@ co->cflag = cflag; sercons_baud = baud; +#if defined(__H8300S__) + h8300_sci_enable(sercons_port,sci_enable); +#endif sci_set_termios_cflag(sercons_port, cflag, baud); sercons_port->old_cflag = cflag; diff -urN linux-2.6.3-rc2/drivers/char/sh-sci.h linux-2.6.3-rc3/drivers/char/sh-sci.h --- linux-2.6.3-rc2/drivers/char/sh-sci.h 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/sh-sci.h 2004-02-14 19:31:02.000000000 -0800 @@ -1,4 +1,4 @@ -/* $Id: sh-sci.h,v 1.6 2003/10/13 01:11:11 lethal Exp $ +/* $Id: sh-sci.h,v 1.7 2004/02/10 17:04:17 lethal Exp $ * * linux/drivers/char/sh-sci.h * @@ -7,10 +7,21 @@ * Copyright (C) 2000 Greg Banks * Modified to support multiple serial ports. Stuart Menefy (May 2000). * Modified to support SH7760 SCIF. Paul Mundt (Oct 2003). + * Modified to support H8/300 Serise Yoshinori Sato (Feb 2004). * */ #include +#if defined(__H8300H__) || defined(__H8300S__) +#include +#if defined(CONFIG_H83007) || defined(CONFIG_H83068) +#include +#endif +#if defined(CONFIG_H8S2678) +#include +#endif +#endif + /* Values for sci_port->type */ #define PORT_SCI 0 #define PORT_SCIF 1 @@ -30,6 +41,12 @@ #define SH7760_SCIF0_IRQS { 52, 53, 55, 54 } #define SH7760_SCIF1_IRQS { 72, 73, 75, 74 } #define SH7760_SCIF2_IRQS { 76, 77, 79, 78 } +#define H8300H_SCI_IRQS0 {52, 53, 54, 0 } +#define H8300H_SCI_IRQS1 {56, 57, 58, 0 } +#define H8300H_SCI_IRQS2 {60, 61, 62, 0 } +#define H8S_SCI_IRQS0 {88, 89, 90, 0 } +#define H8S_SCI_IRQS1 {92, 93, 94, 0 } +#define H8S_SCI_IRQS2 {96, 97, 98, 0 } #if defined(CONFIG_CPU_SUBTYPE_SH7708) # define SCI_NPORTS 1 @@ -87,6 +104,26 @@ # define SCIF_ORER 0x0001 /* overrun error bit */ # define SCSCR_INIT(port) 0x38 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ # define SCIF_ONLY +#elif defined(CONFIG_H83007) || defined(CONFIG_H83068) +# define SCI_NPORTS 3 +# define SCI_INIT { \ + { {}, PORT_SCI, 0x00ffffb0, H8300H_SCI_IRQS0, sci_init_pins_sci }, \ + { {}, PORT_SCI, 0x00ffffb8, H8300H_SCI_IRQS1, sci_init_pins_sci }, \ + { {}, PORT_SCI, 0x00ffffc0, H8300H_SCI_IRQS2, sci_init_pins_sci } \ +} +# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ +# define SCI_ONLY +# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) +#elif defined(CONFIG_H8S2678) +# define SCI_NPORTS 3 +# define SCI_INIT { \ + { {}, PORT_SCI, 0x00ffff78, H8S_SCI_IRQS0, sci_init_pins_sci }, \ + { {}, PORT_SCI, 0x00ffff80, H8S_SCI_IRQS1, sci_init_pins_sci }, \ + { {}, PORT_SCI, 0x00ffff88, H8S_SCI_IRQS2, sci_init_pins_sci } \ +} +# define SCSCR_INIT(port) 0x30 /* TIE=0,RIE=0,TE=1,RE=1 */ +# define SCI_ONLY +# define H8300_SCI_DR(ch) *(volatile char *)(P1DR + h8300_sci_pins[ch].port) #else # error CPU subtype not defined #endif @@ -242,28 +279,46 @@ SCI_OUT(scif_size, scif_offset, value); \ } +#define CPU_SCI_FNS(name, sci_offset, sci_size) \ + static inline unsigned int sci_##name##_in(struct sci_port* port) \ + { \ + SCI_IN(sci_size, sci_offset); \ + } \ + static inline void sci_##name##_out(struct sci_port* port, unsigned int value) \ + { \ + SCI_OUT(sci_size, sci_offset, value); \ + } + #ifdef CONFIG_CPU_SH3 #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ - sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ + sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ + h8_sci_offset, h8_sci_size) \ CPU_SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh3_scif_offset, sh3_scif_size) #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ CPU_SCIF_FNS(name, sh3_scif_offset, sh3_scif_size) +#elif defined(__H8300H__) || defined(__H8300S__) +#define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ + sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ + h8_sci_offset, h8_sci_size) \ + CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) +#define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) #else #define SCIx_FNS(name, sh3_sci_offset, sh3_sci_size, sh4_sci_offset, sh4_sci_size, \ - sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ + sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ + h8_sci_offset, h8_sci_size) \ CPU_SCIx_FNS(name, sh4_sci_offset, sh4_sci_size, sh4_scif_offset, sh4_scif_size) #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ CPU_SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) #endif -/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 */ -/* name off sz off sz off sz off sz */ -SCIx_FNS(SCSMR, 0x00, 8, 0x00, 8, 0x00, 8, 0x00, 16) -SCIx_FNS(SCBRR, 0x02, 8, 0x04, 8, 0x02, 8, 0x04, 8) -SCIx_FNS(SCSCR, 0x04, 8, 0x08, 8, 0x04, 8, 0x08, 16) -SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8) -SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16) -SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8) +/* reg SCI/SH3 SCI/SH4 SCIF/SH3 SCIF/SH4 SCI/H8*/ +/* name off sz off sz off sz off sz off sz*/ +SCIx_FNS(SCSMR, 0x00, 8, 0x00, 8, 0x00, 8, 0x00, 16, 0x00, 8) +SCIx_FNS(SCBRR, 0x02, 8, 0x04, 8, 0x02, 8, 0x04, 8, 0x01, 8) +SCIx_FNS(SCSCR, 0x04, 8, 0x08, 8, 0x04, 8, 0x08, 16, 0x02, 8) +SCIx_FNS(SCxTDR, 0x06, 8, 0x0c, 8, 0x06, 8, 0x0C, 8, 0x03, 8) +SCIx_FNS(SCxSR, 0x08, 8, 0x10, 8, 0x08, 16, 0x10, 16, 0x04, 8) +SCIx_FNS(SCxRDR, 0x0a, 8, 0x14, 8, 0x0A, 8, 0x14, 8, 0x05, 8) SCIF_FNS(SCFCR, 0x0c, 8, 0x18, 16) SCIF_FNS(SCFDR, 0x0e, 16, 0x1C, 16) SCIF_FNS(SCLSR, 0, 0, 0x24, 16) @@ -271,6 +326,50 @@ #define sci_in(port, reg) sci_##reg##_in(port) #define sci_out(port, reg, value) sci_##reg##_out(port, value) +/* H8/300 series SCI pins assignment */ +#if defined(__H8300H__) || defined(__H8300S__) +static const struct __attribute__((packed)) +{ + int port; /* GPIO port no */ + unsigned short rx,tx; /* GPIO bit no */ +} h8300_sci_pins[] = +{ +#if defined(CONFIG_H83007) || defined(CONFIG_H83068) + { /* SCI0 */ + .port = H8300_GPIO_P9, + .rx = H8300_GPIO_B2, + .tx = H8300_GPIO_B0, + }, + { /* SCI1 */ + .port = H8300_GPIO_P9, + .rx = H8300_GPIO_B3, + .tx = H8300_GPIO_B1, + }, + { /* SCI2 */ + .port = H8300_GPIO_PB, + .rx = H8300_GPIO_B7, + .tx = H8300_GPIO_B6, + } +#elif defined(CONFIG_H8S2678) + { /* SCI0 */ + .port = H8300_GPIO_P3, + .rx = H8300_GPIO_B2, + .tx = H8300_GPIO_B0, + }, + { /* SCI1 */ + .port = H8300_GPIO_P3, + .rx = H8300_GPIO_B3, + .tx = H8300_GPIO_B1, + }, + { /* SCI2 */ + .port = H8300_GPIO_P5, + .rx = H8300_GPIO_B1, + .tx = H8300_GPIO_B0, + } +#endif +}; +#endif + #if defined(CONFIG_CPU_SUBTYPE_SH7708) static inline int sci_rxd_in(struct sci_port *port) { @@ -321,6 +420,12 @@ return ctrl_inw(SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ } +#elif defined(__H8300H__) || defined(__H8300S__) +static inline int sci_rxd_in(struct sci_port *port) +{ + int ch = (port->base - SMR0) >> 3; + return (H8300_SCI_DR(ch) & h8300_sci_pins[ch].rx) ? 1 : 0; +} #endif /* @@ -357,7 +462,11 @@ #define PCLK (current_cpu_data.module_clock) +#if !defined(__H8300H__) && !defined(__H8300S__) #define SCBRR_VALUE(bps) ((PCLK+16*bps)/(32*bps)-1) +#else +#define SCBRR_VALUE(bps) (((CONFIG_CPU_CLOCK*1000/32)/bps)-1) +#endif #define BPS_2400 SCBRR_VALUE(2400) #define BPS_4800 SCBRR_VALUE(4800) #define BPS_9600 SCBRR_VALUE(9600) diff -urN linux-2.6.3-rc2/drivers/char/sn_serial.c linux-2.6.3-rc3/drivers/char/sn_serial.c --- linux-2.6.3-rc2/drivers/char/sn_serial.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/sn_serial.c 2004-02-14 19:31:02.000000000 -0800 @@ -772,7 +772,7 @@ int len = 0; off_t begin = 0; - len += sprintf(page, "sn_serial: nasid:%d irq:%d tx:%d rx:%d\n", + len += sprintf(page, "sn_serial: nasid:%ld irq:%d tx:%d rx:%d\n", ia64_sn_get_console_nasid(), sn_sal_irq, sn_total_tx_count, sn_total_rx_count); *eof = 1; diff -urN linux-2.6.3-rc2/drivers/char/watchdog/Kconfig linux-2.6.3-rc3/drivers/char/watchdog/Kconfig --- linux-2.6.3-rc2/drivers/char/watchdog/Kconfig 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/Kconfig 2004-02-14 19:31:03.000000000 -0800 @@ -38,6 +38,15 @@ get killed. If you say Y here, the watchdog cannot be stopped once it has been started. +# +# General Watchdog drivers +# + +comment "Watchdog Device Drivers" + depends on WATCHDOG + +# Architecture Independant + config SOFT_WATCHDOG tristate "Software watchdog" depends on WATCHDOG @@ -49,88 +58,53 @@ To compile this driver as a module, choose M here: the module will be called softdog. -config WDT - tristate "WDT Watchdog timer" - depends on WATCHDOG - ---help--- - If you have a WDT500P or WDT501P watchdog board, say Y here, - otherwise N. It is not possible to probe for this board, which means - that you have to inform the kernel about the IO port and IRQ using - the "wdt=" kernel option (try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time). - - To compile this driver as a module, choose M here: the - module will be called wdt. - -config WDT_501 - bool "WDT501 features" - depends on WDT - help - Saying Y here and creating a character special file /dev/temperature - with major number 10 and minor number 131 ("man mknod") will give - you a thermometer inside your computer: reading from - /dev/temperature yields one byte, the temperature in degrees - Fahrenheit. This works only if you have a WDT501P watchdog board - installed. +# ARM Architecture -config WDT_501_FAN - bool "Fan Tachometer" - depends on WDT_501 +config 21285_WATCHDOG + tristate "DC21285 watchdog" + depends on WATCHDOG && FOOTBRIDGE help - Enable the Fan Tachometer on the WDT501. Only do this if you have a - fan tachometer actually set up. + The Intel Footbridge chip contains a builtin watchdog circuit. Say Y + here if you wish to use this. Alternatively say M to compile the + driver as a module, which will be called wdt285. -config WDTPCI - tristate "WDT PCI Watchdog timer" - depends on WATCHDOG - ---help--- - If you have a PCI WDT500/501 watchdog board, say Y here, otherwise - N. It is not possible to probe for this board, which means that you - have to inform the kernel about the IO port and IRQ using the "wdt=" - kernel option (try "man bootparam" or see the documentation of your - boot loader (lilo or loadlin) about how to pass options to the - kernel at boot time). + This driver does not work on all machines. In particular, early CATS + boards have hardware problems that will cause the machine to simply + lock up if the watchdog fires. - To compile this driver as a module, choose M here: the - module will be called wdt_pci. + "If in doubt, leave it out" - say N. -config WDT_501_PCI - bool "WDT501-PCI features" - depends on WDTPCI +config 977_WATCHDOG + tristate "NetWinder WB83C977 watchdog" + depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER help - Saying Y here and creating a character special file /dev/temperature - with major number 10 and minor number 131 ("man mknod") will give - you a thermometer inside your computer: reading from - /dev/temperature yields one byte, the temperature in degrees - Fahrenheit. This works only if you have a WDT501P watchdog board - installed. + Say Y here to include support for the WB977 watchdog included in + NetWinder machines. Alternatively say M to compile the driver as + a module, which will be called wdt977. -config PCWATCHDOG - tristate "Berkshire Products PC Watchdog" - depends on WATCHDOG - ---help--- - This is the driver for the Berkshire Products PC Watchdog card. - This card simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. This driver is like the WDT501 driver but for different - hardware. Please read . The PC - watchdog cards can be ordered from . + Not sure? It's safe to say N. + +config SA1100_WATCHDOG + tristate "SA1100 watchdog" + depends on WATCHDOG && ARCH_SA1100 + help + Watchdog timer embedded into SA11x0 chips. This will reboot your + system when timeout is reached. + NOTE, that once enabled, this timer cannot be disabled. To compile this driver as a module, choose M here: the - module will be called pcwd. + module will be called sa1100_wdt. - Most people will say N. +# X86 (i386 + ia64 + x86_64) Architecture config ACQUIRE_WDT tristate "Acquire SBC Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- - This is the driver for the hardware watchdog on the PSC-6x86 Single - Board Computer produced by Acquire Inc (and others). This watchdog + This is the driver for the hardware watchdog on Single Board + Computers produced by Acquire Inc (and others). This watchdog simply watches your kernel to make sure it doesn't freeze, and if it does, it reboots your computer after a certain amount of time. - This driver is like the WDT501 driver but for different hardware. To compile this driver as a module, choose M here: the module will be called acquirewdt. @@ -139,50 +113,65 @@ config ADVANTECH_WDT tristate "Advantech SBC Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 help If you are configuring a Linux kernel for the Advantech single-board computer, say `Y' here to support its built-in watchdog timer - feature. See the help for CONFIG_WATCHDOG for discussion. + feature. More information can be found at + -config 21285_WATCHDOG - tristate "DC21285 watchdog" - depends on WATCHDOG && FOOTBRIDGE +config ALIM1535_WDT + tristate "ALi M1535 PMU Watchdog Timer" + depends on WATCHDOG && X86 && PCI + ---help--- + This is the driver for the hardware watchdog on the ALi M1535 PMU. + + To compile this driver as a module, choose M here: the + module will be called alim1535_wdt. + + Most people will say N. + +config ALIM7101_WDT + tristate "ALi M7101 PMU Computer Watchdog" + depends on WATCHDOG && X86 && PCI help - The Intel Footbridge chip contains a builtin watchdog circuit. Say Y - here if you wish to use this. Alternatively say M to compile the - driver as a module, which will be called wdt285. + This is the driver for the hardware watchdog on the ALi M7101 PMU + as used in the x86 Cobalt servers. - This driver does not work on all machines. In particular, early CATS - boards have hardware problems that will cause the machine to simply - lock up if the watchdog fires. + To compile this driver as a module, choose M here: the + module will be called alim7101_wdt. - "If in doubt, leave it out" - say N. + Most people will say N. -config 977_WATCHDOG - tristate "NetWinder WB83C977 watchdog" - depends on WATCHDOG && FOOTBRIDGE && ARCH_NETWINDER +config AMD7XX_TCO + tristate "AMD 766/768 TCO Timer/Watchdog" + depends on WATCHDOG && X86 && PCI help - Say Y here to include support for the WB977 watchdog included in - NetWinder machines. Alternatively say M to compile the driver as - a module, which will be called wdt977. + This is the driver for the hardware watchdog built in to the + AMD 766/768 chipsets. + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. - Not sure? It's safe to say N. + You can compile this driver directly into the kernel, or use + it as a module. The module will be called amd7xx_tco. -config SA1100_WATCHDOG - tristate "SA1100 watchdog" - depends on WATCHDOG && ARCH_SA1100 +config SC520_WDT + tristate "AMD Elan SC520 processor Watchdog" + depends on WATCHDOG && X86 help - Watchdog timer embedded into SA11x0 chips. This will reboot your - system when timeout is reached. - NOTE, that once enabled, this timer cannot be disabled. + This is the driver for the hardware watchdog built in to the + AMD "Elan" SC520 microcomputer commonly used in embedded systems. + This watchdog simply watches your kernel to make sure it doesn't + freeze, and if it does, it reboots your computer after a certain + amount of time. - To compile this driver as a module, choose M here: the - module will be called sa1100_wdt. + You can compile this driver directly into the kernel, or use + it as a module. The module will be called sc520_wdt. config EUROTECH_WDT tristate "Eurotech CPU-1220/1410 Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 help Enable support for the watchdog timer on the Eurotech CPU-1220 and CPU-1410 cards. These are PC/104 SBCs. Spec sheets and product @@ -190,7 +179,7 @@ config IB700_WDT tristate "IB700 SBC Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the IB700 Single Board Computer produced by TMC Technology (www.tmc-uk.com). This watchdog @@ -204,52 +193,60 @@ Most people will say N. -config I810_TCO - tristate "Intel i8xx TCO timer / Watchdog" - depends on WATCHDOG - ---help--- - Hardware driver for the TCO timer built into the Intel i8xx - chipset family. The TCO (Total Cost of Ownership) timer is a - watchdog timer that will reboot the machine after its second - expiration. The expiration time can be configured by commandline - argument "i810_margin=" where is the counter initial value. - It is decremented every 0.6 secs, the default is 50 which gives a - timeout of 30 seconds and one minute until reset. +config WAFER_WDT + tristate "ICP Wafer 5823 Single Board Computer Watchdog" + depends on WATCHDOG && X86 + help + This is a driver for the hardware watchdog on the ICP Wafer 5823 + Single Board Computer (and probably other similar models). + + To compile this driver as a module, choose M here: the + module will be called wafer5823wdt. + +config I8XX_TCO + tristate "Intel i8xx TCO Timer/Watchdog" + depends on WATCHDOG && (X86 || IA64) && PCI + ---help--- + Hardware driver for the TCO timer built into the Intel 82801 + I/O Controller Hub family. The TCO (Total Cost of Ownership) + timer is a watchdog timer that will reboot the machine after + its second expiration. The expiration time can be configured + with the "heartbeat" parameter. On some motherboards the driver may fail to reset the chipset's NO_REBOOT flag which prevents the watchdog from rebooting the machine. If this is the case you will get a kernel message like - "i810tco init: failed to reset NO_REBOOT flag". + "failed to reset NO_REBOOT flag, reboot disabled by hardware". To compile this driver as a module, choose M here: the - module will be called i810-tco. + module will be called i8xx_tco. -config MIXCOMWD - tristate "Mixcom Watchdog" - depends on WATCHDOG - ---help--- - This is a driver for the Mixcom hardware watchdog cards. This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. +config SC1200_WDT + tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" + depends on WATCHDOG && X86 + help + This is a driver for National Semiconductor PC87307/PC97307 hardware + watchdog cards as found on the SC1200. This watchdog is mainly used + for power management purposes and can be used to power down the device + during inactivity periods (includes interrupt activity monitoring). To compile this driver as a module, choose M here: the - module will be called mixcomwd. + module will be called sc1200wdt. Most people will say N. config SCx200_WDT - tristate "NatSemi SCx200 Watchdog" - depends on WATCHDOG + tristate "National Semiconductor SCx200 Watchdog" + depends on WATCHDOG && X86 && PCI help - Enable the built-in watchdog timer support on the National + Enable the built-in watchdog timer support on the National Semiconductor SCx200 processors. If compiled as a module, it will be called scx200_watchdog. config 60XX_WDT tristate "SBC-60XX Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 help This driver can be used with the watchdog timer found on some single board computers, namely the 6010 PII based computer. @@ -261,24 +258,17 @@ You can compile this driver directly into the kernel, or use it as a module. The module will be called sbc60xxwdt. -config W83877F_WDT - tristate "W83877F (EMACS) Watchdog Timer" - depends on WATCHDOG +config CPU5_WDT + tristate "SMA CPU5 Watchdog" + depends on WATCHDOG && X86 ---help--- - This is the driver for the hardware watchdog on the W83877F chipset - as used in EMACS PC-104 motherboards (and likely others). This - watchdog simply watches your kernel to make sure it doesn't freeze, - and if it does, it reboots your computer after a certain amount of - time. - + TBD. To compile this driver as a module, choose M here: the - module will be called w83877f_wdt. - - Most people will say N. + module will be called cpu5wdt. config W83627HF_WDT tristate "W83627HF Watchdog Timer" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- This is the driver for the hardware watchdog on the W83627HF chipset as used in Advantech PC-9578 and Tyan S2721-533 motherboards @@ -291,9 +281,24 @@ Most people will say N. +config W83877F_WDT + tristate "W83877F (EMACS) Watchdog Timer" + depends on WATCHDOG && X86 + ---help--- + This is the driver for the hardware watchdog on the W83877F chipset + as used in EMACS PC-104 motherboards (and likely others). This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. + + To compile this driver as a module, choose M here: the + module will be called w83877f_wdt. + + Most people will say N. + config MACHZ_WDT tristate "ZF MachZ Watchdog" - depends on WATCHDOG + depends on WATCHDOG && X86 ---help--- If you are using a ZF Micro MachZ processor, say Y here, otherwise N. This is the driver for the watchdog timer builtin on that @@ -304,85 +309,150 @@ To compile this driver as a module, choose M here: the module will be called machzwd. -config SC520_WDT - tristate "AMD Elan SC520 processor Watchdog" - depends on WATCHDOG - help - This is the driver for the hardware watchdog built in to the - AMD "Elan" SC520 microcomputer commonly used in embedded systems. - This watchdog simply watches your kernel to make sure it doesn't - freeze, and if it does, it reboots your computer after a certain - amount of time. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called sc520_wdt. +# MIPS Architecture -config AMD7XX_TCO - tristate "AMD 766/768 TCO Timer/Watchdog" - depends on WATCHDOG +config INDYDOG + tristate "Indy/I2 Hardware Watchdog" + depends on WATCHDOG && SGI_IP22 help - This is the driver for the hardware watchdog built in to the - AMD 766/768 chipsets. - This watchdog simply watches your kernel to make sure it doesn't - freeze, and if it does, it reboots your computer after a certain - amount of time. - - You can compile this driver directly into the kernel, or use - it as a module. The module will be called amd7xx_tco. + Hardwaredriver for the Indy's/I2's watchdog. This is a + watchdog timer that will reboot the machine after a 60 second + timer expired and no process has written to /dev/watchdog during + that time. -config ALIM7101_WDT - tristate "ALi M7101 PMU Computer Watchdog" - depends on WATCHDOG +# SUPERH Architecture + +config SH_WDT + tristate "SuperH Watchdog" + depends on WATCHDOG && SUPERH help - This is the driver for the hardware watchdog on the ALi M7101 PMU - as used in the x86 Cobalt servers. + This driver adds watchdog support for the integrated watchdog in the + SuperH processors. If you have one of these processors and wish + to have watchdog support enabled, say Y, otherwise say N. + + As a side note, saying Y here will automatically boost HZ to 1000 + so that the timer has a chance to clear the overflow counter. On + slower systems (such as the SH-2 and SH-3) this will likely yield + some performance issues. As such, the WDT should be avoided here + unless it is absolutely necessary. To compile this driver as a module, choose M here: the - module will be called alim7101_wdt. + module will be called shwdt. - Most people will say N. +# +# ISA-based Watchdog Cards +# -config ALIM1535_WDT - tristate "ALi M1535 PMU Watchdog Timer" - depends on WATCHDOG +comment "ISA-based Watchdog Cards" + depends on WATCHDOG && ISA + +config PCWATCHDOG + tristate "Berkshire Products ISA-PC Watchdog" + depends on WATCHDOG && ISA ---help--- - This is the driver for the hardware watchdog on the ALi M1535 PMU. + This is the driver for the Berkshire Products PC Watchdog card. + This card simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. This driver is like the WDT501 driver but for different + hardware. Please read . The PC + watchdog cards can be ordered from . To compile this driver as a module, choose M here: the - module will be called alim1535_wdt. + module will be called pcwd. Most people will say N. -config SC1200_WDT - tristate "National Semiconductor PC87307/PC97307 (ala SC1200) Watchdog" - depends on WATCHDOG - help - This is a driver for National Semiconductor PC87307/PC97307 hardware - watchdog cards as found on the SC1200. This watchdog is mainly used - for power management purposes and can be used to power down the device - during inactivity periods (includes interrupt activity monitoring). +config MIXCOMWD + tristate "Mixcom Watchdog" + depends on WATCHDOG && ISA + ---help--- + This is a driver for the Mixcom hardware watchdog cards. This + watchdog simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. To compile this driver as a module, choose M here: the - module will be called sc1200wdt. + module will be called mixcomwd. Most people will say N. -config WAFER_WDT - tristate "ICP Wafer 5823 Single Board Computer Watchdog" - depends on WATCHDOG +config WDT + tristate "WDT Watchdog timer" + depends on WATCHDOG && ISA + ---help--- + If you have a WDT500P or WDT501P watchdog board, say Y here, + otherwise N. It is not possible to probe for this board, which means + that you have to inform the kernel about the IO port and IRQ using + the "wdt=" kernel option (try "man bootparam" or see the + documentation of your boot loader (lilo or loadlin) about how to + pass options to the kernel at boot time). + + To compile this driver as a module, choose M here: the + module will be called wdt. + +config WDT_501 + bool "WDT501 features" + depends on WDT help - This is a driver for the hardware watchdog on the ICP Wafer 5823 - Single Board Computer (and probably other similar models). + Saying Y here and creating a character special file /dev/temperature + with major number 10 and minor number 131 ("man mknod") will give + you a thermometer inside your computer: reading from + /dev/temperature yields one byte, the temperature in degrees + Fahrenheit. This works only if you have a WDT501P watchdog board + installed. + +config WDT_501_FAN + bool "Fan Tachometer" + depends on WDT_501 + help + Enable the Fan Tachometer on the WDT501. Only do this if you have a + fan tachometer actually set up. + +# +# PCI-based Watchdog Cards +# + +comment "PCI-based Watchdog Cards" + depends on WATCHDOG && PCI + +config PCIPCWATCHDOG + tristate "Berkshire Products PCI-PC Watchdog" + depends on WATCHDOG && PCI + ---help--- + This is the driver for the Berkshire Products PCI-PC Watchdog card. + This card simply watches your kernel to make sure it doesn't freeze, + and if it does, it reboots your computer after a certain amount of + time. The card can also monitor the internal temperature of the PC. + More info is available at . To compile this driver as a module, choose M here: the - module will be called wafer5823wdt. + module will be called pcwd_pci. -config CPU5_WDT - tristate "SMA CPU5 Watchdog" - depends on WATCHDOG + Most people will say N. + +config WDTPCI + tristate "WDT PCI Watchdog timer" + depends on WATCHDOG && PCI ---help--- - TBD. + If you have a PCI WDT500/501 watchdog board, say Y here, otherwise + N. It is not possible to probe for this board, which means that you + have to inform the kernel about the IO port and IRQ using the "wdt=" + kernel option (try "man bootparam" or see the documentation of your + boot loader (lilo or loadlin) about how to pass options to the + kernel at boot time). + To compile this driver as a module, choose M here: the - module will be called cpu5wdt. + module will be called wdt_pci. + +config WDT_501_PCI + bool "WDT501-PCI features" + depends on WDTPCI + help + Saying Y here and creating a character special file /dev/temperature + with major number 10 and minor number 131 ("man mknod") will give + you a thermometer inside your computer: reading from + /dev/temperature yields one byte, the temperature in degrees + Fahrenheit. This works only if you have a WDT501P watchdog board + installed. endmenu diff -urN linux-2.6.3-rc2/drivers/char/watchdog/Makefile linux-2.6.3-rc3/drivers/char/watchdog/Makefile --- linux-2.6.3-rc2/drivers/char/watchdog/Makefile 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/Makefile 2004-02-14 19:31:03.000000000 -0800 @@ -18,7 +18,7 @@ obj-$(CONFIG_WDTPCI) += wdt_pci.o obj-$(CONFIG_21285_WATCHDOG) += wdt285.o obj-$(CONFIG_977_WATCHDOG) += wdt977.o -obj-$(CONFIG_I810_TCO) += i810-tco.o +obj-$(CONFIG_I8XX_TCO) += i8xx_tco.o obj-$(CONFIG_MACHZ_WDT) += machzwd.o obj-$(CONFIG_SH_WDT) += shwdt.o obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o @@ -33,3 +33,5 @@ obj-$(CONFIG_WAFER_WDT) += wafer5823wdt.o obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o obj-$(CONFIG_AMD7XX_TCO) += amd7xx_tco.o +obj-$(CONFIG_INDYDOG) += indydog.o +obj-$(CONFIG_PCIPCWATCHDOG) += pcwd_pci.o diff -urN linux-2.6.3-rc2/drivers/char/watchdog/acquirewdt.c linux-2.6.3-rc3/drivers/char/watchdog/acquirewdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/acquirewdt.c 2004-02-03 19:43:57.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/acquirewdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -22,6 +22,32 @@ * Can't add timeout - driver doesn't allow changing value */ +/* + * Theory of Operation: + * The Watch-Dog Timer is provided to ensure that standalone + * Systems can always recover from catastrophic conditions that + * caused the CPU to crash. This condition may have occured by + * external EMI or a software bug. When the CPU stops working + * correctly, hardware on the board will either perform a hardware + * reset (cold boot) or a non-maskable interrupt (NMI) to bring the + * system back to a known state. + * + * The Watch-Dog Timer is controlled by two I/O Ports. + * 443 hex - Read - Enable or refresh the Watch-Dog Timer + * 043 hex - Read - Disable the Watch-Dog Timer + * + * To enable the Watch-Dog Timer, a read from I/O port 443h must + * be performed. This will enable and activate the countdown timer + * which will eventually time out and either reset the CPU or cause + * an NMI depending on the setting of a jumper. To ensure that this + * reset condition does not occur, the Watch-Dog Timer must be + * periodically refreshed by reading the same I/O port 443h. + * The Watch-Dog Timer is disabled by reading I/O port 043h. + * + * The Watch-Dog Timer Time-Out Period is set via jumpers. + * It can be 1, 2, 10, 20, 110 or 220 seconds. + */ + #include #include #include @@ -39,7 +65,7 @@ #define WATCHDOG_NAME "Acquire WDT" #define PFX WATCHDOG_NAME ": " -#define WATCHDOG_TIMEOUT 0 /* ??? Is the timeout hardcoded to 1 minute ??? */ +#define WATCHDOG_HEARTBEAT 0 /* There is no way to see what the correct time-out period is */ static unsigned long acq_is_open; static char expect_close; @@ -69,7 +95,7 @@ * Kernel methods. */ -static void acq_ping(void) +static void acq_keepalive(void) { /* Write a watchdog value */ inb_p(wdt_start); @@ -111,7 +137,7 @@ } /* Well, anyhow someone wrote to us, we should return that favour */ - acq_ping(); + acq_keepalive(); } return count; } @@ -119,6 +145,7 @@ static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int options, retval = -EINVAL; static struct watchdog_info ident = { .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, @@ -136,16 +163,14 @@ return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: - acq_ping(); + acq_keepalive(); return 0; case WDIOC_GETTIMEOUT: - return put_user(WATCHDOG_TIMEOUT, (int *)arg); + return put_user(WATCHDOG_HEARTBEAT, (int *)arg); case WDIOC_SETOPTIONS: { - int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) return -EFAULT; @@ -157,7 +182,7 @@ if (options & WDIOS_ENABLECARD) { - acq_ping(); + acq_keepalive(); retval = 0; } @@ -178,7 +203,7 @@ __module_get(THIS_MODULE); /* Activate */ - acq_ping(); + acq_keepalive(); return 0; } @@ -188,7 +213,7 @@ acq_stop(); } else { printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); - acq_ping(); + acq_keepalive(); } clear_bit(0, &acq_is_open); expect_close = 0; @@ -237,8 +262,6 @@ static struct notifier_block acq_notifier = { .notifier_call = acq_notify_sys, - .next = NULL, - .priority = 0, }; static int __init acq_init(void) @@ -280,8 +303,8 @@ printk (KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout); -out: - return ret; + return 0; + unreg_reboot: unregister_reboot_notifier(&acq_notifier); unreg_regions: @@ -289,7 +312,8 @@ unreg_stop: if (wdt_stop != wdt_start) release_region(wdt_stop, 1); - goto out; +out: + return ret; } static void __exit acq_exit(void) @@ -304,6 +328,7 @@ module_init(acq_init); module_exit(acq_exit); +MODULE_AUTHOR("David Woodhouse"); +MODULE_DESCRIPTION("Acquire Inc. Single Board Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Unkown"); -MODULE_DESCRIPTION("Acquire Single Board Computer Watchdog Timer driver"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/advantechwdt.c linux-2.6.3-rc3/drivers/char/watchdog/advantechwdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/advantechwdt.c 2004-02-03 19:43:43.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/advantechwdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -334,4 +334,4 @@ MODULE_LICENSE("GPL"); MODULE_AUTHOR("Marek Michalkiewicz "); MODULE_DESCRIPTION("Advantech Single Board Computer WDT driver"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/alim1535_wdt.c linux-2.6.3-rc3/drivers/char/watchdog/alim1535_wdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/alim1535_wdt.c 2004-02-03 19:43:20.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/alim1535_wdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -463,3 +463,4 @@ MODULE_AUTHOR("Alan Cox"); MODULE_DESCRIPTION("ALi M1535 PMU Watchdog Timer driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/alim7101_wdt.c linux-2.6.3-rc3/drivers/char/watchdog/alim7101_wdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/alim7101_wdt.c 2004-02-03 19:44:14.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/alim7101_wdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -383,3 +383,4 @@ MODULE_AUTHOR("Steve Hill"); MODULE_DESCRIPTION("ALi M7101 PMU Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/amd7xx_tco.c linux-2.6.3-rc3/drivers/char/watchdog/amd7xx_tco.c --- linux-2.6.3-rc2/drivers/char/watchdog/amd7xx_tco.c 2004-02-03 19:43:18.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/amd7xx_tco.c 2004-02-14 19:31:03.000000000 -0800 @@ -390,4 +390,4 @@ MODULE_AUTHOR("Zwane Mwaikambo "); MODULE_DESCRIPTION("AMD 766/768 TCO Timer Driver"); MODULE_LICENSE("GPL"); - +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/i810-tco.c linux-2.6.3-rc3/drivers/char/watchdog/i810-tco.c --- linux-2.6.3-rc2/drivers/char/watchdog/i810-tco.c 2004-02-03 19:43:06.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/i810-tco.c 1969-12-31 16:00:00.000000000 -0800 @@ -1,437 +0,0 @@ -/* - * i810-tco 0.05: TCO timer driver for i8xx chipsets - * - * (c) Copyright 2000 kernel concepts , All Rights Reserved. - * http://www.kernelconcepts.de - * - * 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. - * - * Neither kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox - * - * The TCO timer is implemented in the following I/O controller hubs: - * (See the intel documentation on http://developer.intel.com.) - * 82801AA & 82801AB chip : document number 290655-003, 290677-004, - * 82801BA & 82801BAM chip : document number 290687-002, 298242-005, - * 82801CA & 82801CAM chip : document number 290716-001, 290718-001, - * 82801DB & 82801E chip : document number 290744-001, 273599-001, - * 82801EB & 82801ER chip : document number 252516-001 - * - * 20000710 Nils Faerber - * Initial Version 0.01 - * 20000728 Nils Faerber - * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups - * 20011214 Matt Domsch - * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT - * Didn't add timeout option as i810_margin already exists. - * 20020224 Joel Becker, Wim Van Sebroeck - * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, - * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. - * 20020412 Rob Radez , Wim Van Sebroeck - * 0.05 Fix possible timer_alive race, add expect close support, - * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and - * WDIOC_SETOPTIONS), made i810tco_getdevice __init, - * removed boot_status, removed tco_timer_read, - * added support for 82801DB and 82801E chipset, - * added support for 82801EB and 8280ER chipset, - * general cleanup. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "i810-tco.h" - - -/* Module and version information */ -#define TCO_VERSION "0.05" -#define TCO_MODULE_NAME "i810 TCO timer" -#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION - -/* Default expire timeout */ -#define TIMER_MARGIN 50 /* steps of 0.6sec, 3 0x3f || tmrval < 0x04) - return -1; - - spin_lock(&tco_lock); - val = inb (TCO1_TMR); - val &= 0xc0; - val |= tmrval; - outb (val, TCO1_TMR); - val = inb (TCO1_TMR); - spin_unlock(&tco_lock); - - if ((val & 0x3f) != tmrval) - return -1; - - return 0; -} - -/* - * Reload (trigger) the timer. Lock is needed so we don't reload it during - * a reprogramming event - */ - -static void tco_timer_reload (void) -{ - spin_lock(&tco_lock); - outb (0x01, TCO1_RLD); - spin_unlock(&tco_lock); -} - -/* - * Allow only one person to hold it open - */ - -static int i810tco_open (struct inode *inode, struct file *file) -{ - if (test_and_set_bit(0, &timer_alive)) - return -EBUSY; - - /* - * Reload and activate timer - */ - tco_timer_reload (); - tco_timer_start (); - return 0; -} - -static int i810tco_release (struct inode *inode, struct file *file) -{ - /* - * Shut off the timer. - */ - if (tco_expect_close == 42) { - tco_timer_stop (); - } else { - tco_timer_reload (); - printk(KERN_CRIT TCO_MODULE_NAME ": Unexpected close, not stopping watchdog!\n"); - } - clear_bit(0, &timer_alive); - tco_expect_close = 0; - return 0; -} - -static ssize_t i810tco_write (struct file *file, const char *data, - size_t len, loff_t * ppos) -{ - /* Can't seek (pwrite) on this device */ - if (ppos != &file->f_pos) - return -ESPIPE; - - /* See if we got the magic character 'V' and reload the timer */ - if (len) { - if (!nowayout) { - size_t i; - - /* note: just in case someone wrote the magic character - * five months ago... */ - tco_expect_close = 0; - - /* scan to see whether or not we got the magic character */ - for (i = 0; i != len; i++) { - u8 c; - if(get_user(c, data+i)) - return -EFAULT; - if (c == 'V') - tco_expect_close = 42; - } - } - - /* someone wrote to us, we should reload the timer */ - tco_timer_reload (); - } - return len; -} - -static int i810tco_ioctl (struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - int new_margin, u_margin; - int options, retval = -EINVAL; - - static struct watchdog_info ident = { - .options = WDIOF_SETTIMEOUT | - WDIOF_KEEPALIVEPING | - WDIOF_MAGICCLOSE, - .firmware_version = 0, - .identity = "i810 TCO timer", - }; - switch (cmd) { - default: - return -ENOIOCTLCMD; - case WDIOC_GETSUPPORT: - if (copy_to_user - ((struct watchdog_info *) arg, &ident, sizeof (ident))) - return -EFAULT; - return 0; - case WDIOC_GETSTATUS: - case WDIOC_GETBOOTSTATUS: - return put_user (0, (int *) arg); - case WDIOC_SETOPTIONS: - if (get_user (options, (int *) arg)) - return -EFAULT; - if (options & WDIOS_DISABLECARD) { - tco_timer_stop (); - retval = 0; - } - if (options & WDIOS_ENABLECARD) { - tco_timer_reload (); - tco_timer_start (); - retval = 0; - } - return retval; - case WDIOC_KEEPALIVE: - tco_timer_reload (); - return 0; - case WDIOC_SETTIMEOUT: - if (get_user (u_margin, (int *) arg)) - return -EFAULT; - new_margin = (u_margin * 10 + 5) / 6; - if ((new_margin < 4) || (new_margin > 63)) - return -EINVAL; - if (tco_timer_settimer ((unsigned char) new_margin)) - return -EINVAL; - i810_margin = new_margin; - tco_timer_reload (); - /* Fall */ - case WDIOC_GETTIMEOUT: - return put_user ((int)(i810_margin * 6 / 10), (int *) arg); - } -} - -/* - * Data for PCI driver interface - * - * This data only exists for exporting the supported - * PCI ids via MODULE_DEVICE_TABLE. We do not actually - * register a pci_driver, because someone else might one day - * want to register another driver on the same PCI id. - */ -static struct pci_device_id i810tco_pci_tbl[] = { - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, - { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, - { 0, }, -}; -MODULE_DEVICE_TABLE (pci, i810tco_pci_tbl); - -static struct pci_dev *i810tco_pci; - -static unsigned char __init i810tco_getdevice (void) -{ - struct pci_dev *dev = NULL; - u8 val1, val2; - u16 badr; - /* - * Find the PCI device - */ - - while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { - if (pci_match_device(i810tco_pci_tbl, dev)) { - i810tco_pci = dev; - break; - } - } - - if (i810tco_pci) { - /* - * Find the ACPI base I/O address which is the base - * for the TCO registers (TCOBASE=ACPIBASE + 0x60) - * ACPIBASE is bits [15:7] from 0x40-0x43 - */ - pci_read_config_byte (i810tco_pci, 0x40, &val1); - pci_read_config_byte (i810tco_pci, 0x41, &val2); - badr = ((val2 << 1) | (val1 >> 7)) << 7; - ACPIBASE = badr; - /* Something's wrong here, ACPIBASE has to be set */ - if (badr == 0x0001 || badr == 0x0000) { - printk (KERN_ERR TCO_MODULE_NAME " init: failed to get TCOBASE address\n"); - return 0; - } - /* - * Check chipset's NO_REBOOT bit - */ - pci_read_config_byte (i810tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - val1 &= 0xfd; - pci_write_config_byte (i810tco_pci, 0xd4, val1); - pci_read_config_byte (i810tco_pci, 0xd4, &val1); - if (val1 & 0x02) { - printk (KERN_ERR TCO_MODULE_NAME " init: failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); - return 0; /* Cannot reset NO_REBOOT bit */ - } - } - /* Set the TCO_EN bit in SMI_EN register */ - val1 = inb (SMI_EN + 1); - val1 &= 0xdf; - outb (val1, SMI_EN + 1); - /* Clear out the (probably old) status */ - outb (0, TCO1_STS); - outb (3, TCO2_STS); - return 1; - } - return 0; -} - -static struct file_operations i810tco_fops = { - .owner = THIS_MODULE, - .write = i810tco_write, - .ioctl = i810tco_ioctl, - .open = i810tco_open, - .release = i810tco_release, -}; - -static struct miscdevice i810tco_miscdev = { - .minor = WATCHDOG_MINOR, - .name = "watchdog", - .fops = &i810tco_fops, -}; - -static int __init watchdog_init (void) -{ - spin_lock_init(&tco_lock); - if (!i810tco_getdevice () || i810tco_pci == NULL) - return -ENODEV; - if (!request_region (TCOBASE, 0x10, "i810 TCO")) { - printk (KERN_ERR TCO_MODULE_NAME - ": I/O address 0x%04x already in use\n", - TCOBASE); - return -EIO; - } - if (misc_register (&i810tco_miscdev) != 0) { - release_region (TCOBASE, 0x10); - printk (KERN_ERR TCO_MODULE_NAME ": cannot register miscdev\n"); - return -EIO; - } - tco_timer_settimer ((unsigned char) i810_margin); - tco_timer_reload (); - - printk (KERN_INFO TCO_DRIVER_NAME - ": timer margin: %d sec (0x%04x) (nowayout=%d)\n", - (int) (i810_margin * 6 / 10), TCOBASE, nowayout); - return 0; -} - -static void __exit watchdog_cleanup (void) -{ - u8 val; - - /* Reset the timer before we leave */ - tco_timer_reload (); - /* Set the NO_REBOOT bit to prevent later reboots, just for sure */ - pci_read_config_byte (i810tco_pci, 0xd4, &val); - val |= 0x02; - pci_write_config_byte (i810tco_pci, 0xd4, val); - release_region (TCOBASE, 0x10); - misc_deregister (&i810tco_miscdev); -} - -module_init(watchdog_init); -module_exit(watchdog_cleanup); - -MODULE_AUTHOR("Nils Faerber"); -MODULE_DESCRIPTION("TCO timer driver for i8xx chipsets"); -MODULE_LICENSE("GPL"); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/i810-tco.h linux-2.6.3-rc3/drivers/char/watchdog/i810-tco.h --- linux-2.6.3-rc2/drivers/char/watchdog/i810-tco.h 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/i810-tco.h 1969-12-31 16:00:00.000000000 -0800 @@ -1,42 +0,0 @@ -/* - * i810-tco: TCO timer driver for i8xx chipsets - * - * (c) Copyright 2000 kernel concepts , All Rights Reserved. - * http://www.kernelconcepts.de - * - * 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. - * - * Neither kernel concepts nor Nils Faerber admit liability nor provide - * warranty for any of this software. This material is provided - * "AS-IS" and at no charge. - * - * (c) Copyright 2000 kernel concepts - * developed for - * Jentro AG, Haar/Munich (Germany) - * - * TCO timer driver for i8xx chipsets - * based on softdog.c by Alan Cox - * - * For history and the complete list of supported I/O Controller Hub's - * see i810-tco.c - */ - - -/* - * Some address definitions for the i810 TCO - */ - -#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ -#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ -#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ -#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ -#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ -#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ -#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ -#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ -#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ - -#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff -urN linux-2.6.3-rc2/drivers/char/watchdog/i8xx_tco.c linux-2.6.3-rc3/drivers/char/watchdog/i8xx_tco.c --- linux-2.6.3-rc2/drivers/char/watchdog/i8xx_tco.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/i8xx_tco.c 2004-02-14 19:31:03.000000000 -0800 @@ -0,0 +1,510 @@ +/* + * i8xx_tco 0.06: TCO timer driver for i8xx chipsets + * + * (c) Copyright 2000 kernel concepts , All Rights Reserved. + * http://www.kernelconcepts.de + * + * 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. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * The TCO timer is implemented in the following I/O controller hubs: + * (See the intel documentation on http://developer.intel.com.) + * 82801AA & 82801AB chip : document number 290655-003, 290677-004, + * 82801BA & 82801BAM chip : document number 290687-002, 298242-005, + * 82801CA & 82801CAM chip : document number 290716-001, 290718-001, + * 82801DB & 82801E chip : document number 290744-001, 273599-001, + * 82801EB & 82801ER chip : document number 252516-001 + * + * 20000710 Nils Faerber + * Initial Version 0.01 + * 20000728 Nils Faerber + * 0.02 Fix for SMI_EN->TCO_EN bit, some cleanups + * 20011214 Matt Domsch + * 0.03 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT + * Didn't add timeout option as i810_margin already exists. + * 20020224 Joel Becker, Wim Van Sebroeck + * 0.04 Support for 82801CA(M) chipset, timer margin needs to be > 3, + * add support for WDIOC_SETTIMEOUT and WDIOC_GETTIMEOUT. + * 20020412 Rob Radez , Wim Van Sebroeck + * 0.05 Fix possible timer_alive race, add expect close support, + * clean up ioctls (WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS and + * WDIOC_SETOPTIONS), made i810tco_getdevice __init, + * removed boot_status, removed tco_timer_read, + * added support for 82801DB and 82801E chipset, + * added support for 82801EB and 8280ER chipset, + * general cleanup. + * 20030921 Wim Van Sebroeck + * 0.06 change i810_margin to heartbeat, use module_param, + * added notify system support, renamed module to i8xx_tco. + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "i8xx_tco.h" + +/* Module and version information */ +#define TCO_VERSION "0.06" +#define TCO_MODULE_NAME "i8xx TCO timer" +#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION +#define PFX TCO_MODULE_NAME ": " + +/* internal variables */ +static unsigned int ACPIBASE; +static spinlock_t tco_lock; /* Guards the hardware */ +static unsigned long timer_alive; +static char tco_expect_close; +static struct pci_dev *i8xx_tco_pci; + +/* module parameters */ +#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (2 0x3f || tmrval < 0x04) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + spin_lock(&tco_lock); + val = inb (TCO1_TMR); + val &= 0xc0; + val |= tmrval; + outb (val, TCO1_TMR); + val = inb (TCO1_TMR); + spin_unlock(&tco_lock); + + if ((val & 0x3f) != tmrval) + return -EINVAL; + + heartbeat = t; + return 0; +} + +/* + * /dev/watchdog handling + */ + +static int i8xx_tco_open (struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &timer_alive)) + return -EBUSY; + + /* + * Reload and activate timer + */ + tco_timer_keepalive (); + tco_timer_start (); + return 0; +} + +static int i8xx_tco_release (struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + if (tco_expect_close == 42) { + tco_timer_stop (); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + tco_timer_keepalive (); + } + clear_bit(0, &timer_alive); + tco_expect_close = 0; + return 0; +} + +static ssize_t i8xx_tco_write (struct file *file, const char *data, + size_t len, loff_t * ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + tco_expect_close = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + tco_expect_close = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + tco_timer_keepalive (); + } + return len; +} + +static int i8xx_tco_ioctl (struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + int new_options, retval = -EINVAL; + int new_heartbeat; + static struct watchdog_info ident = { + .options = WDIOF_SETTIMEOUT | + WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = TCO_MODULE_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *) arg, &ident, + sizeof (ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + case WDIOC_GETBOOTSTATUS: + return put_user (0, (int *) arg); + + case WDIOC_KEEPALIVE: + tco_timer_keepalive (); + return 0; + + case WDIOC_SETOPTIONS: + { + if (get_user (new_options, (int *) arg)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + tco_timer_stop (); + retval = 0; + } + + if (new_options & WDIOS_ENABLECARD) { + tco_timer_keepalive (); + tco_timer_start (); + retval = 0; + } + + return retval; + } + + case WDIOC_SETTIMEOUT: + { + if (get_user(new_heartbeat, (int *) arg)) + return -EFAULT; + + if (tco_timer_set_heartbeat(new_heartbeat)) + return -EINVAL; + + tco_timer_keepalive (); + /* Fall */ + } + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, (int *)arg); + + default: + return -ENOIOCTLCMD; + } +} + +/* + * Notify system + */ + +static int i8xx_tco_notify_sys (struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + tco_timer_stop (); + } + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations i8xx_tco_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = i8xx_tco_write, + .ioctl = i8xx_tco_ioctl, + .open = i8xx_tco_open, + .release = i8xx_tco_release, +}; + +static struct miscdevice i8xx_tco_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &i8xx_tco_fops, +}; + +static struct notifier_block i8xx_tco_notifier = { + .notifier_call = i8xx_tco_notify_sys, +}; + +/* + * Data for PCI driver interface + * + * This data only exists for exporting the supported + * PCI ids via MODULE_DEVICE_TABLE. We do not actually + * register a pci_driver, because someone else might one day + * want to register another driver on the same PCI id. + */ +static struct pci_device_id i8xx_tco_pci_tbl[] = { + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_10, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801E_0, PCI_ANY_ID, PCI_ANY_ID, }, + { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0, PCI_ANY_ID, PCI_ANY_ID, }, + { 0, }, /* End of list */ +}; +MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); + +/* + * Init & exit routines + */ + +static unsigned char __init i8xx_tco_getdevice (void) +{ + struct pci_dev *dev = NULL; + u8 val1, val2; + u16 badr; + /* + * Find the PCI device + */ + + while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { + if (pci_match_device(i8xx_tco_pci_tbl, dev)) { + i8xx_tco_pci = dev; + break; + } + } + + if (i8xx_tco_pci) { + /* + * Find the ACPI base I/O address which is the base + * for the TCO registers (TCOBASE=ACPIBASE + 0x60) + * ACPIBASE is bits [15:7] from 0x40-0x43 + */ + pci_read_config_byte (i8xx_tco_pci, 0x40, &val1); + pci_read_config_byte (i8xx_tco_pci, 0x41, &val2); + badr = ((val2 << 1) | (val1 >> 7)) << 7; + ACPIBASE = badr; + /* Something's wrong here, ACPIBASE has to be set */ + if (badr == 0x0001 || badr == 0x0000) { + printk (KERN_ERR PFX "failed to get TCOBASE address\n"); + return 0; + } + /* + * Check chipset's NO_REBOOT bit + */ + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + val1 &= 0xfd; + pci_write_config_byte (i8xx_tco_pci, 0xd4, val1); + pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); + if (val1 & 0x02) { + printk (KERN_ERR PFX "failed to reset NO_REBOOT flag, reboot disabled by hardware\n"); + return 0; /* Cannot reset NO_REBOOT bit */ + } + } + /* Set the TCO_EN bit in SMI_EN register */ + val1 = inb (SMI_EN + 1); + val1 &= 0xdf; + outb (val1, SMI_EN + 1); + /* Clear out the (probably old) status */ + outb (0, TCO1_STS); + outb (3, TCO2_STS); + return 1; + } + return 0; +} + +static int __init watchdog_init (void) +{ + int ret; + + spin_lock_init(&tco_lock); + + /* Check whether or not the hardware watchdog is there */ + if (!i8xx_tco_getdevice () || i8xx_tco_pci == NULL) + return -ENODEV; + + if (!request_region (TCOBASE, 0x10, "i8xx TCO")) { + printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", + TCOBASE); + ret = -EIO; + goto out; + } + + /* Check that the heartbeat value is within it's range ; if not reset to the default */ + if (tco_timer_set_heartbeat (heartbeat)) { + heartbeat = WATCHDOG_HEARTBEAT; + tco_timer_set_heartbeat (heartbeat); + printk(KERN_INFO PFX "heartbeat value must be 2, All Rights Reserved. + * http://www.kernelconcepts.de + * + * 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. + * + * Neither kernel concepts nor Nils Faerber admit liability nor provide + * warranty for any of this software. This material is provided + * "AS-IS" and at no charge. + * + * (c) Copyright 2000 kernel concepts + * developed for + * Jentro AG, Haar/Munich (Germany) + * + * TCO timer driver for i8xx chipsets + * based on softdog.c by Alan Cox + * + * For history and the complete list of supported I/O Controller Hub's + * see i8xx_tco.c + */ + + +/* + * Some address definitions for the TCO + */ + +#define TCOBASE ACPIBASE + 0x60 /* TCO base address */ +#define TCO1_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ +#define TCO1_TMR TCOBASE + 0x01 /* TCO Timer Initial Value */ +#define TCO1_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ +#define TCO1_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ +#define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ +#define TCO2_STS TCOBASE + 0x06 /* TCO2 Status Register */ +#define TCO1_CNT TCOBASE + 0x08 /* TCO1 Control Register */ +#define TCO2_CNT TCOBASE + 0x0a /* TCO2 Control Register */ + +#define SMI_EN ACPIBASE + 0x30 /* SMI Control and Enable Register */ diff -urN linux-2.6.3-rc2/drivers/char/watchdog/indydog.c linux-2.6.3-rc3/drivers/char/watchdog/indydog.c --- linux-2.6.3-rc2/drivers/char/watchdog/indydog.c 2004-02-03 19:44:44.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/indydog.c 2004-02-14 19:31:03.000000000 -0800 @@ -1,5 +1,5 @@ /* - * IndyDog 0.2 A Hardware Watchdog Device for SGI IP22 + * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22 * * (c) Copyright 2002 Guido Guenther , All Rights Reserved. * @@ -19,11 +19,16 @@ #include #include #include +#include +#include #include #include #include #include +#define PFX "indydog: " +#define WATCHDOG_HEARTBEAT 60 + static unsigned long indydog_alive; static struct sgimc_misc_ctrl *mcmisc_regs; static char expect_close; @@ -37,11 +42,30 @@ module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); -static void indydog_ping() +static void indydog_start(void) { - mcmisc_regs->watchdogt = 0; + u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; + + mc_ctrl0 |= SGIMC_CCTRL0_WDOG; + mcmisc_regs->cpuctrl0 = mc_ctrl0; + + printk(KERN_INFO PFX "Started watchdog timer.\n"); } +static void indydog_stop(void) +{ + u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; + + mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; + mcmisc_regs->cpuctrl0 = mc_ctrl0; + + printk(KERN_INFO PFX "Stopped watchdog timer.\n"); +} + +static void indydog_ping(void) +{ + mcmisc_regs->watchdogt = 0; +} /* * Allow only one person to hold it open @@ -49,8 +73,6 @@ static int indydog_open(struct inode *inode, struct file *file) { - u32 mc_ctrl0; - if( test_and_set_bit(0,&indydog_alive) ) return -EBUSY; @@ -60,13 +82,9 @@ /* * Activate timer */ - mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); - - mc_ctrl0 = mcmisc_regs->cpuctrl0 | SGIMC_CCTRL0_WDOG; - mcmisc_regs->cpuctrl0 = mc_ctrl0; + indydog_start(); indydog_ping(); - printk("Started watchdog timer.\n"); return 0; } @@ -78,12 +96,10 @@ */ if (expect_close == 42) { - u32 mc_ctrl0 = mcmisc_regs->cpuctrl0; - mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; - mcmisc_regs->cpuctrl0 = mc_ctrl0; - printk("Stopped watchdog timer.\n"); + indydog_stop(); } else { - printk(KERN_CRIT "WDT device closed unexpectedly. WDT will not stop!\n"); + printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); + indydog_ping(); } clear_bit(0,&indydog_alive); expect_close = 0; @@ -121,9 +137,12 @@ static int indydog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { + int options, retval = -EINVAL; static struct watchdog_info ident = { - .options = WDIOF_MAGICCLOSE, - .identity = "Hardware Watchdog for SGI IP22", + .options = WDIOF_KEEPALIVEPING | + WDIOF_MAGICCLOSE, + .firmware_version = 0, + .identity = "Hardware Watchdog for SGI IP22", }; switch (cmd) { @@ -139,9 +158,40 @@ case WDIOC_KEEPALIVE: indydog_ping(); return 0; + case WDIOC_GETTIMEOUT: + return put_user(WATCHDOG_TIMEOUT,(int *)arg); + case WDIOC_SETOPTIONS: + { + if (get_user(options, (int *)arg)) + return -EFAULT; + + if (options & WDIOS_DISABLECARD) + { + indydog_stop(); + retval = 0; + } + + if (options & WDIOS_ENABLECARD) + { + indydog_start(); + retval = 0; + } + + return retval; + } } } +static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + indydog_stop(); + } + + return NOTIFY_DONE; +} + static struct file_operations indydog_fops = { .owner = THIS_MODULE, .write = indydog_write, @@ -156,16 +206,32 @@ .fops = &indydog_fops, }; -static char banner[] __initdata = KERN_INFO "Hardware Watchdog Timer for SGI IP22: 0.2\n"; +static struct notifier_block indydog_notifier = { + .notifier_call = indydog_notify_sys, +}; + +static char banner[] __initdata = KERN_INFO PFX "Hardware Watchdog Timer for SGI IP22: 0.3\n"; static int __init watchdog_init(void) { int ret; - ret = misc_register(&indydog_miscdev); + mcmisc_regs = (struct sgimc_misc_ctrl *)(KSEG1+0x1fa00000); + + ret = register_reboot_notifier(&indydog_notifier); + if (ret) { + printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", + ret); + return ret; + } - if (ret) + ret = misc_register(&indydog_miscdev); + if (ret) { + printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", + WATCHDOG_MINOR, ret); + unregister_reboot_notifier(&indydog_notifier); return ret; + } printk(banner); @@ -175,8 +241,13 @@ static void __exit watchdog_exit(void) { misc_deregister(&indydog_miscdev); + unregister_reboot_notifier(&indydog_notifier); } module_init(watchdog_init); module_exit(watchdog_exit); + +MODULE_AUTHOR("Guido Guenther "); +MODULE_DESCRIPTION("Hardware Watchdog Device for SGI IP22"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/pcwd_pci.c linux-2.6.3-rc3/drivers/char/watchdog/pcwd_pci.c --- linux-2.6.3-rc2/drivers/char/watchdog/pcwd_pci.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/pcwd_pci.c 2004-02-14 19:31:03.000000000 -0800 @@ -0,0 +1,681 @@ +/* + * Berkshire PCI-PC Watchdog Card Driver + * + * (c) Copyright 2003 Wim Van Sebroeck . + * + * Based on source code of the following authors: + * Ken Hollis , + * Lindsay Harris , + * Alan Cox , + * Matt Domsch , + * Rob Radez + * + * 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. + * + * Neither Wim Van Sebroeck nor Iguana vzw. admit liability nor + * provide warranty for any of this software. This material is + * provided "AS-IS" and at no charge. + */ + +/* + * A bells and whistles driver is available from http://www.pcwd.de/ + * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ + */ + +/* + * Includes, defines, variables, module parameters, ... + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* Module and version information */ +#define WATCHDOG_VERSION "1.00" +#define WATCHDOG_DATE "09/02/2004" +#define WATCHDOG_DRIVER_NAME "PCI-PC Watchdog" +#define WATCHDOG_NAME "pcwd_pci" +#define PFX WATCHDOG_NAME ": " +#define DRIVER_VERSION WATCHDOG_DRIVER_NAME " driver, v" WATCHDOG_VERSION " (" WATCHDOG_DATE ")\n" + +/* Stuff for the PCI ID's */ +#ifndef PCI_VENDOR_ID_QUICKLOGIC +#define PCI_VENDOR_ID_QUICKLOGIC 0x11e3 +#endif + +#ifndef PCI_DEVICE_ID_WATCHDOG_PCIPCWD +#define PCI_DEVICE_ID_WATCHDOG_PCIPCWD 0x5030 +#endif + +/* + * These are the defines that describe the control status bits for the + * PCI-PC Watchdog card. + */ +#define WD_PCI_WTRP 0x01 /* Watchdog Trip status */ +#define WD_PCI_HRBT 0x02 /* Watchdog Heartbeat */ +#define WD_PCI_TTRP 0x04 /* Temperature Trip status */ + +/* according to documentation max. time to process a command for the pci + watchdog card is 100 ms, so we give it 150 ms to do it's job */ +#define PCI_COMMAND_TIMEOUT 150 + +/* Watchdog's internal commands */ +#define CMD_GET_STATUS 0x04 +#define CMD_GET_FIRMWARE_VERSION 0x08 +#define CMD_READ_WATCHDOG_TIMEOUT 0x18 +#define CMD_WRITE_WATCHDOG_TIMEOUT 0x19 + +/* internal variables */ +static int temp_panic; +static unsigned long is_active; +static char expect_release; +static struct { + int supports_temp; /* Wether or not the card has a temperature device */ + int boot_status; /* The card's boot status */ + unsigned long io_addr; /* The cards I/O address */ + spinlock_t io_lock; + struct pci_dev *pdev; +} pcipcwd_private; + +/* module parameters */ +#define WATCHDOG_HEARTBEAT 2 /* 2 sec default heartbeat */ +static int heartbeat = WATCHDOG_HEARTBEAT; +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0 0xFFFF)) + return -EINVAL; + + /* Write new heartbeat to watchdog */ + send_command(CMD_WRITE_WATCHDOG_TIMEOUT, &t_msb, &t_lsb); + + heartbeat = t; + return 0; +} + +static int pcipcwd_get_status(int *status) +{ + int new_status; + + *status=0; + new_status = inb_p(pcipcwd_private.io_addr + 1); + if (new_status & WD_PCI_WTRP) + *status |= WDIOF_CARDRESET; + if (new_status & WD_PCI_TTRP) { + *status |= WDIOF_OVERHEAT; + if (temp_panic) + panic(PFX "Temperature overheat trip!\n"); + } + + return 0; +} + +static int pcipcwd_clear_status(void) +{ + outb_p(0x01, pcipcwd_private.io_addr + 1); + return 0; +} + +static int pcipcwd_get_temperature(int *temperature) +{ + *temperature = 0; + if (!pcipcwd_private.supports_temp) + return -ENODEV; + + /* + * Convert celsius to fahrenheit, since this was + * the decided 'standard' for this return value. + */ + *temperature = ((inb_p(pcipcwd_private.io_addr)) * 9 / 5) + 32; + + return 0; +} + +/* + * /dev/watchdog handling + */ + +static ssize_t pcipcwd_write(struct file *file, const char *data, + size_t len, loff_t *ppos) +{ + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + /* See if we got the magic character 'V' and reload the timer */ + if (len) { + if (!nowayout) { + size_t i; + + /* note: just in case someone wrote the magic character + * five months ago... */ + expect_release = 0; + + /* scan to see whether or not we got the magic character */ + for (i = 0; i != len; i++) { + char c; + if(get_user(c, data+i)) + return -EFAULT; + if (c == 'V') + expect_release = 42; + } + } + + /* someone wrote to us, we should reload the timer */ + pcipcwd_keepalive(); + } + return len; +} + +static int pcipcwd_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + static struct watchdog_info ident = { + .options = WDIOF_OVERHEAT | + WDIOF_CARDRESET | + WDIOF_KEEPALIVEPING | + WDIOF_SETTIMEOUT | + WDIOF_MAGICCLOSE, + .firmware_version = 1, + .identity = WATCHDOG_DRIVER_NAME, + }; + + switch (cmd) { + case WDIOC_GETSUPPORT: + return copy_to_user((struct watchdog_info *) arg, &ident, + sizeof (ident)) ? -EFAULT : 0; + + case WDIOC_GETSTATUS: + { + int status; + + pcipcwd_get_status(&status); + + return put_user(status, (int *) arg); + } + + case WDIOC_GETBOOTSTATUS: + return put_user(pcipcwd_private.boot_status, (int *) arg); + + case WDIOC_GETTEMP: + { + int temperature; + + if (pcipcwd_get_temperature(&temperature)) + return -EFAULT; + + return put_user(temperature, (int *) arg); + } + + case WDIOC_KEEPALIVE: + pcipcwd_keepalive(); + return 0; + + case WDIOC_SETOPTIONS: + { + int new_options, retval = -EINVAL; + + if (get_user (new_options, (int *) arg)) + return -EFAULT; + + if (new_options & WDIOS_DISABLECARD) { + pcipcwd_stop(); + retval = 0; + } + + if (new_options & WDIOS_ENABLECARD) { + pcipcwd_start(); + retval = 0; + } + + if (new_options & WDIOS_TEMPPANIC) { + temp_panic = 1; + retval = 0; + } + + return retval; + } + + case WDIOC_SETTIMEOUT: + { + int new_heartbeat; + + if (get_user(new_heartbeat, (int *) arg)) + return -EFAULT; + + if (pcipcwd_set_heartbeat(new_heartbeat)) + return -EINVAL; + + pcipcwd_keepalive(); + /* Fall */ + } + + case WDIOC_GETTIMEOUT: + return put_user(heartbeat, (int *)arg); + + default: + return -ENOIOCTLCMD; + } +} + +static int pcipcwd_open(struct inode *inode, struct file *file) +{ + /* /dev/watchdog can only be opened once */ + if (test_and_set_bit(0, &is_active)) + return -EBUSY; + + /* Activate */ + pcipcwd_start(); + pcipcwd_keepalive(); + return 0; +} + +static int pcipcwd_release(struct inode *inode, struct file *file) +{ + /* + * Shut off the timer. + */ + if (expect_release == 42) { + pcipcwd_stop(); + } else { + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + pcipcwd_keepalive(); + } + clear_bit(0, &is_active); + expect_release = 0; + return 0; +} + +/* + * /dev/temperature handling + */ + +static ssize_t pcipcwd_temp_read(struct file *file, char *data, + size_t len, loff_t *ppos) +{ + int temperature; + + /* Can't seek (pwrite) on this device */ + if (ppos != &file->f_pos) + return -ESPIPE; + + if (pcipcwd_get_temperature(&temperature)) + return -EFAULT; + + if (copy_to_user (data, &temperature, 1)) + return -EFAULT; + + return 1; +} + +static int pcipcwd_temp_open(struct inode *inode, struct file *file) +{ + if (!pcipcwd_private.supports_temp) + return -ENODEV; + + return 0; +} + +static int pcipcwd_temp_release(struct inode *inode, struct file *file) +{ + return 0; +} + +/* + * Notify system + */ + +static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) +{ + if (code==SYS_DOWN || code==SYS_HALT) { + /* Turn the WDT off */ + pcipcwd_stop(); + } + + return NOTIFY_DONE; +} + +/* + * Kernel Interfaces + */ + +static struct file_operations pcipcwd_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .write = pcipcwd_write, + .ioctl = pcipcwd_ioctl, + .open = pcipcwd_open, + .release = pcipcwd_release, +}; + +static struct miscdevice pcipcwd_miscdev = { + .minor = WATCHDOG_MINOR, + .name = "watchdog", + .fops = &pcipcwd_fops, +}; + +static struct file_operations pcipcwd_temp_fops = { + .owner = THIS_MODULE, + .llseek = no_llseek, + .read = pcipcwd_temp_read, + .open = pcipcwd_temp_open, + .release = pcipcwd_temp_release, +}; + +static struct miscdevice pcipcwd_temp_miscdev = { + .minor = TEMP_MINOR, + .name = "temperature", + .fops = &pcipcwd_temp_fops, +}; + +static struct notifier_block pcipcwd_notifier = { + .notifier_call = pcipcwd_notify_sys, +}; + +/* + * Init & exit routines + */ + +static inline void check_temperature_support(void) +{ + if (inb_p(pcipcwd_private.io_addr) != 0xF0) + pcipcwd_private.supports_temp = 1; +} + +static int __devinit pcipcwd_card_init(struct pci_dev *pdev, + const struct pci_device_id *ent) +{ + static int cards_found; + int ret = -EIO; + int got_fw_rev, fw_rev_major, fw_rev_minor; + char fw_ver_str[20]; + char option_switches; + + cards_found++; + if (cards_found == 1) + printk(KERN_INFO PFX DRIVER_VERSION); + + if (cards_found > 1) { + printk(KERN_ERR PFX "This driver only supports 1 device\n"); + return -ENODEV; + } + + if (pci_enable_device(pdev)) { + printk(KERN_ERR PFX "Not possible to enable PCI Device\n"); + return -ENODEV; + } + + if (pci_resource_start(pdev, 0) == 0x0000) { + printk(KERN_ERR PFX "No I/O-Address for card detected\n"); + return -ENODEV; + } + + pcipcwd_private.pdev = pdev; + pcipcwd_private.io_addr = pci_resource_start(pdev, 0); + + if (pci_request_regions(pdev, WATCHDOG_NAME)) { + printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", + (int) pcipcwd_private.io_addr); + ret = -EIO; + goto err_out_disable_device; + } + + /* get the boot_status */ + pcipcwd_get_status(&pcipcwd_private.boot_status); + + /* clear the "card caused reboot" flag */ + pcipcwd_clear_status(); + + /* disable card */ + pcipcwd_stop(); + + /* Check whether or not the card supports the temperature device */ + check_temperature_support(); + + /* Get the Firmware Version */ + got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); + if (got_fw_rev) { + sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); + } else { + sprintf(fw_ver_str, ""); + } + + /* Get switch settings */ + option_switches = inb_p(pcipcwd_private.io_addr + 3); + + printk(KERN_INFO PFX "Found card at port 0x%04x (Firmware: %s) %s temp option\n", + (int) pcipcwd_private.io_addr, fw_ver_str, + (pcipcwd_private.supports_temp ? "with" : "without")); + + printk(KERN_INFO PFX "Option switches (0x%02x): Temperature Reset Enable=%s, Power On Delay=%s\n", + option_switches, + ((option_switches & 0x10) ? "ON" : "OFF"), + ((option_switches & 0x08) ? "ON" : "OFF")); + + if (pcipcwd_private.boot_status & WDIOF_CARDRESET) + printk(KERN_INFO PFX "Previous reset was caused by the Watchdog card\n"); + + if (pcipcwd_private.boot_status & WDIOF_OVERHEAT) + printk(KERN_INFO PFX "Card sensed a CPU Overheat\n"); + + if (pcipcwd_private.boot_status == 0) + printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); + + /* Check that the heartbeat value is within it's range ; if not reset to the default */ + if (heartbeat < 1 || heartbeat > 0xFFFF) { + heartbeat = WATCHDOG_HEARTBEAT; + printk(KERN_INFO PFX "heartbeat value must be 0"); +MODULE_DESCRIPTION("Berkshire PCI-PC Watchdog driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); +MODULE_ALIAS_MISCDEV(TEMP_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/sbc60xxwdt.c linux-2.6.3-rc3/drivers/char/watchdog/sbc60xxwdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/sbc60xxwdt.c 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/sbc60xxwdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -412,3 +412,4 @@ MODULE_AUTHOR("Jakob Oestergaard "); MODULE_DESCRIPTION("60xx Single Board Computer Watchdog Timer driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/sc520_wdt.c linux-2.6.3-rc3/drivers/char/watchdog/sc520_wdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/sc520_wdt.c 2004-02-03 19:43:46.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/sc520_wdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -447,3 +447,4 @@ MODULE_AUTHOR("Scott and Bill Jennings"); MODULE_DESCRIPTION("Driver for watchdog timer in AMD \"Elan\" SC520 uProcessor"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/scx200_wdt.c linux-2.6.3-rc3/drivers/char/watchdog/scx200_wdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/scx200_wdt.c 2004-02-03 19:44:04.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/scx200_wdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -36,6 +36,7 @@ MODULE_AUTHOR("Christer Weinigel "); MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); #ifndef CONFIG_WATCHDOG_NOWAYOUT #define CONFIG_WATCHDOG_NOWAYOUT 0 diff -urN linux-2.6.3-rc2/drivers/char/watchdog/shwdt.c linux-2.6.3-rc3/drivers/char/watchdog/shwdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/shwdt.c 2004-02-03 19:43:37.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/shwdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -33,6 +33,8 @@ #include #include +#define PFX "shwdt: " + /* * Default clock division ratio is 5.25 msecs. For an additional table of * values, consult the asm-sh/watchdog.h. Overload this at module load @@ -70,7 +72,9 @@ static char shwdt_expect_close; static struct timer_list timer; static unsigned long next_heartbeat; -static int heartbeat = 30; + +#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ +static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ #ifdef CONFIG_WATCHDOG_NOWAYOUT static int nowayout = 1; @@ -87,8 +91,8 @@ { __u8 csr; - mod_timer(&timer, next_ping_period(clock_division_ratio)); next_heartbeat = jiffies + (heartbeat * HZ); + mod_timer(&timer, next_ping_period(clock_division_ratio)); csr = sh_wdt_read_csr(); csr |= WTCSR_WT | clock_division_ratio; @@ -142,6 +146,30 @@ } /** + * sh_wdt_keepalive - Keep the Userspace Watchdog Alive + * + * The Userspace watchdog got a KeepAlive: schedule the next heartbeat. + */ +static void sh_wdt_keepalive(void) +{ + next_heartbeat = jiffies + (heartbeat * HZ); +} + +/** + * sh_wdt_set_heartbeat - Set the Userspace Watchdog heartbeat + * + * Set the Userspace Watchdog heartbeat + */ +static int sh_wdt_set_heartbeat(int t) +{ + if ((t < 1) || (t > 3600)) /* arbitrary upper limit */ + return -EINVAL; + + heartbeat = t; + return 0; +} + +/** * sh_wdt_ping - Ping the Watchdog * * @data: Unused @@ -160,6 +188,8 @@ sh_wdt_write_cnt(0); mod_timer(&timer, next_ping_period(clock_division_ratio)); + } else { + printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); } } @@ -193,11 +223,11 @@ */ static int sh_wdt_close(struct inode *inode, struct file *file) { - if (!nowayout && shwdt_expect_close == 42) { + if (shwdt_expect_close == 42) { sh_wdt_stop(); } else { - printk(KERN_CRIT "shwdt: Unexpected close, not stopping watchdog!\n"); - next_heartbeat = jiffies + (heartbeat * HZ); + printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); + sh_wdt_keepalive(); } clear_bit(0, &shwdt_is_open); @@ -224,18 +254,20 @@ return -ESPIPE; if (count) { - size_t i; + if (!nowayout) { + size_t i; - shwdt_expect_close = 0; + shwdt_expect_close = 0; - for (i = 0; i != count; i++) { - char c; - if (get_user(c, buf + i)) - return -EFAULT; - if (c == 'V') - shwdt_expect_close = 42; + for (i = 0; i != count; i++) { + char c; + if (get_user(c, buf + i)) + return -EFAULT; + if (c == 'V') + shwdt_expect_close = 42; + } } - next_heartbeat = jiffies + (heartbeat * HZ); + sh_wdt_keepalive(); } return count; @@ -255,38 +287,32 @@ static int sh_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) { - int new_timeout; + int new_heartbeat; + int options, retval = -EINVAL; switch (cmd) { case WDIOC_GETSUPPORT: - if (copy_to_user((struct watchdog_info *)arg, + return copy_to_user((struct watchdog_info *)arg, &sh_wdt_info, - sizeof(sh_wdt_info))) { - return -EFAULT; - } - - break; + sizeof(sh_wdt_info)) ? -EFAULT : 0; case WDIOC_GETSTATUS: case WDIOC_GETBOOTSTATUS: return put_user(0, (int *)arg); case WDIOC_KEEPALIVE: - next_heartbeat = jiffies + (heartbeat * HZ); - - break; + sh_wdt_keepalive(); + return 0; case WDIOC_SETTIMEOUT: - if (get_user(new_timeout, (int *)arg)) + if (get_user(new_heartbeat, (int *)arg)) return -EFAULT; - if (new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ + + if (sh_wdt_set_heartbeat(new_heartbeat)) return -EINVAL; - heartbeat = new_timeout; - next_heartbeat = jiffies + (heartbeat * HZ); + + sh_wdt_keepalive(); /* Fall */ case WDIOC_GETTIMEOUT: return put_user(heartbeat, (int *)arg); case WDIOC_SETOPTIONS: - { - int options, retval = -EINVAL; - if (get_user(options, (int *)arg)) return -EFAULT; @@ -301,7 +327,6 @@ } return retval; - } default: return -ENOIOCTLCMD; } @@ -346,7 +371,6 @@ static struct notifier_block sh_wdt_notifier = { .notifier_call = sh_wdt_notify_sys, - .priority = 0, }; static struct miscdevice sh_wdt_miscdev = { @@ -363,21 +387,42 @@ */ static int __init sh_wdt_init(void) { - if (misc_register(&sh_wdt_miscdev)) { - printk(KERN_ERR "shwdt: Can't register misc device\n"); - return -EINVAL; + int rc; + + if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) { + clock_division_ratio = WTCSR_CKS_4096; + printk(KERN_INFO PFX "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", + clock_division_ratio); } - if (register_reboot_notifier(&sh_wdt_notifier)) { - printk(KERN_ERR "shwdt: Can't register reboot notifier\n"); - misc_deregister(&sh_wdt_miscdev); - return -EINVAL; + if (sh_wdt_set_heartbeat(heartbeat)) + { + heartbeat = WATCHDOG_HEARTBEAT; + printk(KERN_INFO PFX "heartbeat value must be 1<=x<=3600, using %d\n", + heartbeat); } init_timer(&timer); timer.function = sh_wdt_ping; timer.data = 0; + rc = register_reboot_notifier(&sh_wdt_notifier); + if (rc) { + printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", rc); + return rc; + } + + rc = misc_register(&sh_wdt_miscdev) + if (rc) { + printk(KERN_ERR PFX "Can't register miscdev on minor=%d (err=%d)\n", + sh_wdt_miscdev.minor, rc); + unregister_reboot_notifier(&sh_wdt_notifier); + return rc; + } + + printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", + heartbeat, nowayout); + return 0; } @@ -389,17 +434,21 @@ */ static void __exit sh_wdt_exit(void) { - unregister_reboot_notifier(&sh_wdt_notifier); misc_deregister(&sh_wdt_miscdev); + unregister_reboot_notifier(&sh_wdt_notifier); } MODULE_AUTHOR("Paul Mundt "); MODULE_DESCRIPTION("SuperH watchdog driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); module_param(clock_division_ratio, int, 0); MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). Defaults to 0x7."); +module_param(heartbeat, int, 0); +MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); + module_param(nowayout, int, 0); MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/softdog.c linux-2.6.3-rc3/drivers/char/watchdog/softdog.c --- linux-2.6.3-rc2/drivers/char/watchdog/softdog.c 2004-02-03 19:43:43.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/softdog.c 2004-02-14 19:31:03.000000000 -0800 @@ -231,3 +231,8 @@ module_init(watchdog_init); module_exit(watchdog_exit); + +MODULE_AUTHOR("Alan Cox"); +MODULE_DESCRIPTION("Software Watchdog Device Driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); diff -urN linux-2.6.3-rc2/drivers/char/watchdog/wafer5823wdt.c linux-2.6.3-rc3/drivers/char/watchdog/wafer5823wdt.c --- linux-2.6.3-rc2/drivers/char/watchdog/wafer5823wdt.c 2004-02-03 19:44:44.000000000 -0800 +++ linux-2.6.3-rc3/drivers/char/watchdog/wafer5823wdt.c 2004-02-14 19:31:03.000000000 -0800 @@ -330,5 +330,6 @@ MODULE_AUTHOR("Justin Cormack"); MODULE_DESCRIPTION("ICP Wafer 5823 Single Board Computer WDT driver"); MODULE_LICENSE("GPL"); +MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); /* end of wafer5823wdt.c */ diff -urN linux-2.6.3-rc2/drivers/cpufreq/cpufreq_userspace.c linux-2.6.3-rc3/drivers/cpufreq/cpufreq_userspace.c --- linux-2.6.3-rc2/drivers/cpufreq/cpufreq_userspace.c 2004-02-03 19:43:11.000000000 -0800 +++ linux-2.6.3-rc3/drivers/cpufreq/cpufreq_userspace.c 2004-02-14 19:31:03.000000000 -0800 @@ -2,7 +2,7 @@ * linux/drivers/cpufreq/cpufreq_userspace.c * * Copyright (C) 2001 Russell King - * (C) 2002 - 2003 Dominik Brodowski + * (C) 2002 - 2004 Dominik Brodowski * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -112,7 +112,14 @@ if (freq > cpu_max_freq[cpu]) freq = cpu_max_freq[cpu]; - ret = cpufreq_driver_target(¤t_policy[cpu], freq, + /* + * We're safe from concurrent calls to ->target() here + * as we hold the userspace_sem lock. If we were calling + * cpufreq_driver_target, a deadlock situation might occur: + * A: cpufreq_set (lock userspace_sem) -> cpufreq_driver_target(lock policy->lock) + * B: cpufreq_set_policy(lock policy->lock) -> __cpufreq_governor -> cpufreq_governor_userspace (lock userspace_sem) + */ + ret = __cpufreq_driver_target(¤t_policy[cpu], freq, CPUFREQ_RELATION_L); err: diff -urN linux-2.6.3-rc2/drivers/i2c/busses/i2c-keywest.c linux-2.6.3-rc3/drivers/i2c/busses/i2c-keywest.c --- linux-2.6.3-rc2/drivers/i2c/busses/i2c-keywest.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/i2c/busses/i2c-keywest.c 2004-02-14 19:31:03.000000000 -0800 @@ -74,14 +74,7 @@ #include "i2c-keywest.h" -/* Currently, we don't deal with the weird interrupt cascade of the G5 - * machines with the ppc64 kernel, so use Polled mode on these - */ -#ifdef CONFIG_PPC64 -#define POLLED_MODE -#else #undef POLLED_MODE -#endif /* Some debug macros */ #define WRONG_STATE(name) do {\ diff -urN linux-2.6.3-rc2/drivers/ide/ppc/pmac.c linux-2.6.3-rc3/drivers/ide/ppc/pmac.c --- linux-2.6.3-rc2/drivers/ide/ppc/pmac.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/ide/ppc/pmac.c 2004-02-14 19:31:03.000000000 -0800 @@ -39,13 +39,16 @@ #include #include #include -#include #include #include #include #include #include +#ifndef CONFIG_PPC64 +#include +#endif + #include "ide-timing.h" extern void ide_do_request(ide_hwgroup_t *hwgroup, int masked_irq); @@ -1183,6 +1186,7 @@ /* Make sure we have sane timings */ sanitize_timings(pmif); +#ifndef CONFIG_PPC64 /* XXX FIXME: Media bay stuff need re-organizing */ if (np->parent && np->parent->name && strcasecmp(np->parent->name, "media-bay") == 0) { @@ -1198,7 +1202,9 @@ * units, I keep the old way */ ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, 0, 1); - } else { + } else +#endif + { /* This is necessary to enable IDE when net-booting */ ppc_md.feature_call(PMAC_FTR_IDE_RESET, np, pmif->aapl_bus_id, 1); ppc_md.feature_call(PMAC_FTR_IDE_ENABLE, np, pmif->aapl_bus_id, 1); @@ -1238,9 +1244,9 @@ hwif->led_act = pmu_hd_kick_blink; #endif - printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s\n", - hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, - pmif->mediabay ? " (mediabay)" : ""); + printk(KERN_INFO "ide%d: Found Apple %s controller, bus ID %d%s, irq %d\n", + hwif->index, model_name[pmif->kind], pmif->aapl_bus_id, + pmif->mediabay ? " (mediabay)" : "", hwif->irq); #ifdef CONFIG_PMAC_PBOOK if (pmif->mediabay && check_media_bay_by_base(pmif->regbase, MB_CD) == 0) @@ -1447,7 +1453,12 @@ #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC pmif->dma_regs = (volatile struct dbdma_regs*)(base + 0x1000); #endif /* CONFIG_BLK_DEV_IDEDMA_PMAC */ - pmif->irq = pdev->irq; + + /* We use the OF node irq mapping */ + if (np->n_intrs == 0) + pmif->irq = pdev->irq; + else + pmif->irq = np->intrs[0].line; pci_set_drvdata(pdev, hwif); diff -urN linux-2.6.3-rc2/drivers/macintosh/Kconfig linux-2.6.3-rc3/drivers/macintosh/Kconfig --- linux-2.6.3-rc2/drivers/macintosh/Kconfig 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/macintosh/Kconfig 2004-02-14 19:31:03.000000000 -0800 @@ -4,7 +4,7 @@ # we want to change this to something like CONFIG_SYSCTRL_CUDA/PMU config ADB_CUDA bool "Support for CUDA based PowerMacs" - depends on PPC_PMAC && !POWER4 + depends on PPC_PMAC && !PPC_PMAC64 help This provides support for CUDA based Power Macintosh systems. This includes most OldWorld PowerMacs, the first generation iMacs, the @@ -69,7 +69,7 @@ config MAC_FLOPPY bool "Support for PowerMac floppy" - depends on PPC_PMAC && !POWER4 + depends on PPC_PMAC && !PPC_PMAC64 help If you have a SWIM-3 (Super Woz Integrated Machine 3; from Apple) floppy controller, say Y here. Most commonly found in PowerMacs. @@ -93,7 +93,7 @@ config ADB_MACIO bool "Include MacIO (CHRP) ADB driver" - depends on ADB && !POWER4 + depends on ADB && PPC_PMAC && !PPC_PMAC64 help Say Y here to include direct support for the ADB controller in the Hydra chip used on PowerPC Macintoshes of the CHRP type. (The Hydra @@ -129,14 +129,14 @@ config THERM_WINDTUNNEL tristate "Support for thermal management on Windtunnel G4s" - depends on I2C && I2C_KEYWEST && !POWER4 + depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 help This driver provides some thermostat and fan control for the desktop G4 "Windtunnel" config THERM_ADT7467 tristate "Support for thermal mgmnt on laptops with ADT 7467 chipset" - depends on I2C && I2C_KEYWEST && !POWER4 + depends on I2C && I2C_KEYWEST && PPC_PMAC && !PPC_PMAC64 help This driver provides some thermostat and fan control for the iBook G4, and the ATI based aluminium PowerBooks, allowing slighlty @@ -144,7 +144,7 @@ config THERM_PM72 tristate "Support for thermal management on PowerMac G5" - depends on I2C && I2C_KEYWEST && POWER4 + depends on I2C && I2C_KEYWEST && PPC_PMAC64 help This driver provides thermostat and fan control for the desktop G5 machines. diff -urN linux-2.6.3-rc2/drivers/macintosh/adb.c linux-2.6.3-rc3/drivers/macintosh/adb.c --- linux-2.6.3-rc2/drivers/macintosh/adb.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/macintosh/adb.c 2004-02-14 19:31:03.000000000 -0800 @@ -40,9 +40,9 @@ #include #ifdef CONFIG_PPC #include -#include #endif + EXPORT_SYMBOL(adb_controller); EXPORT_SYMBOL(adb_client_list); @@ -290,7 +290,7 @@ struct adb_driver *driver; int i; -#ifdef CONFIG_PPC +#ifdef CONFIG_PPC32 if ( (_machine != _MACH_chrp) && (_machine != _MACH_Pmac) ) return 0; #endif diff -urN linux-2.6.3-rc2/drivers/macintosh/macio_asic.c linux-2.6.3-rc3/drivers/macintosh/macio_asic.c --- linux-2.6.3-rc2/drivers/macintosh/macio_asic.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/macintosh/macio_asic.c 2004-02-14 19:31:03.000000000 -0800 @@ -539,6 +539,9 @@ if (np == NULL) return -ENODEV; + /* This assumption is wrong, fix that here for now until I fix the arch */ + of_node_get(np); + /* We also assume that pmac_feature will have done a get() on nodes stored * in the macio chips array */ diff -urN linux-2.6.3-rc2/drivers/macintosh/via-pmu.c linux-2.6.3-rc3/drivers/macintosh/via-pmu.c --- linux-2.6.3-rc2/drivers/macintosh/via-pmu.c 2004-02-14 19:30:52.000000000 -0800 +++ linux-2.6.3-rc3/drivers/macintosh/via-pmu.c 2004-02-14 19:31:03.000000000 -0800 @@ -57,7 +57,6 @@ #include #include #include -#include #ifdef CONFIG_PMAC_BACKLIGHT #include #endif @@ -374,7 +373,9 @@ printk(KERN_INFO "PMU driver %d initialized for %s, firmware: %02x\n", PMU_DRIVER_VERSION, pbook_type[pmu_kind], pmu_version); +#ifndef CONFIG_PPC64 sys_ctrler = SYS_CTRLER_PMU; +#endif return 1; } @@ -459,7 +460,9 @@ if (vias == NULL) return -ENODEV; +#ifndef CONFIG_PPC64 request_OF_resource(vias, 0, NULL); +#endif #ifdef CONFIG_PMAC_BACKLIGHT /* Enable backlight */ register_backlight_controller(&pmu_backlight_controller, NULL, "pmu"); @@ -590,6 +593,7 @@ return pmu_kind; } +#ifndef CONFIG_PPC64 static inline void wakeup_decrementer(void) { set_dec(tb_ticks_per_jiffy); @@ -598,6 +602,7 @@ */ last_jiffy_stamp(0) = tb_last_stamp = get_tbl(); } +#endif static void pmu_set_server_mode(int server_mode) { @@ -1389,7 +1394,7 @@ } pmu_done(req); } else { -#ifdef CONFIG_XMON +#if defined(CONFIG_XMON) && !defined(CONFIG_PPC64) if (len == 4 && data[1] == 0x2c) { extern int xmon_wants_key, xmon_adb_keycode; if (xmon_wants_key) { @@ -1397,7 +1402,7 @@ return; } } -#endif /* CONFIG_XMON */ +#endif /* defined(CONFIG_XMON) && !defined(CONFIG_PPC64) */ #ifdef CONFIG_ADB /* * XXX On the [23]400 the PMU gives us an up diff -urN linux-2.6.3-rc2/drivers/md/dm.c linux-2.6.3-rc3/drivers/md/dm.c --- linux-2.6.3-rc2/drivers/md/dm.c 2004-02-03 19:44:17.000000000 -0800 +++ linux-2.6.3-rc3/drivers/md/dm.c 2004-02-14 19:31:03.000000000 -0800 @@ -674,7 +674,7 @@ bdev = bdget_disk(disk, 0); if (bdev) { down(&bdev->bd_inode->i_sem); - i_size_write(bdev->bd_inode, size << SECTOR_SHIFT); + i_size_write(bdev->bd_inode, (loff_t)size << SECTOR_SHIFT); up(&bdev->bd_inode->i_sem); bdput(bdev); } diff -urN linux-2.6.3-rc2/drivers/pci/pci-sysfs.c linux-2.6.3-rc3/drivers/pci/pci-sysfs.c --- linux-2.6.3-rc2/drivers/pci/pci-sysfs.c 2004-02-03 19:43:56.000000000 -0800 +++ linux-2.6.3-rc3/drivers/pci/pci-sysfs.c 2004-02-14 19:31:08.000000000 -0800 @@ -180,4 +180,7 @@ device_create_file (dev, &dev_attr_irq); device_create_file (dev, &dev_attr_resource); sysfs_create_bin_file(&dev->kobj, &pci_config_attr); + + /* add platform-specific attributes */ + pcibios_add_platform_entries(pdev); } diff -urN linux-2.6.3-rc2/drivers/scsi/BusLogic.c linux-2.6.3-rc3/drivers/scsi/BusLogic.c --- linux-2.6.3-rc2/drivers/scsi/BusLogic.c 2004-02-14 19:30:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/BusLogic.c 2004-02-14 19:31:08.000000000 -0800 @@ -467,8 +467,8 @@ while (--TimeoutCounter >= 0) { StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.HostAdapterReady && - !StatusRegister.CommandParameterRegisterBusy) + if (StatusRegister.sr.HostAdapterReady && + !StatusRegister.sr.CommandParameterRegisterBusy) break; udelay(100); } @@ -504,10 +504,10 @@ udelay(100); InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister.CommandComplete) break; + if (InterruptRegister.ir.CommandComplete) break; if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister.DataInRegisterReady) break; - if (StatusRegister.CommandParameterRegisterBusy) continue; + if (StatusRegister.sr.DataInRegisterReady) break; + if (StatusRegister.sr.CommandParameterRegisterBusy) continue; BusLogic_WriteCommandParameterRegister(HostAdapter, *ParameterPointer++); ParameterLength--; } @@ -524,7 +524,7 @@ if (OperationCode == BusLogic_ModifyIOAddress) { StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.CommandInvalid) + if (StatusRegister.sr.CommandInvalid) { BusLogic_CommandFailureReason = "Modify I/O Address Invalid"; Result = -1; @@ -562,16 +562,16 @@ { InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (InterruptRegister.CommandComplete) break; + if (InterruptRegister.ir.CommandComplete) break; if (HostAdapter->HostAdapterCommandCompleted) break; - if (StatusRegister.DataInRegisterReady) + if (StatusRegister.sr.DataInRegisterReady) { if (++ReplyBytes <= ReplyLength) *ReplyPointer++ = BusLogic_ReadDataInRegister(HostAdapter); else BusLogic_ReadDataInRegister(HostAdapter); } if (OperationCode == BusLogic_FetchHostAdapterLocalRAM && - StatusRegister.HostAdapterReady) break; + StatusRegister.sr.HostAdapterReady) break; udelay(100); } if (TimeoutCounter < 0) @@ -602,7 +602,7 @@ /* Process Command Invalid conditions. */ - if (StatusRegister.CommandInvalid) + if (StatusRegister.sr.CommandInvalid) { /* Some early BusLogic Host Adapters may not recover properly from @@ -614,14 +614,14 @@ */ udelay(1000); StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.CommandInvalid || - StatusRegister.Reserved || - StatusRegister.DataInRegisterReady || - StatusRegister.CommandParameterRegisterBusy || - !StatusRegister.HostAdapterReady || - !StatusRegister.InitializationRequired || - StatusRegister.DiagnosticActive || - StatusRegister.DiagnosticFailure) + if (StatusRegister.sr.CommandInvalid || + StatusRegister.sr.Reserved || + StatusRegister.sr.DataInRegisterReady || + StatusRegister.sr.CommandParameterRegisterBusy || + !StatusRegister.sr.HostAdapterReady || + !StatusRegister.sr.InitializationRequired || + StatusRegister.sr.DiagnosticActive || + StatusRegister.sr.DiagnosticFailure) { BusLogic_SoftReset(HostAdapter); udelay(1000); @@ -1333,11 +1333,11 @@ HostAdapter->IO_Address, StatusRegister.All, InterruptRegister.All, GeometryRegister.All); if (StatusRegister.All == 0 || - StatusRegister.DiagnosticActive || - StatusRegister.CommandParameterRegisterBusy || - StatusRegister.Reserved || - StatusRegister.CommandInvalid || - InterruptRegister.Reserved != 0) + StatusRegister.sr.DiagnosticActive || + StatusRegister.sr.CommandParameterRegisterBusy || + StatusRegister.sr.Reserved || + StatusRegister.sr.CommandInvalid || + InterruptRegister.ir.Reserved != 0) return false; /* Check the undocumented Geometry Register to test if there is an I/O port @@ -1405,7 +1405,7 @@ while (--TimeoutCounter >= 0) { StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.DiagnosticActive) break; + if (StatusRegister.sr.DiagnosticActive) break; udelay(100); } if (BusLogic_GlobalOptions.TraceHardwareReset) @@ -1426,7 +1426,7 @@ while (--TimeoutCounter >= 0) { StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (!StatusRegister.DiagnosticActive) break; + if (!StatusRegister.sr.DiagnosticActive) break; udelay(100); } if (BusLogic_GlobalOptions.TraceHardwareReset) @@ -1442,9 +1442,9 @@ while (--TimeoutCounter >= 0) { StatusRegister.All = BusLogic_ReadStatusRegister(HostAdapter); - if (StatusRegister.DiagnosticFailure || - StatusRegister.HostAdapterReady || - StatusRegister.DataInRegisterReady) + if (StatusRegister.sr.DiagnosticFailure || + StatusRegister.sr.HostAdapterReady || + StatusRegister.sr.DataInRegisterReady) break; udelay(100); } @@ -1458,14 +1458,14 @@ error occurred during the Host Adapter diagnostics. If Data In Register Ready is set, then there is an Error Code available. */ - if (StatusRegister.DiagnosticFailure || - !StatusRegister.HostAdapterReady) + if (StatusRegister.sr.DiagnosticFailure || + !StatusRegister.sr.HostAdapterReady) { BusLogic_CommandFailureReason = NULL; BusLogic_Failure(HostAdapter, "HARD RESET DIAGNOSTICS"); BusLogic_Error("HOST ADAPTER STATUS REGISTER = %02X\n", HostAdapter, StatusRegister.All); - if (StatusRegister.DataInRegisterReady) + if (StatusRegister.sr.DataInRegisterReady) { unsigned char ErrorCode = BusLogic_ReadDataInRegister(HostAdapter); BusLogic_Error("HOST ADAPTER ERROR CODE = %d\n", @@ -1756,7 +1756,7 @@ */ GeometryRegister.All = BusLogic_ReadGeometryRegister(HostAdapter); HostAdapter->ExtendedTranslationEnabled = - GeometryRegister.ExtendedTranslationEnabled; + GeometryRegister.gr.ExtendedTranslationEnabled; /* Save the Scatter Gather Limits, Level Sensitive Interrupt flag, Wide SCSI flag, Differential SCSI flag, SCAM Supported flag, and @@ -3184,7 +3184,7 @@ Read the Host Adapter Interrupt Register. */ InterruptRegister.All = BusLogic_ReadInterruptRegister(HostAdapter); - if (InterruptRegister.InterruptValid) + if (InterruptRegister.ir.InterruptValid) { /* Acknowledge the interrupt and reset the Host Adapter @@ -3197,11 +3197,11 @@ and Outgoing Mailbox Available Interrupts are ignored, as they are never enabled. */ - if (InterruptRegister.ExternalBusReset) + if (InterruptRegister.ir.ExternalBusReset) HostAdapter->HostAdapterExternalReset = true; - else if (InterruptRegister.IncomingMailboxLoaded) + else if (InterruptRegister.ir.IncomingMailboxLoaded) BusLogic_ScanIncomingMailboxes(HostAdapter); - else if (InterruptRegister.CommandComplete) + else if (InterruptRegister.ir.CommandComplete) HostAdapter->HostAdapterCommandCompleted = true; } } diff -urN linux-2.6.3-rc2/drivers/scsi/BusLogic.h linux-2.6.3-rc3/drivers/scsi/BusLogic.h --- linux-2.6.3-rc2/drivers/scsi/BusLogic.h 2004-02-14 19:30:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/BusLogic.h 2004-02-14 19:31:08.000000000 -0800 @@ -344,7 +344,7 @@ boolean InterruptReset:1; /* Bit 5 */ boolean SoftReset:1; /* Bit 6 */ boolean HardReset:1; /* Bit 7 */ - }; + } cr; }; /* @@ -363,7 +363,7 @@ boolean InitializationRequired:1; /* Bit 5 */ boolean DiagnosticFailure:1; /* Bit 6 */ boolean DiagnosticActive:1; /* Bit 7 */ - }; + } sr; }; /* @@ -380,7 +380,7 @@ boolean ExternalBusReset:1; /* Bit 3 */ unsigned char Reserved:3; /* Bits 4-6 */ boolean InterruptValid:1; /* Bit 7 */ - }; + } ir; }; /* @@ -395,7 +395,7 @@ enum BusLogic_BIOS_DiskGeometryTranslation Drive1Geometry:2;/* Bits 2-3 */ unsigned char :3; /* Bits 4-6 */ boolean ExtendedTranslationEnabled:1; /* Bit 7 */ - }; + } gr; }; /* @@ -1272,7 +1272,7 @@ { union BusLogic_ControlRegister ControlRegister; ControlRegister.All = 0; - ControlRegister.SCSIBusReset = true; + ControlRegister.cr.SCSIBusReset = true; outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } @@ -1281,7 +1281,7 @@ { union BusLogic_ControlRegister ControlRegister; ControlRegister.All = 0; - ControlRegister.InterruptReset = true; + ControlRegister.cr.InterruptReset = true; outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } @@ -1290,7 +1290,7 @@ { union BusLogic_ControlRegister ControlRegister; ControlRegister.All = 0; - ControlRegister.SoftReset = true; + ControlRegister.cr.SoftReset = true; outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } @@ -1299,7 +1299,7 @@ { union BusLogic_ControlRegister ControlRegister; ControlRegister.All = 0; - ControlRegister.HardReset = true; + ControlRegister.cr.HardReset = true; outb(ControlRegister.All, HostAdapter->IO_Address + BusLogic_ControlRegisterOffset); } diff -urN linux-2.6.3-rc2/drivers/scsi/ata_piix.c linux-2.6.3-rc3/drivers/scsi/ata_piix.c --- linux-2.6.3-rc2/drivers/scsi/ata_piix.c 2004-02-03 19:43:47.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/ata_piix.c 2004-02-14 19:31:08.000000000 -0800 @@ -3,8 +3,8 @@ ata_piix.c - Intel PATA/SATA controllers - Copyright 2003 Red Hat Inc - Copyright 2003 Jeff Garzik + Copyright 2003-2004 Red Hat Inc + Copyright 2003-2004 Jeff Garzik Copyright header from piix.c: @@ -28,7 +28,7 @@ #include #define DRV_NAME "ata_piix" -#define DRV_VERSION "0.95" +#define DRV_VERSION "1.00" enum { PIIX_IOCFG = 0x54, /* IDE I/O configuration register */ diff -urN linux-2.6.3-rc2/drivers/scsi/libata-core.c linux-2.6.3-rc3/drivers/scsi/libata-core.c --- linux-2.6.3-rc2/drivers/scsi/libata-core.c 2004-02-14 19:30:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/libata-core.c 2004-02-14 19:31:09.000000000 -0800 @@ -1,8 +1,8 @@ /* libata-core.c - helper library for ATA - Copyright 2003 Red Hat, Inc. All rights reserved. - Copyright 2003 Jeff Garzik + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik The contents of this file are subject to the Open Software License version 1.1 that can be found at diff -urN linux-2.6.3-rc2/drivers/scsi/libata-scsi.c linux-2.6.3-rc3/drivers/scsi/libata-scsi.c --- linux-2.6.3-rc2/drivers/scsi/libata-scsi.c 2004-02-03 19:43:43.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/libata-scsi.c 2004-02-14 19:31:09.000000000 -0800 @@ -1,8 +1,8 @@ /* libata-scsi.c - helper library for ATA - Copyright 2003 Red Hat, Inc. All rights reserved. - Copyright 2003 Jeff Garzik + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik The contents of this file are subject to the Open Software License version 1.1 that can be found at diff -urN linux-2.6.3-rc2/drivers/scsi/libata.h linux-2.6.3-rc3/drivers/scsi/libata.h --- linux-2.6.3-rc2/drivers/scsi/libata.h 2004-02-03 19:43:17.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/libata.h 2004-02-14 19:31:09.000000000 -0800 @@ -1,8 +1,8 @@ /* libata.h - helper library for ATA - Copyright 2003 Red Hat, Inc. All rights reserved. - Copyright 2003 Jeff Garzik + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik The contents of this file are subject to the Open Software License version 1.1 that can be found at @@ -26,7 +26,7 @@ #define __LIBATA_H__ #define DRV_NAME "libata" -#define DRV_VERSION "0.81" /* must be exactly four chars */ +#define DRV_VERSION "1.00" /* must be exactly four chars */ struct ata_scsi_args { struct ata_port *ap; diff -urN linux-2.6.3-rc2/drivers/scsi/sata_promise.c linux-2.6.3-rc3/drivers/scsi/sata_promise.c --- linux-2.6.3-rc2/drivers/scsi/sata_promise.c 2004-02-03 19:44:05.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/sata_promise.c 2004-02-14 19:31:09.000000000 -0800 @@ -1,7 +1,7 @@ /* * sata_promise.c - Promise SATA * - * Copyright 2003 Red Hat, Inc. + * Copyright 2003-2004 Red Hat, Inc. * * The contents of this file are subject to the Open * Software License version 1.1 that can be found at diff -urN linux-2.6.3-rc2/drivers/scsi/sata_via.c linux-2.6.3-rc3/drivers/scsi/sata_via.c --- linux-2.6.3-rc2/drivers/scsi/sata_via.c 2004-02-03 19:43:15.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/sata_via.c 2004-02-14 19:31:09.000000000 -0800 @@ -1,8 +1,8 @@ /* sata_via.c - VIA Serial ATA controllers - Copyright 2003 Red Hat, Inc. All rights reserved. - Copyright 2003 Jeff Garzik + Copyright 2003-2004 Red Hat, Inc. All rights reserved. + Copyright 2003-2004 Jeff Garzik The contents of this file are subject to the Open Software License version 1.1 that can be found at diff -urN linux-2.6.3-rc2/drivers/scsi/sr.c linux-2.6.3-rc3/drivers/scsi/sr.c --- linux-2.6.3-rc2/drivers/scsi/sr.c 2004-02-14 19:30:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/scsi/sr.c 2004-02-14 19:31:09.000000000 -0800 @@ -798,10 +798,9 @@ if ((buffer[n + 2] & 0x8) == 0) /* not a DVD drive */ cd->cdi.mask |= CDC_DVD; - if ((buffer[n + 3] & 0x20) == 0) { + if ((buffer[n + 3] & 0x20) == 0) /* can't write DVD-RAM media */ cd->cdi.mask |= CDC_DVD_RAM; - } else if ((buffer[n + 3] & 0x10) == 0) /* can't write DVD-R media */ cd->cdi.mask |= CDC_DVD_R; diff -urN linux-2.6.3-rc2/drivers/serial/8250.c linux-2.6.3-rc3/drivers/serial/8250.c --- linux-2.6.3-rc2/drivers/serial/8250.c 2004-02-03 19:43:07.000000000 -0800 +++ linux-2.6.3-rc3/drivers/serial/8250.c 2004-02-14 19:31:09.000000000 -0800 @@ -1976,6 +1976,8 @@ if (co->index >= UART_NR) co->index = 0; port = &serial8250_ports[co->index].port; + if (port->type == PORT_UNKNOWN) + return -ENODEV; /* * Temporary fix. @@ -2007,6 +2009,14 @@ } console_initcall(serial8250_console_init); +static int __init serial8250_late_console_init(void) +{ + if (!(serial8250_console.flags & CON_ENABLED)) + register_console(&serial8250_console); + return 0; +} +late_initcall(serial8250_late_console_init); + #define SERIAL8250_CONSOLE &serial8250_console #else #define SERIAL8250_CONSOLE NULL diff -urN linux-2.6.3-rc2/drivers/serial/pmac_zilog.c linux-2.6.3-rc3/drivers/serial/pmac_zilog.c --- linux-2.6.3-rc2/drivers/serial/pmac_zilog.c 2004-02-14 19:30:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/serial/pmac_zilog.c 2004-02-14 19:31:09.000000000 -0800 @@ -59,7 +59,6 @@ #include #include #include -#include #include #include @@ -68,6 +67,10 @@ #include "pmac_zilog.h" +#if defined(CONFIG_SERIAL_PMACZILOG_CONSOLE) && defined(CONFIG_PPC64) +#define HAS_SCCDBG +extern int sccdbg; +#endif /* Not yet implemented */ #undef HAS_DBDMA @@ -170,7 +173,6 @@ */ static void pmz_maybe_update_regs(struct uart_pmac_port *up) { -#if 1 if (!ZS_REGS_HELD(up)) { if (ZS_TX_ACTIVE(up)) { up->flags |= PMACZILOG_FLAG_REGS_HELD; @@ -179,10 +181,6 @@ pmz_load_zsregs(up, up->curregs); } } -#else - pr_debug("pmz: maybe_update_regs: updating\n"); - pmz_load_zsregs(up, up->curregs); -#endif } static void pmz_receive_chars(struct uart_pmac_port *up, struct pt_regs *regs) @@ -205,22 +203,18 @@ zssync(up); } - ch = read_zsreg(up, R0); - - /* This funny hack depends upon BRK_ABRT not interfering - * with the other bits we care about in R1. - */ - if (ch & BRK_ABRT) - r1 |= BRK_ABRT; - ch = read_zsdata(up); ch &= up->parity_mask; + if (ch == 0 && up->prev_status & BRK_ABRT) { + r1 |= BRK_ABRT; + printk("rx break\n"); + } /* A real serial line, record the character and status. */ *tty->flip.char_buf_ptr = ch; *tty->flip.flag_buf_ptr = TTY_NORMAL; up->port.icount.rx++; - if (r1 & (BRK_ABRT | PAR_ERR | Rx_OVR | CRC_ERR)) { + if (r1 & (PAR_ERR | Rx_OVR | CRC_ERR | BRK_ABRT)) { if (r1 & BRK_ABRT) { r1 &= ~(PAR_ERR | CRC_ERR); up->port.icount.brk++; @@ -274,6 +268,15 @@ write_zsreg(up, R0, RES_EXT_INT); zssync(up); +#ifdef HAS_SCCDBG + if (sccdbg && (status & BRK_ABRT) && !(up->prev_status & BRK_ABRT)) { +#ifdef CONFIG_XMON + extern void xmon(struct pt_regs *); + xmon(regs); +#endif + } +#endif /* HAS_SCCDBG */ + if (ZS_WANTS_MODEM_STATUS(up)) { if (status & SYNC_HUNT) up->port.icount.dsr++; @@ -383,10 +386,10 @@ write_zsreg(up_a, R0, RES_H_IUS); zssync(up_a); pr_debug("pmz: irq channel A: %x\n", r3); - if (r3 & CHARxIP) - pmz_receive_chars(up_a, regs); if (r3 & CHAEXT) pmz_status_handle(up_a, regs); + if (r3 & CHARxIP) + pmz_receive_chars(up_a, regs); if (r3 & CHATxIP) pmz_transmit_chars(up_a); rc = IRQ_HANDLED; @@ -398,10 +401,10 @@ write_zsreg(up_b, R0, RES_H_IUS); zssync(up_b); pr_debug("pmz: irq channel B: %x\n", r3); - if (r3 & CHBRxIP) - pmz_receive_chars(up_b, regs); if (r3 & CHBEXT) pmz_status_handle(up_b, regs); + if (r3 & CHBRxIP) + pmz_receive_chars(up_b, regs); if (r3 & CHBTxIP) pmz_transmit_chars(up_b); rc = IRQ_HANDLED; @@ -575,15 +578,12 @@ /* * Enable modem status change interrupts - * The port lock is not held. + * The port lock is held. */ static void pmz_enable_ms(struct uart_port *port) { struct uart_pmac_port *up = to_pmz(port); unsigned char new_reg; - unsigned long flags; - - spin_lock_irqsave(&port->lock, flags); new_reg = up->curregs[R15] | (DCDIE | SYNCIE | CTSIE); if (new_reg != up->curregs[R15]) { @@ -592,8 +592,6 @@ /* NOTE: Not subject to 'transmitter active' rule. */ write_zsreg(up, R15, up->curregs[R15]); } - - spin_unlock_irqrestore(&port->lock, flags); } /* @@ -765,7 +763,7 @@ up->curregs[R9] |= NV | MIE; up->curregs[R1] |= EXT_INT_ENAB | INT_ALL_Rx | TxINT_ENAB; - // pmz_maybe_update_regs(up); + pmz_maybe_update_regs(up); return pwr_delay; } @@ -1051,10 +1049,13 @@ pmz_convert_to_zs(up, termios->c_cflag, termios->c_iflag, baud); - if (UART_ENABLE_MS(&up->port, termios->c_cflag)) + if (UART_ENABLE_MS(&up->port, termios->c_cflag)) { + up->curregs[R15] |= DCDIE | SYNCIE | CTSIE; up->flags |= PMACZILOG_FLAG_MODEM_STATUS; - else + } else { + up->curregs[R15] &= ~(DCDIE | SYNCIE | CTSIE); up->flags &= ~PMACZILOG_FLAG_MODEM_STATUS; + } /* set the irda codec to the right rate */ if (ZS_IS_IRDA(up)) @@ -1120,7 +1121,7 @@ * Unlike sunzilog, we don't need to pre-init the spinlock as we don't * register our console before uart_add_one_port() is called */ -static int __init pmz_setup_port(struct uart_pmac_port *up) +static int __init pmz_init_port(struct uart_pmac_port *up) { struct device_node *np = up->node; char *conn; @@ -1225,13 +1226,6 @@ { struct device_node *np; - if (up->flags & PMACZILOG_FLAG_RSRC_REQUESTED) { - release_OF_resource(up->node, 0); - if (ZS_HAS_DMA(up)) { - release_OF_resource(up->node, up->node->n_addrs - 2); - release_OF_resource(up->node, up->node->n_addrs - 1); - } - } iounmap((void *)up->control_reg); np = up->node; up->node = NULL; @@ -1335,9 +1329,9 @@ /* * Setup the ports for real */ - rc = pmz_setup_port(&pmz_ports[count]); + rc = pmz_init_port(&pmz_ports[count]); if (rc == 0) - rc = pmz_setup_port(&pmz_ports[count+1]); + rc = pmz_init_port(&pmz_ports[count+1]); if (rc != 0) { of_node_put(node_a); of_node_put(node_b); @@ -1581,6 +1575,8 @@ /* Probe ports */ pmz_probe(); +#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE +#endif /* TODO: Autoprobe console based on OF */ /* pmz_console.index = i; */ register_console(&pmz_console); diff -urN linux-2.6.3-rc2/drivers/serial/serial_core.c linux-2.6.3-rc3/drivers/serial/serial_core.c --- linux-2.6.3-rc2/drivers/serial/serial_core.c 2004-02-03 19:43:19.000000000 -0800 +++ linux-2.6.3-rc3/drivers/serial/serial_core.c 2004-02-14 19:31:09.000000000 -0800 @@ -1871,9 +1871,6 @@ if (flow == 'r') termios.c_cflag |= CRTSCTS; - if (!port->ops) - return 0; /* "console=" on ia64 */ - port->ops->set_termios(port, &termios, NULL); co->cflag = termios.c_cflag; diff -urN linux-2.6.3-rc2/drivers/video/Kconfig linux-2.6.3-rc3/drivers/video/Kconfig --- linux-2.6.3-rc2/drivers/video/Kconfig 2004-02-14 19:30:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/video/Kconfig 2004-02-14 19:31:09.000000000 -0800 @@ -614,6 +614,16 @@ There is no need for enabling 'Matrox multihead support' if you have only one Matrox card in the box. +config FB_RADEON_OLD + tristate "ATI Radeon display support (Old driver)" + depends on FB && PCI + help + Choose this option if you want to use an ATI Radeon graphics card as + a framebuffer device. There are both PCI and AGP versions. You + don't need to choose this to run the Radeon in plain VGA mode. + There is a product page at + . + config FB_RADEON tristate "ATI Radeon display support" depends on FB && PCI @@ -621,9 +631,25 @@ Choose this option if you want to use an ATI Radeon graphics card as a framebuffer device. There are both PCI and AGP versions. You don't need to choose this to run the Radeon in plain VGA mode. + + If you say Y here and want DDC/I2C support you must first say Y to + "I2C support" and "I2C bit-banging support" in the character devices + section. + + If you say M here then "I2C support" and "I2C bit-banging support" + can be build either as modules or built-in. + There is a product page at . +config FB_RADEON_I2C + bool "DDC/I2C for ATI Radeon support" + depends on FB_RADEON && I2C + select I2C_ALGOBIT + default y + help + Say Y here if you want DDC/I2C support for your Radeon board. + config FB_ATY128 tristate "ATI Rage128 display support" depends on FB && PCI diff -urN linux-2.6.3-rc2/drivers/video/Makefile linux-2.6.3-rc3/drivers/video/Makefile --- linux-2.6.3-rc2/drivers/video/Makefile 2004-02-14 19:30:53.000000000 -0800 +++ linux-2.6.3-rc3/drivers/video/Makefile 2004-02-14 19:31:09.000000000 -0800 @@ -21,7 +21,7 @@ obj-$(CONFIG_FB_Q40) += q40fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_ATARI) += atafb.o obj-$(CONFIG_FB_68328) += 68328fb.o -obj-$(CONFIG_FB_RADEON) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_RADEON_OLD) += radeonfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_NEOMAGIC) += neofb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_IGA) += igafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_CONTROL) += controlfb.o macmodes.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o @@ -60,6 +60,7 @@ obj-$(CONFIG_FB_SIS) += sis/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_ATY) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_ATY128) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o +obj-$(CONFIG_FB_RADEON) += aty/ cfbcopyarea.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_I810) += i810/ cfbfillrect.o cfbcopyarea.o \ cfbimgblt.o vgastate.o @@ -67,7 +68,7 @@ obj-$(CONFIG_FB_HGA) += hgafb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_VIRTUAL) += vfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o -obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o +obj-$(CONFIG_FB_HIT) += hitfb.o cfbfillrect.o cfbimgblt.o obj-$(CONFIG_FB_E1355) += epson1355fb.o obj-$(CONFIG_FB_PVR2) += pvr2fb.o cfbfillrect.o cfbcopyarea.o cfbimgblt.o obj-$(CONFIG_FB_KYRO) += kyro/ cfbfillrect.o cfbcopyarea.o cfbimgblt.o diff -urN linux-2.6.3-rc2/drivers/video/aty/Makefile linux-2.6.3-rc3/drivers/video/aty/Makefile --- linux-2.6.3-rc2/drivers/video/aty/Makefile 2004-02-03 19:43:39.000000000 -0800 +++ linux-2.6.3-rc3/drivers/video/aty/Makefile 2004-02-14 19:31:09.000000000 -0800 @@ -1,7 +1,13 @@ obj-$(CONFIG_FB_ATY) += atyfb.o obj-$(CONFIG_FB_ATY128) += aty128fb.o +obj-$(CONFIG_FB_RADEON) += radeonfb.o atyfb-y := atyfb_base.o mach64_accel.o atyfb-$(CONFIG_FB_ATY_GX) += mach64_gx.o atyfb-$(CONFIG_FB_ATY_CT) += mach64_ct.o mach64_cursor.o atyfb-objs := $(atyfb-y) + +radeonfb-y := radeon_base.o radeon_pm.o radeon_monitor.o radeon_accel.o +radeonfb-$(CONFIG_FB_RADEON_I2C) += radeon_i2c.o +radeonfb-objs := $(radeonfb-y) + diff -urN linux-2.6.3-rc2/drivers/video/aty/ati_ids.h linux-2.6.3-rc3/drivers/video/aty/ati_ids.h --- linux-2.6.3-rc2/drivers/video/aty/ati_ids.h 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/drivers/video/aty/ati_ids.h 2004-02-14 19:31:09.000000000 -0800 @@ -0,0 +1,167 @@ +/* + * ATI PCI IDs from XFree86, kept here to make sync'ing with + * XFree much simpler. Currently, this list is only used by + * radeonfb + */ + +#define PCI_CHIP_RS100_4136 0x4136 +#define PCI_CHIP_RS200_4137 0x4137 +#define PCI_CHIP_R300_AD 0x4144 +#define PCI_CHIP_R300_AE 0x4145 +#define PCI_CHIP_R300_AF 0x4146 +#define PCI_CHIP_R300_AG 0x4147 +#define PCI_CHIP_R350_AH 0x4148 +#define PCI_CHIP_R350_AI 0x4149 +#define PCI_CHIP_R350_AJ 0x414A +#define PCI_CHIP_R350_AK 0x414B +#define PCI_CHIP_RV350_AP 0x4150 +#define PCI_CHIP_RV350_AQ 0x4151 +#define PCI_CHIP_RV360_AR 0x4152 +#define PCI_CHIP_RV350_AS 0x4153 +#define PCI_CHIP_RV350_AT 0x4154 +#define PCI_CHIP_RV350_AV 0x4156 +#define PCI_CHIP_MACH32 0x4158 +#define PCI_CHIP_RS250_4237 0x4237 +#define PCI_CHIP_R200_BB 0x4242 +#define PCI_CHIP_R200_BC 0x4243 +#define PCI_CHIP_RS100_4336 0x4336 +#define PCI_CHIP_RS200_4337 0x4337 +#define PCI_CHIP_MACH64CT 0x4354 +#define PCI_CHIP_MACH64CX 0x4358 +#define PCI_CHIP_RS250_4437 0x4437 +#define PCI_CHIP_MACH64ET 0x4554 +#define PCI_CHIP_MACH64GB 0x4742 +#define PCI_CHIP_MACH64GD 0x4744 +#define PCI_CHIP_MACH64GI 0x4749 +#define PCI_CHIP_MACH64GL 0x474C +#define PCI_CHIP_MACH64GM 0x474D +#define PCI_CHIP_MACH64GN 0x474E +#define PCI_CHIP_MACH64GO 0x474F +#define PCI_CHIP_MACH64GP 0x4750 +#define PCI_CHIP_MACH64GQ 0x4751 +#define PCI_CHIP_MACH64GR 0x4752 +#define PCI_CHIP_MACH64GS 0x4753 +#define PCI_CHIP_MACH64GT 0x4754 +#define PCI_CHIP_MACH64GU 0x4755 +#define PCI_CHIP_MACH64GV 0x4756 +#define PCI_CHIP_MACH64GW 0x4757 +#define PCI_CHIP_MACH64GX 0x4758 +#define PCI_CHIP_MACH64GY 0x4759 +#define PCI_CHIP_MACH64GZ 0x475A +#define PCI_CHIP_RV250_Id 0x4964 +#define PCI_CHIP_RV250_Ie 0x4965 +#define PCI_CHIP_RV250_If 0x4966 +#define PCI_CHIP_RV250_Ig 0x4967 +#define PCI_CHIP_MACH64LB 0x4C42 +#define PCI_CHIP_MACH64LD 0x4C44 +#define PCI_CHIP_RAGE128LE 0x4C45 +#define PCI_CHIP_RAGE128LF 0x4C46 +#define PCI_CHIP_MACH64LG 0x4C47 +#define PCI_CHIP_MACH64LI 0x4C49 +#define PCI_CHIP_MACH64LM 0x4C4D +#define PCI_CHIP_MACH64LN 0x4C4E +#define PCI_CHIP_MACH64LP 0x4C50 +#define PCI_CHIP_MACH64LQ 0x4C51 +#define PCI_CHIP_MACH64LR 0x4C52 +#define PCI_CHIP_MACH64LS 0x4C53 +#define PCI_CHIP_RADEON_LW 0x4C57 +#define PCI_CHIP_RADEON_LX 0x4C58 +#define PCI_CHIP_RADEON_LY 0x4C59 +#define PCI_CHIP_RADEON_LZ 0x4C5A +#define PCI_CHIP_RV250_Ld 0x4C64 +#define PCI_CHIP_RV250_Le 0x4C65 +#define PCI_CHIP_RV250_Lf 0x4C66 +#define PCI_CHIP_RV250_Lg 0x4C67 +#define PCI_CHIP_RAGE128MF 0x4D46 +#define PCI_CHIP_RAGE128ML 0x4D4C +#define PCI_CHIP_R300_ND 0x4E44 +#define PCI_CHIP_R300_NE 0x4E45 +#define PCI_CHIP_R300_NF 0x4E46 +#define PCI_CHIP_R300_NG 0x4E47 +#define PCI_CHIP_R350_NH 0x4E48 +#define PCI_CHIP_R350_NI 0x4E49 +#define PCI_CHIP_R360_NJ 0x4E4A +#define PCI_CHIP_R350_NK 0x4E4B +#define PCI_CHIP_RV350_NP 0x4E50 +#define PCI_CHIP_RV350_NQ 0x4E51 +#define PCI_CHIP_RV350_NR 0x4E52 +#define PCI_CHIP_RV350_NS 0x4E53 +#define PCI_CHIP_RV350_NT 0x4E54 +#define PCI_CHIP_RV350_NV 0x4E56 +#define PCI_CHIP_RAGE128PA 0x5041 +#define PCI_CHIP_RAGE128PB 0x5042 +#define PCI_CHIP_RAGE128PC 0x5043 +#define PCI_CHIP_RAGE128PD 0x5044 +#define PCI_CHIP_RAGE128PE 0x5045 +#define PCI_CHIP_RAGE128PF 0x5046 +#define PCI_CHIP_RAGE128PG 0x5047 +#define PCI_CHIP_RAGE128PH 0x5048 +#define PCI_CHIP_RAGE128PI 0x5049 +#define PCI_CHIP_RAGE128PJ 0x504A +#define PCI_CHIP_RAGE128PK 0x504B +#define PCI_CHIP_RAGE128PL 0x504C +#define PCI_CHIP_RAGE128PM 0x504D +#define PCI_CHIP_RAGE128PN 0x504E +#define PCI_CHIP_RAGE128PO 0x504F +#define PCI_CHIP_RAGE128PP 0x5050 +#define PCI_CHIP_RAGE128PQ 0x5051 +#define PCI_CHIP_RAGE128PR 0x5052 +#define PCI_CHIP_RAGE128PS 0x5053 +#define PCI_CHIP_RAGE128PT 0x5054 +#define PCI_CHIP_RAGE128PU 0x5055 +#define PCI_CHIP_RAGE128PV 0x5056 +#define PCI_CHIP_RAGE128PW 0x5057 +#define PCI_CHIP_RAGE128PX 0x5058 +#define PCI_CHIP_RADEON_QD 0x5144 +#define PCI_CHIP_RADEON_QE 0x5145 +#define PCI_CHIP_RADEON_QF 0x5146 +#define PCI_CHIP_RADEON_QG 0x5147 +#define PCI_CHIP_R200_QH 0x5148 +#define PCI_CHIP_R200_QI 0x5149 +#define PCI_CHIP_R200_QJ 0x514A +#define PCI_CHIP_R200_QK 0x514B +#define PCI_CHIP_R200_QL 0x514C +#define PCI_CHIP_R200_QM 0x514D +#define PCI_CHIP_R200_QN 0x514E +#define PCI_CHIP_R200_QO 0x514F +#define PCI_CHIP_RV200_QW 0x5157 +#define PCI_CHIP_RV200_QX 0x5158 +#define PCI_CHIP_RV100_QY 0x5159 +#define PCI_CHIP_RV100_QZ 0x515A +#define PCI_CHIP_RAGE128RE 0x5245 +#define PCI_CHIP_RAGE128RF 0x5246 +#define PCI_CHIP_RAGE128RG 0x5247 +#define PCI_CHIP_RAGE128RK 0x524B +#define PCI_CHIP_RAGE128RL 0x524C +#define PCI_CHIP_RAGE128SE 0x5345 +#define PCI_CHIP_RAGE128SF 0x5346 +#define PCI_CHIP_RAGE128SG 0x5347 +#define PCI_CHIP_RAGE128SH 0x5348 +#define PCI_CHIP_RAGE128SK 0x534B +#define PCI_CHIP_RAGE128SL 0x534C +#define PCI_CHIP_RAGE128SM 0x534D +#define PCI_CHIP_RAGE128SN 0x534E +#define PCI_CHIP_RAGE128TF 0x5446 +#define PCI_CHIP_RAGE128TL 0x544C +#define PCI_CHIP_RAGE128TR 0x5452 +#define PCI_CHIP_RAGE128TS 0x5453 +#define PCI_CHIP_RAGE128TT 0x5454 +#define PCI_CHIP_RAGE128TU 0x5455 +#define PCI_CHIP_MACH64VT 0x5654 +#define PCI_CHIP_MACH64VU 0x5655 +#define PCI_CHIP_MACH64VV 0x5656 +#define PCI_CHIP_RS300_5834 0x5834 +#define PCI_CHIP_RS300_5835 0x5835 +#define PCI_CHIP_RS300_5836 0x5836 +#define PCI_CHIP_RS300_5837 0x5837 +#define PCI_CHIP_RV280_5960 0x5960 +#define PCI_CHIP_RV280_5961 0x5961 +#define PCI_CHIP_RV280_5962 0x5962 +#define PCI_CHIP_RV280_5963 0x5963 +#define PCI_CHIP_RV280_5964 0x5964 +#define PCI_CHIP_RV280_5968 0x5968 +#define PCI_CHIP_RV280_5969 0x5969 +#define PCI_CHIP_RV280_596A 0x596A +#define PCI_CHIP_RV280_596B 0x596B +#define PCI_CHIP_RV280_5C61 0x5C61 +#define PCI_CHIP_RV280_5C63 0x5C63 diff -urN linux-2.6.3-rc2/drivers/video/aty/radeon_accel.c linux-2.6.3-rc3/drivers/video/aty/radeon_accel.c --- linux-2.6.3-rc2/drivers/video/aty/radeon_accel.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/drivers/video/aty/radeon_accel.c 2004-02-14 19:31:09.000000000 -0800 @@ -0,0 +1,288 @@ +#include "radeonfb.h" + +/* the accelerated functions here are patterned after the + * "ACCEL_MMIO" ifdef branches in XFree86 + * --dte + */ +static void radeonfb_prim_fillrect(struct radeonfb_info *rinfo, + const struct fb_fillrect *region) +{ + radeon_fifo_wait(4); + + OUTREG(DP_GUI_MASTER_CNTL, + rinfo->dp_gui_master_cntl /* contains, like GMC_DST_32BPP */ + | GMC_BRUSH_SOLID_COLOR + | ROP3_P); + OUTREG(DP_BRUSH_FRGD_CLR, region->color); + OUTREG(DP_WRITE_MSK, 0xffffffff); + OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); + + radeon_fifo_wait(2); + OUTREG(DST_Y_X, (region->dy << 16) | region->dx); + OUTREG(DST_WIDTH_HEIGHT, (region->width << 16) | region->height); +} + +void radeonfb_fillrect(struct fb_info *info, const struct fb_fillrect *region) +{ + struct radeonfb_info *rinfo = info->par; + struct fb_fillrect modded; + int vxres, vyres; + + if (rinfo->asleep) + return; + if (radeon_accel_disabled()) { + cfb_fillrect(info, region); + return; + } + + vxres = info->var.xres; + vyres = info->var.yres; + + memcpy(&modded, region, sizeof(struct fb_fillrect)); + + if(!modded.width || !modded.height || + modded.dx >= vxres || modded.dy >= vyres) + return; + + if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; + if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; + + radeonfb_prim_fillrect(rinfo, &modded); +} + +static void radeonfb_prim_copyarea(struct radeonfb_info *rinfo, + const struct fb_copyarea *area) +{ + radeon_fifo_wait(3); + OUTREG(DP_GUI_MASTER_CNTL, + rinfo->dp_gui_master_cntl /* i.e. GMC_DST_32BPP */ + | GMC_SRC_DSTCOLOR + | ROP3_S + | DP_SRC_RECT ); + OUTREG(DP_WRITE_MSK, 0xffffffff); + OUTREG(DP_CNTL, (DST_X_LEFT_TO_RIGHT | DST_Y_TOP_TO_BOTTOM)); + + radeon_fifo_wait(3); + OUTREG(SRC_Y_X, (area->sy << 16) | area->sx); + OUTREG(DST_Y_X, (area->dy << 16) | area->dx); + OUTREG(DST_HEIGHT_WIDTH, (area->height << 16) | area->width); +} + + +void radeonfb_copyarea(struct fb_info *info, const struct fb_copyarea *area) +{ + struct radeonfb_info *rinfo = info->par; + struct fb_copyarea modded; + u32 vxres, vyres; + modded.sx = area->sx; + modded.sy = area->sy; + modded.dx = area->dx; + modded.dy = area->dy; + modded.width = area->width; + modded.height = area->height; + + if (rinfo->asleep) + return; + if (radeon_accel_disabled()) { + cfb_copyarea(info, area); + return; + } + + vxres = info->var.xres; + vyres = info->var.yres; + + if(!modded.width || !modded.height || + modded.sx >= vxres || modded.sy >= vyres || + modded.dx >= vxres || modded.dy >= vyres) + return; + + if(modded.sx + modded.width > vxres) modded.width = vxres - modded.sx; + if(modded.dx + modded.width > vxres) modded.width = vxres - modded.dx; + if(modded.sy + modded.height > vyres) modded.height = vyres - modded.sy; + if(modded.dy + modded.height > vyres) modded.height = vyres - modded.dy; + + radeonfb_prim_copyarea(rinfo, &modded); +} + +void radeonfb_imageblit(struct fb_info *info, const struct fb_image *image) +{ + struct radeonfb_info *rinfo = info->par; + + if (rinfo->asleep) + return; + radeon_engine_idle(); + + cfb_imageblit(info, image); +} + +int radeonfb_sync(struct fb_info *info) +{ + struct radeonfb_info *rinfo = info->par; + + if (rinfo->asleep) + return 0; + radeon_engine_idle(); + + return 0; +} + +void radeonfb_engine_reset(struct radeonfb_info *rinfo) +{ + u32 clock_cntl_index, mclk_cntl, rbbm_soft_reset; + u32 host_path_cntl; + + radeon_engine_flush (rinfo); + + /* Some ASICs have bugs with dynamic-on feature, which are + * ASIC-version dependent, so we force all blocks on for now + * -- from XFree86 + * We don't do that on macs, things just work here with dynamic + * clocking... --BenH + */ +#ifdef CONFIG_ALL_PPC + if (_machine != _MACH_Pmac && rinfo->hasCRTC2) +#else + if (rinfo->has_CRTC2) +#endif + { + u32 tmp; + + tmp = INPLL(SCLK_CNTL); + OUTPLL(SCLK_CNTL, ((tmp & ~DYN_STOP_LAT_MASK) | + CP_MAX_DYN_STOP_LAT | + SCLK_FORCEON_MASK)); + + if (rinfo->family == CHIP_FAMILY_RV200) + { + tmp = INPLL(SCLK_MORE_CNTL); + OUTPLL(SCLK_MORE_CNTL, tmp | SCLK_MORE_FORCEON); + } + } + + clock_cntl_index = INREG(CLOCK_CNTL_INDEX); + mclk_cntl = INPLL(MCLK_CNTL); + + OUTPLL(MCLK_CNTL, (mclk_cntl | + FORCEON_MCLKA | + FORCEON_MCLKB | + FORCEON_YCLKA | + FORCEON_YCLKB | + FORCEON_MC | + FORCEON_AIC)); + + host_path_cntl = INREG(HOST_PATH_CNTL); + rbbm_soft_reset = INREG(RBBM_SOFT_RESET); + + if (rinfo->family == CHIP_FAMILY_R300 || + rinfo->family == CHIP_FAMILY_R350 || + rinfo->family == CHIP_FAMILY_RV350) { + u32 tmp; + + OUTREG(RBBM_SOFT_RESET, (rbbm_soft_reset | + SOFT_RESET_CP | + SOFT_RESET_HI | + SOFT_RESET_E2)); + INREG(RBBM_SOFT_RESET); + OUTREG(RBBM_SOFT_RESET, 0); + tmp = INREG(RB2D_DSTCACHE_MODE); + OUTREG(RB2D_DSTCACHE_MODE, tmp | (1 << 17)); /* FIXME */ + } else { + OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset | + SOFT_RESET_CP | + SOFT_RESET_HI | + SOFT_RESET_SE | + SOFT_RESET_RE | + SOFT_RESET_PP | + SOFT_RESET_E2 | + SOFT_RESET_RB); + INREG(RBBM_SOFT_RESET); + OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset & (u32) + ~(SOFT_RESET_CP | + SOFT_RESET_HI | + SOFT_RESET_SE | + SOFT_RESET_RE | + SOFT_RESET_PP | + SOFT_RESET_E2 | + SOFT_RESET_RB)); + INREG(RBBM_SOFT_RESET); + } + + OUTREG(HOST_PATH_CNTL, host_path_cntl | HDP_SOFT_RESET); + INREG(HOST_PATH_CNTL); + OUTREG(HOST_PATH_CNTL, host_path_cntl); + + if (rinfo->family != CHIP_FAMILY_R300 || + rinfo->family != CHIP_FAMILY_R350 || + rinfo->family != CHIP_FAMILY_RV350) + OUTREG(RBBM_SOFT_RESET, rbbm_soft_reset); + + OUTREG(CLOCK_CNTL_INDEX, clock_cntl_index); + OUTPLL(MCLK_CNTL, mclk_cntl); + if (rinfo->R300_cg_workaround) + R300_cg_workardound(rinfo); +} + +void radeonfb_engine_init (struct radeonfb_info *rinfo) +{ + unsigned long temp; + + /* disable 3D engine */ + OUTREG(RB3D_CNTL, 0); + + radeonfb_engine_reset(rinfo); + + radeon_fifo_wait (1); + if ((rinfo->family != CHIP_FAMILY_R300) && + (rinfo->family != CHIP_FAMILY_R350) && + (rinfo->family != CHIP_FAMILY_RV350)) + OUTREG(RB2D_DSTCACHE_MODE, 0); + + radeon_fifo_wait (3); + /* We re-read MC_FB_LOCATION from card as it can have been + * modified by XFree drivers (ouch !) + */ + rinfo->fb_local_base = INREG(MC_FB_LOCATION) << 16; + + OUTREG(DEFAULT_PITCH_OFFSET, (rinfo->pitch << 0x16) | + (rinfo->fb_local_base >> 10)); + OUTREG(DST_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); + OUTREG(SRC_PITCH_OFFSET, (rinfo->pitch << 0x16) | (rinfo->fb_local_base >> 10)); + + radeon_fifo_wait (1); +#if defined(__BIG_ENDIAN) + OUTREGP(DP_DATATYPE, HOST_BIG_ENDIAN_EN, ~HOST_BIG_ENDIAN_EN); +#else + OUTREGP(DP_DATATYPE, 0, ~HOST_BIG_ENDIAN_EN); +#endif + radeon_fifo_wait (2); + OUTREG(DEFAULT_SC_TOP_LEFT, 0); + OUTREG(DEFAULT_SC_BOTTOM_RIGHT, (DEFAULT_SC_RIGHT_MAX | + DEFAULT_SC_BOTTOM_MAX)); + + temp = radeon_get_dstbpp(rinfo->depth); + rinfo->dp_gui_master_cntl = ((temp << 8) | GMC_CLR_CMP_CNTL_DIS); + + radeon_fifo_wait (1); + OUTREG(DP_GUI_MASTER_CNTL, (rinfo->dp_gui_master_cntl | + GMC_BRUSH_SOLID_COLOR | + GMC_SRC_DATATYPE_COLOR)); + + radeon_fifo_wait (7); + + /* clear line drawing regs */ + OUTREG(DST_LINE_START, 0); + OUTREG(DST_LINE_END, 0); + + /* set brush color regs */ + OUTREG(DP_BRUSH_FRGD_CLR, 0xffffffff); + OUTREG(DP_BRUSH_BKGD_CLR, 0x00000000); + + /* set source color regs */ + OUTREG(DP_SRC_FRGD_CLR, 0xffffffff); + OUTREG(DP_SRC_BKGD_CLR, 0x00000000); + + /* default write mask */ + OUTREG(DP_WRITE_MSK, 0xffffffff); + + radeon_engine_idle (); +} diff -urN linux-2.6.3-rc2/drivers/video/aty/radeon_base.c linux-2.6.3-rc3/drivers/video/aty/radeon_base.c --- linux-2.6.3-rc2/drivers/video/aty/radeon_base.c 1969-12-31 16:00:00.000000000 -0800 +++ linux-2.6.3-rc3/drivers/video/aty/radeon_base.c 2004-02-14 19:31:09.000000000 -0800 @@ -0,0 +1,2387 @@ +/* + * drivers/video/radeonfb.c + * framebuffer driver for ATI Radeon chipset video boards + * + * Copyright 2003 Ben. Herrenschmidt + * Copyright 2000 Ani Joshi + * + * i2c bits from Luca Tettamanti + * + * Special thanks to ATI DevRel team for their hardware donations. + * + * ...Insert GPL boilerplate here... + * + * Significant portions of this driver apdated from XFree86 Radeon + * driver which has the following copyright notice: + * + * Copyright 2000 ATI Technologies Inc., Markham, Ontario, and + * VA Linux Systems Inc., Fremont, California. + * + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining + * a copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation on the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Software, + * and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, VA LINUX SYSTEMS AND/OR + * THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, + * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * XFree86 driver authors: + * + * Kevin E. Martin + * Rickard E. Faith + * Alan Hourihane + * + */ + + +#define RADEON_VERSION "0.2.0" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#ifdef CONFIG_PPC_OF + +#include +#include +#include "../macmodes.h" + +#ifdef CONFIG_PMAC_BACKLIGHT +#include +#endif + +#ifdef CONFIG_BOOTX_TEXT +#include +#endif + +#endif /* CONFIG_PPC_OF */ + +#ifdef CONFIG_MTRR +#include +#endif + +#include