All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v3 1/4] hwmon: (pmbus/core): Add status byte to regulator flag map
@ 2022-11-30 16:59 Naresh Solanki
  2022-11-30 16:59 ` [PATCH v3 2/4] hwmon: (pmbus/core): Add events " Naresh Solanki
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Naresh Solanki @ 2022-11-30 16:59 UTC (permalink / raw)
  To: devicetree, Guenter Roeck, Jean Delvare, Liam Girdwood, Mark Brown
  Cc: linux-kernel, linux-hwmon, Patrick Rudolph, Naresh Solanki

Add PMBus status byte to regulator flag map.

Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>

---
Changes:
- Remove status input
- Add comment for PMBUS status byte.
---
 drivers/hwmon/pmbus/pmbus_core.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 95e95783972a..a7b4ae0f1f3b 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2751,7 +2751,16 @@ struct pmbus_regulator_status_category {
 };
 
 static const struct pmbus_regulator_status_category pmbus_regulator_flag_map[] = {
-	{
+	{	/* STATUS byte is always present. */
+		.func = -1,
+		.reg = PMBUS_STATUS_BYTE,
+		.bits = (const struct pmbus_regulator_status_assoc[]) {
+			{ PB_STATUS_IOUT_OC,   REGULATOR_ERROR_OVER_CURRENT },
+			{ PB_STATUS_VOUT_OV,   REGULATOR_ERROR_REGULATION_OUT },
+			{ PB_STATUS_VIN_UV,    REGULATOR_ERROR_UNDER_VOLTAGE },
+			{ },
+		},
+	}, {
 		.func = PMBUS_HAVE_STATUS_VOUT,
 		.reg = PMBUS_STATUS_VOUT,
 		.bits = (const struct pmbus_regulator_status_assoc[]) {
@@ -2768,6 +2777,7 @@ static const struct pmbus_regulator_status_category pmbus_regulator_flag_map[] =
 			{ PB_IOUT_OC_WARNING,    REGULATOR_ERROR_OVER_CURRENT_WARN },
 			{ PB_IOUT_OC_FAULT,      REGULATOR_ERROR_OVER_CURRENT },
 			{ PB_IOUT_OC_LV_FAULT,   REGULATOR_ERROR_OVER_CURRENT },
+			{ PB_POUT_OP_FAULT,      REGULATOR_ERROR_FAIL },
 			{ },
 		},
 	}, {
@@ -2834,14 +2844,6 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
 		if (status & PB_STATUS_POWER_GOOD_N)
 			*flags |= REGULATOR_ERROR_REGULATION_OUT;
 	}
-	/*
-	 * Unlike most other status bits, PB_STATUS_{IOUT_OC,VOUT_OV} are
-	 * defined strictly as fault indicators (not warnings).
-	 */
-	if (status & PB_STATUS_IOUT_OC)
-		*flags |= REGULATOR_ERROR_OVER_CURRENT;
-	if (status & PB_STATUS_VOUT_OV)
-		*flags |= REGULATOR_ERROR_REGULATION_OUT;
 
 	/*
 	 * If we haven't discovered any thermal faults or warnings via

base-commit: 9494c53e1389b120ba461899207ac8a3aab2632c
-- 
2.37.3


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

* [PATCH v3 2/4] hwmon: (pmbus/core): Add events to regulator flag map
  2022-11-30 16:59 [PATCH v3 1/4] hwmon: (pmbus/core): Add status byte to regulator flag map Naresh Solanki
@ 2022-11-30 16:59 ` Naresh Solanki
  2022-11-30 16:59 ` [PATCH v3 3/4] hwmon: (pmbus/core): Implement irq support Naresh Solanki
  2022-11-30 16:59 ` [PATCH v3 4/4] hwmon: (pmbus/core): Notify hwmon events Naresh Solanki
  2 siblings, 0 replies; 6+ messages in thread
From: Naresh Solanki @ 2022-11-30 16:59 UTC (permalink / raw)
  To: devicetree, Guenter Roeck, Jean Delvare, Liam Girdwood, Mark Brown
  Cc: linux-kernel, linux-hwmon, Patrick Rudolph, Naresh Solanki

From: Patrick Rudolph <patrick.rudolph@9elements.com>

Add regulator events corresponding to regulator error in regulator flag
map.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>
---
 drivers/hwmon/pmbus/pmbus_core.c | 43 +++++++++++++++++++++-----------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index a7b4ae0f1f3b..9a9e380acc23 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2738,9 +2738,9 @@ static int pmbus_regulator_disable(struct regulator_dev *rdev)
 	return _pmbus_regulator_on_off(rdev, 0);
 }
 
-/* A PMBus status flag and the corresponding REGULATOR_ERROR_* flag */
+/* A PMBus status flag and the corresponding REGULATOR_ERROR_* and REGULATOR_EVENTS_* flag */
 struct pmbus_regulator_status_assoc {
-	int pflag, rflag;
+	int pflag, rflag, eflag;
 };
 
 /* PMBus->regulator bit mappings for a PMBus status register */
