open_pic_u3.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 349 行
C
349 行
/* * arch/ppc/kernel/open_pic.c -- OpenPIC Interrupt Handling * * Copyright (C) 1997 Geert Uytterhoeven * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. */#include <linux/config.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/init.h>#include <linux/irq.h>#include <linux/smp.h>#include <linux/interrupt.h>#include <asm/ptrace.h>#include <asm/signal.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/irq.h>#include <asm/prom.h>#include <asm/machdep.h>#include "open_pic.h"#include "open_pic_defs.h"void* OpenPIC2_Addr;static volatile struct OpenPIC *OpenPIC2 = NULL;extern u_int OpenPIC_NumInitSenses;extern u_char *OpenPIC_InitSenses;static u_int NumSources;static int NumISUs;static int open_pic2_irq_offset;static OpenPIC_SourcePtr ISU2[OPENPIC_MAX_ISU];unsigned int openpic2_vec_spurious;/* * Accesses to the current processor's openpic registers * U3 secondary openpic has only one output */#define THIS_CPU Processor[0]#define DECL_THIS_CPU#define CHECK_THIS_CPU#define GET_ISU(source) ISU2[(source) >> 4][(source) & 0xf]static inline u_int openpic2_read(volatile u_int *addr){ u_int val; val = in_be32(addr); return val;}static inline void openpic2_write(volatile u_int *addr, u_int val){ out_be32(addr, val);}static inline u_int openpic2_readfield(volatile u_int *addr, u_int mask){ u_int val = openpic2_read(addr); return val & mask;}static inline void openpic2_writefield(volatile u_int *addr, u_int mask, u_int field){ u_int val = openpic2_read(addr); openpic2_write(addr, (val & ~mask) | (field & mask));}static inline void openpic2_clearfield(volatile u_int *addr, u_int mask){ openpic2_writefield(addr, mask, 0);}static inline void openpic2_setfield(volatile u_int *addr, u_int mask){ openpic2_writefield(addr, mask, mask);}static void openpic2_safe_writefield(volatile u_int *addr, u_int mask, u_int field){ unsigned int loops = 100000; openpic2_setfield(addr, OPENPIC_MASK); while (openpic2_read(addr) & OPENPIC_ACTIVITY) { if (!loops--) { printk(KERN_ERR "openpic2_safe_writefield timeout\n"); break; } } openpic2_writefield(addr, mask | OPENPIC_MASK, field | OPENPIC_MASK);}static inline void openpic2_reset(void){ openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, OPENPIC_CONFIG_RESET);}static void openpic2_disable_8259_pass_through(void){ openpic2_setfield(&OpenPIC2->Global.Global_Configuration0, OPENPIC_CONFIG_8259_PASSTHROUGH_DISABLE);}/* * Find out the current interrupt */static u_int openpic2_irq(void){ u_int vec; DECL_THIS_CPU; CHECK_THIS_CPU; vec = openpic2_readfield(&OpenPIC2->THIS_CPU.Interrupt_Acknowledge, OPENPIC_VECTOR_MASK); return vec;}static void openpic2_eoi(void){ DECL_THIS_CPU; CHECK_THIS_CPU; openpic2_write(&OpenPIC2->THIS_CPU.EOI, 0); /* Handle PCI write posting */ (void)openpic2_read(&OpenPIC2->THIS_CPU.EOI);}static inline u_int openpic2_get_priority(void){ DECL_THIS_CPU; CHECK_THIS_CPU; return openpic2_readfield(&OpenPIC2->THIS_CPU.Current_Task_Priority, OPENPIC_CURRENT_TASK_PRIORITY_MASK);}static void openpic2_set_priority(u_int pri){ DECL_THIS_CPU; CHECK_THIS_CPU; openpic2_writefield(&OpenPIC2->THIS_CPU.Current_Task_Priority, OPENPIC_CURRENT_TASK_PRIORITY_MASK, pri);}/* * Get/set the spurious vector */static inline u_int openpic2_get_spurious(void){ return openpic2_readfield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK);}static void openpic2_set_spurious(u_int vec){ openpic2_writefield(&OpenPIC2->Global.Spurious_Vector, OPENPIC_VECTOR_MASK, vec);}/* * Enable/disable an external interrupt source * * Externally called, irq is an offseted system-wide interrupt number */static void openpic2_enable_irq(u_int irq){ unsigned int loops = 100000; openpic2_clearfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK); /* make sure mask gets to controller before we return to user */ do { if (!loops--) { printk(KERN_ERR "openpic_enable_irq timeout\n"); break; } mb(); /* sync is probably useless here */ } while(openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK));}static void openpic2_disable_irq(u_int irq){ u32 vp; unsigned int loops = 100000; openpic2_setfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK); /* make sure mask gets to controller before we return to user */ do { if (!loops--) { printk(KERN_ERR "openpic_disable_irq timeout\n"); break; } mb(); /* sync is probably useless here */ vp = openpic2_readfield(&GET_ISU(irq - open_pic2_irq_offset).Vector_Priority, OPENPIC_MASK | OPENPIC_ACTIVITY); } while((vp & OPENPIC_ACTIVITY) && !(vp & OPENPIC_MASK));}/* * Initialize an interrupt source (and disable it!) * * irq: OpenPIC interrupt number * pri: interrupt source priority * vec: the vector it will produce * pol: polarity (1 for positive, 0 for negative) * sense: 1 for level, 0 for edge */static void openpic2_initirq(u_int irq, u_int pri, u_int vec, int pol, int sense){ openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority, OPENPIC_PRIORITY_MASK | OPENPIC_VECTOR_MASK | OPENPIC_SENSE_MASK | OPENPIC_POLARITY_MASK, (pri << OPENPIC_PRIORITY_SHIFT) | vec | (pol ? OPENPIC_POLARITY_POSITIVE : OPENPIC_POLARITY_NEGATIVE) | (sense ? OPENPIC_SENSE_LEVEL : OPENPIC_SENSE_EDGE));}/* * Map an interrupt source to one or more CPUs */static void openpic2_mapirq(u_int irq, u_int physmask){ openpic2_write(&GET_ISU(irq).Destination, physmask);}/* * Set the sense for an interrupt source (and disable it!) * * sense: 1 for level, 0 for edge */static inline void openpic2_set_sense(u_int irq, int sense){ openpic2_safe_writefield(&GET_ISU(irq).Vector_Priority, OPENPIC_SENSE_LEVEL, (sense ? OPENPIC_SENSE_LEVEL : 0));}static void openpic2_end_irq(unsigned int irq_nr){ openpic2_eoi();}int openpic2_get_irq(struct pt_regs *regs){ int irq = openpic2_irq(); if (irq == openpic2_vec_spurious) return -1; return irq + open_pic2_irq_offset;}struct hw_interrupt_type open_pic2 = { " OpenPIC2 ", NULL, NULL, openpic2_enable_irq, openpic2_disable_irq, NULL, openpic2_end_irq,};void __init openpic2_init(int offset){ u_int t, i; const char *version; if (!OpenPIC2_Addr) { printk(KERN_INFO "No OpenPIC2 found !\n"); return; } OpenPIC2 = (volatile struct OpenPIC *)OpenPIC2_Addr; ppc64_boot_msg(0x20, "OpenPic U3 Init"); t = openpic2_read(&OpenPIC2->Global.Feature_Reporting0); switch (t & OPENPIC_FEATURE_VERSION_MASK) { case 1: version = "1.0"; break; case 2: version = "1.2"; break; case 3: version = "1.3"; break; default: version = "?"; break; } printk(KERN_INFO "OpenPIC (U3) Version %s\n", version); open_pic2_irq_offset = offset; for (i=0; i<128; i+=0x10) { ISU2[i>>4] = &((struct OpenPIC *)OpenPIC2_Addr)->Source[i]; NumISUs++; } NumSources = NumISUs * 0x10; openpic2_vec_spurious = NumSources; openpic2_set_priority(0xf); /* Init all external sources */ for (i = 0; i < NumSources; i++) { int pri, sense; /* the bootloader may have left it enabled (bad !) */ openpic2_disable_irq(i+offset); pri = 8; sense = (i < OpenPIC_NumInitSenses) ? OpenPIC_InitSenses[i]: 1; if (sense) irq_desc[i+offset].status = IRQ_LEVEL; /* Enabled, Priority 8 or 9 */ openpic2_initirq(i, pri, i, !sense, sense); /* Processor 0 */ openpic2_mapirq(i, 0x1); } /* Init descriptors */ for (i = offset; i < NumSources + offset; i++) irq_desc[i].handler = &open_pic2; /* Initialize the spurious interrupt */ openpic2_set_spurious(openpic2_vec_spurious); openpic2_set_priority(0); openpic2_disable_8259_pass_through(); ppc64_boot_msg(0x25, "OpenPic U3 Done");}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?