Message ID | 20221209171836.71610-3-biju.das.jz@bp.renesas.com |
---|---|
State | Superseded |
Headers | show |
Series | Add Polling support for role detection with HD3SS3220 | expand |
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 --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); }
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(+)