^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Interrupt support for Cirrus Logic Madera codecs
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Copyright (C) 2015-2018 Cirrus Logic, Inc. and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Cirrus Logic International Semiconductor Ltd.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/irqdomain.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/pm_runtime.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include <linux/regmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <linux/of.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/irqchip/irq-madera.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/mfd/madera/core.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/mfd/madera/pdata.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/mfd/madera/registers.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define MADERA_IRQ(_irq, _reg) \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) [MADERA_IRQ_ ## _irq] = { \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) .reg_offset = (_reg) - MADERA_IRQ1_STATUS_2, \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) .mask = MADERA_ ## _irq ## _EINT1 \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* Mappings are the same for all Madera codecs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static const struct regmap_irq madera_irqs[MADERA_NUM_IRQ] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) MADERA_IRQ(FLL1_LOCK, MADERA_IRQ1_STATUS_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) MADERA_IRQ(FLL2_LOCK, MADERA_IRQ1_STATUS_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) MADERA_IRQ(FLL3_LOCK, MADERA_IRQ1_STATUS_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) MADERA_IRQ(FLLAO_LOCK, MADERA_IRQ1_STATUS_2),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) MADERA_IRQ(MICDET1, MADERA_IRQ1_STATUS_6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) MADERA_IRQ(MICDET2, MADERA_IRQ1_STATUS_6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) MADERA_IRQ(HPDET, MADERA_IRQ1_STATUS_6),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) MADERA_IRQ(MICD_CLAMP_RISE, MADERA_IRQ1_STATUS_7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) MADERA_IRQ(MICD_CLAMP_FALL, MADERA_IRQ1_STATUS_7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) MADERA_IRQ(JD1_RISE, MADERA_IRQ1_STATUS_7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) MADERA_IRQ(JD1_FALL, MADERA_IRQ1_STATUS_7),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) MADERA_IRQ(ASRC2_IN1_LOCK, MADERA_IRQ1_STATUS_9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) MADERA_IRQ(ASRC2_IN2_LOCK, MADERA_IRQ1_STATUS_9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) MADERA_IRQ(ASRC1_IN1_LOCK, MADERA_IRQ1_STATUS_9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) MADERA_IRQ(ASRC1_IN2_LOCK, MADERA_IRQ1_STATUS_9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) MADERA_IRQ(DRC2_SIG_DET, MADERA_IRQ1_STATUS_9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) MADERA_IRQ(DRC1_SIG_DET, MADERA_IRQ1_STATUS_9),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) MADERA_IRQ(DSP_IRQ1, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) MADERA_IRQ(DSP_IRQ2, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) MADERA_IRQ(DSP_IRQ3, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) MADERA_IRQ(DSP_IRQ4, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) MADERA_IRQ(DSP_IRQ5, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) MADERA_IRQ(DSP_IRQ6, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) MADERA_IRQ(DSP_IRQ7, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) MADERA_IRQ(DSP_IRQ8, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) MADERA_IRQ(DSP_IRQ9, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) MADERA_IRQ(DSP_IRQ10, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) MADERA_IRQ(DSP_IRQ11, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) MADERA_IRQ(DSP_IRQ12, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) MADERA_IRQ(DSP_IRQ13, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) MADERA_IRQ(DSP_IRQ14, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) MADERA_IRQ(DSP_IRQ15, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) MADERA_IRQ(DSP_IRQ16, MADERA_IRQ1_STATUS_11),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) MADERA_IRQ(HP3R_SC, MADERA_IRQ1_STATUS_12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) MADERA_IRQ(HP3L_SC, MADERA_IRQ1_STATUS_12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) MADERA_IRQ(HP2R_SC, MADERA_IRQ1_STATUS_12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) MADERA_IRQ(HP2L_SC, MADERA_IRQ1_STATUS_12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) MADERA_IRQ(HP1R_SC, MADERA_IRQ1_STATUS_12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) MADERA_IRQ(HP1L_SC, MADERA_IRQ1_STATUS_12),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) MADERA_IRQ(SPK_OVERHEAT_WARN, MADERA_IRQ1_STATUS_15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) MADERA_IRQ(SPK_OVERHEAT, MADERA_IRQ1_STATUS_15),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) MADERA_IRQ(DSP1_BUS_ERR, MADERA_IRQ1_STATUS_33),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) MADERA_IRQ(DSP2_BUS_ERR, MADERA_IRQ1_STATUS_33),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) MADERA_IRQ(DSP3_BUS_ERR, MADERA_IRQ1_STATUS_33),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) MADERA_IRQ(DSP4_BUS_ERR, MADERA_IRQ1_STATUS_33),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) MADERA_IRQ(DSP5_BUS_ERR, MADERA_IRQ1_STATUS_33),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) MADERA_IRQ(DSP6_BUS_ERR, MADERA_IRQ1_STATUS_33),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) MADERA_IRQ(DSP7_BUS_ERR, MADERA_IRQ1_STATUS_33),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) static const struct regmap_irq_chip madera_irq_chip = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) .name = "madera IRQ",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) .status_base = MADERA_IRQ1_STATUS_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) .mask_base = MADERA_IRQ1_MASK_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) .ack_base = MADERA_IRQ1_STATUS_2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) .runtime_pm = true,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) .num_regs = 32,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) .irqs = madera_irqs,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) .num_irqs = ARRAY_SIZE(madera_irqs),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) #ifdef CONFIG_PM_SLEEP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) static int madera_suspend(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) struct madera *madera = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) dev_dbg(madera->irq_dev, "Suspend, disabling IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) * A runtime resume would be needed to access the chip interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) * controller but runtime pm doesn't function during suspend.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) * Temporarily disable interrupts until we reach suspend_noirq state.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) disable_irq(madera->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static int madera_suspend_noirq(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) struct madera *madera = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) dev_dbg(madera->irq_dev, "No IRQ suspend, reenabling IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) /* Re-enable interrupts to service wakeup interrupts from the chip */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) enable_irq(madera->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) static int madera_resume_noirq(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) struct madera *madera = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) dev_dbg(madera->irq_dev, "No IRQ resume, disabling IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) * We can't handle interrupts until runtime pm is available again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * Disable them temporarily.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) disable_irq(madera->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) static int madera_resume(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) struct madera *madera = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) dev_dbg(madera->irq_dev, "Resume, reenabling IRQ\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) /* Interrupts can now be handled */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) enable_irq(madera->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) static const struct dev_pm_ops madera_irq_pm_ops = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) SET_SYSTEM_SLEEP_PM_OPS(madera_suspend, madera_resume)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(madera_suspend_noirq,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) madera_resume_noirq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) static int madera_irq_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) struct madera *madera = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) struct irq_data *irq_data;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) unsigned int irq_flags = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) dev_dbg(&pdev->dev, "probe\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) * Read the flags from the interrupt controller if not specified
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) * by pdata
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) irq_flags = madera->pdata.irq_flags;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) if (!irq_flags) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) irq_data = irq_get_irq_data(madera->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (!irq_data) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) dev_err(&pdev->dev, "Invalid IRQ: %d\n", madera->irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) irq_flags = irqd_get_trigger_type(irq_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) /* Codec defaults to trigger low, use this if no flags given */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) if (irq_flags == IRQ_TYPE_NONE)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) irq_flags = IRQF_TRIGGER_LOW;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) dev_err(&pdev->dev, "Host interrupt not level-triggered\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) * The silicon always starts at active-low, check if we need to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) * switch to active-high.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) if (irq_flags & IRQF_TRIGGER_HIGH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) ret = regmap_update_bits(madera->regmap, MADERA_IRQ1_CTRL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) MADERA_IRQ_POL_MASK, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) dev_err(&pdev->dev,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) "Failed to set IRQ polarity: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) * NOTE: regmap registers this against the OF node of the parent of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) * the regmap - that is, against the mfd driver
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) ret = regmap_add_irq_chip(madera->regmap, madera->irq, IRQF_ONESHOT, 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) &madera_irq_chip, &madera->irq_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) if (ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) dev_err(&pdev->dev, "add_irq_chip failed: %d\n", ret);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) /* Save dev in parent MFD struct so it is accessible to siblings */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) madera->irq_dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) static int madera_irq_remove(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) struct madera *madera = dev_get_drvdata(pdev->dev.parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) * The IRQ is disabled by the parent MFD driver before
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) * it starts cleaning up all child drivers
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) madera->irq_dev = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) regmap_del_irq_chip(madera->irq, madera->irq_data);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) static struct platform_driver madera_irq_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) .probe = &madera_irq_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) .remove = &madera_irq_remove,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) .driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) .name = "madera-irq",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) .pm = &madera_irq_pm_ops,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) module_platform_driver(madera_irq_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) MODULE_SOFTDEP("pre: madera");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) MODULE_DESCRIPTION("Madera IRQ driver");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) MODULE_LICENSE("GPL v2");