linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] mfd: bcm590xx: Add support for interrupt handling
@ 2025-08-16 16:03 Artur Weber
  2025-09-02  7:50 ` Lee Jones
  0 siblings, 1 reply; 3+ messages in thread
From: Artur Weber @ 2025-08-16 16:03 UTC (permalink / raw)
  To: Lee Jones
  Cc: linux-kernel, ~postmarketos/upstreaming, Stanislav Jakubek,
	Artur Weber

The BCM590XX supports up to 128 internal interrupts, which are used by
various parts of the chip. Add regmap_irq-based interrupt handling and
helper functions to allow subdevice drivers to easily use the interrupts.

Signed-off-by: Artur Weber <aweber.kernel@gmail.com>
---
This patch is a prerequisite for future subdevice additions, since
many of them rely on the interrupts; I have a power-on key driver and
an RTC driver ready which both use the IRQ data/helper functions included
in this patch (they will be sent in subsequent patch series), and more
are on the way.
---
 drivers/mfd/Kconfig          |   1 +
 drivers/mfd/bcm590xx.c       | 281 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/mfd/bcm590xx.h | 231 +++++++++++++++++++++++++++++++++++
 3 files changed, 513 insertions(+)

diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6fb3768e3d71cbb5c81f63de36cdb2d27a0a7726..e76b18e29dbc6ba40f162276cb19b89806b326a6 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -175,6 +175,7 @@ config MFD_BCM590XX
 	tristate "Broadcom BCM590xx PMUs"
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	depends on I2C
 	help
 	  Support for the BCM590xx PMUs from Broadcom
diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
index 5a8456bbd63f65b9260f05ef6546c026bf822bae..d688abd08c12b621a38586650843e55bd71ca715 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -26,16 +26,30 @@
 #define BCM590XX_PMUREV_ANA_MASK	0xF0
 #define BCM590XX_PMUREV_ANA_SHIFT	4
 
+#define BCM590XX_REG_IRQ1		0x20
+#define BCM590XX_REG_IRQ1_MASK		0x30
+
 static const struct mfd_cell bcm590xx_devs[] = {
 	{
 		.name = "bcm590xx-vregs",
 	},
 };
 
+static bool bcm590xx_volatile_pri(struct device *dev, unsigned int reg)
+{
+	/*
+	 * IRQ registers are clear-on-read, make sure we don't cache them
+	 * so that they get read/cleared correctly
+	 */
+	return (reg >= BCM590XX_REG_IRQ1 &&
+		reg <= (BCM590XX_REG_IRQ1 + 15));
+}
+
 static const struct regmap_config bcm590xx_regmap_config_pri = {
 	.reg_bits	= 8,
 	.val_bits	= 8,
 	.max_register	= BCM590XX_MAX_REGISTER_PRI,
+	.volatile_reg	= bcm590xx_volatile_pri,
 	.cache_type	= REGCACHE_MAPLE,
 };
 
@@ -46,6 +60,268 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
 	.cache_type	= REGCACHE_MAPLE,
 };
 
+/** Interrupt handling **/
+
+/* IRQ IDs in the MFD header follow the IRQ order in hardware. */
+#define BCM590XX_REGMAP_IRQ_REG(id)	REGMAP_IRQ_REG_LINE(id, 8)
+
+/* BCM59054 IRQs */
+
+static const struct regmap_irq bcm59054_regmap_irqs[] = {
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBINS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBRM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_BATINS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_BATRM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBC_CV_LOOP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBC_CV_TMR_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_EOC),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RESUME_VBUS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBTEMPLOW),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBTEMPHIGH),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBOV),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBOV),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHGERRDIS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBOV_DIS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBOV_DIS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBC_TF),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_HW_TTR_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_HW_TCH_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_SW_TMR_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_TCH_1MIN_BF_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USB_PORT_DIS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USB_CC_REDUCE),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBUSLOWBND),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_UBPD_CHG_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBUS_VALID_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_OTG_SESS_VALID_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VB_SESS_END_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ID_RM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBUS_VALID_R),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VA_SESS_VALID_R),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VB_SESS_END_R),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ID_INS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IDCHG),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RIC_C_TO_FLOAT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHGDET_LATCH),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHGDET_TO),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_CHANGE),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_SNS_END),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_PROB),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_PRB_ERR),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_PRESSED),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_RELEASED),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_WAKEUP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_BIT_VLD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_RESTART),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_T1),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_T2),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_T3),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_I2C_RESTART),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GBAT_PLUG_IN),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SMPL_INT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUX_INS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUX_RM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_XTAL_FAILURE),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBWV_R_10S_WAIT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBWV_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTC_ALARM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTC_SEC),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTC_MIN),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTCADJ),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_FGC),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_BBLOW),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_DIE_OT_R),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_DIE_OT_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_DATA_RDY),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_IN_CON_MEAS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_UPPER),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_IGNORE),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_OVERRIDDEN),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUD_HSAB_SHCKT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUD_IHFD_SHCKT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_NOP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_LEN_ERR),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_RCV_ERR),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_BUSQ_RESP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_BUSQ_POS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_EOT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_XMT_END),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_INT_POS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LOWBAT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CSROVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VSROVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MSROVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR1OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR2OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR1OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR2OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RESERVED),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RFLDO_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUDLDO_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBLDO_OVR),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDXLDO_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MICLDO_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO1_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO2_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MMCLDO1_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO1_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO2_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VIBLDO_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDLDO_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO1_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO2_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO3_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RFLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUDLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDXLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MICLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO1_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO2_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MMCLDO1_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MMCLDO2_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO1_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO2_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VIBLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO1_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO2_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO3_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_TCXLDO_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO1_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO2_OVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_TCXLDO_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO1_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO2_SHD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBOVRV),
+	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBOVRI),
+};
+
+static const struct regmap_irq_chip bcm59054_irq_chip = {
+	.name = "bcm59054-irq",
+	.irqs = bcm59054_regmap_irqs,
+	.num_irqs = BCM59054_IRQ_MAX,
+	.num_regs = 16,
+	.status_base = BCM590XX_REG_IRQ1,
+	.mask_base = BCM590XX_REG_IRQ1_MASK,
+	.clear_on_unmask = true,
+};
+
+/* BCM59056 IRQs */
+
+static const struct regmap_irq bcm59056_regmap_irqs[] = {
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTC_ALARM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTC_SEC),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTC_MIN),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTCADJ),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_BATINS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_BATRM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_GBAT_PLUG_IN),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SMPL_INT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBINS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBRM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBOV),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_EOC),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RESUME_VBUS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHG_HW_TTR_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHG_HW_TCH_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHG_SW_TMR_EXP),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHGDET_LATCH),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHGDET_TO),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBTEMPLOW),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBTEMPHIGH),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBOV),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBOV_DIS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBOV_DIS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHGERRDIS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_1V5_R),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_4V5_R),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_1V5_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_4V5_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBWV_R_10S_WAIT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_BBLOW),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_LOWBAT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VERYLOWBAT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_DATA_RDY),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_IN_CON_MEAS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_UPPER),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_IGNORE),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_OVERRIDDEN),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_AUD_HSAB_SHCKT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_AUD_IHFD_SHCKT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBC_TF),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CSROVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_IOSROVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SDSROVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ASROVRI),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_UBPD_CHG_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ACD_INS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ACD_RM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_HOLD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_F),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_R),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_OFFHOLD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_RESTART),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_IDCHG),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_JIG_USB_INS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_UART_INS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ID_INS),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ID_RM),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ADP_CHANGE),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ADP_SNS_END),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SESSION_END_VLD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SESSION_END_INVLD),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_OVERCURRENT),
+	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_FGC),
+};
+
+static const struct regmap_irq_chip bcm59056_irq_chip = {
+	.name = "bcm59056-irq",
+	.irqs = bcm59056_regmap_irqs,
+	.num_irqs = BCM59056_IRQ_MAX,
+	.num_regs = 16,
+	.status_base = BCM590XX_REG_IRQ1,
+	.mask_base = BCM590XX_REG_IRQ1_MASK,
+	.clear_on_unmask = true,
+};
+
+static int bcm590xx_irq_init(struct bcm590xx *bcm590xx)
+{
+	const struct regmap_irq_chip *irq_chip;
+	int ret;
+
+	if (!bcm590xx->irq) {
+		dev_err(bcm590xx->dev, "No IRQ configured\n");
+		return -EINVAL;
+	}
+
+	switch (bcm590xx->pmu_id) {
+	case BCM590XX_PMUID_BCM59054:
+		irq_chip = &bcm59054_irq_chip;
+		break;
+	case BCM590XX_PMUID_BCM59056:
+		irq_chip = &bcm59056_irq_chip;
+		break;
+	default:
+		dev_err(bcm590xx->dev,
+			"Unknown device type, this is a driver bug!\n");
+		return -EINVAL;
+	}
+
+	ret = devm_regmap_add_irq_chip(bcm590xx->dev, bcm590xx->regmap_pri,
+			bcm590xx->irq, IRQF_TRIGGER_FALLING, 0,
+			irq_chip, &bcm590xx->irq_data);
+	if (ret) {
+		dev_err(bcm590xx->dev, "Failed to reguest IRQ %d: %d\n",
+			bcm590xx->irq, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+/** Chip version parsing **/
+
 /* Map PMU ID value to model name string */
 static const char * const bcm590xx_names[] = {
 	[BCM590XX_PMUID_BCM59054] = "BCM59054",
@@ -98,6 +374,7 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 
 	i2c_set_clientdata(i2c_pri, bcm590xx);
 	bcm590xx->dev = &i2c_pri->dev;
+	bcm590xx->irq = i2c_pri->irq;
 	bcm590xx->i2c_pri = i2c_pri;
 
 	bcm590xx->pmu_id = (uintptr_t) of_device_get_match_data(bcm590xx->dev);
@@ -132,6 +409,10 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
 	if (ret)
 		goto err;
 
+	ret = bcm590xx_irq_init(bcm590xx);
+	if (ret)
+		goto err;
+
 	ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
 				   ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
 	if (ret < 0) {
diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
index 5a5783abd47b9a6bb6f9bb3a8cafddbd01aa7fcc..e6ea643766ab1a9d579c94605b54c53dc1d742d7 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -50,6 +50,237 @@ struct bcm590xx {
 	/* Chip revision, read from PMUREV reg */
 	u8 rev_digital;
 	u8 rev_analog;
+
+	/* Interrupts */
+	int irq;
+	struct regmap_irq_chip_data *irq_data;
+};
+
+/* Interrupt handling helper functions */
+
+static inline int
+bcm590xx_devm_request_irq(struct device *dev, struct bcm590xx *bcm590xx, int irq,
+			  irq_handler_t handler, unsigned long flags,
+			  const char *name, void *data)
+{
+	if (!bcm590xx->irq_data)
+		return -EINVAL;
+
+	return devm_request_threaded_irq(dev,
+				regmap_irq_get_virq(bcm590xx->irq_data, irq),
+				NULL, handler, flags, name, data);
+}
+
+static inline void
+bcm590xx_devm_free_irq(struct device *dev, struct bcm590xx *bcm590xx, int irq,
+		       void *data)
+{
+	if (!bcm590xx->irq_data)
+		return;
+
+	devm_free_irq(dev, regmap_irq_get_virq(bcm590xx->irq_data, irq), data);
+}
+
+/* BCM59054 IRQs */
+
+enum bcm59054_irq {
+	BCM59054_IRQ_USBINS = 0,
+	BCM59054_IRQ_USBRM,
+	BCM59054_IRQ_BATINS,
+	BCM59054_IRQ_BATRM,
+	BCM59054_IRQ_MBC_CV_LOOP,
+	BCM59054_IRQ_MBC_CV_TMR_EXP,
+	BCM59054_IRQ_EOC,
+	BCM59054_IRQ_RESUME_VBUS,
+	BCM59054_IRQ_MBTEMPLOW,
+	BCM59054_IRQ_MBTEMPHIGH,
+	BCM59054_IRQ_USBOV,
+	BCM59054_IRQ_MBOV,
+	BCM59054_IRQ_CHGERRDIS,
+	BCM59054_IRQ_MBOV_DIS,
+	BCM59054_IRQ_USBOV_DIS,
+	BCM59054_IRQ_MBC_TF,
+	BCM59054_IRQ_CHG_HW_TTR_EXP,
+	BCM59054_IRQ_CHG_HW_TCH_EXP,
+	BCM59054_IRQ_CHG_SW_TMR_EXP,
+	BCM59054_IRQ_CHG_TCH_1MIN_BF_EXP,
+	BCM59054_IRQ_USB_PORT_DIS,
+	BCM59054_IRQ_USB_CC_REDUCE,
+	BCM59054_IRQ_VBUSLOWBND,
+	BCM59054_IRQ_UBPD_CHG_F,
+	BCM59054_IRQ_VBUS_VALID_F,
+	BCM59054_IRQ_OTG_SESS_VALID_F,
+	BCM59054_IRQ_VB_SESS_END_F,
+	BCM59054_IRQ_ID_RM,
+	BCM59054_IRQ_VBUS_VALID_R,
+	BCM59054_IRQ_VA_SESS_VALID_R,
+	BCM59054_IRQ_VB_SESS_END_R,
+	BCM59054_IRQ_ID_INS,
+	BCM59054_IRQ_IDCHG,
+	BCM59054_IRQ_RIC_C_TO_FLOAT,
+	BCM59054_IRQ_CHGDET_LATCH,
+	BCM59054_IRQ_CHGDET_TO,
+	BCM59054_IRQ_ADP_CHANGE,
+	BCM59054_IRQ_ADP_SNS_END,
+	BCM59054_IRQ_ADP_PROB,
+	BCM59054_IRQ_ADP_PRB_ERR,
+	BCM59054_IRQ_POK_PRESSED,
+	BCM59054_IRQ_POK_RELEASED,
+	BCM59054_IRQ_POK_WAKEUP,
+	BCM59054_IRQ_POK_BIT_VLD,
+	BCM59054_IRQ_POK_RESTART,
+	BCM59054_IRQ_POK_T1,
+	BCM59054_IRQ_POK_T2,
+	BCM59054_IRQ_POK_T3,
+	BCM59054_IRQ_I2C_RESTART,
+	BCM59054_IRQ_GBAT_PLUG_IN,
+	BCM59054_IRQ_SMPL_INT,
+	BCM59054_IRQ_AUX_INS,
+	BCM59054_IRQ_AUX_RM,
+	BCM59054_IRQ_XTAL_FAILURE,
+	BCM59054_IRQ_MBWV_R_10S_WAIT,
+	BCM59054_IRQ_MBWV_F,
+	BCM59054_IRQ_RTC_ALARM,
+	BCM59054_IRQ_RTC_SEC,
+	BCM59054_IRQ_RTC_MIN,
+	BCM59054_IRQ_RTCADJ,
+	BCM59054_IRQ_FGC,
+	BCM59054_IRQ_BBLOW,
+	BCM59054_IRQ_DIE_OT_R,
+	BCM59054_IRQ_DIE_OT_F,
+	BCM59054_IRQ_RTM_DATA_RDY,
+	BCM59054_IRQ_RTM_IN_CON_MEAS,
+	BCM59054_IRQ_RTM_UPPER,
+	BCM59054_IRQ_RTM_IGNORE,
+	BCM59054_IRQ_RTM_OVERRIDDEN,
+	BCM59054_IRQ_AUD_HSAB_SHCKT,
+	BCM59054_IRQ_AUD_IHFD_SHCKT,
+	BCM59054_IRQ_POK_NOP,
+	BCM59054_IRQ_MIPI_LEN_ERR,
+	BCM59054_IRQ_MIPI_RCV_ERR,
+	BCM59054_IRQ_MIPI_BUSQ_RESP,
+	BCM59054_IRQ_MIPI_BUSQ_POS,
+	BCM59054_IRQ_MIPI_EOT,
+	BCM59054_IRQ_MIPI_XMT_END,
+	BCM59054_IRQ_MIPI_INT_POS,
+	BCM59054_IRQ_LOWBAT,
+	BCM59054_IRQ_CSROVRI,
+	BCM59054_IRQ_VSROVRI,
+	BCM59054_IRQ_MSROVRI,
+	BCM59054_IRQ_SDSR1OVRI,
+	BCM59054_IRQ_SDSR2OVRI,
+	BCM59054_IRQ_IOSR1OVRI,
+	BCM59054_IRQ_IOSR2OVRI,
+	BCM59054_IRQ_RESERVED,
+	BCM59054_IRQ_RFLDO_OVRI,
+	BCM59054_IRQ_AUDLDO_OVRI,
+	BCM59054_IRQ_USBLDO_OVR,
+	BCM59054_IRQ_SDXLDO_OVRI,
+	BCM59054_IRQ_MICLDO_OVRI,
+	BCM59054_IRQ_SIMLDO1_OVRI,
+	BCM59054_IRQ_SIMLDO2_OVRI,
+	BCM59054_IRQ_MMCLDO1_OVRI,
+	BCM59054_IRQ_CAMLDO1_OVRI,
+	BCM59054_IRQ_CAMLDO2_OVRI,
+	BCM59054_IRQ_VIBLDO_OVRI,
+	BCM59054_IRQ_SDLDO_OVRI,
+	BCM59054_IRQ_GPLDO1_OVRI,
+	BCM59054_IRQ_GPLDO2_OVRI,
+	BCM59054_IRQ_GPLDO3_OVRI,
+	BCM59054_IRQ_RFLDO_SHD,
+	BCM59054_IRQ_AUDLDO_SHD,
+	BCM59054_IRQ_USBLDO_SHD,
+	BCM59054_IRQ_SDXLDO_SHD,
+	BCM59054_IRQ_MICLDO_SHD,
+	BCM59054_IRQ_SIMLDO1_SHD,
+	BCM59054_IRQ_SIMLDO2_SHD,
+	BCM59054_IRQ_MMCLDO1_SHD,
+	BCM59054_IRQ_MMCLDO2_SHD,
+	BCM59054_IRQ_CAMLDO1_SHD,
+	BCM59054_IRQ_CAMLDO2_SHD,
+	BCM59054_IRQ_VIBLDO_SHD,
+	BCM59054_IRQ_SDLDO_SHD,
+	BCM59054_IRQ_GPLDO1_SHD,
+	BCM59054_IRQ_GPLDO2_SHD,
+	BCM59054_IRQ_GPLDO3_SHD,
+	BCM59054_IRQ_TCXLDO_OVRI,
+	BCM59054_IRQ_LVLDO1_OVRI,
+	BCM59054_IRQ_LVLDO2_OVRI,
+	BCM59054_IRQ_TCXLDO_SHD,
+	BCM59054_IRQ_LVLDO1_SHD,
+	BCM59054_IRQ_LVLDO2_SHD,
+	BCM59054_IRQ_VBOVRV,
+	BCM59054_IRQ_VBOVRI,
+	BCM59054_IRQ_MAX,
+};
+
+/* BCM59056 IRQs */
+
+enum bcm59056_irq {
+	BCM59056_IRQ_RTC_ALARM = 0,
+	BCM59056_IRQ_RTC_SEC,
+	BCM59056_IRQ_RTC_MIN,
+	BCM59056_IRQ_RTCADJ,
+	BCM59056_IRQ_BATINS,
+	BCM59056_IRQ_BATRM,
+	BCM59056_IRQ_GBAT_PLUG_IN,
+	BCM59056_IRQ_SMPL_INT,
+	BCM59056_IRQ_USBINS,
+	BCM59056_IRQ_USBRM,
+	BCM59056_IRQ_USBOV,
+	BCM59056_IRQ_EOC,
+	BCM59056_IRQ_RESUME_VBUS,
+	BCM59056_IRQ_CHG_HW_TTR_EXP,
+	BCM59056_IRQ_CHG_HW_TCH_EXP,
+	BCM59056_IRQ_CHG_SW_TMR_EXP,
+	BCM59056_IRQ_CHGDET_LATCH,
+	BCM59056_IRQ_CHGDET_TO,
+	BCM59056_IRQ_MBTEMPLOW,
+	BCM59056_IRQ_MBTEMPHIGH,
+	BCM59056_IRQ_MBOV,
+	BCM59056_IRQ_MBOV_DIS,
+	BCM59056_IRQ_USBOV_DIS,
+	BCM59056_IRQ_CHGERRDIS,
+	BCM59056_IRQ_VBUS_1V5_R,
+	BCM59056_IRQ_VBUS_4V5_R,
+	BCM59056_IRQ_VBUS_1V5_F,
+	BCM59056_IRQ_VBUS_4V5_F,
+	BCM59056_IRQ_MBWV_R_10S_WAIT,
+	BCM59056_IRQ_BBLOW,
+	BCM59056_IRQ_LOWBAT,
+	BCM59056_IRQ_VERYLOWBAT,
+	BCM59056_IRQ_RTM_DATA_RDY,
+	BCM59056_IRQ_RTM_IN_CON_MEAS,
+	BCM59056_IRQ_RTM_UPPER,
+	BCM59056_IRQ_RTM_IGNORE,
+	BCM59056_IRQ_RTM_OVERRIDDEN,
+	BCM59056_IRQ_AUD_HSAB_SHCKT,
+	BCM59056_IRQ_AUD_IHFD_SHCKT,
+	BCM59056_IRQ_MBC_TF,
+	BCM59056_IRQ_CSROVRI,
+	BCM59056_IRQ_IOSROVRI,
+	BCM59056_IRQ_SDSROVRI,
+	BCM59056_IRQ_ASROVRI,
+	BCM59056_IRQ_UBPD_CHG_F,
+	BCM59056_IRQ_ACD_INS,
+	BCM59056_IRQ_ACD_RM,
+	BCM59056_IRQ_PONKEYB_HOLD,
+	BCM59056_IRQ_PONKEYB_F,
+	BCM59056_IRQ_PONKEYB_R,
+	BCM59056_IRQ_PONKEYB_OFFHOLD,
+	BCM59056_IRQ_PONKEYB_RESTART,
+	BCM59056_IRQ_IDCHG,
+	BCM59056_IRQ_JIG_USB_INS,
+	BCM59056_IRQ_UART_INS,
+	BCM59056_IRQ_ID_INS,
+	BCM59056_IRQ_ID_RM,
+	BCM59056_IRQ_ADP_CHANGE,
+	BCM59056_IRQ_ADP_SNS_END,
+	BCM59056_IRQ_SESSION_END_VLD,
+	BCM59056_IRQ_SESSION_END_INVLD,
+	BCM59056_IRQ_VBUS_OVERCURRENT,
+	BCM59056_IRQ_FGC,
+	BCM59056_IRQ_MAX,
 };
 
 #endif /*  __LINUX_MFD_BCM590XX_H */

---
base-commit: 038d61fd642278bab63ee8ef722c50d10ab01e8f
change-id: 20250816-bcm590xx-irq-2d4c1cbe00b1

Best regards,
-- 
Artur Weber <aweber.kernel@gmail.com>


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] mfd: bcm590xx: Add support for interrupt handling
  2025-08-16 16:03 [PATCH] mfd: bcm590xx: Add support for interrupt handling Artur Weber
@ 2025-09-02  7:50 ` Lee Jones
  2025-09-02 15:23   ` Artur Weber
  0 siblings, 1 reply; 3+ messages in thread
From: Lee Jones @ 2025-09-02  7:50 UTC (permalink / raw)
  To: Artur Weber; +Cc: linux-kernel, ~postmarketos/upstreaming, Stanislav Jakubek

On Sat, 16 Aug 2025, Artur Weber wrote:

> The BCM590XX supports up to 128 internal interrupts, which are used by
> various parts of the chip. Add regmap_irq-based interrupt handling and
> helper functions to allow subdevice drivers to easily use the interrupts.
> 
> Signed-off-by: Artur Weber <aweber.kernel@gmail.com>
> ---
> This patch is a prerequisite for future subdevice additions, since
> many of them rely on the interrupts; I have a power-on key driver and
> an RTC driver ready which both use the IRQ data/helper functions included
> in this patch (they will be sent in subsequent patch series), and more
> are on the way.
> ---
>  drivers/mfd/Kconfig          |   1 +
>  drivers/mfd/bcm590xx.c       | 281 +++++++++++++++++++++++++++++++++++++++++++
>  include/linux/mfd/bcm590xx.h | 231 +++++++++++++++++++++++++++++++++++
>  3 files changed, 513 insertions(+)
> 
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 6fb3768e3d71cbb5c81f63de36cdb2d27a0a7726..e76b18e29dbc6ba40f162276cb19b89806b326a6 100644
> --- a/drivers/mfd/Kconfig
> +++ b/drivers/mfd/Kconfig
> @@ -175,6 +175,7 @@ config MFD_BCM590XX
>  	tristate "Broadcom BCM590xx PMUs"
>  	select MFD_CORE
>  	select REGMAP_I2C
> +	select REGMAP_IRQ
>  	depends on I2C
>  	help
>  	  Support for the BCM590xx PMUs from Broadcom
> diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
> index 5a8456bbd63f65b9260f05ef6546c026bf822bae..d688abd08c12b621a38586650843e55bd71ca715 100644
> --- a/drivers/mfd/bcm590xx.c
> +++ b/drivers/mfd/bcm590xx.c
> @@ -26,16 +26,30 @@
>  #define BCM590XX_PMUREV_ANA_MASK	0xF0
>  #define BCM590XX_PMUREV_ANA_SHIFT	4
>  
> +#define BCM590XX_REG_IRQ1		0x20
> +#define BCM590XX_REG_IRQ1_MASK		0x30

REG and MASK mean different things.  What is it?

> +
>  static const struct mfd_cell bcm590xx_devs[] = {
>  	{
>  		.name = "bcm590xx-vregs",
>  	},
>  };
>  
> +static bool bcm590xx_volatile_pri(struct device *dev, unsigned int reg)

What does pri mean?

> +{
> +	/*
> +	 * IRQ registers are clear-on-read, make sure we don't cache them
> +	 * so that they get read/cleared correctly
> +	 */
> +	return (reg >= BCM590XX_REG_IRQ1 &&
> +		reg <= (BCM590XX_REG_IRQ1 + 15));

Use up to 100-chars to prevent these line feeds.

> +}
> +
>  static const struct regmap_config bcm590xx_regmap_config_pri = {
>  	.reg_bits	= 8,
>  	.val_bits	= 8,
>  	.max_register	= BCM590XX_MAX_REGISTER_PRI,
> +	.volatile_reg	= bcm590xx_volatile_pri,
>  	.cache_type	= REGCACHE_MAPLE,
>  };
>  
> @@ -46,6 +60,268 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
>  	.cache_type	= REGCACHE_MAPLE,
>  };
>  
> +/** Interrupt handling **/

This is obvious with the alerting header comment.

> +/* IRQ IDs in the MFD header follow the IRQ order in hardware. */

Not sure I the helpfulness of this comment.

> +#define BCM590XX_REGMAP_IRQ_REG(id)	REGMAP_IRQ_REG_LINE(id, 8)

What does the 8 mean?

> +
> +/* BCM59054 IRQs */

We can see this by the nomenclature.

> +static const struct regmap_irq bcm59054_regmap_irqs[] = {
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBINS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBRM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_BATINS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_BATRM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBC_CV_LOOP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBC_CV_TMR_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_EOC),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RESUME_VBUS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBTEMPLOW),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBTEMPHIGH),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBOV),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBOV),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHGERRDIS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBOV_DIS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBOV_DIS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBC_TF),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_HW_TTR_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_HW_TCH_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_SW_TMR_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHG_TCH_1MIN_BF_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USB_PORT_DIS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USB_CC_REDUCE),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBUSLOWBND),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_UBPD_CHG_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBUS_VALID_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_OTG_SESS_VALID_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VB_SESS_END_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ID_RM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBUS_VALID_R),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VA_SESS_VALID_R),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VB_SESS_END_R),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ID_INS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IDCHG),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RIC_C_TO_FLOAT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHGDET_LATCH),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CHGDET_TO),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_CHANGE),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_SNS_END),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_PROB),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_ADP_PRB_ERR),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_PRESSED),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_RELEASED),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_WAKEUP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_BIT_VLD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_RESTART),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_T1),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_T2),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_T3),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_I2C_RESTART),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GBAT_PLUG_IN),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SMPL_INT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUX_INS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUX_RM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_XTAL_FAILURE),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBWV_R_10S_WAIT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MBWV_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTC_ALARM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTC_SEC),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTC_MIN),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTCADJ),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_FGC),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_BBLOW),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_DIE_OT_R),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_DIE_OT_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_DATA_RDY),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_IN_CON_MEAS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_UPPER),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_IGNORE),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RTM_OVERRIDDEN),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUD_HSAB_SHCKT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUD_IHFD_SHCKT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_POK_NOP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_LEN_ERR),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_RCV_ERR),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_BUSQ_RESP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_BUSQ_POS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_EOT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_XMT_END),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MIPI_INT_POS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LOWBAT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CSROVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VSROVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MSROVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR1OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR2OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR1OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR2OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RESERVED),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RFLDO_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUDLDO_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBLDO_OVR),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDXLDO_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MICLDO_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO1_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO2_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MMCLDO1_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO1_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO2_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VIBLDO_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDLDO_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO1_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO2_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO3_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_RFLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_AUDLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_USBLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDXLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MICLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO1_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SIMLDO2_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MMCLDO1_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MMCLDO2_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO1_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_CAMLDO2_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VIBLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO1_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO2_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_GPLDO3_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_TCXLDO_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO1_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO2_OVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_TCXLDO_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO1_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_LVLDO2_SHD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBOVRV),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VBOVRI),
> +};
> +
> +static const struct regmap_irq_chip bcm59054_irq_chip = {
> +	.name = "bcm59054-irq",
> +	.irqs = bcm59054_regmap_irqs,
> +	.num_irqs = BCM59054_IRQ_MAX,
> +	.num_regs = 16,
> +	.status_base = BCM590XX_REG_IRQ1,
> +	.mask_base = BCM590XX_REG_IRQ1_MASK,
> +	.clear_on_unmask = true,
> +};
> +
> +/* BCM59056 IRQs */

As above.

> +static const struct regmap_irq bcm59056_regmap_irqs[] = {
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTC_ALARM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTC_SEC),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTC_MIN),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTCADJ),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_BATINS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_BATRM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_GBAT_PLUG_IN),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SMPL_INT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBINS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBRM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBOV),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_EOC),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RESUME_VBUS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHG_HW_TTR_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHG_HW_TCH_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHG_SW_TMR_EXP),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHGDET_LATCH),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHGDET_TO),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBTEMPLOW),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBTEMPHIGH),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBOV),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBOV_DIS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_USBOV_DIS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CHGERRDIS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_1V5_R),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_4V5_R),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_1V5_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_4V5_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBWV_R_10S_WAIT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_BBLOW),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_LOWBAT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VERYLOWBAT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_DATA_RDY),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_IN_CON_MEAS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_UPPER),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_IGNORE),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_RTM_OVERRIDDEN),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_AUD_HSAB_SHCKT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_AUD_IHFD_SHCKT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_MBC_TF),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_CSROVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_IOSROVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SDSROVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ASROVRI),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_UBPD_CHG_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ACD_INS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ACD_RM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_HOLD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_F),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_R),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_OFFHOLD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_PONKEYB_RESTART),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_IDCHG),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_JIG_USB_INS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_UART_INS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ID_INS),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ID_RM),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ADP_CHANGE),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ADP_SNS_END),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SESSION_END_VLD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SESSION_END_INVLD),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_VBUS_OVERCURRENT),
> +	BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_FGC),
> +};
> +
> +static const struct regmap_irq_chip bcm59056_irq_chip = {
> +	.name = "bcm59056-irq",
> +	.irqs = bcm59056_regmap_irqs,
> +	.num_irqs = BCM59056_IRQ_MAX,
> +	.num_regs = 16,
> +	.status_base = BCM590XX_REG_IRQ1,
> +	.mask_base = BCM590XX_REG_IRQ1_MASK,
> +	.clear_on_unmask = true,
> +};
> +
> +static int bcm590xx_irq_init(struct bcm590xx *bcm590xx)
> +{
> +	const struct regmap_irq_chip *irq_chip;
> +	int ret;
> +
> +	if (!bcm590xx->irq) {
> +		dev_err(bcm590xx->dev, "No IRQ configured\n");
> +		return -EINVAL;
> +	}
> +
> +	switch (bcm590xx->pmu_id) {
> +	case BCM590XX_PMUID_BCM59054:
> +		irq_chip = &bcm59054_irq_chip;
> +		break;
> +	case BCM590XX_PMUID_BCM59056:
> +		irq_chip = &bcm59056_irq_chip;
> +		break;
> +	default:
> +		dev_err(bcm590xx->dev,
> +			"Unknown device type, this is a driver bug!\n");

Prevent the wrap here.

No, this is not a driver bug.

Just "Unsupported device type %d" will be fine.

> +		return -EINVAL;
> +	}
> +
> +	ret = devm_regmap_add_irq_chip(bcm590xx->dev, bcm590xx->regmap_pri,
> +			bcm590xx->irq, IRQF_TRIGGER_FALLING, 0,
> +			irq_chip, &bcm590xx->irq_data);
> +	if (ret) {
> +		dev_err(bcm590xx->dev, "Failed to reguest IRQ %d: %d\n",

"Failed to add IRQ Chip for IRQ: %d (%d)"

> +			bcm590xx->irq, ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +/** Chip version parsing **/

Not needed.

>  /* Map PMU ID value to model name string */
>  static const char * const bcm590xx_names[] = {
>  	[BCM590XX_PMUID_BCM59054] = "BCM59054",
> @@ -98,6 +374,7 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
>  
>  	i2c_set_clientdata(i2c_pri, bcm590xx);
>  	bcm590xx->dev = &i2c_pri->dev;
> +	bcm590xx->irq = i2c_pri->irq;
>  	bcm590xx->i2c_pri = i2c_pri;
>  
>  	bcm590xx->pmu_id = (uintptr_t) of_device_get_match_data(bcm590xx->dev);
> @@ -132,6 +409,10 @@ static int bcm590xx_i2c_probe(struct i2c_client *i2c_pri)
>  	if (ret)
>  		goto err;
>  
> +	ret = bcm590xx_irq_init(bcm590xx);
> +	if (ret)
> +		goto err;
> +
>  	ret = devm_mfd_add_devices(&i2c_pri->dev, -1, bcm590xx_devs,
>  				   ARRAY_SIZE(bcm590xx_devs), NULL, 0, NULL);
>  	if (ret < 0) {
> diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
> index 5a5783abd47b9a6bb6f9bb3a8cafddbd01aa7fcc..e6ea643766ab1a9d579c94605b54c53dc1d742d7 100644
> --- a/include/linux/mfd/bcm590xx.h
> +++ b/include/linux/mfd/bcm590xx.h
> @@ -50,6 +50,237 @@ struct bcm590xx {
>  	/* Chip revision, read from PMUREV reg */
>  	u8 rev_digital;
>  	u8 rev_analog;
> +
> +	/* Interrupts */
> +	int irq;
> +	struct regmap_irq_chip_data *irq_data;
> +};
> +
> +/* Interrupt handling helper functions */
> +
> +static inline int
> +bcm590xx_devm_request_irq(struct device *dev, struct bcm590xx *bcm590xx, int irq,
> +			  irq_handler_t handler, unsigned long flags,
> +			  const char *name, void *data)
> +{
> +	if (!bcm590xx->irq_data)
> +		return -EINVAL;
> +
> +	return devm_request_threaded_irq(dev,
> +				regmap_irq_get_virq(bcm590xx->irq_data, irq),
> +				NULL, handler, flags, name, data);
> +}
> +
> +static inline void
> +bcm590xx_devm_free_irq(struct device *dev, struct bcm590xx *bcm590xx, int irq,
> +		       void *data)
> +{
> +	if (!bcm590xx->irq_data)
> +		return;
> +
> +	devm_free_irq(dev, regmap_irq_get_virq(bcm590xx->irq_data, irq), data);
> +}

These functions are abstracted for the sake of abstraction.  Please remove.

> +/* BCM59054 IRQs */
> +
> +enum bcm59054_irq {
> +	BCM59054_IRQ_USBINS = 0,
> +	BCM59054_IRQ_USBRM,
> +	BCM59054_IRQ_BATINS,
> +	BCM59054_IRQ_BATRM,
> +	BCM59054_IRQ_MBC_CV_LOOP,
> +	BCM59054_IRQ_MBC_CV_TMR_EXP,
> +	BCM59054_IRQ_EOC,
> +	BCM59054_IRQ_RESUME_VBUS,
> +	BCM59054_IRQ_MBTEMPLOW,
> +	BCM59054_IRQ_MBTEMPHIGH,
> +	BCM59054_IRQ_USBOV,
> +	BCM59054_IRQ_MBOV,
> +	BCM59054_IRQ_CHGERRDIS,
> +	BCM59054_IRQ_MBOV_DIS,
> +	BCM59054_IRQ_USBOV_DIS,
> +	BCM59054_IRQ_MBC_TF,
> +	BCM59054_IRQ_CHG_HW_TTR_EXP,
> +	BCM59054_IRQ_CHG_HW_TCH_EXP,
> +	BCM59054_IRQ_CHG_SW_TMR_EXP,
> +	BCM59054_IRQ_CHG_TCH_1MIN_BF_EXP,
> +	BCM59054_IRQ_USB_PORT_DIS,
> +	BCM59054_IRQ_USB_CC_REDUCE,
> +	BCM59054_IRQ_VBUSLOWBND,
> +	BCM59054_IRQ_UBPD_CHG_F,
> +	BCM59054_IRQ_VBUS_VALID_F,
> +	BCM59054_IRQ_OTG_SESS_VALID_F,
> +	BCM59054_IRQ_VB_SESS_END_F,
> +	BCM59054_IRQ_ID_RM,
> +	BCM59054_IRQ_VBUS_VALID_R,
> +	BCM59054_IRQ_VA_SESS_VALID_R,
> +	BCM59054_IRQ_VB_SESS_END_R,
> +	BCM59054_IRQ_ID_INS,
> +	BCM59054_IRQ_IDCHG,
> +	BCM59054_IRQ_RIC_C_TO_FLOAT,
> +	BCM59054_IRQ_CHGDET_LATCH,
> +	BCM59054_IRQ_CHGDET_TO,
> +	BCM59054_IRQ_ADP_CHANGE,
> +	BCM59054_IRQ_ADP_SNS_END,
> +	BCM59054_IRQ_ADP_PROB,
> +	BCM59054_IRQ_ADP_PRB_ERR,
> +	BCM59054_IRQ_POK_PRESSED,
> +	BCM59054_IRQ_POK_RELEASED,
> +	BCM59054_IRQ_POK_WAKEUP,
> +	BCM59054_IRQ_POK_BIT_VLD,
> +	BCM59054_IRQ_POK_RESTART,
> +	BCM59054_IRQ_POK_T1,
> +	BCM59054_IRQ_POK_T2,
> +	BCM59054_IRQ_POK_T3,
> +	BCM59054_IRQ_I2C_RESTART,
> +	BCM59054_IRQ_GBAT_PLUG_IN,
> +	BCM59054_IRQ_SMPL_INT,
> +	BCM59054_IRQ_AUX_INS,
> +	BCM59054_IRQ_AUX_RM,
> +	BCM59054_IRQ_XTAL_FAILURE,
> +	BCM59054_IRQ_MBWV_R_10S_WAIT,
> +	BCM59054_IRQ_MBWV_F,
> +	BCM59054_IRQ_RTC_ALARM,
> +	BCM59054_IRQ_RTC_SEC,
> +	BCM59054_IRQ_RTC_MIN,
> +	BCM59054_IRQ_RTCADJ,
> +	BCM59054_IRQ_FGC,
> +	BCM59054_IRQ_BBLOW,
> +	BCM59054_IRQ_DIE_OT_R,
> +	BCM59054_IRQ_DIE_OT_F,
> +	BCM59054_IRQ_RTM_DATA_RDY,
> +	BCM59054_IRQ_RTM_IN_CON_MEAS,
> +	BCM59054_IRQ_RTM_UPPER,
> +	BCM59054_IRQ_RTM_IGNORE,
> +	BCM59054_IRQ_RTM_OVERRIDDEN,
> +	BCM59054_IRQ_AUD_HSAB_SHCKT,
> +	BCM59054_IRQ_AUD_IHFD_SHCKT,
> +	BCM59054_IRQ_POK_NOP,
> +	BCM59054_IRQ_MIPI_LEN_ERR,
> +	BCM59054_IRQ_MIPI_RCV_ERR,
> +	BCM59054_IRQ_MIPI_BUSQ_RESP,
> +	BCM59054_IRQ_MIPI_BUSQ_POS,
> +	BCM59054_IRQ_MIPI_EOT,
> +	BCM59054_IRQ_MIPI_XMT_END,
> +	BCM59054_IRQ_MIPI_INT_POS,
> +	BCM59054_IRQ_LOWBAT,
> +	BCM59054_IRQ_CSROVRI,
> +	BCM59054_IRQ_VSROVRI,
> +	BCM59054_IRQ_MSROVRI,
> +	BCM59054_IRQ_SDSR1OVRI,
> +	BCM59054_IRQ_SDSR2OVRI,
> +	BCM59054_IRQ_IOSR1OVRI,
> +	BCM59054_IRQ_IOSR2OVRI,
> +	BCM59054_IRQ_RESERVED,
> +	BCM59054_IRQ_RFLDO_OVRI,
> +	BCM59054_IRQ_AUDLDO_OVRI,
> +	BCM59054_IRQ_USBLDO_OVR,
> +	BCM59054_IRQ_SDXLDO_OVRI,
> +	BCM59054_IRQ_MICLDO_OVRI,
> +	BCM59054_IRQ_SIMLDO1_OVRI,
> +	BCM59054_IRQ_SIMLDO2_OVRI,
> +	BCM59054_IRQ_MMCLDO1_OVRI,
> +	BCM59054_IRQ_CAMLDO1_OVRI,
> +	BCM59054_IRQ_CAMLDO2_OVRI,
> +	BCM59054_IRQ_VIBLDO_OVRI,
> +	BCM59054_IRQ_SDLDO_OVRI,
> +	BCM59054_IRQ_GPLDO1_OVRI,
> +	BCM59054_IRQ_GPLDO2_OVRI,
> +	BCM59054_IRQ_GPLDO3_OVRI,
> +	BCM59054_IRQ_RFLDO_SHD,
> +	BCM59054_IRQ_AUDLDO_SHD,
> +	BCM59054_IRQ_USBLDO_SHD,
> +	BCM59054_IRQ_SDXLDO_SHD,
> +	BCM59054_IRQ_MICLDO_SHD,
> +	BCM59054_IRQ_SIMLDO1_SHD,
> +	BCM59054_IRQ_SIMLDO2_SHD,
> +	BCM59054_IRQ_MMCLDO1_SHD,
> +	BCM59054_IRQ_MMCLDO2_SHD,
> +	BCM59054_IRQ_CAMLDO1_SHD,
> +	BCM59054_IRQ_CAMLDO2_SHD,
> +	BCM59054_IRQ_VIBLDO_SHD,
> +	BCM59054_IRQ_SDLDO_SHD,
> +	BCM59054_IRQ_GPLDO1_SHD,
> +	BCM59054_IRQ_GPLDO2_SHD,
> +	BCM59054_IRQ_GPLDO3_SHD,
> +	BCM59054_IRQ_TCXLDO_OVRI,
> +	BCM59054_IRQ_LVLDO1_OVRI,
> +	BCM59054_IRQ_LVLDO2_OVRI,
> +	BCM59054_IRQ_TCXLDO_SHD,
> +	BCM59054_IRQ_LVLDO1_SHD,
> +	BCM59054_IRQ_LVLDO2_SHD,
> +	BCM59054_IRQ_VBOVRV,
> +	BCM59054_IRQ_VBOVRI,
> +	BCM59054_IRQ_MAX,
> +};
> +
> +/* BCM59056 IRQs */
> +
> +enum bcm59056_irq {
> +	BCM59056_IRQ_RTC_ALARM = 0,
> +	BCM59056_IRQ_RTC_SEC,
> +	BCM59056_IRQ_RTC_MIN,
> +	BCM59056_IRQ_RTCADJ,
> +	BCM59056_IRQ_BATINS,
> +	BCM59056_IRQ_BATRM,
> +	BCM59056_IRQ_GBAT_PLUG_IN,
> +	BCM59056_IRQ_SMPL_INT,
> +	BCM59056_IRQ_USBINS,
> +	BCM59056_IRQ_USBRM,
> +	BCM59056_IRQ_USBOV,
> +	BCM59056_IRQ_EOC,
> +	BCM59056_IRQ_RESUME_VBUS,
> +	BCM59056_IRQ_CHG_HW_TTR_EXP,
> +	BCM59056_IRQ_CHG_HW_TCH_EXP,
> +	BCM59056_IRQ_CHG_SW_TMR_EXP,
> +	BCM59056_IRQ_CHGDET_LATCH,
> +	BCM59056_IRQ_CHGDET_TO,
> +	BCM59056_IRQ_MBTEMPLOW,
> +	BCM59056_IRQ_MBTEMPHIGH,
> +	BCM59056_IRQ_MBOV,
> +	BCM59056_IRQ_MBOV_DIS,
> +	BCM59056_IRQ_USBOV_DIS,
> +	BCM59056_IRQ_CHGERRDIS,
> +	BCM59056_IRQ_VBUS_1V5_R,
> +	BCM59056_IRQ_VBUS_4V5_R,
> +	BCM59056_IRQ_VBUS_1V5_F,
> +	BCM59056_IRQ_VBUS_4V5_F,
> +	BCM59056_IRQ_MBWV_R_10S_WAIT,
> +	BCM59056_IRQ_BBLOW,
> +	BCM59056_IRQ_LOWBAT,
> +	BCM59056_IRQ_VERYLOWBAT,
> +	BCM59056_IRQ_RTM_DATA_RDY,
> +	BCM59056_IRQ_RTM_IN_CON_MEAS,
> +	BCM59056_IRQ_RTM_UPPER,
> +	BCM59056_IRQ_RTM_IGNORE,
> +	BCM59056_IRQ_RTM_OVERRIDDEN,
> +	BCM59056_IRQ_AUD_HSAB_SHCKT,
> +	BCM59056_IRQ_AUD_IHFD_SHCKT,
> +	BCM59056_IRQ_MBC_TF,
> +	BCM59056_IRQ_CSROVRI,
> +	BCM59056_IRQ_IOSROVRI,
> +	BCM59056_IRQ_SDSROVRI,
> +	BCM59056_IRQ_ASROVRI,
> +	BCM59056_IRQ_UBPD_CHG_F,
> +	BCM59056_IRQ_ACD_INS,
> +	BCM59056_IRQ_ACD_RM,
> +	BCM59056_IRQ_PONKEYB_HOLD,
> +	BCM59056_IRQ_PONKEYB_F,
> +	BCM59056_IRQ_PONKEYB_R,
> +	BCM59056_IRQ_PONKEYB_OFFHOLD,
> +	BCM59056_IRQ_PONKEYB_RESTART,
> +	BCM59056_IRQ_IDCHG,
> +	BCM59056_IRQ_JIG_USB_INS,
> +	BCM59056_IRQ_UART_INS,
> +	BCM59056_IRQ_ID_INS,
> +	BCM59056_IRQ_ID_RM,
> +	BCM59056_IRQ_ADP_CHANGE,
> +	BCM59056_IRQ_ADP_SNS_END,
> +	BCM59056_IRQ_SESSION_END_VLD,
> +	BCM59056_IRQ_SESSION_END_INVLD,
> +	BCM59056_IRQ_VBUS_OVERCURRENT,
> +	BCM59056_IRQ_FGC,
> +	BCM59056_IRQ_MAX,
>  };
>  
>  #endif /*  __LINUX_MFD_BCM590XX_H */
> 
> ---
> base-commit: 038d61fd642278bab63ee8ef722c50d10ab01e8f
> change-id: 20250816-bcm590xx-irq-2d4c1cbe00b1
> 
> Best regards,
> -- 
> Artur Weber <aweber.kernel@gmail.com>
> 

-- 
Lee Jones [李琼斯]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] mfd: bcm590xx: Add support for interrupt handling
  2025-09-02  7:50 ` Lee Jones
