Commit dc6e69e6 authored by Marek Szyprowski's avatar Marek Szyprowski Committed by Felipe Balbi
Browse files

usb: dwc2: gadget: rework suspend/resume code to correctly restore gadget state



Suspend/resume code assumed that the gadget was always started and
enabled to connect to usb bus. This means that the actual state of the
gadget (started/stopped or connected/disconnected) was not correctly
preserved on suspend/resume cycle. This patch fixes this issue.

Signed-off-by: default avatarMarek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 7ad8096e
Loading
Loading
Loading
Loading
+2 −1
Original line number Original line Diff line number Diff line
@@ -688,8 +688,9 @@ struct dwc2_hsotg {
	u8 ctrl_buff[8];
	u8 ctrl_buff[8];


	struct usb_gadget gadget;
	struct usb_gadget gadget;
	unsigned int enabled:1;
	unsigned int connected:1;
	unsigned int connected:1;
	unsigned int setup;
	unsigned int setup:1;
	unsigned long last_rst;
	unsigned long last_rst;
	struct s3c_hsotg_ep *eps;
	struct s3c_hsotg_ep *eps;
#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
+22 −17
Original line number Original line Diff line number Diff line
@@ -2889,6 +2889,7 @@ static int s3c_hsotg_udc_start(struct usb_gadget *gadget,
	spin_lock_irqsave(&hsotg->lock, flags);
	spin_lock_irqsave(&hsotg->lock, flags);
	s3c_hsotg_init(hsotg);
	s3c_hsotg_init(hsotg);
	s3c_hsotg_core_init_disconnected(hsotg);
	s3c_hsotg_core_init_disconnected(hsotg);
	hsotg->enabled = 0;
	spin_unlock_irqrestore(&hsotg->lock, flags);
	spin_unlock_irqrestore(&hsotg->lock, flags);


	dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
	dev_info(hsotg->dev, "bound driver %s\n", driver->driver.name);
@@ -2929,6 +2930,7 @@ static int s3c_hsotg_udc_stop(struct usb_gadget *gadget)


	hsotg->driver = NULL;
	hsotg->driver = NULL;
	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
	hsotg->gadget.speed = USB_SPEED_UNKNOWN;
	hsotg->enabled = 0;


	spin_unlock_irqrestore(&hsotg->lock, flags);
	spin_unlock_irqrestore(&hsotg->lock, flags);


@@ -2972,9 +2974,11 @@ static int s3c_hsotg_pullup(struct usb_gadget *gadget, int is_on)
	spin_lock_irqsave(&hsotg->lock, flags);
	spin_lock_irqsave(&hsotg->lock, flags);
	if (is_on) {
	if (is_on) {
		clk_enable(hsotg->clk);
		clk_enable(hsotg->clk);
		hsotg->enabled = 1;
		s3c_hsotg_core_connect(hsotg);
		s3c_hsotg_core_connect(hsotg);
	} else {
	} else {
		s3c_hsotg_core_disconnect(hsotg);
		s3c_hsotg_core_disconnect(hsotg);
		hsotg->enabled = 0;
		clk_disable(hsotg->clk);
		clk_disable(hsotg->clk);
	}
	}


@@ -3585,11 +3589,14 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)


	mutex_lock(&hsotg->init_mutex);
	mutex_lock(&hsotg->init_mutex);


	if (hsotg->driver)
	if (hsotg->driver) {
		int ep;

		dev_info(hsotg->dev, "suspending usb gadget %s\n",
		dev_info(hsotg->dev, "suspending usb gadget %s\n",
			 hsotg->driver->driver.name);
			 hsotg->driver->driver.name);


		spin_lock_irqsave(&hsotg->lock, flags);
		spin_lock_irqsave(&hsotg->lock, flags);
		if (hsotg->enabled)
			s3c_hsotg_core_disconnect(hsotg);
			s3c_hsotg_core_disconnect(hsotg);
		s3c_hsotg_disconnect(hsotg);
		s3c_hsotg_disconnect(hsotg);
		hsotg->gadget.speed = USB_SPEED_UNKNOWN;
		hsotg->gadget.speed = USB_SPEED_UNKNOWN;
@@ -3597,8 +3604,6 @@ int s3c_hsotg_suspend(struct dwc2_hsotg *hsotg)


		s3c_hsotg_phy_disable(hsotg);
		s3c_hsotg_phy_disable(hsotg);


	if (hsotg->driver) {
		int ep;
		for (ep = 0; ep < hsotg->num_of_eps; ep++)
		for (ep = 0; ep < hsotg->num_of_eps; ep++)
			s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);
			s3c_hsotg_ep_disable(&hsotg->eps[ep].ep);


@@ -3627,15 +3632,15 @@ int s3c_hsotg_resume(struct dwc2_hsotg *hsotg)
		clk_enable(hsotg->clk);
		clk_enable(hsotg->clk);
		ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
		ret = regulator_bulk_enable(ARRAY_SIZE(hsotg->supplies),
					    hsotg->supplies);
					    hsotg->supplies);
	}


		s3c_hsotg_phy_enable(hsotg);
		s3c_hsotg_phy_enable(hsotg);


		spin_lock_irqsave(&hsotg->lock, flags);
		spin_lock_irqsave(&hsotg->lock, flags);
		s3c_hsotg_core_init_disconnected(hsotg);
		s3c_hsotg_core_init_disconnected(hsotg);
		if (hsotg->enabled)
			s3c_hsotg_core_connect(hsotg);
			s3c_hsotg_core_connect(hsotg);
		spin_unlock_irqrestore(&hsotg->lock, flags);
		spin_unlock_irqrestore(&hsotg->lock, flags);

	}
	mutex_unlock(&hsotg->init_mutex);
	mutex_unlock(&hsotg->init_mutex);


	return ret;
	return ret;