1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * PRU-ICSS INTC IRQChip driver for various TI SoCs 4 * 5 * Copyright (C) 2016-2020 Texas Instruments Incorporated - http://www.ti.com/ 6 * 7 * Author(s): 8 * Andrew F. Davis <afd@ti.com> 9 * Suman Anna <s-anna@ti.com> 10 * Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org> for Texas Instruments 11 * 12 * Copyright (C) 2019 David Lechner <david@lechnology.com> 13 */ 14 15 #include <linux/interrupt.h> 16 #include <linux/irq.h> 17 #include <linux/irqchip/chained_irq.h> 18 #include <linux/irqdomain.h> 19 #include <linux/module.h> 20 #include <linux/of_device.h> 21 #include <linux/platform_device.h> 22 23 /* 24 * Number of host interrupts reaching the main MPU sub-system. Note that this 25 * is not the same as the total number of host interrupts supported by the PRUSS 26 * INTC instance 27 */ 28 #define MAX_NUM_HOST_IRQS 8 29 30 /* minimum starting host interrupt number for MPU */ 31 #define FIRST_PRU_HOST_INT 2 32 33 /* PRU_ICSS_INTC registers */ 34 #define PRU_INTC_REVID 0x0000 35 #define PRU_INTC_CR 0x0004 36 #define PRU_INTC_GER 0x0010 37 #define PRU_INTC_GNLR 0x001c 38 #define PRU_INTC_SISR 0x0020 39 #define PRU_INTC_SICR 0x0024 40 #define PRU_INTC_EISR 0x0028 41 #define PRU_INTC_EICR 0x002c 42 #define PRU_INTC_HIEISR 0x0034 43 #define PRU_INTC_HIDISR 0x0038 44 #define PRU_INTC_GPIR 0x0080 45 #define PRU_INTC_SRSR(x) (0x0200 + (x) * 4) 46 #define PRU_INTC_SECR(x) (0x0280 + (x) * 4) 47 #define PRU_INTC_ESR(x) (0x0300 + (x) * 4) 48 #define PRU_INTC_ECR(x) (0x0380 + (x) * 4) 49 #define PRU_INTC_CMR(x) (0x0400 + (x) * 4) 50 #define PRU_INTC_HMR(x) (0x0800 + (x) * 4) 51 #define PRU_INTC_HIPIR(x) (0x0900 + (x) * 4) 52 #define PRU_INTC_SIPR(x) (0x0d00 + (x) * 4) 53 #define PRU_INTC_SITR(x) (0x0d80 + (x) * 4) 54 #define PRU_INTC_HINLR(x) (0x1100 + (x) * 4) 55 #define PRU_INTC_HIER 0x1500 56 57 /* CMR register bit-field macros */ 58 #define CMR_EVT_MAP_MASK 0xf 59 #define CMR_EVT_MAP_BITS 8 60 #define CMR_EVT_PER_REG 4 61 62 /* HMR register bit-field macros */ 63 #define HMR_CH_MAP_MASK 0xf 64 #define HMR_CH_MAP_BITS 8 65 #define HMR_CH_PER_REG 4 66 67 /* HIPIR register bit-fields */ 68 #define INTC_HIPIR_NONE_HINT 0x80000000 69 70 #define MAX_PRU_SYS_EVENTS 160 71 #define MAX_PRU_CHANNELS 20 72 73 /** 74 * struct pruss_intc_map_record - keeps track of actual mapping state 75 * @value: The currently mapped value (channel or host) 76 * @ref_count: Keeps track of number of current users of this resource 77 */ 78 struct pruss_intc_map_record { 79 u8 value; 80 u8 ref_count; 81 }; 82 83 /** 84 * struct pruss_intc_match_data - match data to handle SoC variations 85 * @num_system_events: number of input system events handled by the PRUSS INTC 86 * @num_host_events: number of host events (which is equal to number of 87 * channels) supported by the PRUSS INTC 88 */ 89 struct pruss_intc_match_data { 90 u8 num_system_events; 91 u8 num_host_events; 92 }; 93 94 /** 95 * struct pruss_intc - PRUSS interrupt controller structure 96 * @event_channel: current state of system event to channel mappings 97 * @channel_host: current state of channel to host mappings 98 * @irqs: kernel irq numbers corresponding to PRUSS host interrupts 99 * @base: base virtual address of INTC register space 100 * @domain: irq domain for this interrupt controller 101 * @soc_config: cached PRUSS INTC IP configuration data 102 * @dev: PRUSS INTC device pointer 103 * @lock: mutex to serialize interrupts mapping 104 */ 105 struct pruss_intc { 106 struct pruss_intc_map_record event_channel[MAX_PRU_SYS_EVENTS]; 107 struct pruss_intc_map_record channel_host[MAX_PRU_CHANNELS]; 108 unsigned int irqs[MAX_NUM_HOST_IRQS]; 109 void __iomem *base; 110 struct irq_domain *domain; 111 const struct pruss_intc_match_data *soc_config; 112 struct device *dev; 113 struct mutex lock; /* PRUSS INTC lock */ 114 }; 115 116 /** 117 * struct pruss_host_irq_data - PRUSS host irq data structure 118 * @intc: PRUSS interrupt controller pointer 119 * @host_irq: host irq number 120 */ 121 struct pruss_host_irq_data { 122 struct pruss_intc *intc; 123 u8 host_irq; 124 }; 125 126 static inline u32 pruss_intc_read_reg(struct pruss_intc *intc, unsigned int reg) 127 { 128 return readl_relaxed(intc->base + reg); 129 } 130 131 static inline void pruss_intc_write_reg(struct pruss_intc *intc, 132 unsigned int reg, u32 val) 133 { 134 writel_relaxed(val, intc->base + reg); 135 } 136 137 static void pruss_intc_update_cmr(struct pruss_intc *intc, unsigned int evt, 138 u8 ch) 139 { 140 u32 idx, offset, val; 141 142 idx = evt / CMR_EVT_PER_REG; 143 offset = (evt % CMR_EVT_PER_REG) * CMR_EVT_MAP_BITS; 144 145 val = pruss_intc_read_reg(intc, PRU_INTC_CMR(idx)); 146 val &= ~(CMR_EVT_MAP_MASK << offset); 147 val |= ch << offset; 148 pruss_intc_write_reg(intc, PRU_INTC_CMR(idx), val); 149 150 dev_dbg(intc->dev, "SYSEV%u -> CH%d (CMR%d 0x%08x)\n", evt, ch, 151 idx, pruss_intc_read_reg(intc, PRU_INTC_CMR(idx))); 152 } 153 154 static void pruss_intc_update_hmr(struct pruss_intc *intc, u8 ch, u8 host) 155 { 156 u32 idx, offset, val; 157 158 idx = ch / HMR_CH_PER_REG; 159 offset = (ch % HMR_CH_PER_REG) * HMR_CH_MAP_BITS; 160 161 val = pruss_intc_read_reg(intc, PRU_INTC_HMR(idx)); 162 val &= ~(HMR_CH_MAP_MASK << offset); 163 val |= host << offset; 164 pruss_intc_write_reg(intc, PRU_INTC_HMR(idx), val); 165 166 dev_dbg(intc->dev, "CH%d -> HOST%d (HMR%d 0x%08x)\n", ch, host, idx, 167 pruss_intc_read_reg(intc, PRU_INTC_HMR(idx))); 168 } 169 170 /** 171 * pruss_intc_map() - configure the PRUSS INTC 172 * @intc: PRUSS interrupt controller pointer 173 * @hwirq: the system event number 174 * 175 * Configures the PRUSS INTC with the provided configuration from the one parsed 176 * in the xlate function. 177 */ 178 static void pruss_intc_map(struct pruss_intc *intc, unsigned long hwirq) 179 { 180 struct device *dev = intc->dev; 181 u8 ch, host, reg_idx; 182 u32 val; 183 184 mutex_lock(&intc->lock); 185 186 intc->event_channel[hwirq].ref_count++; 187 188 ch = intc->event_channel[hwirq].value; 189 host = intc->channel_host[ch].value; 190 191 pruss_intc_update_cmr(intc, hwirq, ch); 192 193 reg_idx = hwirq / 32; 194 val = BIT(hwirq % 32); 195 196 /* clear and enable system event */ 197 pruss_intc_write_reg(intc, PRU_INTC_ESR(reg_idx), val); 198 pruss_intc_write_reg(intc, PRU_INTC_SECR(reg_idx), val); 199 200 if (++intc->channel_host[ch].ref_count == 1) { 201 pruss_intc_update_hmr(intc, ch, host); 202 203 /* enable host interrupts */ 204 pruss_intc_write_reg(intc, PRU_INTC_HIEISR, host); 205 } 206 207 dev_dbg(dev, "mapped system_event = %lu channel = %d host = %d", 208 hwirq, ch, host); 209 210 mutex_unlock(&intc->lock); 211 } 212 213 /** 214 * pruss_intc_unmap() - unconfigure the PRUSS INTC 215 * @intc: PRUSS interrupt controller pointer 216 * @hwirq: the system event number 217 * 218 * Undo whatever was done in pruss_intc_map() for a PRU core. 219 * Mappings are reference counted, so resources are only disabled when there 220 * are no longer any users. 221 */ 222 static void pruss_intc_unmap(struct pruss_intc *intc, unsigned long hwirq) 223 { 224 u8 ch, host, reg_idx; 225 u32 val; 226 227 mutex_lock(&intc->lock); 228 229 ch = intc->event_channel[hwirq].value; 230 host = intc->channel_host[ch].value; 231 232 if (--intc->channel_host[ch].ref_count == 0) { 233 /* disable host interrupts */ 234 pruss_intc_write_reg(intc, PRU_INTC_HIDISR, host); 235 236 /* clear the map using reset value 0 */ 237 pruss_intc_update_hmr(intc, ch, 0); 238 } 239 240 intc->event_channel[hwirq].ref_count--; 241 reg_idx = hwirq / 32; 242 val = BIT(hwirq % 32); 243 244 /* disable system events */ 245 pruss_intc_write_reg(intc, PRU_INTC_ECR(reg_idx), val); 246 /* clear any pending status */ 247 pruss_intc_write_reg(intc, PRU_INTC_SECR(reg_idx), val); 248 249 /* clear the map using reset value 0 */ 250 pruss_intc_update_cmr(intc, hwirq, 0); 251 252 dev_dbg(intc->dev, "unmapped system_event = %lu channel = %d host = %d\n", 253 hwirq, ch, host); 254 255 mutex_unlock(&intc->lock); 256 } 257 258 static void pruss_intc_init(struct pruss_intc *intc) 259 { 260 const struct pruss_intc_match_data *soc_config = intc->soc_config; 261 int num_chnl_map_regs, num_host_intr_regs, num_event_type_regs, i; 262 263 num_chnl_map_regs = DIV_ROUND_UP(soc_config->num_system_events, 264 CMR_EVT_PER_REG); 265 num_host_intr_regs = DIV_ROUND_UP(soc_config->num_host_events, 266 HMR_CH_PER_REG); 267 num_event_type_regs = DIV_ROUND_UP(soc_config->num_system_events, 32); 268 269 /* 270 * configure polarity (SIPR register) to active high and 271 * type (SITR register) to level interrupt for all system events 272 */ 273 for (i = 0; i < num_event_type_regs; i++) { 274 pruss_intc_write_reg(intc, PRU_INTC_SIPR(i), 0xffffffff); 275 pruss_intc_write_reg(intc, PRU_INTC_SITR(i), 0); 276 } 277 278 /* clear all interrupt channel map registers, 4 events per register */ 279 for (i = 0; i < num_chnl_map_regs; i++) 280 pruss_intc_write_reg(intc, PRU_INTC_CMR(i), 0); 281 282 /* clear all host interrupt map registers, 4 channels per register */ 283 for (i = 0; i < num_host_intr_regs; i++) 284 pruss_intc_write_reg(intc, PRU_INTC_HMR(i), 0); 285 286 /* global interrupt enable */ 287 pruss_intc_write_reg(intc, PRU_INTC_GER, 1); 288 } 289 290 static void pruss_intc_irq_ack(struct irq_data *data) 291 { 292 struct pruss_intc *intc = irq_data_get_irq_chip_data(data); 293 unsigned int hwirq = data->hwirq; 294 295 pruss_intc_write_reg(intc, PRU_INTC_SICR, hwirq); 296 } 297 298 static void pruss_intc_irq_mask(struct irq_data *data) 299 { 300 struct pruss_intc *intc = irq_data_get_irq_chip_data(data); 301 unsigned int hwirq = data->hwirq; 302 303 pruss_intc_write_reg(intc, PRU_INTC_EICR, hwirq); 304 } 305 306 static void pruss_intc_irq_unmask(struct irq_data *data) 307 { 308 struct pruss_intc *intc = irq_data_get_irq_chip_data(data); 309 unsigned int hwirq = data->hwirq; 310 311 pruss_intc_write_reg(intc, PRU_INTC_EISR, hwirq); 312 } 313 314 static int pruss_intc_irq_reqres(struct irq_data *data) 315 { 316 if (!try_module_get(THIS_MODULE)) 317 return -ENODEV; 318 319 return 0; 320 } 321 322 static void pruss_intc_irq_relres(struct irq_data *data) 323 { 324 module_put(THIS_MODULE); 325 } 326 327 static int pruss_intc_irq_get_irqchip_state(struct irq_data *data, 328 enum irqchip_irq_state which, 329 bool *state) 330 { 331 struct pruss_intc *intc = irq_data_get_irq_chip_data(data); 332 u32 reg, mask, srsr; 333 334 if (which != IRQCHIP_STATE_PENDING) 335 return -EINVAL; 336 337 reg = PRU_INTC_SRSR(data->hwirq / 32); 338 mask = BIT(data->hwirq % 32); 339 340 srsr = pruss_intc_read_reg(intc, reg); 341 342 *state = !!(srsr & mask); 343 344 return 0; 345 } 346 347 static int pruss_intc_irq_set_irqchip_state(struct irq_data *data, 348 enum irqchip_irq_state which, 349 bool state) 350 { 351 struct pruss_intc *intc = irq_data_get_irq_chip_data(data); 352 353 if (which != IRQCHIP_STATE_PENDING) 354 return -EINVAL; 355 356 if (state) 357 pruss_intc_write_reg(intc, PRU_INTC_SISR, data->hwirq); 358 else 359 pruss_intc_write_reg(intc, PRU_INTC_SICR, data->hwirq); 360 361 return 0; 362 } 363 364 static struct irq_chip pruss_irqchip = { 365 .name = "pruss-intc", 366 .irq_ack = pruss_intc_irq_ack, 367 .irq_mask = pruss_intc_irq_mask, 368 .irq_unmask = pruss_intc_irq_unmask, 369 .irq_request_resources = pruss_intc_irq_reqres, 370 .irq_release_resources = pruss_intc_irq_relres, 371 .irq_get_irqchip_state = pruss_intc_irq_get_irqchip_state, 372 .irq_set_irqchip_state = pruss_intc_irq_set_irqchip_state, 373 }; 374 375 static int pruss_intc_validate_mapping(struct pruss_intc *intc, int event, 376 int channel, int host) 377 { 378 struct device *dev = intc->dev; 379 int ret = 0; 380 381 mutex_lock(&intc->lock); 382 383 /* check if sysevent already assigned */ 384 if (intc->event_channel[event].ref_count > 0 && 385 intc->event_channel[event].value != channel) { 386 dev_err(dev, "event %d (req. ch %d) already assigned to channel %d\n", 387 event, channel, intc->event_channel[event].value); 388 ret = -EBUSY; 389 goto unlock; 390 } 391 392 /* check if channel already assigned */ 393 if (intc->channel_host[channel].ref_count > 0 && 394 intc->channel_host[channel].value != host) { 395 dev_err(dev, "channel %d (req. host %d) already assigned to host %d\n", 396 channel, host, intc->channel_host[channel].value); 397 ret = -EBUSY; 398 goto unlock; 399 } 400 401 intc->event_channel[event].value = channel; 402 intc->channel_host[channel].value = host; 403 404 unlock: 405 mutex_unlock(&intc->lock); 406 return ret; 407 } 408 409 static int 410 pruss_intc_irq_domain_xlate(struct irq_domain *d, struct device_node *node, 411 const u32 *intspec, unsigned int intsize, 412 unsigned long *out_hwirq, unsigned int *out_type) 413 { 414 struct pruss_intc *intc = d->host_data; 415 struct device *dev = intc->dev; 416 int ret, sys_event, channel, host; 417 418 if (intsize < 3) 419 return -EINVAL; 420 421 sys_event = intspec[0]; 422 if (sys_event < 0 || sys_event >= intc->soc_config->num_system_events) { 423 dev_err(dev, "%d is not valid event number\n", sys_event); 424 return -EINVAL; 425 } 426 427 channel = intspec[1]; 428 if (channel < 0 || channel >= intc->soc_config->num_host_events) { 429 dev_err(dev, "%d is not valid channel number", channel); 430 return -EINVAL; 431 } 432 433 host = intspec[2]; 434 if (host < 0 || host >= intc->soc_config->num_host_events) { 435 dev_err(dev, "%d is not valid host irq number\n", host); 436 return -EINVAL; 437 } 438 439 /* check if requested sys_event was already mapped, if so validate it */ 440 ret = pruss_intc_validate_mapping(intc, sys_event, channel, host); 441 if (ret) 442 return ret; 443 444 *out_hwirq = sys_event; 445 *out_type = IRQ_TYPE_LEVEL_HIGH; 446 447 return 0; 448 } 449 450 static int pruss_intc_irq_domain_map(struct irq_domain *d, unsigned int virq, 451 irq_hw_number_t hw) 452 { 453 struct pruss_intc *intc = d->host_data; 454 455 pruss_intc_map(intc, hw); 456 457 irq_set_chip_data(virq, intc); 458 irq_set_chip_and_handler(virq, &pruss_irqchip, handle_level_irq); 459 460 return 0; 461 } 462 463 static void pruss_intc_irq_domain_unmap(struct irq_domain *d, unsigned int virq) 464 { 465 struct pruss_intc *intc = d->host_data; 466 unsigned long hwirq = irqd_to_hwirq(irq_get_irq_data(virq)); 467 468 irq_set_chip_and_handler(virq, NULL, NULL); 469 irq_set_chip_data(virq, NULL); 470 pruss_intc_unmap(intc, hwirq); 471 } 472 473 static const struct irq_domain_ops pruss_intc_irq_domain_ops = { 474 .xlate = pruss_intc_irq_domain_xlate, 475 .map = pruss_intc_irq_domain_map, 476 .unmap = pruss_intc_irq_domain_unmap, 477 }; 478 479 static void pruss_intc_irq_handler(struct irq_desc *desc) 480 { 481 unsigned int irq = irq_desc_get_irq(desc); 482 struct irq_chip *chip = irq_desc_get_chip(desc); 483 struct pruss_host_irq_data *host_irq_data = irq_get_handler_data(irq); 484 struct pruss_intc *intc = host_irq_data->intc; 485 u8 host_irq = host_irq_data->host_irq + FIRST_PRU_HOST_INT; 486 487 chained_irq_enter(chip, desc); 488 489 while (true) { 490 u32 hipir; 491 unsigned int virq; 492 int hwirq; 493 494 /* get highest priority pending PRUSS system event */ 495 hipir = pruss_intc_read_reg(intc, PRU_INTC_HIPIR(host_irq)); 496 if (hipir & INTC_HIPIR_NONE_HINT) 497 break; 498 499 hwirq = hipir & GENMASK(9, 0); 500 virq = irq_find_mapping(intc->domain, hwirq); 501 502 /* 503 * NOTE: manually ACK any system events that do not have a 504 * handler mapped yet 505 */ 506 if (WARN_ON_ONCE(!virq)) 507 pruss_intc_write_reg(intc, PRU_INTC_SICR, hwirq); 508 else 509 generic_handle_irq(virq); 510 } 511 512 chained_irq_exit(chip, desc); 513 } 514 515 static const char * const irq_names[MAX_NUM_HOST_IRQS] = { 516 "host_intr0", "host_intr1", "host_intr2", "host_intr3", 517 "host_intr4", "host_intr5", "host_intr6", "host_intr7", 518 }; 519 520 static int pruss_intc_probe(struct platform_device *pdev) 521 { 522 const struct pruss_intc_match_data *data; 523 struct device *dev = &pdev->dev; 524 struct pruss_intc *intc; 525 struct pruss_host_irq_data *host_data; 526 int i, irq, ret; 527 u8 max_system_events, irqs_reserved = 0; 528 529 data = of_device_get_match_data(dev); 530 if (!data) 531 return -ENODEV; 532 533 max_system_events = data->num_system_events; 534 535 intc = devm_kzalloc(dev, sizeof(*intc), GFP_KERNEL); 536 if (!intc) 537 return -ENOMEM; 538 539 intc->soc_config = data; 540 intc->dev = dev; 541 platform_set_drvdata(pdev, intc); 542 543 intc->base = devm_platform_ioremap_resource(pdev, 0); 544 if (IS_ERR(intc->base)) 545 return PTR_ERR(intc->base); 546 547 ret = of_property_read_u8(dev->of_node, "ti,irqs-reserved", 548 &irqs_reserved); 549 550 /* 551 * The irqs-reserved is used only for some SoC's therefore not having 552 * this property is still valid 553 */ 554 if (ret < 0 && ret != -EINVAL) 555 return ret; 556 557 pruss_intc_init(intc); 558 559 mutex_init(&intc->lock); 560 561 intc->domain = irq_domain_add_linear(dev->of_node, max_system_events, 562 &pruss_intc_irq_domain_ops, intc); 563 if (!intc->domain) 564 return -ENOMEM; 565 566 for (i = 0; i < MAX_NUM_HOST_IRQS; i++) { 567 if (irqs_reserved & BIT(i)) 568 continue; 569 570 irq = platform_get_irq_byname(pdev, irq_names[i]); 571 if (irq <= 0) { 572 ret = (irq == 0) ? -EINVAL : irq; 573 goto fail_irq; 574 } 575 576 intc->irqs[i] = irq; 577 578 host_data = devm_kzalloc(dev, sizeof(*host_data), GFP_KERNEL); 579 if (!host_data) { 580 ret = -ENOMEM; 581 goto fail_irq; 582 } 583 584 host_data->intc = intc; 585 host_data->host_irq = i; 586 587 irq_set_handler_data(irq, host_data); 588 irq_set_chained_handler(irq, pruss_intc_irq_handler); 589 } 590 591 return 0; 592 593 fail_irq: 594 while (--i >= 0) { 595 if (intc->irqs[i]) 596 irq_set_chained_handler_and_data(intc->irqs[i], NULL, 597 NULL); 598 } 599 600 irq_domain_remove(intc->domain); 601 602 return ret; 603 } 604 605 static int pruss_intc_remove(struct platform_device *pdev) 606 { 607 struct pruss_intc *intc = platform_get_drvdata(pdev); 608 u8 max_system_events = intc->soc_config->num_system_events; 609 unsigned int hwirq; 610 int i; 611 612 for (i = 0; i < MAX_NUM_HOST_IRQS; i++) { 613 if (intc->irqs[i]) 614 irq_set_chained_handler_and_data(intc->irqs[i], NULL, 615 NULL); 616 } 617 618 for (hwirq = 0; hwirq < max_system_events; hwirq++) 619 irq_dispose_mapping(irq_find_mapping(intc->domain, hwirq)); 620 621 irq_domain_remove(intc->domain); 622 623 return 0; 624 } 625 626 static const struct pruss_intc_match_data pruss_intc_data = { 627 .num_system_events = 64, 628 .num_host_events = 10, 629 }; 630 631 static const struct pruss_intc_match_data icssg_intc_data = { 632 .num_system_events = 160, 633 .num_host_events = 20, 634 }; 635 636 static const struct of_device_id pruss_intc_of_match[] = { 637 { 638 .compatible = "ti,pruss-intc", 639 .data = &pruss_intc_data, 640 }, 641 { 642 .compatible = "ti,icssg-intc", 643 .data = &icssg_intc_data, 644 }, 645 { /* sentinel */ }, 646 }; 647 MODULE_DEVICE_TABLE(of, pruss_intc_of_match); 648 649 static struct platform_driver pruss_intc_driver = { 650 .driver = { 651 .name = "pruss-intc", 652 .of_match_table = pruss_intc_of_match, 653 .suppress_bind_attrs = true, 654 }, 655 .probe = pruss_intc_probe, 656 .remove = pruss_intc_remove, 657 }; 658 module_platform_driver(pruss_intc_driver); 659 660 MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>"); 661 MODULE_AUTHOR("Suman Anna <s-anna@ti.com>"); 662 MODULE_AUTHOR("Grzegorz Jaszczyk <grzegorz.jaszczyk@linaro.org>"); 663 MODULE_DESCRIPTION("TI PRU-ICSS INTC Driver"); 664 MODULE_LICENSE("GPL v2"); 665