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

Commit c9f721b2 authored by Robert Baldyga's avatar Robert Baldyga Committed by Felipe Balbi
Browse files

usb: gadget: s3c-hsotg: stall ep0 in set_halt function



When s3c_hsotg_ep_sethalt() function is called for ep0 it should be stalled
in the same way that it is in s3c_hsotg_process_control() function, because
SET_HALT for ep0 is delayed response for setup request. Endpoint 0, if
halted, it doesn't need CLEAR_HALT because it clears "stalled" state
automatically when next setup request is received.

For this reason this patch moves code setting ep0 to "stalled" state to new
function named s3c_hsotg_stall_ep0() which is called in
s3c_hsotg_process_control() function as an immediate response for setup
request, and in s3c_hsotg_ep_sethalt() function as a delayed response for
setup request.

Signed-off-by: default avatarRobert Baldyga <r.baldyga@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 7e98f600
Loading
Loading
Loading
Loading
+46 −32
Original line number Diff line number Diff line
@@ -1185,6 +1185,41 @@ static int s3c_hsotg_process_req_feature(struct s3c_hsotg *hsotg,
static void s3c_hsotg_enqueue_setup(struct s3c_hsotg *hsotg);
static void s3c_hsotg_disconnect(struct s3c_hsotg *hsotg);

/**
 * s3c_hsotg_stall_ep0 - stall ep0
 * @hsotg: The device state
 *
 * Set stall for ep0 as response for setup request.
 */
static void s3c_hsotg_stall_ep0(struct s3c_hsotg *hsotg) {
	struct s3c_hsotg_ep *ep0 = &hsotg->eps[0];
	u32 reg;
	u32 ctrl;

	dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
	reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;

	/*
	 * DxEPCTL_Stall will be cleared by EP once it has
	 * taken effect, so no need to clear later.
	 */

	ctrl = readl(hsotg->regs + reg);
	ctrl |= DxEPCTL_Stall;
	ctrl |= DxEPCTL_CNAK;
	writel(ctrl, hsotg->regs + reg);

	dev_dbg(hsotg->dev,
		"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
		ctrl, reg, readl(hsotg->regs + reg));

	 /*
	  * complete won't be called, so we enqueue
	  * setup request here
	  */
	 s3c_hsotg_enqueue_setup(hsotg);
}

/**
 * s3c_hsotg_process_control - process a control request
 * @hsotg: The device state
@@ -1262,38 +1297,8 @@ static void s3c_hsotg_process_control(struct s3c_hsotg *hsotg,
	 * so respond with a STALL for the status stage to indicate failure.
	 */

	if (ret < 0) {
		u32 reg;
		u32 ctrl;

		dev_dbg(hsotg->dev, "ep0 stall (dir=%d)\n", ep0->dir_in);
		reg = (ep0->dir_in) ? DIEPCTL0 : DOEPCTL0;

		/*
		 * DxEPCTL_Stall will be cleared by EP once it has
		 * taken effect, so no need to clear later.
		 */

		ctrl = readl(hsotg->regs + reg);
		ctrl |= DxEPCTL_Stall;
		ctrl |= DxEPCTL_CNAK;
		writel(ctrl, hsotg->regs + reg);

		dev_dbg(hsotg->dev,
			"written DxEPCTL=0x%08x to %08x (DxEPCTL=0x%08x)\n",
			ctrl, reg, readl(hsotg->regs + reg));

		/*
		 * don't believe we need to anything more to get the EP
		 * to reply with a STALL packet
		 */

		 /*
		  * complete won't be called, so we enqueue
		  * setup request here
		  */
		 s3c_hsotg_enqueue_setup(hsotg);
	}
	if (ret < 0)
		s3c_hsotg_stall_ep0(hsotg);
}

/**
@@ -2832,6 +2837,15 @@ static int s3c_hsotg_ep_sethalt(struct usb_ep *ep, int value)

	dev_info(hs->dev, "%s(ep %p %s, %d)\n", __func__, ep, ep->name, value);

	if (index == 0) {
		if (value)
			s3c_hsotg_stall_ep0(hs);
		else
			dev_warn(hs->dev,
				 "%s: can't clear halt on ep0\n", __func__);
		return 0;
	}

	/* write both IN and OUT control registers */

	epreg = DIEPCTL(index);