Selaa lähdekoodia

Merge branch 'core/percpu' into perfcounters/core

Conflicts:
	arch/x86/include/asm/pda.h

We merge tip/core/percpu into tip/perfcounters/core because of a
semantic and contextual conflict: the former eliminates the PDA,
while the latter extends it with apic_perf_irqs field.

Resolve the conflict by moving the new field to the irq_cpustat
structure on 64-bit too.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Ingo Molnar 16 vuotta sitten
vanhempi
commit
af37501c79
100 muutettua tiedostoa jossa 1703 lisäystä ja 2138 poistoa
  1. 3 3
      Documentation/cputopology.txt
  2. 1 1
      arch/alpha/kernel/irq.c
  3. 12 6
      arch/arm/kernel/irq.c
  4. 1 0
      arch/arm/kernel/vmlinux.lds.S
  5. 1 1
      arch/arm/mach-imx/clock.c
  6. 3 3
      arch/arm/mach-imx/generic.c
  7. 0 106
      arch/arm/mach-imx/include/mach/imx-regs.h
  8. 1 0
      arch/arm/mach-w90x900/mach-w90p910evb.c
  9. 0 1
      arch/arm/mach-w90x900/time.c
  10. 1 0
      arch/arm/mm/proc-syms.c
  11. 1 1
      arch/arm/oprofile/op_model_mpcore.c
  12. 5 0
      arch/blackfin/kernel/irqchip.c
  13. 1 1
      arch/ia64/kernel/iosapic.c
  14. 2 2
      arch/ia64/kernel/irq.c
  15. 8 4
      arch/ia64/kernel/irq_ia64.c
  16. 2 2
      arch/ia64/kernel/msi_ia64.c
  17. 1 0
      arch/ia64/kernel/vmlinux.lds.S
  18. 1 1
      arch/ia64/sn/kernel/msi_sn.c
  19. 8 4
      arch/m68k/amiga/amiints.c
  20. 3 1
      arch/m68k/amiga/cia.c
  21. 2 1
      arch/m68k/amiga/config.c
  22. 2 5
      arch/m68k/apollo/config.c
  23. 7 3
      arch/m68k/atari/atakeyb.c
  24. 3 2
      arch/m68k/atari/stdma.c
  25. 3 2
      arch/m68k/atari/time.c
  26. 0 1
      arch/m68k/bvme6000/config.c
  27. 2 1
      arch/m68k/hp300/time.c
  28. 1 0
      arch/m68k/kernel/.gitignore
  29. 1 1
      arch/m68k/kernel/entry.S
  30. 5 6
      arch/m68k/kernel/setup.c
  31. 15 0
      arch/m68k/kernel/signal.c
  32. 1 0
      arch/m68k/kernel/vmlinux-sun3.lds
  33. 2 1
      arch/m68k/mac/baboon.c
  34. 0 12
      arch/m68k/mac/config.c
  35. 0 1
      arch/m68k/mac/debug.c
  36. 6 4
      arch/m68k/mac/iop.c
  37. 4 11
      arch/m68k/mac/macints.c
  38. 0 1
      arch/m68k/mac/misc.c
  39. 15 10
      arch/m68k/mac/oss.c
  40. 8 4
      arch/m68k/mac/psc.c
  41. 21 14
      arch/m68k/mac/via.c
  42. 0 1
      arch/m68k/math-emu/fp_log.c
  43. 1 3
      arch/m68k/mm/init.c
  44. 3 4
      arch/m68k/mm/motorola.c
  45. 3 3
      arch/m68k/mvme147/config.c
  46. 0 1
      arch/m68k/mvme16x/config.c
  47. 0 3
      arch/m68k/q40/config.c
  48. 3 5
      arch/m68k/sun3/config.c
  49. 0 1
      arch/m68k/sun3/mmu_emu.c
  50. 6 3
      arch/m68k/sun3/sun3ints.c
  51. 0 1
      arch/m68k/sun3x/config.c
  52. 69 2
      arch/mips/Kconfig
  53. 28 12
      arch/mips/Makefile
  54. 3 2
      arch/mips/alchemy/Kconfig
  55. 2 2
      arch/mips/alchemy/common/Makefile
  56. 0 205
      arch/mips/alchemy/common/au1xxx_irqmap.c
  57. 44 21
      arch/mips/alchemy/common/clocks.c
  58. 0 52
      arch/mips/alchemy/common/cputable.c
  59. 65 0
      arch/mips/alchemy/common/dbdma.c
  60. 380 365
      arch/mips/alchemy/common/irq.c
  61. 79 327
      arch/mips/alchemy/common/power.c
  62. 0 2
      arch/mips/alchemy/common/reset.c
  63. 12 59
      arch/mips/alchemy/common/setup.c
  64. 68 50
      arch/mips/alchemy/common/sleeper.S
  65. 105 206
      arch/mips/alchemy/common/time.c
  66. 0 62
      arch/mips/alchemy/db1x00/init.c
  67. 18 0
      arch/mips/alchemy/devboards/Makefile
  68. 1 1
      arch/mips/alchemy/devboards/db1x00/Makefile
  69. 37 0
      arch/mips/alchemy/devboards/db1x00/board_setup.c
  70. 14 10
      arch/mips/alchemy/devboards/db1x00/irqmap.c
  71. 1 1
      arch/mips/alchemy/devboards/pb1000/Makefile
  72. 28 2
      arch/mips/alchemy/devboards/pb1000/board_setup.c
  73. 1 1
      arch/mips/alchemy/devboards/pb1100/Makefile
  74. 47 0
      arch/mips/alchemy/devboards/pb1100/board_setup.c
  75. 1 2
      arch/mips/alchemy/devboards/pb1200/Makefile
  76. 18 16
      arch/mips/alchemy/devboards/pb1200/board_setup.c
  77. 34 60
      arch/mips/alchemy/devboards/pb1200/irqmap.c
  78. 0 0
      arch/mips/alchemy/devboards/pb1200/platform.c
  79. 1 1
      arch/mips/alchemy/devboards/pb1500/Makefile
  80. 44 0
      arch/mips/alchemy/devboards/pb1500/board_setup.c
  81. 1 1
      arch/mips/alchemy/devboards/pb1550/Makefile
  82. 34 0
      arch/mips/alchemy/devboards/pb1550/board_setup.c
  83. 229 0
      arch/mips/alchemy/devboards/pm.c
  84. 15 11
      arch/mips/alchemy/devboards/prom.c
  85. 12 0
      arch/mips/alchemy/mtx-1/board_setup.c
  86. 1 1
      arch/mips/alchemy/mtx-1/init.c
  87. 11 7
      arch/mips/alchemy/mtx-1/irqmap.c
  88. 0 57
      arch/mips/alchemy/pb1000/init.c
  89. 0 38
      arch/mips/alchemy/pb1000/irqmap.c
  90. 0 60
      arch/mips/alchemy/pb1100/init.c
  91. 0 40
      arch/mips/alchemy/pb1100/irqmap.c
  92. 0 58
      arch/mips/alchemy/pb1200/init.c
  93. 0 58
      arch/mips/alchemy/pb1500/init.c
  94. 0 46
      arch/mips/alchemy/pb1500/irqmap.c
  95. 0 43
      arch/mips/alchemy/pb1550/irqmap.c
  96. 12 0
      arch/mips/alchemy/xxs1500/board_setup.c
  97. 1 1
      arch/mips/alchemy/xxs1500/init.c
  98. 17 14
      arch/mips/alchemy/xxs1500/irqmap.c
  99. 85 0
      arch/mips/cavium-octeon/Kconfig
  100. 16 0
      arch/mips/cavium-octeon/Makefile

