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>
This commit is contained in:
Ingo Molnar 2009-01-18 18:15:49 +01:00
commit af37501c79
524 changed files with 29494 additions and 5766 deletions

View File

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

View File

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

View File

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

View File

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

View File

@ -23,7 +23,7 @@
#include <linux/err.h> #include <linux/err.h>
#include <linux/io.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 * Very simple approach: We can't disable clocks, so we do

View File

@ -245,11 +245,11 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
imx_mmc_device.dev.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[] = { static struct resource imxfb_resources[] = {

View File

@ -373,110 +373,4 @@
#define TSTAT_CAPT (1<<1) #define TSTAT_CAPT (1<<1)
#define TSTAT_COMP (1<<0) #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 #endif // _IMX_REGS_H

View File

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

View File

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

View File

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

View File

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

View File

@ -69,6 +69,11 @@ static struct irq_desc bad_irq_desc = {
#endif #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 show_interrupts(struct seq_file *p, void *v)
{ {
int i = *(loff_t *) v, j; int i = *(loff_t *) v, j;

View File

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

View File

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

View File

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

View File

@ -75,7 +75,7 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
msg.data = data; msg.data = data;
write_msi_msg(irq, &msg); 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 */ #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)); msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu));
dmar_msi_write(irq, &msg); dmar_msi_write(irq, &msg);
irq_desc[irq].affinity = *mask; cpumask_copy(irq_desc[irq].affinity, mask);
} }
#endif /* CONFIG_SMP */ #endif /* CONFIG_SMP */

View File

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

View File

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

View File

@ -72,10 +72,14 @@ static struct irq_controller amiga_irq_controller = {
void __init amiga_init_IRQ(void) void __init amiga_init_IRQ(void)
{ {
request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL); if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL); pr_err("Couldn't register int%d\n", 1);
request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL); if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", 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); m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);

View File

@ -176,5 +176,7 @@ void __init cia_init_IRQ(struct ciabase *base)
/* override auto int and install CIA handler */ /* override auto int and install CIA handler */
m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1); m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
m68k_irq_startup(base->handler_irq); 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);
} }

View File

@ -493,7 +493,8 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
* Please don't change this to use ciaa, as it interferes with the * 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 * 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 */ /* start timer */
ciab.cra |= 0x11; ciab.cra |= 0x11;
} }

View File

@ -31,10 +31,6 @@ extern unsigned long dn_gettimeoffset(void);
extern int dn_dummy_hwclk(int, struct rtc_time *); extern int dn_dummy_hwclk(int, struct rtc_time *);
extern int dn_dummy_set_clock_mmss(unsigned long); extern int dn_dummy_set_clock_mmss(unsigned long);
extern void dn_dummy_reset(void); 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 #ifdef CONFIG_HEARTBEAT
static void dn_heartbeat(int on); static void dn_heartbeat(int on);
#endif #endif
@ -204,7 +200,8 @@ void dn_sched_init(irq_handler_t timer_routine)
printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3)); printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
#endif #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) { unsigned long dn_gettimeoffset(void) {

View File

@ -33,7 +33,6 @@
#include <asm/atari_joystick.h> #include <asm/atari_joystick.h>
#include <asm/irq.h> #include <asm/irq.h>
extern unsigned int keymap_count;
/* Hook for MIDI serial driver */ /* Hook for MIDI serial driver */
void (*atari_MIDI_interrupt_hook) (void); void (*atari_MIDI_interrupt_hook) (void);
@ -567,14 +566,19 @@ static int atari_keyb_done = 0;
int atari_keyb_init(void) int atari_keyb_init(void)
{ {
int error;
if (atari_keyb_done) if (atari_keyb_done)
return 0; return 0;
kb_state.state = KEYBOARD; kb_state.state = KEYBOARD;
kb_state.len = 0; kb_state.len = 0;
request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW, error = request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt,
"keyboard/mouse/MIDI", atari_keyboard_interrupt); IRQ_TYPE_SLOW, "keyboard/mouse/MIDI",
atari_keyboard_interrupt);
if (error)
return error;
atari_turnoff_irq(IRQ_MFP_ACIA); atari_turnoff_irq(IRQ_MFP_ACIA);
do { do {

View File

@ -179,8 +179,9 @@ EXPORT_SYMBOL(stdma_islocked);
void __init stdma_init(void) void __init stdma_init(void)
{ {
stdma_isr = NULL; stdma_isr = NULL;
request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED, if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
"ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int); "ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int))
pr_err("Couldn't register ST-DMA interrupt\n");
} }

View File

@ -31,8 +31,9 @@ atari_sched_init(irq_handler_t timer_routine)
/* start timer C, div = 1:100 */ /* start timer C, div = 1:100 */
mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60; mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
/* install interrupt service routine for MFP Timer C */ /* install interrupt service routine for MFP Timer C */
request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW, if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
"timer", timer_routine); "timer", timer_routine))
pr_err("Couldn't register timer interrupt\n");
} }
/* ++andreas: gettimeoffset fixed to check for pending interrupt */ /* ++andreas: gettimeoffset fixed to check for pending interrupt */

View File

@ -43,7 +43,6 @@ extern unsigned long bvme6000_gettimeoffset (void);
extern int bvme6000_hwclk (int, struct rtc_time *); extern int bvme6000_hwclk (int, struct rtc_time *);
extern int bvme6000_set_clock_mmss (unsigned long); extern int bvme6000_set_clock_mmss (unsigned long);
extern void bvme6000_reset (void); extern void bvme6000_reset (void);
extern void bvme6000_waitbut(void);
void bvme6000_set_vectors (void); void bvme6000_set_vectors (void);
/* Save tick handler routine pointer, will point to do_timer() in /* Save tick handler routine pointer, will point to do_timer() in

View File

@ -70,7 +70,8 @@ void __init hp300_sched_init(irq_handler_t vector)
asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE)); 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 + CLKCR2, 0x1); /* select CR1 */
out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */ out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */

1
arch/m68k/kernel/.gitignore vendored Normal file
View File

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

View File

@ -424,7 +424,7 @@ resume:
.data .data
ALIGN ALIGN
sys_call_table: 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_exit
.long sys_fork .long sys_fork
.long sys_read .long sys_read

View File

@ -26,6 +26,7 @@
#include <linux/initrd.h> #include <linux/initrd.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/sections.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/fpu.h> #include <asm/fpu.h>
#include <asm/irq.h> #include <asm/irq.h>
@ -62,7 +63,6 @@ EXPORT_SYMBOL(vme_brdtype);
int m68k_is040or060; int m68k_is040or060;
EXPORT_SYMBOL(m68k_is040or060); EXPORT_SYMBOL(m68k_is040or060);
extern int end;
extern unsigned long availmem; extern unsigned long availmem;
int m68k_num_memory; 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) void __init setup_arch(char **cmdline_p)
{ {
extern int _etext, _edata, _end;
int i; int i;
/* The bootinfo is located right after the kernel bss */ /* 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) if (CPU_IS_040)
m68k_is040or060 = 4; m68k_is040or060 = 4;
@ -252,9 +251,9 @@ void __init setup_arch(char **cmdline_p)
} }
init_mm.start_code = PAGE_OFFSET; init_mm.start_code = PAGE_OFFSET;
init_mm.end_code = (unsigned long) &_etext; init_mm.end_code = (unsigned long)_etext;
init_mm.end_data = (unsigned long) &_edata; init_mm.end_data = (unsigned long)_edata;
init_mm.brk = (unsigned long) &_end; init_mm.brk = (unsigned long)_end;
*cmdline_p = m68k_command_line; *cmdline_p = m68k_command_line;
memcpy(boot_command_line, *cmdline_p, CL_SIZE); memcpy(boot_command_line, *cmdline_p, CL_SIZE);

View File

@ -326,6 +326,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
struct sigcontext context; struct sigcontext context;
int err; int err;
/* Always make any pending restarted system calls return -EINTR */
current_thread_info()->restart_block.fn = do_no_restart_syscall;
/* get previous context */ /* get previous context */
if (copy_from_user(&context, usc, sizeof(context))) if (copy_from_user(&context, usc, sizeof(context)))
goto badframe; goto badframe;
@ -411,6 +414,9 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
unsigned long usp; unsigned long usp;
int err; 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); err = __get_user(temp, &uc->uc_mcontext.version);
if (temp != MCONTEXT_VERSION) if (temp != MCONTEXT_VERSION)
goto badframe; goto badframe;
@ -937,6 +943,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
regs->d0 = -EINTR; regs->d0 = -EINTR;
break; break;
case -ERESTART_RESTARTBLOCK:
if (!has_handler) {
regs->d0 = __NR_restart_syscall;
regs->pc -= 2;
break;
}
regs->d0 = -EINTR;
break;
case -ERESTARTSYS: case -ERESTARTSYS:
if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) { if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
regs->d0 = -EINTR; regs->d0 = -EINTR;

View File

@ -33,6 +33,7 @@ SECTIONS
} :data } :data
/* End of data goes *here* so that freeing init code works properly. */ /* End of data goes *here* so that freeing init code works properly. */
_edata = .; _edata = .;
NOTES
/* will be freed after init */ /* will be freed after init */
. = ALIGN(PAGE_SIZE); /* Init code and data */ . = ALIGN(PAGE_SIZE); /* Init code and data */

