| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 1 | /* | 
 | 2 |  * sh73a0 processor support - INTC hardware block | 
 | 3 |  * | 
 | 4 |  * Copyright (C) 2010  Magnus Damm | 
 | 5 |  * | 
 | 6 |  * This program is free software; you can redistribute it and/or modify | 
 | 7 |  * it under the terms of the GNU General Public License as published by | 
 | 8 |  * the Free Software Foundation; version 2 of the License. | 
 | 9 |  * | 
 | 10 |  * This program is distributed in the hope that it will be useful, | 
 | 11 |  * but WITHOUT ANY WARRANTY; without even the implied warranty of | 
 | 12 |  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
 | 13 |  * GNU General Public License for more details. | 
 | 14 |  * | 
 | 15 |  * You should have received a copy of the GNU General Public License | 
 | 16 |  * along with this program; if not, write to the Free Software | 
 | 17 |  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA | 
 | 18 |  */ | 
 | 19 | #include <linux/kernel.h> | 
 | 20 | #include <linux/init.h> | 
 | 21 | #include <linux/interrupt.h> | 
 | 22 | #include <linux/irq.h> | 
 | 23 | #include <linux/io.h> | 
 | 24 | #include <linux/sh_intc.h> | 
| Magnus Damm | a199305 | 2011-10-12 16:21:42 +0900 | [diff] [blame] | 25 | #include <mach/intc.h> | 
| Magnus Damm | 566aad3 | 2011-10-17 18:00:52 +0900 | [diff] [blame] | 26 | #include <mach/sh73a0.h> | 
| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 27 | #include <asm/hardware/gic.h> | 
 | 28 | #include <asm/mach-types.h> | 
 | 29 | #include <asm/mach/arch.h> | 
 | 30 |  | 
 | 31 | enum { | 
 | 32 | 	UNUSED = 0, | 
 | 33 |  | 
 | 34 | 	/* interrupt sources INTCS */ | 
 | 35 | 	PINTCS_PINT1, PINTCS_PINT2, | 
 | 36 | 	RTDMAC_0_DEI0, RTDMAC_0_DEI1, RTDMAC_0_DEI2, RTDMAC_0_DEI3, | 
 | 37 | 	CEU, MFI, BBIF2, VPU, TSIF1, _3DG_SGX543, _2DDMAC_2DDM0, | 
 | 38 | 	RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR, | 
 | 39 | 	KEYSC_KEY, VINT, MSIOF, | 
 | 40 | 	TMU0_TUNI00, TMU0_TUNI01, TMU0_TUNI02, | 
 | 41 | 	CMT0, TSIF0, CMT2, LMB, MSUG, MSU_MSU, MSU_MSU2, | 
 | 42 | 	CTI, RWDT0, ICB, PEP, ASA, JPU_JPEG, LCDC, LCRC, | 
 | 43 | 	RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9, | 
 | 44 | 	RTDMAC_3_DEI10, RTDMAC_3_DEI11, | 
 | 45 | 	FRC, GCU, LCDC1, CSIRX, | 
 | 46 | 	DSITX0_DSITX00, DSITX0_DSITX01, | 
 | 47 | 	SPU2_SPU0, SPU2_SPU1, FSI, | 
 | 48 | 	TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, | 
 | 49 | 	TSIF2, CMT4, MFIS2, CPORTS2R, TSG, DMASCH1, SCUW, | 
 | 50 | 	VIO60, VIO61, CEU21, CSI21, DSITX1_DSITX10, DSITX1_DSITX11, | 
 | 51 | 	DISP, DSRV, EMUX2_EMUX20I, EMUX2_EMUX21I, | 
 | 52 | 	MSTIF0_MST00I, MSTIF0_MST01I, MSTIF1_MST10I, MSTIF1_MST11I, | 
 | 53 | 	SPUV, | 
 | 54 |  | 
 | 55 | 	/* interrupt groups INTCS */ | 
 | 56 | 	RTDMAC_0, RTDMAC_1, RTDMAC_2, RTDMAC_3, | 
 | 57 | 	DSITX0, SPU2, TMU1, MSU, | 
 | 58 | }; | 
 | 59 |  | 
 | 60 | static struct intc_vect intcs_vectors[] = { | 
 | 61 | 	INTCS_VECT(PINTCS_PINT1, 0x0600), INTCS_VECT(PINTCS_PINT2, 0x0620), | 
 | 62 | 	INTCS_VECT(RTDMAC_0_DEI0, 0x0800), INTCS_VECT(RTDMAC_0_DEI1, 0x0820), | 
 | 63 | 	INTCS_VECT(RTDMAC_0_DEI2, 0x0840), INTCS_VECT(RTDMAC_0_DEI3, 0x0860), | 
 | 64 | 	INTCS_VECT(CEU, 0x0880), INTCS_VECT(MFI, 0x0900), | 
 | 65 | 	INTCS_VECT(BBIF2, 0x0960), INTCS_VECT(VPU, 0x0980), | 
 | 66 | 	INTCS_VECT(TSIF1, 0x09a0), INTCS_VECT(_3DG_SGX543, 0x09e0), | 
 | 67 | 	INTCS_VECT(_2DDMAC_2DDM0, 0x0a00), | 
 | 68 | 	INTCS_VECT(RTDMAC_1_DEI4, 0x0b80), INTCS_VECT(RTDMAC_1_DEI5, 0x0ba0), | 
 | 69 | 	INTCS_VECT(RTDMAC_1_DADERR, 0x0bc0), | 
 | 70 | 	INTCS_VECT(KEYSC_KEY, 0x0be0), INTCS_VECT(VINT, 0x0c80), | 
 | 71 | 	INTCS_VECT(MSIOF, 0x0d20), | 
 | 72 | 	INTCS_VECT(TMU0_TUNI00, 0x0e80), INTCS_VECT(TMU0_TUNI01, 0x0ea0), | 
 | 73 | 	INTCS_VECT(TMU0_TUNI02, 0x0ec0), | 
 | 74 | 	INTCS_VECT(CMT0, 0x0f00), INTCS_VECT(TSIF0, 0x0f20), | 
 | 75 | 	INTCS_VECT(CMT2, 0x0f40), INTCS_VECT(LMB, 0x0f60), | 
 | 76 | 	INTCS_VECT(MSUG, 0x0f80), | 
 | 77 | 	INTCS_VECT(MSU_MSU, 0x0fa0), INTCS_VECT(MSU_MSU2, 0x0fc0), | 
 | 78 | 	INTCS_VECT(CTI, 0x0400), INTCS_VECT(RWDT0, 0x0440), | 
 | 79 | 	INTCS_VECT(ICB, 0x0480), INTCS_VECT(PEP, 0x04a0), | 
 | 80 | 	INTCS_VECT(ASA, 0x04c0), INTCS_VECT(JPU_JPEG, 0x0560), | 
 | 81 | 	INTCS_VECT(LCDC, 0x0580), INTCS_VECT(LCRC, 0x05a0), | 
 | 82 | 	INTCS_VECT(RTDMAC_2_DEI6, 0x1300), INTCS_VECT(RTDMAC_2_DEI7, 0x1320), | 
 | 83 | 	INTCS_VECT(RTDMAC_2_DEI8, 0x1340), INTCS_VECT(RTDMAC_2_DEI9, 0x1360), | 
 | 84 | 	INTCS_VECT(RTDMAC_3_DEI10, 0x1380), INTCS_VECT(RTDMAC_3_DEI11, 0x13a0), | 
 | 85 | 	INTCS_VECT(FRC, 0x1700), INTCS_VECT(GCU, 0x1760), | 
 | 86 | 	INTCS_VECT(LCDC1, 0x1780), INTCS_VECT(CSIRX, 0x17a0), | 
 | 87 | 	INTCS_VECT(DSITX0_DSITX00, 0x17c0), INTCS_VECT(DSITX0_DSITX01, 0x17e0), | 
 | 88 | 	INTCS_VECT(SPU2_SPU0, 0x1800), INTCS_VECT(SPU2_SPU1, 0x1820), | 
 | 89 | 	INTCS_VECT(FSI, 0x1840), | 
 | 90 | 	INTCS_VECT(TMU1_TUNI10, 0x1900), INTCS_VECT(TMU1_TUNI11, 0x1920), | 
 | 91 | 	INTCS_VECT(TMU1_TUNI12, 0x1940), | 
 | 92 | 	INTCS_VECT(TSIF2, 0x1960), INTCS_VECT(CMT4, 0x1980), | 
 | 93 | 	INTCS_VECT(MFIS2, 0x1a00), INTCS_VECT(CPORTS2R, 0x1a20), | 
 | 94 | 	INTCS_VECT(TSG, 0x1ae0), INTCS_VECT(DMASCH1, 0x1b00), | 
 | 95 | 	INTCS_VECT(SCUW, 0x1b40), | 
 | 96 | 	INTCS_VECT(VIO60, 0x1b60), INTCS_VECT(VIO61, 0x1b80), | 
 | 97 | 	INTCS_VECT(CEU21, 0x1ba0), INTCS_VECT(CSI21, 0x1be0), | 
 | 98 | 	INTCS_VECT(DSITX1_DSITX10, 0x1c00), INTCS_VECT(DSITX1_DSITX11, 0x1c20), | 
 | 99 | 	INTCS_VECT(DISP, 0x1c40), INTCS_VECT(DSRV, 0x1c60), | 
 | 100 | 	INTCS_VECT(EMUX2_EMUX20I, 0x1c80), INTCS_VECT(EMUX2_EMUX21I, 0x1ca0), | 
 | 101 | 	INTCS_VECT(MSTIF0_MST00I, 0x1cc0), INTCS_VECT(MSTIF0_MST01I, 0x1ce0), | 
 | 102 | 	INTCS_VECT(MSTIF1_MST10I, 0x1d00), INTCS_VECT(MSTIF1_MST11I, 0x1d20), | 
 | 103 | 	INTCS_VECT(SPUV, 0x2300), | 
 | 104 | }; | 
 | 105 |  | 
 | 106 | static struct intc_group intcs_groups[] __initdata = { | 
 | 107 | 	INTC_GROUP(RTDMAC_0, RTDMAC_0_DEI0, RTDMAC_0_DEI1, | 
 | 108 | 		   RTDMAC_0_DEI2, RTDMAC_0_DEI3), | 
 | 109 | 	INTC_GROUP(RTDMAC_1, RTDMAC_1_DEI4, RTDMAC_1_DEI5, RTDMAC_1_DADERR), | 
 | 110 | 	INTC_GROUP(RTDMAC_2, RTDMAC_2_DEI6, RTDMAC_2_DEI7, | 
 | 111 | 		   RTDMAC_2_DEI8, RTDMAC_2_DEI9), | 
 | 112 | 	INTC_GROUP(RTDMAC_3, RTDMAC_3_DEI10, RTDMAC_3_DEI11), | 
 | 113 | 	INTC_GROUP(TMU1, TMU1_TUNI12, TMU1_TUNI11, TMU1_TUNI10), | 
 | 114 | 	INTC_GROUP(DSITX0, DSITX0_DSITX00, DSITX0_DSITX01), | 
 | 115 | 	INTC_GROUP(SPU2, SPU2_SPU0, SPU2_SPU1), | 
 | 116 | 	INTC_GROUP(MSU, MSU_MSU, MSU_MSU2), | 
 | 117 | }; | 
 | 118 |  | 
 | 119 | static struct intc_mask_reg intcs_mask_registers[] = { | 
 | 120 | 	{ 0xffd20184, 0xffd201c4, 8, /* IMR1SA / IMCR1SA */ | 
 | 121 | 	  { 0, 0, 0, CEU, | 
 | 122 | 	    0, 0, 0, 0 } }, | 
 | 123 | 	{ 0xffd20188, 0xffd201c8, 8, /* IMR2SA / IMCR2SA */ | 
 | 124 | 	  { 0, 0, 0, VPU, | 
 | 125 | 	    BBIF2, 0, 0, MFI } }, | 
 | 126 | 	{ 0xffd2018c, 0xffd201cc, 8, /* IMR3SA / IMCR3SA */ | 
 | 127 | 	  { 0, 0, 0, _2DDMAC_2DDM0, | 
 | 128 | 	    0, ASA, PEP, ICB } }, | 
 | 129 | 	{ 0xffd20190, 0xffd201d0, 8, /* IMR4SA / IMCR4SA */ | 
 | 130 | 	  { 0, 0, 0, CTI, | 
 | 131 | 	    JPU_JPEG, 0, LCRC, LCDC } }, | 
 | 132 | 	{ 0xffd20194, 0xffd201d4, 8, /* IMR5SA / IMCR5SA */ | 
 | 133 | 	  { KEYSC_KEY, RTDMAC_1_DADERR, RTDMAC_1_DEI5, RTDMAC_1_DEI4, | 
 | 134 | 	    RTDMAC_0_DEI3, RTDMAC_0_DEI2, RTDMAC_0_DEI1, RTDMAC_0_DEI0 } }, | 
 | 135 | 	{ 0xffd20198, 0xffd201d8, 8, /* IMR6SA / IMCR6SA */ | 
 | 136 | 	  { 0, 0, MSIOF, 0, | 
 | 137 | 	    _3DG_SGX543, 0, 0, 0 } }, | 
 | 138 | 	{ 0xffd2019c, 0xffd201dc, 8, /* IMR7SA / IMCR7SA */ | 
 | 139 | 	  { 0, TMU0_TUNI02, TMU0_TUNI01, TMU0_TUNI00, | 
 | 140 | 	    0, 0, 0, 0 } }, | 
 | 141 | 	{ 0xffd201a0, 0xffd201e0, 8, /* IMR8SA / IMCR8SA */ | 
 | 142 | 	  { 0, 0, 0, 0, | 
 | 143 | 	    0, MSU_MSU, MSU_MSU2, MSUG } }, | 
 | 144 | 	{ 0xffd201a4, 0xffd201e4, 8, /* IMR9SA / IMCR9SA */ | 
 | 145 | 	  { 0, RWDT0, CMT2, CMT0, | 
 | 146 | 	    0, 0, 0, 0 } }, | 
 | 147 | 	{ 0xffd201ac, 0xffd201ec, 8, /* IMR11SA / IMCR11SA */ | 
 | 148 | 	  { 0, 0, 0, 0, | 
 | 149 | 	    0, TSIF1, LMB, TSIF0 } }, | 
 | 150 | 	{ 0xffd201b0, 0xffd201f0, 8, /* IMR12SA / IMCR12SA */ | 
 | 151 | 	  { 0, 0, 0, 0, | 
 | 152 | 	    0, 0, PINTCS_PINT2, PINTCS_PINT1 } }, | 
 | 153 | 	{ 0xffd50180, 0xffd501c0, 8, /* IMR0SA3 / IMCR0SA3 */ | 
 | 154 | 	  { RTDMAC_2_DEI6, RTDMAC_2_DEI7, RTDMAC_2_DEI8, RTDMAC_2_DEI9, | 
 | 155 | 	    RTDMAC_3_DEI10, RTDMAC_3_DEI11, 0, 0 } }, | 
 | 156 | 	{ 0xffd50190, 0xffd501d0, 8, /* IMR4SA3 / IMCR4SA3 */ | 
 | 157 | 	  { FRC, 0, 0, GCU, | 
 | 158 | 	    LCDC1, CSIRX, DSITX0_DSITX00, DSITX0_DSITX01 } }, | 
 | 159 | 	{ 0xffd50194, 0xffd501d4, 8, /* IMR5SA3 / IMCR5SA3 */ | 
 | 160 | 	  { SPU2_SPU0, SPU2_SPU1, FSI, 0, | 
 | 161 | 	    0, 0, 0, 0 } }, | 
 | 162 | 	{ 0xffd50198, 0xffd501d8, 8, /* IMR6SA3 / IMCR6SA3 */ | 
 | 163 | 	  { TMU1_TUNI10, TMU1_TUNI11, TMU1_TUNI12, 0, | 
 | 164 | 	    TSIF2, CMT4, 0, 0 } }, | 
 | 165 | 	{ 0xffd5019c, 0xffd501dc, 8, /* IMR7SA3 / IMCR7SA3 */ | 
 | 166 | 	  { MFIS2, CPORTS2R, 0, 0, | 
 | 167 | 	    0, 0, 0, TSG } }, | 
 | 168 | 	{ 0xffd501a0, 0xffd501e0, 8, /* IMR8SA3 / IMCR8SA3 */ | 
 | 169 | 	  { DMASCH1, 0, SCUW, VIO60, | 
 | 170 | 	    VIO61, CEU21, 0, CSI21 } }, | 
 | 171 | 	{ 0xffd501a4, 0xffd501e4, 8, /* IMR9SA3 / IMCR9SA3 */ | 
 | 172 | 	  { DSITX1_DSITX10, DSITX1_DSITX11, DISP, DSRV, | 
 | 173 | 	    EMUX2_EMUX20I, EMUX2_EMUX21I, MSTIF0_MST00I, MSTIF0_MST01I } }, | 
 | 174 | 	{ 0xffd501a8, 0xffd501e8, 8, /* IMR10SA3 / IMCR10SA3 */ | 
 | 175 | 	  { MSTIF0_MST00I, MSTIF0_MST01I, 0, 0, | 
 | 176 | 	    0, 0, 0, 0  } }, | 
 | 177 | 	{ 0xffd60180, 0xffd601c0, 8, /* IMR0SA4 / IMCR0SA4 */ | 
 | 178 | 	  { SPUV, 0, 0, 0, | 
 | 179 | 	    0, 0, 0, 0  } }, | 
 | 180 | }; | 
 | 181 |  | 
 | 182 | /* Priority is needed for INTCA to receive the INTCS interrupt */ | 
 | 183 | static struct intc_prio_reg intcs_prio_registers[] = { | 
 | 184 | 	{ 0xffd20000, 0, 16, 4, /* IPRAS */ { CTI, 0, _2DDMAC_2DDM0, ICB } }, | 
 | 185 | 	{ 0xffd20004, 0, 16, 4, /* IPRBS */ { JPU_JPEG, LCDC, 0, LCRC } }, | 
 | 186 | 	{ 0xffd20008, 0, 16, 4, /* IPRCS */ { BBIF2, 0, 0, 0 } }, | 
 | 187 | 	{ 0xffd2000c, 0, 16, 4, /* IPRDS */ { PINTCS_PINT1, PINTCS_PINT2, | 
 | 188 | 					      0, 0 } }, | 
 | 189 | 	{ 0xffd20010, 0, 16, 4, /* IPRES */ { RTDMAC_0, CEU, MFI, VPU } }, | 
 | 190 | 	{ 0xffd20014, 0, 16, 4, /* IPRFS */ { KEYSC_KEY, RTDMAC_1, | 
 | 191 | 					      CMT2, CMT0 } }, | 
 | 192 | 	{ 0xffd20018, 0, 16, 4, /* IPRGS */ { TMU0_TUNI00, TMU0_TUNI01, | 
 | 193 | 					      TMU0_TUNI02, TSIF1 } }, | 
 | 194 | 	{ 0xffd2001c, 0, 16, 4, /* IPRHS */ { VINT, 0, 0, 0 } }, | 
 | 195 | 	{ 0xffd20020, 0, 16, 4, /* IPRIS */ { 0, MSIOF, TSIF0, 0 } }, | 
 | 196 | 	{ 0xffd20024, 0, 16, 4, /* IPRJS */ { 0, _3DG_SGX543, MSUG, MSU } }, | 
 | 197 | 	{ 0xffd20028, 0, 16, 4, /* IPRKS */ { 0, ASA, LMB, PEP } }, | 
 | 198 | 	{ 0xffd20030, 0, 16, 4, /* IPRMS */ { 0, 0, 0, RWDT0 } }, | 
 | 199 | 	{ 0xffd50000, 0, 16, 4, /* IPRAS3 */ { RTDMAC_2, 0, 0, 0 } }, | 
 | 200 | 	{ 0xffd50004, 0, 16, 4, /* IPRBS3 */ { RTDMAC_3, 0, 0, 0 } }, | 
 | 201 | 	{ 0xffd50020, 0, 16, 4, /* IPRIS3 */ { FRC, 0, 0, 0 } }, | 
 | 202 | 	{ 0xffd50024, 0, 16, 4, /* IPRJS3 */ { LCDC1, CSIRX, DSITX0, 0 } }, | 
 | 203 | 	{ 0xffd50028, 0, 16, 4, /* IPRKS3 */ { SPU2, 0, FSI, 0 } }, | 
 | 204 | 	{ 0xffd50030, 0, 16, 4, /* IPRMS3 */ { TMU1, 0, 0, TSIF2 } }, | 
 | 205 | 	{ 0xffd50034, 0, 16, 4, /* IPRNS3 */ { CMT4, 0, 0, 0 } }, | 
 | 206 | 	{ 0xffd50038, 0, 16, 4, /* IPROS3 */ { MFIS2, CPORTS2R, 0, 0 } }, | 
 | 207 | 	{ 0xffd50040, 0, 16, 4, /* IPRQS3 */ { DMASCH1, 0, SCUW, VIO60 } }, | 
 | 208 | 	{ 0xffd50044, 0, 16, 4, /* IPRRS3 */ { VIO61, CEU21, 0, CSI21 } }, | 
 | 209 | 	{ 0xffd50048, 0, 16, 4, /* IPRSS3 */ { DSITX1_DSITX10, DSITX1_DSITX11, | 
 | 210 | 					       DISP, DSRV } }, | 
 | 211 | 	{ 0xffd5004c, 0, 16, 4, /* IPRTS3 */ { EMUX2_EMUX20I, EMUX2_EMUX21I, | 
 | 212 | 					       MSTIF0_MST00I, MSTIF0_MST01I } }, | 
 | 213 | 	{ 0xffd50050, 0, 16, 4, /* IPRUS3 */ { MSTIF1_MST10I, MSTIF1_MST11I, | 
 | 214 | 					       0, 0 } }, | 
 | 215 | 	{ 0xffd60000, 0, 16, 4, /* IPRAS4 */ { SPUV, 0, 0, 0 } }, | 
 | 216 | }; | 
 | 217 |  | 
 | 218 | static struct resource intcs_resources[] __initdata = { | 
 | 219 | 	[0] = { | 
 | 220 | 		.start	= 0xffd20000, | 
 | 221 | 		.end	= 0xffd201ff, | 
 | 222 | 		.flags	= IORESOURCE_MEM, | 
 | 223 | 	}, | 
 | 224 | 	[1] = { | 
 | 225 | 		.start	= 0xffd50000, | 
 | 226 | 		.end	= 0xffd501ff, | 
 | 227 | 		.flags	= IORESOURCE_MEM, | 
 | 228 | 	}, | 
 | 229 | 	[2] = { | 
 | 230 | 		.start	= 0xffd60000, | 
 | 231 | 		.end	= 0xffd601ff, | 
 | 232 | 		.flags	= IORESOURCE_MEM, | 
 | 233 | 	} | 
 | 234 | }; | 
 | 235 |  | 
 | 236 | static struct intc_desc intcs_desc __initdata = { | 
 | 237 | 	.name = "sh73a0-intcs", | 
 | 238 | 	.resource = intcs_resources, | 
 | 239 | 	.num_resources = ARRAY_SIZE(intcs_resources), | 
 | 240 | 	.hw = INTC_HW_DESC(intcs_vectors, intcs_groups, intcs_mask_registers, | 
 | 241 | 			   intcs_prio_registers, NULL, NULL), | 
 | 242 | }; | 
 | 243 |  | 
 | 244 | static struct irqaction sh73a0_intcs_cascade; | 
 | 245 |  | 
 | 246 | static irqreturn_t sh73a0_intcs_demux(int irq, void *dev_id) | 
 | 247 | { | 
 | 248 | 	unsigned int evtcodeas = ioread32((void __iomem *)dev_id); | 
 | 249 |  | 
 | 250 | 	generic_handle_irq(intcs_evt2irq(evtcodeas)); | 
 | 251 |  | 
 | 252 | 	return IRQ_HANDLED; | 
 | 253 | } | 
 | 254 |  | 