@@ -2755,37 +2755,50 @@ static const struct pmbus_regulator_status_category pmbus_regulator_flag_map[] =
 		.func = -1,
 		.reg = PMBUS_STATUS_BYTE,
 		.bits = (const struct pmbus_regulator_status_assoc[]) {
-			{ PB_STATUS_IOUT_OC,   REGULATOR_ERROR_OVER_CURRENT },
-			{ PB_STATUS_VOUT_OV,   REGULATOR_ERROR_REGULATION_OUT },
-			{ PB_STATUS_VIN_UV,    REGULATOR_ERROR_UNDER_VOLTAGE },
+			{ PB_STATUS_IOUT_OC,   REGULATOR_ERROR_OVER_CURRENT,
+			REGULATOR_EVENT_OVER_CURRENT },
+			{ PB_STATUS_VOUT_OV,   REGULATOR_ERROR_REGULATION_OUT,
+			REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+			{ PB_STATUS_VIN_UV,    REGULATOR_ERROR_UNDER_VOLTAGE,
+			REGULATOR_EVENT_UNDER_VOLTAGE },
 			{ },
 		},
 	}, {
 		.func = PMBUS_HAVE_STATUS_VOUT,
 		.reg = PMBUS_STATUS_VOUT,
 		.bits = (const struct pmbus_regulator_status_assoc[]) {
-			{ PB_VOLTAGE_UV_WARNING, REGULATOR_ERROR_UNDER_VOLTAGE_WARN },
-			{ PB_VOLTAGE_UV_FAULT,   REGULATOR_ERROR_UNDER_VOLTAGE },
-			{ PB_VOLTAGE_OV_WARNING, REGULATOR_ERROR_OVER_VOLTAGE_WARN },
-			{ PB_VOLTAGE_OV_FAULT,   REGULATOR_ERROR_REGULATION_OUT },
+			{ PB_VOLTAGE_UV_WARNING, REGULATOR_ERROR_UNDER_VOLTAGE_WARN,
+			REGULATOR_EVENT_UNDER_VOLTAGE_WARN },
+			{ PB_VOLTAGE_UV_FAULT,   REGULATOR_ERROR_UNDER_VOLTAGE,
+			REGULATOR_EVENT_UNDER_VOLTAGE },
+			{ PB_VOLTAGE_OV_WARNING, REGULATOR_ERROR_OVER_VOLTAGE_WARN,
+			REGULATOR_EVENT_OVER_VOLTAGE_WARN },
+			{ PB_VOLTAGE_OV_FAULT,   REGULATOR_ERROR_REGULATION_OUT,
+			REGULATOR_EVENT_OVER_VOLTAGE_WARN },
 			{ },
 		},
 	}, {
 		.func = PMBUS_HAVE_STATUS_IOUT,
 		.reg = PMBUS_STATUS_IOUT,
 		.bits = (const struct pmbus_regulator_status_assoc[]) {
-			{ PB_IOUT_OC_WARNING,    REGULATOR_ERROR_OVER_CURRENT_WARN },
-			{ PB_IOUT_OC_FAULT,      REGULATOR_ERROR_OVER_CURRENT },
-			{ PB_IOUT_OC_LV_FAULT,   REGULATOR_ERROR_OVER_CURRENT },
-			{ PB_POUT_OP_FAULT,      REGULATOR_ERROR_FAIL },
+			{ PB_IOUT_OC_WARNING,   REGULATOR_ERROR_OVER_CURRENT_WARN,
+			REGULATOR_EVENT_OVER_CURRENT_WARN },
+			{ PB_IOUT_OC_FAULT,     REGULATOR_ERROR_OVER_CURRENT,
+			REGULATOR_EVENT_OVER_CURRENT },
+			{ PB_IOUT_OC_LV_FAULT,  REGULATOR_ERROR_OVER_CURRENT,
+			REGULATOR_EVENT_OVER_CURRENT },
+			{ PB_POUT_OP_FAULT,     REGULATOR_ERROR_FAIL,
+			REGULATOR_EVENT_FAIL },
 			{ },
 		},
 	}, {
 		.func = PMBUS_HAVE_STATUS_TEMP,
 		.reg = PMBUS_STATUS_TEMPERATURE,
 		.bits = (const struct pmbus_regulator_status_assoc[]) {
-			{ PB_TEMP_OT_WARNING,    REGULATOR_ERROR_OVER_TEMP_WARN },
-			{ PB_TEMP_OT_FAULT,      REGULATOR_ERROR_OVER_TEMP },
+			{ PB_TEMP_OT_WARNING,    REGULATOR_ERROR_OVER_TEMP_WARN,
+			REGULATOR_EVENT_OVER_TEMP_WARN },
+			{ PB_TEMP_OT_FAULT,      REGULATOR_ERROR_OVER_TEMP,
+			REGULATOR_EVENT_OVER_TEMP },
 			{ },
 		},
 	},
-- 
2.37.3


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

* [PATCH v3 3/4] hwmon: (pmbus/core): Implement irq support
  2022-11-30 16:59 [PATCH v3 1/4] hwmon: (pmbus/core): Add status byte to regulator flag map Naresh Solanki
  2022-11-30 16:59 ` [PATCH v3 2/4] hwmon: (pmbus/core): Add events " Naresh Solanki
@ 2022-11-30 16:59 ` Naresh Solanki
  2022-11-30 18:24   ` Guenter Roeck
  2022-11-30 16:59 ` [PATCH v3 4/4] hwmon: (pmbus/core): Notify hwmon events Naresh Solanki
  2 siblings, 1 reply; 6+ messages in thread
From: Naresh Solanki @ 2022-11-30 16:59 UTC (permalink / raw)
  To: devicetree, Guenter Roeck, Jean Delvare, Liam Girdwood, Mark Brown
  Cc: linux-kernel, linux-hwmon, Patrick Rudolph, Naresh Solanki

From: Patrick Rudolph <patrick.rudolph@9elements.com>

Implement PMBUS irq handler to notify regulator events.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>
---
 drivers/hwmon/pmbus/pmbus.h      |   2 +-
 drivers/hwmon/pmbus/pmbus_core.c | 151 ++++++++++++++++++++++++++++---
 2 files changed, 137 insertions(+), 16 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
