Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 13 Jan 2009 17:02:21 +0000 (09:02 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 13 Jan 2009 17:02:21 +0000 (09:02 -0800)
* 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  smp_call_function_single(): be slightly less stupid, fix #2
  lockdep, mm: fix might_fault() annotation

375 files changed:
arch/m68k/amiga/amiints.c
arch/m68k/amiga/cia.c
arch/m68k/amiga/config.c
arch/m68k/apollo/config.c
arch/m68k/atari/atakeyb.c
arch/m68k/atari/stdma.c
arch/m68k/atari/time.c
arch/m68k/bvme6000/config.c
arch/m68k/hp300/time.c
arch/m68k/kernel/.gitignore [new file with mode: 0644]
arch/m68k/kernel/entry.S
arch/m68k/kernel/setup.c
arch/m68k/kernel/signal.c
arch/m68k/kernel/vmlinux-sun3.lds
arch/m68k/mac/baboon.c
arch/m68k/mac/config.c
arch/m68k/mac/debug.c
arch/m68k/mac/iop.c
arch/m68k/mac/macints.c
arch/m68k/mac/misc.c
arch/m68k/mac/oss.c
arch/m68k/mac/psc.c
arch/m68k/mac/via.c
arch/m68k/math-emu/fp_log.c
arch/m68k/mm/init.c
arch/m68k/mm/motorola.c
arch/m68k/mvme147/config.c
arch/m68k/mvme16x/config.c
arch/m68k/q40/config.c
arch/m68k/sun3/config.c
arch/m68k/sun3/mmu_emu.c
arch/m68k/sun3/sun3ints.c
arch/m68k/sun3x/config.c
arch/mips/Kconfig
arch/mips/Makefile
arch/mips/alchemy/Kconfig
arch/mips/alchemy/common/Makefile
arch/mips/alchemy/common/au1xxx_irqmap.c [deleted file]
arch/mips/alchemy/common/clocks.c
arch/mips/alchemy/common/cputable.c [deleted file]
arch/mips/alchemy/common/dbdma.c
arch/mips/alchemy/common/irq.c
arch/mips/alchemy/common/power.c
arch/mips/alchemy/common/reset.c
arch/mips/alchemy/common/setup.c
arch/mips/alchemy/common/sleeper.S
arch/mips/alchemy/common/time.c
arch/mips/alchemy/db1x00/init.c [deleted file]
arch/mips/alchemy/devboards/Makefile [new file with mode: 0644]
arch/mips/alchemy/devboards/db1x00/Makefile [moved from arch/mips/alchemy/db1x00/Makefile with 81% similarity]
arch/mips/alchemy/devboards/db1x00/board_setup.c [moved from arch/mips/alchemy/db1x00/board_setup.c with 80% similarity]
arch/mips/alchemy/devboards/db1x00/irqmap.c [moved from arch/mips/alchemy/db1x00/irqmap.c with 77% similarity]
arch/mips/alchemy/devboards/pb1000/Makefile [moved from arch/mips/alchemy/pb1000/Makefile with 81% similarity]
arch/mips/alchemy/devboards/pb1000/board_setup.c [moved from arch/mips/alchemy/pb1000/board_setup.c with 90% similarity]
arch/mips/alchemy/devboards/pb1100/Makefile [moved from arch/mips/alchemy/pb1100/Makefile with 81% similarity]
arch/mips/alchemy/devboards/pb1100/board_setup.c [moved from arch/mips/alchemy/pb1100/board_setup.c with 76% similarity]
arch/mips/alchemy/devboards/pb1200/Makefile [moved from arch/mips/alchemy/pb1200/Makefile with 61% similarity]
arch/mips/alchemy/devboards/pb1200/board_setup.c [moved from arch/mips/alchemy/pb1200/board_setup.c with 93% similarity]
arch/mips/alchemy/devboards/pb1200/irqmap.c [moved from arch/mips/alchemy/pb1200/irqmap.c with 64% similarity]
arch/mips/alchemy/devboards/pb1200/platform.c [moved from arch/mips/alchemy/pb1200/platform.c with 100% similarity]
arch/mips/alchemy/devboards/pb1500/Makefile [moved from arch/mips/alchemy/pb1500/Makefile with 81% similarity]
arch/mips/alchemy/devboards/pb1500/board_setup.c [moved from arch/mips/alchemy/pb1500/board_setup.c with 79% similarity]
arch/mips/alchemy/devboards/pb1550/Makefile [moved from arch/mips/alchemy/pb1550/Makefile with 81% similarity]
arch/mips/alchemy/devboards/pb1550/board_setup.c [moved from arch/mips/alchemy/pb1550/board_setup.c with 72% similarity]
arch/mips/alchemy/devboards/pm.c [new file with mode: 0644]
arch/mips/alchemy/devboards/prom.c [moved from arch/mips/alchemy/pb1550/init.c with 71% similarity]
arch/mips/alchemy/mtx-1/board_setup.c
arch/mips/alchemy/mtx-1/init.c
arch/mips/alchemy/mtx-1/irqmap.c
arch/mips/alchemy/pb1000/init.c [deleted file]
arch/mips/alchemy/pb1000/irqmap.c [deleted file]
arch/mips/alchemy/pb1100/init.c [deleted file]
arch/mips/alchemy/pb1100/irqmap.c [deleted file]
arch/mips/alchemy/pb1200/init.c [deleted file]
arch/mips/alchemy/pb1500/init.c [deleted file]
arch/mips/alchemy/pb1500/irqmap.c [deleted file]
arch/mips/alchemy/pb1550/irqmap.c [deleted file]
arch/mips/alchemy/xxs1500/board_setup.c
arch/mips/alchemy/xxs1500/init.c
arch/mips/alchemy/xxs1500/irqmap.c
arch/mips/cavium-octeon/Kconfig [new file with mode: 0644]
arch/mips/cavium-octeon/Makefile [new file with mode: 0644]
arch/mips/cavium-octeon/csrc-octeon.c [new file with mode: 0644]
arch/mips/cavium-octeon/dma-octeon.c [new file with mode: 0644]
arch/mips/cavium-octeon/executive/Makefile [new file with mode: 0644]
arch/mips/cavium-octeon/executive/cvmx-bootmem.c [new file with mode: 0644]
arch/mips/cavium-octeon/executive/cvmx-l2c.c [new file with mode: 0644]
arch/mips/cavium-octeon/executive/cvmx-sysinfo.c [new file with mode: 0644]
arch/mips/cavium-octeon/executive/octeon-model.c [new file with mode: 0644]
arch/mips/cavium-octeon/flash_setup.c [new file with mode: 0644]
arch/mips/cavium-octeon/octeon-irq.c [new file with mode: 0644]
arch/mips/cavium-octeon/octeon-memcpy.S [new file with mode: 0644]
arch/mips/cavium-octeon/serial.c [new file with mode: 0644]
arch/mips/cavium-octeon/setup.c [new file with mode: 0644]
arch/mips/cavium-octeon/smp.c [new file with mode: 0644]
arch/mips/configs/cavium-octeon_defconfig [new file with mode: 0644]
arch/mips/include/asm/cpu-features.h
arch/mips/include/asm/cpu.h
arch/mips/include/asm/hazards.h
arch/mips/include/asm/io.h
arch/mips/include/asm/mach-au1x00/au1000.h
arch/mips/include/asm/mach-au1x00/au1xxx_dbdma.h
arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h [new file with mode: 0644]
arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h [new file with mode: 0644]
arch/mips/include/asm/mach-cavium-octeon/irq.h [new file with mode: 0644]
arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h [new file with mode: 0644]
arch/mips/include/asm/mach-cavium-octeon/war.h [new file with mode: 0644]
arch/mips/include/asm/mach-generic/dma-coherence.h
arch/mips/include/asm/mach-ip27/dma-coherence.h
arch/mips/include/asm/mach-ip32/dma-coherence.h
arch/mips/include/asm/mach-jazz/dma-coherence.h
arch/mips/include/asm/mach-lemote/dma-coherence.h
arch/mips/include/asm/mipsregs.h
arch/mips/include/asm/module.h
arch/mips/include/asm/octeon/cvmx-asm.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-bootinfo.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-bootmem.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-ciu-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-gpio-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-iob-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-ipd-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-l2c-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-l2c.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-l2d-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-l2t-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-led-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-mio-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-packet.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-pow-defs.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-spinlock.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx-sysinfo.h [new file with mode: 0644]
arch/mips/include/asm/octeon/cvmx.h [new file with mode: 0644]
arch/mips/include/asm/octeon/octeon-feature.h [new file with mode: 0644]
arch/mips/include/asm/octeon/octeon-model.h [new file with mode: 0644]
arch/mips/include/asm/octeon/octeon.h [new file with mode: 0644]
arch/mips/include/asm/processor.h
arch/mips/include/asm/ptrace.h
arch/mips/include/asm/smp.h
arch/mips/include/asm/stackframe.h
arch/mips/include/asm/time.h
arch/mips/kernel/Makefile
arch/mips/kernel/asm-offsets.c
arch/mips/kernel/branch.c
arch/mips/kernel/cevt-r4k.c
arch/mips/kernel/cpu-probe.c
arch/mips/kernel/csrc-r4k.c
arch/mips/kernel/genex.S
arch/mips/kernel/irq.c
arch/mips/kernel/octeon_switch.S [new file with mode: 0644]
arch/mips/kernel/ptrace32.c
arch/mips/kernel/traps.c
arch/mips/lib/Makefile
arch/mips/mm/Makefile
arch/mips/mm/c-octeon.c [new file with mode: 0644]
arch/mips/mm/cache.c
arch/mips/mm/cex-oct.S [new file with mode: 0644]
arch/mips/mm/dma-default.c
arch/mips/mm/tlb-r4k.c
arch/mips/mm/tlbex.c
arch/powerpc/boot/dts/gef_sbc610.dts
arch/powerpc/configs/86xx/gef_sbc610_defconfig
arch/powerpc/platforms/cell/cbe_cpufreq.c
arch/powerpc/platforms/cell/cpufreq_spudemand.c
arch/powerpc/platforms/pasemi/cpufreq.c
arch/powerpc/platforms/powermac/cpufreq_64.c
arch/sparc/configs/sparc32_defconfig
arch/sparc/include/asm/oplib_32.h
arch/sparc/include/asm/oplib_64.h
arch/sparc/include/asm/signal.h
arch/sparc/kernel/auxio_32.c
arch/sparc/kernel/auxio_64.c
arch/sparc/kernel/cpu.c
arch/sparc/kernel/idprom.c
arch/sparc/kernel/ioport.c
arch/sparc/kernel/irq_32.c
arch/sparc/kernel/pci.c
arch/sparc/kernel/pcic.c
arch/sparc/kernel/process_32.c
arch/sparc/kernel/process_64.c
arch/sparc/kernel/psycho_common.c
arch/sparc/kernel/sbus.c
arch/sparc/kernel/setup_32.c
arch/sparc/kernel/setup_64.c
arch/sparc/kernel/sparc_ksyms_32.c
arch/sparc/kernel/sparc_ksyms_64.c
arch/sparc/kernel/sun4d_smp.c
arch/sparc/kernel/sys_sparc_64.c
arch/sparc/kernel/time_32.c
arch/sparc/kernel/time_64.c
arch/sparc/kernel/traps_32.c
arch/sparc/kernel/traps_64.c
arch/sparc/kernel/unaligned_64.c
arch/sparc/lib/Makefile
arch/sparc/lib/PeeCeeI.c
arch/sparc/lib/ksyms.c [new file with mode: 0644]
arch/sparc/lib/user_fixup.c
arch/sparc/mm/generic_32.c
arch/sparc/mm/generic_64.c
arch/sparc/mm/highmem.c
arch/sparc/mm/init_32.c
arch/sparc/mm/init_64.c
arch/sparc/prom/init_32.c
arch/sparc/prom/misc_32.c
arch/sparc/prom/misc_64.c
arch/sparc/prom/ranges.c
arch/sparc/prom/tree_32.c
arch/sparc/prom/tree_64.c
arch/x86/include/asm/mach-default/mach_wakecpu.h
arch/x86/include/asm/mtrr.h
arch/x86/kernel/apic.c
arch/x86/kernel/cpu/cpufreq/acpi-cpufreq.c
arch/x86/kernel/mpparse.c
arch/x86/mm/fault.c
drivers/ata/libata-sff.c
drivers/ata/pata_it821x.c
drivers/block/amiflop.c
drivers/char/amiserial.c
drivers/char/pty.c
drivers/char/ser_a2232.c
drivers/char/vme_scc.c
drivers/dio/dio-sysfs.c
drivers/dio/dio.c
drivers/infiniband/hw/ehca/ehca_main.c
drivers/infiniband/hw/mlx4/main.c
drivers/infiniband/hw/nes/nes_cm.c
drivers/infiniband/hw/nes/nes_utils.c
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/infiniband/ulp/iser/Kconfig
drivers/input/misc/Kconfig
drivers/input/misc/Makefile
drivers/input/misc/pcf50633-input.c [new file with mode: 0644]
drivers/isdn/hardware/mISDN/hfcmulti.c
drivers/isdn/hardware/mISDN/hfcpci.c
drivers/isdn/mISDN/dsp_cmx.c
drivers/isdn/mISDN/dsp_pipeline.c
drivers/mfd/Kconfig
drivers/mfd/Makefile
drivers/mfd/dm355evm_msp.c
drivers/mfd/pcf50633-adc.c [new file with mode: 0644]
drivers/mfd/pcf50633-core.c [new file with mode: 0644]
drivers/mfd/pcf50633-gpio.c [new file with mode: 0644]
drivers/mfd/sm501.c
drivers/mfd/twl4030-core.c
drivers/net/3c503.c
drivers/net/3c59x.c
drivers/net/8139cp.c
drivers/net/8139too.c
drivers/net/8390.c
drivers/net/8390p.c
drivers/net/Kconfig
drivers/net/acenic.c
drivers/net/arm/etherh.c
drivers/net/arm/ks8695net.c
drivers/net/b44.c
drivers/net/cxgb3/adapter.h
drivers/net/cxgb3/cxgb3_main.c
drivers/net/cxgb3/sge.c
drivers/net/e1000e/ich8lan.c
drivers/net/e2100.c
drivers/net/enic/enic_main.c
drivers/net/forcedeth.c
drivers/net/gianfar.c
drivers/net/hamachi.c
drivers/net/hamradio/6pack.c
drivers/net/hp-plus.c
drivers/net/hydra.c
drivers/net/irda/au1k_ir.c
drivers/net/irda/donauboe.c
drivers/net/mac8390.c
drivers/net/mlx4/en_netdev.c
drivers/net/mlx4/main.c
drivers/net/ne-h8300.c
drivers/net/ne2k-pci.c
drivers/net/ns83820.c
drivers/net/qlge/qlge.h
drivers/net/qlge/qlge_dbg.c
drivers/net/qlge/qlge_main.c
drivers/net/r6040.c
drivers/net/sc92031.c
drivers/net/sfc/tenxpress.c
drivers/net/sis900.c
drivers/net/smc-mca.c
drivers/net/smc-ultra.c
drivers/net/smsc911x.c
drivers/net/smsc9420.c
drivers/net/ucc_geth.c
drivers/net/ucc_geth.h
drivers/net/via-rhine.c
drivers/net/via-velocity.c
drivers/net/wd.c
drivers/net/wireless/libertas/main.c
drivers/net/yellowfin.c
drivers/net/zorro8390.c
drivers/pci/intel-iommu.c
drivers/power/Kconfig
drivers/power/Makefile
drivers/power/pcf50633-charger.c [new file with mode: 0644]
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/pcf50633-regulator.c [new file with mode: 0644]
drivers/rtc/Kconfig
drivers/rtc/Makefile
drivers/rtc/rtc-pcf50633.c [new file with mode: 0644]
drivers/s390/net/qeth_l2_main.c
drivers/s390/net/qeth_l3_main.c
drivers/serial/jsm/jsm_neo.c
drivers/usb/serial/ti_usb_3410_5052.c
drivers/usb/serial/ti_usb_3410_5052.h
drivers/usb/serial/usb-serial.c
drivers/video/Makefile
drivers/video/amifb.c
drivers/video/atafb.c
drivers/video/c2p.c [deleted file]
drivers/video/c2p.h
drivers/video/c2p_core.h [new file with mode: 0644]
drivers/video/c2p_iplan2.c [new file with mode: 0644]
drivers/video/c2p_planar.c [new file with mode: 0644]
drivers/video/console/fbcon.c
drivers/watchdog/Kconfig
drivers/watchdog/Makefile
drivers/watchdog/gef_wdt.c [new file with mode: 0644]
drivers/watchdog/pika_wdt.c [new file with mode: 0644]
drivers/watchdog/wm8350_wdt.c
drivers/zorro/.gitignore [new file with mode: 0644]
drivers/zorro/zorro-sysfs.c
drivers/zorro/zorro.c
drivers/zorro/zorro.h
firmware/Makefile
firmware/WHENCE
firmware/mts_cdma.fw.ihex [new file with mode: 0644]
firmware/mts_edge.fw.ihex [new file with mode: 0644]
firmware/mts_gsm.fw.ihex [new file with mode: 0644]
fs/dlm/debug_fs.c
fs/dlm/dlm_internal.h
fs/dlm/lock.c
fs/dlm/lockspace.c
fs/dlm/recover.c
include/asm-m68k/unistd.h
include/linux/dio.h
include/linux/dmaengine.h
include/linux/mISDNif.h
include/linux/mfd/pcf50633/adc.h [new file with mode: 0644]
include/linux/mfd/pcf50633/core.h [new file with mode: 0644]
include/linux/mfd/pcf50633/gpio.h [new file with mode: 0644]
include/linux/mfd/pcf50633/mbc.h [new file with mode: 0644]
include/linux/mfd/pcf50633/pmic.h [new file with mode: 0644]
include/net/wimax.h
include/sound/soc-dapm.h
include/sound/soc.h
kernel/async.c
kernel/sched.c
kernel/sched_debug.c
net/bridge/netfilter/ebtables.c
net/core/dev.c
net/dccp/ccids/Kconfig
net/dccp/ccids/lib/tfrc.c
net/tipc/bcast.h
net/xfrm/xfrm_ipcomp.c
scripts/markup_oops.pl
sound/oss/dmasound/dmasound_atari.c
sound/oss/dmasound/dmasound_q40.c
sound/pci/hda/hda_beep.c
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_analog.c
sound/pci/hda/patch_nvhdmi.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/twl4030.c
sound/soc/soc-core.c
sound/soc/soc-dapm.c
sound/usb/caiaq/caiaq-device.c
sound/usb/caiaq/caiaq-device.h
sound/usb/caiaq/caiaq-midi.c

index 907a5533c845792e74fb9365378a527f45eb8b8a..c5b5212cc3f91544f42b27f73323f9cf0a9bfc42 100644 (file)
@@ -72,10 +72,14 @@ static struct irq_controller amiga_irq_controller = {
 
 void __init amiga_init_IRQ(void)
 {
-       request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL);
-       request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL);
-       request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL);
-       request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL);
+       if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
+               pr_err("Couldn't register int%d\n", 1);
+       if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
+               pr_err("Couldn't register int%d\n", 3);
+       if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
+               pr_err("Couldn't register int%d\n", 4);
+       if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
+               pr_err("Couldn't register int%d\n", 5);
 
        m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
 
index 343fab49bd9a751435ae710bd4e848c9b6abd6ec..ecd0f7ca6f0e34caca534e4dcc3a445805649741 100644 (file)
@@ -176,5 +176,7 @@ void __init cia_init_IRQ(struct ciabase *base)
        /* override auto int and install CIA handler */
        m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
        m68k_irq_startup(base->handler_irq);
-       request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base);
+       if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
+                       base->name, base))
+               pr_err("Couldn't register %s interrupt\n", base->name);
 }
index ab9862c3a136f4bc49f744b04bd2feae51912e83..6e562751ad51b5653181165d8b4ffc54f6cb1b8b 100644 (file)
@@ -493,7 +493,8 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
         * Please don't change this to use ciaa, as it interferes with the
         * SCSI code. We'll have to take a look at this later
         */
-       request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
+       if (request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL))
+               pr_err("Couldn't register timer interrupt\n");
        /* start timer */
        ciab.cra |= 0x11;
 }
index 78df98f2029af9e5556f33973c71949da070a8fc..8d3eafab1ffeb0f89aae3a64697aa47827a7b11b 100644 (file)
@@ -31,10 +31,6 @@ extern unsigned long dn_gettimeoffset(void);
 extern int dn_dummy_hwclk(int, struct rtc_time *);
 extern int dn_dummy_set_clock_mmss(unsigned long);
 extern void dn_dummy_reset(void);
-extern void dn_dummy_waitbut(void);
-extern struct fb_info *dn_fb_init(long *);
-extern void dn_dummy_debug_init(void);
-extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
 #ifdef CONFIG_HEARTBEAT
 static void dn_heartbeat(int on);
 #endif
@@ -204,7 +200,8 @@ void dn_sched_init(irq_handler_t timer_routine)
        printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
 #endif
 
-       request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine);
+       if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine))
+               pr_err("Couldn't register timer interrupt\n");
 }
 
 unsigned long dn_gettimeoffset(void) {
index c038b7c7eff0e8ea20f009b83eb4b1658040a229..a5f33c059979077ea17229a97c36fe692041cb23 100644 (file)
@@ -33,7 +33,6 @@
 #include <asm/atari_joystick.h>
 #include <asm/irq.h>
 
-extern unsigned int keymap_count;
 
 /* Hook for MIDI serial driver */
 void (*atari_MIDI_interrupt_hook) (void);
@@ -567,14 +566,19 @@ static int atari_keyb_done = 0;
 
 int atari_keyb_init(void)
 {
+       int error;
+
        if (atari_keyb_done)
                return 0;
 
        kb_state.state = KEYBOARD;
        kb_state.len = 0;
 
-       request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
-                   "keyboard/mouse/MIDI", atari_keyboard_interrupt);
+       error = request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt,
+                           IRQ_TYPE_SLOW, "keyboard/mouse/MIDI",
+                           atari_keyboard_interrupt);
+       if (error)
+               return error;
 
        atari_turnoff_irq(IRQ_MFP_ACIA);
        do {
index d1bd029a34ac612acfe5b04936a8dab1821ce2de..604329fafbb86d2bd4219a06b6c5a384bc0225e8 100644 (file)
@@ -179,8 +179,9 @@ EXPORT_SYMBOL(stdma_islocked);
 void __init stdma_init(void)
 {
        stdma_isr = NULL;
-       request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
-                   "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
+       if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
+                       "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int))
+               pr_err("Couldn't register ST-DMA interrupt\n");
 }
 
 
index 1edde27fa32dbb600dd5d07822cfd0bb5281b992..d076ff8d1b39138ba16b4483d2874a7d5b4bcaa9 100644 (file)
@@ -31,8 +31,9 @@ atari_sched_init(irq_handler_t timer_routine)
     /* start timer C, div = 1:100 */
     mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
     /* install interrupt service routine for MFP Timer C */
-    request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
-                "timer", timer_routine);
+    if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
+                   "timer", timer_routine))
+       pr_err("Couldn't register timer interrupt\n");
 }
 
 /* ++andreas: gettimeoffset fixed to check for pending interrupt */