+ 3 - 3
Documentation/cputopology.txt

@@ -18,11 +18,11 @@ For an architecture to support this feature, it must define some of
 these macros in include/asm-XXX/topology.h:
 #define topology_physical_package_id(cpu)
 #define topology_core_id(cpu)
-#define topology_thread_siblings(cpu)
-#define topology_core_siblings(cpu)
+#define topology_thread_cpumask(cpu)
+#define topology_core_cpumask(cpu)
 
 The type of **_id is int.
-The type of siblings is cpumask_t.
+The type of siblings is (const) struct cpumask *.
 
 To be consistent on all architectures, include/linux/topology.h
 provides default definitions for any of the above macros that are

+ 1 - 1
arch/alpha/kernel/irq.c

@@ -55,7 +55,7 @@ int irq_select_affinity(unsigned int irq)
 		cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
 	last_cpu = cpu;
 
-	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
 	irq_desc[irq].chip->set_affinity(irq, cpumask_of(cpu));
 	return 0;
 }

+ 12 - 6
arch/arm/kernel/irq.c

@@ -104,6 +104,11 @@ static struct irq_desc bad_irq_desc = {
 	.lock = SPIN_LOCK_UNLOCKED
 };
 
+#ifdef CONFIG_CPUMASK_OFFSTACK
+/* We are not allocating bad_irq_desc.affinity or .pending_mask */
+#error "ARM architecture does not support CONFIG_CPUMASK_OFFSTACK."
+#endif
+
 /*
  * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
  * come via this function.  Instead, they should provide their
@@ -161,7 +166,7 @@ void __init init_IRQ(void)
 		irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
 
 #ifdef CONFIG_SMP
-	bad_irq_desc.affinity = CPU_MASK_ALL;
+	cpumask_setall(bad_irq_desc.affinity);
 	bad_irq_desc.cpu = smp_processor_id();
 #endif
 	init_arch_irq();
@@ -191,15 +196,16 @@ void migrate_irqs(void)
 		struct irq_desc *desc = irq_desc + i;
 
 		if (desc->cpu == cpu) {
-			unsigned int newcpu = any_online_cpu(desc->affinity);
-
-			if (newcpu == NR_CPUS) {
+			unsigned int newcpu = cpumask_any_and(desc->affinity,
+							      cpu_online_mask);
+			if (newcpu >= nr_cpu_ids) {
 				if (printk_ratelimit())
 					printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",
 					       i, cpu);
 
-				cpus_setall(desc->affinity);
-				newcpu = any_online_cpu(desc->affinity);
+				cpumask_setall(desc->affinity);
+				newcpu = cpumask_any_and(desc->affinity,
+							 cpu_online_mask);
 			}
 
 			route_irq(desc, i, newcpu);

+ 1 - 0
arch/arm/kernel/vmlinux.lds.S

@@ -65,6 +65,7 @@ SECTIONS
 #endif
 		. = ALIGN(4096);
 		__per_cpu_start = .;
+			*(.data.percpu.page_aligned)
 			*(.data.percpu)
 			*(.data.percpu.shared_aligned)
 		__per_cpu_end = .;

+ 1 - 1
arch/arm/mach-imx/clock.c

@@ -23,7 +23,7 @@
 #include <linux/err.h>
 #include <linux/io.h>
 
-#include <mach/imx-regs.h>
+#include <mach/hardware.h>
 
 /*
  * Very simple approach: We can't disable clocks, so we do

+ 3 - 3
arch/arm/mach-imx/generic.c

@@ -245,11 +245,11 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
 	imx_mmc_device.dev.platform_data = info;
 }
 
-static struct imxfb_mach_info imx_fb_info;
+static struct imx_fb_platform_data imx_fb_info;
 
-void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
+void __init set_imx_fb_info(struct imx_fb_platform_data *hard_imx_fb_info)
 {
-	memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imxfb_mach_info));
+	memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imx_fb_platform_data));
 }
 
 static struct resource imxfb_resources[] = {

+ 0 - 106
arch/arm/mach-imx/include/mach/imx-regs.h

@@ -373,110 +373,4 @@
 #define TSTAT_CAPT         (1<<1)
 #define TSTAT_COMP         (1<<0)
 
-/*
- * LCD Controller
- */
-
-#define LCDC_SSA	__REG(IMX_LCDC_BASE+0x00)
-
-#define LCDC_SIZE	__REG(IMX_LCDC_BASE+0x04)
-#define SIZE_XMAX(x)	((((x) >> 4) & 0x3f) << 20)
-#define SIZE_YMAX(y)    ( (y) & 0x1ff )
-
-#define LCDC_VPW	__REG(IMX_LCDC_BASE+0x08)
-#define VPW_VPW(x)	( (x) & 0x3ff )
-
-#define LCDC_CPOS	__REG(IMX_LCDC_BASE+0x0C)
-#define CPOS_CC1        (1<<31)
-#define CPOS_CC0        (1<<30)
-#define CPOS_OP         (1<<28)
-#define CPOS_CXP(x)     (((x) & 3ff) << 16)
-#define CPOS_CYP(y)     ((y) & 0x1ff)
-
-#define LCDC_LCWHB	__REG(IMX_LCDC_BASE+0x10)
-#define LCWHB_BK_EN     (1<<31)
-#define LCWHB_CW(w)     (((w) & 0x1f) << 24)
-#define LCWHB_CH(h)     (((h) & 0x1f) << 16)
-#define LCWHB_BD(x)     ((x) & 0xff)
-
-#define LCDC_LCHCC	__REG(IMX_LCDC_BASE+0x14)
-#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
-#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
-#define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
-
-#define LCDC_PCR	__REG(IMX_LCDC_BASE+0x18)
-#define PCR_TFT         (1<<31)
-#define PCR_COLOR       (1<<30)
-#define PCR_PBSIZ_1     (0<<28)
-#define PCR_PBSIZ_2     (1<<28)
-#define PCR_PBSIZ_4     (2<<28)
-#define PCR_PBSIZ_8     (3<<28)
-#define PCR_BPIX_1      (0<<25)
-#define PCR_BPIX_2      (1<<25)
-#define PCR_BPIX_4      (2<<25)
-#define PCR_BPIX_8      (3<<25)
-#define PCR_BPIX_12     (4<<25)
-#define PCR_BPIX_16     (4<<25)
-#define PCR_PIXPOL      (1<<24)
-#define PCR_FLMPOL      (1<<23)
-#define PCR_LPPOL       (1<<22)
-#define PCR_CLKPOL      (1<<21)
-#define PCR_OEPOL       (1<<20)
-#define PCR_SCLKIDLE    (1<<19)
-#define PCR_END_SEL     (1<<18)
-#define PCR_END_BYTE_SWAP (1<<17)
-#define PCR_REV_VS      (1<<16)
-#define PCR_ACD_SEL     (1<<15)
-#define PCR_ACD(x)      (((x) & 0x7f) << 8)
-#define PCR_SCLK_SEL    (1<<7)
-#define PCR_SHARP       (1<<6)
-#define PCR_PCD(x)      ((x) & 0x3f)
-
-#define LCDC_HCR	__REG(IMX_LCDC_BASE+0x1C)
-#define HCR_H_WIDTH(x)  (((x) & 0x3f) << 26)
-#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8)
-#define HCR_H_WAIT_2(x) ((x) & 0xff)
-
-#define LCDC_VCR	__REG(IMX_LCDC_BASE+0x20)
-#define VCR_V_WIDTH(x)  (((x) & 0x3f) << 26)
-#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8)
-#define VCR_V_WAIT_2(x) ((x) & 0xff)
-
-#define LCDC_POS	__REG(IMX_LCDC_BASE+0x24)
-#define POS_POS(x)      ((x) & 1f)
-
-#define LCDC_LSCR1	__REG(IMX_LCDC_BASE+0x28)
-#define LSCR1_PS_RISE_DELAY(x)    (((x) & 0x7f) << 26)
-#define LSCR1_CLS_RISE_DELAY(x)   (((x) & 0x3f) << 16)
-#define LSCR1_REV_TOGGLE_DELAY(x) (((x) & 0xf) << 8)
-#define LSCR1_GRAY2(x)            (((x) & 0xf) << 4)
-#define LSCR1_GRAY1(x)            (((x) & 0xf))
-
-#define LCDC_PWMR	__REG(IMX_LCDC_BASE+0x2C)
-#define PWMR_CLS(x)     (((x) & 0x1ff) << 16)
-#define PWMR_LDMSK      (1<<15)
-#define PWMR_SCR1       (1<<10)
-#define PWMR_SCR0       (1<<9)
-#define PWMR_CC_EN      (1<<8)
-#define PWMR_PW(x)      ((x) & 0xff)
-
-#define LCDC_DMACR	__REG(IMX_LCDC_BASE+0x30)
-#define DMACR_BURST     (1<<31)
-#define DMACR_HM(x)     (((x) & 0xf) << 16)
-#define DMACR_TM(x)     ((x) &0xf)
-
-#define LCDC_RMCR	__REG(IMX_LCDC_BASE+0x34)
-#define RMCR_LCDC_EN		(1<<1)
-#define RMCR_SELF_REF		(1<<0)
-
-#define LCDC_LCDICR	__REG(IMX_LCDC_BASE+0x38)
-#define LCDICR_INT_SYN  (1<<2)
-#define LCDICR_INT_CON  (1)
-
-#define LCDC_LCDISR	__REG(IMX_LCDC_BASE+0x40)
-#define LCDISR_UDR_ERR (1<<3)
-#define LCDISR_ERR_RES (1<<2)
-#define LCDISR_EOF     (1<<1)
-#define LCDISR_BOF     (1<<0)
-
 #endif				// _IMX_REGS_H