@ 2025-09-02 15:23   ` Artur Weber
  0 siblings, 0 replies; 3+ messages in thread
From: Artur Weber @ 2025-09-02 15:23 UTC (permalink / raw)
  To: Lee Jones; +Cc: linux-kernel, ~postmarketos/upstreaming, Stanislav Jakubek



On 9/2/25 09:50, Lee Jones wrote:
> On Sat, 16 Aug 2025, Artur Weber wrote:
> 
>> The BCM590XX supports up to 128 internal interrupts, which are used by
>> various parts of the chip. Add regmap_irq-based interrupt handling and
>> helper functions to allow subdevice drivers to easily use the interrupts.
>>
>> Signed-off-by: Artur Weber <aweber.kernel@gmail.com>
>> ---
>> This patch is a prerequisite for future subdevice additions, since
>> many of them rely on the interrupts; I have a power-on key driver and
>> an RTC driver ready which both use the IRQ data/helper functions included
>> in this patch (they will be sent in subsequent patch series), and more
>> are on the way.

(...)

>> diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
>> index 5a8456bbd63f65b9260f05ef6546c026bf822bae..d688abd08c12b621a38586650843e55bd71ca715 100644
>> --- a/drivers/mfd/bcm590xx.c
>> +++ b/drivers/mfd/bcm590xx.c
>> @@ -26,16 +26,30 @@
>>   #define BCM590XX_PMUREV_ANA_MASK	0xF0
>>   #define BCM590XX_PMUREV_ANA_SHIFT	4
>>   
>> +#define BCM590XX_REG_IRQ1		0x20
>> +#define BCM590XX_REG_IRQ1_MASK		0x30
> 
> REG and MASK mean different things.  What is it?

IRQ1_MASK is the corresponding IRQ mask register for IRQ1. I agree that
the naming is confusing, would "IRQ1MASK" (without the underscore
separator) sound better?

> 
>> +
>>   static const struct mfd_cell bcm590xx_devs[] = {
>>   	{
>>   		.name = "bcm590xx-vregs",
>>   	},
>>   };
>>   
>> +static bool bcm590xx_volatile_pri(struct device *dev, unsigned int reg)
> 
> What does pri mean?

Primary I2C subdev/regmap, named after the bcm590xx_regmap_config_pri
struct (where the BCM590XX_REGMAP_PRI/SEC constants got their name as
well). Should I add a comment here?

> 
>> +{
>> +	/*
>> +	 * IRQ registers are clear-on-read, make sure we don't cache them
>> +	 * so that they get read/cleared correctly
>> +	 */
>> +	return (reg >= BCM590XX_REG_IRQ1 &&
>> +		reg <= (BCM590XX_REG_IRQ1 + 15));
> 
> Use up to 100-chars to prevent these line feeds.

Ack, will fix this.

> 
>> +}
>> +
>>   static const struct regmap_config bcm590xx_regmap_config_pri = {
>>   	.reg_bits	= 8,
>>   	.val_bits	= 8,
>>   	.max_register	= BCM590XX_MAX_REGISTER_PRI,
>> +	.volatile_reg	= bcm590xx_volatile_pri,
>>   	.cache_type	= REGCACHE_MAPLE,
>>   };
>>   
>> @@ -46,6 +60,268 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
>>   	.cache_type	= REGCACHE_MAPLE,
>>   };
>>   
>> +/** Interrupt handling **/
> 
> This is obvious with the alerting header comment.
IMO it makes scrolling through the driver code a bit less confusing (the
interrupt list is clearly split from the regmap config and later model
detection and probe code), but I'll remove it if needed.>
>> +/* IRQ IDs in the MFD header follow the IRQ order in hardware. */
> 
> Not sure I the helpfulness of this comment.

Indeed I suppose it's not particularily helpful. I'll remove it.

> 
>> +#define BCM590XX_REGMAP_IRQ_REG(id)	REGMAP_IRQ_REG_LINE(id, 8)
> 
> What does the 8 mean?

IRQ register width - 8-bit wide registers. Each IRQ gets one bit for
status in the IRQx registers, and one bit for mask in the IRQxMASK
registers. See REGMAP_IRQ_REG_LINE in include/linux/regmap.h.

> 
>> +
>> +/* BCM59054 IRQs */
> 
> We can see this by the nomenclature.

(...)

>> +/* BCM59056 IRQs */
> 
> As above.
> 

Ack, will drop these.
>> +	switch (bcm590xx->pmu_id) {
>> +	case BCM590XX_PMUID_BCM59054:
>> +		irq_chip = &bcm59054_irq_chip;
>> +		break;
>> +	case BCM590XX_PMUID_BCM59056:
>> +		irq_chip = &bcm59056_irq_chip;
>> +		break;
>> +	default:
>> +		dev_err(bcm590xx->dev,
>> +			"Unknown device type, this is a driver bug!\n");
> 
> Prevent the wrap here.
> 
> No, this is not a driver bug.
> 
> Just "Unsupported device type %d" will be fine.
Ack, I'll reword the message.

> 
>> +		return -EINVAL;
>> +	}
>> +
>> +	ret = devm_regmap_add_irq_chip(bcm590xx->dev, bcm590xx->regmap_pri,
>> +			bcm590xx->irq, IRQF_TRIGGER_FALLING, 0,
>> +			irq_chip, &bcm590xx->irq_data);
>> +	if (ret) {
>> +		dev_err(bcm590xx->dev, "Failed to reguest IRQ %d: %d\n",
> 
> "Failed to add IRQ Chip for IRQ: %d (%d)"
> 
>> +			bcm590xx->irq, ret);
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +/** Chip version parsing **/
> 
> Not needed.
> 

See my reply to "/** Interrupt handling **/" comment part.

(...)
>> diff --git a/include/linux/mfd/bcm590xx.h b/include/linux/mfd/bcm590xx.h
>> index 5a5783abd47b9a6bb6f9bb3a8cafddbd01aa7fcc..e6ea643766ab1a9d579c94605b54c53dc1d742d7 100644
>> --- a/include/linux/mfd/bcm590xx.h
>> +++ b/include/linux/mfd/bcm590xx.h
>> @@ -50,6 +50,237 @@ struct bcm590xx {
>>   	/* Chip revision, read from PMUREV reg */
>>   	u8 rev_digital;
>>   	u8 rev_analog;
>> +
>> +	/* Interrupts */
>> +	int irq;
>> +	struct regmap_irq_chip_data *irq_data;
>> +};
>> +
>> +/* Interrupt handling helper functions */
>> +
>> +static inline int
>> +bcm590xx_devm_request_irq(struct device *dev, struct bcm590xx *bcm590xx, int irq,
>> +			  irq_handler_t handler, unsigned long flags,
>> +			  const char *name, void *data)
>> +{
>> +	if (!bcm590xx->irq_data)
>> +		return -EINVAL;
>> +
>> +	return devm_request_threaded_irq(dev,
>> +				regmap_irq_get_virq(bcm590xx->irq_data, irq),
>> +				NULL, handler, flags, name, data);
>> +}
>> +
>> +static inline void
>> +bcm590xx_devm_free_irq(struct device *dev, struct bcm590xx *bcm590xx, int irq,
>> +		       void *data)
>> +{
>> +	if (!bcm590xx->irq_data)
>> +		return;
>> +
>> +	devm_free_irq(dev, regmap_irq_get_virq(bcm590xx->irq_data, irq), data);
>> +}
> 
> These functions are abstracted for the sake of abstraction.  Please remove.

OK, will do.

Best regards
Artur

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2025-09-02 15:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-08-16 16:03 [PATCH] mfd: bcm590xx: Add support for interrupt handling Artur Weber
2025-09-02  7:50 ` Lee Jones
2025-09-02 15:23   ` Artur Weber

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).