libpayload: Add zero length packet support to UDC framework

Some IN transfers must be terminated by an empty packet
because otherwise the host wouldn't know.

The zlp() function determines this requirement in
accordance to USB rules: If the transfer's size is aligned
to the maximum packet size, and the host expects a larger
transfer, add the empty packet as a hint.

BRANCH=none
BUG=none
TEST=USB device mode still works

Change-Id: Ia69f3d017f72a3a0e0b21bac72fe97be184c7daa
Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Commit-Id: fd0e946e4948a74a9ed15a5eed6ce827b7672a56
Original-Change-Id: I8153cc5bd2ff1c88e383c1dbcddaf1bf72f9194c
Original-Signed-off-by: Patrick Georgi <pgeorgi@chromium.org>
Original-Reviewed-on: https://chromium-review.googlesource.com/250790
Original-Reviewed-by: Furquan Shaikh <furquan@chromium.org>
Reviewed-on: http://review.coreboot.org/9784
Tested-by: build bot (Jenkins)
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
diff --git a/payloads/libpayload/drivers/udc/chipidea.c b/payloads/libpayload/drivers/udc/chipidea.c
index e06f0d2..58bea06 100644
--- a/payloads/libpayload/drivers/udc/chipidea.c
+++ b/payloads/libpayload/drivers/udc/chipidea.c
@@ -153,6 +153,7 @@
 	setbits_le32(&p->opreg->epctrl[ep],
 		((1 << 7) | (1 << 6) | (ep_type << 2)) << (in_dir*16));
 	p->ep_busy[ep][in_dir] = 0;
+	this->ep_mps[ep][in_dir] = mps;
 }
 
 static void advance_endpoint(struct chipidea_pdata *p, int endpoint, int in_dir)
@@ -463,6 +464,14 @@
 	ctrl->free_data = chipidea_free;
 	ctrl->initialized = 0;
 
+	int i;
+	ctrl->ep_mps[0][0] = 64;
+	ctrl->ep_mps[0][1] = 64;
+	for (i = 1; i < 16; i++) {
+		ctrl->ep_mps[i][0] = 512;
+		ctrl->ep_mps[i][1] = 512;
+	}
+
 	if (!chipidea_hw_init(ctrl, (void *)0x7d000000, dd)) {
 		free(ctrl->pdata);
 		free(ctrl);