View File

@ -92,7 +92,8 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
void __init baboon_register_interrupts(void) void __init baboon_register_interrupts(void)
{ {
baboon_disabled = 0; 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");
} }
/* /*

View File

@ -47,13 +47,6 @@
struct mac_booter_data mac_bi_data; 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 */ /* The phys. video addr. - might be bogus on some machines */
static unsigned long mac_orig_videoaddr; static unsigned long mac_orig_videoaddr;
@ -61,7 +54,6 @@ static unsigned long mac_orig_videoaddr;
extern unsigned long mac_gettimeoffset(void); extern unsigned long mac_gettimeoffset(void);
extern int mac_hwclk(int, struct rtc_time *); extern int mac_hwclk(int, struct rtc_time *);
extern int mac_set_clock_mmss(unsigned long); 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_preinit(void);
extern void iop_init(void); extern void iop_init(void);
extern void via_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); mac_bi_data.boottime, mac_bi_data.gmtbias);
printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n", 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); 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(); iop_init();
via_init(); via_init();

View File

@ -27,7 +27,6 @@
#include <asm/macints.h> #include <asm/macints.h>
extern unsigned long mac_videobase; extern unsigned long mac_videobase;
extern unsigned long mac_videodepth;
extern unsigned long mac_rowbytes; extern unsigned long mac_rowbytes;
extern void mac_serial_print(const char *); extern void mac_serial_print(const char *);

View File

@ -305,14 +305,16 @@ void __init iop_register_interrupts(void)
{ {
if (iop_ism_present) { if (iop_ism_present) {
if (oss_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", 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); oss_irq_enable(IRQ_MAC_ADB);
} else { } 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", 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])) { if (!iop_alive(iop_base[IOP_NUM_ISM])) {
printk("IOP: oh my god, they killed the ISM IOP!\n"); printk("IOP: oh my god, they killed the ISM IOP!\n");

View File

@ -134,6 +134,7 @@
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/macints.h> #include <asm/macints.h>
#include <asm/irq_regs.h> #include <asm/irq_regs.h>
#include <asm/mac_oss.h>
#define DEBUG_SPURIOUS #define DEBUG_SPURIOUS
#define SHUTUP_SONIC #define SHUTUP_SONIC
@ -146,7 +147,6 @@ static int scc_mask;
* VIA/RBV hooks * VIA/RBV hooks
*/ */
extern void via_init(void);
extern void via_register_interrupts(void); extern void via_register_interrupts(void);
extern void via_irq_enable(int); extern void via_irq_enable(int);
extern void via_irq_disable(int); extern void via_irq_disable(int);
@ -157,9 +157,6 @@ extern int via_irq_pending(int);
* OSS hooks * OSS hooks
*/ */
extern int oss_present;
extern void oss_init(void);
extern void oss_register_interrupts(void); extern void oss_register_interrupts(void);
extern void oss_irq_enable(int); extern void oss_irq_enable(int);
extern void oss_irq_disable(int); extern void oss_irq_disable(int);
@ -170,9 +167,6 @@ extern int oss_irq_pending(int);
* PSC hooks * PSC hooks
*/ */
extern int psc_present;
extern void psc_init(void);
extern void psc_register_interrupts(void); extern void psc_register_interrupts(void);
extern void psc_irq_enable(int); extern void psc_irq_enable(int);
extern void psc_irq_disable(int); extern void psc_irq_disable(int);
@ -191,12 +185,10 @@ extern void iop_register_interrupts(void);
extern int baboon_present; extern int baboon_present;
extern void baboon_init(void);
extern void baboon_register_interrupts(void); extern void baboon_register_interrupts(void);
extern void baboon_irq_enable(int); extern void baboon_irq_enable(int);
extern void baboon_irq_disable(int); extern void baboon_irq_disable(int);
extern void baboon_irq_clear(int); extern void baboon_irq_clear(int);
extern int baboon_irq_pending(int);
/* /*
* SCC interrupt routines * SCC interrupt routines
@ -258,8 +250,9 @@ void __init mac_init_IRQ(void)
if (baboon_present) if (baboon_present)
baboon_register_interrupts(); baboon_register_interrupts();
iop_register_interrupts(); iop_register_interrupts();
request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI", if (request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
mac_nmi_handler); mac_nmi_handler))
pr_err("Couldn't register NMI\n");
#ifdef DEBUG_MACINTS #ifdef DEBUG_MACINTS
printk("mac_init_IRQ(): Done!\n"); printk("mac_init_IRQ(): Done!\n");
#endif #endif

View File

@ -35,7 +35,6 @@
#define RTC_OFFSET 2082844800 #define RTC_OFFSET 2082844800
extern struct mac_booter_data mac_bi_data;
static void (*rom_reset)(void); static void (*rom_reset)(void);
#ifdef CONFIG_ADB_CUDA #ifdef CONFIG_ADB_CUDA

View File

@ -66,16 +66,21 @@ void __init oss_init(void)
void __init oss_register_interrupts(void) void __init oss_register_interrupts(void)
{ {
request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK, if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
"scsi", (void *) oss); "scsi", (void *) oss))
request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK, pr_err("Couldn't register %s interrupt\n", "scsi");
"scc", mac_scc_dispatch); if (request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK, "scc", mac_scc_dispatch))
"nubus", (void *) oss); pr_err("Couldn't register %s interrupt\n", "scc");
request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK, if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
"sound", (void *) oss); "nubus", (void *) oss))
request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK, pr_err("Couldn't register %s interrupt\n", "nubus");
"via1", (void *) via1); 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");
} }
/* /*

View File

@ -117,10 +117,14 @@ void __init psc_init(void)
void __init psc_register_interrupts(void) void __init psc_register_interrupts(void)
{ {
request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30); if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40); pr_err("Couldn't register psc%d interrupt\n", 3);
request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50); if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60); 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);
} }
/* /*

View File

@ -34,6 +34,7 @@
#include <asm/macints.h> #include <asm/macints.h>
#include <asm/mac_via.h> #include <asm/mac_via.h>
#include <asm/mac_psc.h> #include <asm/mac_psc.h>
#include <asm/mac_oss.h>
volatile __u8 *via1, *via2; volatile __u8 *via1, *via2;
int rbv_present; int rbv_present;
@ -84,7 +85,6 @@ void via_irq_disable(int irq);
void via_irq_clear(int irq); void via_irq_clear(int irq);
extern irqreturn_t mac_scc_dispatch(int, void *); extern irqreturn_t mac_scc_dispatch(int, void *);
extern int oss_present;
/* /*
* Initialize the VIAs * Initialize the VIAs
@ -283,7 +283,8 @@ void __init via_init_clock(irq_handler_t func)
via1[vT1CL] = MAC_CLOCK_LOW; via1[vT1CL] = MAC_CLOCK_LOW;
via1[vT1CH] = MAC_CLOCK_HIGH; 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) void __init via_register_interrupts(void)
{ {
if (via_alt_mapping) { 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", IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
(void *) via1); (void *) via1))
request_irq(IRQ_AUTO_6, via1_irq, pr_err("Couldn't register %s interrupt\n", "software");
if (request_irq(IRQ_AUTO_6, via1_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
(void *) via1); (void *) via1))
pr_err("Couldn't register %s interrupt\n", "via1");
} else { } else {
request_irq(IRQ_AUTO_1, via1_irq, if (request_irq(IRQ_AUTO_1, via1_irq,
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1", 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, if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
"via2", (void *) via2); "via2", (void *) via2))
pr_err("Couldn't register %s interrupt\n", "via2");
if (!psc_present) { if (!psc_present) {
request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK, if (request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
"scc", mac_scc_dispatch); "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, if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
"nubus", (void *) via2); IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
pr_err("Couldn't register %s interrupt\n", "nubus");
} }
/* /*

View File

@ -24,7 +24,6 @@ static const struct fp_ext fp_one =
extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src); extern struct fp_ext *fp_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_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 * struct fp_ext *
fp_fsqrt(struct fp_ext *dest, struct fp_ext *src) fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)

View File

@ -28,6 +28,7 @@
#ifdef CONFIG_ATARI #ifdef CONFIG_ATARI
#include <asm/atari_stram.h> #include <asm/atari_stram.h>
#endif #endif
#include <asm/sections.h>
#include <asm/tlb.h> #include <asm/tlb.h>
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@ -73,9 +74,6 @@ extern void init_pointer_table(unsigned long ptable);
/* References to section boundaries */ /* References to section boundaries */
extern char _text[], _etext[];
extern char __init_begin[], __init_end[];
extern pmd_t *zero_pgtable; extern pmd_t *zero_pgtable;
void __init mem_init(void) void __init mem_init(void)

View File

@ -30,6 +30,7 @@
#ifdef CONFIG_ATARI #ifdef CONFIG_ATARI
#include <asm/atari_stram.h> #include <asm/atari_stram.h>
#endif #endif
#include <asm/sections.h>
#undef DEBUG #undef DEBUG
@ -301,14 +302,12 @@ void __init paging_init(void)
} }
} }
extern char __init_begin, __init_end;
void free_initmem(void) void free_initmem(void)
{ {
unsigned long addr; unsigned long addr;
addr = (unsigned long)&__init_begin; addr = (unsigned long)__init_begin;
for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) { for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
virt_to_page(addr)->flags &= ~(1 << PG_reserved); virt_to_page(addr)->flags &= ~(1 << PG_reserved);
init_page_count(virt_to_page(addr)); init_page_count(virt_to_page(addr));
free_page(addr); free_page(addr);

View File

@ -42,7 +42,6 @@ extern unsigned long mvme147_gettimeoffset (void);
extern int mvme147_hwclk (int, struct rtc_time *); extern int mvme147_hwclk (int, struct rtc_time *);
extern int mvme147_set_clock_mmss (unsigned long); extern int mvme147_set_clock_mmss (unsigned long);
extern void mvme147_reset (void); extern void mvme147_reset (void);
extern void mvme147_waitbut(void);
static int bcd2int (unsigned char b); 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) void mvme147_sched_init (irq_handler_t timer_routine)
{ {
tick_handler = timer_routine; tick_handler = timer_routine;
request_irq (PCC_IRQ_TIMER1, mvme147_timer_int, if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
IRQ_FLG_REPLACE, "timer 1", NULL); "timer 1", NULL))
pr_err("Couldn't register timer interrupt\n");
/* Init the clock with a value */ /* Init the clock with a value */
/* our clock goes off every 6.25us */ /* our clock goes off every 6.25us */

View File

@ -48,7 +48,6 @@ extern unsigned long mvme16x_gettimeoffset (void);
extern int mvme16x_hwclk (int, struct rtc_time *); extern int mvme16x_hwclk (int, struct rtc_time *);
extern int mvme16x_set_clock_mmss (unsigned long); extern int mvme16x_set_clock_mmss (unsigned long);
extern void mvme16x_reset (void); extern void mvme16x_reset (void);
extern void mvme16x_waitbut(void);
int bcd2int (unsigned char b); int bcd2int (unsigned char b);

View File

@ -36,7 +36,6 @@
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/q40_master.h> #include <asm/q40_master.h>
extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
extern void q40_init_IRQ(void); extern void q40_init_IRQ(void);
static void q40_get_model(char *model); static void q40_get_model(char *model);
extern void q40_sched_init(irq_handler_t handler); 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_set_clock_mmss(unsigned long);
static int q40_get_rtc_pll(struct rtc_pll_info *pll); static int q40_get_rtc_pll(struct rtc_pll_info *pll);
static int q40_set_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*/); extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);