index c072595928c06d0496df7ec0b9a197b763709925..9fe6fefb5e142f5c238441d885fe6ddc076fe19e 100644 (file)
@@ -43,7 +43,6 @@ extern unsigned long bvme6000_gettimeoffset (void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
 extern int bvme6000_set_clock_mmss (unsigned long);
 extern void bvme6000_reset (void);
-extern void bvme6000_waitbut(void);
 void bvme6000_set_vectors (void);
 
 /* Save tick handler routine pointer, will point to do_timer() in
index dd7c8a2583d3395eaa877580905c821f9556e3c6..f6312c7d87276a1c2e4b23005874a0b247689c8a 100644 (file)
@@ -70,7 +70,8 @@ void __init hp300_sched_init(irq_handler_t vector)
 
   asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
 
-  request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
+  if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
+    pr_err("Couldn't register timer interrupt\n");
 
   out_8(CLOCKBASE + CLKCR2, 0x1);              /* select CR1 */
   out_8(CLOCKBASE + CLKCR1, 0x40);             /* enable irq */
diff --git a/arch/m68k/kernel/.gitignore b/arch/m68k/kernel/.gitignore
new file mode 100644 (file)
index 0000000..c5f676c
--- /dev/null
@@ -0,0 +1 @@
+vmlinux.lds
index f28404d9a2bc3594438904f9b23bf97112534b63..5b780826647cce7e90bedfc8243c302c91ffaa71 100644 (file)
@@ -424,7 +424,7 @@ resume:
 .data
 ALIGN
 sys_call_table:
-       .long sys_ni_syscall    /* 0  -  old "setup()" system call*/
+       .long sys_restart_syscall       /* 0 - old "setup()" system call, used for restarting */
        .long sys_exit
        .long sys_fork
        .long sys_read
index 4d97bd2bd573845db42d11b8b03c096b5148eac9..303730afb1c9d5ef0163c7640fee6bc3c057bdc1 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/initrd.h>
 
 #include <asm/bootinfo.h>
+#include <asm/sections.h>
 #include <asm/setup.h>
 #include <asm/fpu.h>
 #include <asm/irq.h>
@@ -62,7 +63,6 @@ EXPORT_SYMBOL(vme_brdtype);
 int m68k_is040or060;
 EXPORT_SYMBOL(m68k_is040or060);
 
-extern int end;
 extern unsigned long availmem;
 
 int m68k_num_memory;
@@ -215,11 +215,10 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
 
 void __init setup_arch(char **cmdline_p)
 {
-       extern int _etext, _edata, _end;
        int i;
 
        /* The bootinfo is located right after the kernel bss */
-       m68k_parse_bootinfo((const struct bi_record *)&_end);
+       m68k_parse_bootinfo((const struct bi_record *)_end);
 
        if (CPU_IS_040)
                m68k_is040or060 = 4;
@@ -252,9 +251,9 @@ void __init setup_arch(char **cmdline_p)
        }
 
        init_mm.start_code = PAGE_OFFSET;
-       init_mm.end_code = (unsigned long) &_etext;
-       init_mm.end_data = (unsigned long) &_edata;
-       init_mm.brk = (unsigned long) &_end;
+       init_mm.end_code = (unsigned long)_etext;
+       init_mm.end_data = (unsigned long)_edata;
+       init_mm.brk = (unsigned long)_end;
 
        *cmdline_p = m68k_command_line;
        memcpy(boot_command_line, *cmdline_p, CL_SIZE);
index f9af893cd2892dde83b6e089d370d093f6db2ac0..de2d05ddd86d9d8ca6c7699f3d93d9ca0ad05861 100644 (file)
@@ -326,6 +326,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
        struct sigcontext context;
        int err;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        /* get previous context */
        if (copy_from_user(&context, usc, sizeof(context)))
                goto badframe;
@@ -411,6 +414,9 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
        unsigned long usp;
        int err;
 
+       /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        err = __get_user(temp, &uc->uc_mcontext.version);
        if (temp != MCONTEXT_VERSION)
                goto badframe;
@@ -937,6 +943,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
                regs->d0 = -EINTR;
                break;
 
+       case -ERESTART_RESTARTBLOCK:
+               if (!has_handler) {
+                       regs->d0 = __NR_restart_syscall;
+                       regs->pc -= 2;
+                       break;
+               }
+               regs->d0 = -EINTR;
+               break;
+
        case -ERESTARTSYS:
                if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
                        regs->d0 = -EINTR;
index 8a4919e4d36a4ef23c996b4a3f4a4dc51d4ddb1e..d9368c0709ba7fc913ffb27377d41ebe53cd2b97 100644 (file)
@@ -33,6 +33,7 @@ SECTIONS
        } :data
   /* End of data goes *here* so that freeing init code works properly. */
   _edata = .;
+  NOTES
 
   /* will be freed after init */
   . = ALIGN(PAGE_SIZE);        /* Init code and data */
index 245d16d078ad817c93bacf94fc15f72803e8e337..2a96bebd8969eb6ef304a00c8f833e010465881c 100644 (file)
@@ -92,7 +92,8 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
 void __init baboon_register_interrupts(void)
 {
        baboon_disabled = 0;
-       request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon);
+       if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
+               pr_err("Couldn't register baboon interrupt\n");
 }
 
 /*
index 8819b97be32401b096587de6dcdda41e504a1749..98b6bcfb37bf4c10aa7e073c899ef84b0e0d4854 100644 (file)
 
 struct mac_booter_data mac_bi_data;
 
-/* New m68k bootinfo stuff and videobase */
-
-extern int m68k_num_memory;
-extern struct mem_info m68k_memory[NUM_MEMINFO];
-
-extern struct mem_info m68k_ramdisk;
-
 /* The phys. video addr. - might be bogus on some machines */
 static unsigned long mac_orig_videoaddr;
 
@@ -61,7 +54,6 @@ static unsigned long mac_orig_videoaddr;
 extern unsigned long mac_gettimeoffset(void);
 extern int mac_hwclk(int, struct rtc_time *);
 extern int mac_set_clock_mmss(unsigned long);
-extern int show_mac_interrupts(struct seq_file *, void *);
 extern void iop_preinit(void);
 extern void iop_init(void);
 extern void via_init(void);
@@ -805,10 +797,6 @@ static void __init mac_identify(void)
                mac_bi_data.boottime, mac_bi_data.gmtbias);
        printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
                mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
-#if 0
-       printk("Ramdisk: addr 0x%lx size 0x%lx\n",
-               m68k_ramdisk.addr, m68k_ramdisk.size);
-#endif
 
        iop_init();
        via_init();
index 65dd77a742a341c493a64982b16a0ec5de60d445..bce074ceb768d9adf97e13c783263a719a9c1677 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/macints.h>
 
 extern unsigned long mac_videobase;
-extern unsigned long mac_videodepth;
 extern unsigned long mac_rowbytes;
 
 extern void mac_serial_print(const char *);
index 326fb9978094961221c14ce4a53a596ee3934816..1ad4e9d80eba7f5be93f530c262636136a01b5b8 100644 (file)
@@ -305,14 +305,16 @@ void __init iop_register_interrupts(void)
 {
        if (iop_ism_present) {
                if (oss_present) {
-                       request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
+                       if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
                                        IRQ_FLG_LOCK, "ISM IOP",
-                                       (void *) IOP_NUM_ISM);
+                                       (void *) IOP_NUM_ISM))
+                               pr_err("Couldn't register ISM IOP interrupt\n");
                        oss_irq_enable(IRQ_MAC_ADB);
                } else {
-                       request_irq(IRQ_VIA2_0, iop_ism_irq,
+                       if (request_irq(IRQ_VIA2_0, iop_ism_irq,
                                        IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
-                                       (void *) IOP_NUM_ISM);
+                                       (void *) IOP_NUM_ISM))
+                               pr_err("Couldn't register ISM IOP interrupt\n");
                }
                if (!iop_alive(iop_base[IOP_NUM_ISM])) {
                        printk("IOP: oh my god, they killed the ISM IOP!\n");
index 82e560c076ce31e1cf82968ac3622f7c58c9a135..23711074e0e2d7ce12342a4e89436a74bf0f77ff 100644 (file)
 #include <asm/errno.h>
 #include <asm/macints.h>
 #include <asm/irq_regs.h>
+#include <asm/mac_oss.h>
 
 #define DEBUG_SPURIOUS
 #define SHUTUP_SONIC
@@ -146,7 +147,6 @@ static int scc_mask;
  * VIA/RBV hooks
  */
 
-extern void via_init(void);
 extern void via_register_interrupts(void);
 extern void via_irq_enable(int);
 extern void via_irq_disable(int);
@@ -157,9 +157,6 @@ extern int  via_irq_pending(int);
  * OSS hooks
  */
 
-extern int oss_present;
-
-extern void oss_init(void);
 extern void oss_register_interrupts(void);
 extern void oss_irq_enable(int);
 extern void oss_irq_disable(int);
@@ -170,9 +167,6 @@ extern int  oss_irq_pending(int);
  * PSC hooks
  */
 
-extern int psc_present;
-
-extern void psc_init(void);
 extern void psc_register_interrupts(void);
 extern void psc_irq_enable(int);
 extern void psc_irq_disable(int);
@@ -191,12 +185,10 @@ extern void iop_register_interrupts(void);
 
 extern int baboon_present;
 
-extern void baboon_init(void);
 extern void baboon_register_interrupts(void);
 extern void baboon_irq_enable(int);
 extern void baboon_irq_disable(int);
 extern void baboon_irq_clear(int);
-extern int  baboon_irq_pending(int);
 
 /*
  * SCC interrupt routines
@@ -258,8 +250,9 @@ void __init mac_init_IRQ(void)
        if (baboon_present)
                baboon_register_interrupts();
        iop_register_interrupts();
-       request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
-                       mac_nmi_handler);
+       if (request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
+                       mac_nmi_handler))
+               pr_err("Couldn't register NMI\n");
 #ifdef DEBUG_MACINTS
        printk("mac_init_IRQ(): Done!\n");
 #endif
index a44c7086ab39a3b9352f2b3c5f0202b9e57bd471..5d818568b343719a7ab82f9a8fb075a048a9535e 100644 (file)
@@ -35,7 +35,6 @@
 
 #define RTC_OFFSET 2082844800
 
-extern struct mac_booter_data mac_bi_data;
 static void (*rom_reset)(void);
 
 #ifdef CONFIG_ADB_CUDA
index 8426501119ca82bf641b3098c4a726d696cc26bb..f3d23d6ebcf8a7ba35e7b07e70e0d4b7276f6ebb 100644 (file)
@@ -66,16 +66,21 @@ void __init oss_init(void)
 
 void __init oss_register_interrupts(void)
 {
-       request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
-                       "scsi", (void *) oss);
-       request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
-                       "scc", mac_scc_dispatch);
-       request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
-                       "nubus", (void *) oss);
-       request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
-                       "sound", (void *) oss);
-       request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
-                       "via1", (void *) via1);
+       if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
+                       "scsi", (void *) oss))
+               pr_err("Couldn't register %s interrupt\n", "scsi");
+       if (request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
+                       "scc", mac_scc_dispatch))
+               pr_err("Couldn't register %s interrupt\n", "scc");
+       if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
+                       "nubus", (void *) oss))
+               pr_err("Couldn't register %s interrupt\n", "nubus");
+       if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
+                       "sound", (void *) oss))
+               pr_err("Couldn't register %s interrupt\n", "sound");
+       if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
+                       "via1", (void *) via1))
+               pr_err("Couldn't register %s interrupt\n", "via1");
 }
 
 /*
index f84a4dd64f94be9788bbea2affed886ef4e78b3f..ba6ccab64018fb9badeafd7b8bbacb51518a5613 100644 (file)
@@ -117,10 +117,14 @@ void __init psc_init(void)
 
 void __init psc_register_interrupts(void)
 {
-       request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30);
-       request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40);
-       request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50);
-       request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60);
+       if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
+               pr_err("Couldn't register psc%d interrupt\n", 3);
+       if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
+               pr_err("Couldn't register psc%d interrupt\n", 4);
+       if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
+               pr_err("Couldn't register psc%d interrupt\n", 5);
+       if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
+               pr_err("Couldn't register psc%d interrupt\n", 6);
 }
 
 /*
index f01d418e64fed5c1fa6c67f9566577d774ec2785..7d97ba54536e6997a5143942737653f8188ee361 100644 (file)
@@ -34,6 +34,7 @@
 #include <asm/macints.h>
 #include <asm/mac_via.h>
 #include <asm/mac_psc.h>
+#include <asm/mac_oss.h>
 
 volatile __u8 *via1, *via2;
 int rbv_present;
@@ -84,7 +85,6 @@ void via_irq_disable(int irq);
 void via_irq_clear(int irq);
 
 extern irqreturn_t mac_scc_dispatch(int, void *);
-extern int oss_present;
 
 /*
  * Initialize the VIAs
@@ -283,7 +283,8 @@ void __init via_init_clock(irq_handler_t func)
        via1[vT1CL] = MAC_CLOCK_LOW;
        via1[vT1CH] = MAC_CLOCK_HIGH;
 
-       request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
+       if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
+               pr_err("Couldn't register %s interrupt\n", "timer");
 }
 
 /*
@@ -293,25 +294,31 @@ void __init via_init_clock(irq_handler_t func)
 void __init via_register_interrupts(void)
 {
        if (via_alt_mapping) {
-               request_irq(IRQ_AUTO_1, via1_irq,
+               if (request_irq(IRQ_AUTO_1, via1_irq,
                                IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
-                               (void *) via1);
-               request_irq(IRQ_AUTO_6, via1_irq,
+                               (void *) via1))
+                       pr_err("Couldn't register %s interrupt\n", "software");
+               if (request_irq(IRQ_AUTO_6, via1_irq,
                                IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1);
+                               (void *) via1))
+                       pr_err("Couldn't register %s interrupt\n", "via1");
        } else {
-               request_irq(IRQ_AUTO_1, via1_irq,
+               if (request_irq(IRQ_AUTO_1, via1_irq,
                                IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
-                               (void *) via1);
+                               (void *) via1))
+                       pr_err("Couldn't register %s interrupt\n", "via1");
        }
-       request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-                       "via2", (void *) via2);
+       if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
+                       "via2", (void *) via2))
+               pr_err("Couldn't register %s interrupt\n", "via2");
        if (!psc_present) {
-               request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
-                               "scc", mac_scc_dispatch);
+               if (request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
+                               "scc", mac_scc_dispatch))
+                       pr_err("Couldn't register %s interrupt\n", "scc");
        }
-       request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
-                       "nubus", (void *) via2);
+       if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
+                       IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
+               pr_err("Couldn't register %s interrupt\n", "nubus");
 }
 
 /*
index b1033ae0d6f084a357ddf318a8e67b10d789098a..367ecee2f981db6a5763ed4ac69452f20afbd79d 100644 (file)
@@ -24,7 +24,6 @@ static const struct fp_ext fp_one =
 
 extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src);
 extern struct fp_ext *fp_fdiv(struct fp_ext *dest, const struct fp_ext *src);
-extern struct fp_ext *fp_fmul(struct fp_ext *dest, const struct fp_ext *src);
 
 struct fp_ext *
 fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
index 81bb08ceec18372e16110a86fe38b7ca441ba383..0007b2adf3a3ebb85e1d1375f824f638e5c09ee0 100644 (file)
@@ -28,6 +28,7 @@
 #ifdef CONFIG_ATARI
 #include <asm/atari_stram.h>
 #endif
+#include <asm/sections.h>
 #include <asm/tlb.h>
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -73,9 +74,6 @@ extern void init_pointer_table(unsigned long ptable);
 
 /* References to section boundaries */
 
-extern char _text[], _etext[];
-extern char __init_begin[], __init_end[];
-
 extern pmd_t *zero_pgtable;
 
 void __init mem_init(void)
index c5dbb9bdb32283c7978736a3b695907e1c076615..4665fc84b7dcc50ab43174bcf7760f43a5859533 100644 (file)
@@ -30,6 +30,7 @@
 #ifdef CONFIG_ATARI
 #include <asm/atari_stram.h>
 #endif
+#include <asm/sections.h>
 
 #undef DEBUG
 
@@ -301,14 +302,12 @@ void __init paging_init(void)
        }
 }
 
-extern char __init_begin, __init_end;
-
 void free_initmem(void)
 {
        unsigned long addr;
 
-       addr = (unsigned long)&__init_begin;
-       for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
+       addr = (unsigned long)__init_begin;
+       for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
                virt_to_page(addr)->flags &= ~(1 << PG_reserved);
                init_page_count(virt_to_page(addr));
                free_page(addr);
index 43cdf476ffab17cd690b1bb8e8abba98082755a4..100baaa692a14fecc4d1cf74c995d3b43f210e1c 100644 (file)
@@ -42,7 +42,6 @@ extern unsigned long mvme147_gettimeoffset (void);
 extern int mvme147_hwclk (int, struct rtc_time *);
 extern int mvme147_set_clock_mmss (unsigned long);
 extern void mvme147_reset (void);
-extern void mvme147_waitbut(void);
 
 
 static int bcd2int (unsigned char b);
@@ -115,8 +114,9 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
 void mvme147_sched_init (irq_handler_t timer_routine)
 {
        tick_handler = timer_routine;
-       request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
-               IRQ_FLG_REPLACE, "timer 1", NULL);
+       if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
+                       "timer 1", NULL))
+               pr_err("Couldn't register timer interrupt\n");
 
        /* Init the clock with a value */
        /* our clock goes off every 6.25us */
index 1521826fc3c7caef9a62935a2bde21f0f6135378..11edf61cc2c4cb864b5a092bf9e1b2ba018f15ee 100644 (file)
@@ -48,7 +48,6 @@ extern unsigned long mvme16x_gettimeoffset (void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
 extern int mvme16x_set_clock_mmss (unsigned long);
 extern void mvme16x_reset (void);
-extern void mvme16x_waitbut(void);
 
 int bcd2int (unsigned char b);
 
index 7110546e3c00f412dcc88c7ad69111feb890d339..31ab3f08bbda25ad37be9a26abeb3f511c25b554 100644 (file)
@@ -36,7 +36,6 @@
 #include <asm/machdep.h>
 #include <asm/q40_master.h>
 
-extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
 extern void q40_init_IRQ(void);
 static void q40_get_model(char *model);
 extern void q40_sched_init(irq_handler_t handler);
@@ -47,8 +46,6 @@ static unsigned int q40_get_ss(void);
 static int q40_set_clock_mmss(unsigned long);
 static int q40_get_rtc_pll(struct rtc_pll_info *pll);
 static int q40_set_rtc_pll(struct rtc_pll_info *pll);
-extern void q40_waitbut(void);
-void q40_set_vectors(void);
 
 extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
 
index 8dfaa201342e142726fc7d4671649da57148040a..2ca25bd01a961c37bbdd8a6b12efbf330e252f79 100644 (file)
 #include <asm/sun3mmu.h>
 #include <asm/rtc.h>
 #include <asm/machdep.h>
+#include <asm/idprom.h>
 #include <asm/intersil.h>
 #include <asm/irq.h>
+#include <asm/sections.h>
 #include <asm/segment.h>
 #include <asm/sun3ints.h>
 
-extern char _text, _end;
-
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
 extern unsigned long sun3_gettimeoffset(void);
 static void sun3_sched_init(irq_handler_t handler);
 extern void sun3_get_model (char* model);
-extern void idprom_init (void);
 extern int sun3_hwclk(int set, struct rtc_time *t);
 
 volatile char* clock_va;
-extern volatile unsigned char* sun3_intreg;
 extern unsigned long availmem;
 unsigned long num_pages;
 
@@ -149,7 +147,7 @@ void __init config_sun3(void)
        mach_halt            =  sun3_halt;
        mach_get_hardware_list = sun3_get_hardware_list;
 
-       memory_start = ((((int)&_end) + 0x2000) & ~0x1fff);
+       memory_start = ((((unsigned long)_end) + 0x2000) & ~0x1fff);
 // PROM seems to want the last couple of physical pages. --m
        memory_end   = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE;
 
index 60f9d4500d729e6d6422240879940414e555303a..3cd19390aae51fcfa73ebe35b8c8075249cf780e 100644 (file)
@@ -27,7 +27,6 @@
 #include <asm/mmu_context.h>
 #include <asm/dvma.h>
 
-extern void prom_reboot (char *) __attribute__ ((__noreturn__));
 
 #undef DEBUG_MMU_EMU
 #define DEBUG_PROM_MAPS
index 7364cd67455e94ba410d3aa4b245b62d8abdba1a..ad90393a336101e003a61dedcbc447350fe9aed2 100644 (file)
@@ -105,7 +105,10 @@ void __init sun3_init_IRQ(void)
        m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
        m68k_setup_user_interrupt(VEC_USER, 128, NULL);
 
-       request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
-       request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
-       request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL);
+       if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
+               pr_err("Couldn't register %s interrupt\n", "int5");
+       if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL))
+               pr_err("Couldn't register %s interrupt\n", "int7");
+       if (request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL))
+               pr_err("Couldn't register %s interrupt\n", "vec255");
 }
index 2b1ca2db070fc429e25cfb9ae9140c5b26f8cbe9..fc599fad4a546542a9ce0a05f9bfe2fe7baa7160 100644 (file)
@@ -23,7 +23,6 @@
 #include "time.h"
 
 volatile char *clock_va;
-extern volatile unsigned char *sun3_intreg;
 
 extern void sun3_get_model(char *model);
 
index a5255e7c79e004001a8f55c82e33d964198b403f..52c80c2a57f208924fb312a1ca1d03f02c4ea57b 100644 (file)
@@ -595,6 +595,44 @@ config WR_PPMC
          This enables support for the Wind River MIPS32 4KC PPMC evaluation
          board, which is based on GT64120 bridge chip.
 
+config CAVIUM_OCTEON_SIMULATOR
+       bool "Support for the Cavium Networks Octeon Simulator"
+       select CEVT_R4K
+       select 64BIT_PHYS_ADDR
+       select DMA_COHERENT
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
+       select CPU_CAVIUM_OCTEON
+       help
+         The Octeon simulator is software performance model of the Cavium
+         Octeon Processor. It supports simulating Octeon processors on x86
+         hardware.
+
+config CAVIUM_OCTEON_REFERENCE_BOARD
+       bool "Support for the Cavium Networks Octeon reference board"
+       select CEVT_R4K
+       select 64BIT_PHYS_ADDR
+       select DMA_COHERENT
+       select SYS_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_BIG_ENDIAN
+       select SYS_SUPPORTS_HIGHMEM
+       select SYS_HAS_EARLY_PRINTK
+       select CPU_CAVIUM_OCTEON
+       select SWAP_IO_SPACE
+       help
+         This option supports all of the Octeon reference boards from Cavium
+         Networks. It builds a kernel that dynamically determines the Octeon
+         CPU type and supports all known board reference implementations.
+         Some of the supported boards are:
+               EBT3000
+               EBH3000
+               EBH3100
+               Thunder
+               Kodama
+               Hikari
+         Say Y here for most Octeon reference boards.
+
 endchoice
 
 source "arch/mips/alchemy/Kconfig"
@@ -607,6 +645,7 @@ source "arch/mips/sgi-ip27/Kconfig"
 source "arch/mips/sibyte/Kconfig"
 source "arch/mips/txx9/Kconfig"
 source "arch/mips/vr41xx/Kconfig"
+source "arch/mips/cavium-octeon/Kconfig"
 
 endmenu
 
@@ -682,7 +721,11 @@ config CEVT_DS1287
 config CEVT_GT641XX
        bool
 
+config CEVT_R4K_LIB
+       bool
+
 config CEVT_R4K
+       select CEVT_R4K_LIB
        bool
 
 config CEVT_SB1250
@@ -697,7 +740,11 @@ config CSRC_BCM1480
 config CSRC_IOASIC
        bool
 
+config CSRC_R4K_LIB
+       bool
+
 config CSRC_R4K
+       select CSRC_R4K_LIB
        bool
 
 config CSRC_SB1250
@@ -835,6 +882,9 @@ config IRQ_GT641XX
 config IRQ_GIC
        bool
 
+config IRQ_CPU_OCTEON
+       bool
+
 config MIPS_BOARDS_GEN
        bool
 
@@ -924,7 +974,7 @@ config BOOT_ELF32
 config MIPS_L1_CACHE_SHIFT
        int
        default "4" if MACH_DECSTATION || MIKROTIK_RB532
-       default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM
+       default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
        default "4" if PMC_MSP4200_EVAL
        default "5"
 
@@ -1185,6 +1235,23 @@ config CPU_SB1
        select CPU_SUPPORTS_HIGHMEM
        select WEAK_ORDERING
 
+config CPU_CAVIUM_OCTEON
+       bool "Cavium Octeon processor"
+       select IRQ_CPU
+       select IRQ_CPU_OCTEON
+       select CPU_HAS_PREFETCH
+       select CPU_SUPPORTS_64BIT_KERNEL
+       select SYS_SUPPORTS_SMP
+       select NR_CPUS_DEFAULT_16
+       select WEAK_ORDERING
+       select WEAK_REORDERING_BEYOND_LLSC
+       select CPU_SUPPORTS_HIGHMEM
+       help
+         The Cavium Octeon processor is a highly integrated chip containing
+         many ethernet hardware widgets for networking tasks. The processor
+         can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets.
+         Full details can be found at http://www.caviumnetworks.com.
+
 endchoice
 
 config SYS_HAS_CPU_LOONGSON2