| Magnus Damm | 485b2ab | 2011-06-09 06:20:03 +0000 | [diff] [blame] | 255 | static int sh73a0_set_wake(struct irq_data *data, unsigned int on) | 
 | 256 | { | 
 | 257 | 	return 0; /* always allow wakeup */ | 
 | 258 | } | 
 | 259 |  | 
| Magnus Damm | a199305 | 2011-10-12 16:21:42 +0900 | [diff] [blame] | 260 | #define RELOC_BASE 0x1000 | 
 | 261 |  | 
 | 262 | /* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */ | 
 | 263 | #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE) | 
 | 264 |  | 
 | 265 | INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000, | 
 | 266 | 		 INTCS_VECT_RELOC, "sh73a0-intca-irq-pins"); | 
 | 267 |  | 
 | 268 | static int to_gic_irq(struct irq_data *data) | 
 | 269 | { | 
 | 270 | 	unsigned int vect = irq2evt(data->irq) - INTCS_VECT_BASE; | 
 | 271 |  | 
 | 272 | 	if (vect >= 0x3200) | 
 | 273 | 		vect -= 0x3000; | 
 | 274 | 	else | 
 | 275 | 		vect -= 0x0200; | 
 | 276 |  | 
 | 277 | 	return gic_spi((vect >> 5) + 1); | 
 | 278 | } | 
 | 279 |  | 
 | 280 | static int to_intca_reloc_irq(struct irq_data *data) | 
 | 281 | { | 
 | 282 | 	return data->irq + (RELOC_BASE >> 5); | 
 | 283 | } | 
 | 284 |  | 
 | 285 | #define irq_cb(cb, irq) irq_get_chip(irq)->cb(irq_get_irq_data(irq)) | 
 | 286 | #define irq_cbp(cb, irq, p...) irq_get_chip(irq)->cb(irq_get_irq_data(irq), p) | 
 | 287 |  | 
 | 288 | static void intca_gic_enable(struct irq_data *data) | 
 | 289 | { | 
 | 290 | 	irq_cb(irq_unmask, to_intca_reloc_irq(data)); | 
 | 291 | 	irq_cb(irq_unmask, to_gic_irq(data)); | 
 | 292 | } | 
 | 293 |  | 
 | 294 | static void intca_gic_disable(struct irq_data *data) | 
 | 295 | { | 
 | 296 | 	irq_cb(irq_mask, to_gic_irq(data)); | 
 | 297 | 	irq_cb(irq_mask, to_intca_reloc_irq(data)); | 
 | 298 | } | 
 | 299 |  | 
 | 300 | static void intca_gic_mask_ack(struct irq_data *data) | 
 | 301 | { | 
 | 302 | 	irq_cb(irq_mask, to_gic_irq(data)); | 
 | 303 | 	irq_cb(irq_mask_ack, to_intca_reloc_irq(data)); | 
 | 304 | } | 
 | 305 |  | 
 | 306 | static void intca_gic_eoi(struct irq_data *data) | 
 | 307 | { | 
 | 308 | 	irq_cb(irq_eoi, to_gic_irq(data)); | 
 | 309 | } | 
 | 310 |  | 
 | 311 | static int intca_gic_set_type(struct irq_data *data, unsigned int type) | 
 | 312 | { | 
 | 313 | 	return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type); | 
 | 314 | } | 
 | 315 |  | 
 | 316 | static int intca_gic_set_wake(struct irq_data *data, unsigned int on) | 
 | 317 | { | 
 | 318 | 	return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on); | 
 | 319 | } | 
 | 320 |  | 
 | 321 | #ifdef CONFIG_SMP | 
 | 322 | static int intca_gic_set_affinity(struct irq_data *data, | 
 | 323 | 				  const struct cpumask *cpumask, | 
 | 324 | 				  bool force) | 
 | 325 | { | 
 | 326 | 	return irq_cbp(irq_set_affinity, to_gic_irq(data), cpumask, force); | 
 | 327 | } | 
 | 328 | #endif | 
 | 329 |  | 
 | 330 | struct irq_chip intca_gic_irq_chip = { | 
 | 331 | 	.name			= "INTCA-GIC", | 
 | 332 | 	.irq_mask		= intca_gic_disable, | 
 | 333 | 	.irq_unmask		= intca_gic_enable, | 
 | 334 | 	.irq_mask_ack		= intca_gic_mask_ack, | 
 | 335 | 	.irq_eoi		= intca_gic_eoi, | 
 | 336 | 	.irq_enable		= intca_gic_enable, | 
 | 337 | 	.irq_disable		= intca_gic_disable, | 
 | 338 | 	.irq_shutdown		= intca_gic_disable, | 
 | 339 | 	.irq_set_type		= intca_gic_set_type, | 
 | 340 | 	.irq_set_wake		= intca_gic_set_wake, | 
 | 341 | #ifdef CONFIG_SMP | 
 | 342 | 	.irq_set_affinity	= intca_gic_set_affinity, | 
 | 343 | #endif | 
 | 344 | }; | 
 | 345 |  | 
 | 346 | static int to_intc_vect(int irq) | 
 | 347 | { | 
 | 348 | 	unsigned int irq_pin = irq - gic_spi(1); | 
 | 349 | 	unsigned int offs; | 
 | 350 |  | 
 | 351 | 	if (irq_pin < 16) | 
 | 352 | 		offs = 0x0200; | 
 | 353 | 	else | 
 | 354 | 		offs = 0x3000; | 
 | 355 |  | 
 | 356 | 	return offs + (irq_pin << 5); | 
 | 357 | } | 
 | 358 |  | 
 | 359 | static irqreturn_t sh73a0_irq_pin_demux(int irq, void *dev_id) | 
 | 360 | { | 
 | 361 | 	generic_handle_irq(intcs_evt2irq(to_intc_vect(irq))); | 
 | 362 | 	return IRQ_HANDLED; | 
 | 363 | } | 
 | 364 |  | 
 | 365 | static struct irqaction sh73a0_irq_pin_cascade[32]; | 
 | 366 |  | 
| Magnus Damm | 566aad3 | 2011-10-17 18:00:52 +0900 | [diff] [blame] | 367 | #define PINTER0 0xe69000a0 | 
 | 368 | #define PINTER1 0xe69000a4 | 
 | 369 | #define PINTRR0 0xe69000d0 | 
 | 370 | #define PINTRR1 0xe69000d4 | 
 | 371 |  | 
 | 372 | #define PINT0A_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq)) | 
 | 373 | #define PINT0B_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 8)) | 
 | 374 | #define PINT0C_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 16)) | 
 | 375 | #define PINT0D_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT0_IRQ(irq + 24)) | 
 | 376 | #define PINT1E_IRQ(n, irq) INTC_IRQ((n), SH73A0_PINT1_IRQ(irq)) | 
 | 377 |  | 
 | 378 | INTC_PINT(intc_pint0, PINTER0, 0xe69000b0, "sh73a0-pint0",		\ | 
 | 379 |   INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\ | 
 | 380 |   INTC_PINT_V(A, PINT0A_IRQ), INTC_PINT_V(B, PINT0B_IRQ),		\ | 
 | 381 |   INTC_PINT_V(C, PINT0C_IRQ), INTC_PINT_V(D, PINT0D_IRQ),		\ | 
 | 382 |   INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D),	\ | 
 | 383 |   INTC_PINT_E(A), INTC_PINT_E(B), INTC_PINT_E(C), INTC_PINT_E(D)); | 
 | 384 |  | 
 | 385 | INTC_PINT(intc_pint1, PINTER1, 0xe69000c0, "sh73a0-pint1",		\ | 
 | 386 |   INTC_PINT_E(E), INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, INTC_PINT_E_EMPTY, \ | 
 | 387 |   INTC_PINT_V(E, PINT1E_IRQ), INTC_PINT_V_NONE,				\ | 
 | 388 |   INTC_PINT_V_NONE, INTC_PINT_V_NONE,					\ | 
 | 389 |   INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E(E), \ | 
 | 390 |   INTC_PINT_E(E), INTC_PINT_E_NONE, INTC_PINT_E_NONE, INTC_PINT_E_NONE); | 
 | 391 |  | 
 | 392 | static struct irqaction sh73a0_pint0_cascade; | 
 | 393 | static struct irqaction sh73a0_pint1_cascade; | 
 | 394 |  | 
 | 395 | static void pint_demux(unsigned long rr, unsigned long er, int base_irq) | 
 | 396 | { | 
 | 397 | 	unsigned long value =  ioread32(rr) & ioread32(er); | 
 | 398 | 	int k; | 
 | 399 |  | 
 | 400 | 	for (k = 0; k < 32; k++) { | 
 | 401 | 		if (value & (1 << (31 - k))) { | 
 | 402 | 			generic_handle_irq(base_irq + k); | 
 | 403 | 			iowrite32(~(1 << (31 - k)), rr); | 
 | 404 | 		} | 
 | 405 | 	} | 
 | 406 | } | 
 | 407 |  | 
 | 408 | static irqreturn_t sh73a0_pint0_demux(int irq, void *dev_id) | 
 | 409 | { | 
 | 410 | 	pint_demux(PINTRR0, PINTER0, SH73A0_PINT0_IRQ(0)); | 
 | 411 | 	return IRQ_HANDLED; | 
 | 412 | } | 
 | 413 |  | 
 | 414 | static irqreturn_t sh73a0_pint1_demux(int irq, void *dev_id) | 
 | 415 | { | 
 | 416 | 	pint_demux(PINTRR1, PINTER1, SH73A0_PINT1_IRQ(0)); | 
 | 417 | 	return IRQ_HANDLED; | 
 | 418 | } | 
 | 419 |  | 
| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 420 | void __init sh73a0_init_irq(void) | 
 | 421 | { | 
| Yoshii Takashi | bd1689c | 2011-01-13 13:17:15 +0000 | [diff] [blame] | 422 | 	void __iomem *gic_dist_base = __io(0xf0001000); | 
 | 423 | 	void __iomem *gic_cpu_base = __io(0xf0000100); | 
| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 424 | 	void __iomem *intevtsa = ioremap_nocache(0xffd20100, PAGE_SIZE); | 
| Magnus Damm | a199305 | 2011-10-12 16:21:42 +0900 | [diff] [blame] | 425 | 	int k, n; | 
| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 426 |  | 
| Yoshii Takashi | bd1689c | 2011-01-13 13:17:15 +0000 | [diff] [blame] | 427 | 	gic_init(0, 29, gic_dist_base, gic_cpu_base); | 
| Magnus Damm | 485b2ab | 2011-06-09 06:20:03 +0000 | [diff] [blame] | 428 | 	gic_arch_extn.irq_set_wake = sh73a0_set_wake; | 
| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 429 |  | 
 | 430 | 	register_intc_controller(&intcs_desc); | 
| Magnus Damm | a199305 | 2011-10-12 16:21:42 +0900 | [diff] [blame] | 431 | 	register_intc_controller(&intca_irq_pins_desc); | 
| Magnus Damm | 566aad3 | 2011-10-17 18:00:52 +0900 | [diff] [blame] | 432 | 	register_intc_controller(&intc_pint0_desc); | 
 | 433 | 	register_intc_controller(&intc_pint1_desc); | 
| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 434 |  | 
 | 435 | 	/* demux using INTEVTSA */ | 
 | 436 | 	sh73a0_intcs_cascade.name = "INTCS cascade"; | 
 | 437 | 	sh73a0_intcs_cascade.handler = sh73a0_intcs_demux; | 
 | 438 | 	sh73a0_intcs_cascade.dev_id = intevtsa; | 
 | 439 | 	setup_irq(gic_spi(50), &sh73a0_intcs_cascade); | 
| Magnus Damm | a199305 | 2011-10-12 16:21:42 +0900 | [diff] [blame] | 440 |  | 
 | 441 | 	/* IRQ pins require special handling through INTCA and GIC */ | 
 | 442 | 	for (k = 0; k < 32; k++) { | 
 | 443 | 		sh73a0_irq_pin_cascade[k].name = "INTCA-GIC cascade"; | 
 | 444 | 		sh73a0_irq_pin_cascade[k].handler = sh73a0_irq_pin_demux; | 
 | 445 | 		setup_irq(gic_spi(1 + k), &sh73a0_irq_pin_cascade[k]); | 
 | 446 |  | 
 | 447 | 		n = intcs_evt2irq(to_intc_vect(gic_spi(1 + k))); | 
 | 448 | 		irq_set_chip_and_handler_name(n, &intca_gic_irq_chip, | 
 | 449 | 					      handle_level_irq, "level"); | 
 | 450 | 		set_irq_flags(n, IRQF_VALID); /* yuck */ | 
 | 451 | 	} | 
| Magnus Damm | 566aad3 | 2011-10-17 18:00:52 +0900 | [diff] [blame] | 452 |  | 
 | 453 | 	/* PINT pins are sanely tied to the GIC as SPI */ | 
 | 454 | 	sh73a0_pint0_cascade.name = "PINT0 cascade"; | 
 | 455 | 	sh73a0_pint0_cascade.handler = sh73a0_pint0_demux; | 
 | 456 | 	setup_irq(gic_spi(33), &sh73a0_pint0_cascade); | 
 | 457 |  | 
 | 458 | 	sh73a0_pint1_cascade.name = "PINT1 cascade"; | 
 | 459 | 	sh73a0_pint1_cascade.handler = sh73a0_pint1_demux; | 
 | 460 | 	setup_irq(gic_spi(34), &sh73a0_pint1_cascade); | 
| Magnus Damm | 5f53a56 | 2010-12-21 08:37:32 +0000 | [diff] [blame] | 461 | } |