+ 1 - 0
arch/arm/mach-w90x900/mach-w90p910evb.c

@@ -29,6 +29,7 @@
 #include <asm/mach-types.h>
 
 #include <mach/regs-serial.h>
+#include <mach/map.h>
 
 #include "cpu.h"
 

+ 0 - 1
arch/arm/mach-w90x900/time.c

@@ -28,7 +28,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/time.h>
 
-#include <mach/system.h>
 #include <mach/map.h>
 #include <mach/regs-timer.h>
 

+ 1 - 0
arch/arm/mm/proc-syms.c

@@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all);
 EXPORT_SYMBOL(__cpuc_flush_user_all);
 EXPORT_SYMBOL(__cpuc_flush_user_range);
 EXPORT_SYMBOL(__cpuc_coherent_kern_range);
+EXPORT_SYMBOL(dmac_inv_range);  /* because of flush_ioremap_region() */
 #else
 EXPORT_SYMBOL(cpu_cache);
 #endif

+ 1 - 1
arch/arm/oprofile/op_model_mpcore.c

@@ -263,7 +263,7 @@ static void em_route_irq(int irq, unsigned int cpu)
 	const struct cpumask *mask = cpumask_of(cpu);
 
 	spin_lock_irq(&desc->lock);
-	desc->affinity = *mask;
+	cpumask_copy(desc->affinity, mask);
 	desc->chip->set_affinity(irq, mask);
 	spin_unlock_irq(&desc->lock);
 }

