File Index
Files and directories
Sign in
FILE

irq.c

File preview with syntax highlighting.

linux-6.19.14/arch/sh/boards/mach-se/7724/irq.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * linux/arch/sh/boards/se/7724/irq.c
  4 *
  5 * Copyright (C) 2009 Renesas Solutions Corp.
  6 *
  7 * Kuninori Morimoto <morimoto.kuninori@renesas.com>
  8 *
  9 * Based on  linux/arch/sh/boards/se/7722/irq.c
 10 * Copyright (C) 2007  Nobuhiro Iwamatsu
 11 *
 12 * Hitachi UL SolutionEngine 7724 Support.
 13 */
 14#include <linux/init.h>
 15#include <linux/irq.h>
 16#include <linux/interrupt.h>
 17#include <linux/export.h>
 18#include <linux/topology.h>
 19#include <linux/io.h>
 20#include <linux/err.h>
 21#include <mach-se/mach/se7724.h>
 22
 23struct fpga_irq {
 24	unsigned long  sraddr;
 25	unsigned long  mraddr;
 26	unsigned short mask;
 27	unsigned int   base;
 28};
 29
 30static unsigned int fpga2irq(unsigned int irq)
 31{
 32	if (irq >= IRQ0_BASE &&
 33	    irq <= IRQ0_END)
 34		return IRQ0_IRQ;
 35	else if (irq >= IRQ1_BASE &&
 36		 irq <= IRQ1_END)
 37		return IRQ1_IRQ;
 38	else
 39		return IRQ2_IRQ;
 40}
 41
 42static struct fpga_irq get_fpga_irq(unsigned int irq)
 43{
 44	struct fpga_irq set;
 45
 46	switch (irq) {
 47	case IRQ0_IRQ:
 48		set.sraddr = IRQ0_SR;
 49		set.mraddr = IRQ0_MR;
 50		set.mask   = IRQ0_MASK;
 51		set.base   = IRQ0_BASE;
 52		break;
 53	case IRQ1_IRQ:
 54		set.sraddr = IRQ1_SR;
 55		set.mraddr = IRQ1_MR;
 56		set.mask   = IRQ1_MASK;
 57		set.base   = IRQ1_BASE;
 58		break;
 59	default:
 60		set.sraddr = IRQ2_SR;
 61		set.mraddr = IRQ2_MR;
 62		set.mask   = IRQ2_MASK;
 63		set.base   = IRQ2_BASE;
 64		break;
 65	}
 66
 67	return set;
 68}
 69
 70static void disable_se7724_irq(struct irq_data *data)
 71{
 72	unsigned int irq = data->irq;
 73	struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
 74	unsigned int bit = irq - set.base;
 75	__raw_writew(__raw_readw(set.mraddr) | 0x0001 << bit, set.mraddr);
 76}
 77
 78static void enable_se7724_irq(struct irq_data *data)
 79{
 80	unsigned int irq = data->irq;
 81	struct fpga_irq set = get_fpga_irq(fpga2irq(irq));
 82	unsigned int bit = irq - set.base;
 83	__raw_writew(__raw_readw(set.mraddr) & ~(0x0001 << bit), set.mraddr);
 84}
 85
 86static struct irq_chip se7724_irq_chip __read_mostly = {
 87	.name		= "SE7724-FPGA",
 88	.irq_mask	= disable_se7724_irq,
 89	.irq_unmask	= enable_se7724_irq,
 90};
 91
 92static void se7724_irq_demux(struct irq_desc *desc)
 93{
 94	unsigned int irq = irq_desc_get_irq(desc);
 95	struct fpga_irq set = get_fpga_irq(irq);
 96	unsigned short intv = __raw_readw(set.sraddr);
 97	unsigned int ext_irq = set.base;
 98
 99	intv &= set.mask;
100
101	for (; intv; intv >>= 1, ext_irq++) {
102		if (!(intv & 1))
103			continue;
104
105		generic_handle_irq(ext_irq);
106	}
107}
108
109/*
110 * Initialize IRQ setting
111 */
112void __init init_se7724_IRQ(void)
113{
114	int irq_base, i;
115
116	__raw_writew(0xffff, IRQ0_MR);  /* mask all */
117	__raw_writew(0xffff, IRQ1_MR);  /* mask all */
118	__raw_writew(0xffff, IRQ2_MR);  /* mask all */
119	__raw_writew(0x0000, IRQ0_SR);  /* clear irq */
120	__raw_writew(0x0000, IRQ1_SR);  /* clear irq */
121	__raw_writew(0x0000, IRQ2_SR);  /* clear irq */
122	__raw_writew(0x002a, IRQ_MODE); /* set irq type */
123
124	irq_base = irq_alloc_descs(SE7724_FPGA_IRQ_BASE, SE7724_FPGA_IRQ_BASE,
125				   SE7724_FPGA_IRQ_NR, numa_node_id());
126	if (IS_ERR_VALUE(irq_base)) {
127		pr_err("%s: failed hooking irqs for FPGA\n", __func__);
128		return;
129	}
130
131	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++)
132		irq_set_chip_and_handler_name(irq_base + i, &se7724_irq_chip,
133					      handle_level_irq, "level");
134
135	irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux);
136	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
137
138	irq_set_chained_handler(IRQ1_IRQ, se7724_irq_demux);
139	irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
140
141	irq_set_chained_handler(IRQ2_IRQ, se7724_irq_demux);
142	irq_set_irq_type(IRQ2_IRQ, IRQ_TYPE_LEVEL_LOW);
143}
~/ Read-only file preview.