aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorRhyland Klein <rklein@nvidia.com>2012-05-18 05:52:19 -0400
committerSamuel Ortiz <sameo@linux.intel.com>2012-05-20 11:27:08 -0400
commit21f7541d8861fdcdff663c68903e961ca1b06dc6 (patch)
tree48e9c376058b13a653146bd67c9e097f794f2ce8 /drivers
parentb09530ef844f0bf29ed3677080c02b179be84818 (diff)
mfd: Add tps65910-irq devicetree init and irqdomain support
This change changes the tps65910-irq code to use irqdomain, and support initialization from devicetree. This assumes that the irq_base in the platform data is -1 if devicetree is used. Signed-off-by: Rhyland Klein <rklein@nvidia.com> Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/tps65910-irq.c96
2 files changed, 63 insertions, 34 deletions
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6da82ded3371..b819eea1775a 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -190,6 +190,7 @@ config MFD_TPS65910
190 depends on I2C=y && GPIOLIB 190 depends on I2C=y && GPIOLIB
191 select MFD_CORE 191 select MFD_CORE
192 select REGMAP_I2C 192 select REGMAP_I2C
193 select IRQ_DOMAIN
193 help 194 help
194 if you say yes here you get support for the TPS65910 series of 195 if you say yes here you get support for the TPS65910 series of
195 Power Management chips. 196 Power Management chips.
diff --git a/drivers/mfd/tps65910-irq.c b/drivers/mfd/tps65910-irq.c
index 0f1ff7fbdc74..09aab3e4776d 100644
--- a/drivers/mfd/tps65910-irq.c
+++ b/drivers/mfd/tps65910-irq.c
@@ -20,15 +20,10 @@
20#include <linux/device.h> 20#include <linux/device.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/irq.h> 22#include <linux/irq.h>
23#include <linux/irqdomain.h>
23#include <linux/gpio.h> 24#include <linux/gpio.h>
24#include <linux/mfd/tps65910.h> 25#include <linux/mfd/tps65910.h>
25 26
26static inline int irq_to_tps65910_irq(struct tps65910 *tps65910,
27 int irq)
28{
29 return (irq - tps65910->irq_base);
30}
31
32/* 27/*
33 * This is a threaded IRQ handler so can access I2C/SPI. Since all 28 * This is a threaded IRQ handler so can access I2C/SPI. Since all
34 * interrupts are clear on read the IRQ line will be reasserted and 29 * interrupts are clear on read the IRQ line will be reasserted and
@@ -76,7 +71,7 @@ static irqreturn_t tps65910_irq(int irq, void *irq_data)
76 if (!(irq_sts & (1 << i))) 71 if (!(irq_sts & (1 << i)))
77 continue; 72 continue;
78 73
79 handle_nested_irq(tps65910->irq_base + i); 74 handle_nested_irq(irq_find_mapping(tps65910->domain, i));
80 } 75 }
81 76
82 /* Write the STS register back to clear IRQs we handled */ 77 /* Write the STS register back to clear IRQs we handled */
@@ -135,14 +130,14 @@ static void tps65910_irq_enable(struct irq_data *data)
135{ 130{
136 struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); 131 struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
137 132
138 tps65910->irq_mask &= ~( 1 << irq_to_tps65910_irq(tps65910, data->irq)); 133 tps65910->irq_mask &= ~(1 << data->hwirq);
139} 134}
140 135
141static void tps65910_irq_disable(struct irq_data *data) 136static void tps65910_irq_disable(struct irq_data *data)
142{ 137{
143 struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); 138 struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data);
144 139
145 tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq)); 140 tps65910->irq_mask |= (1 << data->hwirq);
146} 141}
147 142
148#ifdef CONFIG_PM_SLEEP 143#ifdef CONFIG_PM_SLEEP
@@ -164,10 +159,35 @@ static struct irq_chip tps65910_irq_chip = {
164 .irq_set_wake = tps65910_irq_set_wake, 159 .irq_set_wake = tps65910_irq_set_wake,
165}; 160};
166 161
162static int tps65910_irq_map(struct irq_domain *h, unsigned int virq,
163 irq_hw_number_t hw)
164{
165 struct tps65910 *tps65910 = h->host_data;
166
167 irq_set_chip_data(virq, tps65910);
168 irq_set_chip_and_handler(virq, &tps65910_irq_chip, handle_edge_irq);
169 irq_set_nested_thread(virq, 1);
170
171 /* ARM needs us to explicitly flag the IRQ as valid
172 * and will set them noprobe when we do so. */
173#ifdef CONFIG_ARM
174 set_irq_flags(virq, IRQF_VALID);
175#else
176 irq_set_noprobe(virq);
177#endif
178
179 return 0;
180}
181
182static struct irq_domain_ops tps65910_domain_ops = {
183 .map = tps65910_irq_map,
184 .xlate = irq_domain_xlate_twocell,
185};
186
167int tps65910_irq_init(struct tps65910 *tps65910, int irq, 187int tps65910_irq_init(struct tps65910 *tps65910, int irq,
168 struct tps65910_platform_data *pdata) 188 struct tps65910_platform_data *pdata)
169{ 189{
170 int ret, cur_irq; 190 int ret;
171 int flags = IRQF_ONESHOT; 191 int flags = IRQF_ONESHOT;
172 192
173 if (!irq) { 193 if (!irq) {
@@ -175,17 +195,11 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
175 return -EINVAL; 195 return -EINVAL;
176 } 196 }
177 197
178 if (!pdata || !pdata->irq_base) { 198 if (!pdata) {
179 dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n"); 199 dev_warn(tps65910->dev, "No interrupt support, no pdata\n");
180 return -EINVAL; 200 return -EINVAL;
181 } 201 }
182 202
183 tps65910->irq_mask = 0xFFFFFF;
184
185 mutex_init(&tps65910->irq_lock);
186 tps65910->chip_irq = irq;
187 tps65910->irq_base = pdata->irq_base;
188
189 switch (tps65910_chip_id(tps65910)) { 203 switch (tps65910_chip_id(tps65910)) {
190 case TPS65910: 204 case TPS65910:
191 tps65910->irq_num = TPS65910_NUM_IRQ; 205 tps65910->irq_num = TPS65910_NUM_IRQ;
@@ -195,22 +209,36 @@ int tps65910_irq_init(struct tps65910 *tps65910, int irq,
195 break; 209 break;
196 } 210 }
197 211
198 /* Register with genirq */ 212 if (pdata->irq_base > 0) {
199 for (cur_irq = tps65910->irq_base; 213 pdata->irq_base = irq_alloc_descs(pdata->irq_base, 0,
200 cur_irq < tps65910->irq_num + tps65910->irq_base; 214 tps65910->irq_num, -1);
201 cur_irq++) { 215 if (pdata->irq_base < 0) {
202 irq_set_chip_data(cur_irq, tps65910); 216 dev_warn(tps65910->dev, "Failed to alloc IRQs: %d\n",
203 irq_set_chip_and_handler(cur_irq, &tps65910_irq_chip, 217 pdata->irq_base);
204 handle_edge_irq); 218 return pdata->irq_base;
205 irq_set_nested_thread(cur_irq, 1); 219 }
206 220 }
207 /* ARM needs us to explicitly flag the IRQ as valid 221
208 * and will set them noprobe when we do so. */ 222 tps65910->irq_mask = 0xFFFFFF;
209#ifdef CONFIG_ARM 223
210 set_irq_flags(cur_irq, IRQF_VALID); 224 mutex_init(&tps65910->irq_lock);
211#else 225 tps65910->chip_irq = irq;
212 irq_set_noprobe(cur_irq); 226 tps65910->irq_base = pdata->irq_base;
213#endif 227
228 if (pdata->irq_base > 0)
229 tps65910->domain = irq_domain_add_legacy(tps65910->dev->of_node,
230 tps65910->irq_num,
231 pdata->irq_base,
232 0,
233 &tps65910_domain_ops, tps65910);
234 else
235 tps65910->domain = irq_domain_add_linear(tps65910->dev->of_node,
236 tps65910->irq_num,
237 &tps65910_domain_ops, tps65910);
238
239 if (!tps65910->domain) {
240 dev_err(tps65910->dev, "Failed to create IRQ domain\n");
241 return -ENOMEM;
214 } 242 }
215 243
216 ret = request_threaded_irq(irq, NULL, tps65910_irq, flags, 244 ret = request_threaded_irq(irq, NULL, tps65910_irq, flags,