示例#1
0
static int __devinit ocore_irq_mng_probe(struct platform_device *pdev)
{
	unsigned int irq;
	u16 data;
	int ret = 0;
	struct fpga_irq_mng_platform_data *pdata;

	pr_debug("Initializing FPGA IRQs\n");

	/* check if ID is correct */
	data = ioread16(ARMADEUS_FPGA_BASE_ADDR_VIRT + IRQ_MNGR_BASE + ID_OFFSET);
	if (data != ID) {
        	printk(KERN_WARNING "For irq_mngr id:%d doesn't match with id"
			 "read %d,\n is device present ?\n", ID, data);
//        	return -ENODEV;
	}

	pdata = pdev->dev.platform_data;
	if (!pdata) {
		dev_err(&pdev->dev,"No platform_data available\n");
		return -ENOMEM;
	}

	/* Mask all interrupts initially */
	writew(0, FPGA_IMR);

	if (pdata->init) {
		ret = pdata->init(pdev);
		if (ret)
			goto failed_platform_init;
	}

	for (irq = IRQ_FPGA(0); irq < IRQ_FPGA(NB_IT); irq++) {
		pr_debug("IRQ %d\n", irq);
		set_irq_chip_and_handler(irq, &imx_fpga_chip, handle_edge_irq);
		set_irq_flags(irq, IRQF_VALID);
		/* clear pending interrrupts */ 
		imx_fpga_ack_irq(irq);
	}
	set_irq_chained_handler(ARMADEUS_FPGA_IRQ, imx_fpga_demux_handler);

	pr_debug("FPGA IRQs initialized (Parent=%d)\n", ARMADEUS_FPGA_IRQ);

	return 0;

failed_platform_init:
	return ret;
}
示例#2
0
static int __devexit ocore_irq_mng_remove(struct platform_device *pdev)
{
	unsigned int irq;
	struct fpga_irq_mng_platform_data *pdata = pdev->dev.platform_data;

	for (irq = IRQ_FPGA(0); irq < IRQ_FPGA(NB_IT); irq++) {
		set_irq_chip(irq, NULL);
		set_irq_handler(irq,NULL);
		set_irq_flags(irq, 0);
	}
	set_irq_chained_handler(ARMADEUS_FPGA_IRQ, NULL);
	
	if (pdata && pdata->exit) {
		pdata->exit(pdev);
	}


	pr_debug("%s\n", __FUNCTION__);

	return 0;
}
示例#3
0
文件: test.c 项目: Wailshire/armadeus
 *
 */

#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>

#include <asm/irq.h>
#ifndef CONFIG_MACH_APF9328
#include <mach/fpga.h> /* To remove when MX1 platform is merged*/
#endif


/* Module's parameters: */
static int interrupt = IRQ_FPGA(3);
module_param(interrupt, int, 0000);
MODULE_PARM_DESC(interrupt, "IT to request");

#define DRIVER_NAME "IRQ test module"


static irqreturn_t fpga_interrupt(int irq,void *dev_id,struct pt_regs *reg)
{
	printk(KERN_ERR "FPGA IT n°%d\n", irq);

	return IRQ_HANDLED;
}