+ 5 - 0
arch/blackfin/kernel/irqchip.c

@@ -69,6 +69,11 @@ static struct irq_desc bad_irq_desc = {
 #endif
 };
 
+#ifdef CONFIG_CPUMASK_OFFSTACK
+/* We are not allocating a variable-sized bad_irq_desc.affinity */
+#error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK."
+#endif
+
 int show_interrupts(struct seq_file *p, void *v)
 {
 	int i = *(loff_t *) v, j;

+ 1 - 1
arch/ia64/kernel/iosapic.c

@@ -880,7 +880,7 @@ iosapic_unregister_intr (unsigned int gsi)
 	if (iosapic_intr_info[irq].count == 0) {
 #ifdef CONFIG_SMP
 		/* Clear affinity */
-		cpus_setall(idesc->affinity);
+		cpumask_setall(idesc->affinity);
 #endif
 		/* Clear the interrupt information */
 		iosapic_intr_info[irq].dest = 0;

+ 2 - 2
arch/ia64/kernel/irq.c

@@ -103,7 +103,7 @@ static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
 void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 {
 	if (irq < NR_IRQS) {
-		cpumask_copy(&irq_desc[irq].affinity,
+		cpumask_copy(irq_desc[irq].affinity,
 			     cpumask_of(cpu_logical_id(hwid)));
 		irq_redir[irq] = (char) (redir & 0xff);
 	}
@@ -148,7 +148,7 @@ static void migrate_irqs(void)
 		if (desc->status == IRQ_PER_CPU)
 			continue;
 
-		if (cpumask_any_and(&irq_desc[irq].affinity, cpu_online_mask)
+		if (cpumask_any_and(irq_desc[irq].affinity, cpu_online_mask)
 		    >= nr_cpu_ids) {
 			/*
 			 * Save it for phase 2 processing

+ 8 - 4
arch/ia64/kernel/irq_ia64.c

@@ -493,11 +493,13 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
 	saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
 	ia64_srlz_d();
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
+		struct irq_desc *desc = irq_to_desc(vector);
+
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_this_cpu.irqs[vector]++;
+			kstat_incr_irqs_this_cpu(vector, desc);
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_this_cpu.irqs[vector]++;
+			kstat_incr_irqs_this_cpu(vector, desc);
 		else {
 			int irq = local_vector_to_irq(vector);
 
@@ -551,11 +553,13 @@ void ia64_process_pending_intr(void)
 	  * Perform normal interrupt style processing
 	  */
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
+		struct irq_desc *desc = irq_to_desc(vector);
+
 		if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
 			smp_local_flush_tlb();
-			kstat_this_cpu.irqs[vector]++;
+			kstat_incr_irqs_this_cpu(vector, desc);
 		} else if (unlikely(IS_RESCHEDULE(vector)))
-			kstat_this_cpu.irqs[vector]++;
+			kstat_incr_irqs_this_cpu(vector, desc);
 		else {
 			struct pt_regs *old_regs = set_irq_regs(NULL);
 			int irq = local_vector_to_irq(vector);

+ 2 - 2
arch/ia64/kernel/msi_ia64.c

@@ -75,7 +75,7 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
 	msg.data = data;
 
 	write_msi_msg(irq, &msg);
-	irq_desc[irq].affinity = cpumask_of_cpu(cpu);
+	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
 }
 #endif /* CONFIG_SMP */
 
@@ -187,7 +187,7 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
 	msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu));
 
 	dmar_msi_write(irq, &msg);
-	irq_desc[irq].affinity = *mask;
+	cpumask_copy(irq_desc[irq].affinity, mask);
 }
 #endif /* CONFIG_SMP */
 

+ 1 - 0
arch/ia64/kernel/vmlinux.lds.S

@@ -219,6 +219,7 @@ SECTIONS
   .data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET)
 	{
 		__per_cpu_start = .;
+		*(.data.percpu.page_aligned)
 		*(.data.percpu)
 		*(.data.percpu.shared_aligned)
 		__per_cpu_end = .;

+ 1 - 1
arch/ia64/sn/kernel/msi_sn.c

@@ -205,7 +205,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
 	msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
 
 	write_msi_msg(irq, &msg);
-	irq_desc[irq].affinity = *cpu_mask;
+	cpumask_copy(irq_desc[irq].affinity, cpu_mask);
 }
 #endif /* CONFIG_SMP */
 

+ 8 - 4
arch/m68k/amiga/amiints.c

@@ -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);
 

