All of lore.kernel.org
 help / color / mirror / Atom feed
From: Yassine Oudjana <y.oudjana@protonmail.com>
To: MyungJoo Ham <myungjoo.ham@samsung.com>,
	Chanwoo Choi <cw00.choi@samsung.com>,
	Rob Herring <robh+dt@kernel.org>
Cc: Yassine Oudjana <y.oudjana@protonmail.com>,
	Michael Auchter <michael.auchter@ni.com>,
	linux-kernel@vger.kernel.org, devicetree@vger.kernel.org
Subject: [PATCH v5 2/3] extcon: usbc-tusb320: Add support for TUSB320L
Date: Sat, 25 Sep 2021 05:45:54 +0000	[thread overview]
Message-ID: <20210925054407.944225-3-y.oudjana@protonmail.com> (raw)
In-Reply-To: <20210925054407.944225-1-y.oudjana@protonmail.com>

TUSB320L is a newer chip with additional features, and it has additional steps
in its mode changing sequence:
 - Disable CC state machine,
 - Write to mode register,
 - Wait for 5 ms,
 - Re-enable CC state machine.
It also has an additional register that a revision number can be read from.

Add support for the mode changing sequence, and read the revision number during
probe and print it as info.

Signed-off-by: Yassine Oudjana <y.oudjana@protonmail.com>
---
Changes since v4:
 - Use ops struct instead of type enum.
Changes since v3:
 - Remove extra blank line.
Changes since v2:
 - Use a separate mode setting function for each of TUSB320 and TUSB320L.
Changes since v1:
 - Split first patch into two patches, one adding support for mode setting and reset on TUSB320,
   and the other adding support for TUSB320L.
 drivers/extcon/extcon-usbc-tusb320.c | 82 +++++++++++++++++++++++++++-
 1 file changed, 79 insertions(+), 3 deletions(-)

diff --git a/drivers/extcon/extcon-usbc-tusb320.c b/drivers/extcon/extcon-usbc-tusb320.c
index 1ed1dfe54206..6ba3d89b106d 100644
--- a/drivers/extcon/extcon-usbc-tusb320.c
+++ b/drivers/extcon/extcon-usbc-tusb320.c
@@ -21,10 +21,13 @@
 #define TUSB320_REG9_INTERRUPT_STATUS		BIT(4)
 
 #define TUSB320_REGA				0xa
+#define TUSB320L_REGA_DISABLE_TERM		BIT(0)
 #define TUSB320_REGA_I2C_SOFT_RESET		BIT(3)
 #define TUSB320_REGA_MODE_SELECT_SHIFT		4
 #define TUSB320_REGA_MODE_SELECT_MASK		0x3
 
+#define TUSB320L_REGA0_REVISION			0xa0
+
 enum tusb320_attached_state {
 	TUSB320_ATTACHED_STATE_NONE,
 	TUSB320_ATTACHED_STATE_DFP,
@@ -39,11 +42,18 @@ enum tusb320_mode {
 	TUSB320_MODE_DRP,
 };
 
+struct tusb320_priv;
+
+struct tusb320_ops {
+	int (*set_mode)(struct tusb320_priv *priv, enum tusb320_mode mode);
+	int (*get_revision)(struct tusb320_priv *priv, unsigned int *revision);
+};
+
 struct tusb320_priv {
 	struct device *dev;
 	struct regmap *regmap;
 	struct extcon_dev *edev;
-
+	struct tusb320_ops *ops;
 	enum tusb320_attached_state state;
 };
 
@@ -99,12 +109,46 @@ static int tusb320_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode)
 	return 0;
 }
 
