1da2014a2SPaul Mundt /* 2da2014a2SPaul Mundt * linux/arch/sh/boards/se/7206/irq.c 3da2014a2SPaul Mundt * 4da2014a2SPaul Mundt * Copyright (C) 2005,2006 Yoshinori Sato 5da2014a2SPaul Mundt * 6da2014a2SPaul Mundt * Hitachi SolutionEngine Support. 7da2014a2SPaul Mundt * 8da2014a2SPaul Mundt */ 9da2014a2SPaul Mundt #include <linux/init.h> 10da2014a2SPaul Mundt #include <linux/irq.h> 11da2014a2SPaul Mundt #include <linux/io.h> 12da2014a2SPaul Mundt #include <linux/interrupt.h> 13939a24a6SPaul Mundt #include <mach-se/mach/se7206.h> 14da2014a2SPaul Mundt 15da2014a2SPaul Mundt #define INTSTS0 0x31800000 16da2014a2SPaul Mundt #define INTSTS1 0x31800002 17da2014a2SPaul Mundt #define INTMSK0 0x31800004 18da2014a2SPaul Mundt #define INTMSK1 0x31800006 19da2014a2SPaul Mundt #define INTSEL 0x31800008 20da2014a2SPaul Mundt 21da2014a2SPaul Mundt #define IRQ0_IRQ 64 22da2014a2SPaul Mundt #define IRQ1_IRQ 65 23da2014a2SPaul Mundt #define IRQ3_IRQ 67 24da2014a2SPaul Mundt 25da2014a2SPaul Mundt #define INTC_IPR01 0xfffe0818 26da2014a2SPaul Mundt #define INTC_ICR1 0xfffe0802 27da2014a2SPaul Mundt 2815ff2c67SPaul Mundt static void disable_se7206_irq(struct irq_data *data) 29da2014a2SPaul Mundt { 3015ff2c67SPaul Mundt unsigned int irq = data->irq; 31da2014a2SPaul Mundt unsigned short val; 32da2014a2SPaul Mundt unsigned short mask = 0xffff ^ (0x0f << 4 * (3 - (IRQ0_IRQ - irq))); 33da2014a2SPaul Mundt unsigned short msk0,msk1; 34da2014a2SPaul Mundt 35da2014a2SPaul Mundt /* Set the priority in IPR to 0 */ 369d56dd3bSPaul Mundt val = __raw_readw(INTC_IPR01); 37da2014a2SPaul Mundt val &= mask; 389d56dd3bSPaul Mundt __raw_writew(val, INTC_IPR01); 39da2014a2SPaul Mundt /* FPGA mask set */ 409d56dd3bSPaul Mundt msk0 = __raw_readw(INTMSK0); 419d56dd3bSPaul Mundt msk1 = __raw_readw(INTMSK1); 42da2014a2SPaul Mundt 43da2014a2SPaul Mundt switch (irq) { 44da2014a2SPaul Mundt case IRQ0_IRQ: 45da2014a2SPaul Mundt msk0 |= 0x0010; 46da2014a2SPaul Mundt break; 47da2014a2SPaul Mundt case IRQ1_IRQ: 48da2014a2SPaul Mundt msk0 |= 0x000f; 49da2014a2SPaul Mundt break; 50da2014a2SPaul Mundt case IRQ3_IRQ: 51da2014a2SPaul Mundt msk0 |= 0x0f00; 52da2014a2SPaul Mundt msk1 |= 0x00ff; 53da2014a2SPaul Mundt break; 54da2014a2SPaul Mundt } 559d56dd3bSPaul Mundt __raw_writew(msk0, INTMSK0); 569d56dd3bSPaul Mundt __raw_writew(msk1, INTMSK1); 57da2014a2SPaul Mundt } 58da2014a2SPaul Mundt 5915ff2c67SPaul Mundt static void enable_se7206_irq(struct irq_data *data) 60da2014a2SPaul Mundt { 6115ff2c67SPaul Mundt unsigned int irq = data->irq; 62da2014a2SPaul Mundt unsigned short val; 63da2014a2SPaul Mundt unsigned short value = (0x0001 << 4 * (3 - (IRQ0_IRQ - irq))); 64da2014a2SPaul Mundt unsigned short msk0,msk1; 65da2014a2SPaul Mundt 66da2014a2SPaul Mundt /* Set priority in IPR back to original value */ 679d56dd3bSPaul Mundt val = __raw_readw(INTC_IPR01); 68da2014a2SPaul Mundt val |= value; 699d56dd3bSPaul Mundt __raw_writew(val, INTC_IPR01); 70da2014a2SPaul Mundt 71da2014a2SPaul Mundt /* FPGA mask reset */ 729d56dd3bSPaul Mundt msk0 = __raw_readw(INTMSK0); 739d56dd3bSPaul Mundt msk1 = __raw_readw(INTMSK1); 74da2014a2SPaul Mundt 75da2014a2SPaul Mundt switch (irq) { 76da2014a2SPaul Mundt case IRQ0_IRQ: 77da2014a2SPaul Mundt msk0 &= ~0x0010; 78da2014a2SPaul Mundt break; 79da2014a2SPaul Mundt case IRQ1_IRQ: 80da2014a2SPaul Mundt msk0 &= ~0x000f; 81da2014a2SPaul Mundt break; 82da2014a2SPaul Mundt case IRQ3_IRQ: 83da2014a2SPaul Mundt msk0 &= ~0x0f00; 84da2014a2SPaul Mundt msk1 &= ~0x00ff; 85da2014a2SPaul Mundt break; 86da2014a2SPaul Mundt } 879d56dd3bSPaul Mundt __raw_writew(msk0, INTMSK0); 889d56dd3bSPaul Mundt __raw_writew(msk1, INTMSK1); 89da2014a2SPaul Mundt } 90da2014a2SPaul Mundt 9115ff2c67SPaul Mundt static void eoi_se7206_irq(struct irq_data *data) 92da2014a2SPaul Mundt { 93da2014a2SPaul Mundt unsigned short sts0,sts1; 9415ff2c67SPaul Mundt unsigned int irq = data->irq; 95da2014a2SPaul Mundt 96a821b279SThomas Gleixner if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data)) 9715ff2c67SPaul Mundt enable_se7206_irq(data); 98da2014a2SPaul Mundt /* FPGA isr clear */ 999d56dd3bSPaul Mundt sts0 = __raw_readw(INTSTS0); 1009d56dd3bSPaul Mundt sts1 = __raw_readw(INTSTS1); 101da2014a2SPaul Mundt 102da2014a2SPaul Mundt switch (irq) { 103da2014a2SPaul Mundt case IRQ0_IRQ: 104da2014a2SPaul Mundt sts0 &= ~0x0010; 105da2014a2SPaul Mundt break; 106da2014a2SPaul Mundt case IRQ1_IRQ: 107da2014a2SPaul Mundt sts0 &= ~0x000f; 108da2014a2SPaul Mundt break; 109da2014a2SPaul Mundt case IRQ3_IRQ: 110da2014a2SPaul Mundt sts0 &= ~0x0f00; 111da2014a2SPaul Mundt sts1 &= ~0x00ff; 112da2014a2SPaul Mundt break; 113da2014a2SPaul Mundt } 1149d56dd3bSPaul Mundt __raw_writew(sts0, INTSTS0); 1159d56dd3bSPaul Mundt __raw_writew(sts1, INTSTS1); 116da2014a2SPaul Mundt } 117da2014a2SPaul Mundt 118da2014a2SPaul Mundt static struct irq_chip se7206_irq_chip __read_mostly = { 119da2014a2SPaul Mundt .name = "SE7206-FPGA", 12015ff2c67SPaul Mundt .irq_mask = disable_se7206_irq, 12115ff2c67SPaul Mundt .irq_unmask = enable_se7206_irq, 12215ff2c67SPaul Mundt .irq_eoi = eoi_se7206_irq, 123da2014a2SPaul Mundt }; 124da2014a2SPaul Mundt 125da2014a2SPaul Mundt static void make_se7206_irq(unsigned int irq) 126da2014a2SPaul Mundt { 127da2014a2SPaul Mundt disable_irq_nosync(irq); 128fcb8918fSThomas Gleixner irq_set_chip_and_handler_name(irq, &se7206_irq_chip, 129da2014a2SPaul Mundt handle_level_irq, "level"); 13015ff2c67SPaul Mundt disable_se7206_irq(irq_get_irq_data(irq)); 131da2014a2SPaul Mundt } 132da2014a2SPaul Mundt 133da2014a2SPaul Mundt /* 134da2014a2SPaul Mundt * Initialize IRQ setting 135da2014a2SPaul Mundt */ 136da2014a2SPaul Mundt void __init init_se7206_IRQ(void) 137da2014a2SPaul Mundt { 138da2014a2SPaul Mundt make_se7206_irq(IRQ0_IRQ); /* SMC91C111 */ 139da2014a2SPaul Mundt make_se7206_irq(IRQ1_IRQ); /* ATA */ 140da2014a2SPaul Mundt make_se7206_irq(IRQ3_IRQ); /* SLOT / PCM */ 141e96ce8ebSPaul Mundt 14227434f0aSPaul Mundt __raw_writew(__raw_readw(INTC_ICR1) | 0x000b, INTC_ICR1); /* ICR1 */ 143da2014a2SPaul Mundt 144da2014a2SPaul Mundt /* FPGA System register setup*/ 1459d56dd3bSPaul Mundt __raw_writew(0x0000,INTSTS0); /* Clear INTSTS0 */ 1469d56dd3bSPaul Mundt __raw_writew(0x0000,INTSTS1); /* Clear INTSTS1 */ 147e96ce8ebSPaul Mundt 148da2014a2SPaul Mundt /* IRQ0=LAN, IRQ1=ATA, IRQ3=SLT,PCM */ 1499d56dd3bSPaul Mundt __raw_writew(0x0001,INTSEL); 150da2014a2SPaul Mundt } 151