gbmc-release-23.18.x: linux: Patch in adm1275 driver fixes

The adm1275 driver fixes can potentiall causes production issue and
needs to be released on all existing platforms. Without theses changes,
the driver config may change during runtime and causes the machine to
reset due to bad power controller settings.

Google-Bug-Id: 292103432
Change-Id: Iaa3a116bdbf0e5e1020a69d16aedf083f251adff
Signed-off-by: Willy Tu <wltu@google.com>
diff --git a/recipes-kernel/linux/5.15/0001-hwmon-pmbus-adm1275-Fix-problems-with-temperature-mo.patch b/recipes-kernel/linux/5.15/0001-hwmon-pmbus-adm1275-Fix-problems-with-temperature-mo.patch
new file mode 100644
index 0000000..63d57d2
--- /dev/null
+++ b/recipes-kernel/linux/5.15/0001-hwmon-pmbus-adm1275-Fix-problems-with-temperature-mo.patch
@@ -0,0 +1,128 @@
+From 4712f3b4bf087b0e1581f17ad21ec7629065af1f Mon Sep 17 00:00:00 2001
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Fri, 2 Jun 2023 14:34:47 -0700
+Subject: [PATCH 1/3] hwmon: (pmbus/adm1275) Fix problems with temperature
+ monitoring on ADM1272
+
+The PMON_CONFIG register on ADM1272 is a 16 bit register. Writing a 8 bit
+value into it clears the upper 8 bits of the register, resulting in
+unexpected side effects. Fix by writing the 16 bit register value.
+
+Also, it has been reported that temperature readings are sometimes widely
+inaccurate, to the point where readings may result in device shutdown due
+to errant overtemperature faults. Improve by enabling temperature sampling.
+
+While at it, move the common code for ADM1272 and ADM1278 into a separate
+function, and clarify in the error message that an attempt was made to
+enable both VOUT and temperature monitoring.
+
+Last but not least, return the error code reported by the underlying I2C
+controller and not -ENODEV if updating the PMON_CONFIG register fails.
+After all, this does not indicate that the chip is not present, but an
+error in the communication with the chip.
+
+Fixes: 4ff0ce227a1e ("hwmon: (pmbus/adm1275) Add support for ADM1272")
+Fixes: 9da9c2dc57b2 ("hwmon: (adm1275) enable adm1272 temperature reporting")
+Change-Id: I4b4ad21019df9004fb5e65a1009527f02f6c2291
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20230602213447.3557346-1-linux@roeck-us.net
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Git-repo: https://github.com/torvalds/linux
+Upstream-v6.5-rc2-SHA1: b153a0bb4199566abd337119207f82b59a8cd1ca
+Signed-off-by: Willy Tu <wltu@google.com>
+(cherry picked from commit ff839f5979f66fec4285419024c244856d7f38ef)
+---
+ drivers/hwmon/pmbus/adm1275.c | 52 +++++++++++++++++------------------
+ 1 file changed, 26 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
+index 3b07bfb43e93..b8543c06d022 100644
+--- a/drivers/hwmon/pmbus/adm1275.c
++++ b/drivers/hwmon/pmbus/adm1275.c
+@@ -37,10 +37,13 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
+ 
+ #define ADM1272_IRANGE			BIT(0)
+ 
++#define ADM1278_TSFILT			BIT(15)
+ #define ADM1278_TEMP1_EN		BIT(3)
+ #define ADM1278_VIN_EN			BIT(2)
+ #define ADM1278_VOUT_EN			BIT(1)
+ 
++#define ADM1278_PMON_DEFCONFIG		(ADM1278_VOUT_EN | ADM1278_TEMP1_EN | ADM1278_TSFILT)
++
+ #define ADM1293_IRANGE_25		0
+ #define ADM1293_IRANGE_50		BIT(6)
+ #define ADM1293_IRANGE_100		BIT(7)
+@@ -462,6 +465,22 @@ static const struct i2c_device_id adm1275_id[] = {
+ };
+ MODULE_DEVICE_TABLE(i2c, adm1275_id);
+ 
++/* Enable VOUT & TEMP1 if not enabled (disabled by default) */
++static int adm1275_enable_vout_temp(struct i2c_client *client, int config)
++{
++	int ret;
++
++	if ((config & ADM1278_PMON_DEFCONFIG) != ADM1278_PMON_DEFCONFIG) {
++		config |= ADM1278_PMON_DEFCONFIG;
++		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, config);
++		if (ret < 0) {
++			dev_err(&client->dev, "Failed to enable VOUT/TEMP1 monitoring\n");
++			return ret;
++		}
++	}
++	return 0;
++}
++
+ static int adm1275_probe(struct i2c_client *client)
+ {
+ 	s32 (*config_read_fn)(const struct i2c_client *client, u8 reg);
+@@ -615,19 +634,10 @@ static int adm1275_probe(struct i2c_client *client)
+ 			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ 			PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ 
+-		/* Enable VOUT & TEMP1 if not enabled (disabled by default) */
+-		if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) !=
+-		    (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) {
+-			config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN;
+-			ret = i2c_smbus_write_byte_data(client,
+-							ADM1275_PMON_CONFIG,
+-							config);
+-			if (ret < 0) {
+-				dev_err(&client->dev,
+-					"Failed to enable VOUT monitoring\n");
+-				return -ENODEV;
+-			}
+-		}
++		ret = adm1275_enable_vout_temp(client, config);
++		if (ret)
++			return ret;
++
+ 		if (config & ADM1278_VIN_EN)
+ 			info->func[0] |= PMBUS_HAVE_VIN;
+ 		break;
+@@ -684,19 +694,9 @@ static int adm1275_probe(struct i2c_client *client)
+ 			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ 			PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ 
+-		/* Enable VOUT & TEMP1 if not enabled (disabled by default) */
+-		if ((config & (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) !=
+-		    (ADM1278_VOUT_EN | ADM1278_TEMP1_EN)) {
+-			config |= ADM1278_VOUT_EN | ADM1278_TEMP1_EN;
+-			ret = i2c_smbus_write_word_data(client,
+-							ADM1275_PMON_CONFIG,
+-							config);
+-			if (ret < 0) {
+-				dev_err(&client->dev,
+-					"Failed to enable VOUT monitoring\n");
+-				return -ENODEV;
+-			}
+-		}
++		ret = adm1275_enable_vout_temp(client, config);
++		if (ret)
++			return ret;
+ 
+ 		if (config & ADM1278_VIN_EN)
+ 			info->func[0] |= PMBUS_HAVE_VIN;
+-- 
+2.42.0.rc1.204.g551eb34607-goog
+
diff --git a/recipes-kernel/linux/5.15/0002-hwmon-pmbus-adm1275-Prepare-for-protected-write-to-P.patch b/recipes-kernel/linux/5.15/0002-hwmon-pmbus-adm1275-Prepare-for-protected-write-to-P.patch
new file mode 100644
index 0000000..9fbc80a
--- /dev/null
+++ b/recipes-kernel/linux/5.15/0002-hwmon-pmbus-adm1275-Prepare-for-protected-write-to-P.patch
@@ -0,0 +1,177 @@
+From 47ae63d46d3fde160da18b13fd479899451aaaa1 Mon Sep 17 00:00:00 2001
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Wed, 14 Jun 2023 09:36:04 -0700
+Subject: [PATCH 2/3] hwmon: (pmbus/adm1275) Prepare for protected write to
+ PMON_CONFIG
+
+According to ADI, changing PMON_CONFIG while ADC is running can have
+unexpected results. ADI recommends halting the ADC with PMON_CONTROL
+before setting PMON_CONFIG and then resume after.
+
+To prepare for this change, rename adm1275_read_pmon_config()
+and adm1275_write_pmon_config() to adm1275_read_samples() and
+adm1275_write_samples() to more accurately reflect the functionality
+of the code. Introduce new function adm1275_write_pmon_config()
+and use it for all code writing into the PMON_CONFIG register.
+
+Change-Id: I20ee04b7b52e3f0141254aa6bca199077b540a32
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20230614163605.3688964-2-linux@roeck-us.net
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Git-repo: https://github.com/torvalds/linux
+Upstream-v6.5-rc2-SHA1: 98ac8af4e7b2f260236cf468762450630e73eb67
+Signed-off-by: Willy Tu <wltu@google.com>
+(cherry picked from commit 533e63bff7900e7a2739fea087445be0716069b5)
+---
+ drivers/hwmon/pmbus/adm1275.c | 56 +++++++++++++++++++----------------
+ 1 file changed, 31 insertions(+), 25 deletions(-)
+
+diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
+index b8543c06d022..eaa691b98c14 100644
+--- a/drivers/hwmon/pmbus/adm1275.c
++++ b/drivers/hwmon/pmbus/adm1275.c
+@@ -173,8 +173,8 @@ static const struct coefficients adm1293_coefficients[] = {
+ 	[18] = { 7658, 0, -3 },		/* power, 21V, irange200 */
+ };
+ 
+-static int adm1275_read_pmon_config(const struct adm1275_data *data,
+-				    struct i2c_client *client, bool is_power)
++static int adm1275_read_samples(const struct adm1275_data *data,
++				struct i2c_client *client, bool is_power)
+ {
+ 	int shift, ret;
+ 	u16 mask;
+@@ -200,8 +200,23 @@ static int adm1275_read_pmon_config(const struct adm1275_data *data,
+ }
+ 
+ static int adm1275_write_pmon_config(const struct adm1275_data *data,
+-				     struct i2c_client *client,
+-				     bool is_power, u16 word)
++				     struct i2c_client *client, u16 word)
++{
++	int ret;
++
++	if (data->have_power_sampling)
++		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
++						word);
++	else
++		ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
++						word);
++
++	return ret;
++}
++
++static int adm1275_write_samples(const struct adm1275_data *data,
++				 struct i2c_client *client,
++				 bool is_power, u16 word)
+ {
+ 	int shift, ret;
+ 	u16 mask;
+@@ -219,14 +234,8 @@ static int adm1275_write_pmon_config(const struct adm1275_data *data,
+ 		return ret;
+ 
+ 	word = (ret & ~mask) | ((word << shift) & mask);
+-	if (data->have_power_sampling)
+-		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
+-						word);
+-	else
+-		ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
+-						word);
+ 
+-	return ret;
++	return adm1275_write_pmon_config(data, client, word);
+ }
+ 
+ static int adm1275_read_word_data(struct i2c_client *client, int page,
+@@ -321,14 +330,14 @@ static int adm1275_read_word_data(struct i2c_client *client, int page,
+ 	case PMBUS_VIRT_POWER_SAMPLES:
+ 		if (!data->have_power_sampling)
+ 			return -ENXIO;
+-		ret = adm1275_read_pmon_config(data, client, true);
++		ret = adm1275_read_samples(data, client, true);
+ 		if (ret < 0)
+ 			break;
+ 		ret = BIT(ret);
+ 		break;
+ 	case PMBUS_VIRT_IN_SAMPLES:
+ 	case PMBUS_VIRT_CURR_SAMPLES:
+-		ret = adm1275_read_pmon_config(data, client, false);
++		ret = adm1275_read_samples(data, client, false);
+ 		if (ret < 0)
+ 			break;
+ 		ret = BIT(ret);
+@@ -381,14 +390,12 @@ static int adm1275_write_word_data(struct i2c_client *client, int page, int reg,
+ 		if (!data->have_power_sampling)
+ 			return -ENXIO;
+ 		word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
+-		ret = adm1275_write_pmon_config(data, client, true,
+-						ilog2(word));
++		ret = adm1275_write_samples(data, client, true, ilog2(word));
+ 		break;
+ 	case PMBUS_VIRT_IN_SAMPLES:
+ 	case PMBUS_VIRT_CURR_SAMPLES:
+ 		word = clamp_val(word, 1, ADM1275_SAMPLES_AVG_MAX);
+-		ret = adm1275_write_pmon_config(data, client, false,
+-						ilog2(word));
++		ret = adm1275_write_samples(data, client, false, ilog2(word));
+ 		break;
+ 	default:
+ 		ret = -ENODATA;
+@@ -466,13 +473,14 @@ static const struct i2c_device_id adm1275_id[] = {
+ MODULE_DEVICE_TABLE(i2c, adm1275_id);
+ 
+ /* Enable VOUT & TEMP1 if not enabled (disabled by default) */
+-static int adm1275_enable_vout_temp(struct i2c_client *client, int config)
++static int adm1275_enable_vout_temp(struct adm1275_data *data,
++				    struct i2c_client *client, int config)
+ {
+ 	int ret;
+ 
+ 	if ((config & ADM1278_PMON_DEFCONFIG) != ADM1278_PMON_DEFCONFIG) {
+ 		config |= ADM1278_PMON_DEFCONFIG;
+-		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG, config);
++		ret = adm1275_write_pmon_config(data, client, config);
+ 		if (ret < 0) {
+ 			dev_err(&client->dev, "Failed to enable VOUT/TEMP1 monitoring\n");
+ 			return ret;
+@@ -634,7 +642,7 @@ static int adm1275_probe(struct i2c_client *client)
+ 			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ 			PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ 
+-		ret = adm1275_enable_vout_temp(client, config);
++		ret = adm1275_enable_vout_temp(data, client, config);
+ 		if (ret)
+ 			return ret;
+ 
+@@ -694,7 +702,7 @@ static int adm1275_probe(struct i2c_client *client)
+ 			PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT |
+ 			PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP;
+ 
+-		ret = adm1275_enable_vout_temp(client, config);
++		ret = adm1275_enable_vout_temp(data, client, config);
+ 		if (ret)
+ 			return ret;
+ 
+@@ -766,8 +774,7 @@ static int adm1275_probe(struct i2c_client *client)
+ 				"Invalid number of power samples");
+ 			return -EINVAL;
+ 		}
+-		ret = adm1275_write_pmon_config(data, client, true,
+-						ilog2(avg));
++		ret = adm1275_write_samples(data, client, true, ilog2(avg));
+ 		if (ret < 0) {
+ 			dev_err(&client->dev,
+ 				"Setting power sample averaging failed with error %d",
+@@ -784,8 +791,7 @@ static int adm1275_probe(struct i2c_client *client)
+ 				"Invalid number of voltage/current samples");
+ 			return -EINVAL;
+ 		}
+-		ret = adm1275_write_pmon_config(data, client, false,
+-						ilog2(avg));
++		ret = adm1275_write_samples(data, client, false, ilog2(avg));
+ 		if (ret < 0) {
+ 			dev_err(&client->dev,
+ 				"Setting voltage and current sample averaging failed with error %d",
+-- 
+2.42.0.rc1.204.g551eb34607-goog
+
diff --git a/recipes-kernel/linux/5.15/0003-hwmon-pmbus-adm1275-Disable-ADC-while-updating-PMON_.patch b/recipes-kernel/linux/5.15/0003-hwmon-pmbus-adm1275-Disable-ADC-while-updating-PMON_.patch
new file mode 100644
index 0000000..7686296
--- /dev/null
+++ b/recipes-kernel/linux/5.15/0003-hwmon-pmbus-adm1275-Disable-ADC-while-updating-PMON_.patch
@@ -0,0 +1,71 @@
+From e04afe92e6c710fb431245f29154aa8094cbefec Mon Sep 17 00:00:00 2001
+From: Guenter Roeck <linux@roeck-us.net>
+Date: Wed, 14 Jun 2023 09:36:05 -0700
+Subject: [PATCH 3/3] hwmon: (pmbus/adm1275) Disable ADC while updating
+ PMON_CONFIG
+
+According to ADI, changing PMON_CONFIG while the ADC is running can have
+unexpected results. ADI recommends halting the ADC with PMON_CONTROL
+before setting PMON_CONFIG and then resume after. Follow ADI
+recommendation and disable ADC while PMON_CONFIG is updated.
+
+Change-Id: I4f4afc221f67596b2c7509645394718d4fe4f471
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Link: https://lore.kernel.org/r/20230614163605.3688964-3-linux@roeck-us.net
+Signed-off-by: Guenter Roeck <linux@roeck-us.net>
+Git-repo: https://github.com/torvalds/linux
+Upstream-v6.5-rc2-SHA1: dd5219ce4f295a129ee38baff308f9c1e4f0761b
+Signed-off-by: Willy Tu <wltu@google.com>
+(cherry picked from commit 584b216c911456fa2732bc7b9648bdc62afe5e4f)
+---
+ drivers/hwmon/pmbus/adm1275.c | 18 +++++++++++++++++-
+ 1 file changed, 17 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
+index eaa691b98c14..501646cbef10 100644
+--- a/drivers/hwmon/pmbus/adm1275.c
++++ b/drivers/hwmon/pmbus/adm1275.c
+@@ -27,8 +27,11 @@ enum chips { adm1075, adm1272, adm1275, adm1276, adm1278, adm1293, adm1294 };
+ #define ADM1275_PEAK_IOUT		0xd0
+ #define ADM1275_PEAK_VIN		0xd1
+ #define ADM1275_PEAK_VOUT		0xd2
++#define ADM1275_PMON_CONTROL		0xd3
+ #define ADM1275_PMON_CONFIG		0xd4
+ 
++#define ADM1275_CONVERT_EN		BIT(0)
++
+ #define ADM1275_VIN_VOUT_SELECT		BIT(6)
+ #define ADM1275_VRANGE			BIT(5)
+ #define ADM1075_IRANGE_50		BIT(4)
+@@ -202,7 +205,11 @@ static int adm1275_read_samples(const struct adm1275_data *data,
+ static int adm1275_write_pmon_config(const struct adm1275_data *data,
+ 				     struct i2c_client *client, u16 word)
+ {
+-	int ret;
++	int ret, ret2;
++
++	ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONTROL, 0);
++	if (ret)
++		return ret;
+ 
+ 	if (data->have_power_sampling)
+ 		ret = i2c_smbus_write_word_data(client, ADM1275_PMON_CONFIG,
+@@ -211,6 +218,15 @@ static int adm1275_write_pmon_config(const struct adm1275_data *data,
+ 		ret = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONFIG,
+ 						word);
+ 
++	/*
++	 * We still want to re-enable conversions if writing into
++	 * ADM1275_PMON_CONFIG failed.
++	 */
++	ret2 = i2c_smbus_write_byte_data(client, ADM1275_PMON_CONTROL,
++					 ADM1275_CONVERT_EN);
++	if (!ret)
++		ret = ret2;
++
+ 	return ret;
+ }
+ 
+-- 
+2.42.0.rc1.204.g551eb34607-goog
+
diff --git a/recipes-kernel/linux/linux-gbmc_5.15.bb b/recipes-kernel/linux/linux-gbmc_5.15.bb
index 4dceec5..537b231 100644
--- a/recipes-kernel/linux/linux-gbmc_5.15.bb
+++ b/recipes-kernel/linux/linux-gbmc_5.15.bb
@@ -6,7 +6,12 @@
 LIC_FILES_CHKSUM = "file://COPYING;md5=6bc538ed5bd9a7fc9398086aedcd7e46"
 
 FILESEXTRAPATHS:prepend := "${THISDIR}/5.15:"
-SRC_URI += "file://DOWNSTREAM_0002-mtd-spi-nor-macronix-Add-google-compatible-flash-IDs.patch"
+SRC_URI += " \
+  file://DOWNSTREAM_0002-mtd-spi-nor-macronix-Add-google-compatible-flash-IDs.patch \
+  file://0001-hwmon-pmbus-adm1275-Fix-problems-with-temperature-mo.patch \
+  file://0002-hwmon-pmbus-adm1275-Prepare-for-protected-write-to-P.patch \
+  file://0003-hwmon-pmbus-adm1275-Disable-ADC-while-updating-PMON_.patch \
+"
 
 SRC_URI:append:aspeed-g6 = " \
   file://0001-net-ftgmac100-Support-for-fixed-PHYs.patch \