View File

@ -27,23 +27,21 @@
#include <asm/sun3mmu.h> #include <asm/sun3mmu.h>
#include <asm/rtc.h> #include <asm/rtc.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/idprom.h>
#include <asm/intersil.h> #include <asm/intersil.h>
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/sections.h>
#include <asm/segment.h> #include <asm/segment.h>
#include <asm/sun3ints.h> #include <asm/sun3ints.h>
extern char _text, _end;
char sun3_reserved_pmeg[SUN3_PMEGS_NUM]; char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
extern unsigned long sun3_gettimeoffset(void); extern unsigned long sun3_gettimeoffset(void);
static void sun3_sched_init(irq_handler_t handler); static void sun3_sched_init(irq_handler_t handler);
extern void sun3_get_model (char* model); extern void sun3_get_model (char* model);
extern void idprom_init (void);
extern int sun3_hwclk(int set, struct rtc_time *t); extern int sun3_hwclk(int set, struct rtc_time *t);
volatile char* clock_va; volatile char* clock_va;
extern volatile unsigned char* sun3_intreg;
extern unsigned long availmem; extern unsigned long availmem;
unsigned long num_pages; unsigned long num_pages;
@ -149,7 +147,7 @@ void __init config_sun3(void)
mach_halt = sun3_halt; mach_halt = sun3_halt;
mach_get_hardware_list = sun3_get_hardware_list; 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 // PROM seems to want the last couple of physical pages. --m
memory_end = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE; memory_end = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE;

View File

@ -27,7 +27,6 @@
#include <asm/mmu_context.h> #include <asm/mmu_context.h>
#include <asm/dvma.h> #include <asm/dvma.h>
extern void prom_reboot (char *) __attribute__ ((__noreturn__));
#undef DEBUG_MMU_EMU #undef DEBUG_MMU_EMU
#define DEBUG_PROM_MAPS #define DEBUG_PROM_MAPS

View File

@ -105,7 +105,10 @@ void __init sun3_init_IRQ(void)
m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7); m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
m68k_setup_user_interrupt(VEC_USER, 128, NULL); m68k_setup_user_interrupt(VEC_USER, 128, NULL);
request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL); if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL); pr_err("Couldn't register %s interrupt\n", "int5");
request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL); 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");
} }

View File

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

View File

@ -595,6 +595,44 @@ config WR_PPMC
This enables support for the Wind River MIPS32 4KC PPMC evaluation This enables support for the Wind River MIPS32 4KC PPMC evaluation
board, which is based on GT64120 bridge chip. 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 endchoice
source "arch/mips/alchemy/Kconfig" source "arch/mips/alchemy/Kconfig"
@ -607,6 +645,7 @@ source "arch/mips/sgi-ip27/Kconfig"
source "arch/mips/sibyte/Kconfig" source "arch/mips/sibyte/Kconfig"
source "arch/mips/txx9/Kconfig" source "arch/mips/txx9/Kconfig"
source "arch/mips/vr41xx/Kconfig" source "arch/mips/vr41xx/Kconfig"
source "arch/mips/cavium-octeon/Kconfig"
endmenu endmenu
@ -682,7 +721,11 @@ config CEVT_DS1287
config CEVT_GT641XX config CEVT_GT641XX
bool bool
config CEVT_R4K_LIB
bool
config CEVT_R4K config CEVT_R4K
select CEVT_R4K_LIB
bool bool
config CEVT_SB1250 config CEVT_SB1250
@ -697,7 +740,11 @@ config CSRC_BCM1480
config CSRC_IOASIC config CSRC_IOASIC
bool bool
config CSRC_R4K_LIB
bool
config CSRC_R4K config CSRC_R4K
select CSRC_R4K_LIB
bool bool
config CSRC_SB1250 config CSRC_SB1250
@ -835,6 +882,9 @@ config IRQ_GT641XX
config IRQ_GIC config IRQ_GIC
bool bool
config IRQ_CPU_OCTEON
bool
config MIPS_BOARDS_GEN config MIPS_BOARDS_GEN
bool bool
@ -924,7 +974,7 @@ config BOOT_ELF32
config MIPS_L1_CACHE_SHIFT config MIPS_L1_CACHE_SHIFT
int int
default "4" if MACH_DECSTATION || MIKROTIK_RB532 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 "4" if PMC_MSP4200_EVAL
default "5" default "5"
@ -1185,6 +1235,23 @@ config CPU_SB1
select CPU_SUPPORTS_HIGHMEM select CPU_SUPPORTS_HIGHMEM
select WEAK_ORDERING 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 endchoice
config SYS_HAS_CPU_LOONGSON2 config SYS_HAS_CPU_LOONGSON2
@ -1285,7 +1352,7 @@ config CPU_MIPSR1
config CPU_MIPSR2 config CPU_MIPSR2
bool 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 config SYS_SUPPORTS_32BIT_KERNEL
bool bool

View File

