int wcd9xxx_irq_init(struct wcd9xxx_core_resource *wcd9xxx_res) { int i, ret; u8 irq_level[wcd9xxx_res->num_irq_regs]; mutex_init(&wcd9xxx_res->irq_lock); mutex_init(&wcd9xxx_res->nested_irq_lock); wcd9xxx_res->irq = wcd9xxx_irq_get_upstream_irq(wcd9xxx_res); if (!wcd9xxx_res->irq) { pr_warn("%s: irq driver is not yet initialized\n", __func__); mutex_destroy(&wcd9xxx_res->irq_lock); mutex_destroy(&wcd9xxx_res->nested_irq_lock); return -EPROBE_DEFER; } pr_debug("%s: probed irq %d\n", __func__, wcd9xxx_res->irq); ret = wcd9xxx_irq_setup_downstream_irq(wcd9xxx_res); if (ret) { pr_err("%s: Failed to setup downstream IRQ\n", __func__); wcd9xxx_irq_put_upstream_irq(wcd9xxx_res); mutex_destroy(&wcd9xxx_res->irq_lock); mutex_destroy(&wcd9xxx_res->nested_irq_lock); return ret; } wcd9xxx_res->irq_level_high[0] = true; memset(irq_level, 0, wcd9xxx_res->num_irq_regs); for (i = 0; i < wcd9xxx_res->num_irqs; i++) { wcd9xxx_res->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i); wcd9xxx_res->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i); irq_level[BIT_BYTE(i)] |= wcd9xxx_res->irq_level_high[i] << (i % BITS_PER_BYTE); } if (!wcd9xxx_res->codec_reg_write) { dev_err(wcd9xxx_res->dev, "%s: Codec Register write callback not defined\n", __func__); ret = -EINVAL; goto fail_irq_init; } for (i = 0; i < wcd9xxx_res->num_irq_regs; i++) { wcd9xxx_res->codec_reg_write(wcd9xxx_res, WCD9XXX_A_INTR_LEVEL0 + i, irq_level[i]); wcd9xxx_res->codec_reg_write(wcd9xxx_res, WCD9XXX_A_INTR_MASK0 + i, wcd9xxx_res->irq_masks_cur[i]); } ret = request_threaded_irq(wcd9xxx_res->irq, NULL, wcd9xxx_irq_thread, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "wcd9xxx", wcd9xxx_res); if (ret != 0) dev_err(wcd9xxx_res->dev, "Failed to request IRQ %d: %d\n", wcd9xxx_res->irq, ret); else { ret = enable_irq_wake(wcd9xxx_res->irq); if (ret) dev_err(wcd9xxx_res->dev, "Failed to set wake interrupt on IRQ %d: %d\n", wcd9xxx_res->irq, ret); if (ret) free_irq(wcd9xxx_res->irq, wcd9xxx_res); } if (ret) goto fail_irq_init; return ret; fail_irq_init: dev_err(wcd9xxx_res->dev, "%s: Failed to init wcd9xxx irq\n", __func__); wcd9xxx_irq_put_upstream_irq(wcd9xxx_res); mutex_destroy(&wcd9xxx_res->irq_lock); mutex_destroy(&wcd9xxx_res->nested_irq_lock); return ret; }
int wcd9xxx_irq_init(struct wcd9xxx *wcd9xxx) { int i, ret; u8 irq_level[wcd9xxx_num_irq_regs(wcd9xxx)]; mutex_init(&wcd9xxx->irq_lock); mutex_init(&wcd9xxx->nested_irq_lock); wcd9xxx->irq = wcd9xxx_irq_get_upstream_irq(wcd9xxx); if (!wcd9xxx->irq) { pr_warn("%s: irq driver is not yet initialized\n", __func__); mutex_destroy(&wcd9xxx->irq_lock); mutex_destroy(&wcd9xxx->nested_irq_lock); return -EPROBE_DEFER; } pr_debug("%s: probed irq %d\n", __func__, wcd9xxx->irq); /* Setup downstream IRQs */ ret = wcd9xxx_irq_setup_downstream_irq(wcd9xxx); if (ret) { pr_err("%s: Failed to setup downstream IRQ\n", __func__); wcd9xxx_irq_put_upstream_irq(wcd9xxx); mutex_destroy(&wcd9xxx->irq_lock); mutex_destroy(&wcd9xxx->nested_irq_lock); return ret; } /* All other wcd9xxx interrupts are edge triggered */ wcd9xxx->irq_level_high[0] = true; /* mask all the interrupts */ memset(irq_level, 0, wcd9xxx_num_irq_regs(wcd9xxx)); for (i = 0; i < wcd9xxx->num_irqs; i++) { wcd9xxx->irq_masks_cur[BIT_BYTE(i)] |= BYTE_BIT_MASK(i); wcd9xxx->irq_masks_cache[BIT_BYTE(i)] |= BYTE_BIT_MASK(i); irq_level[BIT_BYTE(i)] |= wcd9xxx->irq_level_high[i] << (i % BITS_PER_BYTE); } for (i = 0; i < wcd9xxx_num_irq_regs(wcd9xxx); i++) { /* Initialize interrupt mask and level registers */ wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_LEVEL0 + i, irq_level[i]); wcd9xxx_reg_write(wcd9xxx, WCD9XXX_A_INTR_MASK0 + i, wcd9xxx->irq_masks_cur[i]); } ret = request_threaded_irq(wcd9xxx->irq, NULL, wcd9xxx_irq_thread, IRQF_TRIGGER_HIGH | IRQF_ONESHOT, "wcd9xxx", wcd9xxx); if (ret != 0) dev_err(wcd9xxx->dev, "Failed to request IRQ %d: %d\n", wcd9xxx->irq, ret); else { ret = enable_irq_wake(wcd9xxx->irq); if (ret == 0) { ret = device_init_wakeup(wcd9xxx->dev, 1); if (ret) { dev_err(wcd9xxx->dev, "Failed to init device" "wakeup : %d\n", ret); disable_irq_wake(wcd9xxx->irq); } } else dev_err(wcd9xxx->dev, "Failed to set wake interrupt on" " IRQ %d: %d\n", wcd9xxx->irq, ret); if (ret) free_irq(wcd9xxx->irq, wcd9xxx); } if (ret) { pr_err("%s: Failed to init wcd9xxx irq\n", __func__); wcd9xxx_irq_put_upstream_irq(wcd9xxx); mutex_destroy(&wcd9xxx->irq_lock); mutex_destroy(&wcd9xxx->nested_irq_lock); } return ret; }