Linux Audio

Check our new training course

Yocto distribution development and maintenance

Need a Yocto distribution for your embedded project?
Loading...
Note: File does not exist in v5.9.
  1/* irq-mb93093.c: MB93093 FPGA interrupt handling
  2 *
  3 * Copyright (C) 2006 Red Hat, Inc. All Rights Reserved.
  4 * Written by David Howells (dhowells@redhat.com)
  5 *
  6 * This program is free software; you can redistribute it and/or
  7 * modify it under the terms of the GNU General Public License
  8 * as published by the Free Software Foundation; either version
  9 * 2 of the License, or (at your option) any later version.
 10 */
 11
 12#include <linux/ptrace.h>
 13#include <linux/errno.h>
 14#include <linux/signal.h>
 15#include <linux/sched.h>
 16#include <linux/ioport.h>
 17#include <linux/interrupt.h>
 18#include <linux/init.h>
 19#include <linux/irq.h>
 20#include <linux/bitops.h>
 21
 22#include <asm/io.h>
 23#include <asm/delay.h>
 24#include <asm/irq.h>
 25#include <asm/irc-regs.h>
 26
 27#define __reg16(ADDR) (*(volatile unsigned short *)(__region_CS2 + (ADDR)))
 28
 29#define __get_IMR()	({ __reg16(0x0a); })
 30#define __set_IMR(M)	do { __reg16(0x0a) = (M);  wmb(); } while(0)
 31#define __get_IFR()	({ __reg16(0x02); })
 32#define __clr_IFR(M)	do { __reg16(0x02) = ~(M); wmb(); } while(0)
 33
 34/*
 35 * off-CPU FPGA PIC operations
 36 */
 37static void frv_fpga_mask(struct irq_data *d)
 38{
 39	uint16_t imr = __get_IMR();
 40
 41	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 42	__set_IMR(imr);
 43}
 44
 45static void frv_fpga_ack(struct irq_data *d)
 46{
 47	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 48}
 49
 50static void frv_fpga_mask_ack(struct irq_data *d)
 51{
 52	uint16_t imr = __get_IMR();
 53
 54	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 55	__set_IMR(imr);
 56
 57	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 58}
 59
 60static void frv_fpga_unmask(struct irq_data *d)
 61{
 62	uint16_t imr = __get_IMR();
 63
 64	imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
 65
 66	__set_IMR(imr);
 67}
 68
 69static struct irq_chip frv_fpga_pic = {
 70	.name		= "mb93093",
 71	.irq_ack	= frv_fpga_ack,
 72	.irq_mask	= frv_fpga_mask,
 73	.irq_mask_ack	= frv_fpga_mask_ack,
 74	.irq_unmask	= frv_fpga_unmask,
 75};
 76
 77/*
 78 * FPGA PIC interrupt handler
 79 */
 80static irqreturn_t fpga_interrupt(int irq, void *_mask)
 81{
 82	uint16_t imr, mask = (unsigned long) _mask;
 83
 84	imr = __get_IMR();
 85	mask = mask & ~imr & __get_IFR();
 86
 87	/* poll all the triggered IRQs */
 88	while (mask) {
 89		int irq;
 90
 91		asm("scan %1,gr0,%0" : "=r"(irq) : "r"(mask));
 92		irq = 31 - irq;
 93		mask &= ~(1 << irq);
 94
 95		generic_handle_irq(IRQ_BASE_FPGA + irq);
 96	}
 97
 98	return IRQ_HANDLED;
 99}
100
101/*
102 * define an interrupt action for each FPGA PIC output
103 * - use dev_id to indicate the FPGA PIC input to output mappings
104 */
105static struct irqaction fpga_irq[1]  = {
106	[0] = {
107		.handler	= fpga_interrupt,
108		.flags		= IRQF_DISABLED,
109		.name		= "fpga.0",
110		.dev_id		= (void *) 0x0700UL,
111	}
112};
113
114/*
115 * initialise the motherboard FPGA's PIC
116 */
117void __init fpga_init(void)
118{
119	int irq;
120
121	/* all PIC inputs are all set to be edge triggered */
122	__set_IMR(0x0700);
123	__clr_IFR(0x0000);
124
125	for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
126		irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
127
128	/* the FPGA drives external IRQ input #2 on the CPU PIC */
129	setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
130}