PageRenderTime 35ms CodeModel.GetById 15ms app.highlight 15ms RepoModel.GetById 2ms app.codeStats 0ms

/arch/mips/momentum/ocelot_c/cpci-irq.c

https://bitbucket.org/evzijst/gittest
C | 153 lines | 85 code | 24 blank | 44 comment | 8 complexity | 40410df3175c2a8876acb259235db55c MD5 | raw file
  1/*
  2 * Copyright 2002 Momentum Computer
  3 * Author: mdharm@momenco.com
  4 *
  5 * arch/mips/momentum/ocelot_c/cpci-irq.c
  6 *     Interrupt routines for cpci.  Interrupt numbers are assigned from
  7 *     CPCI_IRQ_BASE to CPCI_IRQ_BASE+8 (8 interrupt sources).
  8 *
  9 * Note that the high-level software will need to be careful about using
 10 * these interrupts.  If this board is asserting a cPCI interrupt, it will
 11 * also see the asserted interrupt.  Care must be taken to avoid an
 12 * interrupt flood.
 13 *
 14 * This program is free software; you can redistribute  it and/or modify it
 15 * under  the terms of  the GNU General  Public License as published by the
 16 * Free Software Foundation;  either version 2 of the  License, or (at your
 17 * option) any later version.
 18 */
 19
 20#include <linux/module.h>
 21#include <linux/interrupt.h>
 22#include <linux/irq.h>
 23#include <linux/kernel.h>
 24#include <asm/ptrace.h>
 25#include <linux/sched.h>
 26#include <linux/kernel_stat.h>
 27#include <asm/io.h>
 28#include "ocelot_c_fpga.h"
 29
 30#define CPCI_IRQ_BASE	8
 31
 32static inline int ls1bit8(unsigned int x)
 33{
 34        int b = 7, s;
 35
 36        s =  4; if (((unsigned char)(x <<  4)) == 0) s = 0; b -= s; x <<= s;
 37        s =  2; if (((unsigned char)(x <<  2)) == 0) s = 0; b -= s; x <<= s;
 38        s =  1; if (((unsigned char)(x <<  1)) == 0) s = 0; b -= s;
 39
 40        return b;
 41}
 42
 43/* mask off an interrupt -- 0 is enable, 1 is disable */
 44static inline void mask_cpci_irq(unsigned int irq)
 45{
 46	uint32_t value;
 47
 48	value = OCELOT_FPGA_READ(INTMASK);
 49	value |= 1 << (irq - CPCI_IRQ_BASE);
 50	OCELOT_FPGA_WRITE(value, INTMASK);
 51
 52	/* read the value back to assure that it's really been written */
 53	value = OCELOT_FPGA_READ(INTMASK);
 54}
 55
 56/* unmask an interrupt -- 0 is enable, 1 is disable */
 57static inline void unmask_cpci_irq(unsigned int irq)
 58{
 59	uint32_t value;
 60
 61	value = OCELOT_FPGA_READ(INTMASK);
 62	value &= ~(1 << (irq - CPCI_IRQ_BASE));
 63	OCELOT_FPGA_WRITE(value, INTMASK);
 64
 65	/* read the value back to assure that it's really been written */
 66	value = OCELOT_FPGA_READ(INTMASK);
 67}
 68
 69/*
 70 * Enables the IRQ in the FPGA
 71 */
 72static void enable_cpci_irq(unsigned int irq)
 73{
 74	unmask_cpci_irq(irq);
 75}
 76
 77/*
 78 * Initialize the IRQ in the FPGA
 79 */
 80static unsigned int startup_cpci_irq(unsigned int irq)
 81{
 82	unmask_cpci_irq(irq);
 83	return 0;
 84}
 85
 86/*
 87 * Disables the IRQ in the FPGA
 88 */
 89static void disable_cpci_irq(unsigned int irq)
 90{
 91	mask_cpci_irq(irq);
 92}
 93
 94/*
 95 * Masks and ACKs an IRQ
 96 */
 97static void mask_and_ack_cpci_irq(unsigned int irq)
 98{
 99	mask_cpci_irq(irq);
100}
101
102/*
103 * End IRQ processing
104 */
105static void end_cpci_irq(unsigned int irq)
106{
107	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
108		unmask_cpci_irq(irq);
109}
110
111/*
112 * Interrupt handler for interrupts coming from the FPGA chip.
113 * It could be built in ethernet ports etc...
114 */
115void ll_cpci_irq(struct pt_regs *regs)
116{
117	unsigned int irq_src, irq_mask;
118
119	/* read the interrupt status registers */
120	irq_src = OCELOT_FPGA_READ(INTSTAT);
121	irq_mask = OCELOT_FPGA_READ(INTMASK);
122
123	/* mask for just the interrupts we want */
124	irq_src &= ~irq_mask;
125
126	do_IRQ(ls1bit8(irq_src) + CPCI_IRQ_BASE, regs);
127}
128
129#define shutdown_cpci_irq	disable_cpci_irq
130
131struct hw_interrupt_type cpci_irq_type = {
132	"CPCI/FPGA",
133	startup_cpci_irq,
134	shutdown_cpci_irq,
135	enable_cpci_irq,
136	disable_cpci_irq,
137	mask_and_ack_cpci_irq,
138	end_cpci_irq,
139	NULL
140};
141
142void cpci_irq_init(void)
143{
144	int i;
145
146	/* Reset irq handlers pointers to NULL */
147	for (i = CPCI_IRQ_BASE; i < (CPCI_IRQ_BASE + 8); i++) {
148		irq_desc[i].status = IRQ_DISABLED;
149		irq_desc[i].action = 0;
150		irq_desc[i].depth = 2;
151		irq_desc[i].handler = &cpci_irq_type;
152	}
153}