@@ -1285,7 +1352,7 @@ config CPU_MIPSR1
 
 config CPU_MIPSR2
        bool
-       default y if CPU_MIPS32_R2 || CPU_MIPS64_R2
+       default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
 
 config SYS_SUPPORTS_32BIT_KERNEL
        bool
index 28c55f608913c5da94e39127f62cdb72b94650a6..21b00e95daefac7d36c641c308a84b05fa8f92d2 100644 (file)
@@ -144,6 +144,10 @@ cflags-$(CONFIG_CPU_SB1)   += $(call cc-option,-march=sb1,-march=r5000) \
 cflags-$(CONFIG_CPU_R8000)     += -march=r8000 -Wa,--trap
 cflags-$(CONFIG_CPU_R10000)    += $(call cc-option,-march=r10000,-march=r8000) \
                        -Wa,--trap
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += $(call cc-option,-march=octeon) -Wa,--trap
+ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON))))
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
+endif
 
 cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
 cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
@@ -184,84 +188,84 @@ cflags-$(CONFIG_SOC_AU1X00)       += -I$(srctree)/arch/mips/include/asm/mach-au1x00
 #
 # AMD Alchemy Pb1000 eval board
 #
-libs-$(CONFIG_MIPS_PB1000)     += arch/mips/alchemy/pb1000/
+core-$(CONFIG_MIPS_PB1000)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_PB1000)   += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
 load-$(CONFIG_MIPS_PB1000)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Pb1100 eval board
 #
-libs-$(CONFIG_MIPS_PB1100)     += arch/mips/alchemy/pb1100/
+core-$(CONFIG_MIPS_PB1100)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_PB1100)   += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
 load-$(CONFIG_MIPS_PB1100)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Pb1500 eval board
 #
-libs-$(CONFIG_MIPS_PB1500)     += arch/mips/alchemy/pb1500/
+core-$(CONFIG_MIPS_PB1500)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_PB1500)   += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
 load-$(CONFIG_MIPS_PB1500)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Pb1550 eval board
 #
-libs-$(CONFIG_MIPS_PB1550)     += arch/mips/alchemy/pb1550/
+core-$(CONFIG_MIPS_PB1550)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_PB1550)   += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
 load-$(CONFIG_MIPS_PB1550)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Pb1200 eval board
 #
-libs-$(CONFIG_MIPS_PB1200)     += arch/mips/alchemy/pb1200/
+core-$(CONFIG_MIPS_PB1200)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_PB1200)   += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
 load-$(CONFIG_MIPS_PB1200)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Db1000 eval board
 #
-libs-$(CONFIG_MIPS_DB1000)     += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1000)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_DB1000)   += -I$(srctree)/arch/mips/include/asm/mach-db1x00
 load-$(CONFIG_MIPS_DB1000)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Db1100 eval board
 #
-libs-$(CONFIG_MIPS_DB1100)     += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1100)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_DB1100)   += -I$(srctree)/arch/mips/include/asm/mach-db1x00
 load-$(CONFIG_MIPS_DB1100)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Db1500 eval board
 #
-libs-$(CONFIG_MIPS_DB1500)     += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1500)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_DB1500)   += -I$(srctree)/arch/mips/include/asm/mach-db1x00
 load-$(CONFIG_MIPS_DB1500)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Db1550 eval board
 #
-libs-$(CONFIG_MIPS_DB1550)     += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_DB1550)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_DB1550)   += -I$(srctree)/arch/mips/include/asm/mach-db1x00
 load-$(CONFIG_MIPS_DB1550)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Db1200 eval board
 #
-libs-$(CONFIG_MIPS_DB1200)     += arch/mips/alchemy/pb1200/
+core-$(CONFIG_MIPS_DB1200)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_DB1200)   += -I$(srctree)/arch/mips/include/asm/mach-db1x00
 load-$(CONFIG_MIPS_DB1200)     += 0xffffffff80100000
 
 #
 # AMD Alchemy Bosporus eval board
 #
-libs-$(CONFIG_MIPS_BOSPORUS)   += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_BOSPORUS)   += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
 load-$(CONFIG_MIPS_BOSPORUS)   += 0xffffffff80100000
 
 #
 # AMD Alchemy Mirage eval board
 #
-libs-$(CONFIG_MIPS_MIRAGE)     += arch/mips/alchemy/db1x00/
+core-$(CONFIG_MIPS_MIRAGE)     += arch/mips/alchemy/devboards/
 cflags-$(CONFIG_MIPS_MIRAGE)   += -I$(srctree)/arch/mips/include/asm/mach-db1x00
 load-$(CONFIG_MIPS_MIRAGE)     += 0xffffffff80100000
 
@@ -586,6 +590,18 @@ core-$(CONFIG_TOSHIBA_RBTX4927)    += arch/mips/txx9/rbtx4927/
 core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/
 core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/
 
+#
+# Cavium Octeon
+#
+core-$(CONFIG_CPU_CAVIUM_OCTEON)       += arch/mips/cavium-octeon/
+cflags-$(CONFIG_CPU_CAVIUM_OCTEON)     += -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon
+core-$(CONFIG_CPU_CAVIUM_OCTEON)       += arch/mips/cavium-octeon/executive/
+ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
+load-$(CONFIG_CPU_CAVIUM_OCTEON)       += 0xffffffff84100000
+else
+load-$(CONFIG_CPU_CAVIUM_OCTEON)       += 0xffffffff81100000
+endif
+
 cflags-y                       += -I$(srctree)/arch/mips/include/asm/mach-generic
 drivers-$(CONFIG_PCI)          += arch/mips/pci/
 
index e4a057d80ab6edddaf7f075ef781886833e7a024..7f8ef13d0014e3dd022ef4a354fe23c5982c49d8 100644 (file)
@@ -128,9 +128,10 @@ config SOC_AU1200
 config SOC_AU1X00
        bool
        select 64BIT_PHYS_ADDR
-       select CEVT_R4K
-       select CSRC_R4K
+       select CEVT_R4K_LIB
+       select CSRC_R4K_LIB
        select IRQ_CPU
        select SYS_HAS_CPU_MIPS32_R1
        select SYS_SUPPORTS_32BIT_KERNEL
        select SYS_SUPPORTS_APM_EMULATION
+       select GENERIC_HARDIRQS_NO__DO_IRQ
index df48fd65bbf3989cfe5e8be4997214277b2a54a3..d50d4764eafe6be2a1f19db028d4008150aeb602 100644 (file)
@@ -6,8 +6,8 @@
 #
 
 obj-y += prom.o irq.o puts.o time.o reset.o \
-       au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
-       sleeper.o cputable.o dma.o dbdma.o gpio.o
+       clocks.o platform.o power.o setup.o \
+       sleeper.o dma.o dbdma.o gpio.o
 
 obj-$(CONFIG_PCI)              += pci.o
 
diff --git a/arch/mips/alchemy/common/au1xxx_irqmap.c b/arch/mips/alchemy/common/au1xxx_irqmap.c
deleted file mode 100644 (file)
index c7ca159..0000000
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Au1xxx processor specific IRQ tables
- *
- * Copyright 2004 Embedded Edge, LLC
- *     dan@embeddededge.com
- *
- *  This program is free software; you can redistribute         it and/or modify it
- *  under  the terms of         the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <au1000.h>
-
-/* The IC0 interrupt table.  This is processor, rather than
- * board dependent, so no reason to keep this info in the board
- * dependent files.
- *
- * Careful if you change match 2 request!
- * The interrupt handler is called directly from the low level dispatch code.
- */
-struct au1xxx_irqmap __initdata au1xxx_ic0_map[] = {
-
-#if defined(CONFIG_SOC_AU1000)
-       { AU1000_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_UART2_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
-       { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
-
-#elif defined(CONFIG_SOC_AU1500)
-
-       { AU1500_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
-       { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1500_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1500_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
-
-#elif defined(CONFIG_SOC_AU1100)
-
-       { AU1100_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1100_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1100_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1100_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_SSI0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_SSI1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+1, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+2, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+3, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+4, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+5, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+6, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_DMA_INT_BASE+7, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
-       { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_IRDA_TX_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_IRDA_RX_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_ACSYNC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1100_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       /* { AU1000_GPIO215_208_INT, INTC_INT_HIGH_LEVEL, 0 }, */
-       { AU1100_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_AC97C_INT, INTC_INT_RISE_EDGE, 0 },
-
-#elif defined(CONFIG_SOC_AU1550)
-
-       { AU1550_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_PCI_INTA, INTC_INT_LOW_LEVEL, 0 },
-       { AU1550_PCI_INTB, INTC_INT_LOW_LEVEL, 0 },
-       { AU1550_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_CRYPTO_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_PCI_INTC, INTC_INT_LOW_LEVEL, 0 },
-       { AU1550_PCI_INTD, INTC_INT_LOW_LEVEL, 0 },
-       { AU1550_PCI_RST_INT, INTC_INT_LOW_LEVEL, 0 },
-       { AU1550_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_UART3_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_PSC2_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_PSC3_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
-       { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1550_NAND_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1550_USB_DEV_REQ_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_USB_DEV_SUS_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1550_USB_HOST_INT, INTC_INT_LOW_LEVEL, 0 },
-       { AU1550_MAC0_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1550_MAC1_DMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-
-#elif defined(CONFIG_SOC_AU1200)
-
-       { AU1200_UART0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_SWT_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1200_SD_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_DDMA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_MAE_BE_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_UART1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_MAE_FE_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_PSC0_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_PSC1_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_AES_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_CAMERA_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1000_TOY_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_TOY_MATCH2_INT, INTC_INT_RISE_EDGE, 1 },
-       { AU1000_RTC_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH0_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH1_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1000_RTC_MATCH2_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1200_NAND_INT, INTC_INT_RISE_EDGE, 0 },
-       { AU1200_USB_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_LCD_INT, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1200_MAE_BOTH_INT, INTC_INT_HIGH_LEVEL, 0 },
-
-#else
-#error "Error: Unknown Alchemy SOC"
-#endif
-
-};
-
-int __initdata au1xxx_ic0_nr_irqs = ARRAY_SIZE(au1xxx_ic0_map);
index 043429d17c5fd9ec1e3b9ccf01b7f51cf4621d4c..d8991854530e2dbf50bd71297f7518a5a9e659a3 100644 (file)
  */
 
 #include <linux/module.h>
+#include <linux/spinlock.h>
+#include <asm/time.h>
 #include <asm/mach-au1x00/au1000.h>
 
+/*
+ * I haven't found anyone that doesn't use a 12 MHz source clock,
+ * but just in case.....
+ */
+#define AU1000_SRC_CLK 12000000
+
 static unsigned int au1x00_clock; /*  Hz */
-static unsigned int lcd_clock;    /* KHz */
 static unsigned long uart_baud_base;
 
+static DEFINE_SPINLOCK(time_lock);
+
 /*
  * Set the au1000_clock
  */
@@ -63,31 +72,45 @@ void set_au1x00_uart_baud_base(unsigned long new_baud_base)
 }
 
 /*
- * Calculate the Au1x00's LCD clock based on the current
- * cpu clock and the system bus clock, and try to keep it
- * below 40 MHz (the Pb1000 board can lock-up if the LCD
- * clock is over 40 MHz).
+ * We read the real processor speed from the PLL.  This is important
+ * because it is more accurate than computing it from the 32 KHz
+ * counter, if it exists.  If we don't have an accurate processor
+ * speed, all of the peripherals that derive their clocks based on
+ * this advertised speed will introduce error and sometimes not work
+ * properly.  This function is futher convoluted to still allow configurations
+ * to do that in case they have really, really old silicon with a
+ * write-only PLL register.                    -- Dan
  */
-void set_au1x00_lcd_clock(void)
+unsigned long au1xxx_calc_clock(void)
 {
-       unsigned int static_cfg0;
-       unsigned int sys_busclk = (get_au1x00_speed() / 1000) /
-                                 ((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2);
+       unsigned long cpu_speed;
+       unsigned long flags;
 
-       static_cfg0 = au_readl(MEM_STCFG0);
+       spin_lock_irqsave(&time_lock, flags);
 
-       if (static_cfg0 & (1 << 11))
-               lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
+       /*
+        * On early Au1000, sys_cpupll was write-only. Since these
+        * silicon versions of Au1000 are not sold by AMD, we don't bend
+        * over backwards trying to determine the frequency.
+        */
+       if (au1xxx_cpu_has_pll_wo())
+#ifdef CONFIG_SOC_AU1000_FREQUENCY
+               cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
+#else
+               cpu_speed = 396000000;
+#endif
        else
-               lcd_clock = sys_busclk / 4;
+               cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
 
-       if (lcd_clock > 50000) /* Epson MAX */
-               printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n",
-                                   lcd_clock);
-}
+       /* On Alchemy CPU:counter ratio is 1:1 */
+       mips_hpt_frequency = cpu_speed;
+       /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
+       set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
+                                                         & 0x03) + 2) * 16));
 
-unsigned int get_au1x00_lcd_clock(void)
-{
-       return lcd_clock;
+       spin_unlock_irqrestore(&time_lock, flags);
+
+       set_au1x00_speed(cpu_speed);
+
+       return cpu_speed;
 }
-EXPORT_SYMBOL(get_au1x00_lcd_clock);
diff --git a/arch/mips/alchemy/common/cputable.c b/arch/mips/alchemy/common/cputable.c
deleted file mode 100644 (file)
index ba6430b..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- *  arch/mips/au1000/common/cputable.c
- *
- *  Copyright (C) 2004 Dan Malek (dan@embeddededge.com)
- *     Copied from PowerPC and updated for Alchemy Au1xxx processors.
- *
- *  Copyright (C) 2001 Ben. Herrenschmidt (benh@kernel.crashing.org)
- *
- *  This program is free software; you can redistribute it and/or
- *  modify it under the terms of the GNU General Public License
- *  as published by the Free Software Foundation; either version
- *  2 of the License, or (at your option) any later version.
- */
-
-#include <asm/mach-au1x00/au1000.h>
-
-struct cpu_spec *cur_cpu_spec[NR_CPUS];
-
-/* With some thought, we can probably use the mask to reduce the
- * size of the table.
- */
-struct cpu_spec cpu_specs[] = {
-       { 0xffffffff, 0x00030100, "Au1000 DA", 1, 0, 1 },
-       { 0xffffffff, 0x00030201, "Au1000 HA", 1, 0, 1 },
-       { 0xffffffff, 0x00030202, "Au1000 HB", 1, 0, 1 },
-       { 0xffffffff, 0x00030203, "Au1000 HC", 1, 1, 0 },
-       { 0xffffffff, 0x00030204, "Au1000 HD", 1, 1, 0 },
-       { 0xffffffff, 0x01030200, "Au1500 AB", 1, 1, 0 },
-       { 0xffffffff, 0x01030201, "Au1500 AC", 0, 1, 0 },
-       { 0xffffffff, 0x01030202, "Au1500 AD", 0, 1, 0 },
-       { 0xffffffff, 0x02030200, "Au1100 AB", 1, 1, 0 },
-       { 0xffffffff, 0x02030201, "Au1100 BA", 1, 1, 0 },
-       { 0xffffffff, 0x02030202, "Au1100 BC", 1, 1, 0 },
-       { 0xffffffff, 0x02030203, "Au1100 BD", 0, 1, 0 },
-       { 0xffffffff, 0x02030204, "Au1100 BE", 0, 1, 0 },
-       { 0xffffffff, 0x03030200, "Au1550 AA", 0, 1, 0 },
-       { 0xffffffff, 0x04030200, "Au1200 AB", 0, 0, 0 },
-       { 0xffffffff, 0x04030201, "Au1200 AC", 1, 0, 0 },
-       { 0x00000000, 0x00000000, "Unknown Au1xxx", 1, 0, 0 }
-};
-
-void set_cpuspec(void)
-{
-       struct  cpu_spec *sp;
-       u32     prid;
-
-       prid = read_c0_prid();
-       sp = cpu_specs;
-       while ((prid & sp->prid_mask) != sp->prid_value)
-               sp++;
-       cur_cpu_spec[0] = sp;
-}
index 601ee9180ee4fcad79ce0837b4f3c63b73a88348..3ab6d80d150d742b42daea99d652b7a04734c662 100644 (file)
@@ -174,6 +174,11 @@ static dbdev_tab_t dbdev_tab[] = {
 
 #define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab)
 
+#ifdef CONFIG_PM
+static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][8];
+#endif
+
+
 static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
 
 static dbdev_tab_t *find_dbdev_id(u32 id)
@@ -975,4 +980,64 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
        return nbytes;
 }
 
+#ifdef CONFIG_PM
+void au1xxx_dbdma_suspend(void)
+{
+       int i;
+       u32 addr;
+
+       addr = DDMA_GLOBAL_BASE;
+       au1xxx_dbdma_pm_regs[0][0] = au_readl(addr + 0x00);
+       au1xxx_dbdma_pm_regs[0][1] = au_readl(addr + 0x04);
+       au1xxx_dbdma_pm_regs[0][2] = au_readl(addr + 0x08);
+       au1xxx_dbdma_pm_regs[0][3] = au_readl(addr + 0x0c);
+
+       /* save channel configurations */
+       for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
+               au1xxx_dbdma_pm_regs[i][0] = au_readl(addr + 0x00);
+               au1xxx_dbdma_pm_regs[i][1] = au_readl(addr + 0x04);
+               au1xxx_dbdma_pm_regs[i][2] = au_readl(addr + 0x08);
+               au1xxx_dbdma_pm_regs[i][3] = au_readl(addr + 0x0c);
+               au1xxx_dbdma_pm_regs[i][4] = au_readl(addr + 0x10);
+               au1xxx_dbdma_pm_regs[i][5] = au_readl(addr + 0x14);
+               au1xxx_dbdma_pm_regs[i][6] = au_readl(addr + 0x18);
+
+               /* halt channel */
+               au_writel(au1xxx_dbdma_pm_regs[i][0] & ~1, addr + 0x00);
+               au_sync();
+               while (!(au_readl(addr + 0x14) & 1))
+                       au_sync();
+
+               addr += 0x100;  /* next channel base */
+       }
+       /* disable channel interrupts */
+       au_writel(0, DDMA_GLOBAL_BASE + 0x0c);
+       au_sync();
+}
+
+void au1xxx_dbdma_resume(void)
+{
+       int i;
+       u32 addr;
+
+       addr = DDMA_GLOBAL_BASE;
+       au_writel(au1xxx_dbdma_pm_regs[0][0], addr + 0x00);
+       au_writel(au1xxx_dbdma_pm_regs[0][1], addr + 0x04);
+       au_writel(au1xxx_dbdma_pm_regs[0][2], addr + 0x08);
+       au_writel(au1xxx_dbdma_pm_regs[0][3], addr + 0x0c);
+
+       /* restore channel configurations */
+       for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
+               au_writel(au1xxx_dbdma_pm_regs[i][0], addr + 0x00);
+               au_writel(au1xxx_dbdma_pm_regs[i][1], addr + 0x04);
+               au_writel(au1xxx_dbdma_pm_regs[i][2], addr + 0x08);
+               au_writel(au1xxx_dbdma_pm_regs[i][3], addr + 0x0c);
+               au_writel(au1xxx_dbdma_pm_regs[i][4], addr + 0x10);
+               au_writel(au1xxx_dbdma_pm_regs[i][5], addr + 0x14);
+               au_writel(au1xxx_dbdma_pm_regs[i][6], addr + 0x18);
+               au_sync();
+               addr += 0x100;  /* next channel base */
+       }
+}
+#endif /* CONFIG_PM */
 #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
index 40c6ceceb5f9149f4f5a352c504cb6301b22a6fc..c88c821b4c36c00398b66b8a53fcc1d75c07531f 100644 (file)
@@ -24,6 +24,7 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
+
 #include <linux/bitops.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <asm/mach-pb1x00/pb1000.h>
 #endif
 
-#define EXT_INTC0_REQ0 2 /* IP 2 */
-#define EXT_INTC0_REQ1 3 /* IP 3 */
-#define EXT_INTC1_REQ0 4 /* IP 4 */
-#define EXT_INTC1_REQ1 5 /* IP 5 */
-#define MIPS_TIMER_IP  7 /* IP 7 */
-
-void (*board_init_irq)(void) __initdata = NULL;
+static int au1x_ic_settype(unsigned int irq, unsigned int flow_type);
+
+/* per-processor fixed function irqs */
+struct au1xxx_irqmap au1xxx_ic0_map[] __initdata = {
+
+#if defined(CONFIG_SOC_AU1000)
+       { AU1000_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_UART2_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+       { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
+
+#elif defined(CONFIG_SOC_AU1500)
+
+       { AU1500_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1000_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1500_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1000_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+       { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1500_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1500_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
+
+#elif defined(CONFIG_SOC_AU1100)
+
+       { AU1100_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1100_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1100_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1100_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_SSI0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_SSI1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+1, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+2, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+3, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+4, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+5, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+6, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_DMA_INT_BASE+7, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+       { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_IRDA_TX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_IRDA_RX_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1000_ACSYNC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1100_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1100_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_AC97C_INT, IRQ_TYPE_EDGE_RISING, 0 },
+
+#elif defined(CONFIG_SOC_AU1550)
+
+       { AU1550_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_PCI_INTA, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1550_PCI_INTB, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1550_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_CRYPTO_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_PCI_INTC, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1550_PCI_INTD, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1550_PCI_RST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1550_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_UART3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_PSC2_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_PSC3_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+       { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1550_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1550_USB_DEV_REQ_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_USB_DEV_SUS_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1550_USB_HOST_INT, IRQ_TYPE_LEVEL_LOW, 0 },
+       { AU1550_MAC0_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1550_MAC1_DMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+
+#elif defined(CONFIG_SOC_AU1200)
+
+       { AU1200_UART0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_SWT_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1200_SD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_DDMA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_MAE_BE_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_UART1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_MAE_FE_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_PSC0_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_PSC1_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_AES_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_CAMERA_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1000_TOY_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_TOY_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 1 },
+       { AU1000_RTC_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH0_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH1_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1000_RTC_MATCH2_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1200_NAND_INT, IRQ_TYPE_EDGE_RISING, 0 },
+       { AU1200_USB_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_LCD_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+       { AU1200_MAE_BOTH_INT, IRQ_TYPE_LEVEL_HIGH, 0 },
+
+#else
+#error "Error: Unknown Alchemy SOC"
+#endif
+};
 
-static DEFINE_SPINLOCK(irq_lock);
 
 #ifdef CONFIG_PM
 
@@ -130,67 +288,47 @@ void restore_au1xxx_intctl(void)
 #endif /* CONFIG_PM */
 
 
-inline void local_enable_irq(unsigned int irq_nr)
+static void au1x_ic0_unmask(unsigned int irq_nr)
 {
        unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
-       if (bit >= 32) {
-               au_writel(1 << (bit - 32), IC1_MASKSET);
-               au_writel(1 << (bit - 32), IC1_WAKESET);
-       } else {
-               au_writel(1 << bit, IC0_MASKSET);
-               au_writel(1 << bit, IC0_WAKESET);
-       }
+       au_writel(1 << bit, IC0_MASKSET);
+       au_writel(1 << bit, IC0_WAKESET);
        au_sync();
 }
 
-
-inline void local_disable_irq(unsigned int irq_nr)
+static void au1x_ic1_unmask(unsigned int irq_nr)
 {
-       unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+       unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+       au_writel(1 << bit, IC1_MASKSET);
+       au_writel(1 << bit, IC1_WAKESET);
 
-       if (bit >= 32) {
-               au_writel(1 << (bit - 32), IC1_MASKCLR);
-               au_writel(1 << (bit - 32), IC1_WAKECLR);
-       } else {
-               au_writel(1 << bit, IC0_MASKCLR);
-               au_writel(1 << bit, IC0_WAKECLR);
-       }
+/* very hacky. does the pb1000 cpld auto-disable this int?
+ * nowhere in the current kernel sources is it disabled.       --mlau
+ */
+#if defined(CONFIG_MIPS_PB1000)
+       if (irq_nr == AU1000_GPIO_15)
+               au_writel(0x4000, PB1000_MDR); /* enable int */
+#endif
        au_sync();
 }
 
-
-static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
+static void au1x_ic0_mask(unsigned int irq_nr)
 {
        unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
-       if (bit >= 32) {
-               au_writel(1 << (bit - 32), IC1_RISINGCLR);
-               au_writel(1 << (bit - 32), IC1_MASKCLR);
-       } else {
-               au_writel(1 << bit, IC0_RISINGCLR);
-               au_writel(1 << bit, IC0_MASKCLR);
-       }
+       au_writel(1 << bit, IC0_MASKCLR);
+       au_writel(1 << bit, IC0_WAKECLR);
        au_sync();
 }
 
-
-static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
+static void au1x_ic1_mask(unsigned int irq_nr)
 {
-       unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
-       if (bit >= 32) {
-               au_writel(1 << (bit - 32), IC1_FALLINGCLR);
-               au_writel(1 << (bit - 32), IC1_MASKCLR);
-       } else {
-               au_writel(1 << bit, IC0_FALLINGCLR);
-               au_writel(1 << bit, IC0_MASKCLR);
-       }
+       unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+       au_writel(1 << bit, IC1_MASKCLR);
+       au_writel(1 << bit, IC1_WAKECLR);
        au_sync();
 }
 
-
-static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
+static void au1x_ic0_ack(unsigned int irq_nr)
 {
        unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
 
@@ -198,349 +336,229 @@ static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
         * This may assume that we don't get interrupts from
         * both edges at once, or if we do, that we don't care.
         */
-       if (bit >= 32) {
-               au_writel(1 << (bit - 32), IC1_FALLINGCLR);
-               au_writel(1 << (bit - 32), IC1_RISINGCLR);
-               au_writel(1 << (bit - 32), IC1_MASKCLR);
-       } else {
-               au_writel(1 << bit, IC0_FALLINGCLR);
-               au_writel(1 << bit, IC0_RISINGCLR);
-               au_writel(1 << bit, IC0_MASKCLR);
-       }
+       au_writel(1 << bit, IC0_FALLINGCLR);
+       au_writel(1 << bit, IC0_RISINGCLR);
        au_sync();
 }
 
-static inline void mask_and_ack_level_irq(unsigned int irq_nr)
+static void au1x_ic1_ack(unsigned int irq_nr)
 {
-       local_disable_irq(irq_nr);
-       au_sync();
-#if defined(CONFIG_MIPS_PB1000)
-       if (irq_nr == AU1000_GPIO_15) {
-               au_writel(0x8000, PB1000_MDR); /* ack int */
-               au_sync();
-       }
-#endif
-}
-
-static void end_irq(unsigned int irq_nr)
-{
-       if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-               local_enable_irq(irq_nr);
+       unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
 
-#if defined(CONFIG_MIPS_PB1000)
-       if (irq_nr == AU1000_GPIO_15) {
-               au_writel(0x4000, PB1000_MDR); /* enable int */
-               au_sync();
-       }
-#endif
+       /*
+        * This may assume that we don't get interrupts from
+        * both edges at once, or if we do, that we don't care.
+        */
+       au_writel(1 << bit, IC1_FALLINGCLR);
+       au_writel(1 << bit, IC1_RISINGCLR);
+       au_sync();
 }
 
-unsigned long save_local_and_disable(int controller)
+static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
 {
-       int i;
-       unsigned long flags, mask;
-
-       spin_lock_irqsave(&irq_lock, flags);
-       if (controller) {
-               mask = au_readl(IC1_MASKSET);
-               for (i = 32; i < 64; i++)
-                       local_disable_irq(i);
-       } else {
-               mask = au_readl(IC0_MASKSET);
-               for (i = 0; i < 32; i++)
-                       local_disable_irq(i);
-       }
-       spin_unlock_irqrestore(&irq_lock, flags);
-
-       return mask;
-}
+       unsigned int bit = irq - AU1000_INTC1_INT_BASE;
+       unsigned long wakemsk, flags;
 
-void restore_local_and_enable(int controller, unsigned long mask)
-{
-       int i;
-       unsigned long flags, new_mask;
-
-       spin_lock_irqsave(&irq_lock, flags);
-       for (i = 0; i < 32; i++)
-               if (mask & (1 << i)) {
-                       if (controller)
-                               local_enable_irq(i + 32);
-                       else
-                               local_enable_irq(i);
-               }
+       /* only GPIO 0-7 can act as wakeup source: */
+       if ((irq < AU1000_GPIO_0) || (irq > AU1000_GPIO_7))
+               return -EINVAL;
 
-       if (controller)
-               new_mask = au_readl(IC1_MASKSET);
+       local_irq_save(flags);
+       wakemsk = au_readl(SYS_WAKEMSK);
+       if (on)
+               wakemsk |= 1 << bit;
        else
-               new_mask = au_readl(IC0_MASKSET);
+               wakemsk &= ~(1 << bit);
+       au_writel(wakemsk, SYS_WAKEMSK);
+       au_sync();
+       local_irq_restore(flags);
 
-       spin_unlock_irqrestore(&irq_lock, flags);
+       return 0;
 }
 
-
-static struct irq_chip rise_edge_irq_type = {
-       .name           = "Au1000 Rise Edge",
-       .ack            = mask_and_ack_rise_edge_irq,
-       .mask           = local_disable_irq,
-       .mask_ack       = mask_and_ack_rise_edge_irq,
-       .unmask         = local_enable_irq,
-       .end            = end_irq,
-};
-
-static struct irq_chip fall_edge_irq_type = {
-       .name           = "Au1000 Fall Edge",
-       .ack            = mask_and_ack_fall_edge_irq,
-       .mask           = local_disable_irq,
-       .mask_ack       = mask_and_ack_fall_edge_irq,
-       .unmask         = local_enable_irq,
-       .end            = end_irq,
-};
-
-static struct irq_chip either_edge_irq_type = {
-       .name           = "Au1000 Rise or Fall Edge",
-       .ack            = mask_and_ack_either_edge_irq,
-       .mask           = local_disable_irq,
-       .mask_ack       = mask_and_ack_either_edge_irq,
-       .unmask         = local_enable_irq,
-       .end            = end_irq,
+/*
+ * irq_chips for both ICs; this way the mask handlers can be
+ * as short as possible.
+ *
+ * NOTE: the ->ack() callback is used by the handle_edge_irq
+ *      flowhandler only, the ->mask_ack() one by handle_level_irq,
+ *      so no need for an irq_chip for each type of irq (level/edge).
+ */
+static struct irq_chip au1x_ic0_chip = {
+       .name           = "Alchemy-IC0",
+       .ack            = au1x_ic0_ack,         /* edge */
+       .mask           = au1x_ic0_mask,
+       .mask_ack       = au1x_ic0_mask,        /* level */
+       .unmask         = au1x_ic0_unmask,
+       .set_type       = au1x_ic_settype,
 };
 
-static struct irq_chip level_irq_type = {
-       .name           = "Au1000 Level",
-       .ack            = mask_and_ack_level_irq,
-       .mask           = local_disable_irq,
-       .mask_ack       = mask_and_ack_level_irq,
-       .unmask         = local_enable_irq,
-       .end            = end_irq,
+static struct irq_chip au1x_ic1_chip = {
+       .name           = "Alchemy-IC1",
+       .ack            = au1x_ic1_ack,         /* edge */
+       .mask           = au1x_ic1_mask,
+       .mask_ack       = au1x_ic1_mask,        /* level */
+       .unmask         = au1x_ic1_unmask,
+       .set_type       = au1x_ic_settype,
+       .set_wake       = au1x_ic1_setwake,
 };
 
-static void __init setup_local_irq(unsigned int irq_nr, int type, int int_req)
+static int au1x_ic_settype(unsigned int irq, unsigned int flow_type)
 {
-       unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
-
-       if (irq_nr > AU1000_MAX_INTR)
-               return;
-
-       /* Config2[n], Config1[n], Config0[n] */
-       if (bit >= 32) {
-               switch (type) {
-               case INTC_INT_RISE_EDGE: /* 0:0:1 */
-                       au_writel(1 << (bit - 32), IC1_CFG2CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG1CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG0SET);
-                       set_irq_chip(irq_nr, &rise_edge_irq_type);
-                       break;
-               case INTC_INT_FALL_EDGE: /* 0:1:0 */
-                       au_writel(1 << (bit - 32), IC1_CFG2CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG1SET);
-                       au_writel(1 << (bit - 32), IC1_CFG0CLR);
-                       set_irq_chip(irq_nr, &fall_edge_irq_type);
-                       break;
-               case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
-                       au_writel(1 << (bit - 32), IC1_CFG2CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG1SET);
-                       au_writel(1 << (bit - 32), IC1_CFG0SET);
-                       set_irq_chip(irq_nr, &either_edge_irq_type);
-                       break;
-               case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
-                       au_writel(1 << (bit - 32), IC1_CFG2SET);
-                       au_writel(1 << (bit - 32), IC1_CFG1CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG0SET);
-                       set_irq_chip(irq_nr, &level_irq_type);
-                       break;
-               case INTC_INT_LOW_LEVEL: /* 1:1:0 */
-                       au_writel(1 << (bit - 32), IC1_CFG2SET);
-                       au_writel(1 << (bit - 32), IC1_CFG1SET);
-                       au_writel(1 << (bit - 32), IC1_CFG0CLR);
-                       set_irq_chip(irq_nr, &level_irq_type);
-                       break;
-               case INTC_INT_DISABLED: /* 0:0:0 */
-                       au_writel(1 << (bit - 32), IC1_CFG0CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG1CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG2CLR);
-                       break;
-               default: /* disable the interrupt */
-                       printk(KERN_WARNING "unexpected int type %d (irq %d)\n",
-                              type, irq_nr);
-                       au_writel(1 << (bit - 32), IC1_CFG0CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG1CLR);
-                       au_writel(1 << (bit - 32), IC1_CFG2CLR);
-                       return;
-               }
-               if (int_req) /* assign to interrupt request 1 */
-                       au_writel(1 << (bit - 32), IC1_ASSIGNCLR);
-               else         /* assign to interrupt request 0 */
-                       au_writel(1 << (bit - 32), IC1_ASSIGNSET);
-               au_writel(1 << (bit - 32), IC1_SRCSET);
-               au_writel(1 << (bit - 32), IC1_MASKCLR);
-               au_writel(1 << (bit - 32), IC1_WAKECLR);
+       struct irq_chip *chip;
+       unsigned long icr[6];
+       unsigned int bit, ic;
+       int ret;
+
+       if (irq >= AU1000_INTC1_INT_BASE) {
+               bit = irq - AU1000_INTC1_INT_BASE;
+               chip = &au1x_ic1_chip;
+               ic = 1;
        } else {
-               switch (type) {
-               case INTC_INT_RISE_EDGE: /* 0:0:1 */
-                       au_writel(1 << bit, IC0_CFG2CLR);
-                       au_writel(1 << bit, IC0_CFG1CLR);
-                       au_writel(1 << bit, IC0_CFG0SET);
-                       set_irq_chip(irq_nr, &rise_edge_irq_type);
-                       break;
-               case INTC_INT_FALL_EDGE: /* 0:1:0 */
-                       au_writel(1 << bit, IC0_CFG2CLR);
-                       au_writel(1 << bit, IC0_CFG1SET);
-                       au_writel(1 << bit, IC0_CFG0CLR);
-                       set_irq_chip(irq_nr, &fall_edge_irq_type);
-                       break;
-               case INTC_INT_RISE_AND_FALL_EDGE: /* 0:1:1 */
-                       au_writel(1 << bit, IC0_CFG2CLR);
-                       au_writel(1 << bit, IC0_CFG1SET);
-                       au_writel(1 << bit, IC0_CFG0SET);
-                       set_irq_chip(irq_nr, &either_edge_irq_type);
-                       break;
-               case INTC_INT_HIGH_LEVEL: /* 1:0:1 */
-                       au_writel(1 << bit, IC0_CFG2SET);
-                       au_writel(1 << bit, IC0_CFG1CLR);
-                       au_writel(1 << bit, IC0_CFG0SET);
-                       set_irq_chip(irq_nr, &level_irq_type);
-                       break;
-               case INTC_INT_LOW_LEVEL: /* 1:1:0 */
-                       au_writel(1 << bit, IC0_CFG2SET);
-                       au_writel(1 << bit, IC0_CFG1SET);
-                       au_writel(1 << bit, IC0_CFG0CLR);
-                       set_irq_chip(irq_nr, &level_irq_type);
-                       break;
-               case INTC_INT_DISABLED: /* 0:0:0 */
-                       au_writel(1 << bit, IC0_CFG0CLR);
-                       au_writel(1 << bit, IC0_CFG1CLR);
-                       au_writel(1 << bit, IC0_CFG2CLR);
-                       break;
-               default: /* disable the interrupt */
-                       printk(KERN_WARNING "unexpected int type %d (irq %d)\n",
-                              type, irq_nr);
-                       au_writel(1 << bit, IC0_CFG0CLR);
-                       au_writel(1 << bit, IC0_CFG1CLR);
-                       au_writel(1 << bit, IC0_CFG2CLR);
-                       return;
-               }
-               if (int_req) /* assign to interrupt request 1 */
-                       au_writel(1 << bit, IC0_ASSIGNCLR);
-               else         /* assign to interrupt request 0 */
-                       au_writel(1 << bit, IC0_ASSIGNSET);
-               au_writel(1 << bit, IC0_SRCSET);
-               au_writel(1 << bit, IC0_MASKCLR);
-               au_writel(1 << bit, IC0_WAKECLR);
+               bit = irq - AU1000_INTC0_INT_BASE;
+               chip = &au1x_ic0_chip;
+               ic = 0;
+       }
+
+       if (bit > 31)
+               return -EINVAL;
+
+       icr[0] = ic ? IC1_CFG0SET : IC0_CFG0SET;
+       icr[1] = ic ? IC1_CFG1SET : IC0_CFG1SET;
+       icr[2] = ic ? IC1_CFG2SET : IC0_CFG2SET;
+       icr[3] = ic ? IC1_CFG0CLR : IC0_CFG0CLR;
+       icr[4] = ic ? IC1_CFG1CLR : IC0_CFG1CLR;
+       icr[5] = ic ? IC1_CFG2CLR : IC0_CFG2CLR;
+
+       ret = 0;
+
+       switch (flow_type) {    /* cfgregs 2:1:0 */
+       case IRQ_TYPE_EDGE_RISING:      /* 0:0:1 */
+               au_writel(1 << bit, icr[5]);
+               au_writel(1 << bit, icr[4]);
+               au_writel(1 << bit, icr[0]);
+               set_irq_chip_and_handler_name(irq, chip,
+                               handle_edge_irq, "riseedge");
+               break;
+       case IRQ_TYPE_EDGE_FALLING:     /* 0:1:0 */
+               au_writel(1 << bit, icr[5]);
+               au_writel(1 << bit, icr[1]);
+               au_writel(1 << bit, icr[3]);
+               set_irq_chip_and_handler_name(irq, chip,
+                               handle_edge_irq, "falledge");
+               break;
+       case IRQ_TYPE_EDGE_BOTH:        /* 0:1:1 */
+               au_writel(1 << bit, icr[5]);
+               au_writel(1 << bit, icr[1]);
+               au_writel(1 << bit, icr[0]);
+               set_irq_chip_and_handler_name(irq, chip,
+                               handle_edge_irq, "bothedge");
+               break;
+       case IRQ_TYPE_LEVEL_HIGH:       /* 1:0:1 */
+               au_writel(1 << bit, icr[2]);
+               au_writel(1 << bit, icr[4]);
+               au_writel(1 << bit, icr[0]);
+               set_irq_chip_and_handler_name(irq, chip,
+                               handle_level_irq, "hilevel");
+               break;
+       case IRQ_TYPE_LEVEL_LOW:        /* 1:1:0 */
+               au_writel(1 << bit, icr[2]);
+               au_writel(1 << bit, icr[1]);
+               au_writel(1 << bit, icr[3]);
+               set_irq_chip_and_handler_name(irq, chip,
+                               handle_level_irq, "lowlevel");
+               break;
+       case IRQ_TYPE_NONE:             /* 0:0:0 */
+               au_writel(1 << bit, icr[5]);
+               au_writel(1 << bit, icr[4]);
+               au_writel(1 << bit, icr[3]);
+               /* set at least chip so we can call set_irq_type() on it */
+               set_irq_chip(irq, chip);
+               break;
+       default:
+               ret = -EINVAL;
        }
        au_sync();
-}
 
-/*
- * Interrupts are nested. Even if an interrupt handler is registered
- * as "fast", we might get another interrupt before we return from
- * intcX_reqX_irqdispatch().
- */
+       return ret;
+}
 
-static void intc0_req0_irqdispatch(void)
+asmlinkage void plat_irq_dispatch(void)
 {
-       static unsigned long intc0_req0;
-       unsigned int bit;
-
-       intc0_req0 |= au_readl(IC0_REQ0INT);
+       unsigned int pending = read_c0_status() & read_c0_cause();
+       unsigned long s, off, bit;
 
-       if (!intc0_req0)
+       if (pending & CAUSEF_IP7) {
+               do_IRQ(MIPS_CPU_IRQ_BASE + 7);
                return;
-
+       } else if (pending & CAUSEF_IP2) {
+               s = IC0_REQ0INT;
+               off = AU1000_INTC0_INT_BASE;
+       } else if (pending & CAUSEF_IP3) {
+               s = IC0_REQ1INT;
+               off = AU1000_INTC0_INT_BASE;
+       } else if (pending & CAUSEF_IP4) {
+               s = IC1_REQ0INT;
+               off = AU1000_INTC1_INT_BASE;
+       } else if (pending & CAUSEF_IP5) {
+               s = IC1_REQ1INT;
+               off = AU1000_INTC1_INT_BASE;
+       } else
+               goto spurious;
+
+       bit = 0;
+       s = au_readl(s);
+       if (unlikely(!s)) {
+spurious:
+               spurious_interrupt();
+               return;
+       }
 #ifdef AU1000_USB_DEV_REQ_INT
        /*
         * Because of the tight timing of SETUP token to reply
         * transactions, the USB devices-side packet complete
         * interrupt needs the highest priority.
         */
-       if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) {
-               intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT);
+       bit = 1 << (AU1000_USB_DEV_REQ_INT - AU1000_INTC0_INT_BASE);
+       if ((pending & CAUSEF_IP2) && (s & bit)) {
                do_IRQ(AU1000_USB_DEV_REQ_INT);
                return;
        }
 #endif
-       bit = __ffs(intc0_req0);
-       intc0_req0 &= ~(1 << bit);
-       do_IRQ(AU1000_INTC0_INT_BASE + bit);
+       do_IRQ(__ffs(s) + off);
 }
 
-
-static void intc0_req1_irqdispatch(void)
-{
-       static unsigned long intc0_req1;
-       unsigned int bit;
-
-       intc0_req1 |= au_readl(IC0_REQ1INT);
-
-       if (!intc0_req1)
-               return;
-
-       bit = __ffs(intc0_req1);
-       intc0_req1 &= ~(1 << bit);
-       do_IRQ(AU1000_INTC0_INT_BASE + bit);
-}
-
-
-/*
- * Interrupt Controller 1:
- * interrupts 32 - 63
- */
-static void intc1_req0_irqdispatch(void)
+/* setup edge/level and assign request 0/1 */
+void __init au1xxx_setup_irqmap(struct au1xxx_irqmap *map, int count)
 {
-       static unsigned long intc1_req0;
-       unsigned int bit;
-
-       intc1_req0 |= au_readl(IC1_REQ0INT);
-
-       if (!intc1_req0)
-               return;
-
-       bit = __ffs(intc1_req0);
-       intc1_req0 &= ~(1 << bit);
-       do_IRQ(AU1000_INTC1_INT_BASE + bit);
-}
-
-
-static void intc1_req1_irqdispatch(void)
-{
-       static unsigned long intc1_req1;
-       unsigned int bit;
-
-       intc1_req1 |= au_readl(IC1_REQ1INT);
-
-       if (!intc1_req1)
-               return;
-
-       bit = __ffs(intc1_req1);
-       intc1_req1 &= ~(1 << bit);
-       do_IRQ(AU1000_INTC1_INT_BASE + bit);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-       unsigned int pending = read_c0_status() & read_c0_cause();
+       unsigned int bit, irq_nr;
+
+       while (count--) {
+               irq_nr = map[count].im_irq;
+
+               if (((irq_nr < AU1000_INTC0_INT_BASE) ||
+                    (irq_nr >= AU1000_INTC0_INT_BASE + 32)) &&
+                   ((irq_nr < AU1000_INTC1_INT_BASE) ||
+                    (irq_nr >= AU1000_INTC1_INT_BASE + 32)))
+                       continue;
+
+               if (irq_nr >= AU1000_INTC1_INT_BASE) {
+                       bit = irq_nr - AU1000_INTC1_INT_BASE;
+                       if (map[count].im_request)
+                               au_writel(1 << bit, IC1_ASSIGNCLR);
+               } else {
+                       bit = irq_nr - AU1000_INTC0_INT_BASE;
+                       if (map[count].im_request)
+                               au_writel(1 << bit, IC0_ASSIGNCLR);
+               }
 
-       if (pending & CAUSEF_IP7)
-               do_IRQ(MIPS_CPU_IRQ_BASE + 7);
-       else if (pending & CAUSEF_IP2)
-               intc0_req0_irqdispatch();
-       else if (pending & CAUSEF_IP3)
-               intc0_req1_irqdispatch();
-       else if (pending & CAUSEF_IP4)
-               intc1_req0_irqdispatch();
-       else if (pending  & CAUSEF_IP5)
-               intc1_req1_irqdispatch();
-       else
-               spurious_interrupt();
+               au1x_ic_settype(irq_nr, map[count].im_type);
+       }
 }
 
 void __init arch_init_irq(void)
 {
        int i;
-       struct au1xxx_irqmap *imp;
-       extern struct au1xxx_irqmap au1xxx_irq_map[];
-       extern struct au1xxx_irqmap au1xxx_ic0_map[];
-       extern int au1xxx_nr_irqs;
-       extern int au1xxx_ic0_nr_irqs;
 
        /*
         * Initialize interrupt controllers to a safe state.
@@ -569,28 +587,25 @@ void __init arch_init_irq(void)
 
        mips_cpu_irq_init();
 
-       /*
-        * Initialize IC0, which is fixed per processor.
+       /* register all 64 possible IC0+IC1 irq sources as type "none".
+        * Use set_irq_type() to set edge/level behaviour at runtime.
         */
-       imp = au1xxx_ic0_map;
-       for (i = 0; i < au1xxx_ic0_nr_irqs; i++) {
-               setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
-               imp++;
-       }
+       for (i = AU1000_INTC0_INT_BASE;
+            (i < AU1000_INTC0_INT_BASE + 32); i++)
+               au1x_ic_settype(i, IRQ_TYPE_NONE);
+
+       for (i = AU1000_INTC1_INT_BASE;
+            (i < AU1000_INTC1_INT_BASE + 32); i++)
+               au1x_ic_settype(i, IRQ_TYPE_NONE);
 
        /*
-        * Now set up the irq mapping for the board.
+        * Initialize IC0, which is fixed per processor.
         */
-       imp = au1xxx_irq_map;
-       for (i = 0; i < au1xxx_nr_irqs; i++) {
-               setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
-               imp++;
-       }
-
-       set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3 | IE_IRQ4);
+       au1xxx_setup_irqmap(au1xxx_ic0_map, ARRAY_SIZE(au1xxx_ic0_map));
 
-       /* Board specific IRQ initialization.
+       /* Boards can register additional (GPIO-based) IRQs.
        */
-       if (board_init_irq)
-               board_init_irq();
+       board_init_irq();
+
+       set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
 }
index bd854a6d1d89d0d5cd6fd5ff4369d74ee4cc079c..6ab7b42aa1be23c800bc3f07863a2991bda49762 100644 (file)
 #include <linux/jiffies.h>
 
 #include <asm/uaccess.h>
-#include <asm/cacheflush.h>
 #include <asm/mach-au1x00/au1000.h>
-
-#ifdef CONFIG_PM
-
-#define DEBUG 1
-#ifdef DEBUG
-#define DPRINTK(fmt, args...)  printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
-#else
-#define DPRINTK(fmt, args...)
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+#include <asm/mach-au1x00/au1xxx_dbdma.h>
 #endif
 
-static void au1000_calibrate_delay(void);
-
-extern unsigned long save_local_and_disable(int controller);
-extern void restore_local_and_enable(int controller, unsigned long mask);
-extern void local_enable_irq(unsigned int irq_nr);
-
-static DEFINE_SPINLOCK(pm_lock);
+#ifdef CONFIG_PM
 
 /*
  * We need to save/restore a bunch of core registers that are
@@ -65,29 +52,16 @@ static DEFINE_SPINLOCK(pm_lock);
  * We only have to save/restore registers that aren't otherwise
  * done as part of a driver pm_* function.
  */
-static unsigned int    sleep_aux_pll_cntrl;
-static unsigned int    sleep_cpu_pll_cntrl;
-static unsigned int    sleep_pin_function;
-static unsigned int    sleep_uart0_inten;
-static unsigned int    sleep_uart0_fifoctl;
-static unsigned int    sleep_uart0_linectl;
-static unsigned int    sleep_uart0_clkdiv;
-static unsigned int    sleep_uart0_enable;
-static unsigned int    sleep_usbhost_enable;
-static unsigned int    sleep_usbdev_enable;
-static unsigned int    sleep_static_memctlr[4][3];
+static unsigned int sleep_uart0_inten;
+static unsigned int sleep_uart0_fifoctl;
+static unsigned int sleep_uart0_linectl;
+static unsigned int sleep_uart0_clkdiv;
+static unsigned int sleep_uart0_enable;
+static unsigned int sleep_usb[2];
+static unsigned int sleep_sys_clocks[5];
+static unsigned int sleep_sys_pinfunc;
+static unsigned int sleep_static_memctlr[4][3];
 
-/*
- * Define this to cause the value you write to /proc/sys/pm/sleep to
- * set the TOY timer for the amount of time you want to sleep.
- * This is done mainly for testing, but may be useful in other cases.
- * The value is number of 32KHz ticks to sleep.
- */
-#define SLEEP_TEST_TIMEOUT 1
-#ifdef SLEEP_TEST_TIMEOUT
-static int sleep_ticks;
-void wakeup_counter0_set(int ticks);
-#endif
 
 static void save_core_regs(void)
 {
@@ -105,31 +79,45 @@ static void save_core_regs(void)
        sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
        sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
        sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
+       au_sync();
 
+#ifndef CONFIG_SOC_AU1200
        /* Shutdown USB host/device. */
-       sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
+       sleep_usb[0] = au_readl(USB_HOST_CONFIG);
 
        /* There appears to be some undocumented reset register.... */
-       au_writel(0, 0xb0100004); au_sync();
-       au_writel(0, USB_HOST_CONFIG); au_sync();
+       au_writel(0, 0xb0100004);
+       au_sync();
+       au_writel(0, USB_HOST_CONFIG);
+       au_sync();
 
-       sleep_usbdev_enable = au_readl(USBD_ENABLE);
-       au_writel(0, USBD_ENABLE); au_sync();
+       sleep_usb[1] = au_readl(USBD_ENABLE);
+       au_writel(0, USBD_ENABLE);
+       au_sync();
+
+#else  /* AU1200 */
+
+       /* enable access to OTG mmio so we can save OTG CAP/MUX.
+        * FIXME: write an OTG driver and move this stuff there!
+        */
+       au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
+       au_sync();
+       sleep_usb[0] = au_readl(0xb4020020);    /* OTG_CAP */
+       sleep_usb[1] = au_readl(0xb4020024);    /* OTG_MUX */
+#endif
 
        /* Save interrupt controller state. */
        save_au1xxx_intctl();
 
        /* Clocks and PLLs. */
-       sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL);
+       sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
+       sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
+       sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
+       sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
+       sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
 
-       /*
-        * We don't really need to do this one, but unless we
-        * write it again it won't have a valid value if we
-        * happen to read it.
-        */
-       sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL);
-
-       sleep_pin_function = au_readl(SYS_PINFUNC);
+       /* pin mux config */
+       sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
 
        /* Save the static memory controller configuration. */
        sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
@@ -144,16 +132,45 @@ static void save_core_regs(void)
        sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
        sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
        sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
+
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+       au1xxx_dbdma_suspend();
+#endif
 }
 
 static void restore_core_regs(void)
 {
-       extern void restore_au1xxx_intctl(void);
-       extern void wakeup_counter0_adjust(void);
+       /* restore clock configuration.  Writing CPUPLL last will
+        * stall a bit and stabilize other clocks (unless this is
+        * one of those Au1000 with a write-only PLL, where we dont
+        * have a valid value)
+        */
+       au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
+       au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
+       au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
+       au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
+       if (!au1xxx_cpu_has_pll_wo())
+               au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
+       au_sync();
 
-       au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync();
-       au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync();
-       au_writel(sleep_pin_function, SYS_PINFUNC); au_sync();
+       au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
+       au_sync();
+
+#ifndef CONFIG_SOC_AU1200
+       au_writel(sleep_usb[0], USB_HOST_CONFIG);
+       au_writel(sleep_usb[1], USBD_ENABLE);
+       au_sync();
+#else
+       /* enable accces to OTG memory */
+       au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
+       au_sync();
+
+       /* restore OTG caps and port mux. */
+       au_writel(sleep_usb[0], 0xb4020020 + 0);        /* OTG_CAP */
+       au_sync();
+       au_writel(sleep_usb[1], 0xb4020020 + 4);        /* OTG_MUX */
+       au_sync();
+#endif
 
        /* Restore the static memory controller configuration. */
        au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
@@ -184,282 +201,17 @@ static void restore_core_regs(void)
        }
 
        restore_au1xxx_intctl();
-       wakeup_counter0_adjust();
-}
-
-unsigned long suspend_mode;
 
-void wakeup_from_suspend(void)
-{
-       suspend_mode = 0;
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+       au1xxx_dbdma_resume();
+#endif
 }
 
-int au_sleep(void)
+void au_sleep(void)
 {
-       unsigned long wakeup, flags;
-       extern void save_and_sleep(void);
-
-       spin_lock_irqsave(&pm_lock, flags);
-
        save_core_regs();
-
-       flush_cache_all();
-
-       /**
-        ** The code below is all system dependent and we should probably
-        ** have a function call out of here to set this up.  You need
-        ** to configure the GPIO or timer interrupts that will bring
-        ** you out of sleep.
-        ** For testing, the TOY counter wakeup is useful.
-        **/
-#if 0
-       au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
-
-       /* GPIO 6 can cause a wake up event */
-       wakeup = au_readl(SYS_WAKEMSK);
-       wakeup &= ~(1 << 8);    /* turn off match20 wakeup */
-       wakeup |= 1 << 6;       /* turn on  GPIO  6 wakeup */
-#else
-       /* For testing, allow match20 to wake us up. */
-#ifdef SLEEP_TEST_TIMEOUT
-       wakeup_counter0_set(sleep_ticks);
-#endif
-       wakeup = 1 << 8;        /* turn on match20 wakeup   */
-       wakeup = 0;
-#endif
-       au_writel(1, SYS_WAKESRC);      /* clear cause */
-       au_sync();
-       au_writel(wakeup, SYS_WAKEMSK);
-       au_sync();
-
-       save_and_sleep();
-
-       /*
-        * After a wakeup, the cpu vectors back to 0x1fc00000, so
-        * it's up to the boot code to get us back here.
-        */
+       au1xxx_save_and_sleep();
        restore_core_regs();
-       spin_unlock_irqrestore(&pm_lock, flags);
-       return 0;
-}
-
-static int pm_do_sleep(ctl_table *ctl, int write, struct file *file,
-                      void __user *buffer, size_t *len, loff_t *ppos)
-{
-#ifdef SLEEP_TEST_TIMEOUT
-#define TMPBUFLEN2 16
-       char buf[TMPBUFLEN2], *p;
-#endif
-
-       if (!write)
-               *len = 0;
-       else {
-#ifdef SLEEP_TEST_TIMEOUT
-               if (*len > TMPBUFLEN2 - 1)
-                       return -EFAULT;
-               if (copy_from_user(buf, buffer, *len))
-                       return -EFAULT;
-               buf[*len] = 0;
-               p = buf;
-               sleep_ticks = simple_strtoul(p, &p, 0);
-#endif
-
-               au_sleep();
-       }
-       return 0;
-}
-
-static int pm_do_freq(ctl_table *ctl, int write, struct file *file,
-                     void __user *buffer, size_t *len, loff_t *ppos)
-{
-       int retval = 0, i;
-       unsigned long val, pll;
-#define TMPBUFLEN 64
-#define MAX_CPU_FREQ 396
-       char buf[TMPBUFLEN], *p;
-       unsigned long flags, intc0_mask, intc1_mask;
-       unsigned long old_baud_base, old_cpu_freq, old_clk, old_refresh;
-       unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
-       unsigned long baud_rate;
-
-       spin_lock_irqsave(&pm_lock, flags);
-       if (!write)
-               *len = 0;
-       else {
-               /* Parse the new frequency */
-               if (*len > TMPBUFLEN - 1) {
-                       spin_unlock_irqrestore(&pm_lock, flags);
-                       return -EFAULT;
-               }
-               if (copy_from_user(buf, buffer, *len)) {
-                       spin_unlock_irqrestore(&pm_lock, flags);
-                       return -EFAULT;
-               }
-               buf[*len] = 0;
-               p = buf;
-               val = simple_strtoul(p, &p, 0);
-               if (val > MAX_CPU_FREQ) {
-                       spin_unlock_irqrestore(&pm_lock, flags);
-                       return -EFAULT;
-               }
-
-               pll = val / 12;
-               if ((pll > 33) || (pll < 7)) {  /* 396 MHz max, 84 MHz min */
-                       /* Revisit this for higher speed CPUs */
-                       spin_unlock_irqrestore(&pm_lock, flags);
-                       return -EFAULT;
-               }
-
-               old_baud_base = get_au1x00_uart_baud_base();
-               old_cpu_freq = get_au1x00_speed();
-
-               new_cpu_freq = pll * 12 * 1000000;
-               new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)
-                                                           & 0x03) + 2) * 16));
-               set_au1x00_speed(new_cpu_freq);
-               set_au1x00_uart_baud_base(new_baud_base);
-
-               old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
-               new_refresh = ((old_refresh * new_cpu_freq) / old_cpu_freq) |
-                             (au_readl(MEM_SDREFCFG) & ~0x1ffffff);
-
-               au_writel(pll, SYS_CPUPLL);
-               au_sync_delay(1);
-               au_writel(new_refresh, MEM_SDREFCFG);
-               au_sync_delay(1);
-
-               for (i = 0; i < 4; i++)
-                       if (au_readl(UART_BASE + UART_MOD_CNTRL +
-                                    i * 0x00100000) == 3) {
-                               old_clk = au_readl(UART_BASE + UART_CLK +
-                                                  i * 0x00100000);
-                               baud_rate = old_baud_base / old_clk;
-                               /*
-                                * We won't get an exact baud rate and the error
-                                * could be significant enough that our new
-                                * calculation will result in a clock that will
-                                * give us a baud rate that's too far off from
-                                * what we really want.
-                                */
-                               if (baud_rate > 100000)
-                                       baud_rate = 115200;
-                               else if (baud_rate > 50000)
-                                       baud_rate = 57600;
-                               else if (baud_rate > 30000)
-                                       baud_rate = 38400;
-                               else if (baud_rate > 17000)
-                                       baud_rate = 19200;
-                               else
-                                       baud_rate = 9600;
-                               new_clk = new_baud_base / baud_rate;
-                               au_writel(new_clk, UART_BASE + UART_CLK +
-                                         i * 0x00100000);
-                               au_sync_delay(10);
-                       }
-       }
-
-       /*
-        * We don't want _any_ interrupts other than match20. Otherwise our
-        * au1000_calibrate_delay() calculation will be off, potentially a lot.
-        */
-       intc0_mask = save_local_and_disable(0);
-       intc1_mask = save_local_and_disable(1);
-       local_enable_irq(AU1000_TOY_MATCH2_INT);
-       spin_unlock_irqrestore(&pm_lock, flags);
-       au1000_calibrate_delay();
-       restore_local_and_enable(0, intc0_mask);
-       restore_local_and_enable(1, intc1_mask);
-
-       return retval;
 }
 
