core.c

来自「linux2.6.16版本」· C语言 代码 · 共 533 行 · 第 1/2 页

C
533
字号
/************************************************************************* * GPIO helpers *************************************************************************/static unsigned long GPIO_IRQ_falling_edge;static unsigned long GPIO_IRQ_rising_edge;static unsigned long GPIO_IRQ_level_low;static unsigned long GPIO_IRQ_level_high;static void update_gpio_int_csrs(void){	ixp2000_reg_write(IXP2000_GPIO_FEDR, GPIO_IRQ_falling_edge);	ixp2000_reg_write(IXP2000_GPIO_REDR, GPIO_IRQ_rising_edge);	ixp2000_reg_write(IXP2000_GPIO_LSLR, GPIO_IRQ_level_low);	ixp2000_reg_wrb(IXP2000_GPIO_LSHR, GPIO_IRQ_level_high);}void gpio_line_config(int line, int direction){	unsigned long flags;	local_irq_save(flags);	if (direction == GPIO_OUT) {		irq_desc[line + IRQ_IXP2000_GPIO0].valid = 0;		/* if it's an output, it ain't an interrupt anymore */		GPIO_IRQ_falling_edge &= ~(1 << line);		GPIO_IRQ_rising_edge &= ~(1 << line);		GPIO_IRQ_level_low &= ~(1 << line);		GPIO_IRQ_level_high &= ~(1 << line);		update_gpio_int_csrs();		ixp2000_reg_wrb(IXP2000_GPIO_PDSR, 1 << line);	} else if (direction == GPIO_IN) {		ixp2000_reg_wrb(IXP2000_GPIO_PDCR, 1 << line);	}	local_irq_restore(flags);}/************************************************************************* * IRQ handling IXP2000 *************************************************************************/static void ixp2000_GPIO_irq_handler(unsigned int irq, struct irqdesc *desc, struct pt_regs *regs){                               	int i;	unsigned long status = *IXP2000_GPIO_INST;		   	for (i = 0; i <= 7; i++) {		if (status & (1<<i)) {			desc = irq_desc + i + IRQ_IXP2000_GPIO0;			desc_handle_irq(i + IRQ_IXP2000_GPIO0, desc, regs);		}	}}static int ixp2000_GPIO_irq_type(unsigned int irq, unsigned int type){	int line = irq - IRQ_IXP2000_GPIO0;	/*	 * First, configure this GPIO line as an input.	 */	ixp2000_reg_write(IXP2000_GPIO_PDCR, 1 << line);	/*	 * Then, set the proper trigger type.	 */	if (type & IRQT_FALLING)		GPIO_IRQ_falling_edge |= 1 << line;	else		GPIO_IRQ_falling_edge &= ~(1 << line);	if (type & IRQT_RISING)		GPIO_IRQ_rising_edge |= 1 << line;	else		GPIO_IRQ_rising_edge &= ~(1 << line);	if (type & IRQT_LOW)		GPIO_IRQ_level_low |= 1 << line;	else		GPIO_IRQ_level_low &= ~(1 << line);	if (type & IRQT_HIGH)		GPIO_IRQ_level_high |= 1 << line;	else		GPIO_IRQ_level_high &= ~(1 << line);	update_gpio_int_csrs();	/*	 * Finally, mark the corresponding IRQ as valid.	 */	irq_desc[irq].valid = 1;	return 0;}static void ixp2000_GPIO_irq_mask_ack(unsigned int irq){	ixp2000_reg_write(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));	ixp2000_reg_write(IXP2000_GPIO_EDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));	ixp2000_reg_write(IXP2000_GPIO_LDSR, (1 << (irq - IRQ_IXP2000_GPIO0)));	ixp2000_reg_wrb(IXP2000_GPIO_INST, (1 << (irq - IRQ_IXP2000_GPIO0)));}static void ixp2000_GPIO_irq_mask(unsigned int irq){	ixp2000_reg_wrb(IXP2000_GPIO_INCR, (1 << (irq - IRQ_IXP2000_GPIO0)));}static void ixp2000_GPIO_irq_unmask(unsigned int irq){	ixp2000_reg_write(IXP2000_GPIO_INSR, (1 << (irq - IRQ_IXP2000_GPIO0)));}static struct irqchip ixp2000_GPIO_irq_chip = {	.ack		= ixp2000_GPIO_irq_mask_ack,	.mask		= ixp2000_GPIO_irq_mask,	.unmask		= ixp2000_GPIO_irq_unmask,	.set_type	= ixp2000_GPIO_irq_type,};static void ixp2000_pci_irq_mask(unsigned int irq){	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;	if (irq == IRQ_IXP2000_PCIA)		ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 26)));	else if (irq == IRQ_IXP2000_PCIB)		ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, (temp & ~(1 << 27)));}static void ixp2000_pci_irq_unmask(unsigned int irq){	unsigned long temp = *IXP2000_PCI_XSCALE_INT_ENABLE;	if (irq == IRQ_IXP2000_PCIA)		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 26)));	else if (irq == IRQ_IXP2000_PCIB)		ixp2000_reg_write(IXP2000_PCI_XSCALE_INT_ENABLE, (temp | (1 << 27)));}/* * Error interrupts. These are used extensively by the microengine drivers */static void ixp2000_err_irq_handler(unsigned int irq, struct irqdesc *desc,  struct pt_regs *regs){	int i;	unsigned long status = *IXP2000_IRQ_ERR_STATUS;	for(i = 31; i >= 0; i--) {		if(status & (1 << i)) {			desc = irq_desc + IRQ_IXP2000_DRAM0_MIN_ERR + i;			desc->handle(IRQ_IXP2000_DRAM0_MIN_ERR + i, desc, regs);		}	}}static void ixp2000_err_irq_mask(unsigned int irq){	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_CLR,			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));}static void ixp2000_err_irq_unmask(unsigned int irq){	ixp2000_reg_write(IXP2000_IRQ_ERR_ENABLE_SET,			(1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)));}static struct irqchip ixp2000_err_irq_chip = {	.ack	= ixp2000_err_irq_mask,	.mask	= ixp2000_err_irq_mask,	.unmask	= ixp2000_err_irq_unmask};static struct irqchip ixp2000_pci_irq_chip = {	.ack	= ixp2000_pci_irq_mask,	.mask	= ixp2000_pci_irq_mask,	.unmask	= ixp2000_pci_irq_unmask};static void ixp2000_irq_mask(unsigned int irq){	ixp2000_reg_wrb(IXP2000_IRQ_ENABLE_CLR, (1 << irq));}static void ixp2000_irq_unmask(unsigned int irq){	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << irq));}static struct irqchip ixp2000_irq_chip = {	.ack	= ixp2000_irq_mask,	.mask	= ixp2000_irq_mask,	.unmask	= ixp2000_irq_unmask};void __init ixp2000_init_irq(void){	int irq;	/*	 * Mask all sources	 */	ixp2000_reg_write(IXP2000_IRQ_ENABLE_CLR, 0xffffffff);	ixp2000_reg_write(IXP2000_FIQ_ENABLE_CLR, 0xffffffff);	/* clear all GPIO edge/level detects */	ixp2000_reg_write(IXP2000_GPIO_REDR, 0);	ixp2000_reg_write(IXP2000_GPIO_FEDR, 0);	ixp2000_reg_write(IXP2000_GPIO_LSHR, 0);	ixp2000_reg_write(IXP2000_GPIO_LSLR, 0);	ixp2000_reg_write(IXP2000_GPIO_INCR, -1);	/* clear PCI interrupt sources */	ixp2000_reg_wrb(IXP2000_PCI_XSCALE_INT_ENABLE, 0);	/*	 * Certain bits in the IRQ status register of the 	 * IXP2000 are reserved. Instead of trying to map	 * things non 1:1 from bit position to IRQ number,	 * we mark the reserved IRQs as invalid. This makes	 * our mask/unmask code much simpler.	 */	for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {		if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {			set_irq_chip(irq, &ixp2000_irq_chip);			set_irq_handler(irq, do_level_IRQ);			set_irq_flags(irq, IRQF_VALID);		} else set_irq_flags(irq, 0);	}	for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {		if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) &				IXP2000_VALID_ERR_IRQ_MASK) {			set_irq_chip(irq, &ixp2000_err_irq_chip);			set_irq_handler(irq, do_level_IRQ);			set_irq_flags(irq, IRQF_VALID);		}		else			set_irq_flags(irq, 0);	}	set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);	/*	 * GPIO IRQs are invalid until someone sets the interrupt mode	 * by calling set_irq_type().	 */	for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {		set_irq_chip(irq, &ixp2000_GPIO_irq_chip);		set_irq_handler(irq, do_level_IRQ);		set_irq_flags(irq, 0);	}	set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);	/*	 * Enable PCI irqs.  The actual PCI[AB] decoding is done in	 * entry-macro.S, so we don't need a chained handler for the	 * PCI interrupt source.	 */	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));	for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {		set_irq_chip(irq, &ixp2000_pci_irq_chip);		set_irq_handler(irq, do_level_IRQ);		set_irq_flags(irq, IRQF_VALID);	}}

⌨️ 快捷键说明

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