+ 3 - 1
arch/m68k/amiga/cia.c

@@ -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);
 }

+ 2 - 1
arch/m68k/amiga/config.c

@@ -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;
 }

+ 2 - 5
arch/m68k/apollo/config.c

@@ -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) {

+ 7 - 3
arch/m68k/atari/atakeyb.c

@@ -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 {

+ 3 - 2
arch/m68k/atari/stdma.c

@@ -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");
 }
 
 

+ 3 - 2
arch/m68k/atari/time.c

@@ -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 */

+ 0 - 1
arch/m68k/bvme6000/config.c

@@ -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

+ 2 - 1
arch/m68k/hp300/time.c

@@ -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 */

+ 1 - 0
arch/m68k/kernel/.gitignore

@@ -0,0 +1 @@
+vmlinux.lds

+ 1 - 1
arch/m68k/kernel/entry.S

@@ -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

+ 5 - 6
arch/m68k/kernel/setup.c

@@ -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);

+ 15 - 0
arch/m68k/kernel/signal.c

@@ -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;

+ 1 - 0
arch/m68k/kernel/vmlinux-sun3.lds

@@ -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 */

+ 2 - 1
arch/m68k/mac/baboon.c

@@ -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");
 }
 
 /*

+ 0 - 12
arch/m68k/mac/config.c

@@ -47,13 +47,6 @@
 
 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();

+ 0 - 1
arch/m68k/mac/debug.c

@@ -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 *);

+ 6 - 4
arch/m68k/mac/iop.c

@@ -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");

+ 4 - 11
arch/m68k/mac/macints.c

@@ -134,6 +134,7 @@
 #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

+ 0 - 1
arch/m68k/mac/misc.c

@@ -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

+ 15 - 10
arch/m68k/mac/oss.c

@@ -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");
 }
 
 /*

+ 8 - 4
arch/m68k/mac/psc.c

@@ -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);
 }
 
 /*

+ 21 - 14
arch/m68k/mac/via.c

@@ -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");
 }
 
 /*

+ 0 - 1
arch/m68k/math-emu/fp_log.c

@@ -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)

+ 1 - 3
arch/m68k/mm/init.c

@@ -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)

+ 3 - 4
arch/m68k/mm/motorola.c

@@ -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);

+ 3 - 3
arch/m68k/mvme147/config.c

@@ -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 */

+ 0 - 1
arch/m68k/mvme16x/config.c

@@ -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);
 

+ 0 - 3
arch/m68k/q40/config.c

@@ -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*/);
 

+ 3 - 5
arch/m68k/sun3/config.c

@@ -27,23 +27,21 @@
 #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;
 

+ 0 - 1
arch/m68k/sun3/mmu_emu.c

@@ -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

+ 6 - 3
arch/m68k/sun3/sun3ints.c

@@ -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");
 }

+ 0 - 1
arch/m68k/sun3x/config.c

@@ -23,7 +23,6 @@
 #include "time.h"
 
 volatile char *clock_va;
-extern volatile unsigned char *sun3_intreg;
 
 extern void sun3_get_model(char *model);
 

+ 69 - 2
arch/mips/Kconfig

@@ -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

+ 28 - 12
arch/mips/Makefile

@@ -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/
 

+ 3 - 2
arch/mips/alchemy/Kconfig

@@ -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

+ 2 - 2
arch/mips/alchemy/common/Makefile

@@ -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
 

+ 0 - 205
arch/mips/alchemy/common/au1xxx_irqmap.c

@@ -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);

+ 44 - 21
arch/mips/alchemy/common/clocks.c

@@ -27,12 +27,21 @@
  */
 
 #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);

