Beispiel #1
0
static void dwc2_ep0_start_out_transfer(struct dwc2 *dwc,
					struct dwc2_request *req) {
	dwc_otg_dev_out_ep_regs_t	*out_regs = dwc->dev_if.out_ep_regs[0];
	depctl_data_t			 depctl;
	struct dwc2_ep			*dep	  = req->dwc2_ep;
	deptsiz0_data_t			 deptsiz;

	deptsiz.d32 = dwc_readl(&out_regs->doeptsiz);
	deptsiz.b.xfersize = dep->maxp;
	deptsiz.b.supcnt = 0;
	deptsiz.b.pktcnt = 1;

	req->xfersize = dep->maxp;
	req->pktcnt = 1;

	DWC2_EP0_DEBUG_MSG("OUT: next_dma_addr = 0x%08x\n", req->next_dma_addr);

	if (dwc->dma_enable) {
		if (!dwc->dma_desc_enable) {
			dwc_writel(deptsiz.d32, &out_regs->doeptsiz);
			dwc_writel(req->next_dma_addr, &out_regs->doepdma);
		} else {
			/* TODO: Scatter/Gather DMA Mode here */
		}
	} else {
		dwc_writel(deptsiz.d32, &out_regs->doeptsiz);
	}

	/* EP enable */
	dep->flags |= DWC2_EP_BUSY;
	depctl.d32 = dwc_readl(&out_regs->doepctl);
	depctl.b.epena = 1;
	depctl.b.cnak = 1;
	dwc_writel(depctl.d32, &out_regs->doepctl);
}
Beispiel #2
0
static void dwc2_ep0_start_in_transfer(struct dwc2 *dwc,
				struct dwc2_request *req) {
	dwc_otg_dev_in_ep_regs_t	*in_regs = dwc->dev_if.in_ep_regs[0];
	struct dwc2_ep			*dep	 = req->dwc2_ep;
	depctl_data_t			 depctl;
	deptsiz0_data_t			 deptsiz;

	deptsiz.d32 = dwc_readl(&in_regs->dieptsiz);

	if (req->trans_count_left == 0) {
		/* Zero Packet */
		DWC2_EP0_DEBUG_MSG("IN zero packet\n");
		req->zlp_transfered = 1;
		deptsiz.b.xfersize = 0;
	} else {
		if (req->trans_count_left > dep->maxp) {
			deptsiz.b.xfersize = dep->maxp;
		} else {
			deptsiz.b.xfersize = req->trans_count_left;
		}
	}

	deptsiz.b.pktcnt = 1;

	req->xfersize = deptsiz.b.xfersize;
	req->pktcnt = 1;


	DWC2_EP0_DEBUG_MSG("IN: xfersize = %d next_dma_addr = 0x%08x zlp_transfered = %d dep->maxp = %d\n",
			req->xfersize, req->next_dma_addr, req->zlp_transfered, dep->maxp);

	/* Write the DMA register */
	if (dwc->dma_enable) {
		if (!dwc->dma_desc_enable) {
			dwc_writel(req->next_dma_addr, &in_regs->diepdma);
			dwc_writel(deptsiz.d32, &in_regs->dieptsiz);
		} else {
			/* TODO: Scatter/Gather DMA mode here */
		}
	} else {
		dwc_writel(deptsiz.d32, &in_regs->dieptsiz);
	}

	/* EP enable, IN data in FIFO */
	dep->flags |= DWC2_EP_BUSY;
	depctl.d32 = dwc_readl(&in_regs->diepctl);
	depctl.b.epena = 1;
	depctl.b.cnak = 1;
	dwc_writel(depctl.d32, &in_regs->diepctl);
}
Beispiel #3
0
static void dwc2_ep0_complete_status(struct dwc2 *dwc) {
	struct dwc2_ep		*ep0	     = dwc2_ep0_get_ep0(dwc);
	struct dwc2_request	*curr_req;
	dctl_data_t		 dctl;

	/* enter test mode if needed (exit by reset) */
	if (dwc->test_mode) {
		/*
		 * The transition to test mode must be complete no later than 3 ms
		 * after the completion of the status stage of the request.
		 */
		dctl.d32 = dwc_readl(&dwc->dev_if.dev_global_regs->dctl);
		dctl.b.tstctl = dwc->test_mode_nr;
		dwc_writel(dctl.d32, &dwc->dev_if.dev_global_regs->dctl);
	}

	/*
	 * prepare to receive SETUP again to ensure we are prepared!!!
	 */
	dwc2_ep0_out_start(dwc);

	curr_req = next_request(&ep0->request_list);
	if (curr_req) {
		dwc2_gadget_giveback(ep0, curr_req, 0);
	}

	if (dwc->test_mode)
		dev_info(dwc->dev, "entering Test Mode(%d)\n", dwc->test_mode_nr);

	dwc->ep0state = EP0_SETUP_PHASE;
}
int get_eventbuf_count(usb3_device_t *dev)
{
	uint32_t cnt;

	cnt = dwc_readl(&dev->core_global_regs->geventbuf[0].geventcnt);
	return cnt & USB3_EVENTCNT_CNT_BITS;
}
void usb3_dis_flush_eventbuf_intr(usb3_device_t *dev)
{
	uint32_t cnt;

	dis_eventbuf_intr(dev);
	cnt = dwc_readl(&dev->core_global_regs->geventbuf[0].geventcnt);
	dwc_writel(cnt, &dev->core_global_regs->geventbuf[0].geventcnt);
}
void ena_eventbuf_intr(usb3_device_t *dev)
{
	uint32_t eventsiz;

	eventsiz =
	      dwc_readl(&dev->core_global_regs->geventbuf[0].geventsiz);
	eventsiz &= ~USB3_EVENTSIZ_INT_MSK_BIT;
	dwc_writel(eventsiz,
        &dev->core_global_regs->geventbuf[0].geventsiz);
}
Beispiel #7
0
static void dwc2_ep0_out_complete_data(struct dwc2 *dwc) {
	struct dwc2_ep		*ep0	     = dwc2_ep0_get_ep0(dwc);
	struct dwc2_dev_if	*dev_if	     = &dwc->dev_if;
	struct dwc2_request	*curr_req;
	deptsiz0_data_t		 deptsiz;
	int			 trans_count = 0;

	curr_req = next_request(&ep0->request_list);
	if (curr_req == NULL) {
		return;
	}

	if (dwc->dma_enable) {
		if (dwc->dma_desc_enable) {
			/* TODO: Scatter/Gather DMA Mode here! */
		} else {
			deptsiz.d32 = dwc_readl(&dev_if->out_ep_regs[0]->doeptsiz);

			/* The Programming Guide said xfercompl raised when xfersize and pktcnt gets zero */
			WARN(deptsiz.b.xfersize, "%s: xfersize not zero when transfer complete\n", __func__);

			trans_count = curr_req->xfersize - deptsiz.b.xfersize;
		}

		curr_req->trans_count_left -= trans_count;
		if (curr_req->trans_count_left < 0) {
			curr_req->trans_count_left = 0;
		}

		//curr_req->next_dma_addr += trans_count;
		curr_req->request.actual += trans_count;

		/* copy from shadow buffer to real buffer */
		if (curr_req->request.length != 0) {
			int offset = curr_req->request.actual;
			u32 buf_addr = (u32)curr_req->request.buf;

			memcpy( (void *)(buf_addr + offset),
				(void *)dwc->ep0out_shadow_uncached,
				trans_count);
		}

		/* if xfersize is not zero, we receive an short packet, the transfer is complete */
		if (!deptsiz.b.xfersize && (curr_req->trans_count_left || need_send_zlp(curr_req))) {
			dwc2_ep0_start_transfer(dwc, curr_req);
		} else {
			dwc2_ep0_do_status_phase(dwc);
		}
	} else {
		/* TODO: PIOMode */
	}
}
Beispiel #8
0
static void dwc2_ep0_in_complete_data(struct dwc2 *dwc) {
	struct dwc2_ep		*ep0	     = dwc2_ep0_get_ep0(dwc);
	struct dwc2_dev_if	*dev_if	     = &dwc->dev_if;
	struct dwc2_request	*curr_req;
	deptsiz0_data_t		 deptsiz;
	int			 trans_count = 0;

	curr_req = next_request(&ep0->request_list);
	if (curr_req == NULL) {
		return;
	}

	if (dwc->dma_enable) {
		if (dwc->dma_desc_enable) {
			/* TODO: Scatter/Gather DMA Mode here! */
		} else {
			deptsiz.d32 = dwc_readl(&dev_if->in_ep_regs[0]->dieptsiz);

			/* The Programming Guide said xfercompl raised when xfersize and pktcnt gets zero */
			WARN(deptsiz.b.xfersize, "%s: xfersize not zero when transfer complete\n", __func__);

			trans_count = curr_req->xfersize - deptsiz.b.xfersize;
		}

		curr_req->trans_count_left -= trans_count;
		if (curr_req->trans_count_left < 0)
			curr_req->trans_count_left = 0;
		curr_req->next_dma_addr += trans_count;

		if (curr_req->trans_count_left || need_send_zlp(curr_req)) {
			DWC2_EP0_DEBUG_MSG("req 0x%p continue transfer, is_in = %d\n",
					curr_req, curr_req->dwc2_ep->is_in);
			dwc2_ep0_start_transfer(dwc, curr_req);
		} else {
			DWC2_EP0_DEBUG_MSG("req 0x%p done, do %s status phase\n",
					curr_req, dwc->ep0_expect_in ? "OUT" : "IN");
			dwc2_ep0_do_status_phase(dwc);
		}
	} else {
		/* TODO: PIO Mode */
	}
}
Beispiel #9
0
/**
 * This function configures EPO to receive SETUP packets.
 *
 * Priciple: prepare to receive as sooooooon as the OUT ep is idle!
 */
