Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

mfd: Move twl-core IRQ allocation into twl[4030|6030]-irq files

During DT adaptation, the irq_alloc_desc was added into twl-core, but
due to the rather different and weird IRQ management required by the twl4030,
it is much better to have a different approach for it.
The issue is that twl4030 uses a two level IRQ mechanism but handles all the
PWR interrupts as part of the twl-core interrupt range. It ends up with a
range of 16 interrupts total for CORE and PWR.

The other twl4030 functionalities already have a dedicated driver and thus
their IRQs and irqdomain can and should be defined localy.

twl6030 is using a single level IRQ controller and thus does not require any
trick.

Move the irq_alloc_desc and irq_domain_add_legacy in twl4030-irq and
twl6030-irq.

Allocate together CORE and PWR IRQs for twl4030-irq.

Conflicts:

drivers/mfd/twl-core.c

Signed-off-by: Benoit Cousson <b-cousson@ti.com>
Acked-by: Felipe Balbi <balbi@ti.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>

authored by

Benoit Cousson and committed by
Samuel Ortiz
78518ffa 1b8f333f

+56 -37
+5 -24
drivers/mfd/twl-core.c
··· 147 147 148 148 #define TWL_MODULE_LAST TWL4030_MODULE_LAST 149 149 150 - #define TWL4030_NR_IRQS 8 151 - #define TWL6030_NR_IRQS 20 152 - 153 150 /* Base Address defns for twl4030_map[] */ 154 151 155 152 /* subchip/slave 0 - USB ID */ ··· 1183 1186 twl_probe(struct i2c_client *client, const struct i2c_device_id *id) 1184 1187 { 1185 1188 int irq_base; 1186 - int irq_end; 1187 1189 int status; 1188 1190 unsigned i; 1189 1191 struct twl4030_platform_data *pdata = client->dev.platform_data; 1190 1192 struct device_node *node = client->dev.of_node; 1191 1193 u8 temp; 1192 1194 int ret = 0; 1193 - int nr_irqs = TWL4030_NR_IRQS; 1194 - 1195 - if ((id->driver_data) & TWL6030_CLASS) 1196 - nr_irqs = TWL6030_NR_IRQS; 1197 1195 1198 1196 if (node && !pdata) { 1199 1197 /* ··· 1206 1214 dev_dbg(&client->dev, "no platform data?\n"); 1207 1215 return -EINVAL; 1208 1216 } 1209 - 1210 - status = irq_alloc_descs(-1, 0, nr_irqs, 0); 1211 - if (IS_ERR_VALUE(status)) { 1212 - dev_err(&client->dev, "Fail to allocate IRQ descs\n"); 1213 - return status; 1214 - } 1215 - 1216 - irq_base = status; 1217 - irq_end = irq_base + nr_irqs; 1218 - irq_domain_add_legacy(node, nr_irqs, irq_base, 0, 1219 - &irq_domain_simple_ops, NULL); 1220 1217 1221 1218 if (i2c_check_functionality(client->adapter, I2C_FUNC_I2C) == 0) { 1222 1219 dev_dbg(&client->dev, "can't talk I2C?\n"); ··· 1261 1280 if (client->irq) { 1262 1281 if (twl_class_is_4030()) { 1263 1282 twl4030_init_chip_irq(id->name); 1264 - status = twl4030_init_irq(client->irq, irq_base, 1265 - irq_end); 1283 + irq_base = twl4030_init_irq(&client->dev, client->irq); 1266 1284 } else { 1267 - status = twl6030_init_irq(client->irq, irq_base, 1268 - irq_end); 1285 + irq_base = twl6030_init_irq(&client->dev, client->irq); 1269 1286 } 1270 1287 1271 - if (status < 0) 1288 + if (irq_base < 0) { 1289 + status = irq_base; 1272 1290 goto fail; 1291 + } 1273 1292 } 1274 1293 1275 1294 /* Disable TWL4030/TWL5030 I2C Pull-up on I2C1 and I2C4(SR) interface.
+2 -2
drivers/mfd/twl-core.h
··· 1 1 #ifndef __TWL_CORE_H__ 2 2 #define __TWL_CORE_H__ 3 3 4 - extern int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); 4 + extern int twl6030_init_irq(struct device *dev, int irq_num); 5 5 extern int twl6030_exit_irq(void); 6 - extern int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end); 6 + extern int twl4030_init_irq(struct device *dev, int irq_num); 7 7 extern int twl4030_exit_irq(void); 8 8 extern int twl4030_init_chip_irq(const char *chip); 9 9
+27 -2
drivers/mfd/twl4030-irq.c
··· 28 28 */ 29 29 30 30 #include <linux/init.h> 31 + #include <linux/export.h> 31 32 #include <linux/interrupt.h> 32 33 #include <linux/irq.h> 33 34 #include <linux/slab.h> 34 35 36 + #include <linux/of.h> 37 + #include <linux/irqdomain.h> 35 38 #include <linux/i2c/twl.h> 36 39 37 40 #include "twl-core.h" ··· 56 53 * base + 8 .. base + 15 SIH for PWR_INT 57 54 * base + 16 .. base + 33 SIH for GPIO 58 55 */ 56 + #define TWL4030_CORE_NR_IRQS 8 57 + #define TWL4030_PWR_NR_IRQS 8 59 58 60 59 /* PIH register offsets */ 61 60 #define REG_PIH_ISR_P1 0x01 ··· 700 695 /* FIXME pass in which interrupt line we'll use ... */ 701 696 #define twl_irq_line 0 702 697 703 - int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) 698 + int twl4030_init_irq(struct device *dev, int irq_num) 704 699 { 705 700 static struct irq_chip twl4030_irq_chip; 701 + int irq_base, irq_end, nr_irqs; 702 + struct device_node *node = dev->of_node; 706 703 707 704 int status; 708 705 int i; 706 + 707 + /* 708 + * TWL core and pwr interrupts must be contiguous because 709 + * the hwirqs numbers are defined contiguously from 1 to 15. 710 + * Create only one domain for both. 711 + */ 712 + nr_irqs = TWL4030_PWR_NR_IRQS + TWL4030_CORE_NR_IRQS; 713 + 714 + irq_base = irq_alloc_descs(-1, 0, nr_irqs, 0); 715 + if (IS_ERR_VALUE(irq_base)) { 716 + dev_err(dev, "Fail to allocate IRQ descs\n"); 717 + return irq_base; 718 + } 719 + 720 + irq_domain_add_legacy(node, nr_irqs, irq_base, 0, 721 + &irq_domain_simple_ops, NULL); 722 + 723 + irq_end = irq_base + TWL4030_CORE_NR_IRQS; 709 724 710 725 /* 711 726 * Mask and clear all TWL4030 interrupts since initially we do ··· 772 747 goto fail_rqirq; 773 748 } 774 749 775 - return status; 750 + return irq_base; 776 751 fail_rqirq: 777 752 /* clean up twl4030_sih_setup */ 778 753 fail:
+22 -9
drivers/mfd/twl6030-irq.c
··· 39 39 #include <linux/i2c/twl.h> 40 40 #include <linux/platform_device.h> 41 41 #include <linux/suspend.h> 42 + #include <linux/of.h> 43 + #include <linux/irqdomain.h> 42 44 43 45 #include "twl-core.h" 44 46 ··· 55 53 * specifies mapping between interrupt number and the associated module. 56 54 * 57 55 */ 56 + #define TWL6030_NR_IRQS 20 58 57 59 58 static int twl6030_interrupt_mapping[24] = { 60 59 PWR_INTR_OFFSET, /* Bit 0 PWRON */ ··· 249 246 return 0; 250 247 } 251 248 252 - /*----------------------------------------------------------------------*/ 253 - 254 - static unsigned twl6030_irq_next; 255 - 256 - /*----------------------------------------------------------------------*/ 257 249 int twl6030_interrupt_unmask(u8 bit_mask, u8 offset) 258 250 { 259 251 int ret; ··· 348 350 } 349 351 EXPORT_SYMBOL(twl6030_mmc_card_detect); 350 352 351 - int twl6030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) 353 + int twl6030_init_irq(struct device *dev, int irq_num) 352 354 { 355 + struct device_node *node = dev->of_node; 356 + int nr_irqs, irq_base, irq_end; 353 357 354 358 int status = 0; 355 359 int i; ··· 360 360 u8 mask[4]; 361 361 362 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 + 363 377 mask[1] = 0xFF; 364 378 mask[2] = 0xFF; 365 379 mask[3] = 0xFF; ··· 401 387 activate_irq(i); 402 388 } 403 389 404 - twl6030_irq_next = i; 405 390 pr_info("twl6030: %s (irq %d) chaining IRQs %d..%d\n", "PIH", 406 - irq_num, irq_base, twl6030_irq_next - 1); 391 + irq_num, irq_base, irq_end); 407 392 408 393 /* install an irq handler to demultiplex the TWL6030 interrupt */ 409 394 init_completion(&irq_event); ··· 423 410 424 411 twl_irq = irq_num; 425 412 register_pm_notifier(&twl6030_irq_pm_notifier_block); 426 - return status; 413 + return irq_base; 427 414 428 415 fail_kthread: 429 416 free_irq(irq_num, &irq_event);