lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251114-s2mu005-pmic-v1-6-9e3184d3a0c9@disroot.org>
Date: Fri, 14 Nov 2025 00:35:07 +0530
From: Kaustabh Chakraborty <kauschluss@...root.org>
To: Lee Jones <lee@...nel.org>, Pavel Machek <pavel@...nel.org>, 
 Rob Herring <robh@...nel.org>, Krzysztof Kozlowski <krzk+dt@...nel.org>, 
 Conor Dooley <conor+dt@...nel.org>, MyungJoo Ham <myungjoo.ham@...sung.com>, 
 Chanwoo Choi <cw00.choi@...sung.com>, Sebastian Reichel <sre@...nel.org>, 
 Krzysztof Kozlowski <krzk@...nel.org>, 
 André Draszik <andre.draszik@...aro.org>, 
 Alexandre Belloni <alexandre.belloni@...tlin.com>, 
 Jonathan Corbet <corbet@....net>
Cc: linux-leds@...r.kernel.org, devicetree@...r.kernel.org, 
 linux-kernel@...r.kernel.org, linux-pm@...r.kernel.org, 
 linux-samsung-soc@...r.kernel.org, linux-rtc@...r.kernel.org, 
 linux-doc@...r.kernel.org, Kaustabh Chakraborty <kauschluss@...root.org>
Subject: [PATCH 06/13] mfd: sec-irq: add support for creating multiple IRQ
 chips

The current state of the driver only allows creating only one IRQ chip
per PMIC. On some PMICs, such as Samsung's S2MU005, there are multiple
interrupt blocks, for which the current implementation stands insufficient.

Add support for creating multiple IRQ chips for a PMIC. Every IRQ chip is
given it's own index, which is used by sub-device drivers to request IRQs.

A macro is defined which states the maximum number of chips supported.
It's set to 1 as currently, no PMIC requires more than one IRQ chip. The
value must be changed accordingly on adding new PMICs requiring multiple
IRQ chips.

Moreover, adjust the s5m RTC driver to initialize IRQs with the
appropriate IRQ chip index.

Signed-off-by: Kaustabh Chakraborty <kauschluss@...root.org>
---
 drivers/mfd/sec-irq.c            | 163 +++++++++++++++++++++++----------------
 drivers/rtc/rtc-s5m.c            |  15 +++-
 include/linux/mfd/samsung/core.h |   5 +-
 include/linux/mfd/samsung/irq.h  |  14 ++++
 4 files changed, 127 insertions(+), 70 deletions(-)

diff --git a/drivers/mfd/sec-irq.c b/drivers/mfd/sec-irq.c
index c5c80b1ba104..053c28f31ec9 100644
--- a/drivers/mfd/sec-irq.c
+++ b/drivers/mfd/sec-irq.c
@@ -181,25 +181,31 @@ static const struct regmap_irq s5m8767_irqs[] = {
 };
 
 /* All S2MPG10 interrupt sources are read-only and don't require clearing */