void dwc2_ep0_out_start(struct dwc2 *dwc) {
	struct dwc2_dev_if	*dev_if	    = &dwc->dev_if;
	deptsiz0_data_t		 doeptsize0 = {.d32 = 0 };
	depctl_data_t		 doepctl    = {.d32 = 0 };
	doepmsk_data_t		 doepmsk;
	doepint_data_t		 doepint;
	u32			 doepdma;

	doepctl.d32 = dwc_readl(&dev_if->out_ep_regs[0]->doepctl);
	doeptsize0.d32 = dwc_readl(&dev_if->out_ep_regs[0]->doeptsiz);
	doepdma = dwc_readl(&dev_if->out_ep_regs[0]->doepdma);

	if (dwc->setup_prepared) {
		if (!doepctl.b.epena) {
			DWC2_EP0_DEBUG_MSG("setup prepared but ep0out is stoped by someone! "
					"doeptsize0 = 0x%08x doepdma = 0x%08x\n",
					doeptsize0.d32, doepdma);
		} else {
			DWC2_EP0_DEBUG_MSG("setup already prepared and ep0out is running! "
					"doeptsize0 = 0x%08x doepdma = 0x%08x\n",
					doeptsize0.d32, doepdma);
		}

		return;
	}

	if (unlikely(doepctl.b.epena)) {
		DWC2_EP0_DEBUG_MSG("ep0 is already enabled! doeptsize0 = 0x%08x\n", doeptsize0.d32);
		return;
	}

	doepmsk.d32 = dwc_readl(&dev_if->dev_global_regs->doepmsk);
	doepint.d32 = dwc_readl(&dev_if->out_ep_regs[0]->doepint) & doepmsk.d32;
	if (unlikely(doepint.b.setup)) {
		DWC2_EP0_DEBUG_MSG("%s: a setup packet is already pending\n", __func__);
		return;
	}

	dwc->setup_prepared = 1;

	doeptsize0.b.supcnt = 3;
	doeptsize0.b.pktcnt = 1;
	doeptsize0.b.xfersize = 8 * 3;

	if (dwc->dma_enable) {
		if (!dwc->dma_desc_enable) {
			/* TODO: if the endpoint is just transfering a SETUP packet,
			 * and we change these registers, what will happend?
			 *
			 * But how do we know that the core is just transfering a SETUP packet?
			 */

			dwc_writel(doeptsize0.d32, &dev_if->out_ep_regs[0]->doeptsiz);
			dwc_writel(dwc->ctrl_req_addr, &dev_if->out_ep_regs[0]->doepdma);
		} else {
			/* TODO: Scatter/Gather DMA here */
		}
	} else {
		dwc_writel(doeptsize0.d32, &dev_if->out_ep_regs[0]->doeptsiz);
	}

	DWC2_EP0_DEBUG_MSG("dwc2_ep0_out_start(0x%08x)\n", dwc->ctrl_req_addr);

	doepctl.b.cnak = 1;
	doepctl.b.epena = 1;
	dwc_writel(doepctl.d32, &dev_if->out_ep_regs[0]->doepctl);
}

