twl6030-irq.c (78518ffa08fceee42d61359303c58bdd0a82033f) | twl6030-irq.c (ec1a07b3440cc28946a77a974c21570bbef6ffa1) |
---|---|
1/* 2 * twl6030-irq.c - TWL6030 irq support 3 * 4 * Copyright (C) 2005-2009 Texas Instruments, Inc. 5 * 6 * Modifications to defer interrupt handling to a kernel thread: 7 * Copyright (C) 2006 MontaVista Software, Inc. 8 * --- 39 unchanged lines hidden (view full) --- 48 * TWL6030 (unlike its predecessors, which had two level interrupt handling) 49 * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C. 50 * It exposes status bits saying who has raised an interrupt. There are 51 * three mask registers that corresponds to these status registers, that 52 * enables/disables these interrupts. 53 * 54 * We set up IRQs starting at a platform-specified base. An interrupt map table, 55 * specifies mapping between interrupt number and the associated module. | 1/* 2 * twl6030-irq.c - TWL6030 irq support 3 * 4 * Copyright (C) 2005-2009 Texas Instruments, Inc. 5 * 6 * Modifications to defer interrupt handling to a kernel thread: 7 * Copyright (C) 2006 MontaVista Software, Inc. 8 * --- 39 unchanged lines hidden (view full) --- 48 * TWL6030 (unlike its predecessors, which had two level interrupt handling) 49 * three interrupt registers INT_STS_A, INT_STS_B and INT_STS_C. 50 * It exposes status bits saying who has raised an interrupt. There are 51 * three mask registers that corresponds to these status registers, that 52 * enables/disables these interrupts. 53 * 54 * We set up IRQs starting at a platform-specified base. An interrupt map table, 55 * specifies mapping between interrupt number and the associated module. |
56 * | |
57 */ 58#define TWL6030_NR_IRQS 20 59 60static int twl6030_interrupt_mapping[24] = { 61 PWR_INTR_OFFSET, /* Bit 0 PWRON */ 62 PWR_INTR_OFFSET, /* Bit 1 RPWRON */ 63 PWR_INTR_OFFSET, /* Bit 2 BAT_VLOW */ 64 RTC_INTR_OFFSET, /* Bit 3 RTC_ALARM */ --- 282 unchanged lines hidden (view full) --- 347 return ret; 348} 349EXPORT_SYMBOL(twl6030_mmc_card_detect); 350 351int twl6030_init_irq(struct device *dev, int irq_num) 352{ 353 struct device_node *node = dev->of_node; 354 int nr_irqs, irq_base, irq_end; | 56 */ 57#define TWL6030_NR_IRQS 20 58 59static int twl6030_interrupt_mapping[24] = { 60 PWR_INTR_OFFSET, /* Bit 0 PWRON */ 61 PWR_INTR_OFFSET, /* Bit 1 RPWRON */ 62 PWR_INTR_OFFSET, /* Bit 2 BAT_VLOW */ 63 RTC_INTR_OFFSET, /* Bit 3 RTC_ALARM */ --- 282 unchanged lines hidden (view full) --- 346 return ret; 347} 348EXPORT_SYMBOL(twl6030_mmc_card_detect); 349 350int twl6030_init_irq(struct device *dev, int irq_num) 351{ 352 struct device_node *node = dev->of_node; 353 int nr_irqs, irq_base, irq_end; |
355 356 int status = 0; 357 int i; | |
358 struct task_struct *task; | 354 struct task_struct *task; |
359 int ret; 360 u8 mask[4]; | 355 static struct irq_chip twl6030_irq_chip; 356 int status = 0; 357 int i; 358 u8 mask[4]; |
361 | 359 |
362 static struct irq_chip twl6030_irq_chip; 363 | |
364 nr_irqs = TWL6030_NR_IRQS; 365 366 irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); 367 if (IS_ERR_VALUE(irq_base)) { 368 dev_err(dev, "Fail to allocate IRQ descs\n"); 369 return irq_base; 370 } 371 372 irq_domain_add_legacy(node, nr_irqs, irq_base, 0, 373 &irq_domain_simple_ops, NULL); 374 375 irq_end = irq_base + nr_irqs; 376 377 mask[1] = 0xFF; 378 mask[2] = 0xFF; 379 mask[3] = 0xFF; | 360 nr_irqs = TWL6030_NR_IRQS; 361 362 irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); 363 if (IS_ERR_VALUE(irq_base)) { 364 dev_err(dev, "Fail to allocate IRQ descs\n"); 365 return irq_base; 366 } 367 368 irq_domain_add_legacy(node, nr_irqs, irq_base, 0, 369 &irq_domain_simple_ops, NULL); 370 371 irq_end = irq_base + nr_irqs; 372 373 mask[1] = 0xFF; 374 mask[2] = 0xFF; 375 mask[3] = 0xFF; |
380 ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], 381 REG_INT_MSK_LINE_A, 3); /* MASK ALL INT LINES */ 382 ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], 383 REG_INT_MSK_STS_A, 3); /* MASK ALL INT STS */ 384 ret = twl_i2c_write(TWL_MODULE_PIH, &mask[0], 385 REG_INT_STS_A, 3); /* clear INT_STS_A,B,C */ | |
386 | 376 |
377 /* mask all int lines */ 378 twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_LINE_A, 3); 379 /* mask all int sts */ 380 twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_MSK_STS_A, 3); 381 /* clear INT_STS_A,B,C */ 382 twl_i2c_write(TWL_MODULE_PIH, &mask[0], REG_INT_STS_A, 3); 383 |
|
387 twl6030_irq_base = irq_base; 388 | 384 twl6030_irq_base = irq_base; 385 |
389 /* install an irq handler for each of the modules; | 386 /* 387 * install an irq handler for each of the modules; |
390 * clone dummy irq_chip since PIH can't *do* anything 391 */ 392 twl6030_irq_chip = dummy_irq_chip; 393 twl6030_irq_chip.name = "twl6030"; 394 twl6030_irq_chip.irq_set_type = NULL; 395 twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake; 396 397 for (i = irq_base; i < irq_end; i++) { 398 irq_set_chip_and_handler(i, &twl6030_irq_chip, 399 handle_simple_irq); 400 irq_set_chip_data(i, (void *)irq_num); 401 activate_irq(i); 402 } 403 | 388 * clone dummy irq_chip since PIH can't *do* anything 389 */ 390 twl6030_irq_chip = dummy_irq_chip; 391 twl6030_irq_chip.name = "twl6030"; 392 twl6030_irq_chip.irq_set_type = NULL; 393 twl6030_irq_chip.irq_set_wake = twl6030_irq_set_wake; 394 395 for (i = irq_base; i < irq_end; i++) { 396 irq_set_chip_and_handler(i, &twl6030_irq_chip, 397 handle_simple_irq); 398 irq_set_chip_data(i, (void *)irq_num); 399 activate_irq(i); 400 } 401 |
404 pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", | 402 dev_info(dev, "PIH (irq %d) chaining IRQs %d..%d\n", |
405 irq_num, irq_base, irq_end); 406 407 /* install an irq handler to demultiplex the TWL6030 interrupt */ 408 init_completion(&irq_event); 409 | 403 irq_num, irq_base, irq_end); 404 405 /* install an irq handler to demultiplex the TWL6030 interrupt */ 406 init_completion(&irq_event); 407 |
410 status = request_irq(irq_num, handle_twl6030_pih, 0, 411 "TWL6030-PIH", &irq_event); | 408 status = request_irq(irq_num, handle_twl6030_pih, 0, "TWL6030-PIH", 409 &irq_event); |
412 if (status < 0) { | 410 if (status < 0) { |
413 pr_err("twl6030: could not claim irq%d: %d\n", irq_num, status); | 411 dev_err(dev, "could not claim irq %d: %d\n", irq_num, status); |
414 goto fail_irq; 415 } 416 417 task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); 418 if (IS_ERR(task)) { | 412 goto fail_irq; 413 } 414 415 task = kthread_run(twl6030_irq_thread, (void *)irq_num, "twl6030-irq"); 416 if (IS_ERR(task)) { |
419 pr_err("twl6030: could not create irq %d thread!\n", irq_num); | 417 dev_err(dev, "could not create irq %d thread!\n", irq_num); |
420 status = PTR_ERR(task); 421 goto fail_kthread; 422 } 423 424 twl_irq = irq_num; 425 register_pm_notifier(&twl6030_irq_pm_notifier_block); 426 return irq_base; 427 428fail_kthread: 429 free_irq(irq_num, &irq_event); 430 431fail_irq: 432 for (i = irq_base; i < irq_end; i++) 433 irq_set_chip_and_handler(i, NULL, NULL); | 418 status = PTR_ERR(task); 419 goto fail_kthread; 420 } 421 422 twl_irq = irq_num; 423 register_pm_notifier(&twl6030_irq_pm_notifier_block); 424 return irq_base; 425 426fail_kthread: 427 free_irq(irq_num, &irq_event); 428 429fail_irq: 430 for (i = irq_base; i < irq_end; i++) 431 irq_set_chip_and_handler(i, NULL, NULL); |
432 |
|
434 return status; 435} 436 437int twl6030_exit_irq(void) 438{ 439 unregister_pm_notifier(&twl6030_irq_pm_notifier_block); 440 441 if (twl6030_irq_base) { 442 pr_err("twl6030: can't yet clean up IRQs?\n"); 443 return -ENOSYS; 444 } 445 return 0; 446} 447 | 433 return status; 434} 435 436int twl6030_exit_irq(void) 437{ 438 unregister_pm_notifier(&twl6030_irq_pm_notifier_block); 439 440 if (twl6030_irq_base) { 441 pr_err("twl6030: can't yet clean up IRQs?\n"); 442 return -ENOSYS; 443 } 444 return 0; 445} 446 |