@ -144,6 +144,10 @@ cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \
cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap
cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \ cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \
-Wa,--trap -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_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,) 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 # 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 cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000 load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000
# #
# AMD Alchemy Pb1100 eval board # 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 cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000 load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000
# #
# AMD Alchemy Pb1500 eval board # 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 cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000 load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000
# #
# AMD Alchemy Pb1550 eval board # 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 cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000 load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000
# #
# AMD Alchemy Pb1200 eval board # 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 cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000 load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000
# #
# AMD Alchemy Db1000 eval board # 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 cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000 load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000
# #
# AMD Alchemy Db1100 eval board # 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 cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000 load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000
# #
# AMD Alchemy Db1500 eval board # 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 cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000 load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000
# #
# AMD Alchemy Db1550 eval board # 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 cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000 load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000
# #
# AMD Alchemy Db1200 eval board # 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 cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000 load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000
# #
# AMD Alchemy Bosporus eval board # 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 cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000 load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000
# #
# AMD Alchemy Mirage eval board # 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 cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000 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_RBTX4938) += arch/mips/txx9/rbtx4938/
core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/ 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 cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
drivers-$(CONFIG_PCI) += arch/mips/pci/ drivers-$(CONFIG_PCI) += arch/mips/pci/

View File

@ -128,9 +128,10 @@ config SOC_AU1200
config SOC_AU1X00 config SOC_AU1X00
bool bool
select 64BIT_PHYS_ADDR select 64BIT_PHYS_ADDR
select CEVT_R4K select CEVT_R4K_LIB
select CSRC_R4K select CSRC_R4K_LIB
select IRQ_CPU select IRQ_CPU
select SYS_HAS_CPU_MIPS32_R1 select SYS_HAS_CPU_MIPS32_R1
select SYS_SUPPORTS_32BIT_KERNEL select SYS_SUPPORTS_32BIT_KERNEL
select SYS_SUPPORTS_APM_EMULATION select SYS_SUPPORTS_APM_EMULATION
select GENERIC_HARDIRQS_NO__DO_IRQ

View File

@ -6,8 +6,8 @@
# #
obj-y += prom.o irq.o puts.o time.o reset.o \ obj-y += prom.o irq.o puts.o time.o reset.o \
au1xxx_irqmap.o clocks.o platform.o power.o setup.o \ clocks.o platform.o power.o setup.o \
sleeper.o cputable.o dma.o dbdma.o gpio.o sleeper.o dma.o dbdma.o gpio.o
obj-$(CONFIG_PCI) += pci.o obj-$(CONFIG_PCI) += pci.o

View File

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

View File

@ -27,12 +27,21 @@
*/ */
#include <linux/module.h> #include <linux/module.h>
#include <linux/spinlock.h>
#include <asm/time.h>
#include <asm/mach-au1x00/au1000.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 au1x00_clock; /* Hz */
static unsigned int lcd_clock; /* KHz */
static unsigned long uart_baud_base; static unsigned long uart_baud_base;
static DEFINE_SPINLOCK(time_lock);
/* /*
* Set the au1000_clock * 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 * We read the real processor speed from the PLL. This is important
* cpu clock and the system bus clock, and try to keep it * because it is more accurate than computing it from the 32 KHz
* below 40 MHz (the Pb1000 board can lock-up if the LCD * counter, if it exists. If we don't have an accurate processor
* clock is over 40 MHz). * 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 long cpu_speed;
unsigned int sys_busclk = (get_au1x00_speed() / 1000) / unsigned long flags;
((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2);
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 else
lcd_clock = sys_busclk / 4; cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
if (lcd_clock > 50000) /* Epson MAX */ /* On Alchemy CPU:counter ratio is 1:1 */
printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n", mips_hpt_frequency = cpu_speed;
lcd_clock); /* 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) spin_unlock_irqrestore(&time_lock, flags);
{
return lcd_clock; set_au1x00_speed(cpu_speed);
return cpu_speed;
} }
EXPORT_SYMBOL(get_au1x00_lcd_clock);

View File

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

View File

@ -174,6 +174,11 @@ static dbdev_tab_t dbdev_tab[] = {
#define DBDEV_TAB_SIZE ARRAY_SIZE(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 chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
static dbdev_tab_t *find_dbdev_id(u32 id) 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; 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) */ #endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */

View File

@ -24,6 +24,7 @@
* with this program; if not, write to the Free Software Foundation, Inc., * with this program; if not, write to the Free Software Foundation, Inc.,
* 675 Mass Ave, Cambridge, MA 02139, USA. * 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
@ -36,15 +37,172 @@
#include <asm/mach-pb1x00/pb1000.h> #include <asm/mach-pb1x00/pb1000.h>
#endif #endif
#define EXT_INTC0_REQ0 2 /* IP 2 */ static int au1x_ic_settype(unsigned int irq, unsigned int flow_type);
#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; /* 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 #ifdef CONFIG_PM
@ -130,67 +288,47 @@ void restore_au1xxx_intctl(void)
#endif /* CONFIG_PM */ #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; unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
au_writel(1 << bit, IC0_MASKSET);
if (bit >= 32) { au_writel(1 << bit, IC0_WAKESET);
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_sync(); au_sync();
} }
static void au1x_ic1_unmask(unsigned int irq_nr)
inline void local_disable_irq(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) { /* very hacky. does the pb1000 cpld auto-disable this int?
au_writel(1 << (bit - 32), IC1_MASKCLR); * nowhere in the current kernel sources is it disabled. --mlau
au_writel(1 << (bit - 32), IC1_WAKECLR); */
} else { #if defined(CONFIG_MIPS_PB1000)
au_writel(1 << bit, IC0_MASKCLR); if (irq_nr == AU1000_GPIO_15)
au_writel(1 << bit, IC0_WAKECLR); au_writel(0x4000, PB1000_MDR); /* enable int */
} #endif
au_sync(); au_sync();
} }
static void au1x_ic0_mask(unsigned int irq_nr)
static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
{ {
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
au_writel(1 << bit, IC0_MASKCLR);
if (bit >= 32) { au_writel(1 << bit, IC0_WAKECLR);
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_sync(); au_sync();
} }
static void au1x_ic1_mask(unsigned int irq_nr)
static inline void mask_and_ack_fall_edge_irq(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_MASKCLR);
if (bit >= 32) { au_writel(1 << bit, IC1_WAKECLR);
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);
}
au_sync(); au_sync();
} }
static void au1x_ic0_ack(unsigned int irq_nr)
static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
{ {
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE; 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 * This may assume that we don't get interrupts from
* both edges at once, or if we do, that we don't care. * both edges at once, or if we do, that we don't care.
*/ */
if (bit >= 32) { au_writel(1 << bit, IC0_FALLINGCLR);
au_writel(1 << (bit - 32), IC1_FALLINGCLR); au_writel(1 << bit, IC0_RISINGCLR);
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_sync(); 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); unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
/*
* 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(); 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) static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
{ {
if (!(irq_desc[irq_nr].status & (IRQ_DISABLED | IRQ_INPROGRESS))) unsigned int bit = irq - AU1000_INTC1_INT_BASE;
local_enable_irq(irq_nr); unsigned long wakemsk, flags;
#if defined(CONFIG_MIPS_PB1000) /* only GPIO 0-7 can act as wakeup source: */
if (irq_nr == AU1000_GPIO_15) { if ((irq < AU1000_GPIO_0) || (irq > AU1000_GPIO_7))
au_writel(0x4000, PB1000_MDR); /* enable int */ return -EINVAL;
au_sync();
}
#endif
}
unsigned long save_local_and_disable(int controller) local_irq_save(flags);
{ wakemsk = au_readl(SYS_WAKEMSK);
int i; if (on)
unsigned long flags, mask; wakemsk |= 1 << bit;
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;
}
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);
}
if (controller)
new_mask = au_readl(IC1_MASKSET);
else else
new_mask = au_readl(IC0_MASKSET); wakemsk &= ~(1 << bit);
au_writel(wakemsk, SYS_WAKEMSK);
spin_unlock_irqrestore(&irq_lock, flags);
}
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,
};
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 void __init setup_local_irq(unsigned int irq_nr, int type, int int_req)
{
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);
} 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);
}
au_sync(); au_sync();
local_irq_restore(flags);
return 0;
} }
/* /*
* Interrupts are nested. Even if an interrupt handler is registered * irq_chips for both ICs; this way the mask handlers can be
* as "fast", we might get another interrupt before we return from * as short as possible.
* intcX_reqX_irqdispatch(). *
* 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 void intc0_req0_irqdispatch(void) 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 int au1x_ic_settype(unsigned int irq, unsigned int flow_type)
{ {
static unsigned long intc0_req0; struct irq_chip *chip;
unsigned int bit; unsigned long icr[6];
unsigned int bit, ic;
int ret;
intc0_req0 |= au_readl(IC0_REQ0INT); if (irq >= AU1000_INTC1_INT_BASE) {
bit = irq - AU1000_INTC1_INT_BASE;
chip = &au1x_ic1_chip;
ic = 1;
} else {
bit = irq - AU1000_INTC0_INT_BASE;
chip = &au1x_ic0_chip;
ic = 0;
}
if (!intc0_req0) 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();
return ret;
}
asmlinkage void plat_irq_dispatch(void)
{
unsigned int pending = read_c0_status() & read_c0_cause();
unsigned long s, off, bit;
if (pending & CAUSEF_IP7) {
do_IRQ(MIPS_CPU_IRQ_BASE + 7);
return; 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 #ifdef AU1000_USB_DEV_REQ_INT
/* /*
* Because of the tight timing of SETUP token to reply * Because of the tight timing of SETUP token to reply
* transactions, the USB devices-side packet complete * transactions, the USB devices-side packet complete
* interrupt needs the highest priority. * interrupt needs the highest priority.
*/ */
if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) { bit = 1 << (AU1000_USB_DEV_REQ_INT - AU1000_INTC0_INT_BASE);
intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT); if ((pending & CAUSEF_IP2) && (s & bit)) {
do_IRQ(AU1000_USB_DEV_REQ_INT); do_IRQ(AU1000_USB_DEV_REQ_INT);
return; return;
} }
#endif #endif
bit = __ffs(intc0_req0); do_IRQ(__ffs(s) + off);
intc0_req0 &= ~(1 << bit);
do_IRQ(AU1000_INTC0_INT_BASE + bit);
} }
/* setup edge/level and assign request 0/1 */
static void intc0_req1_irqdispatch(void) void __init au1xxx_setup_irqmap(struct au1xxx_irqmap *map, int count)
{ {
static unsigned long intc0_req1; unsigned int bit, irq_nr;
unsigned int bit;
intc0_req1 |= au_readl(IC0_REQ1INT); while (count--) {
irq_nr = map[count].im_irq;
if (!intc0_req1) if (((irq_nr < AU1000_INTC0_INT_BASE) ||
return; (irq_nr >= AU1000_INTC0_INT_BASE + 32)) &&
((irq_nr < AU1000_INTC1_INT_BASE) ||
(irq_nr >= AU1000_INTC1_INT_BASE + 32)))
continue;
bit = __ffs(intc0_req1); if (irq_nr >= AU1000_INTC1_INT_BASE) {
intc0_req1 &= ~(1 << bit); bit = irq_nr - AU1000_INTC1_INT_BASE;
do_IRQ(AU1000_INTC0_INT_BASE + bit); 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);
}
au1x_ic_settype(irq_nr, map[count].im_type);
/* }
* Interrupt Controller 1:
* interrupts 32 - 63
*/
static void intc1_req0_irqdispatch(void)
{
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();
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();
} }
void __init arch_init_irq(void) void __init arch_init_irq(void)
{ {
int i; 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. * Initialize interrupt controllers to a safe state.
@ -569,28 +587,25 @@ void __init arch_init_irq(void)
mips_cpu_irq_init(); mips_cpu_irq_init();
/* register all 64 possible IC0+IC1 irq sources as type "none".
* Use set_irq_type() to set edge/level behaviour at runtime.
*/
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);
/* /*
* Initialize IC0, which is fixed per processor. * Initialize IC0, which is fixed per processor.
*/ */
imp = au1xxx_ic0_map; au1xxx_setup_irqmap(au1xxx_ic0_map, ARRAY_SIZE(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++;
}
/* /* Boards can register additional (GPIO-based) IRQs.
* Now set up the irq mapping for the board.
*/
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);
/* Board specific IRQ initialization.
*/ */
if (board_init_irq) board_init_irq();
board_init_irq();
set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
} }

