All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Andreas Böhler" <dev@aboehler.at>
To: unlisted-recipients:; (no To-header on input)
Cc: dev@aboehler.at, Robert Marko <robert.marko@sartura.hr>,
	Luka Perkov <luka.perkov@sartura.hr>,
	Jean Delvare <jdelvare@suse.com>,
	Guenter Roeck <linux@roeck-us.net>,
	Rob Herring <robh+dt@kernel.org>,
	Krzysztof Kozlowski <krzysztof.kozlowski+dt@linaro.org>,
	linux-hwmon@vger.kernel.org, devicetree@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH v3 2/2] hwmon: tps23861: add support for initializing the chip
Date: Thu, 25 Aug 2022 16:37:37 +0200	[thread overview]
Message-ID: <20220825143737.77732-2-dev@aboehler.at> (raw)
In-Reply-To: <20220825143737.77732-1-dev@aboehler.at>

The tps23861 driver does not initialize the chip and relies on it being
in auto-mode by default. On some devices, these controllers default to
OFF-Mode and hence cannot be used at all.

This brings minimal support for initializing the controller in a user-
defined mode.

Tested on a TP-Link TL-SG2452P with 12x TI TPS23861 controllers.

Signed-off-by: Andreas Böhler <dev@aboehler.at>
---
 drivers/hwmon/tps23861.c | 81 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 81 insertions(+)

diff --git a/drivers/hwmon/tps23861.c b/drivers/hwmon/tps23861.c
index 42762e87b014..27bf8716cf12 100644
--- a/drivers/hwmon/tps23861.c
+++ b/drivers/hwmon/tps23861.c
@@ -85,6 +85,8 @@
 #define PORT_DETECT_CAPACITANCE_INVALID_DELTA	11
 #define PORT_DETECT_CAPACITANCE_OUT_OF_RANGE	12
 #define POE_PLUS			0x40
+#define POE_PLUS_MASK(_port)	\
+	GENMASK(_port + 4, _port + 4)
 #define OPERATING_MODE			0x12
 #define OPERATING_MODE_OFF		0
 #define OPERATING_MODE_MANUAL		1
@@ -94,9 +96,22 @@
 #define OPERATING_MODE_PORT_2_MASK	GENMASK(3, 2)
 #define OPERATING_MODE_PORT_3_MASK	GENMASK(5, 4)
 #define OPERATING_MODE_PORT_4_MASK	GENMASK(7, 6)
+#define OPERATING_MODE_PORT(_mode, _port)	\
+	(_mode << (_port * 2))
 
+#define DISCONNECT_ENABLE		0x13
+#define DISCONNECT_ENABLE_MASK(_port)	\
+	GENMASK(_port, _port)
+#define DISCONNECT_MASK(_port)	\
+	(GENMASK(_port, _port) | GENMASK(_port + 4, _port + 4))
+
+#define DETECT_CLASS_ENABLE		0x14
 #define DETECT_CLASS_RESTART		0x18
 #define POWER_ENABLE			0x19
+#define POWER_ENABLE_ON_MASK(_port)	\
+	GENMASK(_port, _port)
+#define POWER_ENABLE_OFF_MASK(_port)	\
+	GENMASK(_port + 4, _port + 4)
 #define TPS23861_NUM_PORTS		4
 
 #define TPS23861_GENERAL_MASK_1		0x17
@@ -548,7 +563,16 @@ static int tps23861_probe(struct i2c_client *client)
 	struct device *dev = &client->dev;
 	struct tps23861_data *data;
 	struct device *hwmon_dev;
+	struct device_node *child;
 	u32 shunt_resistor;
+	u32 reg;
+	u32 temp;
+	const char *mode;
+	unsigned int poe_plusval;
+	unsigned int mode_val;
+	unsigned int power_val;
+	unsigned int enable_val;
+	unsigned int disconnect_enable_val;
 
 	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
@@ -577,6 +601,63 @@ static int tps23861_probe(struct i2c_client *client)
 				TPS23861_GENERAL_MASK_1,
 				TPS23861_CURRENT_SHUNT_MASK);
 