-
-static struct ctl_table pm_table[] = {
-       {
-               .ctl_name       = CTL_UNNUMBERED,
-               .procname       = "sleep",
-               .data           = NULL,
-               .maxlen         = 0,
-               .mode           = 0600,
-               .proc_handler   = &pm_do_sleep
-       },
-       {
-               .ctl_name       = CTL_UNNUMBERED,
-               .procname       = "freq",
-               .data           = NULL,
-               .maxlen         = 0,
-               .mode           = 0600,
-               .proc_handler   = &pm_do_freq
-       },
-       {}
-};
-
-static struct ctl_table pm_dir_table[] = {
-       {
-               .ctl_name       = CTL_UNNUMBERED,
-               .procname       = "pm",
-               .mode           = 0555,
-               .child          = pm_table
-       },
-       {}
-};
-
-/*
- * Initialize power interface
- */
-static int __init pm_init(void)
-{
-       register_sysctl_table(pm_dir_table);
-       return 0;
-}
-
-__initcall(pm_init);
-
-/*
- * This is right out of init/main.c
- */
-
-/*
- * This is the number of bits of precision for the loops_per_jiffy.
- * Each bit takes on average 1.5/HZ seconds.  This (like the original)
- * is a little better than 1%.
- */
-#define LPS_PREC 8
-
-static void au1000_calibrate_delay(void)
-{
-       unsigned long ticks, loopbit;
-       int lps_precision = LPS_PREC;
-
-       loops_per_jiffy = 1 << 12;
-
-       while (loops_per_jiffy <<= 1) {
-               /* Wait for "start of" clock tick */
-               ticks = jiffies;
-               while (ticks == jiffies)
-                       /* nothing */ ;
-               /* Go ... */
-               ticks = jiffies;
-               __delay(loops_per_jiffy);
-               ticks = jiffies - ticks;
-               if (ticks)
-                       break;
-       }
-
-       /*
-        * Do a binary approximation to get loops_per_jiffy set to be equal
-        * one clock (up to lps_precision bits)
-        */
-       loops_per_jiffy >>= 1;
-       loopbit = loops_per_jiffy;
-       while (lps_precision-- && (loopbit >>= 1)) {
-               loops_per_jiffy |= loopbit;
-               ticks = jiffies;
-               while (ticks == jiffies);
-               ticks = jiffies;
-               __delay(loops_per_jiffy);
-               if (jiffies != ticks)   /* longer than 1 tick */
-                       loops_per_jiffy &= ~loopbit;
-       }
-}
 #endif /* CONFIG_PM */
index d555429c8d6fff683fb8941cf872d83f3f022950..0191c936cb5e258b35024babf72a8b63fcb872dd 100644 (file)
@@ -31,8 +31,6 @@
 
 #include <asm/mach-au1x00/au1000.h>
 
-extern int au_sleep(void);
-
 void au1000_restart(char *command)
 {
        /* Set all integrated peripherals to disabled states */
index 1ac6b06f42a369ef8e8d578bf33c72ef99eafe44..3f036b3d400e3077da869ad20021378101f26811 100644 (file)
@@ -35,7 +35,6 @@
 #include <asm/time.h>
 
 #include <au1000.h>
-#include <prom.h>
 
 extern void __init board_setup(void);
 extern void au1000_restart(char *);
@@ -45,80 +44,34 @@ extern void set_cpuspec(void);
 
 void __init plat_mem_setup(void)
 {
-       struct  cpu_spec *sp;
-       char *argptr;
-       unsigned long prid, cpufreq, bclk;
+       unsigned long est_freq;
 
-       set_cpuspec();
-       sp = cur_cpu_spec[0];
+       /* determine core clock */
+       est_freq = au1xxx_calc_clock();
+       est_freq += 5000;    /* round */
+       est_freq -= est_freq % 10000;
+       printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
+              est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
 
-       board_setup();  /* board specific setup */
-
-       prid = read_c0_prid();
-       if (sp->cpu_pll_wo)
-#ifdef CONFIG_SOC_AU1000_FREQUENCY
-               cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000;
-#else
-               cpufreq = 396;
-#endif
-       else
-               cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12;
-       printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq);
+       _machine_restart = au1000_restart;
+       _machine_halt = au1000_halt;
+       pm_power_off = au1000_power_off;
 
-       if (sp->cpu_bclk) {
-               /* Enable BCLK switching */
-               bclk = au_readl(SYS_POWERCTRL);
-               au_writel(bclk | 0x60, SYS_POWERCTRL);
-               printk(KERN_INFO "BCLK switching enabled!\n");
-       }
+       board_setup();  /* board specific setup */
 
-       if (sp->cpu_od)
+       if (au1xxx_cpu_needs_config_od())
                /* Various early Au1xx0 errata corrected by this */
                set_c0_config(1 << 19); /* Set Config[OD] */
        else
                /* Clear to obtain best system bus performance */
                clear_c0_config(1 << 19); /* Clear Config[OD] */
 
-       argptr = prom_getcmdline();
-
-#ifdef CONFIG_SERIAL_8250_CONSOLE
-       argptr = strstr(argptr, "console=");
-       if (argptr == NULL) {
-               argptr = prom_getcmdline();
-               strcat(argptr, " console=ttyS0,115200");
-       }
-#endif
-
-#ifdef CONFIG_FB_AU1100
-       argptr = strstr(argptr, "video=");
-       if (argptr == NULL) {
-               argptr = prom_getcmdline();
-               /* default panel */
-               /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
-       }
-#endif
-
-#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
-       /* au1000 does not support vra, au1500 and au1100 do */
-       strcat(argptr, " au1000_audio=vra");
-       argptr = prom_getcmdline();
-#endif
-       _machine_restart = au1000_restart;
-       _machine_halt = au1000_halt;
-       pm_power_off = au1000_power_off;
-
        /* IO/MEM resources. */
        set_io_port_base(0);
        ioport_resource.start = IOPORT_RESOURCE_START;
        ioport_resource.end = IOPORT_RESOURCE_END;
        iomem_resource.start = IOMEM_RESOURCE_START;
        iomem_resource.end = IOMEM_RESOURCE_END;
-
-       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
-       au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
-       au_sync();
-       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
-       au_writel(0, SYS_TOYTRIM);
 }
 
 #if defined(CONFIG_64BIT_PHYS_ADDR)
index 3006e270c8bc317994e5c7dd4626b5af20f20234..4f4b16741d12e61e57ffb24f791e0fdfbeef1a9d 100644 (file)
 #include <asm/regdef.h>
 #include <asm/stackframe.h>
 
+       .extern __flush_cache_all
+
        .text
-       .set    macro
-       .set    noat
+       .set noreorder
+       .set noat
        .align  5
 
 /* Save all of the processor general registers and go to sleep.
  * A wakeup condition will get us back here to restore the registers.
  */
-LEAF(save_and_sleep)
-
+LEAF(au1xxx_save_and_sleep)
        subu    sp, PT_SIZE
        sw      $1, PT_R1(sp)
        sw      $2, PT_R2(sp)
@@ -33,14 +34,6 @@ LEAF(save_and_sleep)
        sw      $5, PT_R5(sp)
        sw      $6, PT_R6(sp)
        sw      $7, PT_R7(sp)
-       sw      $8, PT_R8(sp)
-       sw      $9, PT_R9(sp)
-       sw      $10, PT_R10(sp)
-       sw      $11, PT_R11(sp)
-       sw      $12, PT_R12(sp)
-       sw      $13, PT_R13(sp)
-       sw      $14, PT_R14(sp)
-       sw      $15, PT_R15(sp)
        sw      $16, PT_R16(sp)
        sw      $17, PT_R17(sp)
        sw      $18, PT_R18(sp)
@@ -49,12 +42,9 @@ LEAF(save_and_sleep)
        sw      $21, PT_R21(sp)
        sw      $22, PT_R22(sp)
        sw      $23, PT_R23(sp)
-       sw      $24, PT_R24(sp)
-       sw      $25, PT_R25(sp)
        sw      $26, PT_R26(sp)
        sw      $27, PT_R27(sp)
        sw      $28, PT_R28(sp)
-       sw      $29, PT_R29(sp)
        sw      $30, PT_R30(sp)
        sw      $31, PT_R31(sp)
        mfc0    k0, CP0_STATUS
@@ -66,20 +56,26 @@ LEAF(save_and_sleep)
        mfc0    k0, CP0_CONFIG
        sw      k0, 0x14(sp)
 
+       /* flush caches to make sure context is in memory */
+       la      t1, __flush_cache_all
+       lw      t0, 0(t1)
+       jalr    t0
+        nop
+
        /* Now set up the scratch registers so the boot rom will
         * return to this point upon wakeup.
+        * sys_scratch0 : SP
+        * sys_scratch1 : RA
         */
-       la      k0, 1f
-       lui     k1, 0xb190
-       ori     k1, 0x18
-       sw      sp, 0(k1)
-       ori     k1, 0x1c
-       sw      k0, 0(k1)
+       lui     t3, 0xb190              /* sys_xxx */
+       sw      sp, 0x0018(t3)
+       la      k0, 3f                  /* resume path */
+       sw      k0, 0x001c(t3)
 
-/* Put SDRAM into self refresh.  Preload instructions into cache,
* issue a precharge, then auto refresh, then sleep commands to it.
- */
-       la      t0, sdsleep
+       /* Put SDRAM into self refresh:  Preload instructions into cache,
       * issue a precharge, auto/self refresh, then sleep commands to it.
       */
+       la      t0, 1f
        .set    mips3
        cache   0x14, 0(t0)
        cache   0x14, 32(t0)
@@ -87,24 +83,57 @@ LEAF(save_and_sleep)
        cache   0x14, 96(t0)
        .set    mips0
 
-sdsleep:
-       lui     k0, 0xb400
-       sw      zero, 0x001c(k0)        /* Precharge */
-       sw      zero, 0x0020(k0)        /* Auto refresh */
-       sw      zero, 0x0030(k0)        /* SDRAM sleep */
+1:     lui     a0, 0xb400              /* mem_xxx */
+#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) ||        \
+    defined(CONFIG_SOC_AU1500)
+       sw      zero, 0x001c(a0)        /* Precharge */
+       sync
+       sw      zero, 0x0020(a0)        /* Auto Refresh */
+       sync
+       sw      zero, 0x0030(a0)        /* Sleep */
+       sync
+#endif
+
+#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
+       sw      zero, 0x08c0(a0)        /* Precharge */
        sync
+       sw      zero, 0x08d0(a0)        /* Self Refresh */
+       sync
+
+       /* wait for sdram to enter self-refresh mode */
+       lui     t0, 0x0100
+2:     lw      t1, 0x0850(a0)          /* mem_sdstat */
+       and     t2, t1, t0
+       beq     t2, zero, 2b
+        nop
 
-       lui     k1, 0xb190
-       sw      zero, 0x0078(k1)        /* get ready  to sleep */
+       /* disable SDRAM clocks */
+       lui     t0, 0xcfff
+       ori     t0, t0, 0xffff
+       lw      t1, 0x0840(a0)          /* mem_sdconfiga */
+       and     t1, t0, t1              /* clear CE[1:0] */
+       sw      t1, 0x0840(a0)          /* mem_sdconfiga */
        sync
-       sw      zero, 0x007c(k1)        /* Put processor to sleep */
+#endif
+
+       /* put power supply and processor to sleep */
+       sw      zero, 0x0078(t3)        /* sys_slppwr */
+       sync
+       sw      zero, 0x007c(t3)        /* sys_sleep */
        sync
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
+       nop
 
        /* This is where we return upon wakeup.
         * Reload all of the registers and return.
         */
-1:     nop
-       lw      k0, 0x20(sp)
+3:     lw      k0, 0x20(sp)
        mtc0    k0, CP0_STATUS
        lw      k0, 0x1c(sp)
        mtc0    k0, CP0_CONTEXT