View File

@ -35,25 +35,12 @@
#include <linux/jiffies.h> #include <linux/jiffies.h>
#include <asm/uaccess.h> #include <asm/uaccess.h>
#include <asm/cacheflush.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
#ifdef CONFIG_PM #include <asm/mach-au1x00/au1xxx_dbdma.h>
#define DEBUG 1
#ifdef DEBUG
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
#else
#define DPRINTK(fmt, args...)
#endif #endif
static void au1000_calibrate_delay(void); #ifdef CONFIG_PM
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);
/* /*
* We need to save/restore a bunch of core registers that are * 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 * We only have to save/restore registers that aren't otherwise
* done as part of a driver pm_* function. * done as part of a driver pm_* function.
*/ */
static unsigned int sleep_aux_pll_cntrl; static unsigned int sleep_uart0_inten;
static unsigned int sleep_cpu_pll_cntrl; static unsigned int sleep_uart0_fifoctl;
static unsigned int sleep_pin_function; static unsigned int sleep_uart0_linectl;
static unsigned int sleep_uart0_inten; static unsigned int sleep_uart0_clkdiv;
static unsigned int sleep_uart0_fifoctl; static unsigned int sleep_uart0_enable;
static unsigned int sleep_uart0_linectl; static unsigned int sleep_usb[2];
static unsigned int sleep_uart0_clkdiv; static unsigned int sleep_sys_clocks[5];
static unsigned int sleep_uart0_enable; static unsigned int sleep_sys_pinfunc;
static unsigned int sleep_usbhost_enable; static unsigned int sleep_static_memctlr[4][3];
static unsigned int sleep_usbdev_enable;
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) 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_linectl = au_readl(UART0_ADDR + UART_LCR);
sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK); sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL); sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
au_sync();
#ifndef CONFIG_SOC_AU1200
/* Shutdown USB host/device. */ /* 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.... */ /* There appears to be some undocumented reset register.... */
au_writel(0, 0xb0100004); au_sync(); au_writel(0, 0xb0100004);
au_writel(0, USB_HOST_CONFIG); au_sync(); au_sync();
au_writel(0, USB_HOST_CONFIG);
au_sync();
sleep_usbdev_enable = au_readl(USBD_ENABLE); sleep_usb[1] = au_readl(USBD_ENABLE);
au_writel(0, USBD_ENABLE); au_sync(); 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 interrupt controller state. */
save_au1xxx_intctl(); save_au1xxx_intctl();
/* Clocks and PLLs. */ /* 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);
/* /* pin mux config */
* We don't really need to do this one, but unless we sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
* 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);
/* Save the static memory controller configuration. */ /* Save the static memory controller configuration. */
sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0); 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][0] = au_readl(MEM_STCFG3);
sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3); sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3); 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) static void restore_core_regs(void)
{ {
extern void restore_au1xxx_intctl(void); /* restore clock configuration. Writing CPUPLL last will
extern void wakeup_counter0_adjust(void); * 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_sys_pinfunc, SYS_PINFUNC);
au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync(); au_sync();
au_writel(sleep_pin_function, 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. */ /* Restore the static memory controller configuration. */
au_writel(sleep_static_memctlr[0][0], MEM_STCFG0); au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
@ -184,282 +201,17 @@ static void restore_core_regs(void)
} }
restore_au1xxx_intctl(); restore_au1xxx_intctl();
wakeup_counter0_adjust();
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
au1xxx_dbdma_resume();
#endif
} }
unsigned long suspend_mode; void au_sleep(void)
void wakeup_from_suspend(void)
{ {
suspend_mode = 0;
}
int au_sleep(void)
{
unsigned long wakeup, flags;
extern void save_and_sleep(void);
spin_lock_irqsave(&pm_lock, flags);
save_core_regs(); save_core_regs();
au1xxx_save_and_sleep();
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.
*/
restore_core_regs(); 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 */ #endif /* CONFIG_PM */

View File

@ -31,8 +31,6 @@
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
extern int au_sleep(void);
void au1000_restart(char *command) void au1000_restart(char *command)
{ {
/* Set all integrated peripherals to disabled states */ /* Set all integrated peripherals to disabled states */

View File

@ -35,7 +35,6 @@
#include <asm/time.h> #include <asm/time.h>
#include <au1000.h> #include <au1000.h>
#include <prom.h>
extern void __init board_setup(void); extern void __init board_setup(void);
extern void au1000_restart(char *); extern void au1000_restart(char *);
@ -45,80 +44,34 @@ extern void set_cpuspec(void);
void __init plat_mem_setup(void) void __init plat_mem_setup(void)
{ {
struct cpu_spec *sp; unsigned long est_freq;
char *argptr;
unsigned long prid, cpufreq, bclk;
set_cpuspec(); /* determine core clock */
sp = cur_cpu_spec[0]; 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);
_machine_restart = au1000_restart;
_machine_halt = au1000_halt;
pm_power_off = au1000_power_off;
board_setup(); /* board specific setup */ board_setup(); /* board specific setup */
prid = read_c0_prid(); if (au1xxx_cpu_needs_config_od())
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);
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");
}
if (sp->cpu_od)
/* Various early Au1xx0 errata corrected by this */ /* Various early Au1xx0 errata corrected by this */
set_c0_config(1 << 19); /* Set Config[OD] */ set_c0_config(1 << 19); /* Set Config[OD] */
else else
/* Clear to obtain best system bus performance */ /* Clear to obtain best system bus performance */
clear_c0_config(1 << 19); /* Clear Config[OD] */ 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. */ /* IO/MEM resources. */
set_io_port_base(0); set_io_port_base(0);
ioport_resource.start = IOPORT_RESOURCE_START; ioport_resource.start = IOPORT_RESOURCE_START;
ioport_resource.end = IOPORT_RESOURCE_END; ioport_resource.end = IOPORT_RESOURCE_END;
iomem_resource.start = IOMEM_RESOURCE_START; iomem_resource.start = IOMEM_RESOURCE_START;
iomem_resource.end = IOMEM_RESOURCE_END; 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) #if defined(CONFIG_64BIT_PHYS_ADDR)

View File

@ -15,16 +15,17 @@
#include <asm/regdef.h> #include <asm/regdef.h>
#include <asm/stackframe.h> #include <asm/stackframe.h>
.extern __flush_cache_all
.text .text
.set macro .set noreorder
.set noat .set noat
.align 5 .align 5
/* Save all of the processor general registers and go to sleep. /* Save all of the processor general registers and go to sleep.
* A wakeup condition will get us back here to restore the registers. * 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 subu sp, PT_SIZE
sw $1, PT_R1(sp) sw $1, PT_R1(sp)
sw $2, PT_R2(sp) sw $2, PT_R2(sp)
@ -33,14 +34,6 @@ LEAF(save_and_sleep)
sw $5, PT_R5(sp) sw $5, PT_R5(sp)
sw $6, PT_R6(sp) sw $6, PT_R6(sp)
sw $7, PT_R7(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 $16, PT_R16(sp)
sw $17, PT_R17(sp) sw $17, PT_R17(sp)
sw $18, PT_R18(sp) sw $18, PT_R18(sp)
@ -49,12 +42,9 @@ LEAF(save_and_sleep)
sw $21, PT_R21(sp) sw $21, PT_R21(sp)
sw $22, PT_R22(sp) sw $22, PT_R22(sp)
sw $23, PT_R23(sp) sw $23, PT_R23(sp)
sw $24, PT_R24(sp)
sw $25, PT_R25(sp)
sw $26, PT_R26(sp) sw $26, PT_R26(sp)
sw $27, PT_R27(sp) sw $27, PT_R27(sp)
sw $28, PT_R28(sp) sw $28, PT_R28(sp)
sw $29, PT_R29(sp)
sw $30, PT_R30(sp) sw $30, PT_R30(sp)
sw $31, PT_R31(sp) sw $31, PT_R31(sp)
mfc0 k0, CP0_STATUS mfc0 k0, CP0_STATUS
@ -66,20 +56,26 @@ LEAF(save_and_sleep)
mfc0 k0, CP0_CONFIG mfc0 k0, CP0_CONFIG
sw k0, 0x14(sp) 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 /* Now set up the scratch registers so the boot rom will
* return to this point upon wakeup. * return to this point upon wakeup.
* sys_scratch0 : SP
* sys_scratch1 : RA
*/ */
la k0, 1f lui t3, 0xb190 /* sys_xxx */
lui k1, 0xb190 sw sp, 0x0018(t3)
ori k1, 0x18 la k0, 3f /* resume path */
sw sp, 0(k1) sw k0, 0x001c(t3)
ori k1, 0x1c
sw k0, 0(k1)
/* Put SDRAM into self refresh. Preload instructions into cache, /* Put SDRAM into self refresh: Preload instructions into cache,
* issue a precharge, then auto refresh, then sleep commands to it. * issue a precharge, auto/self refresh, then sleep commands to it.
*/ */
la t0, sdsleep la t0, 1f
.set mips3 .set mips3
cache 0x14, 0(t0) cache 0x14, 0(t0)
cache 0x14, 32(t0) cache 0x14, 32(t0)
@ -87,24 +83,57 @@ LEAF(save_and_sleep)
cache 0x14, 96(t0) cache 0x14, 96(t0)
.set mips0 .set mips0
sdsleep: 1: lui a0, 0xb400 /* mem_xxx */
lui k0, 0xb400 #if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \
sw zero, 0x001c(k0) /* Precharge */ defined(CONFIG_SOC_AU1500)
sw zero, 0x0020(k0) /* Auto refresh */ sw zero, 0x001c(a0) /* Precharge */
sw zero, 0x0030(k0) /* SDRAM sleep */ 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 sync
lui k1, 0xb190 /* wait for sdram to enter self-refresh mode */
sw zero, 0x0078(k1) /* get ready to sleep */ lui t0, 0x0100
2: lw t1, 0x0850(a0) /* mem_sdstat */
and t2, t1, t0
beq t2, zero, 2b
nop
/* 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 sync
sw zero, 0x007c(k1) /* Put processor to sleep */ #endif
/* put power supply and processor to sleep */
sw zero, 0x0078(t3) /* sys_slppwr */
sync sync
sw zero, 0x007c(t3) /* sys_sleep */
sync
nop
nop
nop
nop
nop
nop
nop
nop
/* This is where we return upon wakeup. /* This is where we return upon wakeup.
* Reload all of the registers and return. * Reload all of the registers and return.
*/ */
1: nop 3: lw k0, 0x20(sp)
lw k0, 0x20(sp)
mtc0 k0, CP0_STATUS mtc0 k0, CP0_STATUS
lw k0, 0x1c(sp) lw k0, 0x1c(sp)
mtc0 k0, CP0_CONTEXT mtc0 k0, CP0_CONTEXT
@ -113,10 +142,11 @@ sdsleep:
lw k0, 0x14(sp) lw k0, 0x14(sp)
mtc0 k0, CP0_CONFIG 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... * the write-only Config[OD] bit and set it back to one...
*/ */
jal au1x00_fixup_config_od jal au1x00_fixup_config_od
nop
lw $1, PT_R1(sp) lw $1, PT_R1(sp)
lw $2, PT_R2(sp) lw $2, PT_R2(sp)
lw $3, PT_R3(sp) lw $3, PT_R3(sp)
@ -124,14 +154,6 @@ sdsleep:
lw $5, PT_R5(sp) lw $5, PT_R5(sp)
lw $6, PT_R6(sp) lw $6, PT_R6(sp)
lw $7, PT_R7(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 $16, PT_R16(sp)
lw $17, PT_R17(sp) lw $17, PT_R17(sp)
lw $18, PT_R18(sp) lw $18, PT_R18(sp)
@ -140,15 +162,11 @@ sdsleep:
lw $21, PT_R21(sp) lw $21, PT_R21(sp)
lw $22, PT_R22(sp) lw $22, PT_R22(sp)
lw $23, PT_R23(sp) lw $23, PT_R23(sp)
lw $24, PT_R24(sp)
lw $25, PT_R25(sp)
lw $26, PT_R26(sp) lw $26, PT_R26(sp)
lw $27, PT_R27(sp) lw $27, PT_R27(sp)
lw $28, PT_R28(sp) lw $28, PT_R28(sp)
lw $29, PT_R29(sp)
lw $30, PT_R30(sp) lw $30, PT_R30(sp)
lw $31, PT_R31(sp) lw $31, PT_R31(sp)
addiu sp, PT_SIZE
jr ra jr ra
END(save_and_sleep) addiu sp, PT_SIZE
END(au1xxx_save_and_sleep)

View File

@ -1,5 +1,7 @@
/* /*
* Copyright (C) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
* *
* Previous incarnations were:
* Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com> * Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com>
* Copied and modified Carsten Langgaard's time.c * Copied and modified Carsten Langgaard's time.c
* *
@ -23,244 +25,141 @@
* *
* ######################################################################## * ########################################################################
* *
* Setting up the clock on the MIPS boards. * Clocksource/event using the 32.768kHz-clocked Counter1 ('RTC' in the
* * databooks). Firmware/Board init code must enable the counters in the
* We provide the clock interrupt processing and the timer offset compute * counter control register, otherwise the CP0 counter clocksource/event
* functions. If CONFIG_PM is selected, we also ensure the 32KHz timer is * will be installed instead (and use of 'wait' instruction is prohibited).
* available. -- Dan
*/ */
#include <linux/types.h> #include <linux/clockchips.h>
#include <linux/init.h> #include <linux/clocksource.h>
#include <linux/interrupt.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <asm/mipsregs.h>
#include <asm/time.h> #include <asm/time.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
static int no_au1xxx_32khz; /* 32kHz clock enabled and detected */
#define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
extern int allow_au1k_wait; /* default off for CP0 Counter */ extern int allow_au1k_wait; /* default off for CP0 Counter */
#ifdef CONFIG_PM static cycle_t au1x_counter1_read(void)
#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
static DEFINE_SPINLOCK(time_lock);
unsigned long wtimer;
#ifdef CONFIG_PM
static irqreturn_t counter0_irq(int irq, void *dev_id)
{ {
unsigned long pc0; return au_readl(SYS_RTCREAD);
int time_elapsed; }
static int jiffie_drift;
if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) { static struct clocksource au1x_counter1_clocksource = {
/* should never happen! */ .name = "alchemy-counter1",
printk(KERN_WARNING "counter 0 w status error\n"); .read = au1x_counter1_read,
return IRQ_NONE; .mask = CLOCKSOURCE_MASK(32),
} .flags = CLOCK_SOURCE_IS_CONTINUOUS,
.rating = 100,
};
pc0 = au_readl(SYS_TOYREAD); static int au1x_rtcmatch2_set_next_event(unsigned long delta,
if (pc0 < last_match20) struct clock_event_device *cd)
/* counter overflowed */ {
time_elapsed = (0xffffffff - last_match20) + pc0; delta += au_readl(SYS_RTCREAD);
else /* wait for register access */
time_elapsed = pc0 - last_match20; while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
;
while (time_elapsed > 0) { au_writel(delta, SYS_RTCMATCH2);
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(); au_sync();
/* return 0;
* Our counter ticks at 10.009765625 ms/tick, we we're running }
* almost 10 uS too slow per tick.
*/
if (jiffie_drift >= 999) { static void au1x_rtcmatch2_set_mode(enum clock_event_mode mode,
jiffie_drift -= 999; struct clock_event_device *cd)
do_timer(1); /* increment jiffies by one */ {
#ifndef CONFIG_SMP }
update_process_times(user_mode(get_irq_regs()));
#endif
}
static irqreturn_t au1x_rtcmatch2_irq(int irq, void *dev_id)
{
struct clock_event_device *cd = dev_id;
cd->event_handler(cd);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
struct irqaction counter0_action = { static struct clock_event_device au1x_rtcmatch2_clockdev = {
.handler = counter0_irq, .name = "rtcmatch2",
.flags = IRQF_DISABLED, .features = CLOCK_EVT_FEAT_ONESHOT,
.name = "alchemy-toy", .rating = 100,
.dev_id = NULL, .irq = AU1000_RTC_MATCH2_INT,
.set_next_event = au1x_rtcmatch2_set_next_event,
.set_mode = au1x_rtcmatch2_set_mode,
.cpumask = CPU_MASK_ALL,
}; };
/* When we wakeup from sleep, we have to "catch up" on all of the static struct irqaction au1x_rtcmatch2_irqaction = {
* timer ticks we have missed. .handler = au1x_rtcmatch2_irq,
*/ .flags = IRQF_DISABLED | IRQF_TIMER,
void wakeup_counter0_adjust(void) .name = "timer",
{ .dev_id = &au1x_rtcmatch2_clockdev,
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);
au_sync();
}
/* This is just for debugging to set the timer for a sleep delay. */
void wakeup_counter0_set(int ticks)
{
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)
{
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);
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;
/*
* 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;
}
void __init plat_time_init(void) void __init plat_time_init(void)
{ {
unsigned int est_freq = calc_clock(); struct clock_event_device *cd = &au1x_rtcmatch2_clockdev;
unsigned long t;
est_freq += 5000; /* round */ /* Check if firmware (YAMON, ...) has enabled 32kHz and clock
est_freq -= est_freq%10000; * has been detected. If so install the rtcmatch2 clocksource,
printk(KERN_INFO "CPU frequency %u.%02u MHz\n", * otherwise don't bother. Note that both bits being set is by
est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000); * no means a definite guarantee that the counters actually work
set_au1x00_speed(est_freq); * (the 32S bit seems to be stuck set to 1 once a single clock-
set_au1x00_lcd_clock(); /* program the LCD clock */ * edge is detected, hence the timeouts).
#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.
*/ */
if (no_au1xxx_32khz) if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
printk(KERN_WARNING "WARNING: no 32KHz clock found.\n"); goto cntr_err;
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); * setup counter 1 (RTC) to tick at full speed
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 */ au_writel(0, SYS_RTCTRIM); /* 32.768 kHz */
last_pc0 = last_match20 = au_readl(SYS_TOYREAD); au_sync();
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);
/* We can use the real 'wait' instruction. */ t = 0xffffff;
allow_au1k_wait = 1; 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;
} }

View File

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

View File

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

View File

@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor DBAu1xx0 boards. # Makefile for the Alchemy Semiconductor DBAu1xx0 boards.
# #
lib-y := init.o board_setup.o irqmap.o obj-y := board_setup.o irqmap.o

View File

@ -32,8 +32,20 @@
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <asm/mach-db1x00/db1x00.h> #include <asm/mach-db1x00/db1x00.h>
#include <prom.h>
static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR; 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) void board_reset(void)
{ {
/* Hit BCSR.SW_RESET[RESET] */ /* Hit BCSR.SW_RESET[RESET] */
@ -43,6 +55,31 @@ void board_reset(void)
void __init board_setup(void) void __init board_setup(void)
{ {
u32 pin_func = 0; 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 */ /* Not valid for Au1550 */
#if defined(CONFIG_IRDA) && \ #if defined(CONFIG_IRDA) && \

View File

@ -27,6 +27,7 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
@ -66,21 +67,24 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
#ifndef CONFIG_MIPS_MIRAGE #ifndef CONFIG_MIPS_MIRAGE
#ifdef CONFIG_MIPS_DB1550 #ifdef CONFIG_MIPS_DB1550
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
#else #else
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */ { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 Fully_Interted# */
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */ { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 STSCHG# */
{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */ { 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_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 Fully_Interted# */
{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */ { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 STSCHG# */
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */ { AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
#endif #endif
#else #else
{ AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */ { AU1000_GPIO_7, IRQF_TRIGGER_RISING, 0 }, /* touchscreen pen down */
#endif #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));
}

View File

@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1000 board. # Makefile for the Alchemy Semiconductor Pb1000 board.
# #
lib-y := init.o board_setup.o irqmap.o obj-y := board_setup.o

View File

@ -23,22 +23,48 @@
* 675 Mass Ave, Cambridge, MA 02139, USA. * 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1000.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 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) void __init board_setup(void)
{ {
u32 pin_func, static_cfg0; u32 pin_func, static_cfg0;
u32 sys_freqctrl, sys_clksrc; u32 sys_freqctrl, sys_clksrc;
u32 prid = read_c0_prid(); 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 */ /* Set AUX clock to 12 MHz * 8 = 96 MHz */
au_writel(8, SYS_AUXPLL); au_writel(8, SYS_AUXPLL);
au_writel(0, SYS_PINSTATERD); au_writel(0, SYS_PINSTATERD);

View File

@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1100 board. # Makefile for the Alchemy Semiconductor Pb1100 board.
# #
lib-y := init.o board_setup.o irqmap.o obj-y := board_setup.o

View File

@ -25,19 +25,66 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1100.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) void board_reset(void)
{ {
/* Hit BCSR.RST_VDDI[SOFT_RESET] */ /* Hit BCSR.RST_VDDI[SOFT_RESET] */
au_writel(0x00000000, PB1100_RST_VDDI); 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) void __init board_setup(void)
{ {
volatile void __iomem *base = (volatile void __iomem *)0xac000000UL; 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 */ /* Set AUX clock to 12 MHz * 8 = 96 MHz */
au_writel(8, SYS_AUXPLL); au_writel(8, SYS_AUXPLL);

View File

@ -2,7 +2,6 @@
# Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards. # Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards.
# #
lib-y := init.o board_setup.o irqmap.o obj-y := board_setup.o irqmap.o platform.o
obj-y += platform.o
EXTRA_CFLAGS += -Werror EXTRA_CFLAGS += -Werror

View File

@ -30,8 +30,11 @@
#include <prom.h> #include <prom.h>
#include <au1xxx.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) void board_reset(void)
{ {
@ -41,7 +44,19 @@ void board_reset(void)
void __init board_setup(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 #if 0
{ {
@ -99,16 +114,6 @@ void __init board_setup(void)
} }
#endif #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 * The Pb1200 development board uses external MUX for PSC0 to
* support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI * support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
@ -124,9 +129,6 @@ void __init board_setup(void)
#ifdef CONFIG_MIPS_DB1200 #ifdef CONFIG_MIPS_DB1200
printk(KERN_INFO "AMD Alchemy Db1200 Board\n"); printk(KERN_INFO "AMD Alchemy Db1200 Board\n");
#endif #endif
/* Setup Pb1200 External Interrupt Controller */
board_init_irq = _board_init_irq;
} }
int board_au1200fb_panel(void) int board_au1200fb_panel(void)

View File

@ -40,91 +40,65 @@
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
/* This is external interrupt cascade */ /* 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. * 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; unsigned short bisr = bcsr->int_status;
int extirq_nr = 0;
/* Clear all the edge interrupts. This has no effect on level. */ for ( ; bisr; bisr &= bisr - 1)
bcsr->int_status = bisr; generic_handle_irq(PB1200_INT_BEGIN + __ffs(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) /* NOTE: both the enable and mask bits must be cleared, otherwise the
{ * CPLD generates tons of spurious interrupts (at least on the DB1200).
bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN); */
bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN); static void pb1200_mask_irq(unsigned int irq_nr)
}
inline void pb1200_disable_irq(unsigned int irq_nr)
{ {
bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN); bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN); bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
au_sync();
} }
static unsigned int pb1200_setup_cascade(void) static void pb1200_maskack_irq(unsigned int irq_nr)
{ {
return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler, bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
0, "Pb1200 Cascade", &pb1200_cascade_handler); bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
bcsr->int_status = 1 << (irq_nr - PB1200_INT_BEGIN); /* ack */
au_sync();
} }
static unsigned int pb1200_startup_irq(unsigned int irq) static void pb1200_unmask_irq(unsigned int irq_nr)
{ {
if (++pb1200_cascade_en == 1) { bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
int res; bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
au_sync();
res = pb1200_setup_cascade();
if (res)
return res;
}
pb1200_enable_irq(irq);
return 0;
} }
static void pb1200_shutdown_irq(unsigned int irq) static struct irq_chip pb1200_cpld_irq_type = {
{
pb1200_disable_irq(irq);
if (--pb1200_cascade_en == 0)
free_irq(AU1000_GPIO_7, &pb1200_cascade_handler);
}
static struct irq_chip external_irq_type = {
#ifdef CONFIG_MIPS_PB1200 #ifdef CONFIG_MIPS_PB1200
.name = "Pb1200 Ext", .name = "Pb1200 Ext",
#endif #endif
#ifdef CONFIG_MIPS_DB1200 #ifdef CONFIG_MIPS_DB1200
.name = "Db1200 Ext", .name = "Db1200 Ext",
#endif #endif
.startup = pb1200_startup_irq, .mask = pb1200_mask_irq,
.shutdown = pb1200_shutdown_irq, .mask_ack = pb1200_maskack_irq,
.ack = pb1200_disable_irq, .unmask = pb1200_unmask_irq,
.mask = pb1200_disable_irq,
.mask_ack = pb1200_disable_irq,
.unmask = pb1200_enable_irq,
}; };
void _board_init_irq(void) void __init board_init_irq(void)
{ {
unsigned int irq; unsigned int irq;
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
#ifdef CONFIG_MIPS_PB1200 #ifdef CONFIG_MIPS_PB1200
/* We have a problem with CPLD rev 3. */ /* We have a problem with CPLD rev 3. */
if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 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."); panic("Game over. Your score is 0.");
} }
#endif #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++) { for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++)
set_irq_chip_and_handler(irq, &external_irq_type, set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type,
handle_level_irq); handle_level_irq, "level");
pb1200_disable_irq(irq);
}
/* set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler);
* GPIO_7 can not be hooked here, so it is hooked upon first
* request of any source attached to the cascade.
*/
} }

View File

@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1500 board. # Makefile for the Alchemy Semiconductor Pb1500 board.
# #
lib-y := init.o board_setup.o irqmap.o obj-y := board_setup.o

View File

@ -25,20 +25,64 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1500.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) void board_reset(void)
{ {
/* Hit BCSR.RST_VDDI[SOFT_RESET] */ /* Hit BCSR.RST_VDDI[SOFT_RESET] */
au_writel(0x00000000, PB1500_RST_VDDI); 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) void __init board_setup(void)
{ {
u32 pin_func; u32 pin_func;
u32 sys_freqctrl, sys_clksrc; 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; sys_clksrc = sys_freqctrl = pin_func = 0;
/* Set AUX clock to 12 MHz * 8 = 96 MHz */ /* Set AUX clock to 12 MHz * 8 = 96 MHz */

View File

@ -5,4 +5,4 @@
# Makefile for the Alchemy Semiconductor Pb1550 board. # Makefile for the Alchemy Semiconductor Pb1550 board.
# #
lib-y := init.o board_setup.o irqmap.o obj-y := board_setup.o

View File

@ -28,20 +28,54 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <asm/mach-pb1x00/pb1550.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) void board_reset(void)
{ {
/* Hit BCSR.SYSTEM[RESET] */ /* Hit BCSR.SYSTEM[RESET] */
au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C); 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) void __init board_setup(void)
{ {
u32 pin_func; 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, * Enable PSC1 SYNC for AC'97. Normaly done in audio driver,
* but it is board specific code, so put it here. * but it is board specific code, so put it here.

View File

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

View File

@ -1,9 +1,9 @@
/* /*
* Common code used by all Alchemy develboards.
* *
* BRIEF MODULE DESCRIPTION * Extracted from files which had this to say:
* Pb1550 board setup
* *
* Copyright 2001, 2008 MontaVista Software Inc. * Copyright 2000, 2008 MontaVista Software Inc.
* Author: MontaVista Software, Inc. <source@mvista.com> * Author: MontaVista Software, Inc. <source@mvista.com>
* *
* This program is free software; you can redistribute it and/or modify it * This program is free software; you can redistribute it and/or modify it
@ -29,15 +29,19 @@
#include <linux/init.h> #include <linux/init.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <asm/bootinfo.h> #include <asm/bootinfo.h>
#include <asm/mach-au1x00/au1000.h>
#include <prom.h> #include <prom.h>
const char *get_system_type(void) #if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_DB1000) || \
{ defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || \
return "Alchemy Pb1550"; 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) void __init prom_init(void)
{ {
@ -51,8 +55,8 @@ void __init prom_init(void)
prom_init_cmdline(); prom_init_cmdline();
memsize_str = prom_getenv("memsize"); memsize_str = prom_getenv("memsize");
if (!memsize_str) if (!memsize_str)
memsize = 0x08000000; memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
else else
strict_strtol(memsize_str, 0, &memsize); strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM); add_memory_region(0, memsize, BOOT_MEM_RAM);
} }

View File

@ -32,6 +32,8 @@
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <prom.h>
extern int (*board_pci_idsel)(unsigned int devsel, int assert); extern int (*board_pci_idsel)(unsigned int devsel, int assert);
int mtx1_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) 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) #if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
/* Enable USB power switch */ /* Enable USB power switch */
au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR); au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR);

View File

@ -55,6 +55,6 @@ void __init prom_init(void)
if (!memsize_str) if (!memsize_str)
memsize = 0x04000000; memsize = 0x04000000;
else else
strict_strtol(memsize_str, 0, &memsize); strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM); add_memory_region(0, memsize, BOOT_MEM_RAM);
} }

View File

@ -27,7 +27,7 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
char irq_tab_alchemy[][5] __initdata = { char irq_tab_alchemy[][5] __initdata = {
@ -42,11 +42,15 @@ char irq_tab_alchemy[][5] __initdata = {
}; };
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 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));
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -28,6 +28,8 @@
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
#include <prom.h>
void board_reset(void) void board_reset(void)
{ {
/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */ /* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
@ -38,6 +40,16 @@ void __init board_setup(void)
{ {
u32 pin_func; 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) */ /* 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 = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
pin_func |= SYS_PF_UR3; pin_func |= SYS_PF_UR3;

View File

@ -53,6 +53,6 @@ void __init prom_init(void)
if (!memsize_str) if (!memsize_str)
memsize = 0x04000000; memsize = 0x04000000;
else else
strict_strtol(memsize_str, 0, &memsize); strict_strtoul(memsize_str, 0, &memsize);
add_memory_region(0, memsize, BOOT_MEM_RAM); add_memory_region(0, memsize, BOOT_MEM_RAM);
} }

View File

@ -27,23 +27,26 @@
*/ */
#include <linux/init.h> #include <linux/init.h>
#include <linux/interrupt.h>
#include <asm/mach-au1x00/au1000.h> #include <asm/mach-au1x00/au1000.h>
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = { struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 }, { AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 }, { AU1500_GPIO_207, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, { AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, { AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, { AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, { AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 },
{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */ { AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* CF interrupt */
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, { 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));
}

View File

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

View File

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

Some files were not shown because too many files have changed in this diff Show More