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: <20250131163408.2019144-7-laurentiu.palcu@oss.nxp.com>
Date: Fri, 31 Jan 2025 18:34:00 +0200
From: Laurentiu Palcu <laurentiu.palcu@....nxp.com>
To: Niklas Söderlund <niklas.soderlund@...natech.se>,
	Mauro Carvalho Chehab <mchehab@...nel.org>,
	Greg Kroah-Hartman <gregkh@...uxfoundation.org>
Cc: Laurentiu Palcu <laurentiu.palcu@....nxp.com>,
	linux-kernel@...r.kernel.org,
	linux-media@...r.kernel.org,
	linux-staging@...ts.linux.dev
Subject: [RFC 06/12] staging: media: max96712: add I2C mux support

The deserializer chip allows communicating with remote serializers over
an I2C control channel within the GMSL link. However, to avoid address
collisions, we need to enable only the I2C CC corresponding to a
certain GMSL link and disable the other ones. Hence, add support for
I2C multiplexer which will allow us to do just that.

Signed-off-by: Laurentiu Palcu <laurentiu.palcu@....nxp.com>
---
 drivers/staging/media/max96712/max96712.c | 76 ++++++++++++++++++++++-
 1 file changed, 75 insertions(+), 1 deletion(-)

diff --git a/drivers/staging/media/max96712/max96712.c b/drivers/staging/media/max96712/max96712.c
index 546660e4b3d1e..f68a1d241b846 100644
--- a/drivers/staging/media/max96712/max96712.c
+++ b/drivers/staging/media/max96712/max96712.c
@@ -8,6 +8,7 @@
 
 #include <linux/delay.h>
 #include <linux/i2c.h>
+#include <linux/i2c-mux.h>
 #include <linux/module.h>
 #include <linux/of_graph.h>
 #include <linux/regmap.h>
@@ -17,6 +18,17 @@
 #include <media/v4l2-fwnode.h>
 #include <media/v4l2-subdev.h>
 
+/* DEV */
+#define MAX96712_DEV_REG3				CCI_REG8(0x0003)
+#define   DIS_REM_CC_A_MASK				GENMASK(1, 0)
+#define   DIS_REM_CC_A_SHIFT				0
+#define   DIS_REM_CC_B_MASK				GENMASK(3, 2)
+#define   DIS_REM_CC_B_SHIFT				2
+#define   DIS_REM_CC_C_MASK				GENMASK(5, 4)
+#define   DIS_REM_CC_C_SHIFT				4
+#define   DIS_REM_CC_D_MASK				GENMASK(7, 6)
+#define   DIS_REM_CC_D_SHIFT				6
+
 /* TOP_CTRL */
 #define MAX96712_DEBUG_EXTRA_REG			CCI_REG8(0x0009)
 #define   DEBUG_EXTRA_PCLK_25MHZ			0x00
@@ -162,6 +174,9 @@ struct max96712_priv {
 	struct regmap *regmap;
 	struct gpio_desc *gpiod_pwdn;
 
+	struct i2c_mux_core *mux;
+	int mux_chan;
+
 	const struct max96712_info *info;
 
 	bool cphy;
@@ -489,6 +504,61 @@ static int max96712_v4l2_register(struct max96712_priv *priv)
 	return ret;
 }
 
+static int max96712_i2c_mux_select(struct i2c_mux_core *muxc, u32 chan)
+{
+	struct max96712_priv *priv = i2c_mux_priv(muxc);
+	u8 val = 0xff;
+
+	if (priv->mux_chan == chan)
+		return 0;
+
+	val &= ~(0x3 << (chan * 2));
+	val |= 0x2 << (chan * 2);
+	max96712_write(priv, MAX96712_DEV_REG3, val);
+
+	priv->mux_chan = chan;
+
+	return 0;
+}
+
+static int max96712_i2c_init(struct max96712_priv *priv)
+{
+	int link;
+	int ret;
+
+	if (!i2c_check_functionality(priv->client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		return -ENODEV;
+
+	priv->mux_chan = -1;
+
+	priv->mux = i2c_mux_alloc(priv->client->adapter, &priv->client->dev,
+				  priv->n_rx_ports, 0, I2C_MUX_LOCKED,
+				  max96712_i2c_mux_select, NULL);
+	if (!priv->mux) {
+		dev_err(&priv->client->dev, "Could not alloc I2C multiplexer.\n");
+		return -ENOMEM;
+	}
+
+	priv->mux->priv = priv;
+
+	for (link = 0; link < MAX96712_MAX_RX_PORTS; link++) {
+		if (!(priv->rx_port_mask & BIT(link)))
+			continue;
+
+		ret = i2c_mux_add_adapter(priv->mux, 0, link);
+		if (ret < 0) {
+			dev_err(&priv->client->dev, "Could not add I2C mux adapter.\n");
+			goto error;
+		}
+	}
+
+	return 0;
+
+error:
+	i2c_mux_del_adapters(priv->mux);
+	return ret;
+}
+
 static int max96712_parse_rx_ports(struct max96712_priv *priv, struct device_node *node,
 				   struct of_endpoint *ep)
 {
@@ -665,7 +735,11 @@ static int max96712_probe(struct i2c_client *client)
 
 	max96712_mipi_configure(priv);
 
-	return max96712_v4l2_register(priv);
+	ret = max96712_v4l2_register(priv);
+	if (ret)
+		return ret;
+
+	return max96712_i2c_init(priv);
 }
 
 static void max96712_remove(struct i2c_client *client)
-- 
2.44.1


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