static void dwc2_ep0_status_cmpl(struct usb_ep *ep, struct usb_request *req)
{
	/* do nothing */
}

static void dwc2_ep0_start_transfer(struct dwc2 *dwc,
				struct dwc2_request *req);

/**
 * Problem: as soon as we receive the xfercompl intr for status phase,
 *       a new SETUP packet may comming, so we must prepare this.
 *
 * Solution: when do OUT status phase, call dwc2_ep0_out_start() instead,
 *
 *           when do IN status phase, firstly call dwc2_ep0_out_start(),
 *           then do a ZPL IN status transfer
 */
static int dwc2_ep0_do_status_phase(struct dwc2 *dwc) {
	unsigned	is_in = !dwc->ep0_expect_in;

	dwc->ep0state = EP0_STATUS_PHASE;
	dwc2_ep0_out_start(dwc);

	if (!is_in) {	      /* OUT status phase */
		return 0;
	} else {
		dwc->ep0_usb_req.dwc2_ep = dwc2_ep0_get_in_ep(dwc);
		dwc->ep0_usb_req.request.length = 0;
		dwc->ep0_usb_req.request.buf = (void *)0xFFFFFFFF;
		dwc->ep0_usb_req.request.complete = dwc2_ep0_status_cmpl;
		dwc2_ep0_start_transfer(dwc, &dwc->ep0_usb_req);
		return 0;
	}
}

/*
 * ch 9.4.6, the spec said:
 *     The USB device does not change its device address until after
 *     the Status stage of this request is completed successfully
 * TODO: do we need to set address after status stage compl?
 */
static int dwc2_ep0_set_address(struct dwc2 *dwc, struct usb_ctrlrequest *ctrl)
{
	dcfg_data_t	dcfg;
	u32		addr;

	addr = le16_to_cpu(ctrl->wValue);
	if (addr > 127) {
		dev_dbg(dwc->dev, "invalid device address %d\n", addr);
		return -EINVAL;
	}

	if (dwc->dev_state == DWC2_CONFIGURED_STATE) {
		dev_dbg(dwc->dev, "trying to set address when configured\n");
		return -EINVAL;
	}

	dcfg.d32 = dwc_readl(&dwc->dev_if.dev_global_regs->dcfg);
	dcfg.b.devaddr = addr;
	dwc_writel(dcfg.d32, &dwc->dev_if.dev_global_regs->dcfg);

	if (addr)
		dwc->dev_state = DWC2_ADDRESS_STATE;
	else
		dwc->dev_state = DWC2_DEFAULT_STATE;

	dwc2_ep0_do_status_phase(dwc);

	return 0;
}