diff options
Diffstat (limited to 'kernel/irq/generic-chip.c')
| -rw-r--r-- | kernel/irq/generic-chip.c | 314 |
1 files changed, 266 insertions, 48 deletions
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index c89295a8f668..452d6f2ba21d 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <linux/irq.h> | 7 | #include <linux/irq.h> |
| 8 | #include <linux/slab.h> | 8 | #include <linux/slab.h> |
| 9 | #include <linux/export.h> | 9 | #include <linux/export.h> |
| 10 | #include <linux/irqdomain.h> | ||
| 10 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
| 11 | #include <linux/kernel_stat.h> | 12 | #include <linux/kernel_stat.h> |
| 12 | #include <linux/syscore_ops.h> | 13 | #include <linux/syscore_ops.h> |
| @@ -16,11 +17,6 @@ | |||
| 16 | static LIST_HEAD(gc_list); | 17 | static LIST_HEAD(gc_list); |
| 17 | static DEFINE_RAW_SPINLOCK(gc_lock); | 18 | static DEFINE_RAW_SPINLOCK(gc_lock); |
| 18 | 19 | ||
| 19 | static inline struct irq_chip_regs *cur_regs(struct irq_data *d) | ||
| 20 | { | ||
| 21 | return &container_of(d->chip, struct irq_chip_type, chip)->regs; | ||
| 22 | } | ||
| 23 | |||
| 24 | /** | 20 | /** |
| 25 | * irq_gc_noop - NOOP function | 21 | * irq_gc_noop - NOOP function |
| 26 | * @d: irq_data | 22 | * @d: irq_data |
| @@ -39,16 +35,17 @@ void irq_gc_noop(struct irq_data *d) | |||
| 39 | void irq_gc_mask_disable_reg(struct irq_data *d) | 35 | void irq_gc_mask_disable_reg(struct irq_data *d) |
| 40 | { | 36 | { |
| 41 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 37 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 42 | u32 mask = 1 << (d->irq - gc->irq_base); | 38 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 39 | u32 mask = d->mask; | ||
| 43 | 40 | ||
| 44 | irq_gc_lock(gc); | 41 | irq_gc_lock(gc); |
| 45 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->disable); | 42 | irq_reg_writel(mask, gc->reg_base + ct->regs.disable); |
| 46 | gc->mask_cache &= ~mask; | 43 | *ct->mask_cache &= ~mask; |
| 47 | irq_gc_unlock(gc); | 44 | irq_gc_unlock(gc); |
| 48 | } | 45 | } |
| 49 | 46 | ||
| 50 | /** | 47 | /** |
| 51 | * irq_gc_mask_set_mask_bit - Mask chip via setting bit in mask register | 48 | * irq_gc_mask_set_bit - Mask chip via setting bit in mask register |
| 52 | * @d: irq_data | 49 | * @d: irq_data |
| 53 | * | 50 | * |
| 54 | * Chip has a single mask register. Values of this register are cached | 51 | * Chip has a single mask register. Values of this register are cached |
| @@ -57,16 +54,18 @@ void irq_gc_mask_disable_reg(struct irq_data *d) | |||
| 57 | void irq_gc_mask_set_bit(struct irq_data *d) | 54 | void irq_gc_mask_set_bit(struct irq_data *d) |
| 58 | { | 55 | { |
| 59 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 56 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 60 | u32 mask = 1 << (d->irq - gc->irq_base); | 57 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 58 | u32 mask = d->mask; | ||
| 61 | 59 | ||
| 62 | irq_gc_lock(gc); | 60 | irq_gc_lock(gc); |
| 63 | gc->mask_cache |= mask; | 61 | *ct->mask_cache |= mask; |
| 64 | irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask); | 62 | irq_reg_writel(*ct->mask_cache, gc->reg_base + ct->regs.mask); |
| 65 | irq_gc_unlock(gc); | 63 | irq_gc_unlock(gc); |
| 66 | } | 64 | } |
| 65 | EXPORT_SYMBOL_GPL(irq_gc_mask_set_bit); | ||
| 67 | 66 | ||
| 68 | /** | 67 | /** |
| 69 | * irq_gc_mask_set_mask_bit - Mask chip via clearing bit in mask register | 68 | * irq_gc_mask_clr_bit - Mask chip via clearing bit in mask register |
| 70 | * @d: irq_data | 69 | * @d: irq_data |
| 71 | * | 70 | * |
| 72 | * Chip has a single mask register. Values of this register are cached | 71 | * Chip has a single mask register. Values of this register are cached |
| @@ -75,13 +74,15 @@ void irq_gc_mask_set_bit(struct irq_data *d) | |||
| 75 | void irq_gc_mask_clr_bit(struct irq_data *d) | 74 | void irq_gc_mask_clr_bit(struct irq_data *d) |
| 76 | { | 75 | { |
| 77 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 76 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 78 | u32 mask = 1 << (d->irq - gc->irq_base); | 77 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 78 | u32 mask = d->mask; | ||
| 79 | 79 | ||
| 80 | irq_gc_lock(gc); | 80 | irq_gc_lock(gc); |
| 81 | gc->mask_cache &= ~mask; | 81 | *ct->mask_cache &= ~mask; |
| 82 | irq_reg_writel(gc->mask_cache, gc->reg_base + cur_regs(d)->mask); | 82 | irq_reg_writel(*ct->mask_cache, gc->reg_base + ct->regs.mask); |
| 83 | irq_gc_unlock(gc); | 83 | irq_gc_unlock(gc); |
| 84 | } | 84 | } |
| 85 | EXPORT_SYMBOL_GPL(irq_gc_mask_clr_bit); | ||
| 85 | 86 | ||
| 86 | /** | 87 | /** |
| 87 | * irq_gc_unmask_enable_reg - Unmask chip via enable register | 88 | * irq_gc_unmask_enable_reg - Unmask chip via enable register |
| @@ -93,11 +94,12 @@ void irq_gc_mask_clr_bit(struct irq_data *d) | |||
| 93 | void irq_gc_unmask_enable_reg(struct irq_data *d) | 94 | void irq_gc_unmask_enable_reg(struct irq_data *d) |
| 94 | { | 95 | { |
| 95 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 96 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 96 | u32 mask = 1 << (d->irq - gc->irq_base); | 97 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 98 | u32 mask = d->mask; | ||
| 97 | 99 | ||
| 98 | irq_gc_lock(gc); | 100 | irq_gc_lock(gc); |
| 99 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->enable); | 101 | irq_reg_writel(mask, gc->reg_base + ct->regs.enable); |
| 100 | gc->mask_cache |= mask; | 102 | *ct->mask_cache |= mask; |
| 101 | irq_gc_unlock(gc); | 103 | irq_gc_unlock(gc); |
| 102 | } | 104 | } |
| 103 | 105 | ||
| @@ -108,12 +110,14 @@ void irq_gc_unmask_enable_reg(struct irq_data *d) | |||
| 108 | void irq_gc_ack_set_bit(struct irq_data *d) | 110 | void irq_gc_ack_set_bit(struct irq_data *d) |
| 109 | { | 111 | { |
| 110 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 112 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 111 | u32 mask = 1 << (d->irq - gc->irq_base); | 113 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 114 | u32 mask = d->mask; | ||
| 112 | 115 | ||
| 113 | irq_gc_lock(gc); | 116 | irq_gc_lock(gc); |
| 114 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); | 117 | irq_reg_writel(mask, gc->reg_base + ct->regs.ack); |
| 115 | irq_gc_unlock(gc); | 118 | irq_gc_unlock(gc); |
| 116 | } | 119 | } |
| 120 | EXPORT_SYMBOL_GPL(irq_gc_ack_set_bit); | ||
| 117 | 121 | ||
| 118 | /** | 122 | /** |
| 119 | * irq_gc_ack_clr_bit - Ack pending interrupt via clearing bit | 123 | * irq_gc_ack_clr_bit - Ack pending interrupt via clearing bit |
| @@ -122,25 +126,27 @@ void irq_gc_ack_set_bit(struct irq_data *d) | |||
| 122 | void irq_gc_ack_clr_bit(struct irq_data *d) | 126 | void irq_gc_ack_clr_bit(struct irq_data *d) |
| 123 | { | 127 | { |
| 124 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 128 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 125 | u32 mask = ~(1 << (d->irq - gc->irq_base)); | 129 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 130 | u32 mask = ~d->mask; | ||
| 126 | 131 | ||
| 127 | irq_gc_lock(gc); | 132 | irq_gc_lock(gc); |
| 128 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); | 133 | irq_reg_writel(mask, gc->reg_base + ct->regs.ack); |
| 129 | irq_gc_unlock(gc); | 134 | irq_gc_unlock(gc); |
| 130 | } | 135 | } |
| 131 | 136 | ||
| 132 | /** | 137 | /** |
| 133 | * irq_gc_mask_disable_reg_and_ack- Mask and ack pending interrupt | 138 | * irq_gc_mask_disable_reg_and_ack - Mask and ack pending interrupt |
| 134 | * @d: irq_data | 139 | * @d: irq_data |
| 135 | */ | 140 | */ |
| 136 | void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) | 141 | void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) |
| 137 | { | 142 | { |
| 138 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 143 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 139 | u32 mask = 1 << (d->irq - gc->irq_base); | 144 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 145 | u32 mask = d->mask; | ||
| 140 | 146 | ||
| 141 | irq_gc_lock(gc); | 147 | irq_gc_lock(gc); |
| 142 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->mask); | 148 | irq_reg_writel(mask, gc->reg_base + ct->regs.mask); |
| 143 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->ack); | 149 | irq_reg_writel(mask, gc->reg_base + ct->regs.ack); |
| 144 | irq_gc_unlock(gc); | 150 | irq_gc_unlock(gc); |
| 145 | } | 151 | } |
| 146 | 152 | ||
| @@ -151,16 +157,18 @@ void irq_gc_mask_disable_reg_and_ack(struct irq_data *d) | |||
| 151 | void irq_gc_eoi(struct irq_data *d) | 157 | void irq_gc_eoi(struct irq_data *d) |
| 152 | { | 158 | { |
| 153 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 159 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 154 | u32 mask = 1 << (d->irq - gc->irq_base); | 160 | struct irq_chip_type *ct = irq_data_get_chip_type(d); |
| 161 | u32 mask = d->mask; | ||
| 155 | 162 | ||
| 156 | irq_gc_lock(gc); | 163 | irq_gc_lock(gc); |
| 157 | irq_reg_writel(mask, gc->reg_base + cur_regs(d)->eoi); | 164 | irq_reg_writel(mask, gc->reg_base + ct->regs.eoi); |
| 158 | irq_gc_unlock(gc); | 165 | irq_gc_unlock(gc); |
| 159 | } | 166 | } |
| 160 | 167 | ||
| 161 | /** | 168 | /** |
| 162 | * irq_gc_set_wake - Set/clr wake bit for an interrupt | 169 | * irq_gc_set_wake - Set/clr wake bit for an interrupt |
| 163 | * @d: irq_data | 170 | * @d: irq_data |
| 171 | * @on: Indicates whether the wake bit should be set or cleared | ||
| 164 | * | 172 | * |
| 165 | * For chips where the wake from suspend functionality is not | 173 | * For chips where the wake from suspend functionality is not |
| 166 | * configured in a separate register and the wakeup active state is | 174 | * configured in a separate register and the wakeup active state is |
| @@ -169,7 +177,7 @@ void irq_gc_eoi(struct irq_data *d) | |||
| 169 | int irq_gc_set_wake(struct irq_data *d, unsigned int on) | 177 | int irq_gc_set_wake(struct irq_data *d, unsigned int on) |
| 170 | { | 178 | { |
| 171 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); | 179 | struct irq_chip_generic *gc = irq_data_get_irq_chip_data(d); |
| 172 | u32 mask = 1 << (d->irq - gc->irq_base); | 180 | u32 mask = d->mask; |
| 173 | 181 | ||
| 174 | if (!(mask & gc->wake_enabled)) | 182 | if (!(mask & gc->wake_enabled)) |
| 175 | return -EINVAL; | 183 | return -EINVAL; |
| @@ -183,6 +191,19 @@ int irq_gc_set_wake(struct irq_data *d, unsigned int on) | |||
| 183 | return 0; | 191 | return 0; |
| 184 | } | 192 | } |
| 185 | 193 | ||
| 194 | static void | ||
| 195 | irq_init_generic_chip(struct irq_chip_generic *gc, const char *name, | ||
| 196 | int num_ct, unsigned int irq_base, | ||
| 197 | void __iomem *reg_base, irq_flow_handler_t handler) | ||
| 198 | { | ||
| 199 | raw_spin_lock_init(&gc->lock); | ||
| 200 | gc->num_ct = num_ct; | ||
| 201 | gc->irq_base = irq_base; | ||
| 202 | gc->reg_base = reg_base; | ||
| 203 | gc->chip_types->chip.name = name; | ||
| 204 | gc->chip_types->handler = handler; | ||
| 205 | } | ||
| 206 | |||
| 186 | /** | 207 | /** |
| 187 | * irq_alloc_generic_chip - Allocate a generic chip and initialize it | 208 | * irq_alloc_generic_chip - Allocate a generic chip and initialize it |
| 188 | * @name: Name of the irq chip | 209 | * @name: Name of the irq chip |
| @@ -203,23 +224,183 @@ irq_alloc_generic_chip(const char *name, int num_ct, unsigned int irq_base, | |||
| 203 | 224 | ||
| 204 | gc = kzalloc(sz, GFP_KERNEL); | 225 | gc = kzalloc(sz, GFP_KERNEL); |
| 205 | if (gc) { | 226 | if (gc) { |
| 206 | raw_spin_lock_init(&gc->lock); | 227 | irq_init_generic_chip(gc, name, num_ct, irq_base, reg_base, |
| 207 | gc->num_ct = num_ct; | 228 | handler); |
| 208 | gc->irq_base = irq_base; | ||
| 209 | gc->reg_base = reg_base; | ||
| 210 | gc->chip_types->chip.name = name; | ||
| 211 | gc->chip_types->handler = handler; | ||
| 212 | } | 229 | } |
| 213 | return gc; | 230 | return gc; |
| 214 | } | 231 | } |
| 215 | EXPORT_SYMBOL_GPL(irq_alloc_generic_chip); | 232 | EXPORT_SYMBOL_GPL(irq_alloc_generic_chip); |
| 216 | 233 | ||
| 234 | static void | ||
| 235 | irq_gc_init_mask_cache(struct irq_chip_generic *gc, enum irq_gc_flags flags) | ||
| 236 | { | ||
| 237 | struct irq_chip_type *ct = gc->chip_types; | ||
| 238 | u32 *mskptr = &gc->mask_cache, mskreg = ct->regs.mask; | ||
| 239 | int i; | ||
| 240 | |||
| 241 | for (i = 0; i < gc->num_ct; i++) { | ||
| 242 | if (flags & IRQ_GC_MASK_CACHE_PER_TYPE) { | ||
| 243 | mskptr = &ct[i].mask_cache_priv; | ||
| 244 | mskreg = ct[i].regs.mask; | ||
| 245 | } | ||
| 246 | ct[i].mask_cache = mskptr; | ||
| 247 | if (flags & IRQ_GC_INIT_MASK_CACHE) | ||
| 248 | *mskptr = irq_reg_readl(gc->reg_base + mskreg); | ||
| 249 | } | ||
| 250 | } | ||
| 251 | |||
| 252 | /** | ||
| 253 | * irq_alloc_domain_generic_chip - Allocate generic chips for an irq domain | ||
| 254 | * @d: irq domain for which to allocate chips | ||
| 255 | * @irqs_per_chip: Number of interrupts each chip handles | ||
| 256 | * @num_ct: Number of irq_chip_type instances associated with this | ||
| 257 | * @name: Name of the irq chip | ||
| 258 | * @handler: Default flow handler associated with these chips | ||
| 259 | * @clr: IRQ_* bits to clear in the mapping function | ||
| 260 | * @set: IRQ_* bits to set in the mapping function | ||
| 261 | * @gcflags: Generic chip specific setup flags | ||
| 262 | */ | ||
| 263 | int irq_alloc_domain_generic_chips(struct irq_domain *d, int irqs_per_chip, | ||
| 264 | int num_ct, const char *name, | ||
| 265 | irq_flow_handler_t handler, | ||
| 266 | unsigned int clr, unsigned int set, | ||
| 267 | enum irq_gc_flags gcflags) | ||
| 268 | { | ||
| 269 | struct irq_domain_chip_generic *dgc; | ||
| 270 | struct irq_chip_generic *gc; | ||
| 271 | int numchips, sz, i; | ||
| 272 | unsigned long flags; | ||
| 273 | void *tmp; | ||
| 274 | |||
| 275 | if (d->gc) | ||
| 276 | return -EBUSY; | ||
| 277 | |||
| 278 | numchips = DIV_ROUND_UP(d->revmap_size, irqs_per_chip); | ||
| 279 | if (!numchips) | ||
| 280 | return -EINVAL; | ||
| 281 | |||
| 282 | /* Allocate a pointer, generic chip and chiptypes for each chip */ | ||
| 283 | sz = sizeof(*dgc) + numchips * sizeof(gc); | ||
| 284 | sz += numchips * (sizeof(*gc) + num_ct * sizeof(struct irq_chip_type)); | ||
| 285 | |||
| 286 | tmp = dgc = kzalloc(sz, GFP_KERNEL); | ||
| 287 | if (!dgc) | ||
| 288 | return -ENOMEM; | ||
| 289 | dgc->irqs_per_chip = irqs_per_chip; | ||
| 290 | dgc->num_chips = numchips; | ||
| 291 | dgc->irq_flags_to_set = set; | ||
| 292 | dgc->irq_flags_to_clear = clr; | ||
| 293 | dgc->gc_flags = gcflags; | ||
| 294 | d->gc = dgc; | ||
| 295 | |||
| 296 | /* Calc pointer to the first generic chip */ | ||
| 297 | tmp += sizeof(*dgc) + numchips * sizeof(gc); | ||
| 298 | for (i = 0; i < numchips; i++) { | ||
| 299 | /* Store the pointer to the generic chip */ | ||
| 300 | dgc->gc[i] = gc = tmp; | ||
| 301 | irq_init_generic_chip(gc, name, num_ct, i * irqs_per_chip, | ||
| 302 | NULL, handler); | ||
| 303 | gc->domain = d; | ||
| 304 | raw_spin_lock_irqsave(&gc_lock, flags); | ||
| 305 | list_add_tail(&gc->list, &gc_list); | ||
| 306 | raw_spin_unlock_irqrestore(&gc_lock, flags); | ||
| 307 | /* Calc pointer to the next generic chip */ | ||
| 308 | tmp += sizeof(*gc) + num_ct * sizeof(struct irq_chip_type); | ||
| 309 | } | ||
| 310 | d->name = name; | ||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | EXPORT_SYMBOL_GPL(irq_alloc_domain_generic_chips); | ||
| 314 | |||
| 315 | /** | ||
| 316 | * irq_get_domain_generic_chip - Get a pointer to the generic chip of a hw_irq | ||
| 317 | * @d: irq domain pointer | ||
| 318 | * @hw_irq: Hardware interrupt number | ||
| 319 | */ | ||
| 320 | struct irq_chip_generic * | ||
| 321 | irq_get_domain_generic_chip(struct irq_domain *d, unsigned int hw_irq) | ||
| 322 | { | ||
| 323 | struct irq_domain_chip_generic *dgc = d->gc; | ||
| 324 | int idx; | ||
| 325 | |||
| 326 | if (!dgc) | ||
| 327 | return NULL; | ||
| 328 | idx = hw_irq / dgc->irqs_per_chip; | ||
| 329 | if (idx >= dgc->num_chips) | ||
| 330 | return NULL; | ||
| 331 | return dgc->gc[idx]; | ||
| 332 | } | ||
| 333 | EXPORT_SYMBOL_GPL(irq_get_domain_generic_chip); | ||
| 334 | |||
| 217 | /* | 335 | /* |
| 218 | * Separate lockdep class for interrupt chip which can nest irq_desc | 336 | * Separate lockdep class for interrupt chip which can nest irq_desc |
| 219 | * lock. | 337 | * lock. |
| 220 | */ | 338 | */ |
| 221 | static struct lock_class_key irq_nested_lock_class; | 339 | static struct lock_class_key irq_nested_lock_class; |
| 222 | 340 | ||
| 341 | /* | ||
| 342 | * irq_map_generic_chip - Map a generic chip for an irq domain | ||
| 343 | */ | ||
| 344 | static int irq_map_generic_chip(struct irq_domain *d, unsigned int virq, | ||
| 345 | irq_hw_number_t hw_irq) | ||
| 346 | { | ||
| 347 | struct irq_data *data = irq_get_irq_data(virq); | ||
| 348 | struct irq_domain_chip_generic *dgc = d->gc; | ||
| 349 | struct irq_chip_generic *gc; | ||
| 350 | struct irq_chip_type *ct; | ||
| 351 | struct irq_chip *chip; | ||
| 352 | unsigned long flags; | ||
| 353 | int idx; | ||
| 354 | |||
| 355 | if (!d->gc) | ||
| 356 | return -ENODEV; | ||
| 357 | |||
| 358 | idx = hw_irq / dgc->irqs_per_chip; | ||
| 359 | if (idx >= dgc->num_chips) | ||
| 360 | return -EINVAL; | ||
| 361 | gc = dgc->gc[idx]; | ||
| 362 | |||
| 363 | idx = hw_irq % dgc->irqs_per_chip; | ||
| 364 | |||
| 365 | if (test_bit(idx, &gc->unused)) | ||
| 366 | return -ENOTSUPP; | ||
| 367 | |||
| 368 | if (test_bit(idx, &gc->installed)) | ||
| 369 | return -EBUSY; | ||
| 370 | |||
| 371 | ct = gc->chip_types; | ||
| 372 | chip = &ct->chip; | ||
| 373 | |||
| 374 | /* We only init the cache for the first mapping of a generic chip */ | ||
| 375 | if (!gc->installed) { | ||
| 376 | raw_spin_lock_irqsave(&gc->lock, flags); | ||
| 377 | irq_gc_init_mask_cache(gc, dgc->gc_flags); | ||
| 378 | raw_spin_unlock_irqrestore(&gc->lock, flags); | ||
| 379 | } | ||
| 380 | |||
| 381 | /* Mark the interrupt as installed */ | ||
| 382 | set_bit(idx, &gc->installed); | ||
| 383 | |||
| 384 | if (dgc->gc_flags & IRQ_GC_INIT_NESTED_LOCK) | ||
| 385 | irq_set_lockdep_class(virq, &irq_nested_lock_class); | ||
| 386 | |||
| 387 | if (chip->irq_calc_mask) | ||
| 388 | chip->irq_calc_mask(data); | ||
| 389 | else | ||
| 390 | data->mask = 1 << idx; | ||
| 391 | |||
| 392 | irq_set_chip_and_handler(virq, chip, ct->handler); | ||
| 393 | irq_set_chip_data(virq, gc); | ||
| 394 | irq_modify_status(virq, dgc->irq_flags_to_clear, dgc->irq_flags_to_set); | ||
| 395 | return 0; | ||
| 396 | } | ||
| 397 | |||
| 398 | struct irq_domain_ops irq_generic_chip_ops = { | ||
| 399 | .map = irq_map_generic_chip, | ||
| 400 | .xlate = irq_domain_xlate_onetwocell, | ||
| 401 | }; | ||
| 402 | EXPORT_SYMBOL_GPL(irq_generic_chip_ops); | ||
| 403 | |||
| 223 | /** | 404 | /** |
| 224 | * irq_setup_generic_chip - Setup a range of interrupts with a generic chip | 405 | * irq_setup_generic_chip - Setup a range of interrupts with a generic chip |
| 225 | * @gc: Generic irq chip holding all data | 406 | * @gc: Generic irq chip holding all data |
| @@ -237,15 +418,14 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
| 237 | unsigned int set) | 418 | unsigned int set) |
| 238 | { | 419 | { |
| 239 | struct irq_chip_type *ct = gc->chip_types; | 420 | struct irq_chip_type *ct = gc->chip_types; |
| 421 | struct irq_chip *chip = &ct->chip; | ||
| 240 | unsigned int i; | 422 | unsigned int i; |
| 241 | 423 | ||
| 242 | raw_spin_lock(&gc_lock); | 424 | raw_spin_lock(&gc_lock); |
| 243 | list_add_tail(&gc->list, &gc_list); | 425 | list_add_tail(&gc->list, &gc_list); |
| 244 | raw_spin_unlock(&gc_lock); | 426 | raw_spin_unlock(&gc_lock); |
| 245 | 427 | ||
| 246 | /* Init mask cache ? */ | 428 | irq_gc_init_mask_cache(gc, flags); |
| 247 | if (flags & IRQ_GC_INIT_MASK_CACHE) | ||
| 248 | gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask); | ||
| 249 | 429 | ||
| 250 | for (i = gc->irq_base; msk; msk >>= 1, i++) { | 430 | for (i = gc->irq_base; msk; msk >>= 1, i++) { |
| 251 | if (!(msk & 0x01)) | 431 | if (!(msk & 0x01)) |
| @@ -254,7 +434,15 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
| 254 | if (flags & IRQ_GC_INIT_NESTED_LOCK) | 434 | if (flags & IRQ_GC_INIT_NESTED_LOCK) |
| 255 | irq_set_lockdep_class(i, &irq_nested_lock_class); | 435 | irq_set_lockdep_class(i, &irq_nested_lock_class); |
| 256 | 436 | ||
| 257 | irq_set_chip_and_handler(i, &ct->chip, ct->handler); | 437 | if (!(flags & IRQ_GC_NO_MASK)) { |
| 438 | struct irq_data *d = irq_get_irq_data(i); | ||
| 439 | |||
| 440 | if (chip->irq_calc_mask) | ||
| 441 | chip->irq_calc_mask(d); | ||
| 442 | else | ||
| 443 | d->mask = 1 << (i - gc->irq_base); | ||
| 444 | } | ||
| 445 | irq_set_chip_and_handler(i, chip, ct->handler); | ||
| 258 | irq_set_chip_data(i, gc); | 446 | irq_set_chip_data(i, gc); |
| 259 | irq_modify_status(i, clr, set); | 447 | irq_modify_status(i, clr, set); |
| 260 | } | 448 | } |
| @@ -265,7 +453,7 @@ EXPORT_SYMBOL_GPL(irq_setup_generic_chip); | |||
| 265 | /** | 453 | /** |
| 266 | * irq_setup_alt_chip - Switch to alternative chip | 454 | * irq_setup_alt_chip - Switch to alternative chip |
| 267 | * @d: irq_data for this interrupt | 455 | * @d: irq_data for this interrupt |
| 268 | * @type Flow type to be initialized | 456 | * @type: Flow type to be initialized |
| 269 | * | 457 | * |
| 270 | * Only to be called from chip->irq_set_type() callbacks. | 458 | * Only to be called from chip->irq_set_type() callbacks. |
| 271 | */ | 459 | */ |
| @@ -317,6 +505,24 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
| 317 | } | 505 | } |
| 318 | EXPORT_SYMBOL_GPL(irq_remove_generic_chip); | 506 | EXPORT_SYMBOL_GPL(irq_remove_generic_chip); |
| 319 | 507 | ||
| 508 | static struct irq_data *irq_gc_get_irq_data(struct irq_chip_generic *gc) | ||
| 509 | { | ||
| 510 | unsigned int virq; | ||
| 511 | |||
| 512 | if (!gc->domain) | ||
| 513 | return irq_get_irq_data(gc->irq_base); | ||
| 514 | |||
| 515 | /* | ||
| 516 | * We don't know which of the irqs has been actually | ||
| 517 | * installed. Use the first one. | ||
| 518 | */ | ||
| 519 | if (!gc->installed) | ||
| 520 | return NULL; | ||
| 521 | |||
| 522 | virq = irq_find_mapping(gc->domain, gc->irq_base + __ffs(gc->installed)); | ||
| 523 | return virq ? irq_get_irq_data(virq) : NULL; | ||
| 524 | } | ||
| 525 | |||
| 320 | #ifdef CONFIG_PM | 526 | #ifdef CONFIG_PM |
| 321 | static int irq_gc_suspend(void) | 527 | static int irq_gc_suspend(void) |
| 322 | { | 528 | { |
| @@ -325,8 +531,12 @@ static int irq_gc_suspend(void) | |||
| 325 | list_for_each_entry(gc, &gc_list, list) { | 531 | list_for_each_entry(gc, &gc_list, list) { |
| 326 | struct irq_chip_type *ct = gc->chip_types; | 532 | struct irq_chip_type *ct = gc->chip_types; |
| 327 | 533 | ||
| 328 | if (ct->chip.irq_suspend) | 534 | if (ct->chip.irq_suspend) { |
| 329 | ct->chip.irq_suspend(irq_get_irq_data(gc->irq_base)); | 535 | struct irq_data *data = irq_gc_get_irq_data(gc); |
| 536 | |||
| 537 | if (data) | ||
| 538 | ct->chip.irq_suspend(data); | ||
| 539 | } | ||
| 330 | } | 540 | } |
| 331 | return 0; | 541 | return 0; |
| 332 | } | 542 | } |
| @@ -338,8 +548,12 @@ static void irq_gc_resume(void) | |||
| 338 | list_for_each_entry(gc, &gc_list, list) { | 548 | list_for_each_entry(gc, &gc_list, list) { |
| 339 | struct irq_chip_type *ct = gc->chip_types; | 549 | struct irq_chip_type *ct = gc->chip_types; |
| 340 | 550 | ||
| 341 | if (ct->chip.irq_resume) | 551 | if (ct->chip.irq_resume) { |
| 342 | ct->chip.irq_resume(irq_get_irq_data(gc->irq_base)); | 552 | struct irq_data *data = irq_gc_get_irq_data(gc); |
| 553 | |||
| 554 | if (data) | ||
| 555 | ct->chip.irq_resume(data); | ||
| 556 | } | ||
| 343 | } | 557 | } |
| 344 | } | 558 | } |
| 345 | #else | 559 | #else |
| @@ -354,8 +568,12 @@ static void irq_gc_shutdown(void) | |||
| 354 | list_for_each_entry(gc, &gc_list, list) { | 568 | list_for_each_entry(gc, &gc_list, list) { |
| 355 | struct irq_chip_type *ct = gc->chip_types; | 569 | struct irq_chip_type *ct = gc->chip_types; |
| 356 | 570 | ||
| 357 | if (ct->chip.irq_pm_shutdown) | 571 | if (ct->chip.irq_pm_shutdown) { |
| 358 | ct->chip.irq_pm_shutdown(irq_get_irq_data(gc->irq_base)); | 572 | struct irq_data *data = irq_gc_get_irq_data(gc); |
| 573 | |||
| 574 | if (data) | ||
| 575 | ct->chip.irq_pm_shutdown(data); | ||
| 576 | } | ||
| 359 | } | 577 | } |
| 360 | } | 578 | } |
| 361 | 579 | ||
