Commit 4fca54aa authored by Robert Baldyga's avatar Robert Baldyga Committed by Felipe Balbi

usb: gadget: s3c-hsotg: add multi count support

This patch adds Multi Count support. It adds few modifications:
- Fix s3c_hsotg_set_ep_maxpacket() function. Field wMaxPacketSize of endpoint
  descriptor is now splitted into maximum packet size value and number of
  additional transaction per microframe.
- Modify s3c_hsotg_write_fifo() function. It actually calculates transfer
  size, taking into account Multi Count value, which indicates number of
  transactions per microframe.
- Fix s3c_hsotg_start_req() function by setting number of packets to Multi
  Count field in DIEPTSIZ register for isochronous endpoints.
Signed-off-by: default avatarRobert Baldyga <r.baldyga@samsung.com>
Signed-off-by: default avatarKyungmin Park <kyungmin.park@samsung.com>
Signed-off-by: default avatarFelipe Balbi <balbi@ti.com>
parent 1479e841
...@@ -83,6 +83,7 @@ struct s3c_hsotg_req; ...@@ -83,6 +83,7 @@ struct s3c_hsotg_req;
* @dir_in: Set to true if this endpoint is of the IN direction, which * @dir_in: Set to true if this endpoint is of the IN direction, which
* means that it is sending data to the Host. * means that it is sending data to the Host.
* @index: The index for the endpoint registers. * @index: The index for the endpoint registers.
* @mc: Multi Count - number of transactions per microframe
* @interval - Interval for periodic endpoints * @interval - Interval for periodic endpoints
* @name: The name array passed to the USB core. * @name: The name array passed to the USB core.
* @halted: Set if the endpoint has been halted. * @halted: Set if the endpoint has been halted.
...@@ -123,6 +124,7 @@ struct s3c_hsotg_ep { ...@@ -123,6 +124,7 @@ struct s3c_hsotg_ep {
unsigned char dir_in; unsigned char dir_in;
unsigned char index; unsigned char index;
unsigned char mc;
unsigned char interval; unsigned char interval;
unsigned int halted:1; unsigned int halted:1;
...@@ -472,6 +474,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, ...@@ -472,6 +474,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
void *data; void *data;
int can_write; int can_write;
int pkt_round; int pkt_round;
int max_transfer;
to_write -= (buf_pos - hs_ep->last_load); to_write -= (buf_pos - hs_ep->last_load);
...@@ -539,8 +542,10 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, ...@@ -539,8 +542,10 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
can_write *= 4; /* fifo size is in 32bit quantities. */ can_write *= 4; /* fifo size is in 32bit quantities. */
} }
dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, mps %d\n", max_transfer = hs_ep->ep.maxpacket * hs_ep->mc;
__func__, gnptxsts, can_write, to_write, hs_ep->ep.maxpacket);
dev_dbg(hsotg->dev, "%s: GNPTXSTS=%08x, can=%d, to=%d, max_transfer %d\n",
__func__, gnptxsts, can_write, to_write, max_transfer);
/* /*
* limit to 512 bytes of data, it seems at least on the non-periodic * limit to 512 bytes of data, it seems at least on the non-periodic
...@@ -555,8 +560,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, ...@@ -555,8 +560,8 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
* the transfer to return that it did not run out of fifo space * the transfer to return that it did not run out of fifo space
* doing it. * doing it.
*/ */
if (to_write > hs_ep->ep.maxpacket) { if (to_write > max_transfer) {
to_write = hs_ep->ep.maxpacket; to_write = max_transfer;
s3c_hsotg_en_gsint(hsotg, s3c_hsotg_en_gsint(hsotg,
periodic ? GINTSTS_PTxFEmp : periodic ? GINTSTS_PTxFEmp :
...@@ -567,7 +572,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg, ...@@ -567,7 +572,7 @@ static int s3c_hsotg_write_fifo(struct s3c_hsotg *hsotg,
if (to_write > can_write) { if (to_write > can_write) {
to_write = can_write; to_write = can_write;
pkt_round = to_write % hs_ep->ep.maxpacket; pkt_round = to_write % max_transfer;
/* /*
* Round the write down to an * Round the write down to an
...@@ -731,7 +736,15 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg, ...@@ -731,7 +736,15 @@ static void s3c_hsotg_start_req(struct s3c_hsotg *hsotg,
else else
packets = 1; /* send one packet if length is zero. */ packets = 1; /* send one packet if length is zero. */
if (hs_ep->isochronous && length > (hs_ep->mc * hs_ep->ep.maxpacket)) {
dev_err(hsotg->dev, "req length > maxpacket*mc\n");
return;
}
if (dir_in && index != 0) if (dir_in && index != 0)
if (hs_ep->isochronous)
epsize = DxEPTSIZ_MC(packets);
else
epsize = DxEPTSIZ_MC(1); epsize = DxEPTSIZ_MC(1);
else else
epsize = 0; epsize = 0;
...@@ -1702,6 +1715,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, ...@@ -1702,6 +1715,7 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep]; struct s3c_hsotg_ep *hs_ep = &hsotg->eps[ep];
void __iomem *regs = hsotg->regs; void __iomem *regs = hsotg->regs;
u32 mpsval; u32 mpsval;
u32 mcval;
u32 reg; u32 reg;
if (ep == 0) { if (ep == 0) {
...@@ -1710,10 +1724,15 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg, ...@@ -1710,10 +1724,15 @@ static void s3c_hsotg_set_ep_maxpacket(struct s3c_hsotg *hsotg,
if (mpsval > 3) if (mpsval > 3)
goto bad_mps; goto bad_mps;
hs_ep->ep.maxpacket = mps; hs_ep->ep.maxpacket = mps;
hs_ep->mc = 1;
} else { } else {
mpsval = mps & DxEPCTL_MPS_MASK; mpsval = mps & DxEPCTL_MPS_MASK;
if (mpsval > 1024) if (mpsval > 1024)
goto bad_mps; goto bad_mps;
mcval = ((mps >> 11) & 0x3) + 1;
hs_ep->mc = mcval;
if (mcval > 3)
goto bad_mps;
hs_ep->ep.maxpacket = mpsval; hs_ep->ep.maxpacket = mpsval;
} }
...@@ -2599,6 +2618,9 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep, ...@@ -2599,6 +2618,9 @@ static int s3c_hsotg_ep_enable(struct usb_ep *ep,
hs_ep->periodic = 0; hs_ep->periodic = 0;
hs_ep->interval = desc->bInterval; hs_ep->interval = desc->bInterval;
if (hs_ep->interval > 1 && hs_ep->mc > 1)
dev_err(hsotg->dev, "MC > 1 when interval is not 1\n");
switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) { switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
case USB_ENDPOINT_XFER_ISOC: case USB_ENDPOINT_XFER_ISOC:
epctrl |= DxEPCTL_EPType_Iso; epctrl |= DxEPCTL_EPType_Iso;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment