1/* 2 * linux/arch/m32r/platforms/usrv/setup.c 3 * 4 * Setup routines for MITSUBISHI uServer 5 * 6 * Copyright (c) 2001, 2002, 2003 Hiroyuki Kondo, Hirokazu Takata, 7 * Hitoshi Yamamoto 8 */ 9 10#include <linux/irq.h> 11#include <linux/kernel.h> 12#include <linux/init.h> 13 14#include <asm/m32r.h> 15#include <asm/io.h> 16 17#define irq2port(x) (M32R_ICU_CR1_PORTL + ((x - 1) * sizeof(unsigned long))) 18 19icu_data_t icu_data[M32700UT_NUM_CPU_IRQ]; 20 21static void disable_mappi_irq(unsigned int irq) 22{ 23 unsigned long port, data; 24 25 port = irq2port(irq); 26 data = icu_data[irq].icucr|M32R_ICUCR_ILEVEL7; 27 outl(data, port); 28} 29 30static void enable_mappi_irq(unsigned int irq) 31{ 32 unsigned long port, data; 33 34 port = irq2port(irq); 35 data = icu_data[irq].icucr|M32R_ICUCR_IEN|M32R_ICUCR_ILEVEL6; 36 outl(data, port); 37} 38 39static void mask_mappi(struct irq_data *data) 40{ 41 disable_mappi_irq(data->irq); 42} 43 44static void unmask_mappi(struct irq_data *data) 45{ 46 enable_mappi_irq(data->irq); 47} 48 49static void shutdown_mappi(struct irq_data *data) 50{ 51 unsigned long port; 52 53 port = irq2port(data->irq); 54 outl(M32R_ICUCR_ILEVEL7, port); 55} 56 57static struct irq_chip mappi_irq_type = 58{ 59 .name = "M32700-IRQ", 60 .irq_shutdown = shutdown_mappi, 61 .irq_mask = mask_mappi, 62 .irq_unmask = unmask_mappi, 63}; 64 65/* 66 * Interrupt Control Unit of PLD on M32700UT (Level 2) 67 */ 68#define irq2pldirq(x) ((x) - M32700UT_PLD_IRQ_BASE) 69#define pldirq2port(x) (unsigned long)((int)PLD_ICUCR1 + \ 70 (((x) - 1) * sizeof(unsigned short))) 71 72typedef struct { 73 unsigned short icucr; /* ICU Control Register */ 74} pld_icu_data_t; 75 76static pld_icu_data_t pld_icu_data[M32700UT_NUM_PLD_IRQ]; 77 78static void disable_m32700ut_pld_irq(unsigned int irq) 79{ 80 unsigned long port, data; 81 unsigned int pldirq; 82 83 pldirq = irq2pldirq(irq); 84 port = pldirq2port(pldirq); 85 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_ILEVEL7; 86 outw(data, port); 87} 88 89static void enable_m32700ut_pld_irq(unsigned int irq) 90{ 91 unsigned long port, data; 92 unsigned int pldirq; 93 94 pldirq = irq2pldirq(irq); 95 port = pldirq2port(pldirq); 96 data = pld_icu_data[pldirq].icucr|PLD_ICUCR_IEN|PLD_ICUCR_ILEVEL6; 97 outw(data, port); 98} 99 100static void mask_m32700ut_pld(struct irq_data *data) 101{ 102 disable_m32700ut_pld_irq(data->irq); 103} 104 105static void unmask_m32700ut_pld(struct irq_data *data) 106{ 107 enable_m32700ut_pld_irq(data->irq); 108 enable_mappi_irq(M32R_IRQ_INT1); 109} 110 111static void shutdown_m32700ut_pld(struct irq_data *data) 112{ 113 unsigned long port; 114 unsigned int pldirq; 115 116 pldirq = irq2pldirq(data->irq); 117 port = pldirq2port(pldirq); 118 outw(PLD_ICUCR_ILEVEL7, port); 119} 120 121static struct irq_chip m32700ut_pld_irq_type = 122{ 123 .name = "USRV-PLD-IRQ", 124 .irq_shutdown = shutdown_m32700ut_pld, 125 .irq_mask = mask_m32700ut_pld, 126 .irq_unmask = unmask_m32700ut_pld, 127}; 128 129void __init init_IRQ(void) 130{ 131 static int once = 0; 132 int i; 133 134 if (once) 135 return; 136 else 137 once++; 138 139 /* MFT2 : system timer */ 140 irq_set_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type, 141 handle_level_irq); 142 icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN; 143 disable_mappi_irq(M32R_IRQ_MFT2); 144 145#if defined(CONFIG_SERIAL_M32R_SIO) 146 /* SIO0_R : uart receive data */ 147 irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type, 148 handle_level_irq); 149 icu_data[M32R_IRQ_SIO0_R].icucr = 0; 150 disable_mappi_irq(M32R_IRQ_SIO0_R); 151 152 /* SIO0_S : uart send data */ 153 irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type, 154 handle_level_irq); 155 icu_data[M32R_IRQ_SIO0_S].icucr = 0; 156 disable_mappi_irq(M32R_IRQ_SIO0_S); 157 158 /* SIO1_R : uart receive data */ 159 irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type, 160 handle_level_irq); 161 icu_data[M32R_IRQ_SIO1_R].icucr = 0; 162 disable_mappi_irq(M32R_IRQ_SIO1_R); 163 164 /* SIO1_S : uart send data */ 165 irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type, 166 handle_level_irq); 167 icu_data[M32R_IRQ_SIO1_S].icucr = 0; 168 disable_mappi_irq(M32R_IRQ_SIO1_S); 169#endif /* CONFIG_SERIAL_M32R_SIO */ 170 171 /* INT#67-#71: CFC#0 IREQ on PLD */ 172 for (i = 0 ; i < CONFIG_M32R_CFC_NUM ; i++ ) { 173 irq_set_chip_and_handler(PLD_IRQ_CF0 + i, 174 &m32700ut_pld_irq_type, 175 handle_level_irq); 176 pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr 177 = PLD_ICUCR_ISMOD01; /* 'L' level sense */ 178 disable_m32700ut_pld_irq(PLD_IRQ_CF0 + i); 179 } 180 181#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE) 182 /* INT#76: 16552D#0 IREQ on PLD */ 183 irq_set_chip_and_handler(PLD_IRQ_UART0, &m32700ut_pld_irq_type, 184 handle_level_irq); 185 pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr 186 = PLD_ICUCR_ISMOD03; /* 'H' level sense */ 187 disable_m32700ut_pld_irq(PLD_IRQ_UART0); 188 189 /* INT#77: 16552D#1 IREQ on PLD */ 190 irq_set_chip_and_handler(PLD_IRQ_UART1, &m32700ut_pld_irq_type, 191 handle_level_irq); 192 pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr 193 = PLD_ICUCR_ISMOD03; /* 'H' level sense */ 194 disable_m32700ut_pld_irq(PLD_IRQ_UART1); 195#endif /* CONFIG_SERIAL_8250 || CONFIG_SERIAL_8250_MODULE */ 196 197#if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE) 198 /* INT#80: AK4524 IREQ on PLD */ 199 irq_set_chip_and_handler(PLD_IRQ_SNDINT, &m32700ut_pld_irq_type, 200 handle_level_irq); 201 pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr 202 = PLD_ICUCR_ISMOD01; /* 'L' level sense */ 203 disable_m32700ut_pld_irq(PLD_IRQ_SNDINT); 204#endif /* CONFIG_IDC_AK4524 || CONFIG_IDC_AK4524_MODULE */ 205 206 /* 207 * INT1# is used for UART, MMC, CF Controller in FPGA. 208 * We enable it here. 209 */ 210 icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD11; 211 enable_mappi_irq(M32R_IRQ_INT1); 212} 213