index 10fb17879f8e..6b2e6cf93b19 100644
--- a/drivers/hwmon/pmbus/pmbus.h
+++ b/drivers/hwmon/pmbus/pmbus.h
@@ -26,7 +26,7 @@ enum pmbus_regs {
 
 	PMBUS_CAPABILITY		= 0x19,
 	PMBUS_QUERY			= 0x1A,
-
+	PMBUS_SMBALERT_MASK		= 0x1B,
 	PMBUS_VOUT_MODE			= 0x20,
 	PMBUS_VOUT_COMMAND		= 0x21,
 	PMBUS_VOUT_TRIM			= 0x22,
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 9a9e380acc23..613e2e484a0f 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -81,6 +81,7 @@ struct pmbus_label {
 struct pmbus_data {
 	struct device *dev;
 	struct device *hwmon_dev;
+	struct regulator_dev **rdevs;
 
 	u32 flags;		/* from platform data */
 
@@ -2804,7 +2805,8 @@ static const struct pmbus_regulator_status_category pmbus_regulator_flag_map[] =
 	},
 };
 
-static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
+static int pmbus_regulator_get_flags(struct regulator_dev *rdev, unsigned int *error,
+				    unsigned int *event)
 {
 	int i, status;
 	const struct pmbus_regulator_status_category *cat;
@@ -2815,7 +2817,8 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
 	u8 page = rdev_get_id(rdev);
 	int func = data->info->func[page];
 
-	*flags = 0;
+	*error = 0;
+	*event = 0;
 
 	mutex_lock(&data->update_lock);
 
@@ -2831,8 +2834,10 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
 		}
 
 		for (bit = cat->bits; bit->pflag; bit++) {
-			if (status & bit->pflag)
-				*flags |= bit->rflag;
+			if (status & bit->pflag) {
+				*error |= bit->rflag;
+				*event |= bit->eflag;
+			}
 		}
 	}
 
@@ -2851,11 +2856,15 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
 		return status;
 
 	if (pmbus_regulator_is_enabled(rdev)) {
-		if (status & PB_STATUS_OFF)
-			*flags |= REGULATOR_ERROR_FAIL;
+		if (status & PB_STATUS_OFF) {
+			*error |= REGULATOR_ERROR_FAIL;
+			*event |= REGULATOR_EVENT_FAIL;
+		}
 
-		if (status & PB_STATUS_POWER_GOOD_N)
-			*flags |= REGULATOR_ERROR_REGULATION_OUT;
+		if (status & PB_STATUS_POWER_GOOD_N) {
+			*error |= REGULATOR_ERROR_REGULATION_OUT;
+			*event |= REGULATOR_EVENT_REGULATION_OUT;
+		}
 	}
 
 	/*
@@ -2863,13 +2872,22 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
 	 * PMBUS_STATUS_TEMPERATURE, map PB_STATUS_TEMPERATURE to a warning as
 	 * a (conservative) best-effort interpretation.
 	 */
-	if (!(*flags & (REGULATOR_ERROR_OVER_TEMP | REGULATOR_ERROR_OVER_TEMP_WARN)) &&
-	    (status & PB_STATUS_TEMPERATURE))
-		*flags |= REGULATOR_ERROR_OVER_TEMP_WARN;
+	if (!(*error & (REGULATOR_ERROR_OVER_TEMP | REGULATOR_ERROR_OVER_TEMP_WARN)) &&
+	    (status & PB_STATUS_TEMPERATURE)) {
+		*error |= REGULATOR_ERROR_OVER_TEMP_WARN;
+		*event |= REGULATOR_EVENT_OVER_TEMP_WARN;
+	}
 
 	return 0;
 }
 
