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