162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * linux/arch/sh/boards/se/7206/irq.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (C) 2005,2006 Yoshinori Sato
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Hitachi SolutionEngine Support.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci#include <linux/init.h>
1162306a36Sopenharmony_ci#include <linux/irq.h>
1262306a36Sopenharmony_ci#include <linux/io.h>
1362306a36Sopenharmony_ci#include <linux/interrupt.h>
1462306a36Sopenharmony_ci#include <mach-se/mach/se7206.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#define INTSTS0 0x31800000
1762306a36Sopenharmony_ci#define INTSTS1 0x31800002
1862306a36Sopenharmony_ci#define INTMSK0 0x31800004
1962306a36Sopenharmony_ci#define INTMSK1 0x31800006
2062306a36Sopenharmony_ci#define INTSEL  0x31800008
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_ci#define IRQ0_IRQ 64
2362306a36Sopenharmony_ci#define IRQ1_IRQ 65
2462306a36Sopenharmony_ci#define IRQ3_IRQ 67
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#define INTC_IPR01 0xfffe0818
2762306a36Sopenharmony_ci#define INTC_ICR1  0xfffe0802
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic void disable_se7206_irq(struct irq_data *data)
3062306a36Sopenharmony_ci{
3162306a36Sopenharmony_ci	unsigned int irq = data->irq;
3262306a36Sopenharmony_ci	unsigned short val;
3362306a36Sopenharmony_ci	unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq)));
3462306a36Sopenharmony_ci	unsigned short msk0,msk1;
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ci	/* Set the priority in IPR to 0 */
3762306a36Sopenharmony_ci	val = __raw_readw(INTC_IPR01);
3862306a36Sopenharmony_ci	val &= mask;
3962306a36Sopenharmony_ci	__raw_writew(val, INTC_IPR01);
4062306a36Sopenharmony_ci	/* FPGA mask set */
4162306a36Sopenharmony_ci	msk0 = __raw_readw(INTMSK0);
4262306a36Sopenharmony_ci	msk1 = __raw_readw(INTMSK1);
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	switch (irq) {
4562306a36Sopenharmony_ci	case IRQ0_IRQ:
4662306a36Sopenharmony_ci		msk0 |= 0x0010;
4762306a36Sopenharmony_ci		break;
4862306a36Sopenharmony_ci	case IRQ1_IRQ:
4962306a36Sopenharmony_ci		msk0 |= 0x000f;
5062306a36Sopenharmony_ci		break;
5162306a36Sopenharmony_ci	case IRQ3_IRQ:
5262306a36Sopenharmony_ci		msk0 |= 0x0f00;
5362306a36Sopenharmony_ci		msk1 |= 0x00ff;
5462306a36Sopenharmony_ci		break;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci	__raw_writew(msk0, INTMSK0);
5762306a36Sopenharmony_ci	__raw_writew(msk1, INTMSK1);
5862306a36Sopenharmony_ci}
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistatic void enable_se7206_irq(struct irq_data *data)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	unsigned int irq = data->irq;
6362306a36Sopenharmony_ci	unsigned short val;
6462306a36Sopenharmony_ci	unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq)));
6562306a36Sopenharmony_ci	unsigned short msk0,msk1;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	/* Set priority in IPR back to original value */
6862306a36Sopenharmony_ci	val = __raw_readw(INTC_IPR01);
6962306a36Sopenharmony_ci	val |= value;
7062306a36Sopenharmony_ci	__raw_writew(val, INTC_IPR01);
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	/* FPGA mask reset */
7362306a36Sopenharmony_ci	msk0 = __raw_readw(INTMSK0);
7462306a36Sopenharmony_ci	msk1 = __raw_readw(INTMSK1);
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	switch (irq) {
7762306a36Sopenharmony_ci	case IRQ0_IRQ:
7862306a36Sopenharmony_ci		msk0 &= ~0x0010;
7962306a36Sopenharmony_ci		break;
8062306a36Sopenharmony_ci	case IRQ1_IRQ:
8162306a36Sopenharmony_ci		msk0 &= ~0x000f;
8262306a36Sopenharmony_ci		break;
8362306a36Sopenharmony_ci	case IRQ3_IRQ:
8462306a36Sopenharmony_ci		msk0 &= ~0x0f00;
8562306a36Sopenharmony_ci		msk1 &= ~0x00ff;
8662306a36Sopenharmony_ci		break;
8762306a36Sopenharmony_ci	}
8862306a36Sopenharmony_ci	__raw_writew(msk0, INTMSK0);
8962306a36Sopenharmony_ci	__raw_writew(msk1, INTMSK1);
9062306a36Sopenharmony_ci}
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistatic void eoi_se7206_irq(struct irq_data *data)
9362306a36Sopenharmony_ci{
9462306a36Sopenharmony_ci	unsigned short sts0,sts1;
9562306a36Sopenharmony_ci	unsigned int irq = data->irq;
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data))
9862306a36Sopenharmony_ci		enable_se7206_irq(data);
9962306a36Sopenharmony_ci	/* FPGA isr clear */
10062306a36Sopenharmony_ci	sts0 = __raw_readw(INTSTS0);
10162306a36Sopenharmony_ci	sts1 = __raw_readw(INTSTS1);
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_ci	switch (irq) {
10462306a36Sopenharmony_ci	case IRQ0_IRQ:
10562306a36Sopenharmony_ci		sts0 &= ~0x0010;
10662306a36Sopenharmony_ci		break;
10762306a36Sopenharmony_ci	case IRQ1_IRQ:
10862306a36Sopenharmony_ci		sts0 &= ~0x000f;
10962306a36Sopenharmony_ci		break;
11062306a36Sopenharmony_ci	case IRQ3_IRQ:
11162306a36Sopenharmony_ci		sts0 &= ~0x0f00;
11262306a36Sopenharmony_ci		sts1 &= ~0x00ff;
11362306a36Sopenharmony_ci		break;
11462306a36Sopenharmony_ci	}
11562306a36Sopenharmony_ci	__raw_writew(sts0, INTSTS0);
11662306a36Sopenharmony_ci	__raw_writew(sts1, INTSTS1);
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_cistatic struct irq_chip se7206_irq_chip __read_mostly = {
12062306a36Sopenharmony_ci	.name		= "SE7206-FPGA",
12162306a36Sopenharmony_ci	.irq_mask	= disable_se7206_irq,
12262306a36Sopenharmony_ci	.irq_unmask	= enable_se7206_irq,
12362306a36Sopenharmony_ci	.irq_eoi	= eoi_se7206_irq,
12462306a36Sopenharmony_ci};
12562306a36Sopenharmony_ci
12662306a36Sopenharmony_cistatic void make_se7206_irq(unsigned int irq)
12762306a36Sopenharmony_ci{
12862306a36Sopenharmony_ci	disable_irq_nosync(irq);
12962306a36Sopenharmony_ci	irq_set_chip_and_handler_name(irq, &se7206_irq_chip,
13062306a36Sopenharmony_ci				      handle_level_irq, "level");
13162306a36Sopenharmony_ci	disable_se7206_irq(irq_get_irq_data(irq));
13262306a36Sopenharmony_ci}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci/*
13562306a36Sopenharmony_ci * Initialize IRQ setting
13662306a36Sopenharmony_ci */
13762306a36Sopenharmony_civoid __init init_se7206_IRQ(void)
13862306a36Sopenharmony_ci{
13962306a36Sopenharmony_ci	make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */
14062306a36Sopenharmony_ci	make_se7206_irq(IRQ1_IRQ); /* ATA */
14162306a36Sopenharmony_ci	make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	__raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ci	/* FPGA System register setup*/
14662306a36Sopenharmony_ci	__raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */
14762306a36Sopenharmony_ci	__raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */
14862306a36Sopenharmony_ci
14962306a36Sopenharmony_ci	/* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */
15062306a36Sopenharmony_ci	__raw_writew(0x0001,INTSEL);
15162306a36Sopenharmony_ci}
152