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

📄 pq2ads-pci-pic.c

📁 linux内核源码
💻 C
字号:
/* * PQ2 ADS-style PCI interrupt controller * * Copyright 2007 Freescale Semiconductor, Inc. * Author: Scott Wood <scottwood@freescale.com> * * Loosely based on mpc82xx ADS support by Vitaly Bordug <vbordug@ru.mvista.com> * Copyright (c) 2006 MontaVista Software, Inc. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published * by the Free Software Foundation. */#include <linux/init.h>#include <linux/spinlock.h>#include <linux/irq.h>#include <linux/types.h>#include <linux/bootmem.h>#include <asm/io.h>#include <asm/prom.h>#include <asm/cpm2.h>#include "pq2.h"static DEFINE_SPINLOCK(pci_pic_lock);struct pq2ads_pci_pic {	struct device_node *node;	struct irq_host *host;	struct {		u32 stat;		u32 mask;	} __iomem *regs;};#define NUM_IRQS 32static void pq2ads_pci_mask_irq(unsigned int virq){	struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);	int irq = NUM_IRQS - virq_to_hw(virq) - 1;	if (irq != -1) {		unsigned long flags;		spin_lock_irqsave(&pci_pic_lock, flags);		setbits32(&priv->regs->mask, 1 << irq);		mb();		spin_unlock_irqrestore(&pci_pic_lock, flags);	}}static void pq2ads_pci_unmask_irq(unsigned int virq){	struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);	int irq = NUM_IRQS - virq_to_hw(virq) - 1;	if (irq != -1) {		unsigned long flags;		spin_lock_irqsave(&pci_pic_lock, flags);		clrbits32(&priv->regs->mask, 1 << irq);		spin_unlock_irqrestore(&pci_pic_lock, flags);	}}static struct irq_chip pq2ads_pci_ic = {	.typename = "PQ2 ADS PCI",	.name = "PQ2 ADS PCI",	.end = pq2ads_pci_unmask_irq,	.mask = pq2ads_pci_mask_irq,	.mask_ack = pq2ads_pci_mask_irq,	.ack = pq2ads_pci_mask_irq,	.unmask = pq2ads_pci_unmask_irq,	.enable = pq2ads_pci_unmask_irq,	.disable = pq2ads_pci_mask_irq};static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc){	struct pq2ads_pci_pic *priv = desc->handler_data;	u32 stat, mask, pend;	int bit;	for (;;) {		stat = in_be32(&priv->regs->stat);		mask = in_be32(&priv->regs->mask);		pend = stat & ~mask;		if (!pend)			break;		for (bit = 0; pend != 0; ++bit, pend <<= 1) {			if (pend & 0x80000000) {				int virq = irq_linear_revmap(priv->host, bit);				generic_handle_irq(virq);			}		}	}}static int pci_pic_host_map(struct irq_host *h, unsigned int virq,			    irq_hw_number_t hw){	get_irq_desc(virq)->status |= IRQ_LEVEL;	set_irq_chip_data(virq, h->host_data);	set_irq_chip(virq, &pq2ads_pci_ic);	return 0;}static void pci_host_unmap(struct irq_host *h, unsigned int virq){	/* remove chip and handler */	set_irq_chip_data(virq, NULL);	set_irq_chip(virq, NULL);}static struct irq_host_ops pci_pic_host_ops = {	.map = pci_pic_host_map,	.unmap = pci_host_unmap,};int __init pq2ads_pci_init_irq(void){	struct pq2ads_pci_pic *priv;	struct irq_host *host;	struct device_node *np;	int ret = -ENODEV;	int irq;	np = of_find_compatible_node(NULL, NULL, "fsl,pq2ads-pci-pic");	if (!np) {		printk(KERN_ERR "No pci pic node in device tree.\n");		of_node_put(np);		goto out;	}	irq = irq_of_parse_and_map(np, 0);	if (irq == NO_IRQ) {		printk(KERN_ERR "No interrupt in pci pic node.\n");		of_node_put(np);		goto out;	}	priv = alloc_bootmem(sizeof(struct pq2ads_pci_pic));	if (!priv) {		of_node_put(np);		ret = -ENOMEM;		goto out_unmap_irq;	}	/* PCI interrupt controller registers: status and mask */	priv->regs = of_iomap(np, 0);	if (!priv->regs) {		printk(KERN_ERR "Cannot map PCI PIC registers.\n");		goto out_free_bootmem;	}	/* mask all PCI interrupts */	out_be32(&priv->regs->mask, ~0);	mb();	host = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, NUM_IRQS,	                      &pci_pic_host_ops, NUM_IRQS);	if (!host) {		ret = -ENOMEM;		goto out_unmap_regs;	}	host->host_data = priv;	priv->host = host;	host->host_data = priv;	set_irq_data(irq, priv);	set_irq_chained_handler(irq, pq2ads_pci_irq_demux);	of_node_put(np);	return 0;out_unmap_regs:	iounmap(priv->regs);out_free_bootmem:	free_bootmem((unsigned long)priv,	             sizeof(sizeof(struct pq2ads_pci_pic)));	of_node_put(np);out_unmap_irq:	irq_dispose_mapping(irq);out:	return ret;}

⌨️ 快捷键说明

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