+ 0 - 52
arch/mips/alchemy/common/cputable.c

@@ -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;
-}

+ 65 - 0
arch/mips/alchemy/common/dbdma.c

@@ -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) */

+ 380 - 365
arch/mips/alchemy/common/irq.c

@@ -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>
@@ -36,15 +37,172 @@
 #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);
 }

+ 79 - 327
arch/mips/alchemy/common/power.c

@@ -35,25 +35,12 @@
 #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 */

+ 0 - 2
arch/mips/alchemy/common/reset.c

@@ -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 */

+ 12 - 59
arch/mips/alchemy/common/setup.c

@@ -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)

+ 68 - 50
arch/mips/alchemy/common/sleeper.S

@@ -15,16 +15,17 @@
 #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)

+ 105 - 206
arch/mips/alchemy/common/time.c

@@ -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
  *
@@ -23,244 +25,141 @@
  *
  * ########################################################################
  *
- * 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;
 }

+ 0 - 62
arch/mips/alchemy/db1x00/init.c

@@ -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);
-}

+ 18 - 0
arch/mips/alchemy/devboards/Makefile

@@ -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/

+ 1 - 1
arch/mips/alchemy/db1x00/Makefile → arch/mips/alchemy/devboards/db1x00/Makefile

@@ -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

+ 37 - 0
arch/mips/alchemy/db1x00/board_setup.c → arch/mips/alchemy/devboards/db1x00/board_setup.c

@@ -32,8 +32,20 @@
 #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) && \

+ 14 - 10
arch/mips/alchemy/db1x00/irqmap.c → arch/mips/alchemy/devboards/db1x00/irqmap.c

@@ -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));
+}