+	regmap_read(data->regmap, POE_PLUS, &poe_plusval);
+	regmap_read(data->regmap, POWER_ENABLE, &power_val);
+	regmap_read(data->regmap, OPERATING_MODE, &mode_val);
+	regmap_read(data->regmap, DETECT_CLASS_ENABLE, &enable_val);
+	regmap_read(data->regmap, DISCONNECT_ENABLE, &disconnect_enable_val);
+
+	for_each_child_of_node(dev->of_node, child) {
+		if (of_property_read_u32(child, "reg", &reg))
+			continue;
+
+		if (reg > (TPS23861_NUM_PORTS - 1) || reg < 0)
+			continue;
+
+		if (!of_property_read_string(child, "mode", &mode)) {
+			if (!strncmp(mode, "manual", 6)) {
+				mode_val &= ~OPERATING_MODE_PORT(OPERATING_MODE_AUTO, reg);
+				mode_val |= OPERATING_MODE_PORT(OPERATING_MODE_MANUAL, reg);
+			} else if (!strncmp(mode, "semiauto", 8)) {
+				mode_val &= ~OPERATING_MODE_PORT(OPERATING_MODE_AUTO, reg);
+				mode_val |= OPERATING_MODE_PORT(OPERATING_MODE_SEMI, reg);
+			} else if (!strncmp(mode, "auto", 4))
+				mode_val |= OPERATING_MODE_PORT(OPERATING_MODE_AUTO, reg);
+			else
+				mode_val &= ~OPERATING_MODE_PORT(OPERATING_MODE_AUTO, reg);
+		}
+
+		if (!of_property_read_u32(child, "enable", &temp)) {
+			if (temp) {
+				enable_val |= DISCONNECT_MASK(reg);
+				disconnect_enable_val |= DISCONNECT_ENABLE_MASK(reg);
+			} else {
+				enable_val &= ~DISCONNECT_MASK(reg);
+				disconnect_enable_val &= ~DISCONNECT_ENABLE_MASK(reg);
+			}
+		}
+
+		if (!of_property_read_u32(child, "power", &temp)) {
+			if (temp)
+				power_val |= POWER_ENABLE_ON_MASK(reg);
+			else
+				power_val |= POWER_ENABLE_OFF_MASK(reg);
+		}
+
+		if (!of_property_read_u32(child, "poe_plus", &temp)) {
+			if (temp)
+				poe_plusval |= POE_PLUS_MASK(reg);
+			else
+				poe_plusval &= ~POE_PLUS_MASK(reg);
+		}
+	}
+
+	regmap_write(data->regmap, POE_PLUS, poe_plusval);
+	regmap_write(data->regmap, POWER_ENABLE, power_val);
+	regmap_write(data->regmap, OPERATING_MODE, mode_val);
+	regmap_write(data->regmap, DETECT_CLASS_ENABLE, enable_val);
+	regmap_write(data->regmap, DISCONNECT_ENABLE, disconnect_enable_val);
+
 	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
 							 data, &tps23861_chip_info,
 							 NULL);
-- 
2.37.2


  reply	other threads:[~2022-08-25 14:40 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2022-08-25 14:37 [PATCH v3 1/2] Documentation: devicetree: update bindings for tps23861 Andreas Böhler
2022-08-25 14:37 ` Andreas Böhler [this message]
2022-08-25 14:49 ` Krzysztof Kozlowski
2022-08-25 15:02 ` Guenter Roeck
2022-08-25 15:07   ` Robert Marko
2022-08-25 15:29     ` Guenter Roeck
2022-08-25 15:31       ` Robert Marko
2022-08-26  6:56         ` Krzysztof Kozlowski
2022-08-26 12:19           ` Guenter Roeck
2022-08-25 18:51 ` Rob Herring

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20220825143737.77732-2-dev@aboehler.at \
    --to=dev@aboehler.at \
    --cc=devicetree@vger.kernel.org \
    --cc=jdelvare@suse.com \
    --cc=krzysztof.kozlowski+dt@linaro.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=luka.perkov@sartura.hr \
    --cc=robert.marko@sartura.hr \
    --cc=robh+dt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.