+static int tusb320l_set_mode(struct tusb320_priv *priv, enum tusb320_mode mode)
+{
+	int ret;
+
+	/* Disable CC state machine */
+	ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
+		TUSB320L_REGA_DISABLE_TERM, 1);
+	if (ret) {
+		dev_err(priv->dev,
+			"failed to disable CC state machine: %d\n", ret);
+		return ret;
+	}
+
+	/* Write mode */
+	ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
+		TUSB320_REGA_MODE_SELECT_MASK << TUSB320_REGA_MODE_SELECT_SHIFT,
+		mode << TUSB320_REGA_MODE_SELECT_SHIFT);
+	if (ret) {
+		dev_err(priv->dev, "failed to write mode: %d\n", ret);
+		goto err;
+	}
+
+	msleep(5);
+err:
+	/* Re-enable CC state machine */
+	ret = regmap_write_bits(priv->regmap, TUSB320_REGA,
+		TUSB320L_REGA_DISABLE_TERM, 0);
+	if (ret)
+		dev_err(priv->dev,
+			"failed to re-enable CC state machine: %d\n", ret);
+
+	return ret;
+}
+
 static int tusb320_reset(struct tusb320_priv *priv)
 {
 	int ret;
 
 	/* Set mode to default (follow PORT pin) */
-	ret = tusb320_set_mode(priv, TUSB320_MODE_PORT);
+	ret = priv->ops->set_mode(priv, TUSB320_MODE_PORT);
 	if (ret && ret != -EBUSY) {
 		dev_err(priv->dev,
 			"failed to set mode to PORT: %d\n", ret);
@@ -126,6 +170,20 @@ static int tusb320_reset(struct tusb320_priv *priv)
 	return 0;
 }
 
+static int tusb320l_get_revision(struct tusb320_priv *priv, unsigned int *revision)
+{
+	return regmap_read(priv->regmap, TUSB320L_REGA0_REVISION, revision);
+}
+
+static struct tusb320_ops tusb320_ops = {
+	.set_mode = tusb320_set_mode,
+};
+
+static struct tusb320_ops tusb320l_ops = {
+	.set_mode = tusb320l_set_mode,
+	.get_revision = tusb320l_get_revision,
+};
+
 static irqreturn_t tusb320_irq_handler(int irq, void *dev_id)
 {
 	struct tusb320_priv *priv = dev_id;
@@ -176,6 +234,8 @@ static int tusb320_extcon_probe(struct i2c_client *client,
 				const struct i2c_device_id *id)
 {
 	struct tusb320_priv *priv;
+	const void *match_data;
+	unsigned int revision;
 	int ret;
 
 	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
@@ -191,12 +251,27 @@ static int tusb320_extcon_probe(struct i2c_client *client,
 	if (ret)
 		return ret;
 
+	match_data = device_get_match_data(&client->dev);
+	if (!match_data)
+		return -EINVAL;
+
+	priv->ops = (struct tusb320_ops*)match_data;
+
 	priv->edev = devm_extcon_dev_allocate(priv->dev, tusb320_extcon_cable);
 	if (IS_ERR(priv->edev)) {
 		dev_err(priv->dev, "failed to allocate extcon device\n");
 		return PTR_ERR(priv->edev);
 	}
 
+	if (priv->ops->get_revision) {
+		ret = priv->ops->get_revision(priv, &revision);
+		if (ret)
+			dev_warn(priv->dev,
+				"failed to read revision register: %d\n", ret);
+		else
+			dev_info(priv->dev, "chip revision %d\n", revision);
+	}
+
 	ret = devm_extcon_dev_register(priv->dev, priv->edev);
 	if (ret < 0) {
 		dev_err(priv->dev, "failed to register extcon device\n");
@@ -231,7 +306,8 @@ static int tusb320_extcon_probe(struct i2c_client *client,
 }
 
 static const struct of_device_id tusb320_extcon_dt_match[] = {
-	{ .compatible = "ti,tusb320", },
+	{ .compatible = "ti,tusb320", .data = &tusb320_ops, },
+	{ .compatible = "ti,tusb320l", .data = &tusb320l_ops, },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, tusb320_extcon_dt_match);
-- 
2.33.0



  parent reply	other threads:[~2021-09-25  5:46 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <CGME20210925054535epcas1p45ad283474c848a9ec83febd44b4965b5@epcas1p4.samsung.com>
2021-09-25  5:45 ` [PATCH v5 0/3] extcon: usbc-tusb320: Initial TUSB320L support Yassine Oudjana
2021-09-25  5:45   ` [PATCH v5 1/3] extcon: usbc-tusb320: Add support for mode setting and reset Yassine Oudjana
2021-09-25  5:45   ` Yassine Oudjana [this message]
2021-09-25  5:46   ` [PATCH v5 3/3] dt-bindings: extcon: usbc-tusb320: Add TUSB320L compatible string Yassine Oudjana
2021-09-30  3:36   ` [PATCH v5 0/3] extcon: usbc-tusb320: Initial TUSB320L support Chanwoo Choi

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=20210925054407.944225-3-y.oudjana@protonmail.com \
    --to=y.oudjana@protonmail.com \
    --cc=cw00.choi@samsung.com \
    --cc=devicetree@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=michael.auchter@ni.com \
    --cc=myungjoo.ham@samsung.com \
    --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.