⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mpc52xx_pic.c

📁 底层驱动开发
💻 C
字号:
/* * arch/ppc/syslib/mpc52xx_pic.c * * Programmable Interrupt Controller functions for the Freescale MPC52xx  * embedded CPU. * *  * Maintainer : Sylvain Munaut <tnt@246tNt.com> * * Based on (well, mostly copied from) the code from the 2.4 kernel by * Dale Farnsworth <dfarnsworth@mvista.com> and Kent Borg. *  * Copyright (C) 2004 Sylvain Munaut <tnt@246tNt.com> * Copyright (C) 2003 Montavista Software, Inc *  * This file is licensed under the terms of the GNU General Public License * version 2. This program is licensed "as is" without any warranty of any * kind, whether express or implied. */#include <linux/stddef.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/stddef.h>#include <linux/delay.h>#include <linux/irq.h>#include <asm/io.h>#include <asm/processor.h>#include <asm/system.h>#include <asm/irq.h>#include <asm/mpc52xx.h>static struct mpc52xx_intr __iomem *intr;static struct mpc52xx_sdma __iomem *sdma;static voidmpc52xx_ic_disable(unsigned int irq){	u32 val;	if (irq == MPC52xx_IRQ0) {		val = in_be32(&intr->ctrl);		val &= ~(1 << 11);		out_be32(&intr->ctrl, val);	}	else if (irq < MPC52xx_IRQ1) {		BUG();	}	else if (irq <= MPC52xx_IRQ3) {		val = in_be32(&intr->ctrl);		val &= ~(1 << (10 - (irq - MPC52xx_IRQ1)));		out_be32(&intr->ctrl, val);	}	else if (irq < MPC52xx_SDMA_IRQ_BASE) {		val = in_be32(&intr->main_mask);		val |= 1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE));		out_be32(&intr->main_mask, val);	}	else if (irq < MPC52xx_PERP_IRQ_BASE) {		val = in_be32(&sdma->IntMask);		val |= 1 << (irq - MPC52xx_SDMA_IRQ_BASE);		out_be32(&sdma->IntMask, val);	}	else {		val = in_be32(&intr->per_mask);		val |= 1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE));		out_be32(&intr->per_mask, val);	}}static voidmpc52xx_ic_enable(unsigned int irq){	u32 val;	if (irq == MPC52xx_IRQ0) {		val = in_be32(&intr->ctrl);		val |= 1 << 11;		out_be32(&intr->ctrl, val);	}	else if (irq < MPC52xx_IRQ1) {		BUG();	}	else if (irq <= MPC52xx_IRQ3) {		val = in_be32(&intr->ctrl);		val |= 1 << (10 - (irq - MPC52xx_IRQ1));		out_be32(&intr->ctrl, val);	}	else if (irq < MPC52xx_SDMA_IRQ_BASE) {		val = in_be32(&intr->main_mask);		val &= ~(1 << (16 - (irq - MPC52xx_MAIN_IRQ_BASE)));		out_be32(&intr->main_mask, val);	}	else if (irq < MPC52xx_PERP_IRQ_BASE) {		val = in_be32(&sdma->IntMask);		val &= ~(1 << (irq - MPC52xx_SDMA_IRQ_BASE));		out_be32(&sdma->IntMask, val);	}	else {		val = in_be32(&intr->per_mask);		val &= ~(1 << (31 - (irq - MPC52xx_PERP_IRQ_BASE)));		out_be32(&intr->per_mask, val);	}}static voidmpc52xx_ic_ack(unsigned int irq){	u32 val;	/*	 * Only some irqs are reset here, others in interrupting hardware.	 */	switch (irq) {	case MPC52xx_IRQ0:		val = in_be32(&intr->ctrl);		val |= 0x08000000;		out_be32(&intr->ctrl, val);		break;	case MPC52xx_CCS_IRQ:		val = in_be32(&intr->enc_status);		val |= 0x00000400;		out_be32(&intr->enc_status, val);		break;	case MPC52xx_IRQ1:		val = in_be32(&intr->ctrl);		val |= 0x04000000;		out_be32(&intr->ctrl, val);		break;	case MPC52xx_IRQ2:		val = in_be32(&intr->ctrl);		val |= 0x02000000;		out_be32(&intr->ctrl, val);		break;	case MPC52xx_IRQ3:		val = in_be32(&intr->ctrl);		val |= 0x01000000;		out_be32(&intr->ctrl, val);		break;	default:		if (irq >= MPC52xx_SDMA_IRQ_BASE		    && irq < (MPC52xx_SDMA_IRQ_BASE + MPC52xx_SDMA_IRQ_NUM)) {			out_be32(&sdma->IntPend,				 1 << (irq - MPC52xx_SDMA_IRQ_BASE));		}		break;	}}static voidmpc52xx_ic_disable_and_ack(unsigned int irq){	mpc52xx_ic_disable(irq);	mpc52xx_ic_ack(irq);}static voidmpc52xx_ic_end(unsigned int irq){	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))		mpc52xx_ic_enable(irq);}static struct hw_interrupt_type mpc52xx_ic = {	.typename	= " MPC52xx  ",	.enable		= mpc52xx_ic_enable,	.disable	= mpc52xx_ic_disable,	.ack		= mpc52xx_ic_disable_and_ack,	.end		= mpc52xx_ic_end,};void __initmpc52xx_init_irq(void){	int i;	u32 intr_ctrl;	/* Remap the necessary zones */	intr = ioremap(MPC52xx_PA(MPC52xx_INTR_OFFSET), MPC52xx_INTR_SIZE);	sdma = ioremap(MPC52xx_PA(MPC52xx_SDMA_OFFSET), MPC52xx_SDMA_SIZE);	if ((intr==NULL) || (sdma==NULL))		panic("Can't ioremap PIC/SDMA register for init_irq !");	/* Disable all interrupt sources. */	out_be32(&sdma->IntPend, 0xffffffff);	/* 1 means clear pending */	out_be32(&sdma->IntMask, 0xffffffff);	/* 1 means disabled */	out_be32(&intr->per_mask, 0x7ffffc00);	/* 1 means disabled */	out_be32(&intr->main_mask, 0x00010fff);	/* 1 means disabled */	intr_ctrl = in_be32(&intr->ctrl);	intr_ctrl &=    0x00ff0000;	/* Keeps IRQ[0-3] config */	intr_ctrl |=	0x0f000000 |	/* clear IRQ 0-3 */			0x00001000 |	/* MEE master external enable */			0x00000000 |	/* 0 means disable IRQ 0-3 */			0x00000001;	/* CEb route critical normally */	out_be32(&intr->ctrl, intr_ctrl);	/* Zero a bunch of the priority settings.  */	out_be32(&intr->per_pri1, 0);	out_be32(&intr->per_pri2, 0);	out_be32(&intr->per_pri3, 0);	out_be32(&intr->main_pri1, 0);	out_be32(&intr->main_pri2, 0);	/* Initialize irq_desc[i].handler's with mpc52xx_ic. */	for (i = 0; i < NR_IRQS; i++) {		irq_desc[i].handler = &mpc52xx_ic;		irq_desc[i].status = IRQ_LEVEL;	}	#define IRQn_MODE(intr_ctrl,irq) (((intr_ctrl) >> (22-(i<<1))) & 0x03)	for (i=0 ; i<4 ; i++) {		int mode;		mode = IRQn_MODE(intr_ctrl,i);		if ((mode == 0x1) || (mode == 0x2))			irq_desc[i?MPC52xx_IRQ1+i-1:MPC52xx_IRQ0].status = 0;	}}intmpc52xx_get_irq(struct pt_regs *regs){	u32 status;	int irq = -1;	status = in_be32(&intr->enc_status);	if (status & 0x00000400) {		/* critical */		irq = (status >> 8) & 0x3;		if (irq == 2)			/* high priority peripheral */			goto peripheral;		irq += MPC52xx_CRIT_IRQ_BASE;	}	else if (status & 0x00200000) {		/* main */		irq = (status >> 16) & 0x1f;		if (irq == 4)			/* low priority peripheral */			goto peripheral;		irq += MPC52xx_MAIN_IRQ_BASE;	}	else if (status & 0x20000000) {		/* peripheral */peripheral:		irq = (status >> 24) & 0x1f;		if (irq == 0) {			/* bestcomm */			status = in_be32(&sdma->IntPend);			irq = ffs(status) + MPC52xx_SDMA_IRQ_BASE-1;		}		else			irq += MPC52xx_PERP_IRQ_BASE;	}	return irq;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -