diff mbox

[U-Boot,4/4] usb: fastboot: implement fastboot

Message ID 1421793730-8179-5-git-send-email-srae@broadcom.com
State Rejected
Delegated to: Ɓukasz Majewski
Headers show

Commit Message

Steve Rae Jan. 20, 2015, 10:42 p.m. UTC
- add "bcm_usb_gadget.c"
- implement fastboot on 'bcm28155_ap' boards

Signed-off-by: Steve Rae <srae@broadcom.com>
---

 drivers/usb/gadget/Makefile         |   2 +
 drivers/usb/gadget/bcm_usb_gadget.c | 240 ++++++++++++++++++++++++++++++++++++
 include/configs/bcm28155_ap.h       |  20 ++-
 3 files changed, 261 insertions(+), 1 deletion(-)
 create mode 100644 drivers/usb/gadget/bcm_usb_gadget.c
diff mbox

Patch

diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 70bb550..8b55c1f 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -20,6 +20,8 @@  obj-$(CONFIG_USBDOWNLOAD_GADGET) += g_dnl.o
 obj-$(CONFIG_DFU_FUNCTION) += f_dfu.o
 obj-$(CONFIG_USB_GADGET_MASS_STORAGE) += f_mass_storage.o
 obj-$(CONFIG_CMD_FASTBOOT) += f_fastboot.o
+obj-$(CONFIG_BCM_UDC_OTG) += bcm_usb_gadget.o
+obj-$(CONFIG_BCM_UDC_OTG) += bcm_udc_otg.o
 endif
 ifdef CONFIG_USB_ETHER
 obj-y += ether.o
diff --git a/drivers/usb/gadget/bcm_usb_gadget.c b/drivers/usb/gadget/bcm_usb_gadget.c
new file mode 100644
index 0000000..cc7e182
--- /dev/null
+++ b/drivers/usb/gadget/bcm_usb_gadget.c
@@ -0,0 +1,240 @@ 
+/*
+ * Copyright 2015 Broadcom Corporation.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <config.h>
+#include <common.h>
+#include <malloc.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+
+#include "bcm_udc_otg.h"
+
+/* fwd declarations */
+static struct usb_request *in_req;
+static struct usb_request *out_req;
+
+#define RESPONSE_LEN	(64 + 1)
+
+/*
+ * usb_ep_ops: stub callback functions
+ */
+
+static int stub_enable(struct usb_ep *ep,
+		       const struct usb_endpoint_descriptor *desc)
+{
+	printf("called: %s\n", __func__);
+	return 0;
+}
+
+static int stub_disable(struct usb_ep *ep)
+{
+	printf("called: %s\n", __func__);
+	return 0;
+}
+
+static struct usb_request *stub_alloc_request(struct usb_ep *ep,
+					      gfp_t gfp_flags)
+{
+	printf("called: %s\n", __func__);
+	return NULL;
+}
+
+static void stub_free_request(struct usb_ep *ep, struct usb_request *req)
+{
+	printf("called: %s\n", __func__);
+}
+
+/*
+ * static int stub_queue(struct usb_ep *ep, struct usb_request *request,
+ *			 gfp_t gfp_flags)
+ */
+
+static int stub_dequeue(struct usb_ep *ep, struct usb_request *request)
+{
+	printf("called: %s\n", __func__);
+	return 0;
+}
+
+static int stub_set_halt(struct usb_ep *ep, int value)
+{
+	printf("called: %s\n", __func__);
+	return 0;
+}
+
+static int stub_fifo_status(struct usb_ep *ep)
+{
+	printf("called: %s\n", __func__);
+	return 0;
+}
+
+static void stub_fifo_flush(struct usb_ep *ep)
+{
+	printf("called: %s\n", __func__);
+}
+
+/*
+ * usb_ep_ops: implement callback functions
+ */
+
+static int queue_bulk_in_ep(struct usb_ep *ep, struct usb_request *req,
+			    gfp_t gfp_flags)
+{
+	int ret;
+	/* verify: only "send" requests (in_req) on this bulk endpoint */
+	if (req != in_req) {
+		error("fatal %p %p", req, in_req);
+		return -1;
+	}
+
+	/* send a packet via the bulk endpoint */
+	ret = usb_send_bulk_otg(req->buf, strlen(req->buf));
+	if (ret)
+		printf("%s: usb_send_bulk_otg() returned: %d\n", __func__, ret);
+
+	if (req->complete)
+		req->complete(ep, req);
+	else
+		printf("%s: skipping complete()\n", __func__);
+
+	return ret;
+}
+
+static int queue_bulk_out_ep(struct usb_ep *ep, struct usb_request *req,
+			     gfp_t gfp_flags)
+{
+	/* verify: only "receive" requests (out_req) on this bulk endpoint */
+	if (req != out_req) {
+		error("fatal %p %p", req, out_req);
+		return -1;
+	}
+
+	/* calling req->complete causes infinite loop, therefore, do nothing */
+
+	return 0;
+}
+
+/* initial values for USB Endpoint Operations */
+static const struct usb_ep_ops out_ep_ops = {
+	.enable		= stub_enable,
+	.disable	= stub_disable,
+	.alloc_request	= stub_alloc_request,
+	.free_request	= stub_free_request,
+	.queue		= queue_bulk_out_ep,
+	.dequeue	= stub_dequeue,
+	.set_halt	= stub_set_halt,
+	.fifo_status	= stub_fifo_status,
+	.fifo_flush	= stub_fifo_flush
+};
+
+static const struct usb_ep_ops in_ep_ops = {
+	.enable		= stub_enable,
+	.disable	= stub_disable,
+	.alloc_request	= stub_alloc_request,
+	.free_request	= stub_free_request,
+	.queue		= queue_bulk_in_ep,
+	.dequeue	= stub_dequeue,
+	.set_halt	= stub_set_halt,
+	.fifo_status	= stub_fifo_status,
+	.fifo_flush	= stub_fifo_flush
+};
+
+/* initial values for USB Endpoints */
+static struct usb_ep in_ep_init = {
+	.name		= "in_ep",
+	.ops		= &in_ep_ops,
+	.maxpacket	= 512,
+};
+static struct usb_ep *in_ep = &in_ep_init;	/* bulk ep, to host */
+
+static struct usb_ep out_ep_init = {
+	.name		= "out_ep",
+	.ops		= &out_ep_ops,
+	.maxpacket	= 512,
+};
+static struct usb_ep *out_ep = &out_ep_init;	/* bulk ep, from host */
+
+/* initial values for USB Requests */
+static struct usb_request in_req_init;
+static struct usb_request *in_req = &in_req_init;
+
+static struct usb_request out_req_init;
+static struct usb_request *out_req = &out_req_init;
+
+/*
+ * local functions
+ */
+
+static int rx_handler(const unsigned char *buffer, unsigned int buffer_size)
+{
+	/* zero the Response Buffer */
+	memset(in_req->buf, 0, RESPONSE_LEN);
+
+	/* seed the Out Request values */
+	out_req->buf = (char *)buffer;
+	out_req->actual = buffer_size;
+
+	/* perform the callback */
+	if (out_req->complete)
+		out_req->complete(out_ep, out_req);
+	else
+		error("FATAL: no handler defined!");
+
+	return out_req->status;
+}
+
+static int fastboot_init(void)
+{
+	int ret;
+
+	usb_shutdown_otg();
+
+	ret = usb_init_otg(rx_handler);
+
+	return ret;
+}
+
+extern void fastboot_func_init(struct usb_ep *in_ep, struct usb_ep *out_ep,
+		struct usb_request *in_req, struct usb_request *out_req);
+
+/*
+ * USB Gadget implementation
+ */
+
+int usb_gadget_register_driver(struct usb_gadget_driver *driver)
+{
+	int ret;
+	ret = fastboot_init();
+	debug("%s: ret=%d\n", __func__, ret);
+	if (ret) {
+		error("fastboot_init() failed!");
+		return -1;
+	}
+
+	in_req->length = RESPONSE_LEN;
+	in_req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, RESPONSE_LEN);
+	if (!in_req->buf) {
+		error("fatal: alloc failed");
+		return -1;
+	}
+
+	fastboot_func_init(in_ep, NULL, in_req, out_req);
+	return 0;
+}
+
+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
+{
+	if (in_req->buf)
+		free(in_req->buf);
+	debug("%s\n", __func__);
+	return 0;
+}
+
+int usb_gadget_handle_interrupts(void)
+{
+	usb_handle_ints_otg();
+	return 0;
+}
diff --git a/include/configs/bcm28155_ap.h b/include/configs/bcm28155_ap.h
index 1045779..e5103d4 100644
--- a/include/configs/bcm28155_ap.h
+++ b/include/configs/bcm28155_ap.h
@@ -1,7 +1,7 @@ 
 /*
  * Copyright 2013 Broadcom Corporation.
  *
- * SPDX-License-Identifier:      GPL-2.0+
+ * SPDX-License-Identifier:	GPL-2.0+
  */
 
 #ifndef __BCM28155_AP_H
