* [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers
@ 2014-09-05 6:46 Siva Durga Prasad Paladugu
2014-09-24 12:31 ` Michal Simek
2015-04-28 8:59 ` Michal Simek
0 siblings, 2 replies; 6+ messages in thread
From: Siva Durga Prasad Paladugu @ 2014-09-05 6:46 UTC (permalink / raw)
To: u-boot
Update the ci_udc driver to support bulk transfer
and also added capability of having multiple dtds
if requested data is more thank 16K.
These changes are tested for both the DFU and lthor.
Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
---
drivers/usb/gadget/ci_udc.c | 135 +++++++++++++++++++++++++++++++++++++------
drivers/usb/gadget/ci_udc.h | 1 +
2 files changed, 117 insertions(+), 19 deletions(-)
diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
index 2572b34..d1d19dc 100644
--- a/drivers/usb/gadget/ci_udc.c
+++ b/drivers/usb/gadget/ci_udc.c
@@ -50,6 +50,8 @@
/* For each endpoint, we need 2 QTDs, one for each of IN and OUT */
#define ILIST_SZ (NUM_ENDPOINTS * 2 * ILIST_ENT_SZ)
+#define EP_MAX_LENGTH_TRANSFER 0x4000
+
#ifndef DEBUG
#define DBG(x...) do {} while (0)
#else
@@ -102,13 +104,28 @@ static struct usb_ep_ops ci_ep_ops = {
};
/* Init values for USB endpoints. */
-static const struct usb_ep ci_ep_init[2] = {
+static const struct usb_ep ci_ep_init[5] = {
[0] = { /* EP 0 */
.maxpacket = 64,
.name = "ep0",
.ops = &ci_ep_ops,
},
- [1] = { /* EP 1..n */
+ [1] = {
+ .maxpacket = 512,
+ .name = "ep1in-bulk",
+ .ops = &ci_ep_ops,
+ },
+ [2] = {
+ .maxpacket = 512,
+ .name = "ep2out-bulk",
+ .ops = &ci_ep_ops,
+ },
+ [3] = {
+ .maxpacket = 512,
+ .name = "ep3in-int",
+ .ops = &ci_ep_ops,
+ },
+ [4] = {
.maxpacket = 512,
.name = "ep-",
.ops = &ci_ep_ops,
@@ -197,6 +214,19 @@ static void ci_flush_qtd(int ep_num)
}
/**
+ * ci_flush_td - flush cache over queue item
+ * @td: td pointer
+ *
+ * This function flushes cache for particular transfer descriptor.
+ */
+static void ci_flush_td(struct ept_queue_item *td)
+{
+ const uint32_t start = (uint32_t)td;
+ const uint32_t end = (uint32_t) td + ILIST_ENT_SZ;
+ flush_dcache_range(start, end);
+}
+
+/**
* ci_invalidate_qtd - invalidate cache over queue item
* @ep_num: Endpoint number
*
@@ -211,6 +241,19 @@ static void ci_invalidate_qtd(int ep_num)
invalidate_dcache_range(start, end);
}
+/**
+ * ci_invalidate_td - invalidate cache over queue item
+ * @td: td pointer
+ *
+ * This function invalidates cache for particular transfer descriptor.
+ */
+static void ci_invalidate_td(struct ept_queue_item *td)
+{
+ const uint32_t start = (uint32_t)td;
+ const uint32_t end = start + ILIST_ENT_SZ;
+ invalidate_dcache_range(start, end);
+}
+
static struct usb_request *
ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
{
@@ -376,6 +419,9 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
struct ept_queue_head *head;
int bit, num, len, in;
struct ci_req *ci_req;
+ u8 *buf;
+ uint32_t length, actlen;
+ struct ept_queue_item *dtd, *qtd;
ci_ep->req_primed = true;
@@ -387,16 +433,41 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
len = ci_req->req.length;
- item->info = INFO_BYTES(len) | INFO_ACTIVE;
- item->page0 = (uint32_t)ci_req->hw_buf;
- item->page1 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x1000;
- item->page2 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x2000;
- item->page3 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x3000;
- item->page4 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x4000;
-
head->next = (unsigned) item;
head->info = 0;
+ ci_req->dtd_count = 0;
+ buf = ci_req->hw_buf;
+ actlen = 0;
+ dtd = item;
+
+ do {
+ length = min(ci_req->req.length - actlen,
+ (unsigned)EP_MAX_LENGTH_TRANSFER);
+
+ dtd->info = INFO_BYTES(length) | INFO_ACTIVE;
+ dtd->page0 = (uint32_t)buf;
+ dtd->page1 = ((uint32_t)buf & 0xfffff000) + 0x1000;
+ dtd->page2 = ((uint32_t)buf & 0xfffff000) + 0x2000;
+ dtd->page3 = ((uint32_t)buf & 0xfffff000) + 0x3000;
+ dtd->page4 = ((uint32_t)buf & 0xfffff000) + 0x4000;
+
+ len -= length;
+ actlen += length;
+ buf += length;
+
+ if (len) {
+ qtd = (struct ept_queue_item *)
+ memalign(ILIST_ALIGN, ILIST_ENT_SZ);
+ dtd->next = (uint32_t)qtd;
+ dtd = qtd;
+ memset(dtd, 0, ILIST_ENT_SZ);
+ }
+
+ ci_req->dtd_count++;
+ } while (len);
+
+ item = dtd;
/*
* When sending the data for an IN transaction, the attached host
* knows that all data for the IN is sent when one of the following
@@ -432,6 +503,12 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
ci_flush_qtd(num);
+ item = (struct ept_queue_item *)head->next;
+ while (item->next != TERMINATE) {
+ ci_flush_td((struct ept_queue_item *)item->next);
+ item = (struct ept_queue_item *)item->next;
+ }
+
DBG("ept%d %s queue len %x, req %p, buffer %p\n",
num, in ? "in" : "out", len, ci_req, ci_req->hw_buf);
ci_flush_qh(num);
@@ -497,21 +574,31 @@ static void flip_ep0_direction(void)
static void handle_ep_complete(struct ci_ep *ci_ep)
{
- struct ept_queue_item *item;
- int num, in, len;
+ struct ept_queue_item *item, *next_td;
+ int num, in, len, j;
struct ci_req *ci_req;
num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
item = ci_get_qtd(num, in);
ci_invalidate_qtd(num);
+ ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
- len = (item->info >> 16) & 0x7fff;
- if (item->info & 0xff)
- printf("EP%d/%s FAIL info=%x pg0=%x\n",
- num, in ? "in" : "out", item->info, item->page0);
+ next_td = item;
+ len = 0;
+ for (j = 0; j < ci_req->dtd_count; j++) {
+ ci_invalidate_td(next_td);
+ item = next_td;
+ len += (item->info >> 16) & 0x7fff;
+ if (item->info & 0xff)
+ printf("EP%d/%s FAIL info=%x pg0=%x\n",
+ num, in ? "in" : "out", item->info, item->page0);
+ if (j != ci_req->dtd_count - 1)
+ next_td = (struct ept_queue_item *)item->next;
+ if (j != 0)
+ free(item);
+ }
- ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
list_del_init(&ci_req->queue);
ci_ep->req_primed = false;
@@ -847,9 +934,19 @@ static int ci_udc_probe(void)
controller.gadget.ep0 = &controller.ep[0].ep;
INIT_LIST_HEAD(&controller.gadget.ep0->ep_list);
- /* Init EP 1..n */
- for (i = 1; i < NUM_ENDPOINTS; i++) {
- memcpy(&controller.ep[i].ep, &ci_ep_init[1],
+ /* Init EP 1..3 */
+ for (i = 1; i < 4; i++) {
+ memcpy(&controller.ep[i].ep, &ci_ep_init[i],
+ sizeof(*ci_ep_init));
+ INIT_LIST_HEAD(&controller.ep[i].queue);
+ controller.ep[i].req_primed = false;
+ list_add_tail(&controller.ep[i].ep.ep_list,
+ &controller.gadget.ep_list);
+ }
+
+ /* Init EP 4..n */
+ for (i = 4; i < NUM_ENDPOINTS; i++) {
+ memcpy(&controller.ep[i].ep, &ci_ep_init[4],
sizeof(*ci_ep_init));
INIT_LIST_HEAD(&controller.ep[i].queue);
controller.ep[i].req_primed = false;
diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
index 346164a..95cc079 100644
--- a/drivers/usb/gadget/ci_udc.h
+++ b/drivers/usb/gadget/ci_udc.h
@@ -86,6 +86,7 @@ struct ci_req {
/* Buffer for the current transfer. Either req.buf/len or b_buf/len */
uint8_t *hw_buf;
uint32_t hw_len;
+ uint32_t dtd_count;
};
struct ci_ep {
--
1.7.4
^ permalink raw reply related [flat|nested] 6+ messages in thread* [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers
2014-09-05 6:46 [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers Siva Durga Prasad Paladugu
@ 2014-09-24 12:31 ` Michal Simek
2015-04-15 11:00 ` Michal Simek
2015-04-28 8:59 ` Michal Simek
1 sibling, 1 reply; 6+ messages in thread
From: Michal Simek @ 2014-09-24 12:31 UTC (permalink / raw)
To: u-boot
On 09/05/2014 08:46 AM, Siva Durga Prasad Paladugu wrote:
> Update the ci_udc driver to support bulk transfer
> and also added capability of having multiple dtds
> if requested data is more thank 16K.
> These changes are tested for both the DFU and lthor.
>
> Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
> ---
> drivers/usb/gadget/ci_udc.c | 135 +++++++++++++++++++++++++++++++++++++------
> drivers/usb/gadget/ci_udc.h | 1 +
> 2 files changed, 117 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
> index 2572b34..d1d19dc 100644
> --- a/drivers/usb/gadget/ci_udc.c
> +++ b/drivers/usb/gadget/ci_udc.c
> @@ -50,6 +50,8 @@
> /* For each endpoint, we need 2 QTDs, one for each of IN and OUT */
> #define ILIST_SZ (NUM_ENDPOINTS * 2 * ILIST_ENT_SZ)
>
> +#define EP_MAX_LENGTH_TRANSFER 0x4000
> +
> #ifndef DEBUG
> #define DBG(x...) do {} while (0)
> #else
> @@ -102,13 +104,28 @@ static struct usb_ep_ops ci_ep_ops = {
> };
>
> /* Init values for USB endpoints. */
> -static const struct usb_ep ci_ep_init[2] = {
> +static const struct usb_ep ci_ep_init[5] = {
> [0] = { /* EP 0 */
> .maxpacket = 64,
> .name = "ep0",
> .ops = &ci_ep_ops,
> },
> - [1] = { /* EP 1..n */
> + [1] = {
> + .maxpacket = 512,
> + .name = "ep1in-bulk",
> + .ops = &ci_ep_ops,
> + },
> + [2] = {
> + .maxpacket = 512,
> + .name = "ep2out-bulk",
> + .ops = &ci_ep_ops,
> + },
> + [3] = {
> + .maxpacket = 512,
> + .name = "ep3in-int",
> + .ops = &ci_ep_ops,
> + },
> + [4] = {
> .maxpacket = 512,
> .name = "ep-",
> .ops = &ci_ep_ops,
> @@ -197,6 +214,19 @@ static void ci_flush_qtd(int ep_num)
> }
>
> /**
> + * ci_flush_td - flush cache over queue item
> + * @td: td pointer
> + *
> + * This function flushes cache for particular transfer descriptor.
> + */
> +static void ci_flush_td(struct ept_queue_item *td)
> +{
> + const uint32_t start = (uint32_t)td;
> + const uint32_t end = (uint32_t) td + ILIST_ENT_SZ;
> + flush_dcache_range(start, end);
> +}
> +
> +/**
> * ci_invalidate_qtd - invalidate cache over queue item
> * @ep_num: Endpoint number
> *
> @@ -211,6 +241,19 @@ static void ci_invalidate_qtd(int ep_num)
> invalidate_dcache_range(start, end);
> }
>
> +/**
> + * ci_invalidate_td - invalidate cache over queue item
> + * @td: td pointer
> + *
> + * This function invalidates cache for particular transfer descriptor.
> + */
> +static void ci_invalidate_td(struct ept_queue_item *td)
> +{
> + const uint32_t start = (uint32_t)td;
> + const uint32_t end = start + ILIST_ENT_SZ;
> + invalidate_dcache_range(start, end);
> +}
> +
> static struct usb_request *
> ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
> {
> @@ -376,6 +419,9 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
> struct ept_queue_head *head;
> int bit, num, len, in;
> struct ci_req *ci_req;
> + u8 *buf;
> + uint32_t length, actlen;
> + struct ept_queue_item *dtd, *qtd;
>
> ci_ep->req_primed = true;
>
> @@ -387,16 +433,41 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
> ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
> len = ci_req->req.length;
>
> - item->info = INFO_BYTES(len) | INFO_ACTIVE;
> - item->page0 = (uint32_t)ci_req->hw_buf;
> - item->page1 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x1000;
> - item->page2 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x2000;
> - item->page3 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x3000;
> - item->page4 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x4000;
> -
> head->next = (unsigned) item;
> head->info = 0;
>
> + ci_req->dtd_count = 0;
> + buf = ci_req->hw_buf;
> + actlen = 0;
> + dtd = item;
> +
> + do {
> + length = min(ci_req->req.length - actlen,
> + (unsigned)EP_MAX_LENGTH_TRANSFER);
> +
> + dtd->info = INFO_BYTES(length) | INFO_ACTIVE;
> + dtd->page0 = (uint32_t)buf;
> + dtd->page1 = ((uint32_t)buf & 0xfffff000) + 0x1000;
> + dtd->page2 = ((uint32_t)buf & 0xfffff000) + 0x2000;
> + dtd->page3 = ((uint32_t)buf & 0xfffff000) + 0x3000;
> + dtd->page4 = ((uint32_t)buf & 0xfffff000) + 0x4000;
> +
> + len -= length;
> + actlen += length;
> + buf += length;
> +
> + if (len) {
> + qtd = (struct ept_queue_item *)
> + memalign(ILIST_ALIGN, ILIST_ENT_SZ);
> + dtd->next = (uint32_t)qtd;
> + dtd = qtd;
> + memset(dtd, 0, ILIST_ENT_SZ);
> + }
> +
> + ci_req->dtd_count++;
> + } while (len);
> +
> + item = dtd;
> /*
> * When sending the data for an IN transaction, the attached host
> * knows that all data for the IN is sent when one of the following
> @@ -432,6 +503,12 @@ static void ci_ep_submit_next_request(struct ci_ep *ci_ep)
>
> ci_flush_qtd(num);
>
> + item = (struct ept_queue_item *)head->next;
> + while (item->next != TERMINATE) {
> + ci_flush_td((struct ept_queue_item *)item->next);
> + item = (struct ept_queue_item *)item->next;
> + }
> +
> DBG("ept%d %s queue len %x, req %p, buffer %p\n",
> num, in ? "in" : "out", len, ci_req, ci_req->hw_buf);
> ci_flush_qh(num);
> @@ -497,21 +574,31 @@ static void flip_ep0_direction(void)
>
> static void handle_ep_complete(struct ci_ep *ci_ep)
> {
> - struct ept_queue_item *item;
> - int num, in, len;
> + struct ept_queue_item *item, *next_td;
> + int num, in, len, j;
> struct ci_req *ci_req;
>
> num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
> in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
> item = ci_get_qtd(num, in);
> ci_invalidate_qtd(num);
> + ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
>
> - len = (item->info >> 16) & 0x7fff;
> - if (item->info & 0xff)
> - printf("EP%d/%s FAIL info=%x pg0=%x\n",
> - num, in ? "in" : "out", item->info, item->page0);
> + next_td = item;
> + len = 0;
> + for (j = 0; j < ci_req->dtd_count; j++) {
> + ci_invalidate_td(next_td);
> + item = next_td;
> + len += (item->info >> 16) & 0x7fff;
> + if (item->info & 0xff)
> + printf("EP%d/%s FAIL info=%x pg0=%x\n",
> + num, in ? "in" : "out", item->info, item->page0);
> + if (j != ci_req->dtd_count - 1)
> + next_td = (struct ept_queue_item *)item->next;
> + if (j != 0)
> + free(item);
> + }
>
> - ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
> list_del_init(&ci_req->queue);
> ci_ep->req_primed = false;
>
> @@ -847,9 +934,19 @@ static int ci_udc_probe(void)
> controller.gadget.ep0 = &controller.ep[0].ep;
> INIT_LIST_HEAD(&controller.gadget.ep0->ep_list);
>
> - /* Init EP 1..n */
> - for (i = 1; i < NUM_ENDPOINTS; i++) {
> - memcpy(&controller.ep[i].ep, &ci_ep_init[1],
> + /* Init EP 1..3 */
> + for (i = 1; i < 4; i++) {
> + memcpy(&controller.ep[i].ep, &ci_ep_init[i],
> + sizeof(*ci_ep_init));
> + INIT_LIST_HEAD(&controller.ep[i].queue);
> + controller.ep[i].req_primed = false;
> + list_add_tail(&controller.ep[i].ep.ep_list,
> + &controller.gadget.ep_list);
> + }
> +
> + /* Init EP 4..n */
> + for (i = 4; i < NUM_ENDPOINTS; i++) {
> + memcpy(&controller.ep[i].ep, &ci_ep_init[4],
> sizeof(*ci_ep_init));
> INIT_LIST_HEAD(&controller.ep[i].queue);
> controller.ep[i].req_primed = false;
> diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
> index 346164a..95cc079 100644
> --- a/drivers/usb/gadget/ci_udc.h
> +++ b/drivers/usb/gadget/ci_udc.h
> @@ -86,6 +86,7 @@ struct ci_req {
> /* Buffer for the current transfer. Either req.buf/len or b_buf/len */
> uint8_t *hw_buf;
> uint32_t hw_len;
> + uint32_t dtd_count;
> };
>
> struct ci_ep {
>
Tested-by: Michal Simek <monstr@monstr.eu>
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20140924/420e88dd/attachment.pgp>
^ permalink raw reply [flat|nested] 6+ messages in thread* [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers
2014-09-24 12:31 ` Michal Simek
@ 2015-04-15 11:00 ` Michal Simek
0 siblings, 0 replies; 6+ messages in thread
From: Michal Simek @ 2015-04-15 11:00 UTC (permalink / raw)
To: u-boot
Hi Marek,
2014-09-24 14:31 GMT+02:00 Michal Simek <monstr@monstr.eu>:
> On 09/05/2014 08:46 AM, Siva Durga Prasad Paladugu wrote:
> > Update the ci_udc driver to support bulk transfer
> > and also added capability of having multiple dtds
> > if requested data is more thank 16K.
> > These changes are tested for both the DFU and lthor.
> >
> > Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
> > ---
> > drivers/usb/gadget/ci_udc.c | 135
> +++++++++++++++++++++++++++++++++++++------
> > drivers/usb/gadget/ci_udc.h | 1 +
> > 2 files changed, 117 insertions(+), 19 deletions(-)
> >
> > diff --git a/drivers/usb/gadget/ci_udc.c b/drivers/usb/gadget/ci_udc.c
> > index 2572b34..d1d19dc 100644
> > --- a/drivers/usb/gadget/ci_udc.c
> > +++ b/drivers/usb/gadget/ci_udc.c
> > @@ -50,6 +50,8 @@
> > /* For each endpoint, we need 2 QTDs, one for each of IN and OUT */
> > #define ILIST_SZ (NUM_ENDPOINTS * 2 * ILIST_ENT_SZ)
> >
> > +#define EP_MAX_LENGTH_TRANSFER 0x4000
> > +
> > #ifndef DEBUG
> > #define DBG(x...) do {} while (0)
> > #else
> > @@ -102,13 +104,28 @@ static struct usb_ep_ops ci_ep_ops = {
> > };
> >
> > /* Init values for USB endpoints. */
> > -static const struct usb_ep ci_ep_init[2] = {
> > +static const struct usb_ep ci_ep_init[5] = {
> > [0] = { /* EP 0 */
> > .maxpacket = 64,
> > .name = "ep0",
> > .ops = &ci_ep_ops,
> > },
> > - [1] = { /* EP 1..n */
> > + [1] = {
> > + .maxpacket = 512,
> > + .name = "ep1in-bulk",
> > + .ops = &ci_ep_ops,
> > + },
> > + [2] = {
> > + .maxpacket = 512,
> > + .name = "ep2out-bulk",
> > + .ops = &ci_ep_ops,
> > + },
> > + [3] = {
> > + .maxpacket = 512,
> > + .name = "ep3in-int",
> > + .ops = &ci_ep_ops,
> > + },
> > + [4] = {
> > .maxpacket = 512,
> > .name = "ep-",
> > .ops = &ci_ep_ops,
> > @@ -197,6 +214,19 @@ static void ci_flush_qtd(int ep_num)
> > }
> >
> > /**
> > + * ci_flush_td - flush cache over queue item
> > + * @td: td pointer
> > + *
> > + * This function flushes cache for particular transfer descriptor.
> > + */
> > +static void ci_flush_td(struct ept_queue_item *td)
> > +{
> > + const uint32_t start = (uint32_t)td;
> > + const uint32_t end = (uint32_t) td + ILIST_ENT_SZ;
> > + flush_dcache_range(start, end);
> > +}
> > +
> > +/**
> > * ci_invalidate_qtd - invalidate cache over queue item
> > * @ep_num: Endpoint number
> > *
> > @@ -211,6 +241,19 @@ static void ci_invalidate_qtd(int ep_num)
> > invalidate_dcache_range(start, end);
> > }
> >
> > +/**
> > + * ci_invalidate_td - invalidate cache over queue item
> > + * @td: td pointer
> > + *
> > + * This function invalidates cache for particular transfer descriptor.
> > + */
> > +static void ci_invalidate_td(struct ept_queue_item *td)
> > +{
> > + const uint32_t start = (uint32_t)td;
> > + const uint32_t end = start + ILIST_ENT_SZ;
> > + invalidate_dcache_range(start, end);
> > +}
> > +
> > static struct usb_request *
> > ci_ep_alloc_request(struct usb_ep *ep, unsigned int gfp_flags)
> > {
> > @@ -376,6 +419,9 @@ static void ci_ep_submit_next_request(struct ci_ep
> *ci_ep)
> > struct ept_queue_head *head;
> > int bit, num, len, in;
> > struct ci_req *ci_req;
> > + u8 *buf;
> > + uint32_t length, actlen;
> > + struct ept_queue_item *dtd, *qtd;
> >
> > ci_ep->req_primed = true;
> >
> > @@ -387,16 +433,41 @@ static void ci_ep_submit_next_request(struct ci_ep
> *ci_ep)
> > ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
> > len = ci_req->req.length;
> >
> > - item->info = INFO_BYTES(len) | INFO_ACTIVE;
> > - item->page0 = (uint32_t)ci_req->hw_buf;
> > - item->page1 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x1000;
> > - item->page2 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x2000;
> > - item->page3 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x3000;
> > - item->page4 = ((uint32_t)ci_req->hw_buf & 0xfffff000) + 0x4000;
> > -
> > head->next = (unsigned) item;
> > head->info = 0;
> >
> > + ci_req->dtd_count = 0;
> > + buf = ci_req->hw_buf;
> > + actlen = 0;
> > + dtd = item;
> > +
> > + do {
> > + length = min(ci_req->req.length - actlen,
> > + (unsigned)EP_MAX_LENGTH_TRANSFER);
> > +
> > + dtd->info = INFO_BYTES(length) | INFO_ACTIVE;
> > + dtd->page0 = (uint32_t)buf;
> > + dtd->page1 = ((uint32_t)buf & 0xfffff000) + 0x1000;
> > + dtd->page2 = ((uint32_t)buf & 0xfffff000) + 0x2000;
> > + dtd->page3 = ((uint32_t)buf & 0xfffff000) + 0x3000;
> > + dtd->page4 = ((uint32_t)buf & 0xfffff000) + 0x4000;
> > +
> > + len -= length;
> > + actlen += length;
> > + buf += length;
> > +
> > + if (len) {
> > + qtd = (struct ept_queue_item *)
> > + memalign(ILIST_ALIGN, ILIST_ENT_SZ);
> > + dtd->next = (uint32_t)qtd;
> > + dtd = qtd;
> > + memset(dtd, 0, ILIST_ENT_SZ);
> > + }
> > +
> > + ci_req->dtd_count++;
> > + } while (len);
> > +
> > + item = dtd;
> > /*
> > * When sending the data for an IN transaction, the attached host
> > * knows that all data for the IN is sent when one of the following
> > @@ -432,6 +503,12 @@ static void ci_ep_submit_next_request(struct ci_ep
> *ci_ep)
> >
> > ci_flush_qtd(num);
> >
> > + item = (struct ept_queue_item *)head->next;
> > + while (item->next != TERMINATE) {
> > + ci_flush_td((struct ept_queue_item *)item->next);
> > + item = (struct ept_queue_item *)item->next;
> > + }
> > +
> > DBG("ept%d %s queue len %x, req %p, buffer %p\n",
> > num, in ? "in" : "out", len, ci_req, ci_req->hw_buf);
> > ci_flush_qh(num);
> > @@ -497,21 +574,31 @@ static void flip_ep0_direction(void)
> >
> > static void handle_ep_complete(struct ci_ep *ci_ep)
> > {
> > - struct ept_queue_item *item;
> > - int num, in, len;
> > + struct ept_queue_item *item, *next_td;
> > + int num, in, len, j;
> > struct ci_req *ci_req;
> >
> > num = ci_ep->desc->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
> > in = (ci_ep->desc->bEndpointAddress & USB_DIR_IN) != 0;
> > item = ci_get_qtd(num, in);
> > ci_invalidate_qtd(num);
> > + ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
> >
> > - len = (item->info >> 16) & 0x7fff;
> > - if (item->info & 0xff)
> > - printf("EP%d/%s FAIL info=%x pg0=%x\n",
> > - num, in ? "in" : "out", item->info, item->page0);
> > + next_td = item;
> > + len = 0;
> > + for (j = 0; j < ci_req->dtd_count; j++) {
> > + ci_invalidate_td(next_td);
> > + item = next_td;
> > + len += (item->info >> 16) & 0x7fff;
> > + if (item->info & 0xff)
> > + printf("EP%d/%s FAIL info=%x pg0=%x\n",
> > + num, in ? "in" : "out", item->info,
> item->page0);
> > + if (j != ci_req->dtd_count - 1)
> > + next_td = (struct ept_queue_item *)item->next;
> > + if (j != 0)
> > + free(item);
> > + }
> >
> > - ci_req = list_first_entry(&ci_ep->queue, struct ci_req, queue);
> > list_del_init(&ci_req->queue);
> > ci_ep->req_primed = false;
> >
> > @@ -847,9 +934,19 @@ static int ci_udc_probe(void)
> > controller.gadget.ep0 = &controller.ep[0].ep;
> > INIT_LIST_HEAD(&controller.gadget.ep0->ep_list);
> >
> > - /* Init EP 1..n */
> > - for (i = 1; i < NUM_ENDPOINTS; i++) {
> > - memcpy(&controller.ep[i].ep, &ci_ep_init[1],
> > + /* Init EP 1..3 */
> > + for (i = 1; i < 4; i++) {
> > + memcpy(&controller.ep[i].ep, &ci_ep_init[i],
> > + sizeof(*ci_ep_init));
> > + INIT_LIST_HEAD(&controller.ep[i].queue);
> > + controller.ep[i].req_primed = false;
> > + list_add_tail(&controller.ep[i].ep.ep_list,
> > + &controller.gadget.ep_list);
> > + }
> > +
> > + /* Init EP 4..n */
> > + for (i = 4; i < NUM_ENDPOINTS; i++) {
> > + memcpy(&controller.ep[i].ep, &ci_ep_init[4],
> > sizeof(*ci_ep_init));
> > INIT_LIST_HEAD(&controller.ep[i].queue);
> > controller.ep[i].req_primed = false;
> > diff --git a/drivers/usb/gadget/ci_udc.h b/drivers/usb/gadget/ci_udc.h
> > index 346164a..95cc079 100644
> > --- a/drivers/usb/gadget/ci_udc.h
> > +++ b/drivers/usb/gadget/ci_udc.h
> > @@ -86,6 +86,7 @@ struct ci_req {
> > /* Buffer for the current transfer. Either req.buf/len or
> b_buf/len */
> > uint8_t *hw_buf;
> > uint32_t hw_len;
> > + uint32_t dtd_count;
> > };
> >
> > struct ci_ep {
> >
>
> Tested-by: Michal Simek <monstr@monstr.eu>
>
> Thanks,
> Michal
>
>
>
Any update on this one?
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers
2014-09-05 6:46 [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers Siva Durga Prasad Paladugu
2014-09-24 12:31 ` Michal Simek
@ 2015-04-28 8:59 ` Michal Simek
2015-04-28 13:55 ` Marek Vasut
1 sibling, 1 reply; 6+ messages in thread
From: Michal Simek @ 2015-04-28 8:59 UTC (permalink / raw)
To: u-boot
On 09/05/2014 08:46 AM, Siva Durga Prasad Paladugu wrote:
> Update the ci_udc driver to support bulk transfer
> and also added capability of having multiple dtds
> if requested data is more thank 16K.
> These changes are tested for both the DFU and lthor.
>
> Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
> ---
> drivers/usb/gadget/ci_udc.c | 135 +++++++++++++++++++++++++++++++++++++------
> drivers/usb/gadget/ci_udc.h | 1 +
> 2 files changed, 117 insertions(+), 19 deletions(-)
Marek and Lukasz: Any update on this one?
Thanks,
Michal
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20150428/e233035c/attachment.sig>
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers
2015-04-28 8:59 ` Michal Simek
@ 2015-04-28 13:55 ` Marek Vasut
2015-04-29 7:10 ` Lukasz Majewski
0 siblings, 1 reply; 6+ messages in thread
From: Marek Vasut @ 2015-04-28 13:55 UTC (permalink / raw)
To: u-boot
On Tuesday, April 28, 2015 at 10:59:16 AM, Michal Simek wrote:
> On 09/05/2014 08:46 AM, Siva Durga Prasad Paladugu wrote:
> > Update the ci_udc driver to support bulk transfer
> > and also added capability of having multiple dtds
> > if requested data is more thank 16K.
> > These changes are tested for both the DFU and lthor.
> >
> > Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
> > ---
> >
> > drivers/usb/gadget/ci_udc.c | 135
> > +++++++++++++++++++++++++++++++++++++------ drivers/usb/gadget/ci_udc.h
> > | 1 +
> > 2 files changed, 117 insertions(+), 19 deletions(-)
>
> Marek and Lukasz: Any update on this one?
I wanted to pick this, but I cannot apply this on u-boot-usb/master . Can
you please rebase this and repost ? In case Lukasz doesn't pick it, I will.
Best regards,
Marek Vasut
^ permalink raw reply [flat|nested] 6+ messages in thread
* [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers
2015-04-28 13:55 ` Marek Vasut
@ 2015-04-29 7:10 ` Lukasz Majewski
0 siblings, 0 replies; 6+ messages in thread
From: Lukasz Majewski @ 2015-04-29 7:10 UTC (permalink / raw)
To: u-boot
Hi Marek,
> On Tuesday, April 28, 2015 at 10:59:16 AM, Michal Simek wrote:
> > On 09/05/2014 08:46 AM, Siva Durga Prasad Paladugu wrote:
> > > Update the ci_udc driver to support bulk transfer
> > > and also added capability of having multiple dtds
> > > if requested data is more thank 16K.
> > > These changes are tested for both the DFU and lthor.
> > >
> > > Signed-off-by: Siva Durga Prasad Paladugu <sivadur@xilinx.com>
> > > ---
> > >
> > > drivers/usb/gadget/ci_udc.c | 135
> > > +++++++++++++++++++++++++++++++++++++------
> > > drivers/usb/gadget/ci_udc.h | 1 +
> > > 2 files changed, 117 insertions(+), 19 deletions(-)
> >
> > Marek and Lukasz: Any update on this one?
>
> I wanted to pick this, but I cannot apply this on u-boot-usb/master .
> Can you please rebase this and repost ? In case Lukasz doesn't pick
> it, I will.
Marek, please pick this patch. Thanks!
>
> Best regards,
> Marek Vasut
--
Best regards,
Lukasz Majewski
Samsung R&D Institute Poland (SRPOL) | Linux Platform Group
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2015-04-29 7:10 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-09-05 6:46 [U-Boot] [UBOOT PATCH] ci_udc: Update the ci_udc driver to support bulk transfers Siva Durga Prasad Paladugu
2014-09-24 12:31 ` Michal Simek
2015-04-15 11:00 ` Michal Simek
2015-04-28 8:59 ` Michal Simek
2015-04-28 13:55 ` Marek Vasut
2015-04-29 7:10 ` Lukasz Majewski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox