aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cavium-octeon
diff options
context:
space:
mode:
authorDavid Daney <david.daney@cavium.com>2012-04-04 18:34:41 -0400
committerDavid Daney <david.daney@cavium.com>2012-08-31 13:46:54 -0400
commit88fd85892a55730878fc081eee62553eb18f1b9c (patch)
tree804e3017ac80929504c3035e66b393fd286da98c /arch/mips/cavium-octeon
parent9787c56ee376bfc3ed110c2723462361b700d7d2 (diff)
MIPS: OCTEON: Add support for cn68XX interrupt controller.
The cn68XX has a new interrupt controller named CIU2, add support for this, and use it if cn68XX detected at runtime. Signed-off-by: David Daney <david.daney@cavium.com>
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r--arch/mips/cavium-octeon/octeon-irq.c568
1 files changed, 544 insertions, 24 deletions
diff --git a/arch/mips/cavium-octeon/octeon-irq.c b/arch/mips/cavium-octeon/octeon-irq.c
index 274cd4fad30c..aba085b2c0d5 100644
--- a/arch/mips/cavium-octeon/octeon-irq.c
+++ b/arch/mips/cavium-octeon/octeon-irq.c
@@ -16,6 +16,7 @@
16#include <linux/of.h> 16#include <linux/of.h>
17 17
18#include <asm/octeon/octeon.h> 18#include <asm/octeon/octeon.h>
19#include <asm/octeon/cvmx-ciu2-defs.h>
19 20
20static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock); 21static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock);
21static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock); 22static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock);
@@ -29,8 +30,9 @@ union octeon_ciu_chip_data {
29 void *p; 30 void *p;
30 unsigned long l; 31 unsigned long l;
31 struct { 32 struct {
32 unsigned int line:6; 33 unsigned long line:6;
33 unsigned int bit:6; 34 unsigned long bit:6;
35 unsigned long gpio_line:6;
34 } s; 36 } s;
35}; 37};
36 38
@@ -45,7 +47,7 @@ struct octeon_core_chip_data {
45 47
46static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES]; 48static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
47 49
48static void octeon_irq_set_ciu_mapping(int irq, int line, int bit, 50static void octeon_irq_set_ciu_mapping(int irq, int line, int bit, int gpio_line,
49 struct irq_chip *chip, 51 struct irq_chip *chip,
50 irq_flow_handler_t handler) 52 irq_flow_handler_t handler)
51{ 53{
@@ -56,6 +58,7 @@ static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
56 cd.l = 0; 58 cd.l = 0;
57 cd.s.line = line; 59 cd.s.line = line;
58 cd.s.bit = bit; 60 cd.s.bit = bit;
61 cd.s.gpio_line = gpio_line;
59 62
60 irq_set_chip_data(irq, cd.p); 63 irq_set_chip_data(irq, cd.p);
61 octeon_irq_ciu_to_irq[line][bit] = irq; 64 octeon_irq_ciu_to_irq[line][bit] = irq;
@@ -435,7 +438,7 @@ static void octeon_irq_ciu_ack(struct irq_data *data)
435 u64 mask; 438 u64 mask;
436 union octeon_ciu_chip_data cd; 439 union octeon_ciu_chip_data cd;
437 440
438 cd.p = data->chip_data; 441 cd.p = irq_data_get_irq_chip_data(data);
439 mask = 1ull << (cd.s.bit); 442 mask = 1ull << (cd.s.bit);
440 443
441 if (cd.s.line == 0) { 444 if (cd.s.line == 0) {
@@ -458,7 +461,7 @@ static void octeon_irq_ciu_disable_all_v2(struct irq_data *data)
458 461
459 wmb(); /* Make sure flag changes arrive before register updates. */ 462 wmb(); /* Make sure flag changes arrive before register updates. */
460 463
461 cd.p = data->chip_data; 464 cd.p = irq_data_get_irq_chip_data(data);
462 mask = 1ull << (cd.s.bit); 465 mask = 1ull << (cd.s.bit);
463 466
464 if (cd.s.line == 0) { 467 if (cd.s.line == 0) {
@@ -486,7 +489,7 @@ static void octeon_irq_ciu_enable_all_v2(struct irq_data *data)
486 u64 mask; 489 u64 mask;
487 union octeon_ciu_chip_data cd; 490 union octeon_ciu_chip_data cd;
488 491
489 cd.p = data->chip_data; 492 cd.p = irq_data_get_irq_chip_data(data);
490 mask = 1ull << (cd.s.bit); 493 mask = 1ull << (cd.s.bit);
491 494
492 if (cd.s.line == 0) { 495 if (cd.s.line == 0) {
@@ -521,7 +524,7 @@ static void octeon_irq_gpio_setup(struct irq_data *data)
521 cfg.s.fil_cnt = 7; 524 cfg.s.fil_cnt = 7;
522 cfg.s.fil_sel = 3; 525 cfg.s.fil_sel = 3;
523 526
524 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), cfg.u64); 527 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.gpio_line), cfg.u64);
525} 528}
526 529
527static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data) 530static void octeon_irq_ciu_enable_gpio_v2(struct irq_data *data)
@@ -549,7 +552,7 @@ static void octeon_irq_ciu_disable_gpio_v2(struct irq_data *data)
549 union octeon_ciu_chip_data cd; 552 union octeon_ciu_chip_data cd;
550 553
551 cd.p = irq_data_get_irq_chip_data(data); 554 cd.p = irq_data_get_irq_chip_data(data);
552 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); 555 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.gpio_line), 0);
553 556
554 octeon_irq_ciu_disable_all_v2(data); 557 octeon_irq_ciu_disable_all_v2(data);
555} 558}
@@ -559,7 +562,7 @@ static void octeon_irq_ciu_disable_gpio(struct irq_data *data)
559 union octeon_ciu_chip_data cd; 562 union octeon_ciu_chip_data cd;
560 563
561 cd.p = irq_data_get_irq_chip_data(data); 564 cd.p = irq_data_get_irq_chip_data(data);
562 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.bit - 16), 0); 565 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.gpio_line), 0);
563 566
564 octeon_irq_ciu_disable_all(data); 567 octeon_irq_ciu_disable_all(data);
565} 568}
@@ -570,7 +573,7 @@ static void octeon_irq_ciu_gpio_ack(struct irq_data *data)
570 u64 mask; 573 u64 mask;
571 574
572 cd.p = irq_data_get_irq_chip_data(data); 575 cd.p = irq_data_get_irq_chip_data(data);
573 mask = 1ull << (cd.s.bit - 16); 576 mask = 1ull << (cd.s.gpio_line);
574 577
575 cvmx_write_csr(CVMX_GPIO_INT_CLR, mask); 578 cvmx_write_csr(CVMX_GPIO_INT_CLR, mask);
576} 579}
@@ -616,7 +619,7 @@ static int octeon_irq_ciu_set_affinity(struct irq_data *data,
616 unsigned long flags; 619 unsigned long flags;
617 union octeon_ciu_chip_data cd; 620 union octeon_ciu_chip_data cd;
618 621
619 cd.p = data->chip_data; 622 cd.p = irq_data_get_irq_chip_data(data);
620 623
621 /* 624 /*
622 * For non-v2 CIU, we will allow only single CPU affinity. 625 * For non-v2 CIU, we will allow only single CPU affinity.
@@ -679,7 +682,7 @@ static int octeon_irq_ciu_set_affinity_v2(struct irq_data *data,
679 if (!enable_one) 682 if (!enable_one)
680 return 0; 683 return 0;
681 684
682 cd.p = data->chip_data; 685 cd.p = irq_data_get_irq_chip_data(data);
683 mask = 1ull << cd.s.bit; 686 mask = 1ull << cd.s.bit;
684 687
685 if (cd.s.line == 0) { 688 if (cd.s.line == 0) {
@@ -976,19 +979,20 @@ static int octeon_irq_ciu_map(struct irq_domain *d,
976 return -EINVAL; 979 return -EINVAL;
977 980
978 if (octeon_irq_ciu_is_edge(line, bit)) 981 if (octeon_irq_ciu_is_edge(line, bit))
979 octeon_irq_set_ciu_mapping(virq, line, bit, 982 octeon_irq_set_ciu_mapping(virq, line, bit, 0,
980 octeon_irq_ciu_chip, 983 octeon_irq_ciu_chip,
981 handle_edge_irq); 984 handle_edge_irq);
982 else 985 else
983 octeon_irq_set_ciu_mapping(virq, line, bit, 986 octeon_irq_set_ciu_mapping(virq, line, bit, 0,
984 octeon_irq_ciu_chip, 987 octeon_irq_ciu_chip,
985 handle_level_irq); 988 handle_level_irq);
986 989
987 return 0; 990 return 0;
988} 991}
989 992
990static int octeon_irq_gpio_map(struct irq_domain *d, 993static int octeon_irq_gpio_map_common(struct irq_domain *d,
991 unsigned int virq, irq_hw_number_t hw) 994 unsigned int virq, irq_hw_number_t hw,
995 int line_limit, struct irq_chip *chip)
992{ 996{
993 struct octeon_irq_gpio_domain_data *gpiod = d->host_data; 997 struct octeon_irq_gpio_domain_data *gpiod = d->host_data;
994 unsigned int line, bit; 998 unsigned int line, bit;
@@ -999,15 +1003,20 @@ static int octeon_irq_gpio_map(struct irq_domain *d,
999 hw += gpiod->base_hwirq; 1003 hw += gpiod->base_hwirq;
1000 line = hw >> 6; 1004 line = hw >> 6;
1001 bit = hw & 63; 1005 bit = hw & 63;
1002 if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0) 1006 if (line > line_limit || octeon_irq_ciu_to_irq[line][bit] != 0)
1003 return -EINVAL; 1007 return -EINVAL;
1004 1008
1005 octeon_irq_set_ciu_mapping(virq, line, bit, 1009 octeon_irq_set_ciu_mapping(virq, line, bit, hw,
1006 octeon_irq_gpio_chip, 1010 chip, octeon_irq_handle_gpio);
1007 octeon_irq_handle_gpio);
1008 return 0; 1011 return 0;
1009} 1012}
1010 1013
1014static int octeon_irq_gpio_map(struct irq_domain *d,
1015 unsigned int virq, irq_hw_number_t hw)
1016{
1017 return octeon_irq_gpio_map_common(d, virq, hw, 1, octeon_irq_gpio_chip);
1018}
1019
1011static struct irq_domain_ops octeon_irq_domain_ciu_ops = { 1020static struct irq_domain_ops octeon_irq_domain_ciu_ops = {
1012 .map = octeon_irq_ciu_map, 1021 .map = octeon_irq_ciu_map,
1013 .xlate = octeon_irq_ciu_xlat, 1022 .xlate = octeon_irq_ciu_xlat,
@@ -1091,6 +1100,13 @@ static void octeon_irq_ip3_v2(void)
1091 } 1100 }
1092} 1101}
1093 1102
1103static bool octeon_irq_use_ip4;
1104
1105static void __cpuinit octeon_irq_local_enable_ip4(void *arg)
1106{
1107 set_c0_status(STATUSF_IP4);
1108}
1109
1094static void octeon_irq_ip4_mask(void) 1110static void octeon_irq_ip4_mask(void)
1095{ 1111{
1096 clear_c0_status(STATUSF_IP4); 1112 clear_c0_status(STATUSF_IP4);
@@ -1103,6 +1119,13 @@ static void (*octeon_irq_ip4)(void);
1103 1119
1104void __cpuinitdata (*octeon_irq_setup_secondary)(void); 1120void __cpuinitdata (*octeon_irq_setup_secondary)(void);
1105 1121
1122void __cpuinit octeon_irq_set_ip4_handler(octeon_irq_ip4_handler_t h)
1123{
1124 octeon_irq_ip4 = h;
1125 octeon_irq_use_ip4 = true;
1126 on_each_cpu(octeon_irq_local_enable_ip4, NULL, 1);
1127}
1128
1106static void __cpuinit octeon_irq_percpu_enable(void) 1129static void __cpuinit octeon_irq_percpu_enable(void)
1107{ 1130{
1108 irq_cpu_online(); 1131 irq_cpu_online();
@@ -1123,6 +1146,28 @@ static void __cpuinit octeon_irq_init_ciu_percpu(void)
1123 cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2))); 1146 cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2)));
1124} 1147}
1125 1148
1149static void octeon_irq_init_ciu2_percpu(void)
1150{
1151 u64 regx, ipx;
1152 int coreid = cvmx_get_core_num();
1153 u64 base = CVMX_CIU2_EN_PPX_IP2_WRKQ(coreid);
1154
1155 /*
1156 * Disable All CIU2 Interrupts. The ones we need will be
1157 * enabled later. Read the SUM register so we know the write
1158 * completed.
1159 *
1160 * There are 9 registers and 3 IPX levels with strides 0x1000
1161 * and 0x200 respectivly. Use loops to clear them.
1162 */
1163 for (regx = 0; regx <= 0x8000; regx += 0x1000) {
1164 for (ipx = 0; ipx <= 0x400; ipx += 0x200)
1165 cvmx_write_csr(base + regx + ipx, 0);
1166 }
1167
1168 cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP2(coreid));
1169}
1170
1126static void __cpuinit octeon_irq_setup_secondary_ciu(void) 1171static void __cpuinit octeon_irq_setup_secondary_ciu(void)
1127{ 1172{
1128 1173
@@ -1137,6 +1182,19 @@ static void __cpuinit octeon_irq_setup_secondary_ciu(void)
1137 clear_c0_status(STATUSF_IP4); 1182 clear_c0_status(STATUSF_IP4);
1138} 1183}
1139 1184
1185static void octeon_irq_setup_secondary_ciu2(void)
1186{
1187 octeon_irq_init_ciu2_percpu();
1188 octeon_irq_percpu_enable();
1189
1190 /* Enable the CIU lines */
1191 set_c0_status(STATUSF_IP3 | STATUSF_IP2);
1192 if (octeon_irq_use_ip4)
1193 set_c0_status(STATUSF_IP4);
1194 else
1195 clear_c0_status(STATUSF_IP4);
1196}
1197
1140static void __init octeon_irq_init_ciu(void) 1198static void __init octeon_irq_init_ciu(void)
1141{ 1199{
1142 unsigned int i; 1200 unsigned int i;
@@ -1200,8 +1258,8 @@ static void __init octeon_irq_init_ciu(void)
1200 for (i = 0; i < 16; i++) 1258 for (i = 0; i < 16; i++)
1201 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i + 0); 1259 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i + 0);
1202 1260
1203 octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq); 1261 octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, 0, chip_mbox, handle_percpu_irq);
1204 octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq); 1262 octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, 0, chip_mbox, handle_percpu_irq);
1205 1263
1206 for (i = 0; i < 4; i++) 1264 for (i = 0; i < 4; i++)
1207 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 0, i + 36); 1265 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 0, i + 36);
@@ -1217,7 +1275,7 @@ static void __init octeon_irq_init_ciu(void)
1217 1275
1218 /* CIU_1 */ 1276 /* CIU_1 */
1219 for (i = 0; i < 16; i++) 1277 for (i = 0; i < 16; i++)
1220 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq); 1278 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, 0, chip_wd, handle_level_irq);
1221 1279
1222 octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17); 1280 octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17);
1223 1281
@@ -1226,6 +1284,465 @@ static void __init octeon_irq_init_ciu(void)
1226 clear_c0_status(STATUSF_IP4); 1284 clear_c0_status(STATUSF_IP4);
1227} 1285}
1228 1286
1287/*
1288 * Watchdog interrupts are special. They are associated with a single
1289 * core, so we hardwire the affinity to that core.
1290 */
1291static void octeon_irq_ciu2_wd_enable(struct irq_data *data)
1292{
1293 u64 mask;
1294 u64 en_addr;
1295 int coreid = data->irq - OCTEON_IRQ_WDOG0;
1296 union octeon_ciu_chip_data cd;
1297
1298 cd.p = irq_data_get_irq_chip_data(data);
1299 mask = 1ull << (cd.s.bit);
1300
1301 en_addr = CVMX_CIU2_EN_PPX_IP2_WRKQ_W1S(coreid) + (0x1000ull * cd.s.line);
1302 cvmx_write_csr(en_addr, mask);
1303
1304}
1305
1306static void octeon_irq_ciu2_enable(struct irq_data *data)
1307{
1308 u64 mask;
1309 u64 en_addr;
1310 int cpu = next_cpu_for_irq(data);
1311 int coreid = octeon_coreid_for_cpu(cpu);
1312 union octeon_ciu_chip_data cd;
1313
1314 cd.p = irq_data_get_irq_chip_data(data);
1315 mask = 1ull << (cd.s.bit);
1316
1317 en_addr = CVMX_CIU2_EN_PPX_IP2_WRKQ_W1S(coreid) + (0x1000ull * cd.s.line);
1318 cvmx_write_csr(en_addr, mask);
1319}
1320
1321static void octeon_irq_ciu2_enable_local(struct irq_data *data)
1322{
1323 u64 mask;
1324 u64 en_addr;
1325 int coreid = cvmx_get_core_num();
1326 union octeon_ciu_chip_data cd;
1327
1328 cd.p = irq_data_get_irq_chip_data(data);
1329 mask = 1ull << (cd.s.bit);
1330
1331 en_addr = CVMX_CIU2_EN_PPX_IP2_WRKQ_W1S(coreid) + (0x1000ull * cd.s.line);
1332 cvmx_write_csr(en_addr, mask);
1333
1334}
1335
1336static void octeon_irq_ciu2_disable_local(struct irq_data *data)
1337{
1338 u64 mask;
1339 u64 en_addr;
1340 int coreid = cvmx_get_core_num();
1341 union octeon_ciu_chip_data cd;
1342
1343 cd.p = irq_data_get_irq_chip_data(data);
1344 mask = 1ull << (cd.s.bit);
1345
1346 en_addr = CVMX_CIU2_EN_PPX_IP2_WRKQ_W1C(coreid) + (0x1000ull * cd.s.line);
1347 cvmx_write_csr(en_addr, mask);
1348
1349}
1350
1351static void octeon_irq_ciu2_ack(struct irq_data *data)
1352{
1353 u64 mask;
1354 u64 en_addr;
1355 int coreid = cvmx_get_core_num();
1356 union octeon_ciu_chip_data cd;
1357
1358 cd.p = irq_data_get_irq_chip_data(data);
1359 mask = 1ull << (cd.s.bit);
1360
1361 en_addr = CVMX_CIU2_RAW_PPX_IP2_WRKQ(coreid) + (0x1000ull * cd.s.line);
1362 cvmx_write_csr(en_addr, mask);
1363
1364}
1365
1366static void octeon_irq_ciu2_disable_all(struct irq_data *data)
1367{
1368 int cpu;
1369 u64 mask;
1370 union octeon_ciu_chip_data cd;
1371
1372 cd.p = irq_data_get_irq_chip_data(data);
1373 mask = 1ull << (cd.s.bit);
1374
1375 for_each_online_cpu(cpu) {
1376 u64 en_addr = CVMX_CIU2_EN_PPX_IP2_WRKQ_W1C(octeon_coreid_for_cpu(cpu)) + (0x1000ull * cd.s.line);
1377 cvmx_write_csr(en_addr, mask);
1378 }
1379}
1380
1381static void octeon_irq_ciu2_mbox_enable_all(struct irq_data *data)
1382{
1383 int cpu;
1384 u64 mask;
1385
1386 mask = 1ull << (data->irq - OCTEON_IRQ_MBOX0);
1387
1388 for_each_online_cpu(cpu) {
1389 u64 en_addr = CVMX_CIU2_EN_PPX_IP3_MBOX_W1S(octeon_coreid_for_cpu(cpu));
1390 cvmx_write_csr(en_addr, mask);
1391 }
1392}
1393
1394static void octeon_irq_ciu2_mbox_disable_all(struct irq_data *data)
1395{
1396 int cpu;
1397 u64 mask;
1398
1399 mask = 1ull << (data->irq - OCTEON_IRQ_MBOX0);
1400
1401 for_each_online_cpu(cpu) {
1402 u64 en_addr = CVMX_CIU2_EN_PPX_IP3_MBOX_W1C(octeon_coreid_for_cpu(cpu));
1403 cvmx_write_csr(en_addr, mask);
1404 }
1405}
1406
1407static void octeon_irq_ciu2_mbox_enable_local(struct irq_data *data)
1408{
1409 u64 mask;
1410 u64 en_addr;
1411 int coreid = cvmx_get_core_num();
1412
1413 mask = 1ull << (data->irq - OCTEON_IRQ_MBOX0);
1414 en_addr = CVMX_CIU2_EN_PPX_IP3_MBOX_W1S(coreid);
1415 cvmx_write_csr(en_addr, mask);
1416}
1417
1418static void octeon_irq_ciu2_mbox_disable_local(struct irq_data *data)
1419{
1420 u64 mask;
1421 u64 en_addr;
1422 int coreid = cvmx_get_core_num();
1423
1424 mask = 1ull << (data->irq - OCTEON_IRQ_MBOX0);
1425 en_addr = CVMX_CIU2_EN_PPX_IP3_MBOX_W1C(coreid);
1426 cvmx_write_csr(en_addr, mask);
1427}
1428
1429#ifdef CONFIG_SMP
1430static int octeon_irq_ciu2_set_affinity(struct irq_data *data,
1431 const struct cpumask *dest, bool force)
1432{
1433 int cpu;
1434 bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
1435 u64 mask;
1436 union octeon_ciu_chip_data cd;
1437
1438 if (!enable_one)
1439 return 0;
1440
1441 cd.p = irq_data_get_irq_chip_data(data);
1442 mask = 1ull << cd.s.bit;
1443
1444 for_each_online_cpu(cpu) {
1445 u64 en_addr;
1446 if (cpumask_test_cpu(cpu, dest) && enable_one) {
1447 enable_one = false;
1448 en_addr = CVMX_CIU2_EN_PPX_IP2_WRKQ_W1S(octeon_coreid_for_cpu(cpu)) + (0x1000ull * cd.s.line);
1449 } else {
1450 en_addr = CVMX_CIU2_EN_PPX_IP2_WRKQ_W1C(octeon_coreid_for_cpu(cpu)) + (0x1000ull * cd.s.line);
1451 }
1452 cvmx_write_csr(en_addr, mask);
1453 }
1454
1455 return 0;
1456}
1457#endif
1458
1459static void octeon_irq_ciu2_enable_gpio(struct irq_data *data)
1460{
1461 octeon_irq_gpio_setup(data);
1462 octeon_irq_ciu2_enable(data);
1463}
1464
1465static void octeon_irq_ciu2_disable_gpio(struct irq_data *data)
1466{
1467 union octeon_ciu_chip_data cd;
1468 cd.p = irq_data_get_irq_chip_data(data);
1469
1470 cvmx_write_csr(CVMX_GPIO_BIT_CFGX(cd.s.gpio_line), 0);
1471
1472 octeon_irq_ciu2_disable_all(data);
1473}
1474
1475static struct irq_chip octeon_irq_chip_ciu2 = {
1476 .name = "CIU2-E",
1477 .irq_enable = octeon_irq_ciu2_enable,
1478 .irq_disable = octeon_irq_ciu2_disable_all,
1479 .irq_ack = octeon_irq_ciu2_ack,
1480 .irq_mask = octeon_irq_ciu2_disable_local,
1481 .irq_unmask = octeon_irq_ciu2_enable,
1482#ifdef CONFIG_SMP
1483 .irq_set_affinity = octeon_irq_ciu2_set_affinity,
1484 .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
1485#endif
1486};
1487
1488static struct irq_chip octeon_irq_chip_ciu2_mbox = {
1489 .name = "CIU2-M",
1490 .irq_enable = octeon_irq_ciu2_mbox_enable_all,
1491 .irq_disable = octeon_irq_ciu2_mbox_disable_all,
1492 .irq_ack = octeon_irq_ciu2_mbox_disable_local,
1493 .irq_eoi = octeon_irq_ciu2_mbox_enable_local,
1494
1495 .irq_cpu_online = octeon_irq_ciu2_mbox_enable_local,
1496 .irq_cpu_offline = octeon_irq_ciu2_mbox_disable_local,
1497 .flags = IRQCHIP_ONOFFLINE_ENABLED,
1498};
1499
1500static struct irq_chip octeon_irq_chip_ciu2_wd = {
1501 .name = "CIU2-W",
1502 .irq_enable = octeon_irq_ciu2_wd_enable,
1503 .irq_disable = octeon_irq_ciu2_disable_all,
1504 .irq_mask = octeon_irq_ciu2_disable_local,
1505 .irq_unmask = octeon_irq_ciu2_enable_local,
1506};
1507
1508static struct irq_chip octeon_irq_chip_ciu2_gpio = {
1509 .name = "CIU-GPIO",
1510 .irq_enable = octeon_irq_ciu2_enable_gpio,
1511 .irq_disable = octeon_irq_ciu2_disable_gpio,
1512 .irq_ack = octeon_irq_ciu_gpio_ack,
1513 .irq_mask = octeon_irq_ciu2_disable_local,
1514 .irq_unmask = octeon_irq_ciu2_enable,
1515 .irq_set_type = octeon_irq_ciu_gpio_set_type,
1516#ifdef CONFIG_SMP
1517 .irq_set_affinity = octeon_irq_ciu2_set_affinity,
1518 .irq_cpu_offline = octeon_irq_cpu_offline_ciu,
1519#endif
1520 .flags = IRQCHIP_SET_TYPE_MASKED,
1521};
1522
1523static int octeon_irq_ciu2_xlat(struct irq_domain *d,
1524 struct device_node *node,
1525 const u32 *intspec,
1526 unsigned int intsize,
1527 unsigned long *out_hwirq,
1528 unsigned int *out_type)
1529{
1530 unsigned int ciu, bit;
1531
1532 ciu = intspec[0];
1533 bit = intspec[1];
1534
1535 /* Line 7 are the GPIO lines */
1536 if (ciu > 6 || bit > 63)
1537 return -EINVAL;
1538
1539 *out_hwirq = (ciu << 6) | bit;
1540 *out_type = 0;
1541
1542 return 0;
1543}
1544
1545static bool octeon_irq_ciu2_is_edge(unsigned int line, unsigned int bit)
1546{
1547 bool edge = false;
1548
1549 if (line == 3) /* MIO */
1550 switch (bit) {
1551 case 2: /* IPD_DRP */
1552 case 8 ... 11: /* Timers */
1553 case 48: /* PTP */
1554 edge = true;
1555 break;
1556 default:
1557 break;
1558 }
1559 else if (line == 6) /* PKT */
1560 switch (bit) {
1561 case 52 ... 53: /* ILK_DRP */
1562 case 8 ... 12: /* GMX_DRP */
1563 edge = true;
1564 break;
1565 default:
1566 break;
1567 }
1568 return edge;
1569}
1570
1571static int octeon_irq_ciu2_map(struct irq_domain *d,
1572 unsigned int virq, irq_hw_number_t hw)
1573{
1574 unsigned int line = hw >> 6;
1575 unsigned int bit = hw & 63;
1576
1577 if (!octeon_irq_virq_in_range(virq))
1578 return -EINVAL;
1579
1580 /* Line 7 are the GPIO lines */
1581 if (line > 6 || octeon_irq_ciu_to_irq[line][bit] != 0)
1582 return -EINVAL;
1583
1584 if (octeon_irq_ciu2_is_edge(line, bit))
1585 octeon_irq_set_ciu_mapping(virq, line, bit, 0,
1586 &octeon_irq_chip_ciu2,
1587 handle_edge_irq);
1588 else
1589 octeon_irq_set_ciu_mapping(virq, line, bit, 0,
1590 &octeon_irq_chip_ciu2,
1591 handle_level_irq);
1592
1593 return 0;
1594}
1595static int octeon_irq_ciu2_gpio_map(struct irq_domain *d,
1596 unsigned int virq, irq_hw_number_t hw)
1597{
1598 return octeon_irq_gpio_map_common(d, virq, hw, 7, &octeon_irq_chip_ciu2_gpio);
1599}
1600
1601static struct irq_domain_ops octeon_irq_domain_ciu2_ops = {
1602 .map = octeon_irq_ciu2_map,
1603 .xlate = octeon_irq_ciu2_xlat,
1604};
1605
1606static struct irq_domain_ops octeon_irq_domain_ciu2_gpio_ops = {
1607 .map = octeon_irq_ciu2_gpio_map,
1608 .xlate = octeon_irq_gpio_xlat,
1609};
1610
1611static void octeon_irq_ciu2(void)
1612{
1613 int line;
1614 int bit;
1615 int irq;
1616 u64 src_reg, src, sum;
1617 const unsigned long core_id = cvmx_get_core_num();
1618
1619 sum = cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP2(core_id)) & 0xfful;
1620
1621 if (unlikely(!sum))
1622 goto spurious;
1623
1624 line = fls64(sum) - 1;
1625 src_reg = CVMX_CIU2_SRC_PPX_IP2_WRKQ(core_id) + (0x1000 * line);
1626 src = cvmx_read_csr(src_reg);
1627
1628 if (unlikely(!src))
1629 goto spurious;
1630
1631 bit = fls64(src) - 1;
1632 irq = octeon_irq_ciu_to_irq[line][bit];
1633 if (unlikely(!irq))
1634 goto spurious;
1635
1636 do_IRQ(irq);
1637 goto out;
1638
1639spurious:
1640 spurious_interrupt();
1641out:
1642 /* CN68XX pass 1.x has an errata that accessing the ACK registers
1643 can stop interrupts from propagating */
1644 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
1645 cvmx_read_csr(CVMX_CIU2_INTR_CIU_READY);
1646 else
1647 cvmx_read_csr(CVMX_CIU2_ACK_PPX_IP2(core_id));
1648 return;
1649}
1650
1651static void octeon_irq_ciu2_mbox(void)
1652{
1653 int line;
1654
1655 const unsigned long core_id = cvmx_get_core_num();
1656 u64 sum = cvmx_read_csr(CVMX_CIU2_SUM_PPX_IP3(core_id)) >> 60;
1657
1658 if (unlikely(!sum))
1659 goto spurious;
1660
1661 line = fls64(sum) - 1;
1662
1663 do_IRQ(OCTEON_IRQ_MBOX0 + line);
1664 goto out;
1665
1666spurious:
1667 spurious_interrupt();
1668out:
1669 /* CN68XX pass 1.x has an errata that accessing the ACK registers
1670 can stop interrupts from propagating */
1671 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
1672 cvmx_read_csr(CVMX_CIU2_INTR_CIU_READY);
1673 else
1674 cvmx_read_csr(CVMX_CIU2_ACK_PPX_IP3(core_id));
1675 return;
1676}
1677
1678static void __init octeon_irq_init_ciu2(void)
1679{
1680 unsigned int i;
1681 struct device_node *gpio_node;
1682 struct device_node *ciu_node;
1683 struct irq_domain *ciu_domain = NULL;
1684
1685 octeon_irq_init_ciu2_percpu();
1686 octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu2;
1687
1688 octeon_irq_ip2 = octeon_irq_ciu2;
1689 octeon_irq_ip3 = octeon_irq_ciu2_mbox;
1690 octeon_irq_ip4 = octeon_irq_ip4_mask;
1691
1692 /* Mips internal */
1693 octeon_irq_init_core();
1694
1695 gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
1696 if (gpio_node) {
1697 struct octeon_irq_gpio_domain_data *gpiod;
1698
1699 gpiod = kzalloc(sizeof(*gpiod), GFP_KERNEL);
1700 if (gpiod) {
1701 /* gpio domain host_data is the base hwirq number. */
1702 gpiod->base_hwirq = 7 << 6;
1703 irq_domain_add_linear(gpio_node, 16, &octeon_irq_domain_ciu2_gpio_ops, gpiod);
1704 of_node_put(gpio_node);
1705 } else
1706 pr_warn("Cannot allocate memory for GPIO irq_domain.\n");
1707 } else
1708 pr_warn("Cannot find device node for cavium,octeon-3860-gpio.\n");
1709
1710 ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-6880-ciu2");
1711 if (ciu_node) {
1712 ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu2_ops, NULL);
1713 of_node_put(ciu_node);
1714 } else
1715 panic("Cannot find device node for cavium,octeon-6880-ciu2.");
1716
1717 /* CUI2 */
1718 for (i = 0; i < 64; i++)
1719 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i);
1720
1721 for (i = 0; i < 32; i++)
1722 octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i, 0,
1723 &octeon_irq_chip_ciu2_wd, handle_level_irq);
1724
1725 for (i = 0; i < 4; i++)
1726 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 3, i + 8);
1727
1728 octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 3, 44);
1729
1730 for (i = 0; i < 4; i++)
1731 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 4, i);
1732
1733 for (i = 0; i < 4; i++)
1734 octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 4, i + 8);
1735
1736 irq_set_chip_and_handler(OCTEON_IRQ_MBOX0, &octeon_irq_chip_ciu2_mbox, handle_percpu_irq);
1737 irq_set_chip_and_handler(OCTEON_IRQ_MBOX1, &octeon_irq_chip_ciu2_mbox, handle_percpu_irq);
1738 irq_set_chip_and_handler(OCTEON_IRQ_MBOX2, &octeon_irq_chip_ciu2_mbox, handle_percpu_irq);
1739 irq_set_chip_and_handler(OCTEON_IRQ_MBOX3, &octeon_irq_chip_ciu2_mbox, handle_percpu_irq);
1740
1741 /* Enable the CIU lines */
1742 set_c0_status(STATUSF_IP3 | STATUSF_IP2);
1743 clear_c0_status(STATUSF_IP4);
1744}
1745
1229void __init arch_init_irq(void) 1746void __init arch_init_irq(void)
1230{ 1747{
1231#ifdef CONFIG_SMP 1748#ifdef CONFIG_SMP
@@ -1233,7 +1750,10 @@ void __init arch_init_irq(void)
1233 cpumask_clear(irq_default_affinity); 1750 cpumask_clear(irq_default_affinity);
1234 cpumask_set_cpu(smp_processor_id(), irq_default_affinity); 1751 cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
1235#endif 1752#endif
1236 octeon_irq_init_ciu(); 1753 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
1754 octeon_irq_init_ciu2();
1755 else
1756 octeon_irq_init_ciu();
1237} 1757}
1238 1758
1239asmlinkage void plat_irq_dispatch(void) 1759asmlinkage void plat_irq_dispatch(void)