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

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>

authored by

Rhyland Klein and committed by
Samuel Ortiz
21f7541d b09530ef

+63 -33
+1
drivers/mfd/Kconfig
··· 190 190 depends on I2C=y && GPIOLIB 191 191 select MFD_CORE 192 192 select REGMAP_I2C 193 + select IRQ_DOMAIN 193 194 help 194 195 if you say yes here you get support for the TPS65910 series of 195 196 Power Management chips.
+61 -33
drivers/mfd/tps65910-irq.c
··· 20 20 #include <linux/device.h> 21 21 #include <linux/interrupt.h> 22 22 #include <linux/irq.h> 23 + #include <linux/irqdomain.h> 23 24 #include <linux/gpio.h> 24 25 #include <linux/mfd/tps65910.h> 25 - 26 - static inline int irq_to_tps65910_irq(struct tps65910 *tps65910, 27 - int irq) 28 - { 29 - return (irq - tps65910->irq_base); 30 - } 31 26 32 27 /* 33 28 * This is a threaded IRQ handler so can access I2C/SPI. Since all ··· 71 76 if (!(irq_sts & (1 << i))) 72 77 continue; 73 78 74 - handle_nested_irq(tps65910->irq_base + i); 79 + handle_nested_irq(irq_find_mapping(tps65910->domain, i)); 75 80 } 76 81 77 82 /* Write the STS register back to clear IRQs we handled */ ··· 130 135 { 131 136 struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); 132 137 133 - tps65910->irq_mask &= ~( 1 << irq_to_tps65910_irq(tps65910, data->irq)); 138 + tps65910->irq_mask &= ~(1 << data->hwirq); 134 139 } 135 140 136 141 static void tps65910_irq_disable(struct irq_data *data) 137 142 { 138 143 struct tps65910 *tps65910 = irq_data_get_irq_chip_data(data); 139 144 140 - tps65910->irq_mask |= ( 1 << irq_to_tps65910_irq(tps65910, data->irq)); 145 + tps65910->irq_mask |= (1 << data->hwirq); 141 146 } 142 147 143 148 #ifdef CONFIG_PM_SLEEP ··· 159 164 .irq_set_wake = tps65910_irq_set_wake, 160 165 }; 161 166 167 + static int tps65910_irq_map(struct irq_domain *h, unsigned int virq, 168 + irq_hw_number_t hw) 169 + { 170 + struct tps65910 *tps65910 = h->host_data; 171 + 172 + irq_set_chip_data(virq, tps65910); 173 + irq_set_chip_and_handler(virq, &tps65910_irq_chip, handle_edge_irq); 174 + irq_set_nested_thread(virq, 1); 175 + 176 + /* ARM needs us to explicitly flag the IRQ as valid 177 + * and will set them noprobe when we do so. */ 178 + #ifdef CONFIG_ARM 179 + set_irq_flags(virq, IRQF_VALID); 180 + #else 181 + irq_set_noprobe(virq); 182 + #endif 183 + 184 + return 0; 185 + } 186 + 187 + static struct irq_domain_ops tps65910_domain_ops = { 188 + .map = tps65910_irq_map, 189 + .xlate = irq_domain_xlate_twocell, 190 + }; 191 + 162 192 int tps65910_irq_init(struct tps65910 *tps65910, int irq, 163 193 struct tps65910_platform_data *pdata) 164 194 { 165 - int ret, cur_irq; 195 + int ret; 166 196 int flags = IRQF_ONESHOT; 167 197 168 198 if (!irq) { ··· 195 175 return -EINVAL; 196 176 } 197 177 198 - if (!pdata || !pdata->irq_base) { 199 - dev_warn(tps65910->dev, "No interrupt support, no IRQ base\n"); 178 + if (!pdata) { 179 + dev_warn(tps65910->dev, "No interrupt support, no pdata\n"); 200 180 return -EINVAL; 201 181 } 202 - 203 - tps65910->irq_mask = 0xFFFFFF; 204 - 205 - mutex_init(&tps65910->irq_lock); 206 - tps65910->chip_irq = irq; 207 - tps65910->irq_base = pdata->irq_base; 208 182 209 183 switch (tps65910_chip_id(tps65910)) { 210 184 case TPS65910: ··· 209 195 break; 210 196 } 211 197 212 - /* Register with genirq */ 213 - for (cur_irq = tps65910->irq_base; 214 - cur_irq < tps65910->irq_num + tps65910->irq_base; 215 - cur_irq++) { 216 - irq_set_chip_data(cur_irq, tps65910); 217 - irq_set_chip_and_handler(cur_irq, &tps65910_irq_chip, 218 - handle_edge_irq); 219 - irq_set_nested_thread(cur_irq, 1); 198 + if (pdata->irq_base > 0) { 199 + pdata->irq_base = irq_alloc_descs(pdata->irq_base, 0, 200 + tps65910->irq_num, -1); 201 + if (pdata->irq_base < 0) { 202 + dev_warn(tps65910->dev, "Failed to alloc IRQs: %d\n", 203 + pdata->irq_base); 204 + return pdata->irq_base; 205 + } 206 + } 220 207 221 - /* ARM needs us to explicitly flag the IRQ as valid 222 - * and will set them noprobe when we do so. */ 223 - #ifdef CONFIG_ARM 224 - set_irq_flags(cur_irq, IRQF_VALID); 225 - #else 226 - irq_set_noprobe(cur_irq); 227 - #endif 208 + tps65910->irq_mask = 0xFFFFFF; 209 + 210 + mutex_init(&tps65910->irq_lock); 211 + tps65910->chip_irq = irq; 212 + tps65910->irq_base = pdata->irq_base; 213 + 214 + if (pdata->irq_base > 0) 215 + tps65910->domain = irq_domain_add_legacy(tps65910->dev->of_node, 216 + tps65910->irq_num, 217 + pdata->irq_base, 218 + 0, 219 + &tps65910_domain_ops, tps65910); 220 + else 221 + tps65910->domain = irq_domain_add_linear(tps65910->dev->of_node, 222 + tps65910->irq_num, 223 + &tps65910_domain_ops, tps65910); 224 + 225 + if (!tps65910->domain) { 226 + dev_err(tps65910->dev, "Failed to create IRQ domain\n"); 227 + return -ENOMEM; 228 228 } 229 229 230 230 ret = request_threaded_irq(irq, NULL, tps65910_irq, flags,
+1
include/linux/mfd/tps65910.h
··· 836 836 int irq_base; 837 837 int irq_num; 838 838 u32 irq_mask; 839 + struct irq_domain *domain; 839 840 }; 840 841 841 842 struct tps65910_platform_data {