irqchip: Add driver for Cirrus Logic Madera codecs
Subsystems (2)
Richard Fitzgerald
maintainerPATCH v13 1/1 irqchip: Add driver for Cirrus Logic Madera codecs
The Cirrus Logic Madera codecs (Cirrus Logic CS47L35/85/90/91 and WM1840) are highly complex devices containing up to 7 programmable DSPs and many other internal sources of interrupts plus a number of GPIOs that can be used as interrupt inputs. The large number (>150) of internal interrupt sources are managed by an on-board interrupt controller.
This driver provides the handling for the interrupt controller. As the codec is accessed via regmap, we can make use of the generic IRQ functionality from regmap to do most of the work. Only around half of the possible interrupt source are currently of interest from the driver so only this subset is defined. Others can be added in future if needed.
The KConfig options are not user-configurable because this driver is mandatory so is automatically included when the parent MFD driver is selected.
---
Only difference from v11 is the copyright headers
--- MAINTAINERS | 2 + drivers/irqchip/Kconfig | 3 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-madera.c | 256 +++++++++++++++++++++++++++++++++++++ include/linux/irqchip/irq-madera.h | 132 +++++++++++++++++++ 5 files changed, 394 insertions(+) create mode 100644 drivers/irqchip/irq-madera.c create mode 100644 include/linux/irqchip/irq-madera.h
MAINTAINERS +2 -0
@@ -3595,8 +3595,10 @@ W: https://github.com/CirrusLogic/linux-drivers/wiki S: Supported F: Documentation/devicetree/bindings/mfd/madera.txt F: Documentation/devicetree/bindings/pinctrl/cirrus,madera-pinctrl.txt +F: include/linux/irqchip/irq-madera* F: include/linux/mfd/madera/* F: drivers/gpio/gpio-madera* +F: drivers/irqchip/irq-madera* F: drivers/mfd/madera* F: drivers/mfd/cs47l* F: drivers/pinctrl/cirrus/*
drivers/irqchip/Kconfig +3 -0
@@ -150,6 +150,9 @@ config IMGPDC_IRQ select GENERIC_IRQ_CHIP select IRQ_DOMAIN +config MADERA_IRQ + tristate + config IRQ_MIPS_CPU bool select GENERIC_IRQ_CHIP
drivers/irqchip/Makefile +1 -0
@@ -88,3 +88,4 @@ obj-$(CONFIG_GOLDFISH_PIC) += irq-goldfish-pic.o obj-$(CONFIG_NDS32) += irq-ativic32.o obj-$(CONFIG_QCOM_PDC) += qcom-pdc.o obj-$(CONFIG_SIFIVE_PLIC) += irq-sifive-plic.o +obj-$(CONFIG_MADERA_IRQ) += irq-madera.o
drivers/irqchip/irq-madera.c new file +256 -0
256 lines not on this page · raw message
include/linux/irqchip/irq-madera.h new file +132 -0
132 lines not on this page · raw message
Signature · 1 line
2.11.0
Quoted 31 lines · Richard Fitzgerald
The Cirrus Logic Madera codecs (Cirrus Logic CS47L35/85/90/91 and WM1840) are highly complex devices containing up to 7 programmable DSPs and many other internal sources of interrupts plus a number of GPIOs that can be used as interrupt inputs. The large number (>150) of internal interrupt sources are managed by an on-board interrupt controller.
This driver provides the handling for the interrupt controller. As the codec is accessed via regmap, we can make use of the generic IRQ functionality from regmap to do most of the work. Only around half of the possible interrupt source are currently of interest from the driver so only this subset is defined. Others can be added in future if needed.
The KConfig options are not user-configurable because this driver is mandatory so is automatically included when the parent MFD driver is selected.
Signed-off-by Richard Fitzgerald <[email protected]>Signed-off-by Charles Keepax <[email protected]>---
Only difference from v11 is the copyright headers--- MAINTAINERS | 2 + drivers/irqchip/Kconfig | 3 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-madera.c | 256 +++++++++++++++++++++++++++++++++++++ include/linux/irqchip/irq-madera.h | 132 +++++++++++++++++++ 5 files changed, 394 insertions(+) create mode 100644 drivers/irqchip/irq-madera.c create mode 100644 include/linux/irqchip/irq-madera.h
[...]
Quoted 5 lines
drivers/irqchip/irq-madera.c new file +0
-0
[...]
Quoted 28 lines
drivers/irqchip/irq-madera.c new file +28
-0+static int madera_irq_probe (struct platform_device *pdev) +{ +struct madera *madera =dev_get_drvdata (pdev->dev.parent); +struct irq_data *irq_data; +unsigned int irq_flags =0 ; +int ret; + +dev_dbg (&pdev->dev,"probe\n" ); + +/* +* Read the flags from the interrupt controller if not specified +* by pdata +*/ + irq_flags = madera->pdata.irq_flags; +if (!irq_flags) { + irq_data =irq_get_irq_data (madera->irq); +if (!irq_data) { +dev_err (&pdev->dev,"Invalid IRQ: %d\n" , madera->irq); +return -EINVAL ; + } + + irq_flags =irqd_get_trigger_type (irq_data); + +/* Codec defaults to trigger low, use this if no flags given */ +if (irq_flags ==IRQ_TYPE_NONE ) + irq_flags =IRQF_TRIGGER_LOW ; + } +
drivers/irqchip/irq-madera.c line 202
Quoted 10 lines
drivers/irqchip/irq-madera.c new file +10
-0+if (irq_flags & (IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING )) { +dev_err (&pdev->dev,"Host interrupt not level-triggered\n" ); +return -EINVAL ; + } + +/* +* The silicon always starts at active-low, check if we need to +* switch to active-high. +*/ +if (irq_flags &IRQF_TRIGGER_HIGH ) {
Is it safe to assume that the HW is in its reset state? What if the firmware has configured it otherwise, or if gone through kexec?
Quoted 15 lines
drivers/irqchip/irq-madera.c new file +15
-0+ ret =regmap_update_bits (madera->regmap,MADERA_IRQ1_CTRL , +MADERA_IRQ_POL_MASK ,0 ); +if (ret) { +dev_err (&pdev->dev, +"Failed to set IRQ polarity: %d\n" , ret); +return ret; + } + } + +/* +* NOTE: regmap registers this against the OF node of the parent of +* the regmap - that is, against the mfd driver +*/ + ret =regmap_add_irq_chip (madera->regmap, madera->irq,IRQF_ONESHOT ,0 , + &madera_irq_chip, &madera->irq_data);
drivers/irqchip/irq-madera.c line 227
Quoted 10 lines
drivers/irqchip/irq-madera.c new file +10
-0+if (ret) { +dev_err (&pdev->dev,"add_irq_chip failed: %d\n" , ret); +return ret; + } + +/* Save dev in parent MFD struct so it is accessible to siblings */ + madera->irq_dev = &pdev->dev; + +return 0 ; +}
Thanks,
M.
Signature · 1 line
Jazz is not dead, it just smell funny.
Richard Fitzgerald
maintainerQuoted 77 lines · Marc Zyngier
Quoted 31 lines · Richard Fitzgerald
The Cirrus Logic Madera codecs (Cirrus Logic CS47L35/85/90/91 and WM1840) are highly complex devices containing up to 7 programmable DSPs and many other internal sources of interrupts plus a number of GPIOs that can be used as interrupt inputs. The large number (>150) of internal interrupt sources are managed by an on-board interrupt controller.
This driver provides the handling for the interrupt controller. As the codec is accessed via regmap, we can make use of the generic IRQ functionality from regmap to do most of the work. Only around half of the possible interrupt source are currently of interest from the driver so only this subset is defined. Others can be added in future if needed.
The KConfig options are not user-configurable because this driver is mandatory so is automatically included when the parent MFD driver is selected.
Signed-off-by Richard Fitzgerald <[email protected]>Signed-off-by Charles Keepax <[email protected]>---
Only difference from v11 is the copyright headers--- MAINTAINERS | 2 + drivers/irqchip/Kconfig | 3 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-madera.c | 256 +++++++++++++++++++++++++++++++++++++ include/linux/irqchip/irq-madera.h | 132 +++++++++++++++++++ 5 files changed, 394 insertions(+)create mode 100644
drivers/irqchip/irq-madera.ccreate mode 100644include/linux/irqchip/irq-madera.h[...]
Quoted 5 lines
drivers/irqchip/irq-madera.c new file +0
-0[...]
Quoted 33 lines
drivers/irqchip/irq-madera.c new file +33
-0+static int madera_irq_probe (struct platform_device *pdev) +{ +struct madera *madera =dev_get_drvdata (pdev->dev.parent); +struct irq_data *irq_data; +unsigned int irq_flags =0 ; +int ret; + +dev_dbg (&pdev->dev,"probe\n" ); + +/* +* Read the flags from the interrupt controller if not specified +* by pdata +*/ + irq_flags = madera->pdata.irq_flags; +if (!irq_flags) { + irq_data =irq_get_irq_data (madera->irq); +if (!irq_data) { +dev_err (&pdev->dev,"Invalid IRQ: %d\n" , madera->irq); +return -EINVAL ; + } + + irq_flags =irqd_get_trigger_type (irq_data); + +/* Codec defaults to trigger low, use this if no flags given */ +if (irq_flags ==IRQ_TYPE_NONE ) + irq_flags =IRQF_TRIGGER_LOW ; + } + +if (irq_flags & (IRQF_TRIGGER_RISING |IRQF_TRIGGER_FALLING )) { +dev_err (&pdev->dev,"Host interrupt not level-triggered\n" ); +return -EINVAL ; + } +
Quoted 9 lines
drivers/irqchip/irq-madera.c line 202
Quoted 5 lines
drivers/irqchip/irq-madera.c new file +5
-0+/* +* The silicon always starts at active-low, check if we need to +* switch to active-high. +*/ +if (irq_flags &IRQF_TRIGGER_HIGH ) {Is it safe to assume that the HW is in its reset state? What if the firmware has configured it otherwise, or if gone through kexec?
The parent mfd probe always resets the silicon before registering the children. If this driver were to be removed and reprobed without reprobing the parent mfd, these lines of code are irrelevant because the regmap cache would still preserve the correct setting.
The DSP firmware is not allowed to change the host IRQ configuration or reset the silicon. Firmwares can only be loaded via ALSA/ASoC and the driver for that cannot complete probe until the irqchip driver has probed,
Quoted 30 lines
Quoted 15 lines
drivers/irqchip/irq-madera.c new file +15
-0+ ret =regmap_update_bits (madera->regmap,MADERA_IRQ1_CTRL , +MADERA_IRQ_POL_MASK ,0 ); +if (ret) { +dev_err (&pdev->dev, +"Failed to set IRQ polarity: %d\n" , ret); +return ret; + } + } + +/* +* NOTE: regmap registers this against the OF node of the parent of +* the regmap - that is, against the mfd driver +*/ + ret =regmap_add_irq_chip (madera->regmap, madera->irq,IRQF_ONESHOT ,0 , + &madera_irq_chip, &madera->irq_data);drivers/irqchip/irq-madera.c line 227
Quoted 10 lines
drivers/irqchip/irq-madera.c new file +10
-0+if (ret) { +dev_err (&pdev->dev,"add_irq_chip failed: %d\n" , ret); +return ret; + } + +/* Save dev in parent MFD struct so it is accessible to siblings */ + madera->irq_dev = &pdev->dev; + +return 0 ; +}Thanks,
M.