@@ -113,10 +142,11 @@ sdsleep:
        lw      k0, 0x14(sp)
        mtc0    k0, CP0_CONFIG
 
-       /* We need to catch the ealry Alchemy SOCs with
+       /* We need to catch the early Alchemy SOCs with
         * the write-only Config[OD] bit and set it back to one...
         */
        jal     au1x00_fixup_config_od
+        nop
        lw      $1, PT_R1(sp)
        lw      $2, PT_R2(sp)
        lw      $3, PT_R3(sp)
@@ -124,14 +154,6 @@ sdsleep:
        lw      $5, PT_R5(sp)
        lw      $6, PT_R6(sp)
        lw      $7, PT_R7(sp)
-       lw      $8, PT_R8(sp)
-       lw      $9, PT_R9(sp)
-       lw      $10, PT_R10(sp)
-       lw      $11, PT_R11(sp)
-       lw      $12, PT_R12(sp)
-       lw      $13, PT_R13(sp)
-       lw      $14, PT_R14(sp)
-       lw      $15, PT_R15(sp)
        lw      $16, PT_R16(sp)
        lw      $17, PT_R17(sp)
        lw      $18, PT_R18(sp)
@@ -140,15 +162,11 @@ sdsleep:
        lw      $21, PT_R21(sp)
        lw      $22, PT_R22(sp)
        lw      $23, PT_R23(sp)
-       lw      $24, PT_R24(sp)
-       lw      $25, PT_R25(sp)
        lw      $26, PT_R26(sp)
        lw      $27, PT_R27(sp)
        lw      $28, PT_R28(sp)
-       lw      $29, PT_R29(sp)
        lw      $30, PT_R30(sp)
        lw      $31, PT_R31(sp)
-       addiu   sp, PT_SIZE
-
        jr      ra
-END(save_and_sleep)
+        addiu  sp, PT_SIZE
+END(au1xxx_save_and_sleep)
index 563d9390a87269889e3dee6118fb8e4dd5f7e9c6..32880146cbc1dc4aa2361785e5d9c88bf23a77ae 100644 (file)
@@ -1,5 +1,7 @@
 /*
+ * Copyright (C) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
  *
+ * Previous incarnations were:
  * Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com>
  * Copied and modified Carsten Langgaard's time.c
  *
  *
  * ########################################################################
  *
- * Setting up the clock on the MIPS boards.
- *
- * We provide the clock interrupt processing and the timer offset compute
- * functions.  If CONFIG_PM is selected, we also ensure the 32KHz timer is
- * available.  -- Dan
+ * Clocksource/event using the 32.768kHz-clocked Counter1 ('RTC' in the
+ * databooks).  Firmware/Board init code must enable the counters in the
+ * counter control register, otherwise the CP0 counter clocksource/event
+ * will be installed instead (and use of 'wait' instruction is prohibited).
  */
 
-#include <linux/types.h>
-#include <linux/init.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/interrupt.h>
 #include <linux/spinlock.h>
 
-#include <asm/mipsregs.h>
 #include <asm/time.h>
 #include <asm/mach-au1x00/au1000.h>
 
-static int no_au1xxx_32khz;
-extern int allow_au1k_wait; /* default off for CP0 Counter */
-
-#ifdef CONFIG_PM
-#if HZ < 100 || HZ > 1000
-#error "unsupported HZ value! Must be in [100,1000]"
-#endif
-#define MATCH20_INC (328 * 100 / HZ) /* magic number 328 is for HZ=100... */
-static unsigned long last_pc0, last_match20;
-#endif
+/* 32kHz clock enabled and detected */
+#define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
 
-static DEFINE_SPINLOCK(time_lock);
-
-unsigned long wtimer;
+extern int allow_au1k_wait; /* default off for CP0 Counter */
 
-#ifdef CONFIG_PM
-static irqreturn_t counter0_irq(int irq, void *dev_id)
+static cycle_t au1x_counter1_read(void)
 {
-       unsigned long pc0;
-       int time_elapsed;
-       static int jiffie_drift;
-
-       if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
-               /* should never happen! */
-               printk(KERN_WARNING "counter 0 w status error\n");
-               return IRQ_NONE;
-       }
-
-       pc0 = au_readl(SYS_TOYREAD);
-       if (pc0 < last_match20)
-               /* counter overflowed */
-               time_elapsed = (0xffffffff - last_match20) + pc0;
-       else
-               time_elapsed = pc0 - last_match20;
-
-       while (time_elapsed > 0) {
-               do_timer(1);
-#ifndef CONFIG_SMP
-               update_process_times(user_mode(get_irq_regs()));
-#endif
-               time_elapsed -= MATCH20_INC;
-               last_match20 += MATCH20_INC;
-               jiffie_drift++;
-       }
-
-       last_pc0 = pc0;
-       au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
-       au_sync();
-
-       /*
-        * Our counter ticks at 10.009765625 ms/tick, we we're running
-        * almost 10 uS too slow per tick.
-        */
-
-       if (jiffie_drift >= 999) {
-               jiffie_drift -= 999;
-               do_timer(1); /* increment jiffies by one */
-#ifndef CONFIG_SMP
-               update_process_times(user_mode(get_irq_regs()));
-#endif
-       }
-
-       return IRQ_HANDLED;
+       return au_readl(SYS_RTCREAD);
 }
 
-struct irqaction counter0_action = {
-       .handler        = counter0_irq,
-       .flags          = IRQF_DISABLED,
-       .name           = "alchemy-toy",
-       .dev_id         = NULL,
+static struct clocksource au1x_counter1_clocksource = {
+       .name           = "alchemy-counter1",
+       .read           = au1x_counter1_read,
+       .mask           = CLOCKSOURCE_MASK(32),
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+       .rating         = 100,
 };
 
-/* When we wakeup from sleep, we have to "catch up" on all of the
- * timer ticks we have missed.
- */
-void wakeup_counter0_adjust(void)
+static int au1x_rtcmatch2_set_next_event(unsigned long delta,
+                                        struct clock_event_device *cd)
 {
-       unsigned long pc0;
-       int time_elapsed;
-
-       pc0 = au_readl(SYS_TOYREAD);
-       if (pc0 < last_match20)
-               /* counter overflowed */
-               time_elapsed = (0xffffffff - last_match20) + pc0;
-       else
-               time_elapsed = pc0 - last_match20;
-
-       while (time_elapsed > 0) {
-               time_elapsed -= MATCH20_INC;
-               last_match20 += MATCH20_INC;
-       }
-
-       last_pc0 = pc0;
-       au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
+       delta += au_readl(SYS_RTCREAD);
+       /* wait for register access */
+       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
+               ;
+       au_writel(delta, SYS_RTCMATCH2);
        au_sync();
 
+       return 0;
 }
 
-/* This is just for debugging to set the timer for a sleep delay. */
-void wakeup_counter0_set(int ticks)
+static void au1x_rtcmatch2_set_mode(enum clock_event_mode mode,
+                                   struct clock_event_device *cd)
 {
-       unsigned long pc0;
-
-       pc0 = au_readl(SYS_TOYREAD);
-       last_pc0 = pc0;
-       au_writel(last_match20 + (MATCH20_INC * ticks), SYS_TOYMATCH2);
-       au_sync();
 }
-#endif
 
-/*
- * I haven't found anyone that doesn't use a 12 MHz source clock,
- * but just in case.....
- */
-#define AU1000_SRC_CLK 12000000
-
-/*
- * We read the real processor speed from the PLL.  This is important
- * because it is more accurate than computing it from the 32 KHz
- * counter, if it exists.  If we don't have an accurate processor
- * speed, all of the peripherals that derive their clocks based on
- * this advertised speed will introduce error and sometimes not work
- * properly.  This function is futher convoluted to still allow configurations
- * to do that in case they have really, really old silicon with a
- * write-only PLL register, that we need the 32 KHz when power management
- * "wait" is enabled, and we need to detect if the 32 KHz isn't present
- * but requested......got it? :-)              -- Dan
- */
-unsigned long calc_clock(void)
+static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id)
 {
-       unsigned long cpu_speed;
-       unsigned long flags;
-       unsigned long counter;
-
-       spin_lock_irqsave(&time_lock, flags);
-
-       /* Power management cares if we don't have a 32 KHz counter. */
-       no_au1xxx_32khz = 0;
-       counter = au_readl(SYS_COUNTER_CNTRL);
-       if (counter & SYS_CNTRL_E0) {
-               int trim_divide = 16;
-
-               au_writel(counter | SYS_CNTRL_EN1, SYS_COUNTER_CNTRL);
-
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
-               /* RTC now ticks at 32.768/16 kHz */
-               au_writel(trim_divide - 1, SYS_RTCTRIM);
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S);
+       struct clock_event_device *cd = dev_id;
+       cd->event_handler(cd);
+       return IRQ_HANDLED;
+}
 
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
-               au_writel(0, SYS_TOYWRITE);
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S);
-       } else
-               no_au1xxx_32khz = 1;
+static struct clock_event_device au1x_rtcmatch2_clockdev = {
+       .name           = "rtcmatch2",
+       .features       = CLOCK_EVT_FEAT_ONESHOT,
+       .rating         = 100,
+       .irq            = AU1000_RTC_MATCH2_INT,
+       .set_next_event = au1x_rtcmatch2_set_next_event,
+       .set_mode       = au1x_rtcmatch2_set_mode,
+       .cpumask        = CPU_MASK_ALL,
+};
 
-       /*
-        * On early Au1000, sys_cpupll was write-only. Since these
-        * silicon versions of Au1000 are not sold by AMD, we don't bend
-        * over backwards trying to determine the frequency.
-        */
-       if (cur_cpu_spec[0]->cpu_pll_wo)
-#ifdef CONFIG_SOC_AU1000_FREQUENCY
-               cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
-#else
-               cpu_speed = 396000000;
-#endif
-       else
-               cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
-       /* On Alchemy CPU:counter ratio is 1:1 */
-       mips_hpt_frequency = cpu_speed;
-       /* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
-       set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
-                                                         & 0x03) + 2) * 16));
-       spin_unlock_irqrestore(&time_lock, flags);
-       return cpu_speed;
-}
+static struct irqaction au1x_rtcmatch2_irqaction = {
+       .handler        = au1x_rtcmatch2_irq,
+       .flags          = IRQF_DISABLED | IRQF_TIMER,
+       .name           = "timer",
+       .dev_id         = &au1x_rtcmatch2_clockdev,
+};
 
 void __init plat_time_init(void)
 {
-       unsigned int est_freq = calc_clock();
-
-       est_freq += 5000;    /* round */
-       est_freq -= est_freq%10000;
-       printk(KERN_INFO "CPU frequency %u.%02u MHz\n",
-              est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
-       set_au1x00_speed(est_freq);
-       set_au1x00_lcd_clock(); /* program the LCD clock */
+       struct clock_event_device *cd = &au1x_rtcmatch2_clockdev;
+       unsigned long t;
+
+       /* Check if firmware (YAMON, ...) has enabled 32kHz and clock
+        * has been detected.  If so install the rtcmatch2 clocksource,
+        * otherwise don't bother.  Note that both bits being set is by
+        * no means a definite guarantee that the counters actually work
+        * (the 32S bit seems to be stuck set to 1 once a single clock-
+        * edge is detected, hence the timeouts).
+        */
+       if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
+               goto cntr_err;
 
-#ifdef CONFIG_PM
        /*
-        * setup counter 0, since it keeps ticking after a
-        * 'wait' instruction has been executed. The CP0 timer and
-        * counter 1 do NOT continue running after 'wait'
-        *
-        * It's too early to call request_irq() here, so we handle
-        * counter 0 interrupt as a special irq and it doesn't show
-        * up under /proc/interrupts.
-        *
-        * Check to ensure we really have a 32 KHz oscillator before
-        * we do this.
+        * setup counter 1 (RTC) to tick at full speed
         */
-       if (no_au1xxx_32khz)
-               printk(KERN_WARNING "WARNING: no 32KHz clock found.\n");
-       else {
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
-               au_writel(0, SYS_TOYWRITE);
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
-
-               au_writel(au_readl(SYS_WAKEMSK) | (1 << 8), SYS_WAKEMSK);
-               au_writel(~0, SYS_WAKESRC);
-               au_sync();
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
+       t = 0xffffff;
+       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && t--)
+               asm volatile ("nop");
+       if (!t)
+               goto cntr_err;
 
-               /* Setup match20 to interrupt once every HZ */
-               last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
-               au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
-               au_sync();
-               while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
-               setup_irq(AU1000_TOY_MATCH2_INT, &counter0_action);
+       au_writel(0, SYS_RTCTRIM);      /* 32.768 kHz */
+       au_sync();
 
-               /* We can use the real 'wait' instruction. */
-               allow_au1k_wait = 1;
-       }
+       t = 0xffffff;
+       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+               asm volatile ("nop");
+       if (!t)
+               goto cntr_err;
+       au_writel(0, SYS_RTCWRITE);
+       au_sync();
 
-#endif
+       t = 0xffffff;
+       while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
+               asm volatile ("nop");
+       if (!t)
+               goto cntr_err;
+
+       /* register counter1 clocksource and event device */
+       clocksource_set_clock(&au1x_counter1_clocksource, 32768);
+       clocksource_register(&au1x_counter1_clocksource);
+
+       cd->shift = 32;
+       cd->mult = div_sc(32768, NSEC_PER_SEC, cd->shift);
+       cd->max_delta_ns = clockevent_delta2ns(0xffffffff, cd);
+       cd->min_delta_ns = clockevent_delta2ns(8, cd);  /* ~0.25ms */
+       clockevents_register_device(cd);
+       setup_irq(AU1000_RTC_MATCH2_INT, &au1x_rtcmatch2_irqaction);
+
+       printk(KERN_INFO "Alchemy clocksource installed\n");
+
+       /* can now use 'wait' */
+       allow_au1k_wait = 1;
+       return;
+
+cntr_err:
+       /* counters unusable, use C0 counter */
+       r4k_clockevent_init();
+       init_r4k_clocksource();
+       allow_au1k_wait = 0;
 }