+static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
+{
+	unsigned int event;
+
+	return pmbus_regulator_get_flags(rdev, flags, &event);
+}
+
 static int pmbus_regulator_get_status(struct regulator_dev *rdev)
 {
 	struct device *dev = rdev_get_dev(rdev);
@@ -3060,14 +3078,61 @@ const struct regulator_ops pmbus_regulator_ops = {
 };
 EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
 
+static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg, u8 val)
+{
+	return pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
+}
+
+static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
+{
+	struct pmbus_data *data = pdata;
+	struct i2c_client *client = to_i2c_client(data->dev);
+	int i, ret = IRQ_NONE, status, event;
+	u8 page;
+
+	for (i = 0; i < data->info->num_regulators; i++) {
+
+		if (!data->rdevs[i])
+			continue;
+
+		ret = pmbus_regulator_get_flags(data->rdevs[i], &status, &event);
+		if (ret)
+			return ret;
+
+		if (event) {
+			regulator_notifier_call_chain(data->rdevs[i], event, NULL);
+			ret = IRQ_HANDLED;
+		}
+
+		page = rdev_get_id(data->rdevs[i]);
+		mutex_lock(&data->update_lock);
+		status = pmbus_read_status_word(client, page);
+		if (status < 0) {
+			mutex_unlock(&data->update_lock);
+			return status;
+		}
+
+		if (status & ~(PB_STATUS_OFF | PB_STATUS_BUSY | PB_STATUS_POWER_GOOD_N))
+			pmbus_clear_fault_page(client, page);
+
+		mutex_unlock(&data->update_lock);
+	}
+
+	return ret;
+}
+
 static int pmbus_regulator_register(struct pmbus_data *data)
 {
 	struct device *dev = data->dev;
 	const struct pmbus_driver_info *info = data->info;
 	const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
-	struct regulator_dev *rdev;
 	int i;
 
+	data->rdevs = devm_kzalloc(dev, sizeof(struct regulator_dev *) * info->num_regulators,
+				  GFP_KERNEL);
+	if (!data->rdevs)
+		return -ENOMEM;
+
 	for (i = 0; i < info->num_regulators; i++) {
 		struct regulator_config config = { };
 
@@ -3077,21 +3142,71 @@ static int pmbus_regulator_register(struct pmbus_data *data)
 		if (pdata && pdata->reg_init_data)
 			config.init_data = &pdata->reg_init_data[i];
 
-		rdev = devm_regulator_register(dev, &info->reg_desc[i],
+		data->rdevs[i] = devm_regulator_register(dev, &info->reg_desc[i],
 					       &config);
-		if (IS_ERR(rdev))
-			return dev_err_probe(dev, PTR_ERR(rdev),
+		if (IS_ERR(data->rdevs[i]))
+			return dev_err_probe(dev, PTR_ERR(data->rdevs[i]),
 					     "Failed to register %s regulator\n",
 					     info->reg_desc[i].name);
 	}
 
 	return 0;
 }
+
+static int pmbus_irq_setup(struct i2c_client *client, struct pmbus_data *data)
+{
+	struct device *dev = &client->dev;
+	const struct pmbus_regulator_status_category *cat;
+	const struct pmbus_regulator_status_assoc *bit;
+	int i, j, err, ret;
+	u8 mask;
+	int func;
+
+	for (i = 0; i < data->info->pages; i++) {
+		func = data->info->func[i];
+
+		for (j = 0; j < ARRAY_SIZE(pmbus_regulator_flag_map); j++) {
+			cat = &pmbus_regulator_flag_map[i];
+			if (!(func & cat->func))
+				continue;
+			mask = 0;
+			for (bit = cat->bits; bit->pflag; bit++)
+				mask |= bit->pflag;
+
+			err = pmbus_write_smbalert_mask(client, i, cat->reg, ~mask);
+			if (err)
+				dev_err(dev, "Failed to set smbalert for reg 0x%02x\n",	cat->reg);
+		}
+
+		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_CML, 0xff);
+		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_OTHER, 0xff);
+		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_MFR_SPECIFIC, 0xff);
+		if (data->info->func[i] & PMBUS_HAVE_FAN12)
+			pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_FAN_12, 0xff);
+		if (data->info->func[i] & PMBUS_HAVE_FAN34)
+			pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_FAN_34, 0xff);
+
+	}
+
+	/* Register notifiers - can fail if IRQ is not given */
+	ret = devm_request_threaded_irq(dev, client->irq, NULL, pmbus_fault_handler,
+			      0, "pmbus-irq", data);
+	if (ret) {
+		dev_warn(dev, "IRQ disabled %d\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
 #else
 static int pmbus_regulator_register(struct pmbus_data *data)
 {
 	return 0;
 }
+static int pmbus_irq_setup(struct i2c_client *client, struct pmbus_data *data)
+{
+	return 0;
+}
 #endif
 
 static struct dentry *pmbus_debugfs_dir;	/* pmbus debugfs directory */
@@ -3456,6 +3571,12 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info)
 	if (ret)
 		return ret;
 
+	if (client->irq > 0) {
+		ret = pmbus_irq_setup(client, data);
+		if (ret)
+			return ret;
+	}
+
 	ret = pmbus_init_debugfs(client, data);
 	if (ret)
 		dev_warn(dev, "Failed to register debugfs\n");
-- 
2.37.3


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

* [PATCH v3 4/4] hwmon: (pmbus/core): Notify hwmon events
  2022-11-30 16:59 [PATCH v3 1/4] hwmon: (pmbus/core): Add status byte to regulator flag map Naresh Solanki
  2022-11-30 16:59 ` [PATCH v3 2/4] hwmon: (pmbus/core): Add events " Naresh Solanki
  2022-11-30 16:59 ` [PATCH v3 3/4] hwmon: (pmbus/core): Implement irq support Naresh Solanki
@ 2022-11-30 16:59 ` Naresh Solanki
  2 siblings, 0 replies; 6+ messages in thread
From: Naresh Solanki @ 2022-11-30 16:59 UTC (permalink / raw)
  To: devicetree, Guenter Roeck, Jean Delvare, Liam Girdwood, Mark Brown
  Cc: linux-kernel, linux-hwmon, Patrick Rudolph, Naresh Solanki

Notify hwmon events using the pmbus irq handler.

Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>
---
 drivers/hwmon/pmbus/pmbus_core.c | 37 +++++++++++++++++++++++++++++---
 1 file changed, 34 insertions(+), 3 deletions(-)

diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index 613e2e484a0f..da92a08484c9 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -2805,8 +2805,36 @@ static const struct pmbus_regulator_status_category pmbus_regulator_flag_map[] =
 	},
 };
 
+#define to_dev_attr(_dev_attr) \
+	container_of(_dev_attr, struct device_attribute, attr)
+
+static void pmbus_notify(struct pmbus_data *data, int page, int reg, int flags)
+{
+	int i;
+
+	for (i = 0; i < data->num_attributes; i++) {
+		struct device_attribute *da = to_dev_attr(data->group.attrs[i]);
+		struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+		int index = attr->index;
+		u16 smask = pb_index_to_mask(index);
+		u8 spage = pb_index_to_page(index);
+		u16 sreg = pb_index_to_reg(index);
+
+		if (reg == sreg && page == spage && (smask & flags)) {
+			dev_dbg(data->dev, "sysfs notify: %s", da->attr.name);
+			sysfs_notify(&data->dev->kobj, NULL, da->attr.name);
+			kobject_uevent(&data->dev->kobj, KOBJ_CHANGE);
+		}
+
+		flags &= ~smask;
+
+		if (!flags)
+			break;
+	}
+}
+
 static int pmbus_regulator_get_flags(struct regulator_dev *rdev, unsigned int *error,
-				    unsigned int *event)
+				    unsigned int *event, bool notify)
 {
 	int i, status;
 	const struct pmbus_regulator_status_category *cat;
@@ -2833,6 +2861,9 @@ static int pmbus_regulator_get_flags(struct regulator_dev *rdev, unsigned int *e
 			return status;
 		}
 
+		if (notify && status)
+			pmbus_notify(data, page, cat->reg, status);
+
 		for (bit = cat->bits; bit->pflag; bit++) {
 			if (status & bit->pflag) {
 				*error |= bit->rflag;
@@ -2885,7 +2916,7 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
 {
 	unsigned int event;
 
-	return pmbus_regulator_get_flags(rdev, flags, &event);
+	return pmbus_regulator_get_flags(rdev, flags, &event, false);
 }
 
 static int pmbus_regulator_get_status(struct regulator_dev *rdev)
@@ -3095,7 +3126,7 @@ static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
 		if (!data->rdevs[i])
 			continue;
 
-		ret = pmbus_regulator_get_flags(data->rdevs[i], &status, &event);
+		ret = pmbus_regulator_get_flags(data->rdevs[i], &status, &event, true);
 		if (ret)
 			return ret;
 
-- 
2.37.3


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

* Re: [PATCH v3 3/4] hwmon: (pmbus/core): Implement irq support
  2022-11-30 16:59 ` [PATCH v3 3/4] hwmon: (pmbus/core): Implement irq support Naresh Solanki
@ 2022-11-30 18:24   ` Guenter Roeck
  2022-11-30 18:26     ` Naresh Solanki
  0 siblings, 1 reply; 6+ messages in thread
From: Guenter Roeck @ 2022-11-30 18:24 UTC (permalink / raw)
  To: Naresh Solanki
  Cc: devicetree, Jean Delvare, Liam Girdwood, Mark Brown,
	linux-kernel, linux-hwmon, Patrick Rudolph

On Wed, Nov 30, 2022 at 05:59:53PM +0100, Naresh Solanki wrote:
> From: Patrick Rudolph <patrick.rudolph@9elements.com>
> 
> Implement PMBUS irq handler to notify regulator events.
> 

There should be separate patches for adding irq support, adding
hwmon notifications, and adding regulator notifications. The order
should be:

- Add interrupt support
- Add hwmon notifications
- Add events to regulator flag map
- Add regulator notifications

Guenter

> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>
> ---
>  drivers/hwmon/pmbus/pmbus.h      |   2 +-
>  drivers/hwmon/pmbus/pmbus_core.c | 151 ++++++++++++++++++++++++++++---
>  2 files changed, 137 insertions(+), 16 deletions(-)
> 
> diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
> index 10fb17879f8e..6b2e6cf93b19 100644
> --- a/drivers/hwmon/pmbus/pmbus.h
> +++ b/drivers/hwmon/pmbus/pmbus.h
> @@ -26,7 +26,7 @@ enum pmbus_regs {
>  
>  	PMBUS_CAPABILITY		= 0x19,
>  	PMBUS_QUERY			= 0x1A,
> -
> +	PMBUS_SMBALERT_MASK		= 0x1B,
>  	PMBUS_VOUT_MODE			= 0x20,
>  	PMBUS_VOUT_COMMAND		= 0x21,
>  	PMBUS_VOUT_TRIM			= 0x22,
> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
> index 9a9e380acc23..613e2e484a0f 100644
> --- a/drivers/hwmon/pmbus/pmbus_core.c
> +++ b/drivers/hwmon/pmbus/pmbus_core.c
> @@ -81,6 +81,7 @@ struct pmbus_label {
>  struct pmbus_data {
>  	struct device *dev;
>  	struct device *hwmon_dev;
> +	struct regulator_dev **rdevs;
>  
>  	u32 flags;		/* from platform data */
>  
> @@ -2804,7 +2805,8 @@ static const struct pmbus_regulator_status_category pmbus_regulator_flag_map[] =
>  	},
>  };
>  
> -static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
> +static int pmbus_regulator_get_flags(struct regulator_dev *rdev, unsigned int *error,
> +				    unsigned int *event)
>  {
>  	int i, status;
>  	const struct pmbus_regulator_status_category *cat;
> @@ -2815,7 +2817,8 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>  	u8 page = rdev_get_id(rdev);
>  	int func = data->info->func[page];
>  
> -	*flags = 0;
> +	*error = 0;
> +	*event = 0;
>  
>  	mutex_lock(&data->update_lock);
>  
> @@ -2831,8 +2834,10 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>  		}
>  
>  		for (bit = cat->bits; bit->pflag; bit++) {
> -			if (status & bit->pflag)
> -				*flags |= bit->rflag;
> +			if (status & bit->pflag) {
> +				*error |= bit->rflag;
> +				*event |= bit->eflag;
> +			}
>  		}
>  	}
>  
> @@ -2851,11 +2856,15 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>  		return status;
>  
>  	if (pmbus_regulator_is_enabled(rdev)) {
> -		if (status & PB_STATUS_OFF)
> -			*flags |= REGULATOR_ERROR_FAIL;
> +		if (status & PB_STATUS_OFF) {
> +			*error |= REGULATOR_ERROR_FAIL;
> +			*event |= REGULATOR_EVENT_FAIL;
> +		}
>  
> -		if (status & PB_STATUS_POWER_GOOD_N)
> -			*flags |= REGULATOR_ERROR_REGULATION_OUT;
> +		if (status & PB_STATUS_POWER_GOOD_N) {
> +			*error |= REGULATOR_ERROR_REGULATION_OUT;
> +			*event |= REGULATOR_EVENT_REGULATION_OUT;
> +		}
>  	}
>  
>  	/*
> @@ -2863,13 +2872,22 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>  	 * PMBUS_STATUS_TEMPERATURE, map PB_STATUS_TEMPERATURE to a warning as
>  	 * a (conservative) best-effort interpretation.
>  	 */
> -	if (!(*flags & (REGULATOR_ERROR_OVER_TEMP | REGULATOR_ERROR_OVER_TEMP_WARN)) &&
> -	    (status & PB_STATUS_TEMPERATURE))
> -		*flags |= REGULATOR_ERROR_OVER_TEMP_WARN;
> +	if (!(*error & (REGULATOR_ERROR_OVER_TEMP | REGULATOR_ERROR_OVER_TEMP_WARN)) &&
> +	    (status & PB_STATUS_TEMPERATURE)) {
> +		*error |= REGULATOR_ERROR_OVER_TEMP_WARN;
> +		*event |= REGULATOR_EVENT_OVER_TEMP_WARN;
> +	}
>  
>  	return 0;
>  }
>  
> +static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
> +{
> +	unsigned int event;
> +
> +	return pmbus_regulator_get_flags(rdev, flags, &event);
> +}
> +
>  static int pmbus_regulator_get_status(struct regulator_dev *rdev)
>  {
>  	struct device *dev = rdev_get_dev(rdev);
> @@ -3060,14 +3078,61 @@ const struct regulator_ops pmbus_regulator_ops = {
>  };
>  EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
>  
> +static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg, u8 val)
> +{
> +	return pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
> +}
> +
> +static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
> +{
> +	struct pmbus_data *data = pdata;
> +	struct i2c_client *client = to_i2c_client(data->dev);
> +	int i, ret = IRQ_NONE, status, event;
> +	u8 page;
> +
> +	for (i = 0; i < data->info->num_regulators; i++) {
> +
> +		if (!data->rdevs[i])
> +			continue;
> +
> +		ret = pmbus_regulator_get_flags(data->rdevs[i], &status, &event);
> +		if (ret)
> +			return ret;
> +
> +		if (event) {
> +			regulator_notifier_call_chain(data->rdevs[i], event, NULL);
> +			ret = IRQ_HANDLED;
> +		}
> +
> +		page = rdev_get_id(data->rdevs[i]);
> +		mutex_lock(&data->update_lock);
> +		status = pmbus_read_status_word(client, page);
> +		if (status < 0) {
> +			mutex_unlock(&data->update_lock);
> +			return status;
> +		}
> +
> +		if (status & ~(PB_STATUS_OFF | PB_STATUS_BUSY | PB_STATUS_POWER_GOOD_N))
> +			pmbus_clear_fault_page(client, page);
> +
> +		mutex_unlock(&data->update_lock);
> +	}
> +
> +	return ret;
> +}
> +
>  static int pmbus_regulator_register(struct pmbus_data *data)
>  {
>  	struct device *dev = data->dev;
>  	const struct pmbus_driver_info *info = data->info;
>  	const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
> -	struct regulator_dev *rdev;
>  	int i;
>  
> +	data->rdevs = devm_kzalloc(dev, sizeof(struct regulator_dev *) * info->num_regulators,
> +				  GFP_KERNEL);
> +	if (!data->rdevs)
> +		return -ENOMEM;
> +
>  	for (i = 0; i < info->num_regulators; i++) {
>  		struct regulator_config config = { };
>  
> @@ -3077,21 +3142,71 @@ static int pmbus_regulator_register(struct pmbus_data *data)
>  		if (pdata && pdata->reg_init_data)
>  			config.init_data = &pdata->reg_init_data[i];
>  
> -		rdev = devm_regulator_register(dev, &info->reg_desc[i],
> +		data->rdevs[i] = devm_regulator_register(dev, &info->reg_desc[i],
>  					       &config);
> -		if (IS_ERR(rdev))
> -			return dev_err_probe(dev, PTR_ERR(rdev),
> +		if (IS_ERR(data->rdevs[i]))
> +			return dev_err_probe(dev, PTR_ERR(data->rdevs[i]),
>  					     "Failed to register %s regulator\n",
>  					     info->reg_desc[i].name);
>  	}
>  
>  	return 0;
>  }
> +
> +static int pmbus_irq_setup(struct i2c_client *client, struct pmbus_data *data)
> +{
> +	struct device *dev = &client->dev;
> +	const struct pmbus_regulator_status_category *cat;
> +	const struct pmbus_regulator_status_assoc *bit;
> +	int i, j, err, ret;
> +	u8 mask;
> +	int func;
> +
> +	for (i = 0; i < data->info->pages; i++) {
> +		func = data->info->func[i];
> +
> +		for (j = 0; j < ARRAY_SIZE(pmbus_regulator_flag_map); j++) {
> +			cat = &pmbus_regulator_flag_map[i];
> +			if (!(func & cat->func))
> +				continue;
> +			mask = 0;
> +			for (bit = cat->bits; bit->pflag; bit++)
> +				mask |= bit->pflag;
> +
> +			err = pmbus_write_smbalert_mask(client, i, cat->reg, ~mask);
> +			if (err)
> +				dev_err(dev, "Failed to set smbalert for reg 0x%02x\n",	cat->reg);
> +		}
> +
> +		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_CML, 0xff);
> +		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_OTHER, 0xff);
> +		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_MFR_SPECIFIC, 0xff);
> +		if (data->info->func[i] & PMBUS_HAVE_FAN12)
> +			pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_FAN_12, 0xff);
> +		if (data->info->func[i] & PMBUS_HAVE_FAN34)
> +			pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_FAN_34, 0xff);
> +
> +	}
> +
> +	/* Register notifiers - can fail if IRQ is not given */
> +	ret = devm_request_threaded_irq(dev, client->irq, NULL, pmbus_fault_handler,
> +			      0, "pmbus-irq", data);
> +	if (ret) {
> +		dev_warn(dev, "IRQ disabled %d\n", ret);
> +		return ret;
> +	}
> +
> +	return 0;
> +}
>  #else
>  static int pmbus_regulator_register(struct pmbus_data *data)
>  {
>  	return 0;
>  }
> +static int pmbus_irq_setup(struct i2c_client *client, struct pmbus_data *data)
> +{
> +	return 0;
> +}
>  #endif
>  
>  static struct dentry *pmbus_debugfs_dir;	/* pmbus debugfs directory */
> @@ -3456,6 +3571,12 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info)
>  	if (ret)
>  		return ret;
>  
> +	if (client->irq > 0) {
> +		ret = pmbus_irq_setup(client, data);
> +		if (ret)
> +			return ret;
> +	}
> +
>  	ret = pmbus_init_debugfs(client, data);
>  	if (ret)
>  		dev_warn(dev, "Failed to register debugfs\n");
> -- 
> 2.37.3
> 

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