@@ -109,6 +109,7 @@ 
  * for example.
  */
 #define CONFIG_DOS_PARTITION
+#define CONFIG_EFI_PARTITION
 
 /* version string, parser, etc */
 #define CONFIG_VERSION_VARIABLE
@@ -137,4 +138,21 @@ 
 #undef CONFIG_CMD_NET
 #undef CONFIG_CMD_NFS
 
+/* Fastboot and USB OTG */
+#define CONFIG_USB_GADGET
+#define CONFIG_CMD_FASTBOOT
+#define CONFIG_FASTBOOT_NO_GADGET
+#define CONFIG_FASTBOOT_FLASH
+#define CONFIG_FASTBOOT_FLASH_MMC_DEV	0
+#define CONFIG_SYS_CACHELINE_SIZE	64
+#define CONFIG_USB_FASTBOOT_BUF_SIZE	(CONFIG_SYS_SDRAM_SIZE - (1024 * 1024))
+#define CONFIG_USB_FASTBOOT_BUF_ADDR	CONFIG_SYS_SDRAM_BASE
+#define CONFIG_USB_GADGET_VBUS_DRAW	0
+#define CONFIG_USBDOWNLOAD_GADGET
+#define CONFIG_USBID_ADDR		0x34052c46
+#define CONFIG_G_DNL_VENDOR_NUM		0x18d1	/* google */
+#define CONFIG_G_DNL_PRODUCT_NUM	0x0d02	/* nexus one */
+#define CONFIG_G_DNL_MANUFACTURER	"Broadcom Corporation"
+#define CONFIG_BCM_UDC_OTG
+
 #endif /* __BCM28155_AP_H */