drivers/mfd/Kconfig | 1 + drivers/mfd/bcm590xx.c | 270 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/bcm590xx.h | 206 +++++++++++++++++++++++++++++++++ 3 files changed, 477 insertions(+)
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.
---
Changes in v3:
- Address review comments from Lee Jones
- Link to v2: https://lore.kernel.org/r/20250901-bcm590xx-irq-v2-1-c593ca23b63c@gmail.com
Changes in v2:
- Rename xSROVRI IRQs to xSR_OVRI to match LDO_OVRI naming
- Link to v1: https://lore.kernel.org/r/20250816-bcm590xx-irq-v1-1-ccbb490628dd@gmail.com
---
Changes in v3:
- Rename REG_IRQ1_MASK to REG_IRQ1MASK, to make it more obvious
that it's a register name, not a mask
- Drop bcm590xx_devm_request_irq and bcm590xx_devm_free_irq
- Unwrap some lines to adjust to 100 character line lengths
- Drop useless comments
Changes in v2:
- Rename xSROVRI IRQs to xSR_OVRI to match LDO_OVRI naming
---
drivers/mfd/Kconfig | 1 +
drivers/mfd/bcm590xx.c | 270 +++++++++++++++++++++++++++++++++++++++++++
include/linux/mfd/bcm590xx.h | 206 +++++++++++++++++++++++++++++++++
3 files changed, 477 insertions(+)
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 6fb3768e3d71..e76b18e29dbc 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 5a8456bbd63f..fb6afe277ebf 100644
--- a/drivers/mfd/bcm590xx.c
+++ b/drivers/mfd/bcm590xx.c
@@ -26,16 +26,29 @@
#define BCM590XX_PMUREV_ANA_MASK 0xF0
#define BCM590XX_PMUREV_ANA_SHIFT 4
+#define BCM590XX_REG_IRQ1 0x20
+#define BCM590XX_REG_IRQ1MASK 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 +59,258 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
.cache_type = REGCACHE_MAPLE,
};
+#define BCM590XX_REGMAP_IRQ_REG(id) REGMAP_IRQ_REG_LINE(id, 8)
+
+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_CSR_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VSR_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MSR_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR1_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR2_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR1_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR2_OVRI),
+ 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_IRQ1MASK,
+ .clear_on_unmask = true,
+};
+
+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_CSR_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_IOSR_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SDSR_OVRI),
+ BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ASR_OVRI),
+ 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_IRQ1MASK,
+ .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 %d\n", bcm590xx->pmu_id);
+ 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 add IRQ chip for IRQ: %d: %d\n",
+ bcm590xx->irq, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/* Map PMU ID value to model name string */
static const char * const bcm590xx_names[] = {
[BCM590XX_PMUID_BCM59054] = "BCM59054",
@@ -98,6 +363,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 +398,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 5a5783abd47b..96c7b1066365 100644
--- a/include/linux/mfd/bcm590xx.h
+++ b/include/linux/mfd/bcm590xx.h
@@ -50,6 +50,212 @@ struct bcm590xx {
/* Chip revision, read from PMUREV reg */
u8 rev_digital;
u8 rev_analog;
+
+ /* Interrupts */
+ int irq;
+ struct regmap_irq_chip_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_CSR_OVRI,
+ BCM59054_IRQ_VSR_OVRI,
+ BCM59054_IRQ_MSR_OVRI,
+ BCM59054_IRQ_SDSR1_OVRI,
+ BCM59054_IRQ_SDSR2_OVRI,
+ BCM59054_IRQ_IOSR1_OVRI,
+ BCM59054_IRQ_IOSR2_OVRI,
+ 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_CSR_OVRI,
+ BCM59056_IRQ_IOSR_OVRI,
+ BCM59056_IRQ_SDSR_OVRI,
+ BCM59056_IRQ_ASR_OVRI,
+ 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>
On Mon, 13 Oct 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.
> ---
> Changes in v3:
> - Address review comments from Lee Jones
> - Link to v2: https://lore.kernel.org/r/20250901-bcm590xx-irq-v2-1-c593ca23b63c@gmail.com
>
> Changes in v2:
> - Rename xSROVRI IRQs to xSR_OVRI to match LDO_OVRI naming
> - Link to v1: https://lore.kernel.org/r/20250816-bcm590xx-irq-v1-1-ccbb490628dd@gmail.com
> ---
> Changes in v3:
> - Rename REG_IRQ1_MASK to REG_IRQ1MASK, to make it more obvious
> that it's a register name, not a mask
> - Drop bcm590xx_devm_request_irq and bcm590xx_devm_free_irq
> - Unwrap some lines to adjust to 100 character line lengths
> - Drop useless comments
>
> Changes in v2:
> - Rename xSROVRI IRQs to xSR_OVRI to match LDO_OVRI naming
> ---
> drivers/mfd/Kconfig | 1 +
> drivers/mfd/bcm590xx.c | 270 +++++++++++++++++++++++++++++++++++++++++++
> include/linux/mfd/bcm590xx.h | 206 +++++++++++++++++++++++++++++++++
> 3 files changed, 477 insertions(+)
>
> diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
> index 6fb3768e3d71..e76b18e29dbc 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 5a8456bbd63f..fb6afe277ebf 100644
> --- a/drivers/mfd/bcm590xx.c
> +++ b/drivers/mfd/bcm590xx.c
> @@ -26,16 +26,29 @@
> #define BCM590XX_PMUREV_ANA_MASK 0xF0
> #define BCM590XX_PMUREV_ANA_SHIFT 4
>
> +#define BCM590XX_REG_IRQ1 0x20
> +#define BCM590XX_REG_IRQ1MASK 0x30
This isn't better.
And now the nomenclature is inconsistent with the one above.
What is a mask register? I don't understand.
> static const struct mfd_cell bcm590xx_devs[] = {
> {
> .name = "bcm590xx-vregs",
> },
> };
>
> +static bool bcm590xx_volatile_pri(struct device *dev, unsigned int reg)
If I've asked a question or showed uncertainty about something, it
usually means that changes need to be made. Asking what "pri" meant
wasn't a one time thing. It shows that something is not clear and if
I'm asking, others will wonder too.
Can we change 'sec' to 'secondary' and 'pri' to 'primary' please?
> +{
> + /*
> + * 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 +59,258 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
> .cache_type = REGCACHE_MAPLE,
> };
>
> +#define BCM590XX_REGMAP_IRQ_REG(id) REGMAP_IRQ_REG_LINE(id, 8)
It looks like this may benefit more than just this driver.
Please create a generic helper in include/linux/regmap.h.
Perhaps REGMAP_IRQ_REG_LINE_BYTE, or whatever the 8 represents.
> +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_CSR_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_VSR_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_MSR_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR1_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_SDSR2_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR1_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59054_IRQ_IOSR2_OVRI),
> + 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),
> +};
Wow! These lists are intense.
It's a shame we don't support ranges!
> +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_IRQ1MASK,
> + .clear_on_unmask = true,
> +};
> +
> +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_CSR_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_IOSR_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_SDSR_OVRI),
> + BCM590XX_REGMAP_IRQ_REG(BCM59056_IRQ_ASR_OVRI),
> + 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_IRQ1MASK,
> + .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 %d\n", bcm590xx->pmu_id);
> + 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 add IRQ chip for IRQ: %d: %d\n",
> + bcm590xx->irq, ret);
> + return ret;
> + }
> +
> + return 0;
> +}
> +
> /* Map PMU ID value to model name string */
> static const char * const bcm590xx_names[] = {
> [BCM590XX_PMUID_BCM59054] = "BCM59054",
> @@ -98,6 +363,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 +398,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 5a5783abd47b..96c7b1066365 100644
> --- a/include/linux/mfd/bcm590xx.h
> +++ b/include/linux/mfd/bcm590xx.h
> @@ -50,6 +50,212 @@ struct bcm590xx {
> /* Chip revision, read from PMUREV reg */
> u8 rev_digital;
> u8 rev_analog;
> +
> + /* Interrupts */
> + int irq;
> + struct regmap_irq_chip_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_CSR_OVRI,
> + BCM59054_IRQ_VSR_OVRI,
> + BCM59054_IRQ_MSR_OVRI,
> + BCM59054_IRQ_SDSR1_OVRI,
> + BCM59054_IRQ_SDSR2_OVRI,
> + BCM59054_IRQ_IOSR1_OVRI,
> + BCM59054_IRQ_IOSR2_OVRI,
> + 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_CSR_OVRI,
> + BCM59056_IRQ_IOSR_OVRI,
> + BCM59056_IRQ_SDSR_OVRI,
> + BCM59056_IRQ_ASR_OVRI,
> + 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 [李琼斯]
On 23.10.2025 15:03, Lee Jones wrote:
> On Mon, 13 Oct 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>
>>
>> (...)>>
>> diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
>> index 5a8456bbd63f..fb6afe277ebf 100644
>> --- a/drivers/mfd/bcm590xx.c
>> +++ b/drivers/mfd/bcm590xx.c
>> @@ -26,16 +26,29 @@
>> #define BCM590XX_PMUREV_ANA_MASK 0xF0
>> #define BCM590XX_PMUREV_ANA_SHIFT 4
>>
>> +#define BCM590XX_REG_IRQ1 0x20
>> +#define BCM590XX_REG_IRQ1MASK 0x30
>
> This isn't better.
>
> And now the nomenclature is inconsistent with the one above.
>
> What is a mask register? I don't understand.
The IRQxMASK registers store the interrupt masks for each interrupt. To
explain this more clearly:
The BCM590xx chips have up to 128 internal interrupts (the exact number
is different between the BCM59054 and BCM59056, but both reserve the
exact same amount of registers for them).
The status of each interrupt is stored in the IRQx registers
(0x20-0x2f), and each bit represents a single interrupt.
The interrupt masks (that is, whether the interrupt is enabled or
disabled) are stored in the IRQx_MASK registers (0x30-0x3f), and each
bit represents the mask for a single interrupt, in the same order as the
IRQx registers. (...would IRQMASKx be more consistent?)
Each register stores 8 bits of data, meaning the {status, mask} for 8
interrupts can fit into one {status, mask} register.
>
>> +{
>> + /*
>> + * 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 +59,258 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
>> .cache_type = REGCACHE_MAPLE,
>> };
>>
>> +#define BCM590XX_REGMAP_IRQ_REG(id) REGMAP_IRQ_REG_LINE(id, 8)
>
> It looks like this may benefit more than just this driver.
>
> Please create a generic helper in include/linux/regmap.h.
>
> Perhaps REGMAP_IRQ_REG_LINE_BYTE, or whatever the 8 represents.
I would rather avoid modifying the regmap code if possible.
I've seen another driver (drivers/power/supply/max77705_charger.c) use
REGMAP_IRQ_REG_LINE(id, BITS_PER_BYTE), which is more descriptive than
just leaving the raw number of bits. Would that be a good alternative?
Best regards
Artur
On Wed, 29 Oct 2025, Artur Weber wrote:
> On 23.10.2025 15:03, Lee Jones wrote:
> > On Mon, 13 Oct 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>
> > >
> > > (...)>>
> > > diff --git a/drivers/mfd/bcm590xx.c b/drivers/mfd/bcm590xx.c
> > > index 5a8456bbd63f..fb6afe277ebf 100644
> > > --- a/drivers/mfd/bcm590xx.c
> > > +++ b/drivers/mfd/bcm590xx.c
> > > @@ -26,16 +26,29 @@
> > > #define BCM590XX_PMUREV_ANA_MASK 0xF0
> > > #define BCM590XX_PMUREV_ANA_SHIFT 4
> > > +#define BCM590XX_REG_IRQ1 0x20
> > > +#define BCM590XX_REG_IRQ1MASK 0x30
> >
> > This isn't better.
> >
> > And now the nomenclature is inconsistent with the one above.
> >
> > What is a mask register? I don't understand.
>
> The IRQxMASK registers store the interrupt masks for each interrupt. To
> explain this more clearly:
>
> The BCM590xx chips have up to 128 internal interrupts (the exact number
> is different between the BCM59054 and BCM59056, but both reserve the
> exact same amount of registers for them).
>
> The status of each interrupt is stored in the IRQx registers
> (0x20-0x2f), and each bit represents a single interrupt.
>
> The interrupt masks (that is, whether the interrupt is enabled or
> disabled) are stored in the IRQx_MASK registers (0x30-0x3f), and each
> bit represents the mask for a single interrupt, in the same order as the
> IRQx registers. (...would IRQMASKx be more consistent?)
>
> Each register stores 8 bits of data, meaning the {status, mask} for 8
> interrupts can fit into one {status, mask} register.
Okay, so the "MASK" thing is just silly naming by the H/W designers?
STATUS or ENABLE sounds like it would be better, since a "mask" to me is
a software term which describes the methods for manipulating these kinds
of groups of bits.
> > > +{
> > > + /*
> > > + * 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 +59,258 @@ static const struct regmap_config bcm590xx_regmap_config_sec = {
> > > .cache_type = REGCACHE_MAPLE,
> > > };
> > > +#define BCM590XX_REGMAP_IRQ_REG(id) REGMAP_IRQ_REG_LINE(id, 8)
> >
> > It looks like this may benefit more than just this driver.
> >
> > Please create a generic helper in include/linux/regmap.h.
> >
> > Perhaps REGMAP_IRQ_REG_LINE_BYTE, or whatever the 8 represents.
>
> I would rather avoid modifying the regmap code if possible.
Why not?
> I've seen another driver (drivers/power/supply/max77705_charger.c) use
> REGMAP_IRQ_REG_LINE(id, BITS_PER_BYTE), which is more descriptive than
> just leaving the raw number of bits. Would that be a good alternative?
Sounds fine to me.
--
Lee Jones [李琼斯]
© 2016 - 2025 Red Hat, Inc.