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