Commit 569d23e9 authored by Biju Das's avatar Biju Das Committed by Greg Kroah-Hartman
Browse files

usb: typec: hd3ss3220: Add polling support



Some platforms(for eg: RZ/V2M EVK) does not have interrupt pin
connected to HD3SS3220. Add polling support for role detection.

Signed-off-by: default avatarBiju Das <biju.das.jz@bp.renesas.com>
Reviewed-by: default avatarHeikki Krogerus <heikki.krogerus@linux.intel.com>
Link: https://lore.kernel.org/r/20221209171836.71610-3-biju.das.jz@bp.renesas.com


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent bf58a687
Loading
Loading
Loading
Loading
+29 −0
Original line number Diff line number Diff line
@@ -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)
@@ -223,6 +243,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);
@@ -231,6 +254,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;
@@ -248,6 +274,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);
}