drivers/mfd/Kconfig | 1 + drivers/mfd/bcm590xx.c | 281 +++++++++++++++++++++++++++++++++++++++++++ include/linux/mfd/bcm590xx.h | 231 +++++++++++++++++++++++++++++++++++ 3 files changed, 513 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.
---
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>
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 [李琼斯]
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
© 2016 - 2025 Red Hat, Inc.