-static const struct regmap_irq_chip s2mpg10_irq_chip = {
-	.name = "s2mpg10",
-	.irqs = s2mpg10_irqs,
-	.num_irqs = ARRAY_SIZE(s2mpg10_irqs),
-	.num_regs = 6,
-	.status_base = S2MPG10_PMIC_INT1,
-	.mask_base = S2MPG10_PMIC_INT1M,
+static const struct regmap_irq_chip s2mpg10_irq_chip[] = {
+	[S2MPG10_IRQ_CHIP] = {
+		.name = "s2mpg10",
+		.irqs = s2mpg10_irqs,
+		.num_irqs = ARRAY_SIZE(s2mpg10_irqs),
+		.num_regs = 6,
+		.status_base = S2MPG10_PMIC_INT1,
+		.mask_base = S2MPG10_PMIC_INT1M,
+	},
 };
 
-static const struct regmap_irq_chip s2mps11_irq_chip = {
-	.name = "s2mps11",
-	.irqs = s2mps11_irqs,
-	.num_irqs = ARRAY_SIZE(s2mps11_irqs),
-	.num_regs = 3,
-	.status_base = S2MPS11_REG_INT1,
-	.mask_base = S2MPS11_REG_INT1M,
-	.ack_base = S2MPS11_REG_INT1,
+static const struct regmap_irq_chip s2mps11_irq_chip[] = {
+	[S2MPS11_IRQ_CHIP] = {
+		.name = "s2mps11",
+		.irqs = s2mps11_irqs,
+		.num_irqs = ARRAY_SIZE(s2mps11_irqs),
+		.num_regs = 3,
+		.status_base = S2MPS11_REG_INT1,
+		.mask_base = S2MPS11_REG_INT1M,
+		.ack_base = S2MPS11_REG_INT1,
+	},
 };
 
+#define S2MPS1X_IRQ_CHIP		S2MPS14_IRQ_CHIP
+
 #define S2MPS1X_IRQ_CHIP_COMMON_DATA		\
 	.irqs = s2mps14_irqs,			\
 	.num_irqs = ARRAY_SIZE(s2mps14_irqs),	\
@@ -208,85 +214,106 @@ static const struct regmap_irq_chip s2mps11_irq_chip = {
 	.mask_base = S2MPS14_REG_INT1M,		\
 	.ack_base = S2MPS14_REG_INT1		\
 
-static const struct regmap_irq_chip s2mps13_irq_chip = {
-	.name = "s2mps13",
-	S2MPS1X_IRQ_CHIP_COMMON_DATA,
+static const struct regmap_irq_chip s2mps13_irq_chip[] = {
+	[S2MPS1X_IRQ_CHIP] = {
+		.name = "s2mps13",
+		S2MPS1X_IRQ_CHIP_COMMON_DATA,
+	},
 };
 
-static const struct regmap_irq_chip s2mps14_irq_chip = {
-	.name = "s2mps14",
-	S2MPS1X_IRQ_CHIP_COMMON_DATA,
+static const struct regmap_irq_chip s2mps14_irq_chip[] = {
+	[S2MPS1X_IRQ_CHIP] = {
+		.name = "s2mps14",
+		S2MPS1X_IRQ_CHIP_COMMON_DATA,
+	},
 };
 
-static const struct regmap_irq_chip s2mps15_irq_chip = {
-	.name = "s2mps15",
-	S2MPS1X_IRQ_CHIP_COMMON_DATA,
+static const struct regmap_irq_chip s2mps15_irq_chip[] = {
+	[S2MPS1X_IRQ_CHIP] = {
+		.name = "s2mps15",
+		S2MPS1X_IRQ_CHIP_COMMON_DATA,
+	},
 };
 
-static const struct regmap_irq_chip s2mpu02_irq_chip = {
-	.name = "s2mpu02",
-	.irqs = s2mpu02_irqs,
-	.num_irqs = ARRAY_SIZE(s2mpu02_irqs),
-	.num_regs = 3,
-	.status_base = S2MPU02_REG_INT1,
-	.mask_base = S2MPU02_REG_INT1M,
-	.ack_base = S2MPU02_REG_INT1,
+static const struct regmap_irq_chip s2mpu02_irq_chip[] = {
+	[S2MPU02_IRQ_CHIP] = {
+		.name = "s2mpu02",
+		.irqs = s2mpu02_irqs,
+		.num_irqs = ARRAY_SIZE(s2mpu02_irqs),
+		.num_regs = 3,
+		.status_base = S2MPU02_REG_INT1,
+		.mask_base = S2MPU02_REG_INT1M,
+		.ack_base = S2MPU02_REG_INT1,
+	},
 };
 
-static const struct regmap_irq_chip s2mpu05_irq_chip = {
-	.name = "s2mpu05",
-	.irqs = s2mpu05_irqs,
-	.num_irqs = ARRAY_SIZE(s2mpu05_irqs),
-	.num_regs = 3,
-	.status_base = S2MPU05_REG_INT1,
-	.mask_base = S2MPU05_REG_INT1M,
-	.ack_base = S2MPU05_REG_INT1,
+static const struct regmap_irq_chip s2mpu05_irq_chip[] = {
+	[S2MPU05_IRQ_CHIP] = {
+		.name = "s2mpu05",
+		.irqs = s2mpu05_irqs,
+		.num_irqs = ARRAY_SIZE(s2mpu05_irqs),
+		.num_regs = 3,
+		.status_base = S2MPU05_REG_INT1,
+		.mask_base = S2MPU05_REG_INT1M,
+		.ack_base = S2MPU05_REG_INT1,
+	},
 };
 
-static const struct regmap_irq_chip s5m8767_irq_chip = {
-	.name = "s5m8767",
-	.irqs = s5m8767_irqs,
-	.num_irqs = ARRAY_SIZE(s5m8767_irqs),
-	.num_regs = 3,
-	.status_base = S5M8767_REG_INT1,
-	.mask_base = S5M8767_REG_INT1M,
-	.ack_base = S5M8767_REG_INT1,
+static const struct regmap_irq_chip s5m8767_irq_chip[] = {
+	[S5M8767_IRQ_CHIP] = {
+		.name = "s5m8767",
+		.irqs = s5m8767_irqs,
+		.num_irqs = ARRAY_SIZE(s5m8767_irqs),
+		.num_regs = 3,
+		.status_base = S5M8767_REG_INT1,
+		.mask_base = S5M8767_REG_INT1M,
+		.ack_base = S5M8767_REG_INT1,
+	},
 };
 
 int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 {
 	const struct regmap_irq_chip *sec_irq_chip;
-	int ret;
+	int sec_irq_chip_num, i, ret;
 
 	switch (sec_pmic->device_type) {
 	case S5M8767X:
-		sec_irq_chip = &s5m8767_irq_chip;
+		sec_irq_chip = s5m8767_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s5m8767_irq_chip);
 		break;
 	case S2DOS05:
 		return 0;
 	case S2MPA01:
-		sec_irq_chip = &s2mps14_irq_chip;
+		sec_irq_chip = s2mps14_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mps14_irq_chip);
 		break;
 	case S2MPG10:
-		sec_irq_chip = &s2mpg10_irq_chip;
+		sec_irq_chip = s2mpg10_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mpg10_irq_chip);
 		break;
 	case S2MPS11X:
-		sec_irq_chip = &s2mps11_irq_chip;
+		sec_irq_chip = s2mps11_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mps11_irq_chip);
 		break;
 	case S2MPS13X:
-		sec_irq_chip = &s2mps13_irq_chip;
+		sec_irq_chip = s2mps13_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mps13_irq_chip);
 		break;
 	case S2MPS14X:
-		sec_irq_chip = &s2mps14_irq_chip;
+		sec_irq_chip = s2mps14_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mps14_irq_chip);
 		break;
 	case S2MPS15X:
-		sec_irq_chip = &s2mps15_irq_chip;
+		sec_irq_chip = s2mps15_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mps15_irq_chip);
 		break;
 	case S2MPU02:
-		sec_irq_chip = &s2mpu02_irq_chip;
+		sec_irq_chip = s2mpu02_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mpu02_irq_chip);
 		break;
 	case S2MPU05:
-		sec_irq_chip = &s2mpu05_irq_chip;
+		sec_irq_chip = s2mpu05_irq_chip;
+		sec_irq_chip_num = ARRAY_SIZE(s2mpu05_irq_chip);
 		break;
 	default:
 		return dev_err_probe(sec_pmic->dev, -EINVAL,
@@ -300,13 +327,19 @@ int sec_irq_init(struct sec_pmic_dev *sec_pmic)
 		return 0;
 	}
 
-	ret = devm_regmap_add_irq_chip(sec_pmic->dev, sec_pmic->regmap_pmic,
-				       sec_pmic->irq, IRQF_ONESHOT,
-				       0, sec_irq_chip, &sec_pmic->irq_data);
-	if (ret)
-		return dev_err_probe(sec_pmic->dev, ret,
-				     "Failed to add %s IRQ chip\n",
-				     sec_irq_chip->name);
+	for (i = 0; i < sec_irq_chip_num; i++) {
+		ret = devm_regmap_add_irq_chip(sec_pmic->dev,
+					       sec_pmic->regmap_pmic,
+					       sec_pmic->irq,
+					       IRQF_ONESHOT | IRQF_SHARED, 0,
+					       sec_irq_chip + i,
+					       sec_pmic->irq_data + i);
+		if (ret) {
+			return dev_err_probe(sec_pmic->dev, ret,
+					     "Failed to add %s IRQ chip\n",
+					     sec_irq_chip->name);
+		}
+	}
 
 	/*
 	 * The rtc-s5m driver requests S2MPS14_IRQ_RTCA0 also for S2MPS11
diff --git a/drivers/rtc/rtc-s5m.c b/drivers/rtc/rtc-s5m.c
index a7220b4d0e8d..726915deff7a 100644
--- a/drivers/rtc/rtc-s5m.c
+++ b/drivers/rtc/rtc-s5m.c
@@ -668,7 +668,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 	enum sec_device_type device_type =
 		platform_get_device_id(pdev)->driver_data;
 	struct s5m_rtc_info *info;
-	int ret, alarm_irq;
+	int ret, alarm_irq, irq_chip;
 
 	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
 	if (!info)
@@ -684,21 +684,25 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 			regmap_cfg = &s2mps14_rtc_regmap_config;
 			info->regs = &s2mps15_rtc_regs;
 			alarm_irq = S2MPS14_IRQ_RTCA0;
+			irq_chip = S2MPS11_IRQ_CHIP;
 			break;
 		case S2MPS14X:
 			regmap_cfg = &s2mps14_rtc_regmap_config;
 			info->regs = &s2mps14_rtc_regs;
 			alarm_irq = S2MPS14_IRQ_RTCA0;
+			irq_chip = S2MPS14_IRQ_CHIP;
 			break;
 		case S2MPS13X:
 			regmap_cfg = &s2mps14_rtc_regmap_config;
 			info->regs = &s2mps13_rtc_regs;
 			alarm_irq = S2MPS14_IRQ_RTCA0;
+			irq_chip = S2MPS14_IRQ_CHIP;
 			break;
 		case S5M8767X:
 			regmap_cfg = &s5m_rtc_regmap_config;
 			info->regs = &s5m_rtc_regs;
 			alarm_irq = S5M8767_IRQ_RTCA1;
+			irq_chip = S5M8767_IRQ_CHIP;
 			break;
 		default:
 			return dev_err_probe(&pdev->dev, -ENODEV,
@@ -720,6 +724,7 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 	} else if (device_type == S2MPG10) {
 		info->regs = &s2mpg10_rtc_regs;
 		alarm_irq = S2MPG10_IRQ_RTCA0;
+		irq_chip = S2MPG10_IRQ_CHIP;
 	} else {
 		return dev_err_probe(&pdev->dev, -ENODEV,
 				     "Unsupported device type %d\n",
@@ -730,12 +735,14 @@ static int s5m_rtc_probe(struct platform_device *pdev)
 	info->s5m87xx = s5m87xx;
 	info->device_type = device_type;
 
-	if (s5m87xx->irq_data) {
-		info->irq = regmap_irq_get_virq(s5m87xx->irq_data, alarm_irq);
-		if (info->irq <= 0)
+	if (s5m87xx->irq_data[irq_chip]) {
+		info->irq = regmap_irq_get_virq(s5m87xx->irq_data[irq_chip],
+						alarm_irq);
+		if (info->irq <= 0) {
 			return dev_err_probe(&pdev->dev, -EINVAL,
 					     "Failed to get virtual IRQ %d\n",
 					     alarm_irq);
+		}
 	}
 
 	platform_set_drvdata(pdev, info);
diff --git a/include/linux/mfd/samsung/core.h b/include/linux/mfd/samsung/core.h
index d785e101fe79..dcd741c4f0d6 100644
--- a/include/linux/mfd/samsung/core.h
+++ b/include/linux/mfd/samsung/core.h
@@ -33,6 +33,9 @@
 #define STEP_12_5_MV		12500
 #define STEP_6_25_MV		6250
 
+/* Maximum number of IRQ chips in a PMIC */
+#define MAX_IRQ_CHIPS		1
+
 struct gpio_desc;
 
 enum sec_device_type {
@@ -69,7 +72,7 @@ struct sec_pmic_dev {
 
 	int device_type;
 	int irq;
-	struct regmap_irq_chip_data *irq_data;
+	struct regmap_irq_chip_data *irq_data[MAX_IRQ_CHIPS];
 };
 
 struct sec_platform_data {
diff --git a/include/linux/mfd/samsung/irq.h b/include/linux/mfd/samsung/irq.h
index b4805cbd949b..78eb894e350e 100644
--- a/include/linux/mfd/samsung/irq.h
+++ b/include/linux/mfd/samsung/irq.h
@@ -34,6 +34,8 @@ enum s2mpa01_irq {
 	S2MPA01_IRQ_NR,
 };
 
+#define S2MPA01_IRQ_CHIP		0
+
 #define S2MPA01_IRQ_PWRONF_MASK		(1 << 0)
 #define S2MPA01_IRQ_PWRONR_MASK		(1 << 1)
 #define S2MPA01_IRQ_JIGONBF_MASK	(1 << 2)
@@ -58,6 +60,8 @@ enum s2mpa01_irq {
 #define S2MPA01_IRQ_B35_TSD_MASK	(1 << 5)
 
 enum s2mpg10_irq {
+#define S2MPG10_IRQ_CHIP		0
+
 	/* PMIC */
 	S2MPG10_IRQ_PWRONF,
 	S2MPG10_IRQ_PWRONR,
@@ -183,6 +187,8 @@ enum s2mps11_irq {
 	S2MPS11_IRQ_NR,
 };
 
+#define S2MPS11_IRQ_CHIP		0
+
 #define S2MPS11_IRQ_PWRONF_MASK		(1 << 0)
 #define S2MPS11_IRQ_PWRONR_MASK		(1 << 1)
 #define S2MPS11_IRQ_JIGONBF_MASK	(1 << 2)
@@ -226,6 +232,8 @@ enum s2mps14_irq {
 	S2MPS14_IRQ_NR,
 };
 
+#define S2MPS14_IRQ_CHIP		0
+
 enum s2mpu02_irq {
 	S2MPU02_IRQ_PWRONF,
 	S2MPU02_IRQ_PWRONR,
@@ -250,6 +258,8 @@ enum s2mpu02_irq {
 	S2MPU02_IRQ_NR,
 };
 
+#define S2MPU02_IRQ_CHIP		0
+
 /* Masks for interrupts are the same as in s2mps11 */
 #define S2MPS14_IRQ_TSD_MASK		(1 << 2)
 
@@ -277,6 +287,8 @@ enum s2mpu05_irq {
 	S2MPU05_IRQ_NR,
 };
 
+#define S2MPU05_IRQ_CHIP		0
+
 #define S2MPU05_IRQ_PWRONF_MASK		BIT(0)
 #define S2MPU05_IRQ_PWRONR_MASK		BIT(1)
 #define S2MPU05_IRQ_JIGONBF_MASK	BIT(2)
@@ -321,6 +333,8 @@ enum s5m8767_irq {
 	S5M8767_IRQ_NR,
 };
 
+#define S5M8767_IRQ_CHIP		0
+
 #define S5M8767_IRQ_PWRR_MASK		(1 << 0)
 #define S5M8767_IRQ_PWRF_MASK		(1 << 1)
 #define S5M8767_IRQ_PWR1S_MASK		(1 << 3)

-- 
2.51.2


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