diff --git a/arch/mips/alchemy/db1x00/init.c b/arch/mips/alchemy/db1x00/init.c
deleted file mode 100644 (file)
index 8474135..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     PB1000 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
-#ifdef CONFIG_MIPS_BOSPORUS
-       return "Alchemy Bosporus Gateway Reference";
-#else
-       return "Alchemy Db1x00";
-#endif
-}
-
-void __init prom_init(void)
-{
-       unsigned char *memsize_str;
-       unsigned long memsize;
-
-       prom_argc = fw_arg0;
-       prom_argv = (char **)fw_arg1;
-       prom_envp = (char **)fw_arg2;
-
-       prom_init_cmdline();
-
-       memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
-               memsize = 0x04000000;
-       else
-               strict_strtol(memsize_str, 0, &memsize);
-       add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/devboards/Makefile b/arch/mips/alchemy/devboards/Makefile
new file mode 100644 (file)
index 0000000..730f9f2
--- /dev/null
@@ -0,0 +1,18 @@
+#
+# Alchemy Develboards
+#
+
+obj-y += prom.o
+obj-$(CONFIG_PM)               += pm.o
+obj-$(CONFIG_MIPS_PB1000)      += pb1000/
+obj-$(CONFIG_MIPS_PB1100)      += pb1100/
+obj-$(CONFIG_MIPS_PB1200)      += pb1200/
+obj-$(CONFIG_MIPS_PB1500)      += pb1500/
+obj-$(CONFIG_MIPS_PB1550)      += pb1550/
+obj-$(CONFIG_MIPS_DB1000)      += db1x00/
+obj-$(CONFIG_MIPS_DB1100)      += db1x00/
+obj-$(CONFIG_MIPS_DB1200)      += pb1200/
+obj-$(CONFIG_MIPS_DB1500)      += db1x00/
+obj-$(CONFIG_MIPS_DB1550)      += db1x00/
+obj-$(CONFIG_MIPS_BOSPORUS)    += db1x00/
+obj-$(CONFIG_MIPS_MIRAGE)      += db1x00/
similarity index 81%
rename from arch/mips/alchemy/db1x00/Makefile
rename to arch/mips/alchemy/devboards/db1x00/Makefile
index 274db3b55d829f5d77336cfde244f3b3ab8dfdae..432241ab8677dc59494f3499f402b1aa66c9c104 100644 (file)
@@ -5,4 +5,4 @@
 # Makefile for the Alchemy Semiconductor DBAu1xx0 boards.
 #
 
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o irqmap.o
similarity index 80%
rename from arch/mips/alchemy/db1x00/board_setup.c
rename to arch/mips/alchemy/devboards/db1x00/board_setup.c
index 9e5ccbbfcedd83dc8f11ab0a1b2ac86cf480d01b..a75ffbf99f2520fe91806f32205b2af14b4379c4 100644 (file)
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-db1x00/db1x00.h>
 
+#include <prom.h>
+
+
 static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
 
+const char *get_system_type(void)
+{
+#ifdef CONFIG_MIPS_BOSPORUS
+       return "Alchemy Bosporus Gateway Reference";
+#else
+       return "Alchemy Db1x00";
+#endif
+}
+
 void board_reset(void)
 {
        /* Hit BCSR.SW_RESET[RESET] */
@@ -43,6 +55,31 @@ void board_reset(void)
 void __init board_setup(void)
 {
        u32 pin_func = 0;
+       char *argptr;
+
+       argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+
+#ifdef CONFIG_FB_AU1100
+       argptr = strstr(argptr, "video=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               /* default panel */
+               /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
+       }
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+       /* au1000 does not support vra, au1500 and au1100 do */
+       strcat(argptr, " au1000_audio=vra");
+       argptr = prom_getcmdline();
+#endif
 
        /* Not valid for Au1550 */
 #if defined(CONFIG_IRDA) && \
similarity index 77%
rename from arch/mips/alchemy/db1x00/irqmap.c
rename to arch/mips/alchemy/devboards/db1x00/irqmap.c
index 94c090e8bf7a61e29f04de475d00ef466933e49a..0b09025087c6f3b8ba0407d94cc144b479b5f807 100644 (file)
@@ -27,6 +27,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-au1x00/au1000.h>
 
@@ -66,21 +67,24 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
 
 #ifndef CONFIG_MIPS_MIRAGE
 #ifdef CONFIG_MIPS_DB1550
-       { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
-       { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+       { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
+       { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
 #else
-       { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */
-       { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */
-       { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
+       { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 Fully_Interted# */
+       { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 STSCHG# */
+       { AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
 
-       { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */
-       { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */
-       { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
+       { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 Fully_Interted# */
+       { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 STSCHG# */
+       { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
 #endif
 #else
-       { AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */
+       { AU1000_GPIO_7, IRQF_TRIGGER_RISING, 0 }, /* touchscreen pen down */
 #endif
 
 };
 
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
+void __init board_init_irq(void)
+{
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
similarity index 81%
rename from arch/mips/alchemy/pb1000/Makefile
rename to arch/mips/alchemy/devboards/pb1000/Makefile
index 99bbec0ca41bf9bcc6c8abe7cae650d1e6da5046..97c6615ba2bb89ee4b81fd05977cc97606cc3db6 100644 (file)
@@ -5,4 +5,4 @@
 # Makefile for the Alchemy Semiconductor Pb1000 board.
 #
 
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
similarity index 90%
rename from arch/mips/alchemy/pb1000/board_setup.c
rename to arch/mips/alchemy/devboards/pb1000/board_setup.c
index 25df167a95b3550a8b6599a8f7cc5aa0b464dc46..aed2fdecc70996419ba0c9be0c0725a87f5a3999 100644 (file)
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include <linux/init.h>
 #include <linux/delay.h>
-
+#include <linux/init.h>
+#include <linux/interrupt.h>
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-pb1x00/pb1000.h>
+#include <prom.h>
+
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+       { AU1000_GPIO_15, IRQF_TRIGGER_LOW, 0 },
+};
+
+
+const char *get_system_type(void)
+{
+       return "Alchemy Pb1000";
+}
 
 void board_reset(void)
 {
 }
 
+void __init board_init_irq(void)
+{
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
 void __init board_setup(void)
 {
        u32 pin_func, static_cfg0;
        u32 sys_freqctrl, sys_clksrc;
        u32 prid = read_c0_prid();
 
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       char *argptr = prom_getcmdline();
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+
        /* Set AUX clock to 12 MHz * 8 = 96 MHz */
        au_writel(8, SYS_AUXPLL);
        au_writel(0, SYS_PINSTATERD);
similarity index 81%
rename from arch/mips/alchemy/pb1100/Makefile
rename to arch/mips/alchemy/devboards/pb1100/Makefile
index 793e97c49e46d7f74871170be1e713d99d0894e9..c586dd7e91dcb7ba3d063405aba6c482c641073a 100644 (file)
@@ -5,4 +5,4 @@
 # Makefile for the Alchemy Semiconductor Pb1100 board.
 #
 
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
similarity index 76%
rename from arch/mips/alchemy/pb1100/board_setup.c
rename to arch/mips/alchemy/devboards/pb1100/board_setup.c
index c0bfd59a7a368f1dde18c428a5c9aa41df5a6087..4df57fae15d4cfe24f2cbe598389ce4efa4781f1 100644 (file)
 
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-pb1x00/pb1100.h>
 
+#include <prom.h>
+
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+       { AU1000_GPIO_9,  IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card Fully_Inserted# */
+       { AU1000_GPIO_10, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card STSCHG# */
+       { AU1000_GPIO_11, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card IRQ# */
+       { AU1000_GPIO_13, IRQF_TRIGGER_LOW, 0 }, /* DC_IRQ# */
+};
+
+
+const char *get_system_type(void)
+{
+       return "Alchemy Pb1100";
+}
+
 void board_reset(void)
 {
        /* Hit BCSR.RST_VDDI[SOFT_RESET] */
        au_writel(0x00000000, PB1100_RST_VDDI);
 }
 
+void __init board_init_irq(void)
+{
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
 void __init board_setup(void)
 {
        volatile void __iomem *base = (volatile void __iomem *)0xac000000UL;
+       char *argptr;
+
+       argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+
+#ifdef CONFIG_FB_AU1100
+       argptr = strstr(argptr, "video=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               /* default panel */
+               /*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
+       }
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+       /* au1000 does not support vra, au1500 and au1100 do */
+       strcat(argptr, " au1000_audio=vra");
+       argptr = prom_getcmdline();
+#endif
 
        /* Set AUX clock to 12 MHz * 8 = 96 MHz */
        au_writel(8, SYS_AUXPLL);
similarity index 61%
rename from arch/mips/alchemy/pb1200/Makefile
rename to arch/mips/alchemy/devboards/pb1200/Makefile
index d678adf7ce85fada6e5e7f463b2d062482e559a6..c8c3a99fb68a24ece7297a0632b91e34fd511209 100644 (file)
@@ -2,7 +2,6 @@
 # Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards.
 #
 
-lib-y := init.o board_setup.o irqmap.o
-obj-y += platform.o
+obj-y := board_setup.o irqmap.o platform.o
 
 EXTRA_CFLAGS += -Werror
similarity index 93%
rename from arch/mips/alchemy/pb1200/board_setup.c
rename to arch/mips/alchemy/devboards/pb1200/board_setup.c
index 6cb2115059adaf84a73ac6387037f276f625ecb5..94e6b7e7753d3a3d2321493b8dc07911afb5cdb6 100644 (file)
 #include <prom.h>
 #include <au1xxx.h>
 
-extern void _board_init_irq(void);
-extern void (*board_init_irq)(void);
+
+const char *get_system_type(void)
+{
+       return "Alchemy Pb1200";
+}
 
 void board_reset(void)
 {
@@ -41,7 +44,19 @@ void board_reset(void)
 
 void __init board_setup(void)
 {
-       char *argptr = NULL;
+       char *argptr;
+
+       argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+#ifdef CONFIG_FB_AU1200
+       strcat(argptr, " video=au1200fb:panel:bs");
+#endif
 
 #if 0
        {
@@ -99,16 +114,6 @@ void __init board_setup(void)
        }
 #endif
 
-#ifdef CONFIG_FB_AU1200
-       argptr = prom_getcmdline();
-#ifdef CONFIG_MIPS_PB1200
-       strcat(argptr, " video=au1200fb:panel:bs");
-#endif
-#ifdef CONFIG_MIPS_DB1200
-       strcat(argptr, " video=au1200fb:panel:bs");
-#endif
-#endif
-
        /*
         * The Pb1200 development board uses external MUX for PSC0 to
         * support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
@@ -124,9 +129,6 @@ void __init board_setup(void)
 #ifdef CONFIG_MIPS_DB1200
        printk(KERN_INFO "AMD Alchemy Db1200 Board\n");
 #endif
-
-       /* Setup Pb1200 External Interrupt Controller */
-       board_init_irq = _board_init_irq;
 }
 
 int board_au1200fb_panel(void)
similarity index 64%
rename from arch/mips/alchemy/pb1200/irqmap.c
rename to arch/mips/alchemy/devboards/pb1200/irqmap.c
index 2a505ad8715b482b635a47e5ce4a28f88a59945b..fe47498da2804679c58c3f87ef25df562b2eda86 100644 (file)
 
 struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
        /* This is external interrupt cascade */
-       { AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 },
+       { AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 },
 };
 
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
 
 /*
  * Support for External interrupts on the Pb1200 Development platform.
  */
-static volatile int pb1200_cascade_en;
 
-irqreturn_t pb1200_cascade_handler(int irq, void *dev_id)
+static void pb1200_cascade_handler(unsigned int irq, struct irq_desc *d)
 {
        unsigned short bisr = bcsr->int_status;
-       int extirq_nr = 0;
-
-       /* Clear all the edge interrupts. This has no effect on level. */
-       bcsr->int_status = bisr;
-       for ( ; bisr; bisr &= bisr - 1) {
-               extirq_nr = PB1200_INT_BEGIN + __ffs(bisr);
-               /* Ack and dispatch IRQ */
-               do_IRQ(extirq_nr);
-       }
-
-       return IRQ_RETVAL(1);
-}
 
-inline void pb1200_enable_irq(unsigned int irq_nr)
-{
-       bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
-       bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
+       for ( ; bisr; bisr &= bisr - 1)
+               generic_handle_irq(PB1200_INT_BEGIN + __ffs(bisr));
 }
 
-inline void pb1200_disable_irq(unsigned int irq_nr)
+/* NOTE: both the enable and mask bits must be cleared, otherwise the
+ * CPLD generates tons of spurious interrupts (at least on the DB1200).
+ */
+static void pb1200_mask_irq(unsigned int irq_nr)
 {
        bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
        bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
+       au_sync();
 }
 
-static unsigned int pb1200_setup_cascade(void)
-{
-       return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
-                          0, "Pb1200 Cascade", &pb1200_cascade_handler);
-}
-
-static unsigned int pb1200_startup_irq(unsigned int irq)
+static void pb1200_maskack_irq(unsigned int irq_nr)
 {
-       if (++pb1200_cascade_en == 1) {
-               int res;
-
-               res = pb1200_setup_cascade();
-               if (res)
-                       return res;
-       }
-
-       pb1200_enable_irq(irq);
-
-       return 0;
+       bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
+       bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
+       bcsr->int_status = 1 << (irq_nr - PB1200_INT_BEGIN);    /* ack */
+       au_sync();
 }
 
-static void pb1200_shutdown_irq(unsigned int irq)
+static void pb1200_unmask_irq(unsigned int irq_nr)
 {
-       pb1200_disable_irq(irq);
-       if (--pb1200_cascade_en == 0)
-               free_irq(AU1000_GPIO_7, &pb1200_cascade_handler);
+       bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
+       bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
+       au_sync();
 }
 
-static struct irq_chip external_irq_type = {
+static struct irq_chip pb1200_cpld_irq_type = {
 #ifdef CONFIG_MIPS_PB1200
        .name = "Pb1200 Ext",
 #endif
 #ifdef CONFIG_MIPS_DB1200
        .name = "Db1200 Ext",
 #endif
-       .startup  = pb1200_startup_irq,
-       .shutdown = pb1200_shutdown_irq,
-       .ack      = pb1200_disable_irq,
-       .mask     = pb1200_disable_irq,
-       .mask_ack = pb1200_disable_irq,
-       .unmask   = pb1200_enable_irq,
+       .mask           = pb1200_mask_irq,
+       .mask_ack       = pb1200_maskack_irq,
+       .unmask         = pb1200_unmask_irq,
 };
 
-void _board_init_irq(void)
+void __init board_init_irq(void)
 {
        unsigned int irq;
 
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+
 #ifdef CONFIG_MIPS_PB1200
        /* We have a problem with CPLD rev 3. */
        if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) {
@@ -146,15 +120,15 @@ void _board_init_irq(void)
                panic("Game over.  Your score is 0.");
        }
 #endif
+       /* mask & disable & ack all */
+       bcsr->intclr_mask = 0xffff;
+       bcsr->intclr = 0xffff;
+       bcsr->int_status = 0xffff;
+       au_sync();
 
-       for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) {
-               set_irq_chip_and_handler(irq, &external_irq_type,
-                                        handle_level_irq);
-               pb1200_disable_irq(irq);
-       }
+       for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++)
+               set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type,
+                                        handle_level_irq, "level");
 
-       /*
-        * GPIO_7 can not be hooked here, so it is hooked upon first
-        * request of any source attached to the cascade.
-        */
+       set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler);
 }
similarity index 81%
rename from arch/mips/alchemy/pb1500/Makefile
rename to arch/mips/alchemy/devboards/pb1500/Makefile
index 602f38df20bbfe659e92bada6685637f2a2f0433..173b419a7479977733441633029f4ea68919c30e 100644 (file)
@@ -5,4 +5,4 @@
 # Makefile for the Alchemy Semiconductor Pb1500 board.
 #
 
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
similarity index 79%
rename from arch/mips/alchemy/pb1500/board_setup.c
rename to arch/mips/alchemy/devboards/pb1500/board_setup.c
index 035771c6e5b88f0faab9d99ca13a133157f2bdcd..fed3b093156ae3a3722f7fba4852d2206b205394 100644 (file)
 
 #include <linux/init.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-pb1x00/pb1500.h>
 
+#include <prom.h>
+
+
+char irq_tab_alchemy[][5] __initdata = {
+       [12] = { -1, INTA, INTX, INTX, INTX },   /* IDSEL 12 - HPT370   */
+       [13] = { -1, INTA, INTB, INTC, INTD },   /* IDSEL 13 - PCI slot */
+};
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+       { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
+       { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
+};
+
+
+const char *get_system_type(void)
+{
+       return "Alchemy Pb1500";
+}
+
 void board_reset(void)
 {
        /* Hit BCSR.RST_VDDI[SOFT_RESET] */
        au_writel(0x00000000, PB1500_RST_VDDI);
 }
 
+void __init board_init_irq(void)
+{
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
 void __init board_setup(void)
 {
        u32 pin_func;
        u32 sys_freqctrl, sys_clksrc;
+       char *argptr;
+
+       argptr = prom_getcmdline();
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+
+#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
+       /* au1000 does not support vra, au1500 and au1100 do */
+       strcat(argptr, " au1000_audio=vra");
+       argptr = prom_getcmdline();
+#endif
 
        sys_clksrc = sys_freqctrl = pin_func = 0;
        /* Set AUX clock to 12 MHz * 8 = 96 MHz */
similarity index 81%
rename from arch/mips/alchemy/pb1550/Makefile
rename to arch/mips/alchemy/devboards/pb1550/Makefile
index 7d8beca87fa56f8eab2d40f6e26912ab20c9bfb0..cff95bcdb2cab4972d8bb889905308e2fd673315 100644 (file)
@@ -5,4 +5,4 @@
 # Makefile for the Alchemy Semiconductor Pb1550 board.
 #
 
-lib-y := init.o board_setup.o irqmap.o
+obj-y := board_setup.o
similarity index 72%
rename from arch/mips/alchemy/pb1550/board_setup.c
rename to arch/mips/alchemy/devboards/pb1550/board_setup.c
index 0ed76b64b6ab9d1db957b98dfeb11ac8e37cbca9..b6e9e7d247a30693259576822a7e29b6b999fc95 100644 (file)
  */
 
 #include <linux/init.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-au1x00/au1000.h>
 #include <asm/mach-pb1x00/pb1550.h>
 
+#include <prom.h>
+
+
+char irq_tab_alchemy[][5] __initdata = {
+       [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left)  */
+       [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */
+};
+
+struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
+       { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
+       { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
+};
+
+const char *get_system_type(void)
+{
+       return "Alchemy Pb1550";
+}
+
 void board_reset(void)
 {
        /* Hit BCSR.SYSTEM[RESET] */
        au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C);
 }
 
+void __init board_init_irq(void)
+{
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
+
 void __init board_setup(void)
 {
        u32 pin_func;
 
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       char *argptr;
+       argptr = prom_getcmdline();
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+
        /*
         * Enable PSC1 SYNC for AC'97.  Normaly done in audio driver,
         * but it is board specific code, so put it here.
diff --git a/arch/mips/alchemy/devboards/pm.c b/arch/mips/alchemy/devboards/pm.c
new file mode 100644 (file)
index 0000000..d5eb9c3
--- /dev/null
@@ -0,0 +1,229 @@
+/*
+ * Alchemy Development Board example suspend userspace interface.
+ *
+ * (c) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
+ */
+
+#include <linux/init.h>
+#include <linux/kobject.h>
+#include <linux/suspend.h>
+#include <linux/sysfs.h>
+#include <asm/mach-au1x00/au1000.h>
+
+/*
+ * Generic suspend userspace interface for Alchemy development boards.
+ * This code exports a few sysfs nodes under /sys/power/db1x/ which
+ * can be used by userspace to en/disable all au1x-provided wakeup
+ * sources and configure the timeout after which the the TOYMATCH2 irq
+ * is to trigger a wakeup.
+ */
+
+
+static unsigned long db1x_pm_sleep_secs;
+static unsigned long db1x_pm_wakemsk;
+static unsigned long db1x_pm_last_wakesrc;
+
+static int db1x_pm_enter(suspend_state_t state)
+{
+       /* enable GPIO based wakeup */
+       au_writel(1, SYS_PININPUTEN);
+
+       /* clear and setup wake cause and source */
+       au_writel(0, SYS_WAKEMSK);
+       au_sync();
+       au_writel(0, SYS_WAKESRC);
+       au_sync();
+
+       au_writel(db1x_pm_wakemsk, SYS_WAKEMSK);
+       au_sync();
+
+       /* setup 1Hz-timer-based wakeup: wait for reg access */
+       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+               asm volatile ("nop");
+
+       au_writel(au_readl(SYS_TOYREAD) + db1x_pm_sleep_secs, SYS_TOYMATCH2);
+       au_sync();
+
+       /* wait for value to really hit the register */
+       while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20)
+               asm volatile ("nop");
+
+       /* ...and now the sandman can come! */
+       au_sleep();
+
+       return 0;
+}
+
+static int db1x_pm_begin(suspend_state_t state)
+{
+       if (!db1x_pm_wakemsk) {
+               printk(KERN_ERR "db1x: no wakeup source activated!\n");
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static void db1x_pm_end(void)
+{
+       /* read and store wakeup source, the clear the register. To
+        * be able to clear it, WAKEMSK must be cleared first.
+        */
+       db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+
+       au_writel(0, SYS_WAKEMSK);
+       au_writel(0, SYS_WAKESRC);
+       au_sync();
+
+}
+
+static struct platform_suspend_ops db1x_pm_ops = {
+       .valid          = suspend_valid_only_mem,
+       .begin          = db1x_pm_begin,
+       .enter          = db1x_pm_enter,
+       .end            = db1x_pm_end,
+};
+
+#define ATTRCMP(x) (0 == strcmp(attr->attr.name, #x))
+
+static ssize_t db1x_pmattr_show(struct kobject *kobj,
+                               struct kobj_attribute *attr,
+                               char *buf)
+{
+       int idx;
+
+       if (ATTRCMP(timer_timeout))
+               return sprintf(buf, "%lu\n", db1x_pm_sleep_secs);
+
+       else if (ATTRCMP(timer))
+               return sprintf(buf, "%u\n",
+                               !!(db1x_pm_wakemsk & SYS_WAKEMSK_M2));
+
+       else if (ATTRCMP(wakesrc))
+               return sprintf(buf, "%lu\n", db1x_pm_last_wakesrc);
+
+       else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
+                ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
+                ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
+               idx = (attr->attr.name)[4] - '0';
+               return sprintf(buf, "%d\n",
+                       !!(db1x_pm_wakemsk & SYS_WAKEMSK_GPIO(idx)));
+
+       } else if (ATTRCMP(wakemsk)) {
+               return sprintf(buf, "%08lx\n", db1x_pm_wakemsk);
+       }
+
+       return -ENOENT;
+}
+
+static ssize_t db1x_pmattr_store(struct kobject *kobj,
+                                struct kobj_attribute *attr,
+                                const char *instr,
+                                size_t bytes)
+{
+       unsigned long l;
+       int tmp;
+
+       if (ATTRCMP(timer_timeout)) {
+               tmp = strict_strtoul(instr, 0, &l);
+               if (tmp)
+                       return tmp;
+
+               db1x_pm_sleep_secs = l;
+
+       } else if (ATTRCMP(timer)) {
+               if (instr[0] != '0')
+                       db1x_pm_wakemsk |= SYS_WAKEMSK_M2;
+               else
+                       db1x_pm_wakemsk &= ~SYS_WAKEMSK_M2;
+
+       } else if (ATTRCMP(gpio0) || ATTRCMP(gpio1) || ATTRCMP(gpio2) ||
+                  ATTRCMP(gpio3) || ATTRCMP(gpio4) || ATTRCMP(gpio5) ||
+                  ATTRCMP(gpio6) || ATTRCMP(gpio7)) {
+               tmp = (attr->attr.name)[4] - '0';
+               if (instr[0] != '0') {
+                       db1x_pm_wakemsk |= SYS_WAKEMSK_GPIO(tmp);
+               } else {
+                       db1x_pm_wakemsk &= ~SYS_WAKEMSK_GPIO(tmp);
+               }
+
+       } else if (ATTRCMP(wakemsk)) {
+               tmp = strict_strtoul(instr, 0, &l);
+               if (tmp)
+                       return tmp;
+
+               db1x_pm_wakemsk = l & 0x0000003f;
+
+       } else
+               bytes = -ENOENT;
+
+       return bytes;
+}
+
+#define ATTR(x)                                                        \
+       static struct kobj_attribute x##_attribute =            \
+               __ATTR(x, 0664, db1x_pmattr_show,               \
+                               db1x_pmattr_store);
+
+ATTR(gpio0)            /* GPIO-based wakeup enable */
+ATTR(gpio1)
+ATTR(gpio2)
+ATTR(gpio3)
+ATTR(gpio4)
+ATTR(gpio5)
+ATTR(gpio6)
+ATTR(gpio7)
+ATTR(timer)            /* TOYMATCH2-based wakeup enable */
+ATTR(timer_timeout)    /* timer-based wakeup timeout value, in seconds */
+ATTR(wakesrc)          /* contents of SYS_WAKESRC after last wakeup */
+ATTR(wakemsk)          /* direct access to SYS_WAKEMSK */
+
+#define ATTR_LIST(x)   & x ## _attribute.attr
+static struct attribute *db1x_pmattrs[] = {
+       ATTR_LIST(gpio0),
+       ATTR_LIST(gpio1),
+       ATTR_LIST(gpio2),
+       ATTR_LIST(gpio3),
+       ATTR_LIST(gpio4),
+       ATTR_LIST(gpio5),
+       ATTR_LIST(gpio6),
+       ATTR_LIST(gpio7),
+       ATTR_LIST(timer),
+       ATTR_LIST(timer_timeout),
+       ATTR_LIST(wakesrc),
+       ATTR_LIST(wakemsk),
+       NULL,           /* terminator */
+};
+
+static struct attribute_group db1x_pmattr_group = {
+       .name   = "db1x",
+       .attrs  = db1x_pmattrs,
+};
+
+/*
+ * Initialize suspend interface
+ */
+static int __init pm_init(void)
+{
+       /* init TOY to tick at 1Hz if not already done. No need to wait
+        * for confirmation since there's plenty of time from here to
+        * the next suspend cycle.
+        */
+       if (au_readl(SYS_TOYTRIM) != 32767) {
+               au_writel(32767, SYS_TOYTRIM);
+               au_sync();
+       }
+
+       db1x_pm_last_wakesrc = au_readl(SYS_WAKESRC);
+
+       au_writel(0, SYS_WAKESRC);
+       au_sync();
+       au_writel(0, SYS_WAKEMSK);
+       au_sync();
+
+       suspend_set_ops(&db1x_pm_ops);
+
+       return sysfs_create_group(power_kobj, &db1x_pmattr_group);
+}
+
+late_initcall(pm_init);
similarity index 71%
rename from arch/mips/alchemy/pb1550/init.c
rename to arch/mips/alchemy/devboards/prom.c
index e1055a13a1a0a108e21cd7dabf8af581226a19bc..0042bd6b1d7dc10495afda0ffc83d372370c7838 100644 (file)
@@ -1,9 +1,9 @@
 /*
+ * Common code used by all Alchemy develboards.
  *
- * BRIEF MODULE DESCRIPTION
- *     Pb1550 board setup
+ * Extracted from files which had this to say:
  *
- * Copyright 2001, 2008 MontaVista Software Inc.
+ * Copyright 2000, 2008 MontaVista Software Inc.
  * Author: MontaVista Software, Inc. <source@mvista.com>
  *
  *  This program is free software; you can redistribute  it and/or modify it
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-
 #include <asm/bootinfo.h>
-
+#include <asm/mach-au1x00/au1000.h>
 #include <prom.h>
 
-const char *get_system_type(void)
-{
-       return "Alchemy Pb1550";
-}
+#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_DB1000) || \
+    defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || \
+    defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500) || \
+    defined(CONFIG_MIPS_BOSPORUS) || defined(CONFIG_MIPS_MIRAGE)
+#define ALCHEMY_BOARD_DEFAULT_MEMSIZE  0x04000000
+
+#else  /* Au1550/Au1200-based develboards */
+#define ALCHEMY_BOARD_DEFAULT_MEMSIZE  0x08000000
+#endif
 
 void __init prom_init(void)
 {
@@ -51,8 +55,8 @@ void __init prom_init(void)
        prom_init_cmdline();
        memsize_str = prom_getenv("memsize");
        if (!memsize_str)
-               memsize = 0x08000000;
+               memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
        else
-               strict_strtol(memsize_str, 0, &memsize);
+               strict_strtoul(memsize_str, 0, &memsize);
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
index 3f8079186cf2bc62a1a9a5c595df2d3caa4bac47..8ed1ae12bc55e26b400fccadb1b30beb3acac780 100644 (file)
@@ -32,6 +32,8 @@
 
 #include <asm/mach-au1x00/au1000.h>
 
+#include <prom.h>
+
 extern int (*board_pci_idsel)(unsigned int devsel, int assert);
 int mtx1_pci_idsel(unsigned int devsel, int assert);
 
@@ -43,6 +45,16 @@ void board_reset(void)
 
 void __init board_setup(void)
 {
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       char *argptr;
+       argptr = prom_getcmdline();
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+
 #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
        /* Enable USB power switch */
        au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR);
index 3bae13c2895494788a13571853ab0c5f77b42429..5e871c8d9e964d96cad974abb20743dabff72c2a 100644 (file)
@@ -55,6 +55,6 @@ void __init prom_init(void)
        if (!memsize_str)
                memsize = 0x04000000;
        else
-               strict_strtol(memsize_str, 0, &memsize);
+               strict_strtoul(memsize_str, 0, &memsize);
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
index f2bf02951e9cb426ea92363963339eff6bcc08e4..f1ab12ab343306bcfbe9b26e5335cbd8c11543aa 100644 (file)
@@ -27,7 +27,7 @@
  */
 
 #include <linux/init.h>
-
+#include <linux/interrupt.h>
 #include <asm/mach-au1x00/au1000.h>
 
 char irq_tab_alchemy[][5] __initdata = {
@@ -42,11 +42,15 @@ char irq_tab_alchemy[][5] __initdata = {
 };
 
 struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
-       { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
+       { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
+       { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
 };
 
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
+
+void __init board_init_irq(void)
+{
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
diff --git a/arch/mips/alchemy/pb1000/init.c b/arch/mips/alchemy/pb1000/init.c
deleted file mode 100644 (file)
index 8a9c7d5..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Pb1000 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
-       return "Alchemy Pb1000";
-}
-
-void __init prom_init(void)
-{
-       unsigned char *memsize_str;
-       unsigned long memsize;
-
-       prom_argc = (int)fw_arg0;
-       prom_argv = (char **)fw_arg1;
-       prom_envp = (char **)fw_arg2;
-
-       prom_init_cmdline();
-       memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
-               memsize = 0x04000000;
-       else
-               strict_strtol(memsize_str, 0, &memsize);
-       add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1000/irqmap.c b/arch/mips/alchemy/pb1000/irqmap.c
deleted file mode 100644 (file)
index b3d56b0..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Au1xxx irq map table
- *
- * Copyright 2003 Embedded Edge, LLC
- *             dan@embeddededge.com
- *
- *  This program is free software; you can redistribute         it and/or modify it
- *  under  the terms of         the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
-       { AU1000_GPIO_15, INTC_INT_LOW_LEVEL, 0 },
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/alchemy/pb1100/init.c b/arch/mips/alchemy/pb1100/init.c
deleted file mode 100644 (file)
index 7c67923..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *     Pb1100 board setup
- *
- * Copyright 2002, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
-       return "Alchemy Pb1100";
-}
-
-void __init prom_init(void)
-{
-       unsigned char *memsize_str;
-       unsigned long memsize;
-
-       prom_argc = fw_arg0;
-       prom_argv = (char **)fw_arg1;
-       prom_envp = (char **)fw_arg3;
-
-       prom_init_cmdline();
-
-       memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
-               memsize = 0x04000000;
-       else
-               strict_strtol(memsize_str, 0, &memsize);
-
-       add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1100/irqmap.c b/arch/mips/alchemy/pb1100/irqmap.c
deleted file mode 100644 (file)
index 9b7dd8b..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Au1xx0 IRQ map table
- *
- * Copyright 2003 Embedded Edge, LLC
- *             dan@embeddededge.com
- *
- *  This program is free software; you can redistribute         it and/or modify it
- *  under  the terms of         the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
-       { AU1000_GPIO_9,  INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card Fully_Inserted# */
-       { AU1000_GPIO_10, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card STSCHG# */
-       { AU1000_GPIO_11, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card IRQ# */
-       { AU1000_GPIO_13, INTC_INT_LOW_LEVEL, 0 }, /* DC_IRQ# */
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/alchemy/pb1200/init.c b/arch/mips/alchemy/pb1200/init.c
deleted file mode 100644 (file)
index e9b2a0f..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *     PB1200 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
-       return "Alchemy Pb1200";
-}
-
-void __init prom_init(void)
-{
-       unsigned char *memsize_str;
-       unsigned long memsize;
-
-       prom_argc = (int)fw_arg0;
-       prom_argv = (char **)fw_arg1;
-       prom_envp = (char **)fw_arg2;
-
-       prom_init_cmdline();
-       memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
-               memsize = 0x08000000;
-       else
-               strict_strtol(memsize_str, 0, &memsize);
-       add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1500/init.c b/arch/mips/alchemy/pb1500/init.c
deleted file mode 100644 (file)
index 3b6e395..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- *
- * BRIEF MODULE DESCRIPTION
- *     Pb1500 board setup
- *
- * Copyright 2001, 2008 MontaVista Software Inc.
- * Author: MontaVista Software, Inc. <source@mvista.com>
- *
- *  This program is free software; you can redistribute  it and/or modify it
- *  under  the terms of  the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the  License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED   ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,   INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO  EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED   TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA,  OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-
-#include <asm/bootinfo.h>
-
-#include <prom.h>
-
-const char *get_system_type(void)
-{
-       return "Alchemy Pb1500";
-}
-
-void __init prom_init(void)
-{
-       unsigned char *memsize_str;
-       unsigned long memsize;
-
-       prom_argc = (int)fw_arg0;
-       prom_argv = (char **)fw_arg1;
-       prom_envp = (char **)fw_arg2;
-
-       prom_init_cmdline();
-       memsize_str = prom_getenv("memsize");
-       if (!memsize_str)
-               memsize = 0x04000000;
-       else
-               strict_strtol(memsize_str, 0, &memsize);
-       add_memory_region(0, memsize, BOOT_MEM_RAM);
-}
diff --git a/arch/mips/alchemy/pb1500/irqmap.c b/arch/mips/alchemy/pb1500/irqmap.c
deleted file mode 100644 (file)
index 39c4682..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Au1xxx irq map table
- *
- * Copyright 2003 Embedded Edge, LLC
- *             dan@embeddededge.com
- *
- *  This program is free software; you can redistribute         it and/or modify it
- *  under  the terms of         the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-char irq_tab_alchemy[][5] __initdata = {
-       [12] = { -1, INTA, INTX, INTX, INTX },   /* IDSEL 12 - HPT370   */
-       [13] = { -1, INTA, INTB, INTC, INTD },   /* IDSEL 13 - PCI slot */
-};
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
-       { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
diff --git a/arch/mips/alchemy/pb1550/irqmap.c b/arch/mips/alchemy/pb1550/irqmap.c
deleted file mode 100644 (file)
index a02a4d1..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * BRIEF MODULE DESCRIPTION
- *     Au1xx0 IRQ map table
- *
- * Copyright 2003 Embedded Edge, LLC
- *             dan@embeddededge.com
- *
- *  This program is free software; you can redistribute         it and/or modify it
- *  under  the terms of         the GNU General  Public License as published by the
- *  Free Software Foundation;  either version 2 of the License, or (at your
- *  option) any later version.
- *
- *  THIS  SOFTWARE  IS PROVIDED          ``AS  IS'' AND   ANY  EXPRESS OR IMPLIED
- *  WARRANTIES,          INCLUDING, BUT NOT  LIMITED  TO, THE IMPLIED WARRANTIES OF
- *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
- *  NO EVENT  SHALL   THE AUTHOR  BE    LIABLE FOR ANY   DIRECT, INDIRECT,
- *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- *  NOT LIMITED          TO, PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS OF
- *  USE, DATA, OR PROFITS; OR  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- *  ANY THEORY OF LIABILITY, WHETHER IN         CONTRACT, STRICT LIABILITY, OR TORT
- *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- *  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- *  You should have received a copy of the  GNU General Public License along
- *  with this program; if not, write  to the Free Software Foundation, Inc.,
- *  675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/init.h>
-
-#include <asm/mach-au1x00/au1000.h>
-
-char irq_tab_alchemy[][5] __initdata = {
-       [12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left)  */
-       [13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */
-};
-
-struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
-       { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
-};
-
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
index 4c587acac5c3707a4a21e3ab28f96eb62dbf8b26..a2634fabc50d429bb9494d94bb97b24233a1826b 100644 (file)
@@ -28,6 +28,8 @@
 
 #include <asm/mach-au1x00/au1000.h>
 
+#include <prom.h>
+
 void board_reset(void)
 {
        /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
@@ -38,6 +40,16 @@ void __init board_setup(void)
 {
        u32 pin_func;
 
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+       char *argptr;
+       argptr = prom_getcmdline();
+       argptr = strstr(argptr, "console=");
+       if (argptr == NULL) {
+               argptr = prom_getcmdline();
+               strcat(argptr, " console=ttyS0,115200");
+       }
+#endif
+
        /* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
        pin_func  = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
        pin_func |= SYS_PF_UR3;
index 7516434760a1c18d6300c3bef3b79002385330e2..456fa142c0934ac094e733889b7c07cd2bbd0644 100644 (file)
@@ -53,6 +53,6 @@ void __init prom_init(void)
        if (!memsize_str)
                memsize = 0x04000000;
        else
-               strict_strtol(memsize_str, 0, &memsize);
+               strict_strtoul(memsize_str, 0, &memsize);
        add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
index edf06ed1187000ad3f04fe13f2ab297dc703d894..0f0f3012e5fd7e91de78740edff76cd9e865de9f 100644 (file)
  */
 
 #include <linux/init.h>
-
+#include <linux/interrupt.h>
 #include <asm/mach-au1x00/au1000.h>
 
 struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
-       { AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
-       { AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
-       { AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
+       { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
+       { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
+       { AU1500_GPIO_207, IRQF_TRIGGER_LOW, 0 },
 
-       { AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
-       { AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
-       { AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
+       { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
+       { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
+       { AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 },
+       { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 },
+       { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* CF interrupt */
+       { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 },
 };
 
-int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
+void __init board_init_irq(void)
+{
+       au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
+}
diff --git a/arch/mips/cavium-octeon/Kconfig b/arch/mips/cavium-octeon/Kconfig
new file mode 100644 (file)
index 0000000..094c17e
--- /dev/null
@@ -0,0 +1,85 @@
+config CAVIUM_OCTEON_SPECIFIC_OPTIONS
+       bool "Enable Octeon specific options"
+       depends on CPU_CAVIUM_OCTEON
+       default "y"
+
+config CAVIUM_OCTEON_2ND_KERNEL
+       bool "Build the kernel to be used as a 2nd kernel on the same chip"
+       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+       default "n"
+       help
+         This option configures this kernel to be linked at a different
+         address and use the 2nd uart for output. This allows a kernel built
+         with this option to be run at the same time as one built without this
+         option.
+
+config CAVIUM_OCTEON_HW_FIX_UNALIGNED
+       bool "Enable hardware fixups of unaligned loads and stores"
+       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+       default "y"
+       help
+         Configure the Octeon hardware to automatically fix unaligned loads
+         and stores. Normally unaligned accesses are fixed using a kernel
+         exception handler. This option enables the hardware automatic fixups,
+         which requires only an extra 3 cycles. Disable this option if you
+         are running code that relies on address exceptions on unaligned
+         accesses.
+
+config CAVIUM_OCTEON_CVMSEG_SIZE
+       int "Number of L1 cache lines reserved for CVMSEG memory"
+       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+       range 0 54
+       default 1
+       help
+         CVMSEG LM is a segment that accesses portions of the dcache as a
+         local memory; the larger CVMSEG is, the smaller the cache is.
+         This selects the size of CVMSEG LM, which is in cache blocks. The
+         legally range is from zero to 54 cache blocks (i.e. CVMSEG LM is
+         between zero and 6192 bytes).
+
+config CAVIUM_OCTEON_LOCK_L2
+       bool "Lock often used kernel code in the L2"
+       depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
+       default "y"
+       help
+         Enable locking parts of the kernel into the L2 cache.
+
+config CAVIUM_OCTEON_LOCK_L2_TLB
+       bool "Lock the TLB handler in L2"
+       depends on CAVIUM_OCTEON_LOCK_L2
+       default "y"
+       help
+         Lock the low level TLB fast path into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_EXCEPTION
+       bool "Lock the exception handler in L2"
+       depends on CAVIUM_OCTEON_LOCK_L2
+       default "y"
+       help
+         Lock the low level exception handler into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_LOW_LEVEL_INTERRUPT
+       bool "Lock the interrupt handler in L2"
+       depends on CAVIUM_OCTEON_LOCK_L2
+       default "y"
+       help
+         Lock the low level interrupt handler into L2.
+
+config CAVIUM_OCTEON_LOCK_L2_INTERRUPT
+       bool "Lock the 2nd level interrupt handler in L2"
+       depends on CAVIUM_OCTEON_LOCK_L2
+       default "y"
+       help
+         Lock the 2nd level interrupt handler in L2.
+
+config CAVIUM_OCTEON_LOCK_L2_MEMCPY
+       bool "Lock memcpy() in L2"
+       depends on CAVIUM_OCTEON_LOCK_L2
+       default "y"
+       help
+         Lock the kernel's implementation of memcpy() into L2.
+
+config ARCH_SPARSEMEM_ENABLE
+       def_bool y
+       select SPARSEMEM_STATIC
+       depends on CPU_CAVIUM_OCTEON
diff --git a/arch/mips/cavium-octeon/Makefile b/arch/mips/cavium-octeon/Makefile
new file mode 100644 (file)
index 0000000..1c2a7fa
--- /dev/null
@@ -0,0 +1,16 @@
+#
+# Makefile for the Cavium Octeon specific kernel interface routines
+# under Linux.
+#
+# 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.
+#
+# Copyright (C) 2005-2008 Cavium Networks
+#
+
+obj-y := setup.o serial.o octeon-irq.o csrc-octeon.o
+obj-y += dma-octeon.o flash_setup.o
+obj-y += octeon-memcpy.o
+
+obj-$(CONFIG_SMP)                     += smp.o
diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c
new file mode 100644 (file)
index 0000000..70fd92c
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2007 by Ralf Baechle
+ */
+#include <linux/clocksource.h>
+#include <linux/init.h>
+
+#include <asm/time.h>
+
+#include <asm/octeon/octeon.h>
+#include <asm/octeon/cvmx-ipd-defs.h>
+
+/*
+ * Set the current core's cvmcount counter to the value of the
+ * IPD_CLK_COUNT.  We do this on all cores as they are brought
+ * on-line.  This allows for a read from a local cpu register to
+ * access a synchronized counter.
+ *
+ */
+void octeon_init_cvmcount(void)
+{
+       unsigned long flags;
+       unsigned loops = 2;
+
+       /* Clobber loops so GCC will not unroll the following while loop. */
+       asm("" : "+r" (loops));
+
+       local_irq_save(flags);
+       /*
+        * Loop several times so we are executing from the cache,
+        * which should give more deterministic timing.
+        */
+       while (loops--)
+               write_c0_cvmcount(cvmx_read_csr(CVMX_IPD_CLK_COUNT));
+       local_irq_restore(flags);
+}
+
+static cycle_t octeon_cvmcount_read(void)
+{
+       return read_c0_cvmcount();
+}
+
+static struct clocksource clocksource_mips = {
+       .name           = "OCTEON_CVMCOUNT",
+       .read           = octeon_cvmcount_read,
+       .mask           = CLOCKSOURCE_MASK(64),
+       .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void __init plat_time_init(void)
+{
+       clocksource_mips.rating = 300;
+       clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
+       clocksource_register(&clocksource_mips);
+}
diff --git a/arch/mips/cavium-octeon/dma-octeon.c b/arch/mips/cavium-octeon/dma-octeon.c
new file mode 100644 (file)
index 0000000..01b1ef9
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * 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.
+ *
+ * Copyright (C) 2000  Ani Joshi <ajoshi@unixbox.com>
+ * Copyright (C) 2000, 2001  Ralf Baechle <ralf@gnu.org>
+ * Copyright (C) 2005 Ilya A. Volynets-Evenbakh <ilya@total-knowledge.com>
+ * swiped from i386, and cloned for MIPS by Geert, polished by Ralf.
+ * IP32 changes by Ilya.
+ * Cavium Networks: Create new dma setup for Cavium Networks Octeon based on
+ * the kernels original.
+ */
+#include <linux/types.h>
+#include <linux/mm.h>
+
+#include <dma-coherence.h>
+
+dma_addr_t octeon_map_dma_mem(struct device *dev, void *ptr, size_t size)
+{
+       /* Without PCI/PCIe this function can be called for Octeon internal
+          devices such as USB. These devices all support 64bit addressing */
+       mb();
+       return virt_to_phys(ptr);
+}
+
+void octeon_unmap_dma_mem(struct device *dev, dma_addr_t dma_addr)
+{
+       /* Without PCI/PCIe this function can be called for Octeon internal
+        * devices such as USB. These devices all support 64bit addressing */
+       return;
+}
diff --git a/arch/mips/cavium-octeon/executive/Makefile b/arch/mips/cavium-octeon/executive/Makefile
new file mode 100644 (file)
index 0000000..80d6cb2
--- /dev/null
@@ -0,0 +1,13 @@
+#
+# Makefile for the Cavium Octeon specific kernel interface routines
+# under Linux.
+#
+# 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.
+#
+# Copyright (C) 2005-2008 Cavium Networks
+#
+
+obj-y += cvmx-bootmem.o cvmx-l2c.o cvmx-sysinfo.o octeon-model.o
+
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
new file mode 100644 (file)
index 0000000..4f5a08b
--- /dev/null
@@ -0,0 +1,586 @@
+/***********************license start***************
+ * Author: Cavium Networks
+ *
+ * Contact: support@caviumnetworks.com
+ * This file is part of the OCTEON SDK
+ *
+ * Copyright (c) 2003-2008 Cavium Networks
+ *
+ * This file is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, Version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This file is distributed in the hope that it will be useful, but
+ * AS-IS and WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, TITLE, or
+ * NONINFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this file; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * or visit http://www.gnu.org/licenses/.
+ *
+ * This file may also be available under a different license from Cavium.
+ * Contact Cavium Networks for more information
+ ***********************license end**************************************/
+
+/*
+ * Simple allocate only memory allocator.  Used to allocate memory at
+ * application start time.
+ */
+
+#include <linux/kernel.h>
+
+#include <asm/octeon/cvmx.h>
+#include <asm/octeon/cvmx-spinlock.h>
+#include <asm/octeon/cvmx-bootmem.h>
+
+/*#define DEBUG */
+
+
+static struct cvmx_bootmem_desc *cvmx_bootmem_desc;
+
+/* See header file for descriptions of functions */
+
+/*
+ * Wrapper functions are provided for reading/writing the size and
+ * next block values as these may not be directly addressible (in 32
+ * bit applications, for instance.)  Offsets of data elements in
+ * bootmem list, must match cvmx_bootmem_block_header_t.
+ */
+#define NEXT_OFFSET 0
+#define SIZE_OFFSET 8
+
+static void cvmx_bootmem_phy_set_size(uint64_t addr, uint64_t size)
+{
+       cvmx_write64_uint64((addr + SIZE_OFFSET) | (1ull << 63), size);
+}
+
+static void cvmx_bootmem_phy_set_next(uint64_t addr, uint64_t next)
+{
+       cvmx_write64_uint64((addr + NEXT_OFFSET) | (1ull << 63), next);
+}
+
+static uint64_t cvmx_bootmem_phy_get_size(uint64_t addr)
+{
+       return cvmx_read64_uint64((addr + SIZE_OFFSET) | (1ull << 63));
+}
+
+static uint64_t cvmx_bootmem_phy_get_next(uint64_t addr)
+{
+       return cvmx_read64_uint64((addr + NEXT_OFFSET) | (1ull << 63));
+}
+
+void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment,
+                              uint64_t min_addr, uint64_t max_addr)
+{
+       int64_t address;
+       address =
+           cvmx_bootmem_phy_alloc(size, min_addr, max_addr, alignment, 0);
+
+       if (address > 0)
+               return cvmx_phys_to_ptr(address);
+       else
+               return NULL;
+}
+
+void *cvmx_bootmem_alloc_address(uint64_t size, uint64_t address,
+                                uint64_t alignment)
+{
+       return cvmx_bootmem_alloc_range(size, alignment, address,
+                                       address + size);
+}
+
+void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment)
+{
+       return cvmx_bootmem_alloc_range(size, alignment, 0, 0);
+}
+
+int cvmx_bootmem_free_named(char *name)
+{
+       return cvmx_bootmem_phy_named_block_free(name, 0);
+}
+
+struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name)
+{
+       return cvmx_bootmem_phy_named_block_find(name, 0);
+}
+
+void cvmx_bootmem_lock(void)
+{
+       cvmx_spinlock_lock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+}
+
+void cvmx_bootmem_unlock(void)
+{
+       cvmx_spinlock_unlock((cvmx_spinlock_t *) &(cvmx_bootmem_desc->lock));
+}
+
+int cvmx_bootmem_init(void *mem_desc_ptr)
+{
+       /* Here we set the global pointer to the bootmem descriptor
+        * block.  This pointer will be used directly, so we will set
+        * it up to be directly usable by the application.  It is set
+        * up as follows for the various runtime/ABI combinations:
+        *
+        * Linux 64 bit: Set XKPHYS bit
+        * Linux 32 bit: use mmap to create mapping, use virtual address
+        * CVMX 64 bit:  use physical address directly
+        * CVMX 32 bit:  use physical address directly
+        *
+        * Note that the CVMX environment assumes the use of 1-1 TLB
+        * mappings so that the physical addresses can be used
+        * directly
+        */
+       if (!cvmx_bootmem_desc) {
+#if   defined(CVMX_ABI_64)
+               /* Set XKPHYS bit */
+               cvmx_bootmem_desc = cvmx_phys_to_ptr(CAST64(mem_desc_ptr));
+#else
+               cvmx_bootmem_desc = (struct cvmx_bootmem_desc *) mem_desc_ptr;
+#endif
+       }
+
+       return 0;
+}
+
+/*
+ * The cvmx_bootmem_phy* functions below return 64 bit physical
+ * addresses, and expose more features that the cvmx_bootmem_functions
+ * above.  These are required for full memory space access in 32 bit
+ * applications, as well as for using some advance features.  Most
+ * applications should not need to use these.
+ */
+
+int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
+                              uint64_t address_max, uint64_t alignment,
+                              uint32_t flags)
+{
+
+       uint64_t head_addr;
+       uint64_t ent_addr;
+       /* points to previous list entry, NULL current entry is head of list */
+       uint64_t prev_addr = 0;
+       uint64_t new_ent_addr = 0;
+       uint64_t desired_min_addr;
+
+#ifdef DEBUG
+       cvmx_dprintf("cvmx_bootmem_phy_alloc: req_size: 0x%llx, "
+                    "min_addr: 0x%llx, max_addr: 0x%llx, align: 0x%llx\n",
+                    (unsigned long long)req_size,
+                    (unsigned long long)address_min,
+                    (unsigned long long)address_max,
+                    (unsigned long long)alignment);
+#endif
+
+       if (cvmx_bootmem_desc->major_version > 3) {
+               cvmx_dprintf("ERROR: Incompatible bootmem descriptor "
+                            "version: %d.%d at addr: %p\n",
+                            (int)cvmx_bootmem_desc->major_version,
+                            (int)cvmx_bootmem_desc->minor_version,
+                            cvmx_bootmem_desc);
+               goto error_out;
+       }
+
+       /*
+        * Do a variety of checks to validate the arguments.  The
+        * allocator code will later assume that these checks have
+        * been made.  We validate that the requested constraints are
+        * not self-contradictory before we look through the list of
+        * available memory.
+        */
+
+       /* 0 is not a valid req_size for this allocator */
+       if (!req_size)
+               goto error_out;
+
+       /* Round req_size up to mult of minimum alignment bytes */
+       req_size = (req_size + (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1)) &
+               ~(CVMX_BOOTMEM_ALIGNMENT_SIZE - 1);
+
+       /*
+        * Convert !0 address_min and 0 address_max to special case of
+        * range that specifies an exact memory block to allocate.  Do
+        * this before other checks and adjustments so that this
+        * tranformation will be validated.
+        */
+       if (address_min && !address_max)
+               address_max = address_min + req_size;
+       else if (!address_min && !address_max)
+               address_max = ~0ull;  /* If no limits given, use max limits */
+
+
+       /*
+        * Enforce minimum alignment (this also keeps the minimum free block
+        * req_size the same as the alignment req_size.
+        */
+       if (alignment < CVMX_BOOTMEM_ALIGNMENT_SIZE)
+               alignment = CVMX_BOOTMEM_ALIGNMENT_SIZE;
+
+       /*
+        * Adjust address minimum based on requested alignment (round
+        * up to meet alignment).  Do this here so we can reject
+        * impossible requests up front. (NOP for address_min == 0)
+        */
+       if (alignment)
+               address_min = __ALIGN_MASK(address_min, (alignment - 1));
+
+       /*
+        * Reject inconsistent args.  We have adjusted these, so this
+        * may fail due to our internal changes even if this check
+        * would pass for the values the user supplied.
+        */
+       if (req_size > address_max - address_min)
+               goto error_out;
+
+       /* Walk through the list entries - first fit found is returned */
+
+       if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+               cvmx_bootmem_lock();
+       head_addr = cvmx_bootmem_desc->head_addr;
+       ent_addr = head_addr;
+       for (; ent_addr;
+            prev_addr = ent_addr,
+            ent_addr = cvmx_bootmem_phy_get_next(ent_addr)) {
+               uint64_t usable_base, usable_max;
+               uint64_t ent_size = cvmx_bootmem_phy_get_size(ent_addr);
+
+               if (cvmx_bootmem_phy_get_next(ent_addr)
+                   && ent_addr > cvmx_bootmem_phy_get_next(ent_addr)) {
+                       cvmx_dprintf("Internal bootmem_alloc() error: ent: "
+                               "0x%llx, next: 0x%llx\n",
+                               (unsigned long long)ent_addr,
+                               (unsigned long long)
+                               cvmx_bootmem_phy_get_next(ent_addr));
+                       goto error_out;
+               }
+
+               /*
+                * Determine if this is an entry that can satisify the
+                * request Check to make sure entry is large enough to
+                * satisfy request.
+                */
+               usable_base =
+                   __ALIGN_MASK(max(address_min, ent_addr), alignment - 1);
+               usable_max = min(address_max, ent_addr + ent_size);
+               /*
+                * We should be able to allocate block at address
+                * usable_base.
+                */
+
+               desired_min_addr = usable_base;
+               /*
+                * Determine if request can be satisfied from the
+                * current entry.
+                */
+               if (!((ent_addr + ent_size) > usable_base
+                               && ent_addr < address_max
+                               && req_size <= usable_max - usable_base))
+                       continue;
+               /*
+                * We have found an entry that has room to satisfy the
+                * request, so allocate it from this entry.  If end
+                * CVMX_BOOTMEM_FLAG_END_ALLOC set, then allocate from
+                * the end of this block rather than the beginning.
+                */
+               if (flags & CVMX_BOOTMEM_FLAG_END_ALLOC) {
+                       desired_min_addr = usable_max - req_size;
+                       /*
+                        * Align desired address down to required
+                        * alignment.
+                        */
+                       desired_min_addr &= ~(alignment - 1);
+               }
+
+               /* Match at start of entry */
+               if (desired_min_addr == ent_addr) {
+                       if (req_size < ent_size) {
+                               /*
+                                * big enough to create a new block
+                                * from top portion of block.
+                                */
+                               new_ent_addr = ent_addr + req_size;
+                               cvmx_bootmem_phy_set_next(new_ent_addr,
+                                       cvmx_bootmem_phy_get_next(ent_addr));
+                               cvmx_bootmem_phy_set_size(new_ent_addr,
+                                                       ent_size -
+                                                       req_size);
+
+                               /*
+                                * Adjust next pointer as following
+                                * code uses this.
+                                */
+                               cvmx_bootmem_phy_set_next(ent_addr,
+                                                       new_ent_addr);
+                       }
+
+                       /*
+                        * adjust prev ptr or head to remove this
+                        * entry from list.
+                        */
+                       if (prev_addr)
+                               cvmx_bootmem_phy_set_next(prev_addr,
+                                       cvmx_bootmem_phy_get_next(ent_addr));
+                       else
+                               /*
+                                * head of list being returned, so
+                                * update head ptr.
+                                */
+                               cvmx_bootmem_desc->head_addr =
+                                       cvmx_bootmem_phy_get_next(ent_addr);
+
+                       if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+                               cvmx_bootmem_unlock();
+                       return desired_min_addr;
+               }
+               /*
+                * block returned doesn't start at beginning of entry,
+                * so we know that we will be splitting a block off
+                * the front of this one.  Create a new block from the
+                * beginning, add to list, and go to top of loop
+                * again.
+                *
+                * create new block from high portion of
+                * block, so that top block starts at desired
+                * addr.
+                */
+               new_ent_addr = desired_min_addr;
+               cvmx_bootmem_phy_set_next(new_ent_addr,
+                                       cvmx_bootmem_phy_get_next
+                                       (ent_addr));
+               cvmx_bootmem_phy_set_size(new_ent_addr,
+                                       cvmx_bootmem_phy_get_size
+                                       (ent_addr) -
+                                       (desired_min_addr -
+                                               ent_addr));
+               cvmx_bootmem_phy_set_size(ent_addr,
+                                       desired_min_addr - ent_addr);
+               cvmx_bootmem_phy_set_next(ent_addr, new_ent_addr);
+               /* Loop again to handle actual alloc from new block */
+       }
+error_out:
+       /* We didn't find anything, so return error */
+       if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+               cvmx_bootmem_unlock();
+