diff mbox series

[v2,2/2] usb: typec: hd3ss3220: Add polling support

Message ID 20221209171836.71610-3-biju.das.jz@bp.renesas.com (mailing list archive)
State Accepted
Commit 569d23e9bf58464887c55aa0d2bdb0ead97f8592
Headers show
Series Add Polling support for role detection with HD3SS3220 | expand

Commit Message

Biju Das Dec. 9, 2022, 5:18 p.m. UTC
Some platforms(for eg: RZ/V2M EVK) does not have interrupt pin
connected to HD3SS3220. Add polling support for role detection.

Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>
---
v1->v2:
 * Dropped patch#3 for soring header files.
---
 drivers/usb/typec/hd3ss3220.c | 29 +++++++++++++++++++++++++++++
 1 file changed, 29 insertions(+)

Comments

Heikki Krogerus Dec. 13, 2022, 9:17 a.m. UTC | #1
On Fri, Dec 09, 2022 at 05:18:36PM +0000, Biju Das wrote:
> Some platforms(for eg: RZ/V2M EVK) does not have interrupt pin
> connected to HD3SS3220. Add polling support for role detection.
> 
> Signed-off-by: Biju Das <biju.das.jz@bp.renesas.com>

Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>

> ---
> v1->v2:
>  * Dropped patch#3 for soring header files.
> ---
>  drivers/usb/typec/hd3ss3220.c | 29 +++++++++++++++++++++++++++++
>  1 file changed, 29 insertions(+)
> 
> diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c
> index c24bbccd14f9..a445c1bd0627 100644
> --- a/drivers/usb/typec/hd3ss3220.c
> +++ b/drivers/usb/typec/hd3ss3220.c
> @@ -14,6 +14,7 @@
>  #include <linux/slab.h>
>  #include <linux/usb/typec.h>
>  #include <linux/delay.h>
> +#include <linux/workqueue.h>
>  
>  #define HD3SS3220_REG_CN_STAT_CTRL	0x09
>  #define HD3SS3220_REG_GEN_CTRL		0x0A
> @@ -37,6 +38,9 @@ struct hd3ss3220 {
>  	struct regmap *regmap;
>  	struct usb_role_switch	*role_sw;
>  	struct typec_port *port;
> +	struct delayed_work output_poll_work;
> +	enum usb_role role_state;
> +	bool poll;
>  };
>  
>  static int hd3ss3220_set_source_pref(struct hd3ss3220 *hd3ss3220, int src_pref)
> @@ -118,6 +122,22 @@ static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220)
>  	default:
>  		break;
>  	}
> +
> +	hd3ss3220->role_state = role_state;
> +}
> +
> +static void output_poll_execute(struct work_struct *work)
> +{
> +	struct delayed_work *delayed_work = to_delayed_work(work);
> +	struct hd3ss3220 *hd3ss3220 = container_of(delayed_work,
> +						   struct hd3ss3220,
> +						   output_poll_work);
> +	enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
> +
> +	if (hd3ss3220->role_state != role_state)
> +		hd3ss3220_set_role(hd3ss3220);
> +
> +	schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
>  }
>  
>  static irqreturn_t hd3ss3220_irq(struct hd3ss3220 *hd3ss3220)
> @@ -227,6 +247,9 @@ static int hd3ss3220_probe(struct i2c_client *client,
>  					"hd3ss3220", &client->dev);
>  		if (ret)
>  			goto err_unreg_port;
> +	} else {
> +		INIT_DELAYED_WORK(&hd3ss3220->output_poll_work, output_poll_execute);
> +		hd3ss3220->poll = true;
>  	}
>  
>  	ret = i2c_smbus_read_byte_data(client, HD3SS3220_REG_DEV_REV);
> @@ -235,6 +258,9 @@ static int hd3ss3220_probe(struct i2c_client *client,
>  
>  	fwnode_handle_put(connector);
>  
> +	if (hd3ss3220->poll)
> +		schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
> +
>  	dev_info(&client->dev, "probed revision=0x%x\n", ret);
>  
>  	return 0;
> @@ -252,6 +278,9 @@ static void hd3ss3220_remove(struct i2c_client *client)
>  {
>  	struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
>  
> +	if (hd3ss3220->poll)
> +		cancel_delayed_work_sync(&hd3ss3220->output_poll_work);
> +
>  	typec_unregister_port(hd3ss3220->port);
>  	usb_role_switch_put(hd3ss3220->role_sw);
>  }
> -- 
> 2.25.1
diff mbox series

Patch

diff --git a/drivers/usb/typec/hd3ss3220.c b/drivers/usb/typec/hd3ss3220.c
index c24bbccd14f9..a445c1bd0627 100644
--- a/drivers/usb/typec/hd3ss3220.c
+++ b/drivers/usb/typec/hd3ss3220.c
@@ -14,6 +14,7 @@ 
 #include <linux/slab.h>
 #include <linux/usb/typec.h>
 #include <linux/delay.h>
+#include <linux/workqueue.h>
 
 #define HD3SS3220_REG_CN_STAT_CTRL	0x09
 #define HD3SS3220_REG_GEN_CTRL		0x0A
@@ -37,6 +38,9 @@  struct hd3ss3220 {
 	struct regmap *regmap;
 	struct usb_role_switch	*role_sw;
 	struct typec_port *port;
+	struct delayed_work output_poll_work;
+	enum usb_role role_state;
+	bool poll;
 };
 
 static int hd3ss3220_set_source_pref(struct hd3ss3220 *hd3ss3220, int src_pref)
@@ -118,6 +122,22 @@  static void hd3ss3220_set_role(struct hd3ss3220 *hd3ss3220)
 	default:
 		break;
 	}
+
+	hd3ss3220->role_state = role_state;
+}
+
+static void output_poll_execute(struct work_struct *work)
+{
+	struct delayed_work *delayed_work = to_delayed_work(work);
+	struct hd3ss3220 *hd3ss3220 = container_of(delayed_work,
+						   struct hd3ss3220,
+						   output_poll_work);
+	enum usb_role role_state = hd3ss3220_get_attached_state(hd3ss3220);
+
+	if (hd3ss3220->role_state != role_state)
+		hd3ss3220_set_role(hd3ss3220);
+
+	schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
 }
 
 static irqreturn_t hd3ss3220_irq(struct hd3ss3220 *hd3ss3220)
@@ -227,6 +247,9 @@  static int hd3ss3220_probe(struct i2c_client *client,
 					"hd3ss3220", &client->dev);
 		if (ret)
 			goto err_unreg_port;
+	} else {
+		INIT_DELAYED_WORK(&hd3ss3220->output_poll_work, output_poll_execute);
+		hd3ss3220->poll = true;
 	}
 
 	ret = i2c_smbus_read_byte_data(client, HD3SS3220_REG_DEV_REV);
@@ -235,6 +258,9 @@  static int hd3ss3220_probe(struct i2c_client *client,
 
 	fwnode_handle_put(connector);
 
+	if (hd3ss3220->poll)
+		schedule_delayed_work(&hd3ss3220->output_poll_work, HZ);
+
 	dev_info(&client->dev, "probed revision=0x%x\n", ret);
 
 	return 0;
@@ -252,6 +278,9 @@  static void hd3ss3220_remove(struct i2c_client *client)
 {
 	struct hd3ss3220 *hd3ss3220 = i2c_get_clientdata(client);
 
+	if (hd3ss3220->poll)
+		cancel_delayed_work_sync(&hd3ss3220->output_poll_work);
+
 	typec_unregister_port(hd3ss3220->port);
 	usb_role_switch_put(hd3ss3220->role_sw);
 }