arch/powerpc/platforms/85xx/socrates_fpga_pic.c

Source file repositories/reference/linux-study-clean/arch/powerpc/platforms/85xx/socrates_fpga_pic.c

File Facts

System
Linux kernel
Corpus path
arch/powerpc/platforms/85xx/socrates_fpga_pic.c
Extension
.c
Size
8445 bytes
Lines
311
Domain
Architecture Layer
Bucket
arch/powerpc
Inferred role
Architecture Layer: implementation source
Status
source implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct socrates_fpga_irq_info {
	unsigned int irq_line;
	int type;
};

/*
 * Interrupt routing and type table
 *
 * IRQ_TYPE_NONE means the interrupt type is configurable,
 * otherwise it's fixed to the specified value.
 */
static struct socrates_fpga_irq_info fpga_irqs[SOCRATES_FPGA_NUM_IRQS] = {
	[0] = {0, IRQ_TYPE_NONE},
	[1] = {0, IRQ_TYPE_LEVEL_HIGH},
	[2] = {0, IRQ_TYPE_LEVEL_LOW},
	[3] = {0, IRQ_TYPE_NONE},
	[4] = {0, IRQ_TYPE_NONE},
	[5] = {0, IRQ_TYPE_NONE},
	[6] = {0, IRQ_TYPE_NONE},
	[7] = {0, IRQ_TYPE_NONE},
	[8] = {0, IRQ_TYPE_LEVEL_HIGH},
};

static DEFINE_RAW_SPINLOCK(socrates_fpga_pic_lock);

static void __iomem *socrates_fpga_pic_iobase;
static struct irq_domain *socrates_fpga_pic_irq_host;
static unsigned int socrates_fpga_irqs[3];

static inline uint32_t socrates_fpga_pic_read(int reg)
{
	return in_be32(socrates_fpga_pic_iobase + reg);
}

static inline void socrates_fpga_pic_write(int reg, uint32_t val)
{
	out_be32(socrates_fpga_pic_iobase + reg, val);
}

static inline unsigned int socrates_fpga_pic_get_irq(unsigned int irq)
{
	uint32_t cause;
	unsigned long flags;
	int i;

	/* Check irq line routed to the MPIC */
	for (i = 0; i < 3; i++) {
		if (irq == socrates_fpga_irqs[i])
			break;
	}
	if (i == 3)
		return 0;

	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
	cause = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(i));
	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
	for (i = SOCRATES_FPGA_NUM_IRQS - 1; i >= 0; i--) {
		if (cause >> (i + 16))
			break;
	}
	return irq_find_mapping(socrates_fpga_pic_irq_host,
			(irq_hw_number_t)i);
}

static void socrates_fpga_pic_cascade(struct irq_desc *desc)
{
	struct irq_chip *chip = irq_desc_get_chip(desc);
	unsigned int irq = irq_desc_get_irq(desc);
	unsigned int cascade_irq;

	/*
	 * See if we actually have an interrupt, call generic handling code if
	 * we do.
	 */
	cascade_irq = socrates_fpga_pic_get_irq(irq);

	if (cascade_irq)
		generic_handle_irq(cascade_irq);
	chip->irq_eoi(&desc->irq_data);
}

static void socrates_fpga_pic_ack(struct irq_data *d)
{
	unsigned long flags;
	unsigned int irq_line, hwirq = irqd_to_hwirq(d);
	uint32_t mask;

	irq_line = fpga_irqs[hwirq].irq_line;
	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
	mask = socrates_fpga_pic_read(FPGA_PIC_IRQMASK(irq_line))

Annotation

Implementation Notes