Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a1ca2c6b authored by Hans de Goede's avatar Hans de Goede Committed by Greg Kroah-Hartman
Browse files

usb: musb: sunxi: Simplify dr_mode handling



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.

Tested-by: default avatarMaxime Ripard <maxime.ripard@free-electrons.com>
Signed-off-by: default avatarHans de Goede <hdegoede@redhat.com>
Signed-off-by: default avatarBin Liu <b-liu@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent cd53bd68
Loading
Loading
Loading
Loading
+25 −43
Original line number Diff line number Diff line
@@ -256,12 +256,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 = phy_init(glue->phy);
	if (ret)
@@ -275,7 +273,6 @@ 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);
error_reset_assert:
@@ -301,7 +298,6 @@ 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);

@@ -315,25 +311,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);
@@ -582,7 +559,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,
@@ -638,10 +614,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
@@ -649,15 +621,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
@@ -668,6 +638,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;
@@ -701,6 +675,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)