diff mbox

[v3,4/4] musb: sunxi: Simplify dr_mode handling

Message ID 1465138776-6003-4-git-send-email-hdegoede@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Hans de Goede June 5, 2016, 2:59 p.m. UTC
phy-sun4i-usb now has proper dr_mode handling, it always registers an
extcon, and sends a notify with the mode (even when in peripheral- /
host-only mode) at least once.

So we can simply the sunxi musb glue by always registering its extcon
notifier and relying on sunxi_musb_work() to enable vbus when in
host-only mode.

This also enables host- and peripheral-only mode with vbus monitoring.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
Changes in v2:
-No changes
Changes in v3:
-No changes
---
 drivers/usb/musb/sunxi.c | 68 ++++++++++++++++++------------------------------
 1 file changed, 25 insertions(+), 43 deletions(-)

Comments

Maxime Ripard June 8, 2016, 10:23 a.m. UTC | #1
Hi,

On Sun, Jun 05, 2016 at 04:59:36PM +0200, Hans de Goede wrote:
> phy-sun4i-usb now has proper dr_mode handling, it always registers an
> extcon, and sends a notify with the mode (even when in peripheral- /
> host-only mode) at least once.
> 
> So we can simply the sunxi musb glue by always registering its extcon
> notifier and relying on sunxi_musb_work() to enable vbus when in
> host-only mode.
> 
> This also enables host- and peripheral-only mode with vbus monitoring.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>

It's been a bit painful to track all the patches needed so that it
applies properly, but I've finally been able to test it on a Sinlinx
SinA33 with peripheral-only mUSB, and it works like a charm.

You can add my Tested-by.

Thanks!
Maxime
Hans de Goede June 8, 2016, 10:30 a.m. UTC | #2
Hi,

On 08-06-16 12:23, Maxime Ripard wrote:
> Hi,
>
> On Sun, Jun 05, 2016 at 04:59:36PM +0200, Hans de Goede wrote:
>> phy-sun4i-usb now has proper dr_mode handling, it always registers an
>> extcon, and sends a notify with the mode (even when in peripheral- /
>> host-only mode) at least once.
>>
>> So we can simply the sunxi musb glue by always registering its extcon
>> notifier and relying on sunxi_musb_work() to enable vbus when in
>> host-only mode.
>>
>> This also enables host- and peripheral-only mode with vbus monitoring.
>>
>> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
>
> It's been a bit painful to track all the patches needed so that it
> applies properly, but I've finally been able to test it on a Sinlinx
> SinA33 with peripheral-only mUSB, and it works like a charm.
>
> You can add my Tested-by.

Great, thanks for testing.

This is the board which has an otg connector with vbus not connected,
right? Yet it does have a functional id-pin, right ?

In that case you should be able to put it in dual-role mode (only
specify the id-pin in the phy dts node, no vbus / vbus-monitoring)
and then it _should_ work in host mode if you use a powered hub.

I'm fine with putting in peripheral-only mode, but as said
dual-role might work with a powered hub.

Regards,

Hans
Bin Liu June 10, 2016, 2:53 p.m. UTC | #3
Hi,

On Sun, Jun 05, 2016 at 04:59:36PM +0200, Hans de Goede wrote:
> phy-sun4i-usb now has proper dr_mode handling, it always registers an
> extcon, and sends a notify with the mode (even when in peripheral- /
> host-only mode) at least once.
> 
> So we can simply the sunxi musb glue by always registering its extcon
> notifier and relying on sunxi_musb_work() to enable vbus when in
> host-only mode.
> 
> This also enables host- and peripheral-only mode with vbus monitoring.
> 
> Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> ---
> Changes in v2:
> -No changes
> Changes in v3:
> -No changes

Acked-by: Bin Liu <b-liu@ti.com>

Regards,
-Bin.
Maxime Ripard June 15, 2016, 7:30 p.m. UTC | #4
Hi,

On Wed, Jun 08, 2016 at 12:30:20PM +0200, Hans de Goede wrote:
> Hi,
> 
> On 08-06-16 12:23, Maxime Ripard wrote:
> >Hi,
> >
> >On Sun, Jun 05, 2016 at 04:59:36PM +0200, Hans de Goede wrote:
> >>phy-sun4i-usb now has proper dr_mode handling, it always registers an
> >>extcon, and sends a notify with the mode (even when in peripheral- /
> >>host-only mode) at least once.
> >>
> >>So we can simply the sunxi musb glue by always registering its extcon
> >>notifier and relying on sunxi_musb_work() to enable vbus when in
> >>host-only mode.
> >>
> >>This also enables host- and peripheral-only mode with vbus monitoring.
> >>
> >>Signed-off-by: Hans de Goede <hdegoede@redhat.com>
> >
> >It's been a bit painful to track all the patches needed so that it
> >applies properly, but I've finally been able to test it on a Sinlinx
> >SinA33 with peripheral-only mUSB, and it works like a charm.
> >
> >You can add my Tested-by.
> 
> Great, thanks for testing.
> 
> This is the board which has an otg connector with vbus not connected,
> right? Yet it does have a functional id-pin, right ?

It's that one, yes.

> In that case you should be able to put it in dual-role mode (only
> specify the id-pin in the phy dts node, no vbus / vbus-monitoring)
> and then it _should_ work in host mode if you use a powered hub.
> 
> I'm fine with putting in peripheral-only mode, but as said
> dual-role might work with a powered hub.

Good point, I'll test that.

Thanks!
Maxime
diff mbox

Patch

diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index e7d4617..b88a2f6 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -255,12 +255,10 @@  static int sunxi_musb_init(struct musb *musb)
 	writeb(SUNXI_MUSB_VEND0_PIO_MODE, musb->mregs + SUNXI_MUSB_VEND0);
 
 	/* Register notifier before calling phy_init() */
-	if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE) {
-		ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
-					       &glue->host_nb);
-		if (ret)
-			goto error_reset_assert;
-	}
+	ret = extcon_register_notifier(glue->extcon, EXTCON_USB_HOST,
+				       &glue->host_nb);
+	if (ret)
+		goto error_reset_assert;
 
 	ret = phy_init(glue->phy);
 	if (ret)
@@ -274,9 +272,8 @@  static int sunxi_musb_init(struct musb *musb)
 	return 0;
 
 error_unregister_notifier:
-	if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
-		extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
-					   &glue->host_nb);
+	extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+				   &glue->host_nb);
 error_reset_assert:
 	if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 		reset_control_assert(glue->rst);
@@ -300,9 +297,8 @@  static int sunxi_musb_exit(struct musb *musb)
 
 	phy_exit(glue->phy);
 
-	if (musb->port_mode == MUSB_PORT_MODE_DUAL_ROLE)
-		extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
-					   &glue->host_nb);
+	extcon_unregister_notifier(glue->extcon, EXTCON_USB_HOST,
+				   &glue->host_nb);
 
 	if (test_bit(SUNXI_MUSB_FL_HAS_RESET, &glue->flags))
 		reset_control_assert(glue->rst);
@@ -314,25 +310,6 @@  static int sunxi_musb_exit(struct musb *musb)
 	return 0;
 }
 
-static int sunxi_set_mode(struct musb *musb, u8 mode)
-{
-	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
-	int ret;
-
-	if (mode == MUSB_HOST) {
-		ret = phy_power_on(glue->phy);
-		if (ret)
-			return ret;
-
-		set_bit(SUNXI_MUSB_FL_PHY_ON, &glue->flags);
-		/* Stop musb work from turning vbus off again */
-		set_bit(SUNXI_MUSB_FL_VBUS_ON, &glue->flags);
-		musb->xceiv->otg->state = OTG_STATE_A_WAIT_VRISE;
-	}
-
-	return 0;
-}
-
 static void sunxi_musb_enable(struct musb *musb)
 {
 	struct sunxi_glue *glue = dev_get_drvdata(musb->controller->parent);
@@ -579,7 +556,6 @@  static const struct musb_platform_ops sunxi_musb_ops = {
 	.exit		= sunxi_musb_exit,
 	.enable		= sunxi_musb_enable,
 	.disable	= sunxi_musb_disable,
-	.set_mode	= sunxi_set_mode,
 	.fifo_offset	= sunxi_musb_fifo_offset,
 	.ep_offset	= sunxi_musb_ep_offset,
 	.busctl_offset	= sunxi_musb_busctl_offset,
@@ -635,10 +611,6 @@  static int sunxi_musb_probe(struct platform_device *pdev)
 		return -EINVAL;
 	}
 
-	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
-	if (!glue)
-		return -ENOMEM;
-
 	memset(&pdata, 0, sizeof(pdata));
 	switch (usb_get_dr_mode(&pdev->dev)) {
 #if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_HOST
@@ -646,15 +618,13 @@  static int sunxi_musb_probe(struct platform_device *pdev)
 		pdata.mode = MUSB_PORT_MODE_HOST;
 		break;
 #endif
+#if defined CONFIG_USB_MUSB_DUAL_ROLE || defined CONFIG_USB_MUSB_GADGET
+	case USB_DR_MODE_PERIPHERAL:
+		pdata.mode = MUSB_PORT_MODE_GADGET;
+		break;
+#endif
 #ifdef CONFIG_USB_MUSB_DUAL_ROLE
 	case USB_DR_MODE_OTG:
-		glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
-		if (IS_ERR(glue->extcon)) {
-			if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
-				return -EPROBE_DEFER;
-			dev_err(&pdev->dev, "Invalid or missing extcon\n");
-			return PTR_ERR(glue->extcon);
-		}
 		pdata.mode = MUSB_PORT_MODE_DUAL_ROLE;
 		break;
 #endif
@@ -665,6 +635,10 @@  static int sunxi_musb_probe(struct platform_device *pdev)
 	pdata.platform_ops	= &sunxi_musb_ops;
 	pdata.config		= &sunxi_musb_hdrc_config;
 
+	glue = devm_kzalloc(&pdev->dev, sizeof(*glue), GFP_KERNEL);
+	if (!glue)
+		return -ENOMEM;
+
 	glue->dev = &pdev->dev;
 	INIT_WORK(&glue->work, sunxi_musb_work);
 	glue->host_nb.notifier_call = sunxi_musb_host_notifier;
@@ -698,6 +672,14 @@  static int sunxi_musb_probe(struct platform_device *pdev)
 		}
 	}
 
+	glue->extcon = extcon_get_edev_by_phandle(&pdev->dev, 0);
+	if (IS_ERR(glue->extcon)) {
+		if (PTR_ERR(glue->extcon) == -EPROBE_DEFER)
+			return -EPROBE_DEFER;
+		dev_err(&pdev->dev, "Invalid or missing extcon\n");
+		return PTR_ERR(glue->extcon);
+	}
+
 	glue->phy = devm_phy_get(&pdev->dev, "usb");
 	if (IS_ERR(glue->phy)) {
 		if (PTR_ERR(glue->phy) == -EPROBE_DEFER)