+ 1 - 1
arch/mips/alchemy/pb1000/Makefile → arch/mips/alchemy/devboards/pb1000/Makefile

@@ -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

+ 28 - 2
arch/mips/alchemy/pb1000/board_setup.c → arch/mips/alchemy/devboards/pb1000/board_setup.c

@@ -23,22 +23,48 @@
  *  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);

+ 1 - 1
arch/mips/alchemy/pb1100/Makefile → arch/mips/alchemy/devboards/pb1100/Makefile

@@ -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

+ 47 - 0
arch/mips/alchemy/pb1100/board_setup.c → arch/mips/alchemy/devboards/pb1100/board_setup.c

@@ -25,19 +25,66 @@
 
 #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);

+ 1 - 2
arch/mips/alchemy/pb1200/Makefile → arch/mips/alchemy/devboards/pb1200/Makefile

@@ -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

+ 18 - 16
arch/mips/alchemy/pb1200/board_setup.c → arch/mips/alchemy/devboards/pb1200/board_setup.c

@@ -30,8 +30,11 @@
 #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)

+ 34 - 60
arch/mips/alchemy/pb1200/irqmap.c → arch/mips/alchemy/devboards/pb1200/irqmap.c

@@ -40,91 +40,65 @@
 
 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);
 }

+ 0 - 0
arch/mips/alchemy/pb1200/platform.c → arch/mips/alchemy/devboards/pb1200/platform.c


+ 1 - 1
arch/mips/alchemy/pb1500/Makefile → arch/mips/alchemy/devboards/pb1500/Makefile

@@ -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

+ 44 - 0
arch/mips/alchemy/pb1500/board_setup.c → arch/mips/alchemy/devboards/pb1500/board_setup.c

@@ -25,20 +25,64 @@
 
 #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 */

+ 1 - 1
arch/mips/alchemy/pb1550/Makefile → arch/mips/alchemy/devboards/pb1550/Makefile

@@ -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

+ 34 - 0
arch/mips/alchemy/pb1550/board_setup.c → arch/mips/alchemy/devboards/pb1550/board_setup.c

@@ -28,20 +28,54 @@
  */
 
 #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.

+ 229 - 0
arch/mips/alchemy/devboards/pm.c

@@ -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);

+ 15 - 11
arch/mips/alchemy/pb1550/init.c → arch/mips/alchemy/devboards/prom.c

@@ -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
@@ -29,15 +29,19 @@
 
 #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);
 }

+ 12 - 0
arch/mips/alchemy/mtx-1/board_setup.c

@@ -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);

+ 1 - 1
arch/mips/alchemy/mtx-1/init.c

@@ -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);
 }

+ 11 - 7
arch/mips/alchemy/mtx-1/irqmap.c

@@ -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));
+}

+ 0 - 57
arch/mips/alchemy/pb1000/init.c

@@ -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);
-}

+ 0 - 38
arch/mips/alchemy/pb1000/irqmap.c

@@ -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);

+ 0 - 60
arch/mips/alchemy/pb1100/init.c

@@ -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);
-}

+ 0 - 40
arch/mips/alchemy/pb1100/irqmap.c

@@ -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);

+ 0 - 58
arch/mips/alchemy/pb1200/init.c

@@ -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);
-}

+ 0 - 58
arch/mips/alchemy/pb1500/init.c

@@ -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);
-}

+ 0 - 46
arch/mips/alchemy/pb1500/irqmap.c

@@ -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);

+ 0 - 43
arch/mips/alchemy/pb1550/irqmap.c

@@ -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);

+ 12 - 0
arch/mips/alchemy/xxs1500/board_setup.c

@@ -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;

+ 1 - 1
arch/mips/alchemy/xxs1500/init.c

@@ -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);
 }

+ 17 - 14
arch/mips/alchemy/xxs1500/irqmap.c

@@ -27,23 +27,26 @@
  */
 
 #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));
+}

+ 85 - 0
arch/mips/cavium-octeon/Kconfig

@@ -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

+ 16 - 0
arch/mips/cavium-octeon/Makefile

@@ -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

Kaikkia tiedostoja ei voida näyttää, sillä liian monta tiedostoa muuttui tässä diffissä