unsigned int data;
示例#4
0
static void imx_fpga_ack_irq(struct irq_data *data)
{
	struct irq_mng *mng = irq_data_get_irq_chip_data(data);
	unsigned int irq = data->irq;
#else
static void imx_fpga_ack_irq(unsigned int irq)
{
	struct irq_mng *mng = &global_mng;
#endif
	int shadow;

	shadow = 1 << ((irq - IRQ_FPGA_START) % NB_IT);
	pr_debug("%s: irq %d ack:0x%x\n", __FUNCTION__, irq, shadow);
	writew(shadow, mng->membase + FPGA_ISR);
}

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
static void imx_fpga_mask_irq(struct irq_data *data)
{
	struct irq_mng *mng = irq_data_get_irq_chip_data(data);
	unsigned int irq = data->irq;
#else
static void imx_fpga_mask_irq(unsigned int irq)
{
	struct irq_mng *mng = &global_mng;
#endif
	int shadow;

	shadow = readw(mng->membase + FPGA_IMR);
	shadow &= ~( 1 << ((irq - IRQ_FPGA_START) % NB_IT));
	pr_debug("%s: irq %d mask:0x%x\n", __FUNCTION__, irq, shadow);
	writew(shadow, mng->membase + FPGA_IMR);
}

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
static void imx_fpga_unmask_irq(struct irq_data *data)
{
	struct irq_mng *mng = irq_data_get_irq_chip_data(data);
	unsigned int irq = data->irq;
#else
static void imx_fpga_unmask_irq(unsigned int irq)
{
	struct irq_mng *mng = &global_mng;
#endif
	int shadow;

	shadow = readw(mng->membase + FPGA_IMR);
	shadow |= 1 << ((irq - IRQ_FPGA_START) % NB_IT);
	pr_debug("%s: irq %d mask:0x%x\n", __FUNCTION__, irq, shadow);
	writew(shadow, mng->membase + FPGA_IMR);
}

static irqreturn_t ocore_irq_mng_interrupt(int irq, void *data)
{
	struct irq_mng *mng = data;
	struct irq_desc *desc;
	unsigned int mask;

	mask = readw(mng->membase + FPGA_ISR);
	pr_debug("%s: mask:0x%04x\n", __FUNCTION__, mask);
	do {
		irq = IRQ_FPGA_START;

#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29)
		desc = irq_to_desc(irq);
#else
		desc = irq_desc + irq;
#endif

		/* handle irqs */
		while (mask) {
			if (mask & 1) {
				pr_debug("handling irq %d 0x%08x\n", irq,
						(unsigned int)desc);
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
				desc->handle_irq(irq, desc);
#else
				desc_handle_irq(irq, desc);
#endif
			}
			irq++;
			desc++;
			mask >>= 1;
		}
		mask = readw(mng->membase + FPGA_ISR);
	} while (mask != 0);

	return IRQ_HANDLED;
}

static struct irq_chip imx_fpga_chip = {
	.name		= "FPGA",
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
	.irq_ack	= imx_fpga_ack_irq,
	.irq_mask	= imx_fpga_mask_irq,
	.irq_unmask	= imx_fpga_unmask_irq,
#else
	.ack		= imx_fpga_ack_irq,
	.mask		= imx_fpga_mask_irq,
	.unmask		= imx_fpga_unmask_irq,
#endif
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
	.irq_set_type	= imx_fpga_irq_type,
#else
	.set_type	= imx_fpga_irq_type,
#endif
};

#ifdef CONFIG_PM
static int ocore_irq_mng_suspend(struct platform_device *pdev, pm_message_t state)
{
	dev_dbg(&pdev->dev, "suspended\n");

	return 0;
}

static int ocore_irq_mng_resume(struct platform_device *pdev)
{
	dev_dbg(&pdev->dev, "resumed\n");

	return 0;
}
#else
# define ocore_irq_mng_suspend NULL
# define ocore_irq_mng_resume NULL
#endif /* CONFIG_PM */

#if LINUX_VERSION_CODE > KERNEL_VERSION(3,8,0)
/* __dev* stuff is removed from Linux since 30/11/2012 */
#define __devinit
#define __devexit
#endif

static int __devinit ocore_irq_mng_probe(struct platform_device *pdev)
{
	struct ocore_irq_mng_pdata *pdata = pdev->dev.platform_data;
	unsigned int irq;
	u16 id;
	int ret = 0;
	struct resource *mem_res;
	struct resource *irq_res;
	struct irq_mng *mng;

	if (!pdata) {
		dev_err(&pdev->dev, "Platform data required !\n");
		return -ENODEV;
	}

	/* get resources */
	mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (!mem_res) {
		dev_err(&pdev->dev, "can't find mem resource\n");
		return -EINVAL;
	}
	irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (!irq_res) {
		dev_err(&pdev->dev, "can't find irq resource\n");
		return -EINVAL;
	}

	mem_res = request_mem_region(mem_res->start, resource_size(mem_res), pdev->name);
	if (!mem_res) {
		dev_err(&pdev->dev, "iomem already in use\n");
		return -EBUSY;
	}

	/* allocate memory for private structure */
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
	mng = kmalloc(sizeof(struct irq_mng), GFP_KERNEL);
#else
	mng = &global_mng;
#endif
	if (!mng) {
		ret = -ENOMEM;
		goto out_release_mem;
	}
	pdata->mng = mng;

	mng->membase = ioremap(mem_res->start, resource_size(mem_res));
	if (!mng->membase) {
		dev_err(&pdev->dev, "ioremap failed\n");
		ret = -ENOMEM;
		goto out_dev_free;
	}
	mng->mem_res = mem_res;
	mng->irq_res = irq_res;

	/* check if ID is correct */
	id = readw(mng->membase + ID_OFFSET);
	if (id != pdata->idnum) {
		printk(KERN_WARNING "For irq_mngr id:%d doesn't match with id"
			"read %d,\n is device present ?\n", pdata->idnum, id);
		ret = -ENODEV;
		goto out_iounmap;
	}

	/* Mask all interrupts initially */
	writew(0, mng->membase + FPGA_IMR);

	for (irq = IRQ_FPGA(0); irq < IRQ_FPGA(NB_IT); irq++) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
		irq_set_chip_data(irq, mng);
		irq_set_chip_and_handler_name(irq, &imx_fpga_chip,
						handle_edge_irq, NULL);
#else
		set_irq_chip_data(irq, mng);
		set_irq_chip_and_handler(irq, &imx_fpga_chip, handle_edge_irq);
#endif
		set_irq_flags(irq, IRQF_VALID);
	}
	/* clear pending interrupts */
	writew(0xffff, mng->membase + FPGA_ISR);

	ret = request_irq(mng->irq_res->start, ocore_irq_mng_interrupt,
#if LINUX_VERSION_CODE < KERNEL_VERSION(3,7,0)
				IRQF_SAMPLE_RANDOM,
#else
				0,
#endif
				"ocore_irq_mng", mng);

	if (ret < 0) {
		printk(KERN_ERR "Can't register irq %d\n",
			   mng->irq_res->start);
		goto request_irq_error;
	}

	pr_debug("FPGA IRQs initialized (Parent=%d)\n", mng->irq_res->start);

	return 0;

request_irq_error:
out_iounmap:
	iounmap(mng->membase);
out_dev_free:
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,36)
	kfree(mng);
#endif
out_release_mem:
	release_mem_region(mem_res->start, resource_size(mem_res));

	return ret;
}

static int __devexit ocore_irq_mng_remove(struct platform_device *pdev)
{
	struct ocore_irq_mng_pdata *pdata = pdev->dev.platform_data;
	struct irq_mng *mng = pdata->mng;
	unsigned int irq;

	for (irq = IRQ_FPGA(0); irq < IRQ_FPGA(NB_IT); irq++) {
#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,39)
		irq_set_chip(irq, NULL);
		irq_set_handler(irq, NULL);
#else
		set_irq_chip(irq, NULL);
		set_irq_handler(irq, NULL);
#endif
		set_irq_flags(irq, 0);
	}
	free_irq(mng->irq_res->start, mng);
	release_mem_region(mng->mem_res->start, resource_size(mng->mem_res));
	iounmap(mng->membase);
	kfree(mng);

	return 0;
}

static struct platform_driver ocore_irq_mng_driver = {
	.probe      = ocore_irq_mng_probe,
	.remove     = ocore_irq_mng_remove,
	.suspend    = ocore_irq_mng_suspend,
	.resume     = ocore_irq_mng_resume,
	.driver     = {
		.name   = DRIVER_NAME,
	},
};

static int __init ocore_irq_mng_init(void)
{
	return platform_driver_register(&ocore_irq_mng_driver);
}

static void __exit ocore_irq_mng_exit(void)
{
	platform_driver_unregister(&ocore_irq_mng_driver);
}

module_init(ocore_irq_mng_init);
module_exit(ocore_irq_mng_exit);

MODULE_AUTHOR("Julien Boibessot, <*****@*****.**>");
MODULE_DESCRIPTION("Armadeus OpenCore IRQ manager");
MODULE_LICENSE("GPL");