mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 03:36:19 +00:00
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:
commit
af37501c79
524 changed files with 29494 additions and 5766 deletions
|
@ -18,11 +18,11 @@ For an architecture to support this feature, it must define some of
|
|||
these macros in include/asm-XXX/topology.h:
|
||||
#define topology_physical_package_id(cpu)
|
||||
#define topology_core_id(cpu)
|
||||
#define topology_thread_siblings(cpu)
|
||||
#define topology_core_siblings(cpu)
|
||||
#define topology_thread_cpumask(cpu)
|
||||
#define topology_core_cpumask(cpu)
|
||||
|
||||
The type of **_id is int.
|
||||
The type of siblings is cpumask_t.
|
||||
The type of siblings is (const) struct cpumask *.
|
||||
|
||||
To be consistent on all architectures, include/linux/topology.h
|
||||
provides default definitions for any of the above macros that are
|
||||
|
|
|
@ -55,7 +55,7 @@ int irq_select_affinity(unsigned int irq)
|
|||
cpu = (cpu < (NR_CPUS-1) ? cpu + 1 : 0);
|
||||
last_cpu = cpu;
|
||||
|
||||
irq_desc[irq].affinity = cpumask_of_cpu(cpu);
|
||||
cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
|
||||
irq_desc[irq].chip->set_affinity(irq, cpumask_of(cpu));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -104,6 +104,11 @@ static struct irq_desc bad_irq_desc = {
|
|||
.lock = SPIN_LOCK_UNLOCKED
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CPUMASK_OFFSTACK
|
||||
/* We are not allocating bad_irq_desc.affinity or .pending_mask */
|
||||
#error "ARM architecture does not support CONFIG_CPUMASK_OFFSTACK."
|
||||
#endif
|
||||
|
||||
/*
|
||||
* do_IRQ handles all hardware IRQ's. Decoded IRQs should not
|
||||
* come via this function. Instead, they should provide their
|
||||
|
@ -161,7 +166,7 @@ void __init init_IRQ(void)
|
|||
irq_desc[irq].status |= IRQ_NOREQUEST | IRQ_NOPROBE;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
bad_irq_desc.affinity = CPU_MASK_ALL;
|
||||
cpumask_setall(bad_irq_desc.affinity);
|
||||
bad_irq_desc.cpu = smp_processor_id();
|
||||
#endif
|
||||
init_arch_irq();
|
||||
|
@ -191,15 +196,16 @@ void migrate_irqs(void)
|
|||
struct irq_desc *desc = irq_desc + i;
|
||||
|
||||
if (desc->cpu == cpu) {
|
||||
unsigned int newcpu = any_online_cpu(desc->affinity);
|
||||
|
||||
if (newcpu == NR_CPUS) {
|
||||
unsigned int newcpu = cpumask_any_and(desc->affinity,
|
||||
cpu_online_mask);
|
||||
if (newcpu >= nr_cpu_ids) {
|
||||
if (printk_ratelimit())
|
||||
printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",
|
||||
i, cpu);
|
||||
|
||||
cpus_setall(desc->affinity);
|
||||
newcpu = any_online_cpu(desc->affinity);
|
||||
cpumask_setall(desc->affinity);
|
||||
newcpu = cpumask_any_and(desc->affinity,
|
||||
cpu_online_mask);
|
||||
}
|
||||
|
||||
route_irq(desc, i, newcpu);
|
||||
|
|
|
@ -65,6 +65,7 @@ SECTIONS
|
|||
#endif
|
||||
. = ALIGN(4096);
|
||||
__per_cpu_start = .;
|
||||
*(.data.percpu.page_aligned)
|
||||
*(.data.percpu)
|
||||
*(.data.percpu.shared_aligned)
|
||||
__per_cpu_end = .;
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
#include <linux/err.h>
|
||||
#include <linux/io.h>
|
||||
|
||||
#include <mach/imx-regs.h>
|
||||
#include <mach/hardware.h>
|
||||
|
||||
/*
|
||||
* Very simple approach: We can't disable clocks, so we do
|
||||
|
|
|
@ -245,11 +245,11 @@ void __init imx_set_mmc_info(struct imxmmc_platform_data *info)
|
|||
imx_mmc_device.dev.platform_data = info;
|
||||
}
|
||||
|
||||
static struct imxfb_mach_info imx_fb_info;
|
||||
static struct imx_fb_platform_data imx_fb_info;
|
||||
|
||||
void __init set_imx_fb_info(struct imxfb_mach_info *hard_imx_fb_info)
|
||||
void __init set_imx_fb_info(struct imx_fb_platform_data *hard_imx_fb_info)
|
||||
{
|
||||
memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imxfb_mach_info));
|
||||
memcpy(&imx_fb_info,hard_imx_fb_info,sizeof(struct imx_fb_platform_data));
|
||||
}
|
||||
|
||||
static struct resource imxfb_resources[] = {
|
||||
|
|
|
@ -373,110 +373,4 @@
|
|||
#define TSTAT_CAPT (1<<1)
|
||||
#define TSTAT_COMP (1<<0)
|
||||
|
||||
/*
|
||||
* LCD Controller
|
||||
*/
|
||||
|
||||
#define LCDC_SSA __REG(IMX_LCDC_BASE+0x00)
|
||||
|
||||
#define LCDC_SIZE __REG(IMX_LCDC_BASE+0x04)
|
||||
#define SIZE_XMAX(x) ((((x) >> 4) & 0x3f) << 20)
|
||||
#define SIZE_YMAX(y) ( (y) & 0x1ff )
|
||||
|
||||
#define LCDC_VPW __REG(IMX_LCDC_BASE+0x08)
|
||||
#define VPW_VPW(x) ( (x) & 0x3ff )
|
||||
|
||||
#define LCDC_CPOS __REG(IMX_LCDC_BASE+0x0C)
|
||||
#define CPOS_CC1 (1<<31)
|
||||
#define CPOS_CC0 (1<<30)
|
||||
#define CPOS_OP (1<<28)
|
||||
#define CPOS_CXP(x) (((x) & 3ff) << 16)
|
||||
#define CPOS_CYP(y) ((y) & 0x1ff)
|
||||
|
||||
#define LCDC_LCWHB __REG(IMX_LCDC_BASE+0x10)
|
||||
#define LCWHB_BK_EN (1<<31)
|
||||
#define LCWHB_CW(w) (((w) & 0x1f) << 24)
|
||||
#define LCWHB_CH(h) (((h) & 0x1f) << 16)
|
||||
#define LCWHB_BD(x) ((x) & 0xff)
|
||||
|
||||
#define LCDC_LCHCC __REG(IMX_LCDC_BASE+0x14)
|
||||
#define LCHCC_CUR_COL_R(r) (((r) & 0x1f) << 11)
|
||||
#define LCHCC_CUR_COL_G(g) (((g) & 0x3f) << 5)
|
||||
#define LCHCC_CUR_COL_B(b) ((b) & 0x1f)
|
||||
|
||||
#define LCDC_PCR __REG(IMX_LCDC_BASE+0x18)
|
||||
#define PCR_TFT (1<<31)
|
||||
#define PCR_COLOR (1<<30)
|
||||
#define PCR_PBSIZ_1 (0<<28)
|
||||
#define PCR_PBSIZ_2 (1<<28)
|
||||
#define PCR_PBSIZ_4 (2<<28)
|
||||
#define PCR_PBSIZ_8 (3<<28)
|
||||
#define PCR_BPIX_1 (0<<25)
|
||||
#define PCR_BPIX_2 (1<<25)
|
||||
#define PCR_BPIX_4 (2<<25)
|
||||
#define PCR_BPIX_8 (3<<25)
|
||||
#define PCR_BPIX_12 (4<<25)
|
||||
#define PCR_BPIX_16 (4<<25)
|
||||
#define PCR_PIXPOL (1<<24)
|
||||
#define PCR_FLMPOL (1<<23)
|
||||
#define PCR_LPPOL (1<<22)
|
||||
#define PCR_CLKPOL (1<<21)
|
||||
#define PCR_OEPOL (1<<20)
|
||||
#define PCR_SCLKIDLE (1<<19)
|
||||
#define PCR_END_SEL (1<<18)
|
||||
#define PCR_END_BYTE_SWAP (1<<17)
|
||||
#define PCR_REV_VS (1<<16)
|
||||
#define PCR_ACD_SEL (1<<15)
|
||||
#define PCR_ACD(x) (((x) & 0x7f) << 8)
|
||||
#define PCR_SCLK_SEL (1<<7)
|
||||
#define PCR_SHARP (1<<6)
|
||||
#define PCR_PCD(x) ((x) & 0x3f)
|
||||
|
||||
#define LCDC_HCR __REG(IMX_LCDC_BASE+0x1C)
|
||||
#define HCR_H_WIDTH(x) (((x) & 0x3f) << 26)
|
||||
#define HCR_H_WAIT_1(x) (((x) & 0xff) << 8)
|
||||
#define HCR_H_WAIT_2(x) ((x) & 0xff)
|
||||
|
||||
#define LCDC_VCR __REG(IMX_LCDC_BASE+0x20)
|
||||
#define VCR_V_WIDTH(x) (((x) & 0x3f) << 26)
|
||||
#define VCR_V_WAIT_1(x) (((x) & 0xff) << 8)
|
||||
#define VCR_V_WAIT_2(x) ((x) & 0xff)
|
||||
|
||||
#define LCDC_POS __REG(IMX_LCDC_BASE+0x24)
|
||||
#define POS_POS(x) ((x) & 1f)
|
||||
|
||||
#define LCDC_LSCR1 __REG(IMX_LCDC_BASE+0x28)
|
||||
#define LSCR1_PS_RISE_DELAY(x) (((x) & 0x7f) << 26)
|
||||
#define LSCR1_CLS_RISE_DELAY(x) (((x) & 0x3f) << 16)
|
||||
#define LSCR1_REV_TOGGLE_DELAY(x) (((x) & 0xf) << 8)
|
||||
#define LSCR1_GRAY2(x) (((x) & 0xf) << 4)
|
||||
#define LSCR1_GRAY1(x) (((x) & 0xf))
|
||||
|
||||
#define LCDC_PWMR __REG(IMX_LCDC_BASE+0x2C)
|
||||
#define PWMR_CLS(x) (((x) & 0x1ff) << 16)
|
||||
#define PWMR_LDMSK (1<<15)
|
||||
#define PWMR_SCR1 (1<<10)
|
||||
#define PWMR_SCR0 (1<<9)
|
||||
#define PWMR_CC_EN (1<<8)
|
||||
#define PWMR_PW(x) ((x) & 0xff)
|
||||
|
||||
#define LCDC_DMACR __REG(IMX_LCDC_BASE+0x30)
|
||||
#define DMACR_BURST (1<<31)
|
||||
#define DMACR_HM(x) (((x) & 0xf) << 16)
|
||||
#define DMACR_TM(x) ((x) &0xf)
|
||||
|
||||
#define LCDC_RMCR __REG(IMX_LCDC_BASE+0x34)
|
||||
#define RMCR_LCDC_EN (1<<1)
|
||||
#define RMCR_SELF_REF (1<<0)
|
||||
|
||||
#define LCDC_LCDICR __REG(IMX_LCDC_BASE+0x38)
|
||||
#define LCDICR_INT_SYN (1<<2)
|
||||
#define LCDICR_INT_CON (1)
|
||||
|
||||
#define LCDC_LCDISR __REG(IMX_LCDC_BASE+0x40)
|
||||
#define LCDISR_UDR_ERR (1<<3)
|
||||
#define LCDISR_ERR_RES (1<<2)
|
||||
#define LCDISR_EOF (1<<1)
|
||||
#define LCDISR_BOF (1<<0)
|
||||
|
||||
#endif // _IMX_REGS_H
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <asm/mach-types.h>
|
||||
|
||||
#include <mach/regs-serial.h>
|
||||
#include <mach/map.h>
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <asm/mach/irq.h>
|
||||
#include <asm/mach/time.h>
|
||||
|
||||
#include <mach/system.h>
|
||||
#include <mach/map.h>
|
||||
#include <mach/regs-timer.h>
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ EXPORT_SYMBOL(__cpuc_flush_kern_all);
|
|||
EXPORT_SYMBOL(__cpuc_flush_user_all);
|
||||
EXPORT_SYMBOL(__cpuc_flush_user_range);
|
||||
EXPORT_SYMBOL(__cpuc_coherent_kern_range);
|
||||
EXPORT_SYMBOL(dmac_inv_range); /* because of flush_ioremap_region() */
|
||||
#else
|
||||
EXPORT_SYMBOL(cpu_cache);
|
||||
#endif
|
||||
|
|
|
@ -263,7 +263,7 @@ static void em_route_irq(int irq, unsigned int cpu)
|
|||
const struct cpumask *mask = cpumask_of(cpu);
|
||||
|
||||
spin_lock_irq(&desc->lock);
|
||||
desc->affinity = *mask;
|
||||
cpumask_copy(desc->affinity, mask);
|
||||
desc->chip->set_affinity(irq, mask);
|
||||
spin_unlock_irq(&desc->lock);
|
||||
}
|
||||
|
|
|
@ -69,6 +69,11 @@ static struct irq_desc bad_irq_desc = {
|
|||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_CPUMASK_OFFSTACK
|
||||
/* We are not allocating a variable-sized bad_irq_desc.affinity */
|
||||
#error "Blackfin architecture does not support CONFIG_CPUMASK_OFFSTACK."
|
||||
#endif
|
||||
|
||||
int show_interrupts(struct seq_file *p, void *v)
|
||||
{
|
||||
int i = *(loff_t *) v, j;
|
||||
|
|
|
@ -880,7 +880,7 @@ iosapic_unregister_intr (unsigned int gsi)
|
|||
if (iosapic_intr_info[irq].count == 0) {
|
||||
#ifdef CONFIG_SMP
|
||||
/* Clear affinity */
|
||||
cpus_setall(idesc->affinity);
|
||||
cpumask_setall(idesc->affinity);
|
||||
#endif
|
||||
/* Clear the interrupt information */
|
||||
iosapic_intr_info[irq].dest = 0;
|
||||
|
|
|
@ -103,7 +103,7 @@ static char irq_redir [NR_IRQS]; // = { [0 ... NR_IRQS-1] = 1 };
|
|||
void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
|
||||
{
|
||||
if (irq < NR_IRQS) {
|
||||
cpumask_copy(&irq_desc[irq].affinity,
|
||||
cpumask_copy(irq_desc[irq].affinity,
|
||||
cpumask_of(cpu_logical_id(hwid)));
|
||||
irq_redir[irq] = (char) (redir & 0xff);
|
||||
}
|
||||
|
@ -148,7 +148,7 @@ static void migrate_irqs(void)
|
|||
if (desc->status == IRQ_PER_CPU)
|
||||
continue;
|
||||
|
||||
if (cpumask_any_and(&irq_desc[irq].affinity, cpu_online_mask)
|
||||
if (cpumask_any_and(irq_desc[irq].affinity, cpu_online_mask)
|
||||
>= nr_cpu_ids) {
|
||||
/*
|
||||
* Save it for phase 2 processing
|
||||
|
|
|
@ -493,11 +493,13 @@ ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
|
|||
saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
|
||||
ia64_srlz_d();
|
||||
while (vector != IA64_SPURIOUS_INT_VECTOR) {
|
||||
struct irq_desc *desc = irq_to_desc(vector);
|
||||
|
||||
if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
|
||||
smp_local_flush_tlb();
|
||||
kstat_this_cpu.irqs[vector]++;
|
||||
kstat_incr_irqs_this_cpu(vector, desc);
|
||||
} else if (unlikely(IS_RESCHEDULE(vector)))
|
||||
kstat_this_cpu.irqs[vector]++;
|
||||
kstat_incr_irqs_this_cpu(vector, desc);
|
||||
else {
|
||||
int irq = local_vector_to_irq(vector);
|
||||
|
||||
|
@ -551,11 +553,13 @@ void ia64_process_pending_intr(void)
|
|||
* Perform normal interrupt style processing
|
||||
*/
|
||||
while (vector != IA64_SPURIOUS_INT_VECTOR) {
|
||||
struct irq_desc *desc = irq_to_desc(vector);
|
||||
|
||||
if (unlikely(IS_LOCAL_TLB_FLUSH(vector))) {
|
||||
smp_local_flush_tlb();
|
||||
kstat_this_cpu.irqs[vector]++;
|
||||
kstat_incr_irqs_this_cpu(vector, desc);
|
||||
} else if (unlikely(IS_RESCHEDULE(vector)))
|
||||
kstat_this_cpu.irqs[vector]++;
|
||||
kstat_incr_irqs_this_cpu(vector, desc);
|
||||
else {
|
||||
struct pt_regs *old_regs = set_irq_regs(NULL);
|
||||
int irq = local_vector_to_irq(vector);
|
||||
|
|
|
@ -75,7 +75,7 @@ static void ia64_set_msi_irq_affinity(unsigned int irq,
|
|||
msg.data = data;
|
||||
|
||||
write_msi_msg(irq, &msg);
|
||||
irq_desc[irq].affinity = cpumask_of_cpu(cpu);
|
||||
cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
@ -187,7 +187,7 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
|||
msg.address_lo |= MSI_ADDR_DESTID_CPU(cpu_physical_id(cpu));
|
||||
|
||||
dmar_msi_write(irq, &msg);
|
||||
irq_desc[irq].affinity = *mask;
|
||||
cpumask_copy(irq_desc[irq].affinity, mask);
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
|
|
@ -219,6 +219,7 @@ SECTIONS
|
|||
.data.percpu PERCPU_ADDR : AT(__phys_per_cpu_start - LOAD_OFFSET)
|
||||
{
|
||||
__per_cpu_start = .;
|
||||
*(.data.percpu.page_aligned)
|
||||
*(.data.percpu)
|
||||
*(.data.percpu.shared_aligned)
|
||||
__per_cpu_end = .;
|
||||
|
|
|
@ -205,7 +205,7 @@ static void sn_set_msi_irq_affinity(unsigned int irq,
|
|||
msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
|
||||
|
||||
write_msi_msg(irq, &msg);
|
||||
irq_desc[irq].affinity = *cpu_mask;
|
||||
cpumask_copy(irq_desc[irq].affinity, cpu_mask);
|
||||
}
|
||||
#endif /* CONFIG_SMP */
|
||||
|
||||
|
|
|
@ -72,10 +72,14 @@ static struct irq_controller amiga_irq_controller = {
|
|||
|
||||
void __init amiga_init_IRQ(void)
|
||||
{
|
||||
request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL);
|
||||
request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL);
|
||||
request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL);
|
||||
request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL);
|
||||
if (request_irq(IRQ_AUTO_1, ami_int1, 0, "int1", NULL))
|
||||
pr_err("Couldn't register int%d\n", 1);
|
||||
if (request_irq(IRQ_AUTO_3, ami_int3, 0, "int3", NULL))
|
||||
pr_err("Couldn't register int%d\n", 3);
|
||||
if (request_irq(IRQ_AUTO_4, ami_int4, 0, "int4", NULL))
|
||||
pr_err("Couldn't register int%d\n", 4);
|
||||
if (request_irq(IRQ_AUTO_5, ami_int5, 0, "int5", NULL))
|
||||
pr_err("Couldn't register int%d\n", 5);
|
||||
|
||||
m68k_setup_irq_controller(&amiga_irq_controller, IRQ_USER, AMI_STD_IRQS);
|
||||
|
||||
|
|
|
@ -176,5 +176,7 @@ void __init cia_init_IRQ(struct ciabase *base)
|
|||
/* override auto int and install CIA handler */
|
||||
m68k_setup_irq_controller(&auto_irq_controller, base->handler_irq, 1);
|
||||
m68k_irq_startup(base->handler_irq);
|
||||
request_irq(base->handler_irq, cia_handler, IRQF_SHARED, base->name, base);
|
||||
if (request_irq(base->handler_irq, cia_handler, IRQF_SHARED,
|
||||
base->name, base))
|
||||
pr_err("Couldn't register %s interrupt\n", base->name);
|
||||
}
|
||||
|
|
|
@ -493,7 +493,8 @@ static void __init amiga_sched_init(irq_handler_t timer_routine)
|
|||
* Please don't change this to use ciaa, as it interferes with the
|
||||
* SCSI code. We'll have to take a look at this later
|
||||
*/
|
||||
request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL);
|
||||
if (request_irq(IRQ_AMIGA_CIAB_TA, timer_routine, 0, "timer", NULL))
|
||||
pr_err("Couldn't register timer interrupt\n");
|
||||
/* start timer */
|
||||
ciab.cra |= 0x11;
|
||||
}
|
||||
|
|
|
@ -31,10 +31,6 @@ extern unsigned long dn_gettimeoffset(void);
|
|||
extern int dn_dummy_hwclk(int, struct rtc_time *);
|
||||
extern int dn_dummy_set_clock_mmss(unsigned long);
|
||||
extern void dn_dummy_reset(void);
|
||||
extern void dn_dummy_waitbut(void);
|
||||
extern struct fb_info *dn_fb_init(long *);
|
||||
extern void dn_dummy_debug_init(void);
|
||||
extern irqreturn_t dn_process_int(int irq, struct pt_regs *fp);
|
||||
#ifdef CONFIG_HEARTBEAT
|
||||
static void dn_heartbeat(int on);
|
||||
#endif
|
||||
|
@ -204,7 +200,8 @@ void dn_sched_init(irq_handler_t timer_routine)
|
|||
printk("*(0x10803) %02x\n",*(volatile unsigned char *)(timer+0x3));
|
||||
#endif
|
||||
|
||||
request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine);
|
||||
if (request_irq(IRQ_APOLLO, dn_timer_int, 0, "time", timer_routine))
|
||||
pr_err("Couldn't register timer interrupt\n");
|
||||
}
|
||||
|
||||
unsigned long dn_gettimeoffset(void) {
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <asm/atari_joystick.h>
|
||||
#include <asm/irq.h>
|
||||
|
||||
extern unsigned int keymap_count;
|
||||
|
||||
/* Hook for MIDI serial driver */
|
||||
void (*atari_MIDI_interrupt_hook) (void);
|
||||
|
@ -567,14 +566,19 @@ static int atari_keyb_done = 0;
|
|||
|
||||
int atari_keyb_init(void)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (atari_keyb_done)
|
||||
return 0;
|
||||
|
||||
kb_state.state = KEYBOARD;
|
||||
kb_state.len = 0;
|
||||
|
||||
request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt, IRQ_TYPE_SLOW,
|
||||
"keyboard/mouse/MIDI", atari_keyboard_interrupt);
|
||||
error = request_irq(IRQ_MFP_ACIA, atari_keyboard_interrupt,
|
||||
IRQ_TYPE_SLOW, "keyboard/mouse/MIDI",
|
||||
atari_keyboard_interrupt);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
atari_turnoff_irq(IRQ_MFP_ACIA);
|
||||
do {
|
||||
|
|
|
@ -179,8 +179,9 @@ EXPORT_SYMBOL(stdma_islocked);
|
|||
void __init stdma_init(void)
|
||||
{
|
||||
stdma_isr = NULL;
|
||||
request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
|
||||
"ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int);
|
||||
if (request_irq(IRQ_MFP_FDC, stdma_int, IRQ_TYPE_SLOW | IRQF_SHARED,
|
||||
"ST-DMA: floppy/ACSI/IDE/Falcon-SCSI", stdma_int))
|
||||
pr_err("Couldn't register ST-DMA interrupt\n");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -31,8 +31,9 @@ atari_sched_init(irq_handler_t timer_routine)
|
|||
/* start timer C, div = 1:100 */
|
||||
mfp.tim_ct_cd = (mfp.tim_ct_cd & 15) | 0x60;
|
||||
/* install interrupt service routine for MFP Timer C */
|
||||
request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
|
||||
"timer", timer_routine);
|
||||
if (request_irq(IRQ_MFP_TIMC, timer_routine, IRQ_TYPE_SLOW,
|
||||
"timer", timer_routine))
|
||||
pr_err("Couldn't register timer interrupt\n");
|
||||
}
|
||||
|
||||
/* ++andreas: gettimeoffset fixed to check for pending interrupt */
|
||||
|
|
|
@ -43,7 +43,6 @@ extern unsigned long bvme6000_gettimeoffset (void);
|
|||
extern int bvme6000_hwclk (int, struct rtc_time *);
|
||||
extern int bvme6000_set_clock_mmss (unsigned long);
|
||||
extern void bvme6000_reset (void);
|
||||
extern void bvme6000_waitbut(void);
|
||||
void bvme6000_set_vectors (void);
|
||||
|
||||
/* Save tick handler routine pointer, will point to do_timer() in
|
||||
|
|
|
@ -70,7 +70,8 @@ void __init hp300_sched_init(irq_handler_t vector)
|
|||
|
||||
asm volatile(" movpw %0,%1@(5)" : : "d" (INTVAL), "a" (CLOCKBASE));
|
||||
|
||||
request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector);
|
||||
if (request_irq(IRQ_AUTO_6, hp300_tick, IRQ_FLG_STD, "timer tick", vector))
|
||||
pr_err("Couldn't register timer interrupt\n");
|
||||
|
||||
out_8(CLOCKBASE + CLKCR2, 0x1); /* select CR1 */
|
||||
out_8(CLOCKBASE + CLKCR1, 0x40); /* enable irq */
|
||||
|
|
1
arch/m68k/kernel/.gitignore
vendored
Normal file
1
arch/m68k/kernel/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
vmlinux.lds
|
|
@ -424,7 +424,7 @@ resume:
|
|||
.data
|
||||
ALIGN
|
||||
sys_call_table:
|
||||
.long sys_ni_syscall /* 0 - old "setup()" system call*/
|
||||
.long sys_restart_syscall /* 0 - old "setup()" system call, used for restarting */
|
||||
.long sys_exit
|
||||
.long sys_fork
|
||||
.long sys_read
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/initrd.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/setup.h>
|
||||
#include <asm/fpu.h>
|
||||
#include <asm/irq.h>
|
||||
|
@ -62,7 +63,6 @@ EXPORT_SYMBOL(vme_brdtype);
|
|||
int m68k_is040or060;
|
||||
EXPORT_SYMBOL(m68k_is040or060);
|
||||
|
||||
extern int end;
|
||||
extern unsigned long availmem;
|
||||
|
||||
int m68k_num_memory;
|
||||
|
@ -215,11 +215,10 @@ static void __init m68k_parse_bootinfo(const struct bi_record *record)
|
|||
|
||||
void __init setup_arch(char **cmdline_p)
|
||||
{
|
||||
extern int _etext, _edata, _end;
|
||||
int i;
|
||||
|
||||
/* The bootinfo is located right after the kernel bss */
|
||||
m68k_parse_bootinfo((const struct bi_record *)&_end);
|
||||
m68k_parse_bootinfo((const struct bi_record *)_end);
|
||||
|
||||
if (CPU_IS_040)
|
||||
m68k_is040or060 = 4;
|
||||
|
@ -252,9 +251,9 @@ void __init setup_arch(char **cmdline_p)
|
|||
}
|
||||
|
||||
init_mm.start_code = PAGE_OFFSET;
|
||||
init_mm.end_code = (unsigned long) &_etext;
|
||||
init_mm.end_data = (unsigned long) &_edata;
|
||||
init_mm.brk = (unsigned long) &_end;
|
||||
init_mm.end_code = (unsigned long)_etext;
|
||||
init_mm.end_data = (unsigned long)_edata;
|
||||
init_mm.brk = (unsigned long)_end;
|
||||
|
||||
*cmdline_p = m68k_command_line;
|
||||
memcpy(boot_command_line, *cmdline_p, CL_SIZE);
|
||||
|
|
|
@ -326,6 +326,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __u
|
|||
struct sigcontext context;
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
/* get previous context */
|
||||
if (copy_from_user(&context, usc, sizeof(context)))
|
||||
goto badframe;
|
||||
|
@ -411,6 +414,9 @@ rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
|
|||
unsigned long usp;
|
||||
int err;
|
||||
|
||||
/* Always make any pending restarted system calls return -EINTR */
|
||||
current_thread_info()->restart_block.fn = do_no_restart_syscall;
|
||||
|
||||
err = __get_user(temp, &uc->uc_mcontext.version);
|
||||
if (temp != MCONTEXT_VERSION)
|
||||
goto badframe;
|
||||
|
@ -937,6 +943,15 @@ handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
|
|||
regs->d0 = -EINTR;
|
||||
break;
|
||||
|
||||
case -ERESTART_RESTARTBLOCK:
|
||||
if (!has_handler) {
|
||||
regs->d0 = __NR_restart_syscall;
|
||||
regs->pc -= 2;
|
||||
break;
|
||||
}
|
||||
regs->d0 = -EINTR;
|
||||
break;
|
||||
|
||||
case -ERESTARTSYS:
|
||||
if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
|
||||
regs->d0 = -EINTR;
|
||||
|
|
|
@ -33,6 +33,7 @@ SECTIONS
|
|||
} :data
|
||||
/* End of data goes *here* so that freeing init code works properly. */
|
||||
_edata = .;
|
||||
NOTES
|
||||
|
||||
/* will be freed after init */
|
||||
. = ALIGN(PAGE_SIZE); /* Init code and data */
|
||||
|
|
|
@ -92,7 +92,8 @@ static irqreturn_t baboon_irq(int irq, void *dev_id)
|
|||
void __init baboon_register_interrupts(void)
|
||||
{
|
||||
baboon_disabled = 0;
|
||||
request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon);
|
||||
if (request_irq(IRQ_NUBUS_C, baboon_irq, 0, "baboon", (void *)baboon))
|
||||
pr_err("Couldn't register baboon interrupt\n");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -47,13 +47,6 @@
|
|||
|
||||
struct mac_booter_data mac_bi_data;
|
||||
|
||||
/* New m68k bootinfo stuff and videobase */
|
||||
|
||||
extern int m68k_num_memory;
|
||||
extern struct mem_info m68k_memory[NUM_MEMINFO];
|
||||
|
||||
extern struct mem_info m68k_ramdisk;
|
||||
|
||||
/* The phys. video addr. - might be bogus on some machines */
|
||||
static unsigned long mac_orig_videoaddr;
|
||||
|
||||
|
@ -61,7 +54,6 @@ static unsigned long mac_orig_videoaddr;
|
|||
extern unsigned long mac_gettimeoffset(void);
|
||||
extern int mac_hwclk(int, struct rtc_time *);
|
||||
extern int mac_set_clock_mmss(unsigned long);
|
||||
extern int show_mac_interrupts(struct seq_file *, void *);
|
||||
extern void iop_preinit(void);
|
||||
extern void iop_init(void);
|
||||
extern void via_init(void);
|
||||
|
@ -805,10 +797,6 @@ static void __init mac_identify(void)
|
|||
mac_bi_data.boottime, mac_bi_data.gmtbias);
|
||||
printk(KERN_DEBUG " Machine ID: %ld CPUid: 0x%lx memory size: 0x%lx \n",
|
||||
mac_bi_data.id, mac_bi_data.cpuid, mac_bi_data.memsize);
|
||||
#if 0
|
||||
printk("Ramdisk: addr 0x%lx size 0x%lx\n",
|
||||
m68k_ramdisk.addr, m68k_ramdisk.size);
|
||||
#endif
|
||||
|
||||
iop_init();
|
||||
via_init();
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <asm/macints.h>
|
||||
|
||||
extern unsigned long mac_videobase;
|
||||
extern unsigned long mac_videodepth;
|
||||
extern unsigned long mac_rowbytes;
|
||||
|
||||
extern void mac_serial_print(const char *);
|
||||
|
|
|
@ -305,14 +305,16 @@ void __init iop_register_interrupts(void)
|
|||
{
|
||||
if (iop_ism_present) {
|
||||
if (oss_present) {
|
||||
request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
|
||||
if (request_irq(OSS_IRQLEV_IOPISM, iop_ism_irq,
|
||||
IRQ_FLG_LOCK, "ISM IOP",
|
||||
(void *) IOP_NUM_ISM);
|
||||
(void *) IOP_NUM_ISM))
|
||||
pr_err("Couldn't register ISM IOP interrupt\n");
|
||||
oss_irq_enable(IRQ_MAC_ADB);
|
||||
} else {
|
||||
request_irq(IRQ_VIA2_0, iop_ism_irq,
|
||||
if (request_irq(IRQ_VIA2_0, iop_ism_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "ISM IOP",
|
||||
(void *) IOP_NUM_ISM);
|
||||
(void *) IOP_NUM_ISM))
|
||||
pr_err("Couldn't register ISM IOP interrupt\n");
|
||||
}
|
||||
if (!iop_alive(iop_base[IOP_NUM_ISM])) {
|
||||
printk("IOP: oh my god, they killed the ISM IOP!\n");
|
||||
|
|
|
@ -134,6 +134,7 @@
|
|||
#include <asm/errno.h>
|
||||
#include <asm/macints.h>
|
||||
#include <asm/irq_regs.h>
|
||||
#include <asm/mac_oss.h>
|
||||
|
||||
#define DEBUG_SPURIOUS
|
||||
#define SHUTUP_SONIC
|
||||
|
@ -146,7 +147,6 @@ static int scc_mask;
|
|||
* VIA/RBV hooks
|
||||
*/
|
||||
|
||||
extern void via_init(void);
|
||||
extern void via_register_interrupts(void);
|
||||
extern void via_irq_enable(int);
|
||||
extern void via_irq_disable(int);
|
||||
|
@ -157,9 +157,6 @@ extern int via_irq_pending(int);
|
|||
* OSS hooks
|
||||
*/
|
||||
|
||||
extern int oss_present;
|
||||
|
||||
extern void oss_init(void);
|
||||
extern void oss_register_interrupts(void);
|
||||
extern void oss_irq_enable(int);
|
||||
extern void oss_irq_disable(int);
|
||||
|
@ -170,9 +167,6 @@ extern int oss_irq_pending(int);
|
|||
* PSC hooks
|
||||
*/
|
||||
|
||||
extern int psc_present;
|
||||
|
||||
extern void psc_init(void);
|
||||
extern void psc_register_interrupts(void);
|
||||
extern void psc_irq_enable(int);
|
||||
extern void psc_irq_disable(int);
|
||||
|
@ -191,12 +185,10 @@ extern void iop_register_interrupts(void);
|
|||
|
||||
extern int baboon_present;
|
||||
|
||||
extern void baboon_init(void);
|
||||
extern void baboon_register_interrupts(void);
|
||||
extern void baboon_irq_enable(int);
|
||||
extern void baboon_irq_disable(int);
|
||||
extern void baboon_irq_clear(int);
|
||||
extern int baboon_irq_pending(int);
|
||||
|
||||
/*
|
||||
* SCC interrupt routines
|
||||
|
@ -258,8 +250,9 @@ void __init mac_init_IRQ(void)
|
|||
if (baboon_present)
|
||||
baboon_register_interrupts();
|
||||
iop_register_interrupts();
|
||||
request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
|
||||
mac_nmi_handler);
|
||||
if (request_irq(IRQ_AUTO_7, mac_nmi_handler, 0, "NMI",
|
||||
mac_nmi_handler))
|
||||
pr_err("Couldn't register NMI\n");
|
||||
#ifdef DEBUG_MACINTS
|
||||
printk("mac_init_IRQ(): Done!\n");
|
||||
#endif
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
|
||||
#define RTC_OFFSET 2082844800
|
||||
|
||||
extern struct mac_booter_data mac_bi_data;
|
||||
static void (*rom_reset)(void);
|
||||
|
||||
#ifdef CONFIG_ADB_CUDA
|
||||
|
|
|
@ -66,16 +66,21 @@ void __init oss_init(void)
|
|||
|
||||
void __init oss_register_interrupts(void)
|
||||
{
|
||||
request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
|
||||
"scsi", (void *) oss);
|
||||
request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
|
||||
"scc", mac_scc_dispatch);
|
||||
request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
|
||||
"nubus", (void *) oss);
|
||||
request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
|
||||
"sound", (void *) oss);
|
||||
request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
|
||||
"via1", (void *) via1);
|
||||
if (request_irq(OSS_IRQLEV_SCSI, oss_irq, IRQ_FLG_LOCK,
|
||||
"scsi", (void *) oss))
|
||||
pr_err("Couldn't register %s interrupt\n", "scsi");
|
||||
if (request_irq(OSS_IRQLEV_IOPSCC, mac_scc_dispatch, IRQ_FLG_LOCK,
|
||||
"scc", mac_scc_dispatch))
|
||||
pr_err("Couldn't register %s interrupt\n", "scc");
|
||||
if (request_irq(OSS_IRQLEV_NUBUS, oss_nubus_irq, IRQ_FLG_LOCK,
|
||||
"nubus", (void *) oss))
|
||||
pr_err("Couldn't register %s interrupt\n", "nubus");
|
||||
if (request_irq(OSS_IRQLEV_SOUND, oss_irq, IRQ_FLG_LOCK,
|
||||
"sound", (void *) oss))
|
||||
pr_err("Couldn't register %s interrupt\n", "sound");
|
||||
if (request_irq(OSS_IRQLEV_VIA1, via1_irq, IRQ_FLG_LOCK,
|
||||
"via1", (void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "via1");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -117,10 +117,14 @@ void __init psc_init(void)
|
|||
|
||||
void __init psc_register_interrupts(void)
|
||||
{
|
||||
request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30);
|
||||
request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40);
|
||||
request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50);
|
||||
request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60);
|
||||
if (request_irq(IRQ_AUTO_3, psc_irq, 0, "psc3", (void *) 0x30))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 3);
|
||||
if (request_irq(IRQ_AUTO_4, psc_irq, 0, "psc4", (void *) 0x40))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 4);
|
||||
if (request_irq(IRQ_AUTO_5, psc_irq, 0, "psc5", (void *) 0x50))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 5);
|
||||
if (request_irq(IRQ_AUTO_6, psc_irq, 0, "psc6", (void *) 0x60))
|
||||
pr_err("Couldn't register psc%d interrupt\n", 6);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <asm/macints.h>
|
||||
#include <asm/mac_via.h>
|
||||
#include <asm/mac_psc.h>
|
||||
#include <asm/mac_oss.h>
|
||||
|
||||
volatile __u8 *via1, *via2;
|
||||
int rbv_present;
|
||||
|
@ -84,7 +85,6 @@ void via_irq_disable(int irq);
|
|||
void via_irq_clear(int irq);
|
||||
|
||||
extern irqreturn_t mac_scc_dispatch(int, void *);
|
||||
extern int oss_present;
|
||||
|
||||
/*
|
||||
* Initialize the VIAs
|
||||
|
@ -283,7 +283,8 @@ void __init via_init_clock(irq_handler_t func)
|
|||
via1[vT1CL] = MAC_CLOCK_LOW;
|
||||
via1[vT1CH] = MAC_CLOCK_HIGH;
|
||||
|
||||
request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func);
|
||||
if (request_irq(IRQ_MAC_TIMER_1, func, IRQ_FLG_LOCK, "timer", func))
|
||||
pr_err("Couldn't register %s interrupt\n", "timer");
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -293,25 +294,31 @@ void __init via_init_clock(irq_handler_t func)
|
|||
void __init via_register_interrupts(void)
|
||||
{
|
||||
if (via_alt_mapping) {
|
||||
request_irq(IRQ_AUTO_1, via1_irq,
|
||||
if (request_irq(IRQ_AUTO_1, via1_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "software",
|
||||
(void *) via1);
|
||||
request_irq(IRQ_AUTO_6, via1_irq,
|
||||
(void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "software");
|
||||
if (request_irq(IRQ_AUTO_6, via1_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
|
||||
(void *) via1);
|
||||
(void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "via1");
|
||||
} else {
|
||||
request_irq(IRQ_AUTO_1, via1_irq,
|
||||
if (request_irq(IRQ_AUTO_1, via1_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "via1",
|
||||
(void *) via1);
|
||||
(void *) via1))
|
||||
pr_err("Couldn't register %s interrupt\n", "via1");
|
||||
}
|
||||
request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
|
||||
"via2", (void *) via2);
|
||||
if (request_irq(IRQ_AUTO_2, via2_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
|
||||
"via2", (void *) via2))
|
||||
pr_err("Couldn't register %s interrupt\n", "via2");
|
||||
if (!psc_present) {
|
||||
request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
|
||||
"scc", mac_scc_dispatch);
|
||||
if (request_irq(IRQ_AUTO_4, mac_scc_dispatch, IRQ_FLG_LOCK,
|
||||
"scc", mac_scc_dispatch))
|
||||
pr_err("Couldn't register %s interrupt\n", "scc");
|
||||
}
|
||||
request_irq(IRQ_MAC_NUBUS, via_nubus_irq, IRQ_FLG_LOCK|IRQ_FLG_FAST,
|
||||
"nubus", (void *) via2);
|
||||
if (request_irq(IRQ_MAC_NUBUS, via_nubus_irq,
|
||||
IRQ_FLG_LOCK|IRQ_FLG_FAST, "nubus", (void *) via2))
|
||||
pr_err("Couldn't register %s interrupt\n", "nubus");
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -24,7 +24,6 @@ static const struct fp_ext fp_one =
|
|||
|
||||
extern struct fp_ext *fp_fadd(struct fp_ext *dest, const struct fp_ext *src);
|
||||
extern struct fp_ext *fp_fdiv(struct fp_ext *dest, const struct fp_ext *src);
|
||||
extern struct fp_ext *fp_fmul(struct fp_ext *dest, const struct fp_ext *src);
|
||||
|
||||
struct fp_ext *
|
||||
fp_fsqrt(struct fp_ext *dest, struct fp_ext *src)
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#ifdef CONFIG_ATARI
|
||||
#include <asm/atari_stram.h>
|
||||
#endif
|
||||
#include <asm/sections.h>
|
||||
#include <asm/tlb.h>
|
||||
|
||||
DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
|
||||
|
@ -73,9 +74,6 @@ extern void init_pointer_table(unsigned long ptable);
|
|||
|
||||
/* References to section boundaries */
|
||||
|
||||
extern char _text[], _etext[];
|
||||
extern char __init_begin[], __init_end[];
|
||||
|
||||
extern pmd_t *zero_pgtable;
|
||||
|
||||
void __init mem_init(void)
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#ifdef CONFIG_ATARI
|
||||
#include <asm/atari_stram.h>
|
||||
#endif
|
||||
#include <asm/sections.h>
|
||||
|
||||
#undef DEBUG
|
||||
|
||||
|
@ -301,14 +302,12 @@ void __init paging_init(void)
|
|||
}
|
||||
}
|
||||
|
||||
extern char __init_begin, __init_end;
|
||||
|
||||
void free_initmem(void)
|
||||
{
|
||||
unsigned long addr;
|
||||
|
||||
addr = (unsigned long)&__init_begin;
|
||||
for (; addr < (unsigned long)&__init_end; addr += PAGE_SIZE) {
|
||||
addr = (unsigned long)__init_begin;
|
||||
for (; addr < (unsigned long)__init_end; addr += PAGE_SIZE) {
|
||||
virt_to_page(addr)->flags &= ~(1 << PG_reserved);
|
||||
init_page_count(virt_to_page(addr));
|
||||
free_page(addr);
|
||||
|
|
|
@ -42,7 +42,6 @@ extern unsigned long mvme147_gettimeoffset (void);
|
|||
extern int mvme147_hwclk (int, struct rtc_time *);
|
||||
extern int mvme147_set_clock_mmss (unsigned long);
|
||||
extern void mvme147_reset (void);
|
||||
extern void mvme147_waitbut(void);
|
||||
|
||||
|
||||
static int bcd2int (unsigned char b);
|
||||
|
@ -115,8 +114,9 @@ static irqreturn_t mvme147_timer_int (int irq, void *dev_id)
|
|||
void mvme147_sched_init (irq_handler_t timer_routine)
|
||||
{
|
||||
tick_handler = timer_routine;
|
||||
request_irq (PCC_IRQ_TIMER1, mvme147_timer_int,
|
||||
IRQ_FLG_REPLACE, "timer 1", NULL);
|
||||
if (request_irq(PCC_IRQ_TIMER1, mvme147_timer_int, IRQ_FLG_REPLACE,
|
||||
"timer 1", NULL))
|
||||
pr_err("Couldn't register timer interrupt\n");
|
||||
|
||||
/* Init the clock with a value */
|
||||
/* our clock goes off every 6.25us */
|
||||
|
|
|
@ -48,7 +48,6 @@ extern unsigned long mvme16x_gettimeoffset (void);
|
|||
extern int mvme16x_hwclk (int, struct rtc_time *);
|
||||
extern int mvme16x_set_clock_mmss (unsigned long);
|
||||
extern void mvme16x_reset (void);
|
||||
extern void mvme16x_waitbut(void);
|
||||
|
||||
int bcd2int (unsigned char b);
|
||||
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <asm/machdep.h>
|
||||
#include <asm/q40_master.h>
|
||||
|
||||
extern irqreturn_t q40_process_int(int level, struct pt_regs *regs);
|
||||
extern void q40_init_IRQ(void);
|
||||
static void q40_get_model(char *model);
|
||||
extern void q40_sched_init(irq_handler_t handler);
|
||||
|
@ -47,8 +46,6 @@ static unsigned int q40_get_ss(void);
|
|||
static int q40_set_clock_mmss(unsigned long);
|
||||
static int q40_get_rtc_pll(struct rtc_pll_info *pll);
|
||||
static int q40_set_rtc_pll(struct rtc_pll_info *pll);
|
||||
extern void q40_waitbut(void);
|
||||
void q40_set_vectors(void);
|
||||
|
||||
extern void q40_mksound(unsigned int /*freq*/, unsigned int /*ticks*/);
|
||||
|
||||
|
|
|
@ -27,23 +27,21 @@
|
|||
#include <asm/sun3mmu.h>
|
||||
#include <asm/rtc.h>
|
||||
#include <asm/machdep.h>
|
||||
#include <asm/idprom.h>
|
||||
#include <asm/intersil.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/sections.h>
|
||||
#include <asm/segment.h>
|
||||
#include <asm/sun3ints.h>
|
||||
|
||||
extern char _text, _end;
|
||||
|
||||
char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
|
||||
|
||||
extern unsigned long sun3_gettimeoffset(void);
|
||||
static void sun3_sched_init(irq_handler_t handler);
|
||||
extern void sun3_get_model (char* model);
|
||||
extern void idprom_init (void);
|
||||
extern int sun3_hwclk(int set, struct rtc_time *t);
|
||||
|
||||
volatile char* clock_va;
|
||||
extern volatile unsigned char* sun3_intreg;
|
||||
extern unsigned long availmem;
|
||||
unsigned long num_pages;
|
||||
|
||||
|
@ -149,7 +147,7 @@ void __init config_sun3(void)
|
|||
mach_halt = sun3_halt;
|
||||
mach_get_hardware_list = sun3_get_hardware_list;
|
||||
|
||||
memory_start = ((((int)&_end) + 0x2000) & ~0x1fff);
|
||||
memory_start = ((((unsigned long)_end) + 0x2000) & ~0x1fff);
|
||||
// PROM seems to want the last couple of physical pages. --m
|
||||
memory_end = *(romvec->pv_sun3mem) + PAGE_OFFSET - 2*PAGE_SIZE;
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <asm/mmu_context.h>
|
||||
#include <asm/dvma.h>
|
||||
|
||||
extern void prom_reboot (char *) __attribute__ ((__noreturn__));
|
||||
|
||||
#undef DEBUG_MMU_EMU
|
||||
#define DEBUG_PROM_MAPS
|
||||
|
|
|
@ -105,7 +105,10 @@ void __init sun3_init_IRQ(void)
|
|||
m68k_setup_irq_controller(&sun3_irq_controller, IRQ_AUTO_1, 7);
|
||||
m68k_setup_user_interrupt(VEC_USER, 128, NULL);
|
||||
|
||||
request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL);
|
||||
request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL);
|
||||
request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL);
|
||||
if (request_irq(IRQ_AUTO_5, sun3_int5, 0, "int5", NULL))
|
||||
pr_err("Couldn't register %s interrupt\n", "int5");
|
||||
if (request_irq(IRQ_AUTO_7, sun3_int7, 0, "int7", NULL))
|
||||
pr_err("Couldn't register %s interrupt\n", "int7");
|
||||
if (request_irq(IRQ_USER+127, sun3_vec255, 0, "vec255", NULL))
|
||||
pr_err("Couldn't register %s interrupt\n", "vec255");
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include "time.h"
|
||||
|
||||
volatile char *clock_va;
|
||||
extern volatile unsigned char *sun3_intreg;
|
||||
|
||||
extern void sun3_get_model(char *model);
|
||||
|
||||
|
|
|
@ -595,6 +595,44 @@ config WR_PPMC
|
|||
This enables support for the Wind River MIPS32 4KC PPMC evaluation
|
||||
board, which is based on GT64120 bridge chip.
|
||||
|
||||
config CAVIUM_OCTEON_SIMULATOR
|
||||
bool "Support for the Cavium Networks Octeon Simulator"
|
||||
select CEVT_R4K
|
||||
select 64BIT_PHYS_ADDR
|
||||
select DMA_COHERENT
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select SYS_SUPPORTS_HIGHMEM
|
||||
select CPU_CAVIUM_OCTEON
|
||||
help
|
||||
The Octeon simulator is software performance model of the Cavium
|
||||
Octeon Processor. It supports simulating Octeon processors on x86
|
||||
hardware.
|
||||
|
||||
config CAVIUM_OCTEON_REFERENCE_BOARD
|
||||
bool "Support for the Cavium Networks Octeon reference board"
|
||||
select CEVT_R4K
|
||||
select 64BIT_PHYS_ADDR
|
||||
select DMA_COHERENT
|
||||
select SYS_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_BIG_ENDIAN
|
||||
select SYS_SUPPORTS_HIGHMEM
|
||||
select SYS_HAS_EARLY_PRINTK
|
||||
select CPU_CAVIUM_OCTEON
|
||||
select SWAP_IO_SPACE
|
||||
help
|
||||
This option supports all of the Octeon reference boards from Cavium
|
||||
Networks. It builds a kernel that dynamically determines the Octeon
|
||||
CPU type and supports all known board reference implementations.
|
||||
Some of the supported boards are:
|
||||
EBT3000
|
||||
EBH3000
|
||||
EBH3100
|
||||
Thunder
|
||||
Kodama
|
||||
Hikari
|
||||
Say Y here for most Octeon reference boards.
|
||||
|
||||
endchoice
|
||||
|
||||
source "arch/mips/alchemy/Kconfig"
|
||||
|
@ -607,6 +645,7 @@ source "arch/mips/sgi-ip27/Kconfig"
|
|||
source "arch/mips/sibyte/Kconfig"
|
||||
source "arch/mips/txx9/Kconfig"
|
||||
source "arch/mips/vr41xx/Kconfig"
|
||||
source "arch/mips/cavium-octeon/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
||||
|
@ -682,7 +721,11 @@ config CEVT_DS1287
|
|||
config CEVT_GT641XX
|
||||
bool
|
||||
|
||||
config CEVT_R4K_LIB
|
||||
bool
|
||||
|
||||
config CEVT_R4K
|
||||
select CEVT_R4K_LIB
|
||||
bool
|
||||
|
||||
config CEVT_SB1250
|
||||
|
@ -697,7 +740,11 @@ config CSRC_BCM1480
|
|||
config CSRC_IOASIC
|
||||
bool
|
||||
|
||||
config CSRC_R4K_LIB
|
||||
bool
|
||||
|
||||
config CSRC_R4K
|
||||
select CSRC_R4K_LIB
|
||||
bool
|
||||
|
||||
config CSRC_SB1250
|
||||
|
@ -835,6 +882,9 @@ config IRQ_GT641XX
|
|||
config IRQ_GIC
|
||||
bool
|
||||
|
||||
config IRQ_CPU_OCTEON
|
||||
bool
|
||||
|
||||
config MIPS_BOARDS_GEN
|
||||
bool
|
||||
|
||||
|
@ -924,7 +974,7 @@ config BOOT_ELF32
|
|||
config MIPS_L1_CACHE_SHIFT
|
||||
int
|
||||
default "4" if MACH_DECSTATION || MIKROTIK_RB532
|
||||
default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM
|
||||
default "7" if SGI_IP22 || SGI_IP27 || SGI_IP28 || SNI_RM || CPU_CAVIUM_OCTEON
|
||||
default "4" if PMC_MSP4200_EVAL
|
||||
default "5"
|
||||
|
||||
|
@ -1185,6 +1235,23 @@ config CPU_SB1
|
|||
select CPU_SUPPORTS_HIGHMEM
|
||||
select WEAK_ORDERING
|
||||
|
||||
config CPU_CAVIUM_OCTEON
|
||||
bool "Cavium Octeon processor"
|
||||
select IRQ_CPU
|
||||
select IRQ_CPU_OCTEON
|
||||
select CPU_HAS_PREFETCH
|
||||
select CPU_SUPPORTS_64BIT_KERNEL
|
||||
select SYS_SUPPORTS_SMP
|
||||
select NR_CPUS_DEFAULT_16
|
||||
select WEAK_ORDERING
|
||||
select WEAK_REORDERING_BEYOND_LLSC
|
||||
select CPU_SUPPORTS_HIGHMEM
|
||||
help
|
||||
The Cavium Octeon processor is a highly integrated chip containing
|
||||
many ethernet hardware widgets for networking tasks. The processor
|
||||
can have up to 16 Mips64v2 cores and 8 integrated gigabit ethernets.
|
||||
Full details can be found at http://www.caviumnetworks.com.
|
||||
|
||||
endchoice
|
||||
|
||||
config SYS_HAS_CPU_LOONGSON2
|
||||
|
@ -1285,7 +1352,7 @@ config CPU_MIPSR1
|
|||
|
||||
config CPU_MIPSR2
|
||||
bool
|
||||
default y if CPU_MIPS32_R2 || CPU_MIPS64_R2
|
||||
default y if CPU_MIPS32_R2 || CPU_MIPS64_R2 || CPU_CAVIUM_OCTEON
|
||||
|
||||
config SYS_SUPPORTS_32BIT_KERNEL
|
||||
bool
|
||||
|
|
|
@ -144,6 +144,10 @@ cflags-$(CONFIG_CPU_SB1) += $(call cc-option,-march=sb1,-march=r5000) \
|
|||
cflags-$(CONFIG_CPU_R8000) += -march=r8000 -Wa,--trap
|
||||
cflags-$(CONFIG_CPU_R10000) += $(call cc-option,-march=r10000,-march=r8000) \
|
||||
-Wa,--trap
|
||||
cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += $(call cc-option,-march=octeon) -Wa,--trap
|
||||
ifeq (,$(findstring march=octeon, $(cflags-$(CONFIG_CPU_CAVIUM_OCTEON))))
|
||||
cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -Wa,-march=octeon
|
||||
endif
|
||||
|
||||
cflags-$(CONFIG_CPU_R4000_WORKAROUNDS) += $(call cc-option,-mfix-r4000,)
|
||||
cflags-$(CONFIG_CPU_R4400_WORKAROUNDS) += $(call cc-option,-mfix-r4400,)
|
||||
|
@ -184,84 +188,84 @@ cflags-$(CONFIG_SOC_AU1X00) += -I$(srctree)/arch/mips/include/asm/mach-au1x00
|
|||
#
|
||||
# AMD Alchemy Pb1000 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/pb1000/
|
||||
core-$(CONFIG_MIPS_PB1000) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_PB1000) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
|
||||
load-$(CONFIG_MIPS_PB1000) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Pb1100 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/pb1100/
|
||||
core-$(CONFIG_MIPS_PB1100) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_PB1100) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
|
||||
load-$(CONFIG_MIPS_PB1100) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Pb1500 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/pb1500/
|
||||
core-$(CONFIG_MIPS_PB1500) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_PB1500) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
|
||||
load-$(CONFIG_MIPS_PB1500) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Pb1550 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/pb1550/
|
||||
core-$(CONFIG_MIPS_PB1550) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_PB1550) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
|
||||
load-$(CONFIG_MIPS_PB1550) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Pb1200 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/pb1200/
|
||||
core-$(CONFIG_MIPS_PB1200) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_PB1200) += -I$(srctree)/arch/mips/include/asm/mach-pb1x00
|
||||
load-$(CONFIG_MIPS_PB1200) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Db1000 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/db1x00/
|
||||
core-$(CONFIG_MIPS_DB1000) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_DB1000) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
|
||||
load-$(CONFIG_MIPS_DB1000) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Db1100 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/db1x00/
|
||||
core-$(CONFIG_MIPS_DB1100) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_DB1100) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
|
||||
load-$(CONFIG_MIPS_DB1100) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Db1500 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/db1x00/
|
||||
core-$(CONFIG_MIPS_DB1500) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_DB1500) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
|
||||
load-$(CONFIG_MIPS_DB1500) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Db1550 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/db1x00/
|
||||
core-$(CONFIG_MIPS_DB1550) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_DB1550) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
|
||||
load-$(CONFIG_MIPS_DB1550) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Db1200 eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/pb1200/
|
||||
core-$(CONFIG_MIPS_DB1200) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_DB1200) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
|
||||
load-$(CONFIG_MIPS_DB1200) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Bosporus eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/db1x00/
|
||||
core-$(CONFIG_MIPS_BOSPORUS) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_BOSPORUS) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
|
||||
load-$(CONFIG_MIPS_BOSPORUS) += 0xffffffff80100000
|
||||
|
||||
#
|
||||
# AMD Alchemy Mirage eval board
|
||||
#
|
||||
libs-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/db1x00/
|
||||
core-$(CONFIG_MIPS_MIRAGE) += arch/mips/alchemy/devboards/
|
||||
cflags-$(CONFIG_MIPS_MIRAGE) += -I$(srctree)/arch/mips/include/asm/mach-db1x00
|
||||
load-$(CONFIG_MIPS_MIRAGE) += 0xffffffff80100000
|
||||
|
||||
|
@ -586,6 +590,18 @@ core-$(CONFIG_TOSHIBA_RBTX4927) += arch/mips/txx9/rbtx4927/
|
|||
core-$(CONFIG_TOSHIBA_RBTX4938) += arch/mips/txx9/rbtx4938/
|
||||
core-$(CONFIG_TOSHIBA_RBTX4939) += arch/mips/txx9/rbtx4939/
|
||||
|
||||
#
|
||||
# Cavium Octeon
|
||||
#
|
||||
core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/
|
||||
cflags-$(CONFIG_CPU_CAVIUM_OCTEON) += -I$(srctree)/arch/mips/include/asm/mach-cavium-octeon
|
||||
core-$(CONFIG_CPU_CAVIUM_OCTEON) += arch/mips/cavium-octeon/executive/
|
||||
ifdef CONFIG_CAVIUM_OCTEON_2ND_KERNEL
|
||||
load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff84100000
|
||||
else
|
||||
load-$(CONFIG_CPU_CAVIUM_OCTEON) += 0xffffffff81100000
|
||||
endif
|
||||
|
||||
cflags-y += -I$(srctree)/arch/mips/include/asm/mach-generic
|
||||
drivers-$(CONFIG_PCI) += arch/mips/pci/
|
||||
|
||||
|
|
|
@ -128,9 +128,10 @@ config SOC_AU1200
|
|||
config SOC_AU1X00
|
||||
bool
|
||||
select 64BIT_PHYS_ADDR
|
||||
select CEVT_R4K
|
||||
select CSRC_R4K
|
||||
select CEVT_R4K_LIB
|
||||
select CSRC_R4K_LIB
|
||||
select IRQ_CPU
|
||||
select SYS_HAS_CPU_MIPS32_R1
|
||||
select SYS_SUPPORTS_32BIT_KERNEL
|
||||
select SYS_SUPPORTS_APM_EMULATION
|
||||
select GENERIC_HARDIRQS_NO__DO_IRQ
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#
|
||||
|
||||
obj-y += prom.o irq.o puts.o time.o reset.o \
|
||||
au1xxx_irqmap.o clocks.o platform.o power.o setup.o \
|
||||
sleeper.o cputable.o dma.o dbdma.o gpio.o
|
||||
clocks.o platform.o power.o setup.o \
|
||||
sleeper.o dma.o dbdma.o gpio.o
|
||||
|
||||
obj-$(CONFIG_PCI) += pci.o
|
||||
|
||||
|
|
|
@ -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);
|
|
@ -27,12 +27,21 @@
|
|||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
/*
|
||||
* I haven't found anyone that doesn't use a 12 MHz source clock,
|
||||
* but just in case.....
|
||||
*/
|
||||
#define AU1000_SRC_CLK 12000000
|
||||
|
||||
static unsigned int au1x00_clock; /* Hz */
|
||||
static unsigned int lcd_clock; /* KHz */
|
||||
static unsigned long uart_baud_base;
|
||||
|
||||
static DEFINE_SPINLOCK(time_lock);
|
||||
|
||||
/*
|
||||
* Set the au1000_clock
|
||||
*/
|
||||
|
@ -63,31 +72,45 @@ void set_au1x00_uart_baud_base(unsigned long new_baud_base)
|
|||
}
|
||||
|
||||
/*
|
||||
* Calculate the Au1x00's LCD clock based on the current
|
||||
* cpu clock and the system bus clock, and try to keep it
|
||||
* below 40 MHz (the Pb1000 board can lock-up if the LCD
|
||||
* clock is over 40 MHz).
|
||||
* We read the real processor speed from the PLL. This is important
|
||||
* because it is more accurate than computing it from the 32 KHz
|
||||
* counter, if it exists. If we don't have an accurate processor
|
||||
* speed, all of the peripherals that derive their clocks based on
|
||||
* this advertised speed will introduce error and sometimes not work
|
||||
* properly. This function is futher convoluted to still allow configurations
|
||||
* to do that in case they have really, really old silicon with a
|
||||
* write-only PLL register. -- Dan
|
||||
*/
|
||||
void set_au1x00_lcd_clock(void)
|
||||
unsigned long au1xxx_calc_clock(void)
|
||||
{
|
||||
unsigned int static_cfg0;
|
||||
unsigned int sys_busclk = (get_au1x00_speed() / 1000) /
|
||||
((int)(au_readl(SYS_POWERCTRL) & 0x03) + 2);
|
||||
unsigned long cpu_speed;
|
||||
unsigned long flags;
|
||||
|
||||
static_cfg0 = au_readl(MEM_STCFG0);
|
||||
spin_lock_irqsave(&time_lock, flags);
|
||||
|
||||
if (static_cfg0 & (1 << 11))
|
||||
lcd_clock = sys_busclk / 5; /* note: BCLK switching fails with D5 */
|
||||
/*
|
||||
* On early Au1000, sys_cpupll was write-only. Since these
|
||||
* silicon versions of Au1000 are not sold by AMD, we don't bend
|
||||
* over backwards trying to determine the frequency.
|
||||
*/
|
||||
if (au1xxx_cpu_has_pll_wo())
|
||||
#ifdef CONFIG_SOC_AU1000_FREQUENCY
|
||||
cpu_speed = CONFIG_SOC_AU1000_FREQUENCY;
|
||||
#else
|
||||
cpu_speed = 396000000;
|
||||
#endif
|
||||
else
|
||||
lcd_clock = sys_busclk / 4;
|
||||
cpu_speed = (au_readl(SYS_CPUPLL) & 0x0000003f) * AU1000_SRC_CLK;
|
||||
|
||||
if (lcd_clock > 50000) /* Epson MAX */
|
||||
printk(KERN_WARNING "warning: LCD clock too high (%u KHz)\n",
|
||||
lcd_clock);
|
||||
}
|
||||
/* On Alchemy CPU:counter ratio is 1:1 */
|
||||
mips_hpt_frequency = cpu_speed;
|
||||
/* Equation: Baudrate = CPU / (SD * 2 * CLKDIV * 16) */
|
||||
set_au1x00_uart_baud_base(cpu_speed / (2 * ((int)(au_readl(SYS_POWERCTRL)
|
||||
& 0x03) + 2) * 16));
|
||||
|
||||
unsigned int get_au1x00_lcd_clock(void)
|
||||
{
|
||||
return lcd_clock;
|
||||
spin_unlock_irqrestore(&time_lock, flags);
|
||||
|
||||
set_au1x00_speed(cpu_speed);
|
||||
|
||||
return cpu_speed;
|
||||
}
|
||||
EXPORT_SYMBOL(get_au1x00_lcd_clock);
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -174,6 +174,11 @@ static dbdev_tab_t dbdev_tab[] = {
|
|||
|
||||
#define DBDEV_TAB_SIZE ARRAY_SIZE(dbdev_tab)
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static u32 au1xxx_dbdma_pm_regs[NUM_DBDMA_CHANS + 1][8];
|
||||
#endif
|
||||
|
||||
|
||||
static chan_tab_t *chan_tab_ptr[NUM_DBDMA_CHANS];
|
||||
|
||||
static dbdev_tab_t *find_dbdev_id(u32 id)
|
||||
|
@ -975,4 +980,64 @@ u32 au1xxx_dbdma_put_dscr(u32 chanid, au1x_ddma_desc_t *dscr)
|
|||
return nbytes;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
void au1xxx_dbdma_suspend(void)
|
||||
{
|
||||
int i;
|
||||
u32 addr;
|
||||
|
||||
addr = DDMA_GLOBAL_BASE;
|
||||
au1xxx_dbdma_pm_regs[0][0] = au_readl(addr + 0x00);
|
||||
au1xxx_dbdma_pm_regs[0][1] = au_readl(addr + 0x04);
|
||||
au1xxx_dbdma_pm_regs[0][2] = au_readl(addr + 0x08);
|
||||
au1xxx_dbdma_pm_regs[0][3] = au_readl(addr + 0x0c);
|
||||
|
||||
/* save channel configurations */
|
||||
for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
|
||||
au1xxx_dbdma_pm_regs[i][0] = au_readl(addr + 0x00);
|
||||
au1xxx_dbdma_pm_regs[i][1] = au_readl(addr + 0x04);
|
||||
au1xxx_dbdma_pm_regs[i][2] = au_readl(addr + 0x08);
|
||||
au1xxx_dbdma_pm_regs[i][3] = au_readl(addr + 0x0c);
|
||||
au1xxx_dbdma_pm_regs[i][4] = au_readl(addr + 0x10);
|
||||
au1xxx_dbdma_pm_regs[i][5] = au_readl(addr + 0x14);
|
||||
au1xxx_dbdma_pm_regs[i][6] = au_readl(addr + 0x18);
|
||||
|
||||
/* halt channel */
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][0] & ~1, addr + 0x00);
|
||||
au_sync();
|
||||
while (!(au_readl(addr + 0x14) & 1))
|
||||
au_sync();
|
||||
|
||||
addr += 0x100; /* next channel base */
|
||||
}
|
||||
/* disable channel interrupts */
|
||||
au_writel(0, DDMA_GLOBAL_BASE + 0x0c);
|
||||
au_sync();
|
||||
}
|
||||
|
||||
void au1xxx_dbdma_resume(void)
|
||||
{
|
||||
int i;
|
||||
u32 addr;
|
||||
|
||||
addr = DDMA_GLOBAL_BASE;
|
||||
au_writel(au1xxx_dbdma_pm_regs[0][0], addr + 0x00);
|
||||
au_writel(au1xxx_dbdma_pm_regs[0][1], addr + 0x04);
|
||||
au_writel(au1xxx_dbdma_pm_regs[0][2], addr + 0x08);
|
||||
au_writel(au1xxx_dbdma_pm_regs[0][3], addr + 0x0c);
|
||||
|
||||
/* restore channel configurations */
|
||||
for (i = 1, addr = DDMA_CHANNEL_BASE; i < NUM_DBDMA_CHANS; i++) {
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][0], addr + 0x00);
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][1], addr + 0x04);
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][2], addr + 0x08);
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][3], addr + 0x0c);
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][4], addr + 0x10);
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][5], addr + 0x14);
|
||||
au_writel(au1xxx_dbdma_pm_regs[i][6], addr + 0x18);
|
||||
au_sync();
|
||||
addr += 0x100; /* next channel base */
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
#endif /* defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200) */
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
@ -36,15 +37,172 @@
|
|||
#include <asm/mach-pb1x00/pb1000.h>
|
||||
#endif
|
||||
|
||||
#define EXT_INTC0_REQ0 2 /* IP 2 */
|
||||
#define EXT_INTC0_REQ1 3 /* IP 3 */
|
||||
#define EXT_INTC1_REQ0 4 /* IP 4 */
|
||||
#define EXT_INTC1_REQ1 5 /* IP 5 */
|
||||
#define MIPS_TIMER_IP 7 /* IP 7 */
|
||||
static int au1x_ic_settype(unsigned int irq, unsigned int flow_type);
|
||||
|
||||
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
|
||||
|
||||
|
@ -130,67 +288,47 @@ void restore_au1xxx_intctl(void)
|
|||
#endif /* CONFIG_PM */
|
||||
|
||||
|
||||
inline void local_enable_irq(unsigned int irq_nr)
|
||||
static void au1x_ic0_unmask(unsigned int irq_nr)
|
||||
{
|
||||
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
|
||||
|
||||
if (bit >= 32) {
|
||||
au_writel(1 << (bit - 32), IC1_MASKSET);
|
||||
au_writel(1 << (bit - 32), IC1_WAKESET);
|
||||
} else {
|
||||
au_writel(1 << bit, IC0_MASKSET);
|
||||
au_writel(1 << bit, IC0_WAKESET);
|
||||
}
|
||||
au_sync();
|
||||
}
|
||||
|
||||
static void au1x_ic1_unmask(unsigned int irq_nr)
|
||||
{
|
||||
unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
|
||||
au_writel(1 << bit, IC1_MASKSET);
|
||||
au_writel(1 << bit, IC1_WAKESET);
|
||||
|
||||
inline void local_disable_irq(unsigned int irq_nr)
|
||||
/* very hacky. does the pb1000 cpld auto-disable this int?
|
||||
* nowhere in the current kernel sources is it disabled. --mlau
|
||||
*/
|
||||
#if defined(CONFIG_MIPS_PB1000)
|
||||
if (irq_nr == AU1000_GPIO_15)
|
||||
au_writel(0x4000, PB1000_MDR); /* enable int */
|
||||
#endif
|
||||
au_sync();
|
||||
}
|
||||
|
||||
static void au1x_ic0_mask(unsigned int irq_nr)
|
||||
{
|
||||
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
|
||||
|
||||
if (bit >= 32) {
|
||||
au_writel(1 << (bit - 32), IC1_MASKCLR);
|
||||
au_writel(1 << (bit - 32), IC1_WAKECLR);
|
||||
} else {
|
||||
au_writel(1 << bit, IC0_MASKCLR);
|
||||
au_writel(1 << bit, IC0_WAKECLR);
|
||||
}
|
||||
au_sync();
|
||||
}
|
||||
|
||||
|
||||
static inline void mask_and_ack_rise_edge_irq(unsigned int irq_nr)
|
||||
static void au1x_ic1_mask(unsigned int irq_nr)
|
||||
{
|
||||
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
|
||||
|
||||
if (bit >= 32) {
|
||||
au_writel(1 << (bit - 32), IC1_RISINGCLR);
|
||||
au_writel(1 << (bit - 32), IC1_MASKCLR);
|
||||
} else {
|
||||
au_writel(1 << bit, IC0_RISINGCLR);
|
||||
au_writel(1 << bit, IC0_MASKCLR);
|
||||
}
|
||||
unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
|
||||
au_writel(1 << bit, IC1_MASKCLR);
|
||||
au_writel(1 << bit, IC1_WAKECLR);
|
||||
au_sync();
|
||||
}
|
||||
|
||||
|
||||
static inline void mask_and_ack_fall_edge_irq(unsigned int irq_nr)
|
||||
{
|
||||
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
|
||||
|
||||
if (bit >= 32) {
|
||||
au_writel(1 << (bit - 32), IC1_FALLINGCLR);
|
||||
au_writel(1 << (bit - 32), IC1_MASKCLR);
|
||||
} else {
|
||||
au_writel(1 << bit, IC0_FALLINGCLR);
|
||||
au_writel(1 << bit, IC0_MASKCLR);
|
||||
}
|
||||
au_sync();
|
||||
}
|
||||
|
||||
|
||||
static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
|
||||
static void au1x_ic0_ack(unsigned int irq_nr)
|
||||
{
|
||||
unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
|
||||
|
||||
|
@ -198,349 +336,229 @@ static inline void mask_and_ack_either_edge_irq(unsigned int irq_nr)
|
|||
* This may assume that we don't get interrupts from
|
||||
* both edges at once, or if we do, that we don't care.
|
||||
*/
|
||||
if (bit >= 32) {
|
||||
au_writel(1 << (bit - 32), IC1_FALLINGCLR);
|
||||
au_writel(1 << (bit - 32), IC1_RISINGCLR);
|
||||
au_writel(1 << (bit - 32), IC1_MASKCLR);
|
||||
} else {
|
||||
au_writel(1 << bit, IC0_FALLINGCLR);
|
||||
au_writel(1 << bit, IC0_RISINGCLR);
|
||||
au_writel(1 << bit, IC0_MASKCLR);
|
||||
}
|
||||
au_sync();
|
||||
}
|
||||
|
||||
static inline void mask_and_ack_level_irq(unsigned int irq_nr)
|
||||
static void au1x_ic1_ack(unsigned int irq_nr)
|
||||
{
|
||||
local_disable_irq(irq_nr);
|
||||
au_sync();
|
||||
#if defined(CONFIG_MIPS_PB1000)
|
||||
if (irq_nr == AU1000_GPIO_15) {
|
||||
au_writel(0x8000, PB1000_MDR); /* ack int */
|
||||
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();
|
||||
}
|
||||
#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)))
|
||||
local_enable_irq(irq_nr);
|
||||
unsigned int bit = irq - AU1000_INTC1_INT_BASE;
|
||||
unsigned long wakemsk, flags;
|
||||
|
||||
#if defined(CONFIG_MIPS_PB1000)
|
||||
if (irq_nr == AU1000_GPIO_15) {
|
||||
au_writel(0x4000, PB1000_MDR); /* enable int */
|
||||
au_sync();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* only GPIO 0-7 can act as wakeup source: */
|
||||
if ((irq < AU1000_GPIO_0) || (irq > AU1000_GPIO_7))
|
||||
return -EINVAL;
|
||||
|
||||
unsigned long save_local_and_disable(int controller)
|
||||
{
|
||||
int i;
|
||||
unsigned long flags, mask;
|
||||
|
||||
spin_lock_irqsave(&irq_lock, flags);
|
||||
if (controller) {
|
||||
mask = au_readl(IC1_MASKSET);
|
||||
for (i = 32; i < 64; i++)
|
||||
local_disable_irq(i);
|
||||
} else {
|
||||
mask = au_readl(IC0_MASKSET);
|
||||
for (i = 0; i < 32; i++)
|
||||
local_disable_irq(i);
|
||||
}
|
||||
spin_unlock_irqrestore(&irq_lock, flags);
|
||||
|
||||
return mask;
|
||||
}
|
||||
|
||||
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);
|
||||
local_irq_save(flags);
|
||||
wakemsk = au_readl(SYS_WAKEMSK);
|
||||
if (on)
|
||||
wakemsk |= 1 << bit;
|
||||
else
|
||||
local_enable_irq(i);
|
||||
}
|
||||
|
||||
if (controller)
|
||||
new_mask = au_readl(IC1_MASKSET);
|
||||
else
|
||||
new_mask = au_readl(IC0_MASKSET);
|
||||
|
||||
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);
|
||||
}
|
||||
wakemsk &= ~(1 << bit);
|
||||
au_writel(wakemsk, SYS_WAKEMSK);
|
||||
au_sync();
|
||||
local_irq_restore(flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Interrupts are nested. Even if an interrupt handler is registered
|
||||
* as "fast", we might get another interrupt before we return from
|
||||
* intcX_reqX_irqdispatch().
|
||||
* irq_chips for both ICs; this way the mask handlers can be
|
||||
* as short as possible.
|
||||
*
|
||||
* NOTE: the ->ack() callback is used by the handle_edge_irq
|
||||
* flowhandler only, the ->mask_ack() one by handle_level_irq,
|
||||
* so no need for an irq_chip for each type of irq (level/edge).
|
||||
*/
|
||||
static struct irq_chip au1x_ic0_chip = {
|
||||
.name = "Alchemy-IC0",
|
||||
.ack = au1x_ic0_ack, /* edge */
|
||||
.mask = au1x_ic0_mask,
|
||||
.mask_ack = au1x_ic0_mask, /* level */
|
||||
.unmask = au1x_ic0_unmask,
|
||||
.set_type = au1x_ic_settype,
|
||||
};
|
||||
|
||||
static 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;
|
||||
unsigned int bit;
|
||||
struct irq_chip *chip;
|
||||
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;
|
||||
} else if (pending & CAUSEF_IP2) {
|
||||
s = IC0_REQ0INT;
|
||||
off = AU1000_INTC0_INT_BASE;
|
||||
} else if (pending & CAUSEF_IP3) {
|
||||
s = IC0_REQ1INT;
|
||||
off = AU1000_INTC0_INT_BASE;
|
||||
} else if (pending & CAUSEF_IP4) {
|
||||
s = IC1_REQ0INT;
|
||||
off = AU1000_INTC1_INT_BASE;
|
||||
} else if (pending & CAUSEF_IP5) {
|
||||
s = IC1_REQ1INT;
|
||||
off = AU1000_INTC1_INT_BASE;
|
||||
} else
|
||||
goto spurious;
|
||||
|
||||
bit = 0;
|
||||
s = au_readl(s);
|
||||
if (unlikely(!s)) {
|
||||
spurious:
|
||||
spurious_interrupt();
|
||||
return;
|
||||
}
|
||||
#ifdef AU1000_USB_DEV_REQ_INT
|
||||
/*
|
||||
* Because of the tight timing of SETUP token to reply
|
||||
* transactions, the USB devices-side packet complete
|
||||
* interrupt needs the highest priority.
|
||||
*/
|
||||
if ((intc0_req0 & (1 << AU1000_USB_DEV_REQ_INT))) {
|
||||
intc0_req0 &= ~(1 << AU1000_USB_DEV_REQ_INT);
|
||||
bit = 1 << (AU1000_USB_DEV_REQ_INT - AU1000_INTC0_INT_BASE);
|
||||
if ((pending & CAUSEF_IP2) && (s & bit)) {
|
||||
do_IRQ(AU1000_USB_DEV_REQ_INT);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
bit = __ffs(intc0_req0);
|
||||
intc0_req0 &= ~(1 << bit);
|
||||
do_IRQ(AU1000_INTC0_INT_BASE + bit);
|
||||
do_IRQ(__ffs(s) + off);
|
||||
}
|
||||
|
||||
|
||||
static void intc0_req1_irqdispatch(void)
|
||||
/* setup edge/level and assign request 0/1 */
|
||||
void __init au1xxx_setup_irqmap(struct au1xxx_irqmap *map, int count)
|
||||
{
|
||||
static unsigned long intc0_req1;
|
||||
unsigned int bit;
|
||||
unsigned int bit, irq_nr;
|
||||
|
||||
intc0_req1 |= au_readl(IC0_REQ1INT);
|
||||
while (count--) {
|
||||
irq_nr = map[count].im_irq;
|
||||
|
||||
if (!intc0_req1)
|
||||
return;
|
||||
if (((irq_nr < AU1000_INTC0_INT_BASE) ||
|
||||
(irq_nr >= AU1000_INTC0_INT_BASE + 32)) &&
|
||||
((irq_nr < AU1000_INTC1_INT_BASE) ||
|
||||
(irq_nr >= AU1000_INTC1_INT_BASE + 32)))
|
||||
continue;
|
||||
|
||||
bit = __ffs(intc0_req1);
|
||||
intc0_req1 &= ~(1 << bit);
|
||||
do_IRQ(AU1000_INTC0_INT_BASE + bit);
|
||||
if (irq_nr >= AU1000_INTC1_INT_BASE) {
|
||||
bit = irq_nr - AU1000_INTC1_INT_BASE;
|
||||
if (map[count].im_request)
|
||||
au_writel(1 << bit, IC1_ASSIGNCLR);
|
||||
} else {
|
||||
bit = irq_nr - AU1000_INTC0_INT_BASE;
|
||||
if (map[count].im_request)
|
||||
au_writel(1 << bit, IC0_ASSIGNCLR);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* 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);
|
||||
au1x_ic_settype(irq_nr, map[count].im_type);
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
struct au1xxx_irqmap *imp;
|
||||
extern struct au1xxx_irqmap au1xxx_irq_map[];
|
||||
extern struct au1xxx_irqmap au1xxx_ic0_map[];
|
||||
extern int au1xxx_nr_irqs;
|
||||
extern int au1xxx_ic0_nr_irqs;
|
||||
|
||||
/*
|
||||
* Initialize interrupt controllers to a safe state.
|
||||
|
@ -569,28 +587,25 @@ void __init arch_init_irq(void)
|
|||
|
||||
mips_cpu_irq_init();
|
||||
|
||||
/* 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.
|
||||
*/
|
||||
imp = au1xxx_ic0_map;
|
||||
for (i = 0; i < au1xxx_ic0_nr_irqs; i++) {
|
||||
setup_local_irq(imp->im_irq, imp->im_type, imp->im_request);
|
||||
imp++;
|
||||
}
|
||||
au1xxx_setup_irqmap(au1xxx_ic0_map, ARRAY_SIZE(au1xxx_ic0_map));
|
||||
|
||||
/*
|
||||
* Now set up the irq mapping for the board.
|
||||
/* Boards can register additional (GPIO-based) IRQs.
|
||||
*/
|
||||
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();
|
||||
|
||||
set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 | IE_IRQ3);
|
||||
}
|
||||
|
|
|
@ -35,25 +35,12 @@
|
|||
#include <linux/jiffies.h>
|
||||
|
||||
#include <asm/uaccess.h>
|
||||
#include <asm/cacheflush.h>
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
#define DEBUG 1
|
||||
#ifdef DEBUG
|
||||
#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__, ## args)
|
||||
#else
|
||||
#define DPRINTK(fmt, args...)
|
||||
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
|
||||
#include <asm/mach-au1x00/au1xxx_dbdma.h>
|
||||
#endif
|
||||
|
||||
static void au1000_calibrate_delay(void);
|
||||
|
||||
extern unsigned long save_local_and_disable(int controller);
|
||||
extern void restore_local_and_enable(int controller, unsigned long mask);
|
||||
extern void local_enable_irq(unsigned int irq_nr);
|
||||
|
||||
static DEFINE_SPINLOCK(pm_lock);
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/*
|
||||
* We need to save/restore a bunch of core registers that are
|
||||
|
@ -65,29 +52,16 @@ static DEFINE_SPINLOCK(pm_lock);
|
|||
* We only have to save/restore registers that aren't otherwise
|
||||
* done as part of a driver pm_* function.
|
||||
*/
|
||||
static unsigned int sleep_aux_pll_cntrl;
|
||||
static unsigned int sleep_cpu_pll_cntrl;
|
||||
static unsigned int sleep_pin_function;
|
||||
static unsigned int sleep_uart0_inten;
|
||||
static unsigned int sleep_uart0_fifoctl;
|
||||
static unsigned int sleep_uart0_linectl;
|
||||
static unsigned int sleep_uart0_clkdiv;
|
||||
static unsigned int sleep_uart0_enable;
|
||||
static unsigned int sleep_usbhost_enable;
|
||||
static unsigned int sleep_usbdev_enable;
|
||||
static unsigned int sleep_usb[2];
|
||||
static unsigned int sleep_sys_clocks[5];
|
||||
static unsigned int sleep_sys_pinfunc;
|
||||
static unsigned int sleep_static_memctlr[4][3];
|
||||
|
||||
/*
|
||||
* Define this to cause the value you write to /proc/sys/pm/sleep to
|
||||
* set the TOY timer for the amount of time you want to sleep.
|
||||
* This is done mainly for testing, but may be useful in other cases.
|
||||
* The value is number of 32KHz ticks to sleep.
|
||||
*/
|
||||
#define SLEEP_TEST_TIMEOUT 1
|
||||
#ifdef SLEEP_TEST_TIMEOUT
|
||||
static int sleep_ticks;
|
||||
void wakeup_counter0_set(int ticks);
|
||||
#endif
|
||||
|
||||
static void save_core_regs(void)
|
||||
{
|
||||
|
@ -105,31 +79,45 @@ static void save_core_regs(void)
|
|||
sleep_uart0_linectl = au_readl(UART0_ADDR + UART_LCR);
|
||||
sleep_uart0_clkdiv = au_readl(UART0_ADDR + UART_CLK);
|
||||
sleep_uart0_enable = au_readl(UART0_ADDR + UART_MOD_CNTRL);
|
||||
au_sync();
|
||||
|
||||
#ifndef CONFIG_SOC_AU1200
|
||||
/* Shutdown USB host/device. */
|
||||
sleep_usbhost_enable = au_readl(USB_HOST_CONFIG);
|
||||
sleep_usb[0] = au_readl(USB_HOST_CONFIG);
|
||||
|
||||
/* There appears to be some undocumented reset register.... */
|
||||
au_writel(0, 0xb0100004); au_sync();
|
||||
au_writel(0, USB_HOST_CONFIG); au_sync();
|
||||
au_writel(0, 0xb0100004);
|
||||
au_sync();
|
||||
au_writel(0, USB_HOST_CONFIG);
|
||||
au_sync();
|
||||
|
||||
sleep_usbdev_enable = au_readl(USBD_ENABLE);
|
||||
au_writel(0, USBD_ENABLE); au_sync();
|
||||
sleep_usb[1] = au_readl(USBD_ENABLE);
|
||||
au_writel(0, USBD_ENABLE);
|
||||
au_sync();
|
||||
|
||||
#else /* AU1200 */
|
||||
|
||||
/* enable access to OTG mmio so we can save OTG CAP/MUX.
|
||||
* FIXME: write an OTG driver and move this stuff there!
|
||||
*/
|
||||
au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
|
||||
au_sync();
|
||||
sleep_usb[0] = au_readl(0xb4020020); /* OTG_CAP */
|
||||
sleep_usb[1] = au_readl(0xb4020024); /* OTG_MUX */
|
||||
#endif
|
||||
|
||||
/* Save interrupt controller state. */
|
||||
save_au1xxx_intctl();
|
||||
|
||||
/* Clocks and PLLs. */
|
||||
sleep_aux_pll_cntrl = au_readl(SYS_AUXPLL);
|
||||
sleep_sys_clocks[0] = au_readl(SYS_FREQCTRL0);
|
||||
sleep_sys_clocks[1] = au_readl(SYS_FREQCTRL1);
|
||||
sleep_sys_clocks[2] = au_readl(SYS_CLKSRC);
|
||||
sleep_sys_clocks[3] = au_readl(SYS_CPUPLL);
|
||||
sleep_sys_clocks[4] = au_readl(SYS_AUXPLL);
|
||||
|
||||
/*
|
||||
* We don't really need to do this one, but unless we
|
||||
* write it again it won't have a valid value if we
|
||||
* happen to read it.
|
||||
*/
|
||||
sleep_cpu_pll_cntrl = au_readl(SYS_CPUPLL);
|
||||
|
||||
sleep_pin_function = au_readl(SYS_PINFUNC);
|
||||
/* pin mux config */
|
||||
sleep_sys_pinfunc = au_readl(SYS_PINFUNC);
|
||||
|
||||
/* Save the static memory controller configuration. */
|
||||
sleep_static_memctlr[0][0] = au_readl(MEM_STCFG0);
|
||||
|
@ -144,16 +132,45 @@ static void save_core_regs(void)
|
|||
sleep_static_memctlr[3][0] = au_readl(MEM_STCFG3);
|
||||
sleep_static_memctlr[3][1] = au_readl(MEM_STTIME3);
|
||||
sleep_static_memctlr[3][2] = au_readl(MEM_STADDR3);
|
||||
|
||||
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
|
||||
au1xxx_dbdma_suspend();
|
||||
#endif
|
||||
}
|
||||
|
||||
static void restore_core_regs(void)
|
||||
{
|
||||
extern void restore_au1xxx_intctl(void);
|
||||
extern void wakeup_counter0_adjust(void);
|
||||
/* restore clock configuration. Writing CPUPLL last will
|
||||
* stall a bit and stabilize other clocks (unless this is
|
||||
* one of those Au1000 with a write-only PLL, where we dont
|
||||
* have a valid value)
|
||||
*/
|
||||
au_writel(sleep_sys_clocks[0], SYS_FREQCTRL0);
|
||||
au_writel(sleep_sys_clocks[1], SYS_FREQCTRL1);
|
||||
au_writel(sleep_sys_clocks[2], SYS_CLKSRC);
|
||||
au_writel(sleep_sys_clocks[4], SYS_AUXPLL);
|
||||
if (!au1xxx_cpu_has_pll_wo())
|
||||
au_writel(sleep_sys_clocks[3], SYS_CPUPLL);
|
||||
au_sync();
|
||||
|
||||
au_writel(sleep_aux_pll_cntrl, SYS_AUXPLL); au_sync();
|
||||
au_writel(sleep_cpu_pll_cntrl, SYS_CPUPLL); au_sync();
|
||||
au_writel(sleep_pin_function, SYS_PINFUNC); au_sync();
|
||||
au_writel(sleep_sys_pinfunc, SYS_PINFUNC);
|
||||
au_sync();
|
||||
|
||||
#ifndef CONFIG_SOC_AU1200
|
||||
au_writel(sleep_usb[0], USB_HOST_CONFIG);
|
||||
au_writel(sleep_usb[1], USBD_ENABLE);
|
||||
au_sync();
|
||||
#else
|
||||
/* enable accces to OTG memory */
|
||||
au_writel(au_readl(USB_MSR_BASE + 4) | (1 << 6), USB_MSR_BASE + 4);
|
||||
au_sync();
|
||||
|
||||
/* restore OTG caps and port mux. */
|
||||
au_writel(sleep_usb[0], 0xb4020020 + 0); /* OTG_CAP */
|
||||
au_sync();
|
||||
au_writel(sleep_usb[1], 0xb4020020 + 4); /* OTG_MUX */
|
||||
au_sync();
|
||||
#endif
|
||||
|
||||
/* Restore the static memory controller configuration. */
|
||||
au_writel(sleep_static_memctlr[0][0], MEM_STCFG0);
|
||||
|
@ -184,282 +201,17 @@ static void restore_core_regs(void)
|
|||
}
|
||||
|
||||
restore_au1xxx_intctl();
|
||||
wakeup_counter0_adjust();
|
||||
|
||||
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
|
||||
au1xxx_dbdma_resume();
|
||||
#endif
|
||||
}
|
||||
|
||||
unsigned long suspend_mode;
|
||||
|
||||
void wakeup_from_suspend(void)
|
||||
void au_sleep(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();
|
||||
|
||||
flush_cache_all();
|
||||
|
||||
/**
|
||||
** The code below is all system dependent and we should probably
|
||||
** have a function call out of here to set this up. You need
|
||||
** to configure the GPIO or timer interrupts that will bring
|
||||
** you out of sleep.
|
||||
** For testing, the TOY counter wakeup is useful.
|
||||
**/
|
||||
#if 0
|
||||
au_writel(au_readl(SYS_PINSTATERD) & ~(1 << 11), SYS_PINSTATERD);
|
||||
|
||||
/* GPIO 6 can cause a wake up event */
|
||||
wakeup = au_readl(SYS_WAKEMSK);
|
||||
wakeup &= ~(1 << 8); /* turn off match20 wakeup */
|
||||
wakeup |= 1 << 6; /* turn on GPIO 6 wakeup */
|
||||
#else
|
||||
/* For testing, allow match20 to wake us up. */
|
||||
#ifdef SLEEP_TEST_TIMEOUT
|
||||
wakeup_counter0_set(sleep_ticks);
|
||||
#endif
|
||||
wakeup = 1 << 8; /* turn on match20 wakeup */
|
||||
wakeup = 0;
|
||||
#endif
|
||||
au_writel(1, SYS_WAKESRC); /* clear cause */
|
||||
au_sync();
|
||||
au_writel(wakeup, SYS_WAKEMSK);
|
||||
au_sync();
|
||||
|
||||
save_and_sleep();
|
||||
|
||||
/*
|
||||
* After a wakeup, the cpu vectors back to 0x1fc00000, so
|
||||
* it's up to the boot code to get us back here.
|
||||
*/
|
||||
au1xxx_save_and_sleep();
|
||||
restore_core_regs();
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pm_do_sleep(ctl_table *ctl, int write, struct file *file,
|
||||
void __user *buffer, size_t *len, loff_t *ppos)
|
||||
{
|
||||
#ifdef SLEEP_TEST_TIMEOUT
|
||||
#define TMPBUFLEN2 16
|
||||
char buf[TMPBUFLEN2], *p;
|
||||
#endif
|
||||
|
||||
if (!write)
|
||||
*len = 0;
|
||||
else {
|
||||
#ifdef SLEEP_TEST_TIMEOUT
|
||||
if (*len > TMPBUFLEN2 - 1)
|
||||
return -EFAULT;
|
||||
if (copy_from_user(buf, buffer, *len))
|
||||
return -EFAULT;
|
||||
buf[*len] = 0;
|
||||
p = buf;
|
||||
sleep_ticks = simple_strtoul(p, &p, 0);
|
||||
#endif
|
||||
|
||||
au_sleep();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pm_do_freq(ctl_table *ctl, int write, struct file *file,
|
||||
void __user *buffer, size_t *len, loff_t *ppos)
|
||||
{
|
||||
int retval = 0, i;
|
||||
unsigned long val, pll;
|
||||
#define TMPBUFLEN 64
|
||||
#define MAX_CPU_FREQ 396
|
||||
char buf[TMPBUFLEN], *p;
|
||||
unsigned long flags, intc0_mask, intc1_mask;
|
||||
unsigned long old_baud_base, old_cpu_freq, old_clk, old_refresh;
|
||||
unsigned long new_baud_base, new_cpu_freq, new_clk, new_refresh;
|
||||
unsigned long baud_rate;
|
||||
|
||||
spin_lock_irqsave(&pm_lock, flags);
|
||||
if (!write)
|
||||
*len = 0;
|
||||
else {
|
||||
/* Parse the new frequency */
|
||||
if (*len > TMPBUFLEN - 1) {
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
return -EFAULT;
|
||||
}
|
||||
if (copy_from_user(buf, buffer, *len)) {
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
return -EFAULT;
|
||||
}
|
||||
buf[*len] = 0;
|
||||
p = buf;
|
||||
val = simple_strtoul(p, &p, 0);
|
||||
if (val > MAX_CPU_FREQ) {
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
pll = val / 12;
|
||||
if ((pll > 33) || (pll < 7)) { /* 396 MHz max, 84 MHz min */
|
||||
/* Revisit this for higher speed CPUs */
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
old_baud_base = get_au1x00_uart_baud_base();
|
||||
old_cpu_freq = get_au1x00_speed();
|
||||
|
||||
new_cpu_freq = pll * 12 * 1000000;
|
||||
new_baud_base = (new_cpu_freq / (2 * ((int)(au_readl(SYS_POWERCTRL)
|
||||
& 0x03) + 2) * 16));
|
||||
set_au1x00_speed(new_cpu_freq);
|
||||
set_au1x00_uart_baud_base(new_baud_base);
|
||||
|
||||
old_refresh = au_readl(MEM_SDREFCFG) & 0x1ffffff;
|
||||
new_refresh = ((old_refresh * new_cpu_freq) / old_cpu_freq) |
|
||||
(au_readl(MEM_SDREFCFG) & ~0x1ffffff);
|
||||
|
||||
au_writel(pll, SYS_CPUPLL);
|
||||
au_sync_delay(1);
|
||||
au_writel(new_refresh, MEM_SDREFCFG);
|
||||
au_sync_delay(1);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
if (au_readl(UART_BASE + UART_MOD_CNTRL +
|
||||
i * 0x00100000) == 3) {
|
||||
old_clk = au_readl(UART_BASE + UART_CLK +
|
||||
i * 0x00100000);
|
||||
baud_rate = old_baud_base / old_clk;
|
||||
/*
|
||||
* We won't get an exact baud rate and the error
|
||||
* could be significant enough that our new
|
||||
* calculation will result in a clock that will
|
||||
* give us a baud rate that's too far off from
|
||||
* what we really want.
|
||||
*/
|
||||
if (baud_rate > 100000)
|
||||
baud_rate = 115200;
|
||||
else if (baud_rate > 50000)
|
||||
baud_rate = 57600;
|
||||
else if (baud_rate > 30000)
|
||||
baud_rate = 38400;
|
||||
else if (baud_rate > 17000)
|
||||
baud_rate = 19200;
|
||||
else
|
||||
baud_rate = 9600;
|
||||
new_clk = new_baud_base / baud_rate;
|
||||
au_writel(new_clk, UART_BASE + UART_CLK +
|
||||
i * 0x00100000);
|
||||
au_sync_delay(10);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* We don't want _any_ interrupts other than match20. Otherwise our
|
||||
* au1000_calibrate_delay() calculation will be off, potentially a lot.
|
||||
*/
|
||||
intc0_mask = save_local_and_disable(0);
|
||||
intc1_mask = save_local_and_disable(1);
|
||||
local_enable_irq(AU1000_TOY_MATCH2_INT);
|
||||
spin_unlock_irqrestore(&pm_lock, flags);
|
||||
au1000_calibrate_delay();
|
||||
restore_local_and_enable(0, intc0_mask);
|
||||
restore_local_and_enable(1, intc1_mask);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
static struct ctl_table pm_table[] = {
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "sleep",
|
||||
.data = NULL,
|
||||
.maxlen = 0,
|
||||
.mode = 0600,
|
||||
.proc_handler = &pm_do_sleep
|
||||
},
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "freq",
|
||||
.data = NULL,
|
||||
.maxlen = 0,
|
||||
.mode = 0600,
|
||||
.proc_handler = &pm_do_freq
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct ctl_table pm_dir_table[] = {
|
||||
{
|
||||
.ctl_name = CTL_UNNUMBERED,
|
||||
.procname = "pm",
|
||||
.mode = 0555,
|
||||
.child = pm_table
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize power interface
|
||||
*/
|
||||
static int __init pm_init(void)
|
||||
{
|
||||
register_sysctl_table(pm_dir_table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(pm_init);
|
||||
|
||||
/*
|
||||
* This is right out of init/main.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is the number of bits of precision for the loops_per_jiffy.
|
||||
* Each bit takes on average 1.5/HZ seconds. This (like the original)
|
||||
* is a little better than 1%.
|
||||
*/
|
||||
#define LPS_PREC 8
|
||||
|
||||
static void au1000_calibrate_delay(void)
|
||||
{
|
||||
unsigned long ticks, loopbit;
|
||||
int lps_precision = LPS_PREC;
|
||||
|
||||
loops_per_jiffy = 1 << 12;
|
||||
|
||||
while (loops_per_jiffy <<= 1) {
|
||||
/* Wait for "start of" clock tick */
|
||||
ticks = jiffies;
|
||||
while (ticks == jiffies)
|
||||
/* nothing */ ;
|
||||
/* Go ... */
|
||||
ticks = jiffies;
|
||||
__delay(loops_per_jiffy);
|
||||
ticks = jiffies - ticks;
|
||||
if (ticks)
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Do a binary approximation to get loops_per_jiffy set to be equal
|
||||
* one clock (up to lps_precision bits)
|
||||
*/
|
||||
loops_per_jiffy >>= 1;
|
||||
loopbit = loops_per_jiffy;
|
||||
while (lps_precision-- && (loopbit >>= 1)) {
|
||||
loops_per_jiffy |= loopbit;
|
||||
ticks = jiffies;
|
||||
while (ticks == jiffies);
|
||||
ticks = jiffies;
|
||||
__delay(loops_per_jiffy);
|
||||
if (jiffies != ticks) /* longer than 1 tick */
|
||||
loops_per_jiffy &= ~loopbit;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_PM */
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
extern int au_sleep(void);
|
||||
|
||||
void au1000_restart(char *command)
|
||||
{
|
||||
/* Set all integrated peripherals to disabled states */
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <asm/time.h>
|
||||
|
||||
#include <au1000.h>
|
||||
#include <prom.h>
|
||||
|
||||
extern void __init board_setup(void);
|
||||
extern void au1000_restart(char *);
|
||||
|
@ -45,80 +44,34 @@ extern void set_cpuspec(void);
|
|||
|
||||
void __init plat_mem_setup(void)
|
||||
{
|
||||
struct cpu_spec *sp;
|
||||
char *argptr;
|
||||
unsigned long prid, cpufreq, bclk;
|
||||
unsigned long est_freq;
|
||||
|
||||
set_cpuspec();
|
||||
sp = cur_cpu_spec[0];
|
||||
/* determine core clock */
|
||||
est_freq = au1xxx_calc_clock();
|
||||
est_freq += 5000; /* round */
|
||||
est_freq -= est_freq % 10000;
|
||||
printk(KERN_INFO "(PRId %08x) @ %lu.%02lu MHz\n", read_c0_prid(),
|
||||
est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
|
||||
|
||||
_machine_restart = au1000_restart;
|
||||
_machine_halt = au1000_halt;
|
||||
pm_power_off = au1000_power_off;
|
||||
|
||||
board_setup(); /* board specific setup */
|
||||
|
||||
prid = read_c0_prid();
|
||||
if (sp->cpu_pll_wo)
|
||||
#ifdef CONFIG_SOC_AU1000_FREQUENCY
|
||||
cpufreq = CONFIG_SOC_AU1000_FREQUENCY / 1000000;
|
||||
#else
|
||||
cpufreq = 396;
|
||||
#endif
|
||||
else
|
||||
cpufreq = (au_readl(SYS_CPUPLL) & 0x3F) * 12;
|
||||
printk(KERN_INFO "(PRID %08lx) @ %ld MHz\n", prid, cpufreq);
|
||||
|
||||
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)
|
||||
if (au1xxx_cpu_needs_config_od())
|
||||
/* Various early Au1xx0 errata corrected by this */
|
||||
set_c0_config(1 << 19); /* Set Config[OD] */
|
||||
else
|
||||
/* Clear to obtain best system bus performance */
|
||||
clear_c0_config(1 << 19); /* Clear Config[OD] */
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB_AU1100
|
||||
argptr = strstr(argptr, "video=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
/* default panel */
|
||||
/*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
|
||||
/* au1000 does not support vra, au1500 and au1100 do */
|
||||
strcat(argptr, " au1000_audio=vra");
|
||||
argptr = prom_getcmdline();
|
||||
#endif
|
||||
_machine_restart = au1000_restart;
|
||||
_machine_halt = au1000_halt;
|
||||
pm_power_off = au1000_power_off;
|
||||
|
||||
/* IO/MEM resources. */
|
||||
set_io_port_base(0);
|
||||
ioport_resource.start = IOPORT_RESOURCE_START;
|
||||
ioport_resource.end = IOPORT_RESOURCE_END;
|
||||
iomem_resource.start = IOMEM_RESOURCE_START;
|
||||
iomem_resource.end = IOMEM_RESOURCE_END;
|
||||
|
||||
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_E0S);
|
||||
au_writel(SYS_CNTRL_E0 | SYS_CNTRL_EN0, SYS_COUNTER_CNTRL);
|
||||
au_sync();
|
||||
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T0S);
|
||||
au_writel(0, SYS_TOYTRIM);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_64BIT_PHYS_ADDR)
|
||||
|
|
|
@ -15,16 +15,17 @@
|
|||
#include <asm/regdef.h>
|
||||
#include <asm/stackframe.h>
|
||||
|
||||
.extern __flush_cache_all
|
||||
|
||||
.text
|
||||
.set macro
|
||||
.set noreorder
|
||||
.set noat
|
||||
.align 5
|
||||
|
||||
/* Save all of the processor general registers and go to sleep.
|
||||
* A wakeup condition will get us back here to restore the registers.
|
||||
*/
|
||||
LEAF(save_and_sleep)
|
||||
|
||||
LEAF(au1xxx_save_and_sleep)
|
||||
subu sp, PT_SIZE
|
||||
sw $1, PT_R1(sp)
|
||||
sw $2, PT_R2(sp)
|
||||
|
@ -33,14 +34,6 @@ LEAF(save_and_sleep)
|
|||
sw $5, PT_R5(sp)
|
||||
sw $6, PT_R6(sp)
|
||||
sw $7, PT_R7(sp)
|
||||
sw $8, PT_R8(sp)
|
||||
sw $9, PT_R9(sp)
|
||||
sw $10, PT_R10(sp)
|
||||
sw $11, PT_R11(sp)
|
||||
sw $12, PT_R12(sp)
|
||||
sw $13, PT_R13(sp)
|
||||
sw $14, PT_R14(sp)
|
||||
sw $15, PT_R15(sp)
|
||||
sw $16, PT_R16(sp)
|
||||
sw $17, PT_R17(sp)
|
||||
sw $18, PT_R18(sp)
|
||||
|
@ -49,12 +42,9 @@ LEAF(save_and_sleep)
|
|||
sw $21, PT_R21(sp)
|
||||
sw $22, PT_R22(sp)
|
||||
sw $23, PT_R23(sp)
|
||||
sw $24, PT_R24(sp)
|
||||
sw $25, PT_R25(sp)
|
||||
sw $26, PT_R26(sp)
|
||||
sw $27, PT_R27(sp)
|
||||
sw $28, PT_R28(sp)
|
||||
sw $29, PT_R29(sp)
|
||||
sw $30, PT_R30(sp)
|
||||
sw $31, PT_R31(sp)
|
||||
mfc0 k0, CP0_STATUS
|
||||
|
@ -66,20 +56,26 @@ LEAF(save_and_sleep)
|
|||
mfc0 k0, CP0_CONFIG
|
||||
sw k0, 0x14(sp)
|
||||
|
||||
/* flush caches to make sure context is in memory */
|
||||
la t1, __flush_cache_all
|
||||
lw t0, 0(t1)
|
||||
jalr t0
|
||||
nop
|
||||
|
||||
/* Now set up the scratch registers so the boot rom will
|
||||
* return to this point upon wakeup.
|
||||
* sys_scratch0 : SP
|
||||
* sys_scratch1 : RA
|
||||
*/
|
||||
la k0, 1f
|
||||
lui k1, 0xb190
|
||||
ori k1, 0x18
|
||||
sw sp, 0(k1)
|
||||
ori k1, 0x1c
|
||||
sw k0, 0(k1)
|
||||
lui t3, 0xb190 /* sys_xxx */
|
||||
sw sp, 0x0018(t3)
|
||||
la k0, 3f /* resume path */
|
||||
sw k0, 0x001c(t3)
|
||||
|
||||
/* Put SDRAM into self refresh. Preload instructions into cache,
|
||||
* issue a precharge, then auto refresh, then sleep commands to it.
|
||||
/* Put SDRAM into self refresh: Preload instructions into cache,
|
||||
* issue a precharge, auto/self refresh, then sleep commands to it.
|
||||
*/
|
||||
la t0, sdsleep
|
||||
la t0, 1f
|
||||
.set mips3
|
||||
cache 0x14, 0(t0)
|
||||
cache 0x14, 32(t0)
|
||||
|
@ -87,24 +83,57 @@ LEAF(save_and_sleep)
|
|||
cache 0x14, 96(t0)
|
||||
.set mips0
|
||||
|
||||
sdsleep:
|
||||
lui k0, 0xb400
|
||||
sw zero, 0x001c(k0) /* Precharge */
|
||||
sw zero, 0x0020(k0) /* Auto refresh */
|
||||
sw zero, 0x0030(k0) /* SDRAM sleep */
|
||||
1: lui a0, 0xb400 /* mem_xxx */
|
||||
#if defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100) || \
|
||||
defined(CONFIG_SOC_AU1500)
|
||||
sw zero, 0x001c(a0) /* Precharge */
|
||||
sync
|
||||
sw zero, 0x0020(a0) /* Auto Refresh */
|
||||
sync
|
||||
sw zero, 0x0030(a0) /* Sleep */
|
||||
sync
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOC_AU1550) || defined(CONFIG_SOC_AU1200)
|
||||
sw zero, 0x08c0(a0) /* Precharge */
|
||||
sync
|
||||
sw zero, 0x08d0(a0) /* Self Refresh */
|
||||
sync
|
||||
|
||||
lui k1, 0xb190
|
||||
sw zero, 0x0078(k1) /* get ready to sleep */
|
||||
/* wait for sdram to enter self-refresh mode */
|
||||
lui t0, 0x0100
|
||||
2: lw t1, 0x0850(a0) /* mem_sdstat */
|
||||
and t2, t1, t0
|
||||
beq t2, zero, 2b
|
||||
nop
|
||||
|
||||
/* disable SDRAM clocks */
|
||||
lui t0, 0xcfff
|
||||
ori t0, t0, 0xffff
|
||||
lw t1, 0x0840(a0) /* mem_sdconfiga */
|
||||
and t1, t0, t1 /* clear CE[1:0] */
|
||||
sw t1, 0x0840(a0) /* mem_sdconfiga */
|
||||
sync
|
||||
sw zero, 0x007c(k1) /* Put processor to sleep */
|
||||
#endif
|
||||
|
||||
/* put power supply and processor to sleep */
|
||||
sw zero, 0x0078(t3) /* sys_slppwr */
|
||||
sync
|
||||
sw zero, 0x007c(t3) /* sys_sleep */
|
||||
sync
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
/* This is where we return upon wakeup.
|
||||
* Reload all of the registers and return.
|
||||
*/
|
||||
1: nop
|
||||
lw k0, 0x20(sp)
|
||||
3: lw k0, 0x20(sp)
|
||||
mtc0 k0, CP0_STATUS
|
||||
lw k0, 0x1c(sp)
|
||||
mtc0 k0, CP0_CONTEXT
|
||||
|
@ -113,10 +142,11 @@ sdsleep:
|
|||
lw k0, 0x14(sp)
|
||||
mtc0 k0, CP0_CONFIG
|
||||
|
||||
/* We need to catch the ealry Alchemy SOCs with
|
||||
/* We need to catch the early Alchemy SOCs with
|
||||
* the write-only Config[OD] bit and set it back to one...
|
||||
*/
|
||||
jal au1x00_fixup_config_od
|
||||
nop
|
||||
lw $1, PT_R1(sp)
|
||||
lw $2, PT_R2(sp)
|
||||
lw $3, PT_R3(sp)
|
||||
|
@ -124,14 +154,6 @@ sdsleep:
|
|||
lw $5, PT_R5(sp)
|
||||
lw $6, PT_R6(sp)
|
||||
lw $7, PT_R7(sp)
|
||||
lw $8, PT_R8(sp)
|
||||
lw $9, PT_R9(sp)
|
||||
lw $10, PT_R10(sp)
|
||||
lw $11, PT_R11(sp)
|
||||
lw $12, PT_R12(sp)
|
||||
lw $13, PT_R13(sp)
|
||||
lw $14, PT_R14(sp)
|
||||
lw $15, PT_R15(sp)
|
||||
lw $16, PT_R16(sp)
|
||||
lw $17, PT_R17(sp)
|
||||
lw $18, PT_R18(sp)
|
||||
|
@ -140,15 +162,11 @@ sdsleep:
|
|||
lw $21, PT_R21(sp)
|
||||
lw $22, PT_R22(sp)
|
||||
lw $23, PT_R23(sp)
|
||||
lw $24, PT_R24(sp)
|
||||
lw $25, PT_R25(sp)
|
||||
lw $26, PT_R26(sp)
|
||||
lw $27, PT_R27(sp)
|
||||
lw $28, PT_R28(sp)
|
||||
lw $29, PT_R29(sp)
|
||||
lw $30, PT_R30(sp)
|
||||
lw $31, PT_R31(sp)
|
||||
addiu sp, PT_SIZE
|
||||
|
||||
jr ra
|
||||
END(save_and_sleep)
|
||||
addiu sp, PT_SIZE
|
||||
END(au1xxx_save_and_sleep)
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* Copyright (C) 2008 Manuel Lauss <mano@roarinelk.homelinux.net>
|
||||
*
|
||||
* Previous incarnations were:
|
||||
* Copyright (C) 2001, 2006, 2008 MontaVista Software, <source@mvista.com>
|
||||
* Copied and modified Carsten Langgaard's time.c
|
||||
*
|
||||
|
@ -23,244 +25,141 @@
|
|||
*
|
||||
* ########################################################################
|
||||
*
|
||||
* Setting up the clock on the MIPS boards.
|
||||
*
|
||||
* We provide the clock interrupt processing and the timer offset compute
|
||||
* functions. If CONFIG_PM is selected, we also ensure the 32KHz timer is
|
||||
* available. -- Dan
|
||||
* Clocksource/event using the 32.768kHz-clocked Counter1 ('RTC' in the
|
||||
* databooks). Firmware/Board init code must enable the counters in the
|
||||
* counter control register, otherwise the CP0 counter clocksource/event
|
||||
* will be installed instead (and use of 'wait' instruction is prohibited).
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/clockchips.h>
|
||||
#include <linux/clocksource.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <asm/mipsregs.h>
|
||||
#include <asm/time.h>
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
static int no_au1xxx_32khz;
|
||||
/* 32kHz clock enabled and detected */
|
||||
#define CNTR_OK (SYS_CNTRL_E0 | SYS_CNTRL_32S)
|
||||
|
||||
extern int allow_au1k_wait; /* default off for CP0 Counter */
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
#if HZ < 100 || HZ > 1000
|
||||
#error "unsupported HZ value! Must be in [100,1000]"
|
||||
#endif
|
||||
#define MATCH20_INC (328 * 100 / HZ) /* magic number 328 is for HZ=100... */
|
||||
static unsigned long last_pc0, last_match20;
|
||||
#endif
|
||||
|
||||
static DEFINE_SPINLOCK(time_lock);
|
||||
|
||||
unsigned long wtimer;
|
||||
|
||||
#ifdef CONFIG_PM
|
||||
static irqreturn_t counter0_irq(int irq, void *dev_id)
|
||||
static cycle_t au1x_counter1_read(void)
|
||||
{
|
||||
unsigned long pc0;
|
||||
int time_elapsed;
|
||||
static int jiffie_drift;
|
||||
|
||||
if (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20) {
|
||||
/* should never happen! */
|
||||
printk(KERN_WARNING "counter 0 w status error\n");
|
||||
return IRQ_NONE;
|
||||
return au_readl(SYS_RTCREAD);
|
||||
}
|
||||
|
||||
pc0 = au_readl(SYS_TOYREAD);
|
||||
if (pc0 < last_match20)
|
||||
/* counter overflowed */
|
||||
time_elapsed = (0xffffffff - last_match20) + pc0;
|
||||
else
|
||||
time_elapsed = pc0 - last_match20;
|
||||
static struct clocksource au1x_counter1_clocksource = {
|
||||
.name = "alchemy-counter1",
|
||||
.read = au1x_counter1_read,
|
||||
.mask = CLOCKSOURCE_MASK(32),
|
||||
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
||||
.rating = 100,
|
||||
};
|
||||
|
||||
while (time_elapsed > 0) {
|
||||
do_timer(1);
|
||||
#ifndef CONFIG_SMP
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
#endif
|
||||
time_elapsed -= MATCH20_INC;
|
||||
last_match20 += MATCH20_INC;
|
||||
jiffie_drift++;
|
||||
}
|
||||
|
||||
last_pc0 = pc0;
|
||||
au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
|
||||
static int au1x_rtcmatch2_set_next_event(unsigned long delta,
|
||||
struct clock_event_device *cd)
|
||||
{
|
||||
delta += au_readl(SYS_RTCREAD);
|
||||
/* wait for register access */
|
||||
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M21)
|
||||
;
|
||||
au_writel(delta, SYS_RTCMATCH2);
|
||||
au_sync();
|
||||
|
||||
/*
|
||||
* Our counter ticks at 10.009765625 ms/tick, we we're running
|
||||
* almost 10 uS too slow per tick.
|
||||
*/
|
||||
|
||||
if (jiffie_drift >= 999) {
|
||||
jiffie_drift -= 999;
|
||||
do_timer(1); /* increment jiffies by one */
|
||||
#ifndef CONFIG_SMP
|
||||
update_process_times(user_mode(get_irq_regs()));
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void au1x_rtcmatch2_set_mode(enum clock_event_mode mode,
|
||||
struct clock_event_device *cd)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
struct irqaction counter0_action = {
|
||||
.handler = counter0_irq,
|
||||
.flags = IRQF_DISABLED,
|
||||
.name = "alchemy-toy",
|
||||
.dev_id = NULL,
|
||||
static struct clock_event_device au1x_rtcmatch2_clockdev = {
|
||||
.name = "rtcmatch2",
|
||||
.features = CLOCK_EVT_FEAT_ONESHOT,
|
||||
.rating = 100,
|
||||
.irq = AU1000_RTC_MATCH2_INT,
|
||||
.set_next_event = au1x_rtcmatch2_set_next_event,
|
||||
.set_mode = au1x_rtcmatch2_set_mode,
|
||||
.cpumask = CPU_MASK_ALL,
|
||||
};
|
||||
|
||||
/* When we wakeup from sleep, we have to "catch up" on all of the
|
||||
* timer ticks we have missed.
|
||||
*/
|
||||
void wakeup_counter0_adjust(void)
|
||||
{
|
||||
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;
|
||||
}
|
||||
static struct irqaction au1x_rtcmatch2_irqaction = {
|
||||
.handler = au1x_rtcmatch2_irq,
|
||||
.flags = IRQF_DISABLED | IRQF_TIMER,
|
||||
.name = "timer",
|
||||
.dev_id = &au1x_rtcmatch2_clockdev,
|
||||
};
|
||||
|
||||
void __init plat_time_init(void)
|
||||
{
|
||||
unsigned int est_freq = calc_clock();
|
||||
struct clock_event_device *cd = &au1x_rtcmatch2_clockdev;
|
||||
unsigned long t;
|
||||
|
||||
est_freq += 5000; /* round */
|
||||
est_freq -= est_freq%10000;
|
||||
printk(KERN_INFO "CPU frequency %u.%02u MHz\n",
|
||||
est_freq / 1000000, ((est_freq % 1000000) * 100) / 1000000);
|
||||
set_au1x00_speed(est_freq);
|
||||
set_au1x00_lcd_clock(); /* program the LCD clock */
|
||||
|
||||
#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.
|
||||
/* Check if firmware (YAMON, ...) has enabled 32kHz and clock
|
||||
* has been detected. If so install the rtcmatch2 clocksource,
|
||||
* otherwise don't bother. Note that both bits being set is by
|
||||
* no means a definite guarantee that the counters actually work
|
||||
* (the 32S bit seems to be stuck set to 1 once a single clock-
|
||||
* edge is detected, hence the timeouts).
|
||||
*/
|
||||
if (no_au1xxx_32khz)
|
||||
printk(KERN_WARNING "WARNING: no 32KHz clock found.\n");
|
||||
else {
|
||||
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
|
||||
au_writel(0, SYS_TOYWRITE);
|
||||
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C0S);
|
||||
if (CNTR_OK != (au_readl(SYS_COUNTER_CNTRL) & CNTR_OK))
|
||||
goto cntr_err;
|
||||
|
||||
au_writel(au_readl(SYS_WAKEMSK) | (1 << 8), SYS_WAKEMSK);
|
||||
au_writel(~0, SYS_WAKESRC);
|
||||
/*
|
||||
* setup counter 1 (RTC) to tick at full speed
|
||||
*/
|
||||
t = 0xffffff;
|
||||
while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_T1S) && t--)
|
||||
asm volatile ("nop");
|
||||
if (!t)
|
||||
goto cntr_err;
|
||||
|
||||
au_writel(0, SYS_RTCTRIM); /* 32.768 kHz */
|
||||
au_sync();
|
||||
while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20);
|
||||
|
||||
/* Setup match20 to interrupt once every HZ */
|
||||
last_pc0 = last_match20 = au_readl(SYS_TOYREAD);
|
||||
au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2);
|
||||
t = 0xffffff;
|
||||
while ((au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_C1S) && t--)
|
||||
asm volatile ("nop");
|
||||
if (!t)
|
||||
goto cntr_err;
|
||||
au_writel(0, SYS_RTCWRITE);
|
||||
au_sync();
|
||||
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;
|
||||
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;
|
||||
|
||||
#endif
|
||||
cntr_err:
|
||||
/* counters unusable, use C0 counter */
|
||||
r4k_clockevent_init();
|
||||
init_r4k_clocksource();
|
||||
allow_au1k_wait = 0;
|
||||
}
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
/*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* PB1000 board setup
|
||||
*
|
||||
* Copyright 2001, 2008 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc. <source@mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License as published by the
|
||||
* Free Software Foundation; either version 2 of the License, or (at your
|
||||
* option) any later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
#include <prom.h>
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
#ifdef CONFIG_MIPS_BOSPORUS
|
||||
return "Alchemy Bosporus Gateway Reference";
|
||||
#else
|
||||
return "Alchemy Db1x00";
|
||||
#endif
|
||||
}
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
unsigned char *memsize_str;
|
||||
unsigned long memsize;
|
||||
|
||||
prom_argc = fw_arg0;
|
||||
prom_argv = (char **)fw_arg1;
|
||||
prom_envp = (char **)fw_arg2;
|
||||
|
||||
prom_init_cmdline();
|
||||
|
||||
memsize_str = prom_getenv("memsize");
|
||||
if (!memsize_str)
|
||||
memsize = 0x04000000;
|
||||
else
|
||||
strict_strtol(memsize_str, 0, &memsize);
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
18
arch/mips/alchemy/devboards/Makefile
Normal file
18
arch/mips/alchemy/devboards/Makefile
Normal 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/
|
|
@ -5,4 +5,4 @@
|
|||
# Makefile for the Alchemy Semiconductor DBAu1xx0 boards.
|
||||
#
|
||||
|
||||
lib-y := init.o board_setup.o irqmap.o
|
||||
obj-y := board_setup.o irqmap.o
|
|
@ -32,8 +32,20 @@
|
|||
#include <asm/mach-au1x00/au1000.h>
|
||||
#include <asm/mach-db1x00/db1x00.h>
|
||||
|
||||
#include <prom.h>
|
||||
|
||||
|
||||
static BCSR * const bcsr = (BCSR *)BCSR_KSEG1_ADDR;
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
#ifdef CONFIG_MIPS_BOSPORUS
|
||||
return "Alchemy Bosporus Gateway Reference";
|
||||
#else
|
||||
return "Alchemy Db1x00";
|
||||
#endif
|
||||
}
|
||||
|
||||
void board_reset(void)
|
||||
{
|
||||
/* Hit BCSR.SW_RESET[RESET] */
|
||||
|
@ -43,6 +55,31 @@ void board_reset(void)
|
|||
void __init board_setup(void)
|
||||
{
|
||||
u32 pin_func = 0;
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB_AU1100
|
||||
argptr = strstr(argptr, "video=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
/* default panel */
|
||||
/*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
|
||||
/* au1000 does not support vra, au1500 and au1100 do */
|
||||
strcat(argptr, " au1000_audio=vra");
|
||||
argptr = prom_getcmdline();
|
||||
#endif
|
||||
|
||||
/* Not valid for Au1550 */
|
||||
#if defined(CONFIG_IRDA) && \
|
|
@ -27,6 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
|
@ -66,21 +67,24 @@ struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
|||
|
||||
#ifndef CONFIG_MIPS_MIRAGE
|
||||
#ifdef CONFIG_MIPS_DB1550
|
||||
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
|
||||
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
|
||||
{ AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
|
||||
{ AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
|
||||
#else
|
||||
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 Fully_Interted# */
|
||||
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 STSCHG# */
|
||||
{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 0 IRQ# */
|
||||
{ AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 Fully_Interted# */
|
||||
{ AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 STSCHG# */
|
||||
{ AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 0 IRQ# */
|
||||
|
||||
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 Fully_Interted# */
|
||||
{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 STSCHG# */
|
||||
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 }, /* PCMCIA Card 1 IRQ# */
|
||||
{ AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 Fully_Interted# */
|
||||
{ AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 STSCHG# */
|
||||
{ AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card 1 IRQ# */
|
||||
#endif
|
||||
#else
|
||||
{ AU1000_GPIO_7, INTC_INT_RISE_EDGE, 0 }, /* touchscreen pen down */
|
||||
{ AU1000_GPIO_7, IRQF_TRIGGER_RISING, 0 }, /* touchscreen pen down */
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
}
|
|
@ -5,4 +5,4 @@
|
|||
# Makefile for the Alchemy Semiconductor Pb1000 board.
|
||||
#
|
||||
|
||||
lib-y := init.o board_setup.o irqmap.o
|
||||
obj-y := board_setup.o
|
|
@ -23,22 +23,48 @@
|
|||
* 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
#include <asm/mach-pb1x00/pb1000.h>
|
||||
#include <prom.h>
|
||||
|
||||
|
||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
||||
{ AU1000_GPIO_15, IRQF_TRIGGER_LOW, 0 },
|
||||
};
|
||||
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "Alchemy Pb1000";
|
||||
}
|
||||
|
||||
void board_reset(void)
|
||||
{
|
||||
}
|
||||
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
}
|
||||
|
||||
void __init board_setup(void)
|
||||
{
|
||||
u32 pin_func, static_cfg0;
|
||||
u32 sys_freqctrl, sys_clksrc;
|
||||
u32 prid = read_c0_prid();
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
char *argptr = prom_getcmdline();
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
|
||||
au_writel(8, SYS_AUXPLL);
|
||||
au_writel(0, SYS_PINSTATERD);
|
|
@ -5,4 +5,4 @@
|
|||
# Makefile for the Alchemy Semiconductor Pb1100 board.
|
||||
#
|
||||
|
||||
lib-y := init.o board_setup.o irqmap.o
|
||||
obj-y := board_setup.o
|
|
@ -25,19 +25,66 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
#include <asm/mach-pb1x00/pb1100.h>
|
||||
|
||||
#include <prom.h>
|
||||
|
||||
|
||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
||||
{ AU1000_GPIO_9, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card Fully_Inserted# */
|
||||
{ AU1000_GPIO_10, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card STSCHG# */
|
||||
{ AU1000_GPIO_11, IRQF_TRIGGER_LOW, 0 }, /* PCMCIA Card IRQ# */
|
||||
{ AU1000_GPIO_13, IRQF_TRIGGER_LOW, 0 }, /* DC_IRQ# */
|
||||
};
|
||||
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "Alchemy Pb1100";
|
||||
}
|
||||
|
||||
void board_reset(void)
|
||||
{
|
||||
/* Hit BCSR.RST_VDDI[SOFT_RESET] */
|
||||
au_writel(0x00000000, PB1100_RST_VDDI);
|
||||
}
|
||||
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
}
|
||||
|
||||
void __init board_setup(void)
|
||||
{
|
||||
volatile void __iomem *base = (volatile void __iomem *)0xac000000UL;
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB_AU1100
|
||||
argptr = strstr(argptr, "video=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
/* default panel */
|
||||
/*strcat(argptr, " video=au1100fb:panel:Sharp_320x240_16");*/
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
|
||||
/* au1000 does not support vra, au1500 and au1100 do */
|
||||
strcat(argptr, " au1000_audio=vra");
|
||||
argptr = prom_getcmdline();
|
||||
#endif
|
||||
|
||||
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
|
||||
au_writel(8, SYS_AUXPLL);
|
|
@ -2,7 +2,6 @@
|
|||
# Makefile for the Alchemy Semiconductor Pb1200/DBAu1200 boards.
|
||||
#
|
||||
|
||||
lib-y := init.o board_setup.o irqmap.o
|
||||
obj-y += platform.o
|
||||
obj-y := board_setup.o irqmap.o platform.o
|
||||
|
||||
EXTRA_CFLAGS += -Werror
|
|
@ -30,8 +30,11 @@
|
|||
#include <prom.h>
|
||||
#include <au1xxx.h>
|
||||
|
||||
extern void _board_init_irq(void);
|
||||
extern void (*board_init_irq)(void);
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "Alchemy Pb1200";
|
||||
}
|
||||
|
||||
void board_reset(void)
|
||||
{
|
||||
|
@ -41,7 +44,19 @@ void board_reset(void)
|
|||
|
||||
void __init board_setup(void)
|
||||
{
|
||||
char *argptr = NULL;
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
#ifdef CONFIG_FB_AU1200
|
||||
strcat(argptr, " video=au1200fb:panel:bs");
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
{
|
||||
|
@ -99,16 +114,6 @@ void __init board_setup(void)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FB_AU1200
|
||||
argptr = prom_getcmdline();
|
||||
#ifdef CONFIG_MIPS_PB1200
|
||||
strcat(argptr, " video=au1200fb:panel:bs");
|
||||
#endif
|
||||
#ifdef CONFIG_MIPS_DB1200
|
||||
strcat(argptr, " video=au1200fb:panel:bs");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The Pb1200 development board uses external MUX for PSC0 to
|
||||
* support SMB/SPI. bcsr->resets bit 12: 0=SMB 1=SPI
|
||||
|
@ -124,9 +129,6 @@ void __init board_setup(void)
|
|||
#ifdef CONFIG_MIPS_DB1200
|
||||
printk(KERN_INFO "AMD Alchemy Db1200 Board\n");
|
||||
#endif
|
||||
|
||||
/* Setup Pb1200 External Interrupt Controller */
|
||||
board_init_irq = _board_init_irq;
|
||||
}
|
||||
|
||||
int board_au1200fb_panel(void)
|
|
@ -40,91 +40,65 @@
|
|||
|
||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
||||
/* This is external interrupt cascade */
|
||||
{ AU1000_GPIO_7, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1000_GPIO_7, IRQF_TRIGGER_LOW, 0 },
|
||||
};
|
||||
|
||||
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
|
||||
|
||||
/*
|
||||
* Support for External interrupts on the Pb1200 Development platform.
|
||||
*/
|
||||
static volatile int pb1200_cascade_en;
|
||||
|
||||
irqreturn_t pb1200_cascade_handler(int irq, void *dev_id)
|
||||
static void pb1200_cascade_handler(unsigned int irq, struct irq_desc *d)
|
||||
{
|
||||
unsigned short bisr = bcsr->int_status;
|
||||
int extirq_nr = 0;
|
||||
|
||||
/* Clear all the edge interrupts. This has no effect on level. */
|
||||
bcsr->int_status = bisr;
|
||||
for ( ; bisr; bisr &= bisr - 1) {
|
||||
extirq_nr = PB1200_INT_BEGIN + __ffs(bisr);
|
||||
/* Ack and dispatch IRQ */
|
||||
do_IRQ(extirq_nr);
|
||||
for ( ; bisr; bisr &= bisr - 1)
|
||||
generic_handle_irq(PB1200_INT_BEGIN + __ffs(bisr));
|
||||
}
|
||||
|
||||
return IRQ_RETVAL(1);
|
||||
}
|
||||
|
||||
inline void pb1200_enable_irq(unsigned int irq_nr)
|
||||
{
|
||||
bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
}
|
||||
|
||||
inline void pb1200_disable_irq(unsigned int irq_nr)
|
||||
/* NOTE: both the enable and mask bits must be cleared, otherwise the
|
||||
* CPLD generates tons of spurious interrupts (at least on the DB1200).
|
||||
*/
|
||||
static void pb1200_mask_irq(unsigned int irq_nr)
|
||||
{
|
||||
bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
au_sync();
|
||||
}
|
||||
|
||||
static unsigned int pb1200_setup_cascade(void)
|
||||
static void pb1200_maskack_irq(unsigned int irq_nr)
|
||||
{
|
||||
return request_irq(AU1000_GPIO_7, &pb1200_cascade_handler,
|
||||
0, "Pb1200 Cascade", &pb1200_cascade_handler);
|
||||
bcsr->intclr_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
bcsr->intclr = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
bcsr->int_status = 1 << (irq_nr - PB1200_INT_BEGIN); /* ack */
|
||||
au_sync();
|
||||
}
|
||||
|
||||
static unsigned int pb1200_startup_irq(unsigned int irq)
|
||||
static void pb1200_unmask_irq(unsigned int irq_nr)
|
||||
{
|
||||
if (++pb1200_cascade_en == 1) {
|
||||
int res;
|
||||
|
||||
res = pb1200_setup_cascade();
|
||||
if (res)
|
||||
return res;
|
||||
bcsr->intset = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
bcsr->intset_mask = 1 << (irq_nr - PB1200_INT_BEGIN);
|
||||
au_sync();
|
||||
}
|
||||
|
||||
pb1200_enable_irq(irq);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pb1200_shutdown_irq(unsigned int irq)
|
||||
{
|
||||
pb1200_disable_irq(irq);
|
||||
if (--pb1200_cascade_en == 0)
|
||||
free_irq(AU1000_GPIO_7, &pb1200_cascade_handler);
|
||||
}
|
||||
|
||||
static struct irq_chip external_irq_type = {
|
||||
static struct irq_chip pb1200_cpld_irq_type = {
|
||||
#ifdef CONFIG_MIPS_PB1200
|
||||
.name = "Pb1200 Ext",
|
||||
#endif
|
||||
#ifdef CONFIG_MIPS_DB1200
|
||||
.name = "Db1200 Ext",
|
||||
#endif
|
||||
.startup = pb1200_startup_irq,
|
||||
.shutdown = pb1200_shutdown_irq,
|
||||
.ack = pb1200_disable_irq,
|
||||
.mask = pb1200_disable_irq,
|
||||
.mask_ack = pb1200_disable_irq,
|
||||
.unmask = pb1200_enable_irq,
|
||||
.mask = pb1200_mask_irq,
|
||||
.mask_ack = pb1200_maskack_irq,
|
||||
.unmask = pb1200_unmask_irq,
|
||||
};
|
||||
|
||||
void _board_init_irq(void)
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
unsigned int irq;
|
||||
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
|
||||
#ifdef CONFIG_MIPS_PB1200
|
||||
/* We have a problem with CPLD rev 3. */
|
||||
if (((bcsr->whoami & BCSR_WHOAMI_CPLD) >> 4) <= 3) {
|
||||
|
@ -146,15 +120,15 @@ void _board_init_irq(void)
|
|||
panic("Game over. Your score is 0.");
|
||||
}
|
||||
#endif
|
||||
/* mask & disable & ack all */
|
||||
bcsr->intclr_mask = 0xffff;
|
||||
bcsr->intclr = 0xffff;
|
||||
bcsr->int_status = 0xffff;
|
||||
au_sync();
|
||||
|
||||
for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++) {
|
||||
set_irq_chip_and_handler(irq, &external_irq_type,
|
||||
handle_level_irq);
|
||||
pb1200_disable_irq(irq);
|
||||
}
|
||||
for (irq = PB1200_INT_BEGIN; irq <= PB1200_INT_END; irq++)
|
||||
set_irq_chip_and_handler_name(irq, &pb1200_cpld_irq_type,
|
||||
handle_level_irq, "level");
|
||||
|
||||
/*
|
||||
* GPIO_7 can not be hooked here, so it is hooked upon first
|
||||
* request of any source attached to the cascade.
|
||||
*/
|
||||
set_irq_chained_handler(AU1000_GPIO_7, pb1200_cascade_handler);
|
||||
}
|
|
@ -5,4 +5,4 @@
|
|||
# Makefile for the Alchemy Semiconductor Pb1500 board.
|
||||
#
|
||||
|
||||
lib-y := init.o board_setup.o irqmap.o
|
||||
obj-y := board_setup.o
|
|
@ -25,20 +25,64 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
#include <asm/mach-pb1x00/pb1500.h>
|
||||
|
||||
#include <prom.h>
|
||||
|
||||
|
||||
char irq_tab_alchemy[][5] __initdata = {
|
||||
[12] = { -1, INTA, INTX, INTX, INTX }, /* IDSEL 12 - HPT370 */
|
||||
[13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot */
|
||||
};
|
||||
|
||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
||||
{ AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
|
||||
{ AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
|
||||
};
|
||||
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "Alchemy Pb1500";
|
||||
}
|
||||
|
||||
void board_reset(void)
|
||||
{
|
||||
/* Hit BCSR.RST_VDDI[SOFT_RESET] */
|
||||
au_writel(0x00000000, PB1500_RST_VDDI);
|
||||
}
|
||||
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
}
|
||||
|
||||
void __init board_setup(void)
|
||||
{
|
||||
u32 pin_func;
|
||||
u32 sys_freqctrl, sys_clksrc;
|
||||
char *argptr;
|
||||
|
||||
argptr = prom_getcmdline();
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SOUND_AU1X00) && !defined(CONFIG_SOC_AU1000)
|
||||
/* au1000 does not support vra, au1500 and au1100 do */
|
||||
strcat(argptr, " au1000_audio=vra");
|
||||
argptr = prom_getcmdline();
|
||||
#endif
|
||||
|
||||
sys_clksrc = sys_freqctrl = pin_func = 0;
|
||||
/* Set AUX clock to 12 MHz * 8 = 96 MHz */
|
|
@ -5,4 +5,4 @@
|
|||
# Makefile for the Alchemy Semiconductor Pb1550 board.
|
||||
#
|
||||
|
||||
lib-y := init.o board_setup.o irqmap.o
|
||||
obj-y := board_setup.o
|
|
@ -28,20 +28,54 @@
|
|||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
#include <linux/interrupt.h>
|
||||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
#include <asm/mach-pb1x00/pb1550.h>
|
||||
|
||||
#include <prom.h>
|
||||
|
||||
|
||||
char irq_tab_alchemy[][5] __initdata = {
|
||||
[12] = { -1, INTB, INTC, INTD, INTA }, /* IDSEL 12 - PCI slot 2 (left) */
|
||||
[13] = { -1, INTA, INTB, INTC, INTD }, /* IDSEL 13 - PCI slot 1 (right) */
|
||||
};
|
||||
|
||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
||||
{ AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
|
||||
};
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "Alchemy Pb1550";
|
||||
}
|
||||
|
||||
void board_reset(void)
|
||||
{
|
||||
/* Hit BCSR.SYSTEM[RESET] */
|
||||
au_writew(au_readw(0xAF00001C) & ~BCSR_SYSTEM_RESET, 0xAF00001C);
|
||||
}
|
||||
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
}
|
||||
|
||||
void __init board_setup(void)
|
||||
{
|
||||
u32 pin_func;
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
char *argptr;
|
||||
argptr = prom_getcmdline();
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable PSC1 SYNC for AC'97. Normaly done in audio driver,
|
||||
* but it is board specific code, so put it here.
|
229
arch/mips/alchemy/devboards/pm.c
Normal file
229
arch/mips/alchemy/devboards/pm.c
Normal 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);
|
|
@ -1,9 +1,9 @@
|
|||
/*
|
||||
* Common code used by all Alchemy develboards.
|
||||
*
|
||||
* BRIEF MODULE DESCRIPTION
|
||||
* Pb1550 board setup
|
||||
* Extracted from files which had this to say:
|
||||
*
|
||||
* Copyright 2001, 2008 MontaVista Software Inc.
|
||||
* Copyright 2000, 2008 MontaVista Software Inc.
|
||||
* Author: MontaVista Software, Inc. <source@mvista.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
|
@ -29,15 +29,19 @@
|
|||
|
||||
#include <linux/init.h>
|
||||
#include <linux/kernel.h>
|
||||
|
||||
#include <asm/bootinfo.h>
|
||||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
#include <prom.h>
|
||||
|
||||
const char *get_system_type(void)
|
||||
{
|
||||
return "Alchemy Pb1550";
|
||||
}
|
||||
#if defined(CONFIG_MIPS_PB1000) || defined(CONFIG_MIPS_DB1000) || \
|
||||
defined(CONFIG_MIPS_PB1100) || defined(CONFIG_MIPS_DB1100) || \
|
||||
defined(CONFIG_MIPS_PB1500) || defined(CONFIG_MIPS_DB1500) || \
|
||||
defined(CONFIG_MIPS_BOSPORUS) || defined(CONFIG_MIPS_MIRAGE)
|
||||
#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x04000000
|
||||
|
||||
#else /* Au1550/Au1200-based develboards */
|
||||
#define ALCHEMY_BOARD_DEFAULT_MEMSIZE 0x08000000
|
||||
#endif
|
||||
|
||||
void __init prom_init(void)
|
||||
{
|
||||
|
@ -51,8 +55,8 @@ void __init prom_init(void)
|
|||
prom_init_cmdline();
|
||||
memsize_str = prom_getenv("memsize");
|
||||
if (!memsize_str)
|
||||
memsize = 0x08000000;
|
||||
memsize = ALCHEMY_BOARD_DEFAULT_MEMSIZE;
|
||||
else
|
||||
strict_strtol(memsize_str, 0, &memsize);
|
||||
strict_strtoul(memsize_str, 0, &memsize);
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
|
@ -32,6 +32,8 @@
|
|||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
#include <prom.h>
|
||||
|
||||
extern int (*board_pci_idsel)(unsigned int devsel, int assert);
|
||||
int mtx1_pci_idsel(unsigned int devsel, int assert);
|
||||
|
||||
|
@ -43,6 +45,16 @@ void board_reset(void)
|
|||
|
||||
void __init board_setup(void)
|
||||
{
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
char *argptr;
|
||||
argptr = prom_getcmdline();
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
|
||||
/* Enable USB power switch */
|
||||
au_writel(au_readl(GPIO2_DIR) | 0x10, GPIO2_DIR);
|
||||
|
|
|
@ -55,6 +55,6 @@ void __init prom_init(void)
|
|||
if (!memsize_str)
|
||||
memsize = 0x04000000;
|
||||
else
|
||||
strict_strtol(memsize_str, 0, &memsize);
|
||||
strict_strtoul(memsize_str, 0, &memsize);
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
char irq_tab_alchemy[][5] __initdata = {
|
||||
|
@ -42,11 +42,15 @@ char irq_tab_alchemy[][5] __initdata = {
|
|||
};
|
||||
|
||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
||||
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
|
||||
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
|
||||
{ AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
|
||||
};
|
||||
|
||||
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
|
||||
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
|
@ -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);
|
|
@ -28,6 +28,8 @@
|
|||
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
#include <prom.h>
|
||||
|
||||
void board_reset(void)
|
||||
{
|
||||
/* Hit BCSR.SYSTEM_CONTROL[SW_RST] */
|
||||
|
@ -38,6 +40,16 @@ void __init board_setup(void)
|
|||
{
|
||||
u32 pin_func;
|
||||
|
||||
#ifdef CONFIG_SERIAL_8250_CONSOLE
|
||||
char *argptr;
|
||||
argptr = prom_getcmdline();
|
||||
argptr = strstr(argptr, "console=");
|
||||
if (argptr == NULL) {
|
||||
argptr = prom_getcmdline();
|
||||
strcat(argptr, " console=ttyS0,115200");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Set multiple use pins (UART3/GPIO) to UART (it's used as UART too) */
|
||||
pin_func = au_readl(SYS_PINFUNC) & ~SYS_PF_UR3;
|
||||
pin_func |= SYS_PF_UR3;
|
||||
|
|
|
@ -53,6 +53,6 @@ void __init prom_init(void)
|
|||
if (!memsize_str)
|
||||
memsize = 0x04000000;
|
||||
else
|
||||
strict_strtol(memsize_str, 0, &memsize);
|
||||
strict_strtoul(memsize_str, 0, &memsize);
|
||||
add_memory_region(0, memsize, BOOT_MEM_RAM);
|
||||
}
|
||||
|
|
|
@ -27,23 +27,26 @@
|
|||
*/
|
||||
|
||||
#include <linux/init.h>
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/mach-au1x00/au1000.h>
|
||||
|
||||
struct au1xxx_irqmap __initdata au1xxx_irq_map[] = {
|
||||
{ AU1500_GPIO_204, INTC_INT_HIGH_LEVEL, 0 },
|
||||
{ AU1500_GPIO_201, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_202, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_203, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_205, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_207, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1500_GPIO_204, IRQF_TRIGGER_HIGH, 0 },
|
||||
{ AU1500_GPIO_201, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_202, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_203, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_205, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1500_GPIO_207, IRQF_TRIGGER_LOW, 0 },
|
||||
|
||||
{ AU1000_GPIO_0, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1000_GPIO_1, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1000_GPIO_2, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1000_GPIO_3, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1000_GPIO_4, INTC_INT_LOW_LEVEL, 0 }, /* CF interrupt */
|
||||
{ AU1000_GPIO_5, INTC_INT_LOW_LEVEL, 0 },
|
||||
{ AU1000_GPIO_0, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1000_GPIO_1, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1000_GPIO_2, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1000_GPIO_3, IRQF_TRIGGER_LOW, 0 },
|
||||
{ AU1000_GPIO_4, IRQF_TRIGGER_LOW, 0 }, /* CF interrupt */
|
||||
{ AU1000_GPIO_5, IRQF_TRIGGER_LOW, 0 },
|
||||
};
|
||||
|
||||
int __initdata au1xxx_nr_irqs = ARRAY_SIZE(au1xxx_irq_map);
|
||||
void __init board_init_irq(void)
|
||||
{
|
||||
au1xxx_setup_irqmap(au1xxx_irq_map, ARRAY_SIZE(au1xxx_irq_map));
|
||||
}
|
||||
|
|
85
arch/mips/cavium-octeon/Kconfig
Normal file
85
arch/mips/cavium-octeon/Kconfig
Normal 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
|
16
arch/mips/cavium-octeon/Makefile
Normal file
16
arch/mips/cavium-octeon/Makefile
Normal 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
Loading…
Reference in a new issue