* Re: [PATCH v3 3/4] hwmon: (pmbus/core): Implement irq support
  2022-11-30 18:24   ` Guenter Roeck
@ 2022-11-30 18:26     ` Naresh Solanki
  0 siblings, 0 replies; 6+ messages in thread
From: Naresh Solanki @ 2022-11-30 18:26 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: devicetree, Jean Delvare, Liam Girdwood, Mark Brown,
	linux-kernel, linux-hwmon, Patrick Rudolph

Hi,

On 30-11-2022 11:54 pm, Guenter Roeck wrote:
> On Wed, Nov 30, 2022 at 05:59:53PM +0100, Naresh Solanki wrote:
>> From: Patrick Rudolph <patrick.rudolph@9elements.com>
>>
>> Implement PMBUS irq handler to notify regulator events.
>>
> 
> There should be separate patches for adding irq support, adding
> hwmon notifications, and adding regulator notifications. The order
> should be:
> 
> - Add interrupt support
> - Add hwmon notifications
> - Add events to regulator flag map
> - Add regulator notifications
Yes. Will do that as part of next revision. Thanks.

Naresh
> 
> Guenter
> 
>> Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
>> Signed-off-by: Naresh Solanki <Naresh.Solanki@9elements.com>
>> ---
>>   drivers/hwmon/pmbus/pmbus.h      |   2 +-
>>   drivers/hwmon/pmbus/pmbus_core.c | 151 ++++++++++++++++++++++++++++---
>>   2 files changed, 137 insertions(+), 16 deletions(-)
>>
>> diff --git a/drivers/hwmon/pmbus/pmbus.h b/drivers/hwmon/pmbus/pmbus.h
>> index 10fb17879f8e..6b2e6cf93b19 100644
>> --- a/drivers/hwmon/pmbus/pmbus.h
>> +++ b/drivers/hwmon/pmbus/pmbus.h
>> @@ -26,7 +26,7 @@ enum pmbus_regs {
>>   
>>   	PMBUS_CAPABILITY		= 0x19,
>>   	PMBUS_QUERY			= 0x1A,
>> -
>> +	PMBUS_SMBALERT_MASK		= 0x1B,
>>   	PMBUS_VOUT_MODE			= 0x20,
>>   	PMBUS_VOUT_COMMAND		= 0x21,
>>   	PMBUS_VOUT_TRIM			= 0x22,
>> diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
>> index 9a9e380acc23..613e2e484a0f 100644
>> --- a/drivers/hwmon/pmbus/pmbus_core.c
>> +++ b/drivers/hwmon/pmbus/pmbus_core.c
>> @@ -81,6 +81,7 @@ struct pmbus_label {
>>   struct pmbus_data {
>>   	struct device *dev;
>>   	struct device *hwmon_dev;
>> +	struct regulator_dev **rdevs;
>>   
>>   	u32 flags;		/* from platform data */
>>   
>> @@ -2804,7 +2805,8 @@ static const struct pmbus_regulator_status_category pmbus_regulator_flag_map[] =
>>   	},
>>   };
>>   
>> -static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
>> +static int pmbus_regulator_get_flags(struct regulator_dev *rdev, unsigned int *error,
>> +				    unsigned int *event)
>>   {
>>   	int i, status;
>>   	const struct pmbus_regulator_status_category *cat;
>> @@ -2815,7 +2817,8 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>>   	u8 page = rdev_get_id(rdev);
>>   	int func = data->info->func[page];
>>   
>> -	*flags = 0;
>> +	*error = 0;
>> +	*event = 0;
>>   
>>   	mutex_lock(&data->update_lock);
>>   
>> @@ -2831,8 +2834,10 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>>   		}
>>   
>>   		for (bit = cat->bits; bit->pflag; bit++) {
>> -			if (status & bit->pflag)
>> -				*flags |= bit->rflag;
>> +			if (status & bit->pflag) {
>> +				*error |= bit->rflag;
>> +				*event |= bit->eflag;
>> +			}
>>   		}
>>   	}
>>   
>> @@ -2851,11 +2856,15 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>>   		return status;
>>   
>>   	if (pmbus_regulator_is_enabled(rdev)) {
>> -		if (status & PB_STATUS_OFF)
>> -			*flags |= REGULATOR_ERROR_FAIL;
>> +		if (status & PB_STATUS_OFF) {
>> +			*error |= REGULATOR_ERROR_FAIL;
>> +			*event |= REGULATOR_EVENT_FAIL;
>> +		}
>>   
>> -		if (status & PB_STATUS_POWER_GOOD_N)
>> -			*flags |= REGULATOR_ERROR_REGULATION_OUT;
>> +		if (status & PB_STATUS_POWER_GOOD_N) {
>> +			*error |= REGULATOR_ERROR_REGULATION_OUT;
>> +			*event |= REGULATOR_EVENT_REGULATION_OUT;
>> +		}
>>   	}
>>   
>>   	/*
>> @@ -2863,13 +2872,22 @@ static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned
>>   	 * PMBUS_STATUS_TEMPERATURE, map PB_STATUS_TEMPERATURE to a warning as
>>   	 * a (conservative) best-effort interpretation.
>>   	 */
>> -	if (!(*flags & (REGULATOR_ERROR_OVER_TEMP | REGULATOR_ERROR_OVER_TEMP_WARN)) &&
>> -	    (status & PB_STATUS_TEMPERATURE))
>> -		*flags |= REGULATOR_ERROR_OVER_TEMP_WARN;
>> +	if (!(*error & (REGULATOR_ERROR_OVER_TEMP | REGULATOR_ERROR_OVER_TEMP_WARN)) &&
>> +	    (status & PB_STATUS_TEMPERATURE)) {
>> +		*error |= REGULATOR_ERROR_OVER_TEMP_WARN;
>> +		*event |= REGULATOR_EVENT_OVER_TEMP_WARN;
>> +	}
>>   
>>   	return 0;
>>   }
>>   
>> +static int pmbus_regulator_get_error_flags(struct regulator_dev *rdev, unsigned int *flags)
>> +{
>> +	unsigned int event;
>> +
>> +	return pmbus_regulator_get_flags(rdev, flags, &event);
>> +}
>> +
>>   static int pmbus_regulator_get_status(struct regulator_dev *rdev)
>>   {
>>   	struct device *dev = rdev_get_dev(rdev);
>> @@ -3060,14 +3078,61 @@ const struct regulator_ops pmbus_regulator_ops = {
>>   };
>>   EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
>>   
>> +static int pmbus_write_smbalert_mask(struct i2c_client *client, u8 page, u8 reg, u8 val)
>> +{
>> +	return pmbus_write_word_data(client, page, PMBUS_SMBALERT_MASK, reg | (val << 8));
>> +}
>> +
>> +static irqreturn_t pmbus_fault_handler(int irq, void *pdata)
>> +{
>> +	struct pmbus_data *data = pdata;
>> +	struct i2c_client *client = to_i2c_client(data->dev);
>> +	int i, ret = IRQ_NONE, status, event;
>> +	u8 page;
>> +
>> +	for (i = 0; i < data->info->num_regulators; i++) {
>> +
>> +		if (!data->rdevs[i])
>> +			continue;
>> +
>> +		ret = pmbus_regulator_get_flags(data->rdevs[i], &status, &event);
>> +		if (ret)
>> +			return ret;
>> +
>> +		if (event) {
>> +			regulator_notifier_call_chain(data->rdevs[i], event, NULL);
>> +			ret = IRQ_HANDLED;
>> +		}
>> +
>> +		page = rdev_get_id(data->rdevs[i]);
>> +		mutex_lock(&data->update_lock);
>> +		status = pmbus_read_status_word(client, page);
>> +		if (status < 0) {
>> +			mutex_unlock(&data->update_lock);
>> +			return status;
>> +		}
>> +
>> +		if (status & ~(PB_STATUS_OFF | PB_STATUS_BUSY | PB_STATUS_POWER_GOOD_N))
>> +			pmbus_clear_fault_page(client, page);
>> +
>> +		mutex_unlock(&data->update_lock);
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>>   static int pmbus_regulator_register(struct pmbus_data *data)
>>   {
>>   	struct device *dev = data->dev;
>>   	const struct pmbus_driver_info *info = data->info;
>>   	const struct pmbus_platform_data *pdata = dev_get_platdata(dev);
>> -	struct regulator_dev *rdev;
>>   	int i;
>>   
>> +	data->rdevs = devm_kzalloc(dev, sizeof(struct regulator_dev *) * info->num_regulators,
>> +				  GFP_KERNEL);
>> +	if (!data->rdevs)
>> +		return -ENOMEM;
>> +
>>   	for (i = 0; i < info->num_regulators; i++) {
>>   		struct regulator_config config = { };
>>   
>> @@ -3077,21 +3142,71 @@ static int pmbus_regulator_register(struct pmbus_data *data)
>>   		if (pdata && pdata->reg_init_data)
>>   			config.init_data = &pdata->reg_init_data[i];
>>   
>> -		rdev = devm_regulator_register(dev, &info->reg_desc[i],
>> +		data->rdevs[i] = devm_regulator_register(dev, &info->reg_desc[i],
>>   					       &config);
>> -		if (IS_ERR(rdev))
>> -			return dev_err_probe(dev, PTR_ERR(rdev),
>> +		if (IS_ERR(data->rdevs[i]))
>> +			return dev_err_probe(dev, PTR_ERR(data->rdevs[i]),
>>   					     "Failed to register %s regulator\n",
>>   					     info->reg_desc[i].name);
>>   	}
>>   
>>   	return 0;
>>   }
>> +
>> +static int pmbus_irq_setup(struct i2c_client *client, struct pmbus_data *data)
>> +{
>> +	struct device *dev = &client->dev;
>> +	const struct pmbus_regulator_status_category *cat;
>> +	const struct pmbus_regulator_status_assoc *bit;
>> +	int i, j, err, ret;
>> +	u8 mask;
>> +	int func;
>> +
>> +	for (i = 0; i < data->info->pages; i++) {
>> +		func = data->info->func[i];
>> +
>> +		for (j = 0; j < ARRAY_SIZE(pmbus_regulator_flag_map); j++) {
>> +			cat = &pmbus_regulator_flag_map[i];
>> +			if (!(func & cat->func))
>> +				continue;
>> +			mask = 0;
>> +			for (bit = cat->bits; bit->pflag; bit++)
>> +				mask |= bit->pflag;
>> +
>> +			err = pmbus_write_smbalert_mask(client, i, cat->reg, ~mask);
>> +			if (err)
>> +				dev_err(dev, "Failed to set smbalert for reg 0x%02x\n",	cat->reg);
>> +		}
>> +
>> +		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_CML, 0xff);
>> +		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_OTHER, 0xff);
>> +		pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_MFR_SPECIFIC, 0xff);
>> +		if (data->info->func[i] & PMBUS_HAVE_FAN12)
>> +			pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_FAN_12, 0xff);
>> +		if (data->info->func[i] & PMBUS_HAVE_FAN34)
>> +			pmbus_write_smbalert_mask(client, i, PMBUS_STATUS_FAN_34, 0xff);
>> +
>> +	}
>> +
>> +	/* Register notifiers - can fail if IRQ is not given */
>> +	ret = devm_request_threaded_irq(dev, client->irq, NULL, pmbus_fault_handler,
>> +			      0, "pmbus-irq", data);
>> +	if (ret) {
>> +		dev_warn(dev, "IRQ disabled %d\n", ret);
>> +		return ret;
>> +	}
>> +
>> +	return 0;
>> +}
>>   #else
>>   static int pmbus_regulator_register(struct pmbus_data *data)
>>   {
>>   	return 0;
>>   }
>> +static int pmbus_irq_setup(struct i2c_client *client, struct pmbus_data *data)
>> +{
>> +	return 0;
>> +}
>>   #endif
>>   
>>   static struct dentry *pmbus_debugfs_dir;	/* pmbus debugfs directory */
>> @@ -3456,6 +3571,12 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info)
>>   	if (ret)
>>   		return ret;
>>   
>> +	if (client->irq > 0) {
>> +		ret = pmbus_irq_setup(client, data);
>> +		if (ret)
>> +			return ret;
>> +	}
>> +
>>   	ret = pmbus_init_debugfs(client, data);
>>   	if (ret)
>>   		dev_warn(dev, "Failed to register debugfs\n");
>> -- 
>> 2.37.3
>>

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

end of thread, other threads:[~2022-11-30 18:27 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-11-30 16:59 [PATCH v3 1/4] hwmon: (pmbus/core): Add status byte to regulator flag map Naresh Solanki
2022-11-30 16:59 ` [PATCH v3 2/4] hwmon: (pmbus/core): Add events " Naresh Solanki
2022-11-30 16:59 ` [PATCH v3 3/4] hwmon: (pmbus/core): Implement irq support Naresh Solanki
2022-11-30 18:24   ` Guenter Roeck
2022-11-30 18:26     ` Naresh Solanki
2022-11-30 16:59 ` [PATCH v3 4/4] hwmon: (pmbus/core): Notify hwmon events Naresh Solanki

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.