All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
@ 2017-08-16 18:00 Stefan Agner
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 1/8] imx: move imximage header to common location Stefan Agner
                   ` (9 more replies)
  0 siblings, 10 replies; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

From: Stefan Agner <stefan.agner@toradex.com>

This series adds NXP's Serial Download Protocol (SDP) support via
USB for SPL/U-Boot. It allows to download U-Boot via USB from a
(recovered) SPL using the same tools used to download SPL itself
(specifically imx_usb, but also sb_loader seems to work).

The idea has been brought up when the first targets started to make
use of SPL for DDR initialization, see:
https://lists.denx.de/pipermail/u-boot/2015-July/220330.html

The initial SDP implementation (patch 2) requires the payload to
have the imx specific headers (hence the move of the imx header
file in patch 1).

Patch 3 extends image header support beyond the SDP specification,
specifically implements also support for U-Boot headers. This
allows to use the same SPL/U-Boot binaries for recovery as used on
the regular boot device (SD/eMMC). For that to work also the host
side imx_usb tools needed an extension, currently available here:

https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored

(in case this patchset gets accepted in U-Boot, I plan to push
these imx_usb changes upstream as well)

The full patchset allows to download SPL and U-Boot over USB to a
target in recovery mode using the same usb_imx utility. Refer to
the new README.sdp for details how to use usb_imx in combination
with this implementation.

Changes in v2:
- Changed function signature of sdp_init/sdp_handle to allow specifying
  which USB controller should be used.
- Use #defines for security mode
- Improved types used in format strings
- Changed function signature of sdp_init/sdp_handle
- Use BOOT_DEVICE_BOARD

Stefan Agner (8):
  imx: move imximage header to common location
  usb: gadget: add SDP driver
  usb: gadget: sdp: extend images compatible for jumps
  cmd: add sdp command
  spl: add serial download protocol (SDP) support
  doc: add Serial Download Protocol documentation
  apalis/colibri_imx6: use independent USB PID for SPL
  apalis/colibri_imx6: enable SDP by default

 board/toradex/apalis_imx6/apalis_imx6.c   |  13 +
 board/toradex/colibri_imx6/colibri_imx6.c |  13 +
 cmd/Kconfig                               |   7 +
 cmd/Makefile                              |   1 +
 cmd/usb_gadget_sdp.c                      |  50 ++
 common/spl/Kconfig                        |   6 +
 common/spl/Makefile                       |   1 +
 common/spl/spl_sdp.c                      |  37 ++
 configs/apalis_imx6_defconfig             |   4 +
 configs/colibri_imx6_defconfig            |   4 +
 doc/README.sdp                            | 100 ++++
 drivers/usb/gadget/Kconfig                |   7 +
 drivers/usb/gadget/Makefile               |   2 +
 drivers/usb/gadget/f_sdp.c                | 737 ++++++++++++++++++++++++++++++
 {tools => include}/imximage.h             |   0
 include/sdp.h                             |  16 +
 16 files changed, 998 insertions(+)
 create mode 100644 cmd/usb_gadget_sdp.c
 create mode 100644 common/spl/spl_sdp.c
 create mode 100644 doc/README.sdp
 create mode 100644 drivers/usb/gadget/f_sdp.c
 rename {tools => include}/imximage.h (100%)
 create mode 100644 include/sdp.h

-- 
2.14.1

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 1/8] imx: move imximage header to common location
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver Stefan Agner
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 543 bytes --]

From: Stefan Agner <stefan.agner@toradex.com>

Move the imximage.h header file to a common location so we can make
use of it from U-Boot too.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Reviewed-by: Łukasz Majewski <lukma@denx.de>
---

Changes in v2: None

 {tools => include}/imximage.h | 0
 1 file changed, 0 insertions(+), 0 deletions(-)
 rename {tools => include}/imximage.h (100%)

diff --git a/tools/imximage.h b/include/imximage.h
similarity index 100%
rename from tools/imximage.h
rename to include/imximage.h
-- 
2.14.1


^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 1/8] imx: move imximage header to common location Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-17 10:04   ` Łukasz Majewski
  2017-08-17 13:49   ` Stefano Babic
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 3/8] usb: gadget: sdp: extend images compatible for jumps Stefan Agner
                   ` (7 subsequent siblings)
  9 siblings, 2 replies; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

From: Stefan Agner <stefan.agner@toradex.com>

Add SDP (Serial Downloader Protocol) implementation for U-Boot. The
protocol is used in NXP SoC's boot ROM and allows to download program
images. Beside that, it can also be used to read/write registers and
download complete Device Configuration Data (DCD) sets. This basic
implementation supports downloading images with the imx header format
reading and writing registers.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
---

Changes in v2:
- Changed function signature of sdp_init/sdp_handle to allow specifying
  which USB controller should be used.
- Use #defines for security mode
- Improved types used in format strings

 drivers/usb/gadget/Kconfig  |   7 +
 drivers/usb/gadget/Makefile |   1 +
 drivers/usb/gadget/f_sdp.c  | 721 ++++++++++++++++++++++++++++++++++++++++++++
 include/sdp.h               |  16 +
 4 files changed, 745 insertions(+)
 create mode 100644 drivers/usb/gadget/f_sdp.c
 create mode 100644 include/sdp.h

diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index 261ed128ac..225b66bc95 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -103,6 +103,13 @@ config USB_GADGET_DOWNLOAD
 
 if USB_GADGET_DOWNLOAD
 
+config USB_FUNCTION_SDP
+	bool "Enable USB SDP (Serial Download Protocol)"
+	help
+	  Enable Serial Download Protocol (SDP) device support in U-Boot. This
+	  allows to download images into memory and execute (jump to) them
+	  using the same protocol as implemented by the i.MX family's boot ROM.
+
 config G_DNL_MANUFACTURER
 	string "Vendor name of USB device"
 
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 5e316a7cff..6a007d1bcb 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
 obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
 obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
 obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
+obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
 endif
 endif
 ifdef CONFIG_USB_ETHER
diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
new file mode 100644
index 0000000000..9d82abcd69
--- /dev/null
+++ b/drivers/usb/gadget/f_sdp.c
@@ -0,0 +1,721 @@
+/*
+ * f_sdp.c -- USB HID Serial Download Protocol
+ *
+ * Copyright (C) 2017 Toradex
+ * Author: Stefan Agner <stefan.agner@toradex.com>
+ *
+ * This file implements the Serial Download Protocol (SDP) as specified in
+ * the i.MX 6 Reference Manual. The SDP is a USB HID based protocol and
+ * allows to download images directly to memory. The implementation
+ * works with the imx_loader (imx_usb) USB client software on host side.
+ *
+ * Not all commands are implemented, e.g. WRITE_REGISTER, DCD_WRITE and
+ * SKIP_DCD_HEADER are only stubs.
+ *
+ * Parts of the implementation are based on f_dfu and f_thor.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <errno.h>
+#include <common.h>
+#include <console.h>
+#include <malloc.h>
+
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+
+#include <asm/io.h>
+#include <g_dnl.h>
+#include <sdp.h>
+#include <imximage.h>
+
+#define HID_REPORT_ID_MASK	0x000000ff
+
+/*
+ * HID class requests
+ */
+#define HID_REQ_GET_REPORT		0x01
+#define HID_REQ_GET_IDLE		0x02
+#define HID_REQ_GET_PROTOCOL		0x03
+#define HID_REQ_SET_REPORT		0x09
+#define HID_REQ_SET_IDLE		0x0A
+#define HID_REQ_SET_PROTOCOL		0x0B
+
+#define HID_USAGE_PAGE_LEN		76
+
+struct hid_report {
+	u8 usage_page[HID_USAGE_PAGE_LEN];
+} __packed;
+
+#define SDP_READ_REGISTER	0x0101
+#define SDP_WRITE_REGISTER	0x0202
+#define SDP_WRITE_FILE		0x0404
+#define SDP_ERROR_STATUS	0x0505
+#define SDP_DCD_WRITE		0x0a0a
+#define SDP_JUMP_ADDRESS	0x0b0b
+#define SDP_SKIP_DCD_HEADER	0x0c0c
+
+#define SDP_SECURITY_CLOSED		0x12343412
+#define SDP_SECURITY_OPEN		0x56787856
+
+#define SDP_WRITE_FILE_COMPLETE		0x88888888
+#define SDP_WRITE_REGISTER_COMPLETE	0x128A8A12
+#define SDP_SKIP_DCD_HEADER_COMPLETE	0x900DD009
+#define SDP_ERROR_IMXHEADER		0x000a0533
+
+#define SDP_COMMAND_LEN		16
+
+struct sdp_command {
+	u16 cmd;
+	u32 addr;
+	u8 format;
+	u32 cnt;
+	u32 data;
+	u8 rsvd;
+} __packed;
+
+enum sdp_state {
+	SDP_STATE_IDLE,
+	SDP_STATE_RX_DCD_DATA,
+	SDP_STATE_RX_FILE_DATA,
+	SDP_STATE_TX_SEC_CONF,
+	SDP_STATE_TX_SEC_CONF_BUSY,
+	SDP_STATE_TX_REGISTER,
+	SDP_STATE_TX_REGISTER_BUSY,
+	SDP_STATE_TX_STATUS,
+	SDP_STATE_TX_STATUS_BUSY,
+	SDP_STATE_JUMP,
+};
+
+struct f_sdp {
+	struct usb_function		usb_function;
+
+	struct usb_descriptor_header	**function;
+
+	u8				altsetting;
+	enum sdp_state			state;
+	enum sdp_state			next_state;
+	u32				dnl_address;
+	u32				dnl_bytes_remaining;
+	u32				jmp_address;
+	bool				always_send_status;
+	u32				error_status;
+
+	/* EP0 request */
+	struct usb_request		*req;
+
+	/* EP1 IN */
+	struct usb_ep			*in_ep;
+	struct usb_request		*in_req;
+
+	bool				configuration_done;
+};
+
+static struct f_sdp *sdp_func;
+
+static inline struct f_sdp *func_to_sdp(struct usb_function *f)
+{
+	return container_of(f, struct f_sdp, usb_function);
+}
+
+static struct usb_interface_descriptor sdp_intf_runtime = {
+	.bLength =		sizeof(sdp_intf_runtime),
+	.bDescriptorType =	USB_DT_INTERFACE,
+	.bAlternateSetting =	0,
+	.bNumEndpoints =	1,
+	.bInterfaceClass =	USB_CLASS_HID,
+	.bInterfaceSubClass =	0,
+	.bInterfaceProtocol =	0,
+	/* .iInterface = DYNAMIC */
+};
+
+/* HID configuration */
+static struct usb_class_hid_descriptor sdp_hid_desc = {
+	.bLength =		sizeof(sdp_hid_desc),
+	.bDescriptorType =	USB_DT_CS_DEVICE,
+
+	.bcdCDC =		__constant_cpu_to_le16(0x0110),
+	.bCountryCode =		0,
+	.bNumDescriptors =	1,
+
+	.bDescriptorType0	= USB_DT_HID_REPORT,
+	.wDescriptorLength0	= HID_USAGE_PAGE_LEN,
+};
+
+static struct usb_endpoint_descriptor in_desc = {
+	.bLength =		USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType =	USB_DT_ENDPOINT, /*USB_DT_CS_ENDPOINT*/
+
+	.bEndpointAddress =	1 | USB_DIR_IN,
+	.bmAttributes =	USB_ENDPOINT_XFER_INT,
+	.wMaxPacketSize =	64,
+	.bInterval =		1,
+};
+
+static struct usb_descriptor_header *sdp_runtime_descs[] = {
+	(struct usb_descriptor_header *)&sdp_intf_runtime,
+	(struct usb_descriptor_header *)&sdp_hid_desc,
+	(struct usb_descriptor_header *)&in_desc,
+	NULL,
+};
+
+/* This is synchronized with what the SoC implementation reports */
+static struct hid_report sdp_hid_report = {
+	.usage_page = {
+		0x06, 0x00, 0xff, /* Usage Page */
+		0x09, 0x01, /* Usage (Pointer?) */
+		0xa1, 0x01, /* Collection */
+
+		0x85, 0x01, /* Report ID */
+		0x19, 0x01, /* Usage Minimum */
+		0x29, 0x01, /* Usage Maximum */
+		0x15, 0x00, /* Local Minimum */
+		0x26, 0xFF, 0x00, /* Local Maximum? */
+		0x75, 0x08, /* Report Size */
+		0x95, 0x10, /* Report Count */
+		0x91, 0x02, /* Output Data */
+
+		0x85, 0x02, /* Report ID */
+		0x19, 0x01, /* Usage Minimum */
+		0x29, 0x01, /* Usage Maximum */
+		0x15, 0x00, /* Local Minimum */
+		0x26, 0xFF, 0x00, /* Local Maximum? */
+		0x75, 0x80, /* Report Size 128 */
+		0x95, 0x40, /* Report Count */
+		0x91, 0x02, /* Output Data */
+
+		0x85, 0x03, /* Report ID */
+		0x19, 0x01, /* Usage Minimum */
+		0x29, 0x01, /* Usage Maximum */
+		0x15, 0x00, /* Local Minimum */
+		0x26, 0xFF, 0x00, /* Local Maximum? */
+		0x75, 0x08, /* Report Size 8 */
+		0x95, 0x04, /* Report Count */
+		0x81, 0x02, /* Input Data */
+
+		0x85, 0x04, /* Report ID */
+		0x19, 0x01, /* Usage Minimum */
+		0x29, 0x01, /* Usage Maximum */
+		0x15, 0x00, /* Local Minimum */
+		0x26, 0xFF, 0x00, /* Local Maximum? */
+		0x75, 0x08, /* Report Size 8 */
+		0x95, 0x40, /* Report Count */
+		0x81, 0x02, /* Input Data */
+		0xc0
+	},
+};
+
+static const char sdp_name[] = "Serial Downloader Protocol";
+
+/*
+ * static strings, in UTF-8
+ */
+static struct usb_string strings_sdp_generic[] = {
+	[0].s = sdp_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_sdp_generic = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= strings_sdp_generic,
+};
+
+static struct usb_gadget_strings *sdp_generic_strings[] = {
+	&stringtab_sdp_generic,
+	NULL,
+};
+
+static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_sdp *sdp = req->context;
+	int status = req->status;
+	u8 *data = req->buf;
+	u8 report = data[0];
+
+	if (status != 0) {
+		error("Status: %d", status);
+		return;
+	}
+
+	if (report != 1) {
+		error("Unexpected report %d", report);
+		return;
+	}
+
+	struct sdp_command *cmd = req->buf + 1;
+
+	debug("%s: command: %04x, addr: %08x, cnt: %u\n",
+	      __func__, be16_to_cpu(cmd->cmd),
+	      be32_to_cpu(cmd->addr), be32_to_cpu(cmd->cnt));
+
+	switch (be16_to_cpu(cmd->cmd)) {
+	case SDP_READ_REGISTER:
+		sdp->always_send_status = false;
+		sdp->error_status = 0x0;
+
+		sdp->state = SDP_STATE_TX_SEC_CONF;
+		sdp->dnl_address = be32_to_cpu(cmd->addr);
+		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
+		sdp->next_state = SDP_STATE_TX_REGISTER;
+		printf("Reading %d registers at 0x%08x... ",
+		       sdp->dnl_bytes_remaining, sdp->dnl_address);
+		break;
+	case SDP_WRITE_FILE:
+		sdp->always_send_status = true;
+		sdp->error_status = SDP_WRITE_FILE_COMPLETE;
+
+		sdp->state = SDP_STATE_RX_FILE_DATA;
+		sdp->dnl_address = be32_to_cpu(cmd->addr);
+		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
+		sdp->next_state = SDP_STATE_IDLE;
+
+		printf("Downloading file of size %d to 0x%08x... ",
+		       sdp->dnl_bytes_remaining, sdp->dnl_address);
+
+		break;
+	case SDP_ERROR_STATUS:
+		sdp->always_send_status = true;
+		sdp->error_status = 0;
+
+		sdp->state = SDP_STATE_TX_SEC_CONF;
+		sdp->next_state = SDP_STATE_IDLE;
+		break;
+	case SDP_DCD_WRITE:
+		sdp->always_send_status = true;
+		sdp->error_status = SDP_WRITE_REGISTER_COMPLETE;
+
+		sdp->state = SDP_STATE_RX_DCD_DATA;
+		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
+		sdp->next_state = SDP_STATE_IDLE;
+		break;
+	case SDP_JUMP_ADDRESS:
+		sdp->always_send_status = false;
+		sdp->error_status = 0;
+
+		sdp->jmp_address = be32_to_cpu(cmd->addr);
+		sdp->state = SDP_STATE_TX_SEC_CONF;
+		sdp->next_state = SDP_STATE_JUMP;
+		break;
+	case SDP_SKIP_DCD_HEADER:
+		sdp->always_send_status = true;
+		sdp->error_status = SDP_SKIP_DCD_HEADER_COMPLETE;
+
+		/* Ignore command, DCD not supported anyway */
+		sdp->state = SDP_STATE_TX_SEC_CONF;
+		sdp->next_state = SDP_STATE_IDLE;
+		break;
+	default:
+		error("Unknown command: %04x\n", be16_to_cpu(cmd->cmd));
+	}
+}
+
+static void sdp_rx_data_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_sdp *sdp = req->context;
+	int status = req->status;
+	u8 *data = req->buf;
+	u8 report = data[0];
+	int datalen = req->length - 1;
+
+	if (status != 0) {
+		error("Status: %d", status);
+		return;
+	}
+
+	if (report != 2) {
+		error("Unexpected report %d", report);
+		return;
+	}
+
+	if (sdp->dnl_bytes_remaining < datalen) {
+		/*
+		 * Some USB stacks require to send a complete buffer as
+		 * specified in the HID descriptor. This leads to longer
+		 * transfers than the file length, no problem for us.
+		 */
+		sdp->dnl_bytes_remaining = 0;
+	} else {
+		sdp->dnl_bytes_remaining -= datalen;
+	}
+
+	if (sdp->state == SDP_STATE_RX_FILE_DATA) {
+		memcpy((void *)sdp->dnl_address, req->buf + 1, datalen);
+		sdp->dnl_address += datalen;
+	}
+
+	if (sdp->dnl_bytes_remaining)
+		return;
+
+	printf("done\n");
+
+	switch (sdp->state) {
+	case SDP_STATE_RX_FILE_DATA:
+		sdp->state = SDP_STATE_TX_SEC_CONF;
+		break;
+	case SDP_STATE_RX_DCD_DATA:
+		sdp->state = SDP_STATE_TX_SEC_CONF;
+		break;
+	default:
+		error("Invalid state: %d", sdp->state);
+	}
+}
+
+static void sdp_tx_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_sdp *sdp = req->context;
+	int status = req->status;
+
+	if (status != 0) {
+		error("Status: %d", status);
+		return;
+	}
+
+	switch (sdp->state) {
+	case SDP_STATE_TX_SEC_CONF_BUSY:
+		/* Not all commands require status report */
+		if (sdp->always_send_status || sdp->error_status)
+			sdp->state = SDP_STATE_TX_STATUS;
+		else
+			sdp->state = sdp->next_state;
+
+		break;
+	case SDP_STATE_TX_STATUS_BUSY:
+		sdp->state = sdp->next_state;
+		break;
+	case SDP_STATE_TX_REGISTER_BUSY:
+		if (sdp->dnl_bytes_remaining)
+			sdp->state = SDP_STATE_TX_REGISTER;
+		else
+			sdp->state = SDP_STATE_IDLE;
+		break;
+	default:
+		error("Wrong State: %d", sdp->state);
+		sdp->state = SDP_STATE_IDLE;
+		break;
+	}
+	debug("%s complete --> %d, %d/%d\n", ep->name,
+	      status, req->actual, req->length);
+}
+
+static int sdp_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
+{
+	struct usb_gadget *gadget = f->config->cdev->gadget;
+	struct usb_request *req = f->config->cdev->req;
+	struct f_sdp *sdp = f->config->cdev->req->context;
+	u16 len = le16_to_cpu(ctrl->wLength);
+	u16 w_value = le16_to_cpu(ctrl->wValue);
+	int value = 0;
+	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
+
+	debug("w_value: 0x%04x len: 0x%04x\n", w_value, len);
+	debug("req_type: 0x%02x ctrl->bRequest: 0x%02x sdp->state: %d\n",
+	      req_type, ctrl->bRequest, sdp->state);
+
+	if (req_type == USB_TYPE_STANDARD) {
+		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR) {
+			/* Send HID report descriptor */
+			value = min(len, (u16) sizeof(sdp_hid_report));
+			memcpy(req->buf, &sdp_hid_report, value);
+			sdp->configuration_done = true;
+		}
+	}
+
+	if (req_type == USB_TYPE_CLASS) {
+		int report = w_value & HID_REPORT_ID_MASK;
+
+		/* HID (SDP) request */
+		switch (ctrl->bRequest) {
+		case HID_REQ_SET_REPORT:
+			switch (report) {
+			case 1:
+				value = SDP_COMMAND_LEN + 1;
+				req->complete = sdp_rx_command_complete;
+				break;
+			case 2:
+				value = len;
+				req->complete = sdp_rx_data_complete;
+				break;
+			}
+		}
+	}
+
+	if (value >= 0) {
+		req->length = value;
+		req->zero = value < len;
+		value = usb_ep_queue(gadget->ep0, req, 0);
+		if (value < 0) {
+			debug("ep_queue --> %d\n", value);
+			req->status = 0;
+		}
+	}
+
+	return value;
+}
+
+static int sdp_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	struct usb_gadget *gadget = c->cdev->gadget;
+	struct usb_composite_dev *cdev = c->cdev;
+	struct f_sdp *sdp = func_to_sdp(f);
+	int rv = 0, id;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	sdp_intf_runtime.bInterfaceNumber = id;
+
+	struct usb_ep *ep;
+
+	/* allocate instance-specific endpoints */
+	ep = usb_ep_autoconfig(gadget, &in_desc);
+	if (!ep) {
+		rv = -ENODEV;
+		goto error;
+	}
+
+	sdp->in_ep = ep; /* Store IN EP for enabling @ setup */
+
+	cdev->req->context = sdp;
+
+error:
+	return rv;
+}
+
+static void sdp_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	free(sdp_func);
+	sdp_func = NULL;
+}
+
+static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
+{
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, 0);
+	if (!req)
+		return req;
+
+	req->length = length;
+	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
+	if (!req->buf) {
+		usb_ep_free_request(ep, req);
+		req = NULL;
+	}
+
+	return req;
+}
+
+
+static struct usb_request *sdp_start_ep(struct usb_ep *ep)
+{
+	struct usb_request *req;
+
+	req = alloc_ep_req(ep, 64);
+	debug("%s: ep:%p req:%p\n", __func__, ep, req);
+
+	if (!req)
+		return NULL;
+
+	memset(req->buf, 0, req->length);
+	req->complete = sdp_tx_complete;
+
+	return req;
+}
+static int sdp_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
+{
+	struct f_sdp *sdp = func_to_sdp(f);
+	struct usb_composite_dev *cdev = f->config->cdev;
+	int result;
+
+	debug("%s: intf: %d alt: %d\n", __func__, intf, alt);
+
+	result = usb_ep_enable(sdp->in_ep, &in_desc);
+	if (result)
+		return result;
+	sdp->in_req = sdp_start_ep(sdp->in_ep);
+	sdp->in_req->context = sdp;
+
+	sdp->in_ep->driver_data = cdev; /* claim */
+
+	sdp->altsetting = alt;
+	sdp->state = SDP_STATE_IDLE;
+
+	return 0;
+}
+
+static int sdp_get_alt(struct usb_function *f, unsigned intf)
+{
+	struct f_sdp *sdp = func_to_sdp(f);
+
+	return sdp->altsetting;
+}
+
+static void sdp_disable(struct usb_function *f)
+{
+	struct f_sdp *sdp = func_to_sdp(f);
+
+	usb_ep_disable(sdp->in_ep);
+
+	if (sdp->in_req) {
+		free(sdp->in_req);
+		sdp->in_req = NULL;
+	}
+}
+
+static int sdp_bind_config(struct usb_configuration *c)
+{
+	int status;
+
+	if (!sdp_func) {
+		sdp_func = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*sdp_func));
+		if (!sdp_func)
+			return -ENOMEM;
+	}
+
+	memset(sdp_func, 0, sizeof(*sdp_func));
+
+	sdp_func->usb_function.name = "sdp";
+	sdp_func->usb_function.hs_descriptors = sdp_runtime_descs;
+	sdp_func->usb_function.descriptors = sdp_runtime_descs;
+	sdp_func->usb_function.bind = sdp_bind;
+	sdp_func->usb_function.unbind = sdp_unbind;
+	sdp_func->usb_function.set_alt = sdp_set_alt;
+	sdp_func->usb_function.get_alt = sdp_get_alt;
+	sdp_func->usb_function.disable = sdp_disable;
+	sdp_func->usb_function.strings = sdp_generic_strings;
+	sdp_func->usb_function.setup = sdp_setup;
+
+	status = usb_add_function(c, &sdp_func->usb_function);
+
+	return status;
+}
+
+int sdp_init(int controller_index)
+{
+	printf("SDP: initialize...\n");
+	while (!sdp_func->configuration_done) {
+		if (ctrlc()) {
+			puts("\rCTRL+C - Operation aborted.\n");
+			return 1;
+		}
+		usb_gadget_handle_interrupts(controller_index);
+	}
+
+	return 0;
+}
+
+static u32 sdp_jump_imxheader(void *address)
+{
+	flash_header_v2_t *headerv2 = address;
+	ulong (*entry)(void);
+
+	if (headerv2->header.tag != IVT_HEADER_TAG) {
+		printf("Header Tag is not an IMX image\n");
+		return SDP_ERROR_IMXHEADER;
+	}
+
+	printf("Jumping to 0x%08x\n", headerv2->entry);
+	entry = (void *)headerv2->entry;
+	entry();
+
+	/* The image probably never returns hence we won't reach that point */
+	return 0;
+}
+
+static void sdp_handle_in_ep(void)
+{
+	u8 *data = sdp_func->in_req->buf;
+	u32 status;
+	int datalen;
+
+	switch (sdp_func->state) {
+	case SDP_STATE_TX_SEC_CONF:
+		debug("Report 3: HAB security\n");
+		data[0] = 3;
+
+		status = SDP_SECURITY_OPEN;
+		memcpy(&data[1], &status, 4);
+		sdp_func->in_req->length = 5;
+		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
+		sdp_func->state = SDP_STATE_TX_SEC_CONF_BUSY;
+		break;
+
+	case SDP_STATE_TX_STATUS:
+		debug("Report 4: Status\n");
+		data[0] = 4;
+
+		memcpy(&data[1], &sdp_func->error_status, 4);
+		sdp_func->in_req->length = 65;
+		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
+		sdp_func->state = SDP_STATE_TX_STATUS_BUSY;
+		break;
+	case SDP_STATE_TX_REGISTER:
+		debug("Report 4: Register Values\n");
+		data[0] = 4;
+
+		datalen = sdp_func->dnl_bytes_remaining;
+
+		if (datalen > 64)
+			datalen = 64;
+
+		memcpy(&data[1], (void *)sdp_func->dnl_address, datalen);
+		sdp_func->in_req->length = 65;
+
+		sdp_func->dnl_bytes_remaining -= datalen;
+		sdp_func->dnl_address += datalen;
+
+		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
+		sdp_func->state = SDP_STATE_TX_REGISTER_BUSY;
+		break;
+	case SDP_STATE_JUMP:
+		printf("Checking imxheader at 0x%08x\n", f_sdp->jmp_address);
+		status = sdp_jump_imxheader((void *)f_sdp->jmp_address);
+
+		sdp_func->next_state = SDP_STATE_IDLE;
+		sdp_func->error_status = status;
+
+		/* Only send Report 4 if there was an error */
+		if (status)
+			sdp_func->state = SDP_STATE_TX_STATUS;
+		else
+			sdp_func->state = SDP_STATE_IDLE;
+		break;
+	default:
+		break;
+	};
+}
+
+void sdp_handle(int controller_index)
+{
+	printf("SDP: handle requests...\n");
+	while (1) {
+		if (ctrlc()) {
+			puts("\rCTRL+C - Operation aborted.\n");
+			return;
+		}
+
+		usb_gadget_handle_interrupts(controller_index);
+
+		sdp_handle_in_ep();
+	}
+}
+
+int sdp_add(struct usb_configuration *c)
+{
+	int id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+	strings_sdp_generic[0].id = id;
+	sdp_intf_runtime.iInterface = id;
+
+	debug("%s: cdev: %p gadget: %p gadget->ep0: %p\n", __func__,
+	      c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
+
+	return sdp_bind_config(c);
+}
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_sdp, sdp_add);
diff --git a/include/sdp.h b/include/sdp.h
new file mode 100644
index 0000000000..f476bab8f1
--- /dev/null
+++ b/include/sdp.h
@@ -0,0 +1,16 @@
+/*
+ * sdp.h - Serial Download Protocol
+ *
+ * Copyright (C) 2017 Toradex
+ * Author: Stefan Agner <stefan.agner@toradex.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __SDP_H_
+#define __SDP_H_
+
+int sdp_init(int controller_index);
+void sdp_handle(int controller_index);
+
+#endif /* __SDP_H_ */
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 3/8] usb: gadget: sdp: extend images compatible for jumps
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 1/8] imx: move imximage header to common location Stefan Agner
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 4/8] cmd: add sdp command Stefan Agner
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 1848 bytes --]

From: Stefan Agner <stefan.agner@toradex.com>

Support U-Boot images in SPL so that u-boot.img files can be
directly downloaded and executed. Furthermore support U-Boot
scripts download and execution in full U-Boot so that custom
recovery actions can be downloaded from the host in a third
step.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Reviewed-by: Łukasz Majewski <lukma@denx.de>
Reviewed-by: Stefano Babic <sbabic@denx.de>
---

Changes in v2: None

 drivers/usb/gadget/f_sdp.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
index 9d82abcd69..0fae66beab 100644
--- a/drivers/usb/gadget/f_sdp.c
+++ b/drivers/usb/gadget/f_sdp.c
@@ -29,6 +29,8 @@
 #include <asm/io.h>
 #include <g_dnl.h>
 #include <sdp.h>
+#include <spl.h>
+#include <image.h>
 #include <imximage.h>
 
 #define HID_REPORT_ID_MASK	0x000000ff
@@ -670,8 +672,22 @@ static void sdp_handle_in_ep(void)
 		sdp_func->state = SDP_STATE_TX_REGISTER_BUSY;
 		break;
 	case SDP_STATE_JUMP:
-		printf("Checking imxheader at 0x%08x\n", f_sdp->jmp_address);
-		status = sdp_jump_imxheader((void *)f_sdp->jmp_address);
+		printf("Jumping to header at 0x%08x\n", sdp_func->jmp_address);
+		status = sdp_jump_imxheader((void *)sdp_func->jmp_address);
+
+		/* If imx header fails, try some U-Boot specific headers */
+		if (status) {
+#ifdef CONFIG_SPL_BUILD
+			/* In SPL, allow jumps to U-Boot images */
+			struct spl_image_info spl_image = {};
+			spl_parse_image_header(&spl_image,
+				(struct image_header *)sdp_func->jmp_address);
+			jump_to_image_no_args(&spl_image);
+#else
+			/* In U-Boot, allow jumps to scripts */
+			source(sdp_func->jmp_address, "script at 1");
+#endif
+		}
 
 		sdp_func->next_state = SDP_STATE_IDLE;
 		sdp_func->error_status = status;
-- 
2.14.1


^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 4/8] cmd: add sdp command
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
                   ` (2 preceding siblings ...)
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 3/8] usb: gadget: sdp: extend images compatible for jumps Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 5/8] spl: add serial download protocol (SDP) support Stefan Agner
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

From: Stefan Agner <stefan.agner@toradex.com>

Add a new command to start USB Serial Download Protocol (SDP)
state machine.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Reviewed-by: Łukasz Majewski <lukma@denx.de>
Reviewed-by: Stefano Babic <sbabic@denx.de>
---

Changes in v2:
- Changed function signature of sdp_init/sdp_handle

 cmd/Kconfig          |  7 +++++++
 cmd/Makefile         |  1 +
 cmd/usb_gadget_sdp.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 58 insertions(+)
 create mode 100644 cmd/usb_gadget_sdp.c

diff --git a/cmd/Kconfig b/cmd/Kconfig
index 42d955c96a..d6d130edfa 100644
--- a/cmd/Kconfig
+++ b/cmd/Kconfig
@@ -895,6 +895,13 @@ config CMD_USB
 	help
 	  USB support.
 
+config CMD_USB_SDP
+	bool "sdp"
+	select USB_FUNCTION_SDP
+	help
+	  Enables the command "sdp" which is used to have U-Boot emulating the
+	  Serial Download Protocol (SDP) via USB.
+
 config CMD_USB_MASS_STORAGE
 	bool "UMS usb mass storage"
 	help
diff --git a/cmd/Makefile b/cmd/Makefile
index 13c86f8fcc..4ec0e175cd 100644
--- a/cmd/Makefile
+++ b/cmd/Makefile
@@ -131,6 +131,7 @@ obj-$(CONFIG_CMD_FASTBOOT) += fastboot.o
 obj-$(CONFIG_CMD_FS_UUID) += fs_uuid.o
 
 obj-$(CONFIG_CMD_USB_MASS_STORAGE) += usb_mass_storage.o
+obj-$(CONFIG_CMD_USB_SDP) += usb_gadget_sdp.o
 obj-$(CONFIG_CMD_THOR_DOWNLOAD) += thordown.o
 obj-$(CONFIG_CMD_XIMG) += ximg.o
 obj-$(CONFIG_CMD_YAFFS2) += yaffs2.o
diff --git a/cmd/usb_gadget_sdp.c b/cmd/usb_gadget_sdp.c
new file mode 100644
index 0000000000..b1d8b2858e
--- /dev/null
+++ b/cmd/usb_gadget_sdp.c
@@ -0,0 +1,50 @@
+/*
+ * cmd_sdp.c -- sdp command
+ *
+ * Copyright (C) 2016 Toradex
+ * Author: Stefan Agner <stefan.agner@toradex.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <g_dnl.h>
+#include <sdp.h>
+#include <usb.h>
+
+static int do_sdp(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+	int ret = CMD_RET_FAILURE;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	char *usb_controller = argv[1];
+	int controller_index = simple_strtoul(usb_controller, NULL, 0);
+	board_usb_init(controller_index, USB_INIT_DEVICE);
+
+	g_dnl_clear_detach();
+	g_dnl_register("usb_dnl_sdp");
+
+	ret = sdp_init(controller_index);
+	if (ret) {
+		error("SDP init failed: %d", ret);
+		goto exit;
+	}
+
+	/* This command typically does not return but jumps to an image */
+	sdp_handle(controller_index);
+	error("SDP ended");
+
+exit:
+	g_dnl_unregister();
+	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+
+	return ret;
+}
+
+U_BOOT_CMD(sdp, 2, 1, do_sdp,
+	"Serial Downloader Protocol",
+	"<USB_controller>\n"
+	"  - serial downloader protocol via <USB_controller>\n"
+);
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 5/8] spl: add serial download protocol (SDP) support
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
                   ` (3 preceding siblings ...)
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 4/8] cmd: add sdp command Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-17 10:10   ` Łukasz Majewski
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 6/8] doc: add Serial Download Protocol documentation Stefan Agner
                   ` (4 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

From: Stefan Agner <stefan.agner@toradex.com>

Add USB serial download protocol support to SPL. If the SoC started
in recovery mode the SPL will immediately switch to SDP and wait for
further downloads/commands from the host side.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Reviewed-by: Stefano Babic <sbabic@denx.de>
---

Changes in v2:
- Changed function signature of sdp_init/sdp_handle
- Use BOOT_DEVICE_BOARD

 common/spl/Kconfig          |  6 ++++++
 common/spl/Makefile         |  1 +
 common/spl/spl_sdp.c        | 37 +++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/Makefile |  1 +
 4 files changed, 45 insertions(+)
 create mode 100644 common/spl/spl_sdp.c

diff --git a/common/spl/Kconfig b/common/spl/Kconfig
index 5176857506..b3436b3c28 100644
--- a/common/spl/Kconfig
+++ b/common/spl/Kconfig
@@ -668,6 +668,12 @@ config SPL_DFU_RAM
 
 endchoice
 
+config SPL_USB_SDP_SUPPORT
+	bool "Support SDP (Serial Download Protocol)"
+	help
+	  Enable Serial Download Protocol (SDP) device support in SPL. This
+	  allows to download images into memory and execute (jump to) them
+	  using the same protocol as implemented by the i.MX family's boot ROM.
 endif
 
 config SPL_WATCHDOG_SUPPORT
diff --git a/common/spl/Makefile b/common/spl/Makefile
index 112b3e6022..6255d4f73c 100644
--- a/common/spl/Makefile
+++ b/common/spl/Makefile
@@ -30,4 +30,5 @@ obj-$(CONFIG_$(SPL_TPL_)SATA_SUPPORT) += spl_sata.o
 obj-$(CONFIG_$(SPL_TPL_)DFU_SUPPORT) += spl_dfu.o
 obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o
 obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o
+obj-$(CONFIG_$(SPL_TPL_)USB_SDP_SUPPORT) += spl_sdp.o
 endif
diff --git a/common/spl/spl_sdp.c b/common/spl/spl_sdp.c
new file mode 100644
index 0000000000..350bcdb056
--- /dev/null
+++ b/common/spl/spl_sdp.c
@@ -0,0 +1,37 @@
+/*
+ * (C) Copyright 2016 Toradex
+ * Author: Stefan Agner <stefan.agner@toradex.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <spl.h>
+#include <usb.h>
+#include <g_dnl.h>
+#include <sdp.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static int spl_sdp_load_image(struct spl_image_info *spl_image,
+			      struct spl_boot_device *bootdev)
+{
+	int ret;
+	const int controller_index = 0;
+
+	g_dnl_clear_detach();
+	g_dnl_register("usb_dnl_sdp");
+
+	ret = sdp_init(controller_index);
+	if (ret) {
+		error("SDP init failed: %d", ret);
+		return -ENODEV;
+	}
+
+	/* This command typically does not return but jumps to an image */
+	sdp_handle(controller_index);
+	error("SDP ended");
+
+	return -EINVAL;
+}
+SPL_LOAD_IMAGE_METHOD("USB SDP", 0, BOOT_DEVICE_BOARD, spl_sdp_load_image);
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
index 6a007d1bcb..7258099c1c 100644
--- a/drivers/usb/gadget/Makefile
+++ b/drivers/usb/gadget/Makefile
@@ -11,6 +11,7 @@ obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
 ifdef CONFIG_SPL_BUILD
 obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += g_dnl.o
 obj-$(CONFIG_SPL_DFU_SUPPORT) += f_dfu.o
+obj-$(CONFIG_SPL_USB_SDP_SUPPORT) += f_sdp.o
 endif
 
 # new USB gadget layer dependencies
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 6/8] doc: add Serial Download Protocol documentation
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
                   ` (4 preceding siblings ...)
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 5/8] spl: add serial download protocol (SDP) support Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-17 10:21   ` Łukasz Majewski
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 7/8] apalis/colibri_imx6: use independent USB PID for SPL Stefan Agner
                   ` (3 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

From: Stefan Agner <stefan.agner@toradex.com>

Document the U-Boot Serial Download Protocol implementation and
some typical use cases.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
---
This ended up to be almost more a imx_usb documentation. But there
is really not much to document from a U-Boot side since actual usage
heavily depends on host side tooling...

This assumes that the necessary changes will get merged upstream:
https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored


Changes in v2: None

 doc/README.sdp | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 100 insertions(+)
 create mode 100644 doc/README.sdp

diff --git a/doc/README.sdp b/doc/README.sdp
new file mode 100644
index 0000000000..9b438c0746
--- /dev/null
+++ b/doc/README.sdp
@@ -0,0 +1,100 @@
+-------------
+SDP in U-Boot
+-------------
+
+SDP stands for serial download protocol. It is the protocol used in NXP's
+i.MX SoCs ROM Serial Downloader and provides means to download a program
+image to the chip over USB and UART serial connection.
+
+The implementation in U-Boot uses the USB Downloader Gadget (g_dnl) to
+provide a SDP implementation over USB. This allows to download program
+images to the target in SPL/U-Boot using the same protocol/tooling the
+SoC's recovery mechanism is using.
+
+The SDP protocol over USB is a USB HID class protocol. USB HID class
+protocols allow to access a USB device without OS specific drivers. The
+U-Boot implementation has primarly been tested using the open source
+imx_loader utility (https://github.com/toradex/imx_loader).
+
+The host side utilities are typically capable to interpret the i.MX
+specific image header (see doc/README.imximage). There are extensions
+for imx_loader's imx_usb utility which allow to interpret the U-Boot
+specific legacy image format (see mkimage(1)). Also the U-Boot side
+support beside the i.MX specific header the U-Boot legacy header.
+
+Usage
+-----
+
+This implementation can be started in U-Boot using the sdp command
+(CONFIG_CMD_USB_SDP) or in SPL if Serial Downloader boot mode has been
+detected (CONFIG_SPL_USB_SDP_SUPPORT).
+
+A typical use case is downloading full U-Boot after SPL has been
+downloaded through the boot ROM's Serial Downloader. Using boot mode
+detection the SPL will run the SDP implementation automatically in
+this case:
+
+  # imx_usb SPL
+
+Targets Serial Console:
+
+  Trying to boot from USB SDP
+  SDP: initialize...
+  SDP: handle requests...
+
+At this point the SPL reenumerated as a new HID device and emulating
+the boot ROM's SDP protocol. The USB VID/PID will depend on standard
+U-Boot configurations CONFIG_G_DNL_(VENDOR|PRODUCT)_NUM. Make sure
+imx_usb is aware of the USB VID/PID for your device by adding a
+configuration entry in imx_usb.conf:
+
+  0x1b67:0x4fff, mx6_usb_sdp_spl.conf
+
+And the device specific configuration file mx6_usb_sdp_spl.conf:
+
+  mx6_spl_sdp
+  hid,uboot_header,1024,0x910000,0x10000000,1G,0x00900000,0x40000
+
+This allows to download the regular U-Boot with legacy image headers
+(u-boot.img) using a second invocation of imx_usb:
+
+  # imx_usb u-boot.img
+
+Furthermore, when U-Boot is running the sdp command can be used to
+download and run scripts:
+
+  # imx_usb script.scr
+
+imx_usb configuration files can be also used to download multiple
+files and of arbitrary types, e.g.
+
+  mx6_usb_sdp_uboot
+  hid,1024,0x10000000,1G,0x00907000,0x31000
+  full.itb:load 0x12100000
+  boot.scr:load 0x12000000,jump 0x12000000
+
+There is also a batch mode which allows imx_usb to handle multiple
+consecutive reenumerations by adding multiple VID/PID specifications
+in imx_usb.conf:
+
+  0x15a2:0x0061, mx6_usb_rom.conf, 0x1b67:0x4fff, mx6_usb_sdp_spl.conf
+
+In this mode the file to download (imx_usb job) needs to be specified
+in the configuration files.
+
+mx6_usb_rom.conf:
+
+  mx6_qsb
+  hid,1024,0x910000,0x10000000,1G,0x00900000,0x40000
+  SPL:jump header2
+
+mx6_usb_sdp_spl.conf:
+
+  mx6_spl_sdp
+  hid,uboot_header,1024,0x10000000,1G,0x00907000,0x31000
+  u-boot.img:jump header2
+
+With that SPL and U-Boot can be downloaded with a single invocation
+of imx_usb without arguments:
+
+  # imx_usb
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 7/8] apalis/colibri_imx6: use independent USB PID for SPL
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
                   ` (5 preceding siblings ...)
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 6/8] doc: add Serial Download Protocol documentation Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-17 10:23   ` Łukasz Majewski
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 8/8] apalis/colibri_imx6: enable SDP by default Stefan Agner
                   ` (2 subsequent siblings)
  9 siblings, 1 reply; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

From: Stefan Agner <stefan.agner@toradex.com>

Use a completely independent USB Product ID for SPL. This allows
to differentiate a SDP running in SPL and SDP running in a U-Boot
which could not read the config block successfully.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Acked-by: Max Krummenacher <max.krummenacher@toradex.com>
---

Changes in v2: None

 board/toradex/apalis_imx6/apalis_imx6.c   | 13 +++++++++++++
 board/toradex/colibri_imx6/colibri_imx6.c | 13 +++++++++++++
 2 files changed, 26 insertions(+)

diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c
index 8e5613cb12..edaca5d346 100644
--- a/board/toradex/apalis_imx6/apalis_imx6.c
+++ b/board/toradex/apalis_imx6/apalis_imx6.c
@@ -28,6 +28,7 @@
 #include <dm/platform_data/serial_mxc.h>
 #include <dm/platdata.h>
 #include <fsl_esdhc.h>
+#include <g_dnl.h>
 #include <i2c.h>
 #include <imx_thermal.h>
 #include <linux/errno.h>
@@ -1233,6 +1234,18 @@ void reset_cpu(ulong addr)
 {
 }
 
+#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
+int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
+{
+	unsigned short usb_pid;
+
+	usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff;
+	put_unaligned(usb_pid, &dev->idProduct);
+
+	return 0;
+}
+#endif
+
 #endif
 
 static struct mxc_serial_platdata mxc_serial_plat = {
diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c
index cbf7aa952a..0cc958a0a8 100644
--- a/board/toradex/colibri_imx6/colibri_imx6.c
+++ b/board/toradex/colibri_imx6/colibri_imx6.c
@@ -28,6 +28,7 @@
 #include <dm/platform_data/serial_mxc.h>
 #include <dm/platdata.h>
 #include <fsl_esdhc.h>
+#include <g_dnl.h>
 #include <i2c.h>
 #include <imx_thermal.h>
 #include <linux/errno.h>
@@ -1118,6 +1119,18 @@ void reset_cpu(ulong addr)
 {
 }
 
+#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
+int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
+{
+	unsigned short usb_pid;
+
+	usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff;
+	put_unaligned(usb_pid, &dev->idProduct);
+
+	return 0;
+}
+#endif
+
 #endif
 
 static struct mxc_serial_platdata mxc_serial_plat = {
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 8/8] apalis/colibri_imx6: enable SDP by default
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
                   ` (6 preceding siblings ...)
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 7/8] apalis/colibri_imx6: use independent USB PID for SPL Stefan Agner
@ 2017-08-16 18:00 ` Stefan Agner
  2017-08-23  8:43 ` [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefano Babic
  2017-09-01 16:48 ` Fabio Estevam
  9 siblings, 0 replies; 28+ messages in thread
From: Stefan Agner @ 2017-08-16 18:00 UTC (permalink / raw)
  To: u-boot

From: Stefan Agner <stefan.agner@toradex.com>

Enable Serial Download Protocol (SDP) in SPL and U-Boot. This is
useful to make use of imx_usb to download the complete U-Boot
(u-boot.img) after SPL has been downloaded. The U-Boot command
sdp allows to enumerate as SDP capable device again, e.g. to
download a Linux kernel and/or U-Boot script.

Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
Acked-by: Max Krummenacher <max.krummenacher@toradex.com>
---

Changes in v2: None

 configs/apalis_imx6_defconfig  | 4 ++++
 configs/colibri_imx6_defconfig | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/configs/apalis_imx6_defconfig b/configs/apalis_imx6_defconfig
index 468a1fcac7..8f87f1d34c 100644
--- a/configs/apalis_imx6_defconfig
+++ b/configs/apalis_imx6_defconfig
@@ -17,6 +17,9 @@ CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_USB_HOST_SUPPORT=y
+CONFIG_SPL_USB_GADGET_SUPPORT=y
+CONFIG_SPL_USB_SDP_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Apalis iMX6 # "
 CONFIG_CMD_BOOTZ=y
@@ -33,6 +36,7 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_SDP=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
diff --git a/configs/colibri_imx6_defconfig b/configs/colibri_imx6_defconfig
index edbd87fe19..beb74b5ae5 100644
--- a/configs/colibri_imx6_defconfig
+++ b/configs/colibri_imx6_defconfig
@@ -17,6 +17,9 @@ CONFIG_BOARD_EARLY_INIT_F=y
 CONFIG_SPL=y
 CONFIG_SPL_DMA_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
+CONFIG_SPL_USB_HOST_SUPPORT=y
+CONFIG_SPL_USB_GADGET_SUPPORT=y
+CONFIG_SPL_USB_SDP_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_SYS_PROMPT="Colibri iMX6 # "
 CONFIG_CMD_BOOTZ=y
@@ -33,6 +36,7 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_SDP=y
 CONFIG_CMD_USB_MASS_STORAGE=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
-- 
2.14.1

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver Stefan Agner
@ 2017-08-17 10:04   ` Łukasz Majewski
  2017-08-17 13:49   ` Stefano Babic
  1 sibling, 0 replies; 28+ messages in thread
From: Łukasz Majewski @ 2017-08-17 10:04 UTC (permalink / raw)
  To: u-boot

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 22409 bytes --]

On 08/16/2017 08:00 PM, Stefan Agner wrote:
> From: Stefan Agner <stefan.agner@toradex.com>
>
> Add SDP (Serial Downloader Protocol) implementation for U-Boot. The
> protocol is used in NXP SoC's boot ROM and allows to download program
> images. Beside that, it can also be used to read/write registers and
> download complete Device Configuration Data (DCD) sets. This basic
> implementation supports downloading images with the imx header format
> reading and writing registers.
>
> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>

Reviewed-by: Łukasz Majewski <lukma@denx.de>

> ---
>
> Changes in v2:
> - Changed function signature of sdp_init/sdp_handle to allow specifying
>   which USB controller should be used.
> - Use #defines for security mode
> - Improved types used in format strings
>
>  drivers/usb/gadget/Kconfig  |   7 +
>  drivers/usb/gadget/Makefile |   1 +
>  drivers/usb/gadget/f_sdp.c  | 721 ++++++++++++++++++++++++++++++++++++++++++++
>  include/sdp.h               |  16 +
>  4 files changed, 745 insertions(+)
>  create mode 100644 drivers/usb/gadget/f_sdp.c
>  create mode 100644 include/sdp.h
>
> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
> index 261ed128ac..225b66bc95 100644
> --- a/drivers/usb/gadget/Kconfig
> +++ b/drivers/usb/gadget/Kconfig
> @@ -103,6 +103,13 @@ config USB_GADGET_DOWNLOAD
>
>  if USB_GADGET_DOWNLOAD
>
> +config USB_FUNCTION_SDP
> +	bool "Enable USB SDP (Serial Download Protocol)"
> +	help
> +	  Enable Serial Download Protocol (SDP) device support in U-Boot. This
> +	  allows to download images into memory and execute (jump to) them
> +	  using the same protocol as implemented by the i.MX family's boot ROM.
> +
>  config G_DNL_MANUFACTURER
>  	string "Vendor name of USB device"
>
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index 5e316a7cff..6a007d1bcb 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
>  obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
>  obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
>  obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
> +obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
>  endif
>  endif
>  ifdef CONFIG_USB_ETHER
> diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
> new file mode 100644
> index 0000000000..9d82abcd69
> --- /dev/null
> +++ b/drivers/usb/gadget/f_sdp.c
> @@ -0,0 +1,721 @@
> +/*
> + * f_sdp.c -- USB HID Serial Download Protocol
> + *
> + * Copyright (C) 2017 Toradex
> + * Author: Stefan Agner <stefan.agner@toradex.com>
> + *
> + * This file implements the Serial Download Protocol (SDP) as specified in
> + * the i.MX 6 Reference Manual. The SDP is a USB HID based protocol and
> + * allows to download images directly to memory. The implementation
> + * works with the imx_loader (imx_usb) USB client software on host side.
> + *
> + * Not all commands are implemented, e.g. WRITE_REGISTER, DCD_WRITE and
> + * SKIP_DCD_HEADER are only stubs.
> + *
> + * Parts of the implementation are based on f_dfu and f_thor.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <errno.h>
> +#include <common.h>
> +#include <console.h>
> +#include <malloc.h>
> +
> +#include <linux/usb/ch9.h>
> +#include <linux/usb/gadget.h>
> +#include <linux/usb/composite.h>
> +
> +#include <asm/io.h>
> +#include <g_dnl.h>
> +#include <sdp.h>
> +#include <imximage.h>
> +
> +#define HID_REPORT_ID_MASK	0x000000ff
> +
> +/*
> + * HID class requests
> + */
> +#define HID_REQ_GET_REPORT		0x01
> +#define HID_REQ_GET_IDLE		0x02
> +#define HID_REQ_GET_PROTOCOL		0x03
> +#define HID_REQ_SET_REPORT		0x09
> +#define HID_REQ_SET_IDLE		0x0A
> +#define HID_REQ_SET_PROTOCOL		0x0B
> +
> +#define HID_USAGE_PAGE_LEN		76
> +
> +struct hid_report {
> +	u8 usage_page[HID_USAGE_PAGE_LEN];
> +} __packed;
> +
> +#define SDP_READ_REGISTER	0x0101
> +#define SDP_WRITE_REGISTER	0x0202
> +#define SDP_WRITE_FILE		0x0404
> +#define SDP_ERROR_STATUS	0x0505
> +#define SDP_DCD_WRITE		0x0a0a
> +#define SDP_JUMP_ADDRESS	0x0b0b
> +#define SDP_SKIP_DCD_HEADER	0x0c0c
> +
> +#define SDP_SECURITY_CLOSED		0x12343412
> +#define SDP_SECURITY_OPEN		0x56787856
> +
> +#define SDP_WRITE_FILE_COMPLETE		0x88888888
> +#define SDP_WRITE_REGISTER_COMPLETE	0x128A8A12
> +#define SDP_SKIP_DCD_HEADER_COMPLETE	0x900DD009
> +#define SDP_ERROR_IMXHEADER		0x000a0533
> +
> +#define SDP_COMMAND_LEN		16
> +
> +struct sdp_command {
> +	u16 cmd;
> +	u32 addr;
> +	u8 format;
> +	u32 cnt;
> +	u32 data;
> +	u8 rsvd;
> +} __packed;
> +
> +enum sdp_state {
> +	SDP_STATE_IDLE,
> +	SDP_STATE_RX_DCD_DATA,
> +	SDP_STATE_RX_FILE_DATA,
> +	SDP_STATE_TX_SEC_CONF,
> +	SDP_STATE_TX_SEC_CONF_BUSY,
> +	SDP_STATE_TX_REGISTER,
> +	SDP_STATE_TX_REGISTER_BUSY,
> +	SDP_STATE_TX_STATUS,
> +	SDP_STATE_TX_STATUS_BUSY,
> +	SDP_STATE_JUMP,
> +};
> +
> +struct f_sdp {
> +	struct usb_function		usb_function;
> +
> +	struct usb_descriptor_header	**function;
> +
> +	u8				altsetting;
> +	enum sdp_state			state;
> +	enum sdp_state			next_state;
> +	u32				dnl_address;
> +	u32				dnl_bytes_remaining;
> +	u32				jmp_address;
> +	bool				always_send_status;
> +	u32				error_status;
> +
> +	/* EP0 request */
> +	struct usb_request		*req;
> +
> +	/* EP1 IN */
> +	struct usb_ep			*in_ep;
> +	struct usb_request		*in_req;
> +
> +	bool				configuration_done;
> +};
> +
> +static struct f_sdp *sdp_func;
> +
> +static inline struct f_sdp *func_to_sdp(struct usb_function *f)
> +{
> +	return container_of(f, struct f_sdp, usb_function);
> +}
> +
> +static struct usb_interface_descriptor sdp_intf_runtime = {
> +	.bLength =		sizeof(sdp_intf_runtime),
> +	.bDescriptorType =	USB_DT_INTERFACE,
> +	.bAlternateSetting =	0,
> +	.bNumEndpoints =	1,
> +	.bInterfaceClass =	USB_CLASS_HID,
> +	.bInterfaceSubClass =	0,
> +	.bInterfaceProtocol =	0,
> +	/* .iInterface = DYNAMIC */
> +};
> +
> +/* HID configuration */
> +static struct usb_class_hid_descriptor sdp_hid_desc = {
> +	.bLength =		sizeof(sdp_hid_desc),
> +	.bDescriptorType =	USB_DT_CS_DEVICE,
> +
> +	.bcdCDC =		__constant_cpu_to_le16(0x0110),
> +	.bCountryCode =		0,
> +	.bNumDescriptors =	1,
> +
> +	.bDescriptorType0	= USB_DT_HID_REPORT,
> +	.wDescriptorLength0	= HID_USAGE_PAGE_LEN,
> +};
> +
> +static struct usb_endpoint_descriptor in_desc = {
> +	.bLength =		USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType =	USB_DT_ENDPOINT, /*USB_DT_CS_ENDPOINT*/
> +
> +	.bEndpointAddress =	1 | USB_DIR_IN,
> +	.bmAttributes =	USB_ENDPOINT_XFER_INT,
> +	.wMaxPacketSize =	64,
> +	.bInterval =		1,
> +};
> +
> +static struct usb_descriptor_header *sdp_runtime_descs[] = {
> +	(struct usb_descriptor_header *)&sdp_intf_runtime,
> +	(struct usb_descriptor_header *)&sdp_hid_desc,
> +	(struct usb_descriptor_header *)&in_desc,
> +	NULL,
> +};
> +
> +/* This is synchronized with what the SoC implementation reports */
> +static struct hid_report sdp_hid_report = {
> +	.usage_page = {
> +		0x06, 0x00, 0xff, /* Usage Page */
> +		0x09, 0x01, /* Usage (Pointer?) */
> +		0xa1, 0x01, /* Collection */
> +
> +		0x85, 0x01, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x08, /* Report Size */
> +		0x95, 0x10, /* Report Count */
> +		0x91, 0x02, /* Output Data */
> +
> +		0x85, 0x02, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x80, /* Report Size 128 */
> +		0x95, 0x40, /* Report Count */
> +		0x91, 0x02, /* Output Data */
> +
> +		0x85, 0x03, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x08, /* Report Size 8 */
> +		0x95, 0x04, /* Report Count */
> +		0x81, 0x02, /* Input Data */
> +
> +		0x85, 0x04, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x08, /* Report Size 8 */
> +		0x95, 0x40, /* Report Count */
> +		0x81, 0x02, /* Input Data */
> +		0xc0
> +	},
> +};
> +
> +static const char sdp_name[] = "Serial Downloader Protocol";
> +
> +/*
> + * static strings, in UTF-8
> + */
> +static struct usb_string strings_sdp_generic[] = {
> +	[0].s = sdp_name,
> +	{  }			/* end of list */
> +};
> +
> +static struct usb_gadget_strings stringtab_sdp_generic = {
> +	.language	= 0x0409,	/* en-us */
> +	.strings	= strings_sdp_generic,
> +};
> +
> +static struct usb_gadget_strings *sdp_generic_strings[] = {
> +	&stringtab_sdp_generic,
> +	NULL,
> +};
> +
> +static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct f_sdp *sdp = req->context;
> +	int status = req->status;
> +	u8 *data = req->buf;
> +	u8 report = data[0];
> +
> +	if (status != 0) {
> +		error("Status: %d", status);
> +		return;
> +	}
> +
> +	if (report != 1) {
> +		error("Unexpected report %d", report);
> +		return;
> +	}
> +
> +	struct sdp_command *cmd = req->buf + 1;
> +
> +	debug("%s: command: %04x, addr: %08x, cnt: %u\n",
> +	      __func__, be16_to_cpu(cmd->cmd),
> +	      be32_to_cpu(cmd->addr), be32_to_cpu(cmd->cnt));
> +
> +	switch (be16_to_cpu(cmd->cmd)) {
> +	case SDP_READ_REGISTER:
> +		sdp->always_send_status = false;
> +		sdp->error_status = 0x0;
> +
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->dnl_address = be32_to_cpu(cmd->addr);
> +		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
> +		sdp->next_state = SDP_STATE_TX_REGISTER;
> +		printf("Reading %d registers at 0x%08x... ",
> +		       sdp->dnl_bytes_remaining, sdp->dnl_address);
> +		break;
> +	case SDP_WRITE_FILE:
> +		sdp->always_send_status = true;
> +		sdp->error_status = SDP_WRITE_FILE_COMPLETE;
> +
> +		sdp->state = SDP_STATE_RX_FILE_DATA;
> +		sdp->dnl_address = be32_to_cpu(cmd->addr);
> +		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
> +		sdp->next_state = SDP_STATE_IDLE;
> +
> +		printf("Downloading file of size %d to 0x%08x... ",
> +		       sdp->dnl_bytes_remaining, sdp->dnl_address);
> +
> +		break;
> +	case SDP_ERROR_STATUS:
> +		sdp->always_send_status = true;
> +		sdp->error_status = 0;
> +
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->next_state = SDP_STATE_IDLE;
> +		break;
> +	case SDP_DCD_WRITE:
> +		sdp->always_send_status = true;
> +		sdp->error_status = SDP_WRITE_REGISTER_COMPLETE;
> +
> +		sdp->state = SDP_STATE_RX_DCD_DATA;
> +		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
> +		sdp->next_state = SDP_STATE_IDLE;
> +		break;
> +	case SDP_JUMP_ADDRESS:
> +		sdp->always_send_status = false;
> +		sdp->error_status = 0;
> +
> +		sdp->jmp_address = be32_to_cpu(cmd->addr);
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->next_state = SDP_STATE_JUMP;
> +		break;
> +	case SDP_SKIP_DCD_HEADER:
> +		sdp->always_send_status = true;
> +		sdp->error_status = SDP_SKIP_DCD_HEADER_COMPLETE;
> +
> +		/* Ignore command, DCD not supported anyway */
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->next_state = SDP_STATE_IDLE;
> +		break;
> +	default:
> +		error("Unknown command: %04x\n", be16_to_cpu(cmd->cmd));
> +	}
> +}
> +
> +static void sdp_rx_data_complete(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct f_sdp *sdp = req->context;
> +	int status = req->status;
> +	u8 *data = req->buf;
> +	u8 report = data[0];
> +	int datalen = req->length - 1;
> +
> +	if (status != 0) {
> +		error("Status: %d", status);
> +		return;
> +	}
> +
> +	if (report != 2) {
> +		error("Unexpected report %d", report);
> +		return;
> +	}
> +
> +	if (sdp->dnl_bytes_remaining < datalen) {
> +		/*
> +		 * Some USB stacks require to send a complete buffer as
> +		 * specified in the HID descriptor. This leads to longer
> +		 * transfers than the file length, no problem for us.
> +		 */
> +		sdp->dnl_bytes_remaining = 0;
> +	} else {
> +		sdp->dnl_bytes_remaining -= datalen;
> +	}
> +
> +	if (sdp->state == SDP_STATE_RX_FILE_DATA) {
> +		memcpy((void *)sdp->dnl_address, req->buf + 1, datalen);
> +		sdp->dnl_address += datalen;
> +	}
> +
> +	if (sdp->dnl_bytes_remaining)
> +		return;
> +
> +	printf("done\n");
> +
> +	switch (sdp->state) {
> +	case SDP_STATE_RX_FILE_DATA:
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		break;
> +	case SDP_STATE_RX_DCD_DATA:
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		break;
> +	default:
> +		error("Invalid state: %d", sdp->state);
> +	}
> +}
> +
> +static void sdp_tx_complete(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct f_sdp *sdp = req->context;
> +	int status = req->status;
> +
> +	if (status != 0) {
> +		error("Status: %d", status);
> +		return;
> +	}
> +
> +	switch (sdp->state) {
> +	case SDP_STATE_TX_SEC_CONF_BUSY:
> +		/* Not all commands require status report */
> +		if (sdp->always_send_status || sdp->error_status)
> +			sdp->state = SDP_STATE_TX_STATUS;
> +		else
> +			sdp->state = sdp->next_state;
> +
> +		break;
> +	case SDP_STATE_TX_STATUS_BUSY:
> +		sdp->state = sdp->next_state;
> +		break;
> +	case SDP_STATE_TX_REGISTER_BUSY:
> +		if (sdp->dnl_bytes_remaining)
> +			sdp->state = SDP_STATE_TX_REGISTER;
> +		else
> +			sdp->state = SDP_STATE_IDLE;
> +		break;
> +	default:
> +		error("Wrong State: %d", sdp->state);
> +		sdp->state = SDP_STATE_IDLE;
> +		break;
> +	}
> +	debug("%s complete --> %d, %d/%d\n", ep->name,
> +	      status, req->actual, req->length);
> +}
> +
> +static int sdp_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
> +{
> +	struct usb_gadget *gadget = f->config->cdev->gadget;
> +	struct usb_request *req = f->config->cdev->req;
> +	struct f_sdp *sdp = f->config->cdev->req->context;
> +	u16 len = le16_to_cpu(ctrl->wLength);
> +	u16 w_value = le16_to_cpu(ctrl->wValue);
> +	int value = 0;
> +	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
> +
> +	debug("w_value: 0x%04x len: 0x%04x\n", w_value, len);
> +	debug("req_type: 0x%02x ctrl->bRequest: 0x%02x sdp->state: %d\n",
> +	      req_type, ctrl->bRequest, sdp->state);
> +
> +	if (req_type == USB_TYPE_STANDARD) {
> +		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR) {
> +			/* Send HID report descriptor */
> +			value = min(len, (u16) sizeof(sdp_hid_report));
> +			memcpy(req->buf, &sdp_hid_report, value);
> +			sdp->configuration_done = true;
> +		}
> +	}
> +
> +	if (req_type == USB_TYPE_CLASS) {
> +		int report = w_value & HID_REPORT_ID_MASK;
> +
> +		/* HID (SDP) request */
> +		switch (ctrl->bRequest) {
> +		case HID_REQ_SET_REPORT:
> +			switch (report) {
> +			case 1:
> +				value = SDP_COMMAND_LEN + 1;
> +				req->complete = sdp_rx_command_complete;
> +				break;
> +			case 2:
> +				value = len;
> +				req->complete = sdp_rx_data_complete;
> +				break;
> +			}
> +		}
> +	}
> +
> +	if (value >= 0) {
> +		req->length = value;
> +		req->zero = value < len;
> +		value = usb_ep_queue(gadget->ep0, req, 0);
> +		if (value < 0) {
> +			debug("ep_queue --> %d\n", value);
> +			req->status = 0;
> +		}
> +	}
> +
> +	return value;
> +}
> +
> +static int sdp_bind(struct usb_configuration *c, struct usb_function *f)
> +{
> +	struct usb_gadget *gadget = c->cdev->gadget;
> +	struct usb_composite_dev *cdev = c->cdev;
> +	struct f_sdp *sdp = func_to_sdp(f);
> +	int rv = 0, id;
> +
> +	id = usb_interface_id(c, f);
> +	if (id < 0)
> +		return id;
> +	sdp_intf_runtime.bInterfaceNumber = id;
> +
> +	struct usb_ep *ep;
> +
> +	/* allocate instance-specific endpoints */
> +	ep = usb_ep_autoconfig(gadget, &in_desc);
> +	if (!ep) {
> +		rv = -ENODEV;
> +		goto error;
> +	}
> +
> +	sdp->in_ep = ep; /* Store IN EP for enabling @ setup */
> +
> +	cdev->req->context = sdp;
> +
> +error:
> +	return rv;
> +}
> +
> +static void sdp_unbind(struct usb_configuration *c, struct usb_function *f)
> +{
> +	free(sdp_func);
> +	sdp_func = NULL;
> +}
> +
> +static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
> +{
> +	struct usb_request *req;
> +
> +	req = usb_ep_alloc_request(ep, 0);
> +	if (!req)
> +		return req;
> +
> +	req->length = length;
> +	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
> +	if (!req->buf) {
> +		usb_ep_free_request(ep, req);
> +		req = NULL;
> +	}
> +
> +	return req;
> +}
> +
> +
> +static struct usb_request *sdp_start_ep(struct usb_ep *ep)
> +{
> +	struct usb_request *req;
> +
> +	req = alloc_ep_req(ep, 64);
> +	debug("%s: ep:%p req:%p\n", __func__, ep, req);
> +
> +	if (!req)
> +		return NULL;
> +
> +	memset(req->buf, 0, req->length);
> +	req->complete = sdp_tx_complete;
> +
> +	return req;
> +}
> +static int sdp_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
> +{
> +	struct f_sdp *sdp = func_to_sdp(f);
> +	struct usb_composite_dev *cdev = f->config->cdev;
> +	int result;
> +
> +	debug("%s: intf: %d alt: %d\n", __func__, intf, alt);
> +
> +	result = usb_ep_enable(sdp->in_ep, &in_desc);
> +	if (result)
> +		return result;
> +	sdp->in_req = sdp_start_ep(sdp->in_ep);
> +	sdp->in_req->context = sdp;
> +
> +	sdp->in_ep->driver_data = cdev; /* claim */
> +
> +	sdp->altsetting = alt;
> +	sdp->state = SDP_STATE_IDLE;
> +
> +	return 0;
> +}
> +
> +static int sdp_get_alt(struct usb_function *f, unsigned intf)
> +{
> +	struct f_sdp *sdp = func_to_sdp(f);
> +
> +	return sdp->altsetting;
> +}
> +
> +static void sdp_disable(struct usb_function *f)
> +{
> +	struct f_sdp *sdp = func_to_sdp(f);
> +
> +	usb_ep_disable(sdp->in_ep);
> +
> +	if (sdp->in_req) {
> +		free(sdp->in_req);
> +		sdp->in_req = NULL;
> +	}
> +}
> +
> +static int sdp_bind_config(struct usb_configuration *c)
> +{
> +	int status;
> +
> +	if (!sdp_func) {
> +		sdp_func = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*sdp_func));
> +		if (!sdp_func)
> +			return -ENOMEM;
> +	}
> +
> +	memset(sdp_func, 0, sizeof(*sdp_func));
> +
> +	sdp_func->usb_function.name = "sdp";
> +	sdp_func->usb_function.hs_descriptors = sdp_runtime_descs;
> +	sdp_func->usb_function.descriptors = sdp_runtime_descs;
> +	sdp_func->usb_function.bind = sdp_bind;
> +	sdp_func->usb_function.unbind = sdp_unbind;
> +	sdp_func->usb_function.set_alt = sdp_set_alt;
> +	sdp_func->usb_function.get_alt = sdp_get_alt;
> +	sdp_func->usb_function.disable = sdp_disable;
> +	sdp_func->usb_function.strings = sdp_generic_strings;
> +	sdp_func->usb_function.setup = sdp_setup;
> +
> +	status = usb_add_function(c, &sdp_func->usb_function);
> +
> +	return status;
> +}
> +
> +int sdp_init(int controller_index)
> +{
> +	printf("SDP: initialize...\n");
> +	while (!sdp_func->configuration_done) {
> +		if (ctrlc()) {
> +			puts("\rCTRL+C - Operation aborted.\n");
> +			return 1;
> +		}
> +		usb_gadget_handle_interrupts(controller_index);
> +	}
> +
> +	return 0;
> +}
> +
> +static u32 sdp_jump_imxheader(void *address)
> +{
> +	flash_header_v2_t *headerv2 = address;
> +	ulong (*entry)(void);
> +
> +	if (headerv2->header.tag != IVT_HEADER_TAG) {
> +		printf("Header Tag is not an IMX image\n");
> +		return SDP_ERROR_IMXHEADER;
> +	}
> +
> +	printf("Jumping to 0x%08x\n", headerv2->entry);
> +	entry = (void *)headerv2->entry;
> +	entry();
> +
> +	/* The image probably never returns hence we won't reach that point */
> +	return 0;
> +}
> +
> +static void sdp_handle_in_ep(void)
> +{
> +	u8 *data = sdp_func->in_req->buf;
> +	u32 status;
> +	int datalen;
> +
> +	switch (sdp_func->state) {
> +	case SDP_STATE_TX_SEC_CONF:
> +		debug("Report 3: HAB security\n");
> +		data[0] = 3;
> +
> +		status = SDP_SECURITY_OPEN;
> +		memcpy(&data[1], &status, 4);
> +		sdp_func->in_req->length = 5;
> +		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
> +		sdp_func->state = SDP_STATE_TX_SEC_CONF_BUSY;
> +		break;
> +
> +	case SDP_STATE_TX_STATUS:
> +		debug("Report 4: Status\n");
> +		data[0] = 4;
> +
> +		memcpy(&data[1], &sdp_func->error_status, 4);
> +		sdp_func->in_req->length = 65;
> +		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
> +		sdp_func->state = SDP_STATE_TX_STATUS_BUSY;
> +		break;
> +	case SDP_STATE_TX_REGISTER:
> +		debug("Report 4: Register Values\n");
> +		data[0] = 4;
> +
> +		datalen = sdp_func->dnl_bytes_remaining;
> +
> +		if (datalen > 64)
> +			datalen = 64;
> +
> +		memcpy(&data[1], (void *)sdp_func->dnl_address, datalen);
> +		sdp_func->in_req->length = 65;
> +
> +		sdp_func->dnl_bytes_remaining -= datalen;
> +		sdp_func->dnl_address += datalen;
> +
> +		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
> +		sdp_func->state = SDP_STATE_TX_REGISTER_BUSY;
> +		break;
> +	case SDP_STATE_JUMP:
> +		printf("Checking imxheader at 0x%08x\n", f_sdp->jmp_address);
> +		status = sdp_jump_imxheader((void *)f_sdp->jmp_address);
> +
> +		sdp_func->next_state = SDP_STATE_IDLE;
> +		sdp_func->error_status = status;
> +
> +		/* Only send Report 4 if there was an error */
> +		if (status)
> +			sdp_func->state = SDP_STATE_TX_STATUS;
> +		else
> +			sdp_func->state = SDP_STATE_IDLE;
> +		break;
> +	default:
> +		break;
> +	};
> +}
> +
> +void sdp_handle(int controller_index)
> +{
> +	printf("SDP: handle requests...\n");
> +	while (1) {
> +		if (ctrlc()) {
> +			puts("\rCTRL+C - Operation aborted.\n");
> +			return;
> +		}
> +
> +		usb_gadget_handle_interrupts(controller_index);
> +
> +		sdp_handle_in_ep();
> +	}
> +}
> +
> +int sdp_add(struct usb_configuration *c)
> +{
> +	int id;
> +
> +	id = usb_string_id(c->cdev);
> +	if (id < 0)
> +		return id;
> +	strings_sdp_generic[0].id = id;
> +	sdp_intf_runtime.iInterface = id;
> +
> +	debug("%s: cdev: %p gadget: %p gadget->ep0: %p\n", __func__,
> +	      c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
> +
> +	return sdp_bind_config(c);
> +}
> +
> +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_sdp, sdp_add);
> diff --git a/include/sdp.h b/include/sdp.h
> new file mode 100644
> index 0000000000..f476bab8f1
> --- /dev/null
> +++ b/include/sdp.h
> @@ -0,0 +1,16 @@
> +/*
> + * sdp.h - Serial Download Protocol
> + *
> + * Copyright (C) 2017 Toradex
> + * Author: Stefan Agner <stefan.agner@toradex.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __SDP_H_
> +#define __SDP_H_
> +
> +int sdp_init(int controller_index);
> +void sdp_handle(int controller_index);
> +
> +#endif /* __SDP_H_ */
>



-- 
Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 5/8] spl: add serial download protocol (SDP) support
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 5/8] spl: add serial download protocol (SDP) support Stefan Agner
@ 2017-08-17 10:10   ` Łukasz Majewski
  0 siblings, 0 replies; 28+ messages in thread
From: Łukasz Majewski @ 2017-08-17 10:10 UTC (permalink / raw)
  To: u-boot

On 08/16/2017 08:00 PM, Stefan Agner wrote:
> From: Stefan Agner <stefan.agner@toradex.com>
>
> Add USB serial download protocol support to SPL. If the SoC started
> in recovery mode the SPL will immediately switch to SDP and wait for
> further downloads/commands from the host side.

Reviewed-by: Łukasz Majewski <lukma@denx.de>

>
> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
> Reviewed-by: Stefano Babic <sbabic@denx.de>
> ---
>
> Changes in v2:
> - Changed function signature of sdp_init/sdp_handle
> - Use BOOT_DEVICE_BOARD
>
>  common/spl/Kconfig          |  6 ++++++
>  common/spl/Makefile         |  1 +
>  common/spl/spl_sdp.c        | 37 +++++++++++++++++++++++++++++++++++++
>  drivers/usb/gadget/Makefile |  1 +
>  4 files changed, 45 insertions(+)
>  create mode 100644 common/spl/spl_sdp.c
>
> diff --git a/common/spl/Kconfig b/common/spl/Kconfig
> index 5176857506..b3436b3c28 100644
> --- a/common/spl/Kconfig
> +++ b/common/spl/Kconfig
> @@ -668,6 +668,12 @@ config SPL_DFU_RAM
>
>  endchoice
>
> +config SPL_USB_SDP_SUPPORT
> +	bool "Support SDP (Serial Download Protocol)"
> +	help
> +	  Enable Serial Download Protocol (SDP) device support in SPL. This
> +	  allows to download images into memory and execute (jump to) them
> +	  using the same protocol as implemented by the i.MX family's boot ROM.
>  endif
>
>  config SPL_WATCHDOG_SUPPORT
> diff --git a/common/spl/Makefile b/common/spl/Makefile
> index 112b3e6022..6255d4f73c 100644
> --- a/common/spl/Makefile
> +++ b/common/spl/Makefile
> @@ -30,4 +30,5 @@ obj-$(CONFIG_$(SPL_TPL_)SATA_SUPPORT) += spl_sata.o
>  obj-$(CONFIG_$(SPL_TPL_)DFU_SUPPORT) += spl_dfu.o
>  obj-$(CONFIG_$(SPL_TPL_)SPI_LOAD) += spl_spi.o
>  obj-$(CONFIG_$(SPL_TPL_)RAM_SUPPORT) += spl_ram.o
> +obj-$(CONFIG_$(SPL_TPL_)USB_SDP_SUPPORT) += spl_sdp.o
>  endif
> diff --git a/common/spl/spl_sdp.c b/common/spl/spl_sdp.c
> new file mode 100644
> index 0000000000..350bcdb056
> --- /dev/null
> +++ b/common/spl/spl_sdp.c
> @@ -0,0 +1,37 @@
> +/*
> + * (C) Copyright 2016 Toradex
> + * Author: Stefan Agner <stefan.agner@toradex.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <spl.h>
> +#include <usb.h>
> +#include <g_dnl.h>
> +#include <sdp.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +static int spl_sdp_load_image(struct spl_image_info *spl_image,
> +			      struct spl_boot_device *bootdev)
> +{
> +	int ret;
> +	const int controller_index = 0;
> +
> +	g_dnl_clear_detach();
> +	g_dnl_register("usb_dnl_sdp");
> +
> +	ret = sdp_init(controller_index);
> +	if (ret) {
> +		error("SDP init failed: %d", ret);
> +		return -ENODEV;
> +	}
> +
> +	/* This command typically does not return but jumps to an image */
> +	sdp_handle(controller_index);
> +	error("SDP ended");
> +
> +	return -EINVAL;
> +}
> +SPL_LOAD_IMAGE_METHOD("USB SDP", 0, BOOT_DEVICE_BOARD, spl_sdp_load_image);
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index 6a007d1bcb..7258099c1c 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -11,6 +11,7 @@ obj-$(CONFIG_USB_ETHER) += epautoconf.o config.o usbstring.o
>  ifdef CONFIG_SPL_BUILD
>  obj-$(CONFIG_SPL_USB_GADGET_SUPPORT) += g_dnl.o
>  obj-$(CONFIG_SPL_DFU_SUPPORT) += f_dfu.o
> +obj-$(CONFIG_SPL_USB_SDP_SUPPORT) += f_sdp.o
>  endif
>
>  # new USB gadget layer dependencies
>


-- 
Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 6/8] doc: add Serial Download Protocol documentation
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 6/8] doc: add Serial Download Protocol documentation Stefan Agner
@ 2017-08-17 10:21   ` Łukasz Majewski
  0 siblings, 0 replies; 28+ messages in thread
From: Łukasz Majewski @ 2017-08-17 10:21 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

> From: Stefan Agner <stefan.agner@toradex.com>
>
> Document the U-Boot Serial Download Protocol implementation and
> some typical use cases.

Thanks for providing the description :-)

Reviewed-by: Łukasz Majewski <lukma@denx.de>

>
> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
> ---
> This ended up to be almost more a imx_usb documentation. But there
> is really not much to document from a U-Boot side since actual usage
> heavily depends on host side tooling...
>
> This assumes that the necessary changes will get merged upstream:
> https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored
>
>
> Changes in v2: None
>
>  doc/README.sdp | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 100 insertions(+)
>  create mode 100644 doc/README.sdp
>
> diff --git a/doc/README.sdp b/doc/README.sdp
> new file mode 100644
> index 0000000000..9b438c0746
> --- /dev/null
> +++ b/doc/README.sdp
> @@ -0,0 +1,100 @@
> +-------------
> +SDP in U-Boot
> +-------------
> +
> +SDP stands for serial download protocol. It is the protocol used in NXP's
> +i.MX SoCs ROM Serial Downloader and provides means to download a program
> +image to the chip over USB and UART serial connection.
> +
> +The implementation in U-Boot uses the USB Downloader Gadget (g_dnl) to
> +provide a SDP implementation over USB. This allows to download program
> +images to the target in SPL/U-Boot using the same protocol/tooling the
> +SoC's recovery mechanism is using.
> +
> +The SDP protocol over USB is a USB HID class protocol. USB HID class
> +protocols allow to access a USB device without OS specific drivers. The
> +U-Boot implementation has primarly been tested using the open source
> +imx_loader utility (https://github.com/toradex/imx_loader).
> +
> +The host side utilities are typically capable to interpret the i.MX
> +specific image header (see doc/README.imximage). There are extensions
> +for imx_loader's imx_usb utility which allow to interpret the U-Boot
> +specific legacy image format (see mkimage(1)). Also the U-Boot side
> +support beside the i.MX specific header the U-Boot legacy header.
> +
> +Usage
> +-----
> +
> +This implementation can be started in U-Boot using the sdp command
> +(CONFIG_CMD_USB_SDP) or in SPL if Serial Downloader boot mode has been
> +detected (CONFIG_SPL_USB_SDP_SUPPORT).
> +
> +A typical use case is downloading full U-Boot after SPL has been
> +downloaded through the boot ROM's Serial Downloader. Using boot mode
> +detection the SPL will run the SDP implementation automatically in
> +this case:
> +
> +  # imx_usb SPL
> +
> +Targets Serial Console:
> +
> +  Trying to boot from USB SDP
> +  SDP: initialize...
> +  SDP: handle requests...
> +
> +At this point the SPL reenumerated as a new HID device and emulating
> +the boot ROM's SDP protocol. The USB VID/PID will depend on standard
> +U-Boot configurations CONFIG_G_DNL_(VENDOR|PRODUCT)_NUM. Make sure
> +imx_usb is aware of the USB VID/PID for your device by adding a
> +configuration entry in imx_usb.conf:
> +
> +  0x1b67:0x4fff, mx6_usb_sdp_spl.conf
> +
> +And the device specific configuration file mx6_usb_sdp_spl.conf:
> +
> +  mx6_spl_sdp
> +  hid,uboot_header,1024,0x910000,0x10000000,1G,0x00900000,0x40000
> +
> +This allows to download the regular U-Boot with legacy image headers
> +(u-boot.img) using a second invocation of imx_usb:
> +
> +  # imx_usb u-boot.img
> +
> +Furthermore, when U-Boot is running the sdp command can be used to
> +download and run scripts:
> +
> +  # imx_usb script.scr
> +
> +imx_usb configuration files can be also used to download multiple
> +files and of arbitrary types, e.g.
> +
> +  mx6_usb_sdp_uboot
> +  hid,1024,0x10000000,1G,0x00907000,0x31000
> +  full.itb:load 0x12100000
> +  boot.scr:load 0x12000000,jump 0x12000000
> +
> +There is also a batch mode which allows imx_usb to handle multiple
> +consecutive reenumerations by adding multiple VID/PID specifications
> +in imx_usb.conf:
> +
> +  0x15a2:0x0061, mx6_usb_rom.conf, 0x1b67:0x4fff, mx6_usb_sdp_spl.conf
> +
> +In this mode the file to download (imx_usb job) needs to be specified
> +in the configuration files.
> +
> +mx6_usb_rom.conf:
> +
> +  mx6_qsb
> +  hid,1024,0x910000,0x10000000,1G,0x00900000,0x40000
> +  SPL:jump header2
> +
> +mx6_usb_sdp_spl.conf:
> +
> +  mx6_spl_sdp
> +  hid,uboot_header,1024,0x10000000,1G,0x00907000,0x31000
> +  u-boot.img:jump header2
> +
> +With that SPL and U-Boot can be downloaded with a single invocation
> +of imx_usb without arguments:
> +
> +  # imx_usb
>


-- 
Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 7/8] apalis/colibri_imx6: use independent USB PID for SPL
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 7/8] apalis/colibri_imx6: use independent USB PID for SPL Stefan Agner
@ 2017-08-17 10:23   ` Łukasz Majewski
  0 siblings, 0 replies; 28+ messages in thread
From: Łukasz Majewski @ 2017-08-17 10:23 UTC (permalink / raw)
  To: u-boot

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="windows-1254", Size: 2654 bytes --]

On 08/16/2017 08:00 PM, Stefan Agner wrote:
> From: Stefan Agner <stefan.agner@toradex.com>
>
> Use a completely independent USB Product ID for SPL. This allows
> to differentiate a SDP running in SPL and SDP running in a U-Boot
> which could not read the config block successfully.

Reviewed-by: Łukasz Majewski <lukma@denx.de>

>
> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
> Acked-by: Max Krummenacher <max.krummenacher@toradex.com>
> ---
>
> Changes in v2: None
>
>  board/toradex/apalis_imx6/apalis_imx6.c   | 13 +++++++++++++
>  board/toradex/colibri_imx6/colibri_imx6.c | 13 +++++++++++++
>  2 files changed, 26 insertions(+)
>
> diff --git a/board/toradex/apalis_imx6/apalis_imx6.c b/board/toradex/apalis_imx6/apalis_imx6.c
> index 8e5613cb12..edaca5d346 100644
> --- a/board/toradex/apalis_imx6/apalis_imx6.c
> +++ b/board/toradex/apalis_imx6/apalis_imx6.c
> @@ -28,6 +28,7 @@
>  #include <dm/platform_data/serial_mxc.h>
>  #include <dm/platdata.h>
>  #include <fsl_esdhc.h>
> +#include <g_dnl.h>
>  #include <i2c.h>
>  #include <imx_thermal.h>
>  #include <linux/errno.h>
> @@ -1233,6 +1234,18 @@ void reset_cpu(ulong addr)
>  {
>  }
>
> +#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
> +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
> +{
> +	unsigned short usb_pid;
> +
> +	usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff;
> +	put_unaligned(usb_pid, &dev->idProduct);
> +
> +	return 0;
> +}
> +#endif
> +
>  #endif
>
>  static struct mxc_serial_platdata mxc_serial_plat = {
> diff --git a/board/toradex/colibri_imx6/colibri_imx6.c b/board/toradex/colibri_imx6/colibri_imx6.c
> index cbf7aa952a..0cc958a0a8 100644
> --- a/board/toradex/colibri_imx6/colibri_imx6.c
> +++ b/board/toradex/colibri_imx6/colibri_imx6.c
> @@ -28,6 +28,7 @@
>  #include <dm/platform_data/serial_mxc.h>
>  #include <dm/platdata.h>
>  #include <fsl_esdhc.h>
> +#include <g_dnl.h>
>  #include <i2c.h>
>  #include <imx_thermal.h>
>  #include <linux/errno.h>
> @@ -1118,6 +1119,18 @@ void reset_cpu(ulong addr)
>  {
>  }
>
> +#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
> +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
> +{
> +	unsigned short usb_pid;
> +
> +	usb_pid = TORADEX_USB_PRODUCT_NUM_OFFSET + 0xfff;
> +	put_unaligned(usb_pid, &dev->idProduct);
> +
> +	return 0;
> +}
> +#endif
> +
>  #endif
>
>  static struct mxc_serial_platdata mxc_serial_plat = {
>


-- 
Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver Stefan Agner
  2017-08-17 10:04   ` Łukasz Majewski
@ 2017-08-17 13:49   ` Stefano Babic
  2017-08-17 13:54     ` Marek Vasut
  1 sibling, 1 reply; 28+ messages in thread
From: Stefano Babic @ 2017-08-17 13:49 UTC (permalink / raw)
  To: u-boot

On 16/08/2017 20:00, Stefan Agner wrote:
> From: Stefan Agner <stefan.agner@toradex.com>
> 
> Add SDP (Serial Downloader Protocol) implementation for U-Boot. The
> protocol is used in NXP SoC's boot ROM and allows to download program
> images. Beside that, it can also be used to read/write registers and
> download complete Device Configuration Data (DCD) sets. This basic
> implementation supports downloading images with the imx header format
> reading and writing registers.
> 
> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>

Reviewed by : Stefano Babic ysbabic at denx.de>

Marek, this is related to USB. Anyway, I will prefer that the whole
patchset will be merged at once, and not split between u-boot-imx and
u-boot-usb. If you agree (and after the patchset is ok for you, of
course !), I will propose that I will merge the whole patchset into
u-boot-imx to avoid breakages.

Best regards,
Stefano

> ---
> 
> Changes in v2:
> - Changed function signature of sdp_init/sdp_handle to allow specifying
>   which USB controller should be used.
> - Use #defines for security mode
> - Improved types used in format strings
> 
>  drivers/usb/gadget/Kconfig  |   7 +
>  drivers/usb/gadget/Makefile |   1 +
>  drivers/usb/gadget/f_sdp.c  | 721 ++++++++++++++++++++++++++++++++++++++++++++
>  include/sdp.h               |  16 +
>  4 files changed, 745 insertions(+)
>  create mode 100644 drivers/usb/gadget/f_sdp.c
>  create mode 100644 include/sdp.h
> 
> diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
> index 261ed128ac..225b66bc95 100644
> --- a/drivers/usb/gadget/Kconfig
> +++ b/drivers/usb/gadget/Kconfig
> @@ -103,6 +103,13 @@ config USB_GADGET_DOWNLOAD
>  
>  if USB_GADGET_DOWNLOAD
>  
> +config USB_FUNCTION_SDP
> +	bool "Enable USB SDP (Serial Download Protocol)"
> +	help
> +	  Enable Serial Download Protocol (SDP) device support in U-Boot. This
> +	  allows to download images into memory and execute (jump to) them
> +	  using the same protocol as implemented by the i.MX family's boot ROM.
> +
>  config G_DNL_MANUFACTURER
>  	string "Vendor name of USB device"
>  
> diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
> index 5e316a7cff..6a007d1bcb 100644
> --- a/drivers/usb/gadget/Makefile
> +++ b/drivers/usb/gadget/Makefile
> @@ -28,6 +28,7 @@ obj-$(CONFIG_USB_FUNCTION_THOR) += f_thor.o
>  obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
>  obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
>  obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
> +obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
>  endif
>  endif
>  ifdef CONFIG_USB_ETHER
> diff --git a/drivers/usb/gadget/f_sdp.c b/drivers/usb/gadget/f_sdp.c
> new file mode 100644
> index 0000000000..9d82abcd69
> --- /dev/null
> +++ b/drivers/usb/gadget/f_sdp.c
> @@ -0,0 +1,721 @@
> +/*
> + * f_sdp.c -- USB HID Serial Download Protocol
> + *
> + * Copyright (C) 2017 Toradex
> + * Author: Stefan Agner <stefan.agner@toradex.com>
> + *
> + * This file implements the Serial Download Protocol (SDP) as specified in
> + * the i.MX 6 Reference Manual. The SDP is a USB HID based protocol and
> + * allows to download images directly to memory. The implementation
> + * works with the imx_loader (imx_usb) USB client software on host side.
> + *
> + * Not all commands are implemented, e.g. WRITE_REGISTER, DCD_WRITE and
> + * SKIP_DCD_HEADER are only stubs.
> + *
> + * Parts of the implementation are based on f_dfu and f_thor.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <errno.h>
> +#include <common.h>
> +#include <console.h>
> +#include <malloc.h>
> +
> +#include <linux/usb/ch9.h>
> +#include <linux/usb/gadget.h>
> +#include <linux/usb/composite.h>
> +
> +#include <asm/io.h>
> +#include <g_dnl.h>
> +#include <sdp.h>
> +#include <imximage.h>
> +
> +#define HID_REPORT_ID_MASK	0x000000ff
> +
> +/*
> + * HID class requests
> + */
> +#define HID_REQ_GET_REPORT		0x01
> +#define HID_REQ_GET_IDLE		0x02
> +#define HID_REQ_GET_PROTOCOL		0x03
> +#define HID_REQ_SET_REPORT		0x09
> +#define HID_REQ_SET_IDLE		0x0A
> +#define HID_REQ_SET_PROTOCOL		0x0B
> +
> +#define HID_USAGE_PAGE_LEN		76
> +
> +struct hid_report {
> +	u8 usage_page[HID_USAGE_PAGE_LEN];
> +} __packed;
> +
> +#define SDP_READ_REGISTER	0x0101
> +#define SDP_WRITE_REGISTER	0x0202
> +#define SDP_WRITE_FILE		0x0404
> +#define SDP_ERROR_STATUS	0x0505
> +#define SDP_DCD_WRITE		0x0a0a
> +#define SDP_JUMP_ADDRESS	0x0b0b
> +#define SDP_SKIP_DCD_HEADER	0x0c0c
> +
> +#define SDP_SECURITY_CLOSED		0x12343412
> +#define SDP_SECURITY_OPEN		0x56787856
> +
> +#define SDP_WRITE_FILE_COMPLETE		0x88888888
> +#define SDP_WRITE_REGISTER_COMPLETE	0x128A8A12
> +#define SDP_SKIP_DCD_HEADER_COMPLETE	0x900DD009
> +#define SDP_ERROR_IMXHEADER		0x000a0533
> +
> +#define SDP_COMMAND_LEN		16
> +
> +struct sdp_command {
> +	u16 cmd;
> +	u32 addr;
> +	u8 format;
> +	u32 cnt;
> +	u32 data;
> +	u8 rsvd;
> +} __packed;
> +
> +enum sdp_state {
> +	SDP_STATE_IDLE,
> +	SDP_STATE_RX_DCD_DATA,
> +	SDP_STATE_RX_FILE_DATA,
> +	SDP_STATE_TX_SEC_CONF,
> +	SDP_STATE_TX_SEC_CONF_BUSY,
> +	SDP_STATE_TX_REGISTER,
> +	SDP_STATE_TX_REGISTER_BUSY,
> +	SDP_STATE_TX_STATUS,
> +	SDP_STATE_TX_STATUS_BUSY,
> +	SDP_STATE_JUMP,
> +};
> +
> +struct f_sdp {
> +	struct usb_function		usb_function;
> +
> +	struct usb_descriptor_header	**function;
> +
> +	u8				altsetting;
> +	enum sdp_state			state;
> +	enum sdp_state			next_state;
> +	u32				dnl_address;
> +	u32				dnl_bytes_remaining;
> +	u32				jmp_address;
> +	bool				always_send_status;
> +	u32				error_status;
> +
> +	/* EP0 request */
> +	struct usb_request		*req;
> +
> +	/* EP1 IN */
> +	struct usb_ep			*in_ep;
> +	struct usb_request		*in_req;
> +
> +	bool				configuration_done;
> +};
> +
> +static struct f_sdp *sdp_func;
> +
> +static inline struct f_sdp *func_to_sdp(struct usb_function *f)
> +{
> +	return container_of(f, struct f_sdp, usb_function);
> +}
> +
> +static struct usb_interface_descriptor sdp_intf_runtime = {
> +	.bLength =		sizeof(sdp_intf_runtime),
> +	.bDescriptorType =	USB_DT_INTERFACE,
> +	.bAlternateSetting =	0,
> +	.bNumEndpoints =	1,
> +	.bInterfaceClass =	USB_CLASS_HID,
> +	.bInterfaceSubClass =	0,
> +	.bInterfaceProtocol =	0,
> +	/* .iInterface = DYNAMIC */
> +};
> +
> +/* HID configuration */
> +static struct usb_class_hid_descriptor sdp_hid_desc = {
> +	.bLength =		sizeof(sdp_hid_desc),
> +	.bDescriptorType =	USB_DT_CS_DEVICE,
> +
> +	.bcdCDC =		__constant_cpu_to_le16(0x0110),
> +	.bCountryCode =		0,
> +	.bNumDescriptors =	1,
> +
> +	.bDescriptorType0	= USB_DT_HID_REPORT,
> +	.wDescriptorLength0	= HID_USAGE_PAGE_LEN,
> +};
> +
> +static struct usb_endpoint_descriptor in_desc = {
> +	.bLength =		USB_DT_ENDPOINT_SIZE,
> +	.bDescriptorType =	USB_DT_ENDPOINT, /*USB_DT_CS_ENDPOINT*/
> +
> +	.bEndpointAddress =	1 | USB_DIR_IN,
> +	.bmAttributes =	USB_ENDPOINT_XFER_INT,
> +	.wMaxPacketSize =	64,
> +	.bInterval =		1,
> +};
> +
> +static struct usb_descriptor_header *sdp_runtime_descs[] = {
> +	(struct usb_descriptor_header *)&sdp_intf_runtime,
> +	(struct usb_descriptor_header *)&sdp_hid_desc,
> +	(struct usb_descriptor_header *)&in_desc,
> +	NULL,
> +};
> +
> +/* This is synchronized with what the SoC implementation reports */
> +static struct hid_report sdp_hid_report = {
> +	.usage_page = {
> +		0x06, 0x00, 0xff, /* Usage Page */
> +		0x09, 0x01, /* Usage (Pointer?) */
> +		0xa1, 0x01, /* Collection */
> +
> +		0x85, 0x01, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x08, /* Report Size */
> +		0x95, 0x10, /* Report Count */
> +		0x91, 0x02, /* Output Data */
> +
> +		0x85, 0x02, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x80, /* Report Size 128 */
> +		0x95, 0x40, /* Report Count */
> +		0x91, 0x02, /* Output Data */
> +
> +		0x85, 0x03, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x08, /* Report Size 8 */
> +		0x95, 0x04, /* Report Count */
> +		0x81, 0x02, /* Input Data */
> +
> +		0x85, 0x04, /* Report ID */
> +		0x19, 0x01, /* Usage Minimum */
> +		0x29, 0x01, /* Usage Maximum */
> +		0x15, 0x00, /* Local Minimum */
> +		0x26, 0xFF, 0x00, /* Local Maximum? */
> +		0x75, 0x08, /* Report Size 8 */
> +		0x95, 0x40, /* Report Count */
> +		0x81, 0x02, /* Input Data */
> +		0xc0
> +	},
> +};
> +
> +static const char sdp_name[] = "Serial Downloader Protocol";
> +
> +/*
> + * static strings, in UTF-8
> + */
> +static struct usb_string strings_sdp_generic[] = {
> +	[0].s = sdp_name,
> +	{  }			/* end of list */
> +};
> +
> +static struct usb_gadget_strings stringtab_sdp_generic = {
> +	.language	= 0x0409,	/* en-us */
> +	.strings	= strings_sdp_generic,
> +};
> +
> +static struct usb_gadget_strings *sdp_generic_strings[] = {
> +	&stringtab_sdp_generic,
> +	NULL,
> +};
> +
> +static void sdp_rx_command_complete(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct f_sdp *sdp = req->context;
> +	int status = req->status;
> +	u8 *data = req->buf;
> +	u8 report = data[0];
> +
> +	if (status != 0) {
> +		error("Status: %d", status);
> +		return;
> +	}
> +
> +	if (report != 1) {
> +		error("Unexpected report %d", report);
> +		return;
> +	}
> +
> +	struct sdp_command *cmd = req->buf + 1;
> +
> +	debug("%s: command: %04x, addr: %08x, cnt: %u\n",
> +	      __func__, be16_to_cpu(cmd->cmd),
> +	      be32_to_cpu(cmd->addr), be32_to_cpu(cmd->cnt));
> +
> +	switch (be16_to_cpu(cmd->cmd)) {
> +	case SDP_READ_REGISTER:
> +		sdp->always_send_status = false;
> +		sdp->error_status = 0x0;
> +
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->dnl_address = be32_to_cpu(cmd->addr);
> +		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
> +		sdp->next_state = SDP_STATE_TX_REGISTER;
> +		printf("Reading %d registers at 0x%08x... ",
> +		       sdp->dnl_bytes_remaining, sdp->dnl_address);
> +		break;
> +	case SDP_WRITE_FILE:
> +		sdp->always_send_status = true;
> +		sdp->error_status = SDP_WRITE_FILE_COMPLETE;
> +
> +		sdp->state = SDP_STATE_RX_FILE_DATA;
> +		sdp->dnl_address = be32_to_cpu(cmd->addr);
> +		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
> +		sdp->next_state = SDP_STATE_IDLE;
> +
> +		printf("Downloading file of size %d to 0x%08x... ",
> +		       sdp->dnl_bytes_remaining, sdp->dnl_address);
> +
> +		break;
> +	case SDP_ERROR_STATUS:
> +		sdp->always_send_status = true;
> +		sdp->error_status = 0;
> +
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->next_state = SDP_STATE_IDLE;
> +		break;
> +	case SDP_DCD_WRITE:
> +		sdp->always_send_status = true;
> +		sdp->error_status = SDP_WRITE_REGISTER_COMPLETE;
> +
> +		sdp->state = SDP_STATE_RX_DCD_DATA;
> +		sdp->dnl_bytes_remaining = be32_to_cpu(cmd->cnt);
> +		sdp->next_state = SDP_STATE_IDLE;
> +		break;
> +	case SDP_JUMP_ADDRESS:
> +		sdp->always_send_status = false;
> +		sdp->error_status = 0;
> +
> +		sdp->jmp_address = be32_to_cpu(cmd->addr);
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->next_state = SDP_STATE_JUMP;
> +		break;
> +	case SDP_SKIP_DCD_HEADER:
> +		sdp->always_send_status = true;
> +		sdp->error_status = SDP_SKIP_DCD_HEADER_COMPLETE;
> +
> +		/* Ignore command, DCD not supported anyway */
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		sdp->next_state = SDP_STATE_IDLE;
> +		break;
> +	default:
> +		error("Unknown command: %04x\n", be16_to_cpu(cmd->cmd));
> +	}
> +}
> +
> +static void sdp_rx_data_complete(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct f_sdp *sdp = req->context;
> +	int status = req->status;
> +	u8 *data = req->buf;
> +	u8 report = data[0];
> +	int datalen = req->length - 1;
> +
> +	if (status != 0) {
> +		error("Status: %d", status);
> +		return;
> +	}
> +
> +	if (report != 2) {
> +		error("Unexpected report %d", report);
> +		return;
> +	}
> +
> +	if (sdp->dnl_bytes_remaining < datalen) {
> +		/*
> +		 * Some USB stacks require to send a complete buffer as
> +		 * specified in the HID descriptor. This leads to longer
> +		 * transfers than the file length, no problem for us.
> +		 */
> +		sdp->dnl_bytes_remaining = 0;
> +	} else {
> +		sdp->dnl_bytes_remaining -= datalen;
> +	}
> +
> +	if (sdp->state == SDP_STATE_RX_FILE_DATA) {
> +		memcpy((void *)sdp->dnl_address, req->buf + 1, datalen);
> +		sdp->dnl_address += datalen;
> +	}
> +
> +	if (sdp->dnl_bytes_remaining)
> +		return;
> +
> +	printf("done\n");
> +
> +	switch (sdp->state) {
> +	case SDP_STATE_RX_FILE_DATA:
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		break;
> +	case SDP_STATE_RX_DCD_DATA:
> +		sdp->state = SDP_STATE_TX_SEC_CONF;
> +		break;
> +	default:
> +		error("Invalid state: %d", sdp->state);
> +	}
> +}
> +
> +static void sdp_tx_complete(struct usb_ep *ep, struct usb_request *req)
> +{
> +	struct f_sdp *sdp = req->context;
> +	int status = req->status;
> +
> +	if (status != 0) {
> +		error("Status: %d", status);
> +		return;
> +	}
> +
> +	switch (sdp->state) {
> +	case SDP_STATE_TX_SEC_CONF_BUSY:
> +		/* Not all commands require status report */
> +		if (sdp->always_send_status || sdp->error_status)
> +			sdp->state = SDP_STATE_TX_STATUS;
> +		else
> +			sdp->state = sdp->next_state;
> +
> +		break;
> +	case SDP_STATE_TX_STATUS_BUSY:
> +		sdp->state = sdp->next_state;
> +		break;
> +	case SDP_STATE_TX_REGISTER_BUSY:
> +		if (sdp->dnl_bytes_remaining)
> +			sdp->state = SDP_STATE_TX_REGISTER;
> +		else
> +			sdp->state = SDP_STATE_IDLE;
> +		break;
> +	default:
> +		error("Wrong State: %d", sdp->state);
> +		sdp->state = SDP_STATE_IDLE;
> +		break;
> +	}
> +	debug("%s complete --> %d, %d/%d\n", ep->name,
> +	      status, req->actual, req->length);
> +}
> +
> +static int sdp_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl)
> +{
> +	struct usb_gadget *gadget = f->config->cdev->gadget;
> +	struct usb_request *req = f->config->cdev->req;
> +	struct f_sdp *sdp = f->config->cdev->req->context;
> +	u16 len = le16_to_cpu(ctrl->wLength);
> +	u16 w_value = le16_to_cpu(ctrl->wValue);
> +	int value = 0;
> +	u8 req_type = ctrl->bRequestType & USB_TYPE_MASK;
> +
> +	debug("w_value: 0x%04x len: 0x%04x\n", w_value, len);
> +	debug("req_type: 0x%02x ctrl->bRequest: 0x%02x sdp->state: %d\n",
> +	      req_type, ctrl->bRequest, sdp->state);
> +
> +	if (req_type == USB_TYPE_STANDARD) {
> +		if (ctrl->bRequest == USB_REQ_GET_DESCRIPTOR) {
> +			/* Send HID report descriptor */
> +			value = min(len, (u16) sizeof(sdp_hid_report));
> +			memcpy(req->buf, &sdp_hid_report, value);
> +			sdp->configuration_done = true;
> +		}
> +	}
> +
> +	if (req_type == USB_TYPE_CLASS) {
> +		int report = w_value & HID_REPORT_ID_MASK;
> +
> +		/* HID (SDP) request */
> +		switch (ctrl->bRequest) {
> +		case HID_REQ_SET_REPORT:
> +			switch (report) {
> +			case 1:
> +				value = SDP_COMMAND_LEN + 1;
> +				req->complete = sdp_rx_command_complete;
> +				break;
> +			case 2:
> +				value = len;
> +				req->complete = sdp_rx_data_complete;
> +				break;
> +			}
> +		}
> +	}
> +
> +	if (value >= 0) {
> +		req->length = value;
> +		req->zero = value < len;
> +		value = usb_ep_queue(gadget->ep0, req, 0);
> +		if (value < 0) {
> +			debug("ep_queue --> %d\n", value);
> +			req->status = 0;
> +		}
> +	}
> +
> +	return value;
> +}
> +
> +static int sdp_bind(struct usb_configuration *c, struct usb_function *f)
> +{
> +	struct usb_gadget *gadget = c->cdev->gadget;
> +	struct usb_composite_dev *cdev = c->cdev;
> +	struct f_sdp *sdp = func_to_sdp(f);
> +	int rv = 0, id;
> +
> +	id = usb_interface_id(c, f);
> +	if (id < 0)
> +		return id;
> +	sdp_intf_runtime.bInterfaceNumber = id;
> +
> +	struct usb_ep *ep;
> +
> +	/* allocate instance-specific endpoints */
> +	ep = usb_ep_autoconfig(gadget, &in_desc);
> +	if (!ep) {
> +		rv = -ENODEV;
> +		goto error;
> +	}
> +
> +	sdp->in_ep = ep; /* Store IN EP for enabling @ setup */
> +
> +	cdev->req->context = sdp;
> +
> +error:
> +	return rv;
> +}
> +
> +static void sdp_unbind(struct usb_configuration *c, struct usb_function *f)
> +{
> +	free(sdp_func);
> +	sdp_func = NULL;
> +}
> +
> +static struct usb_request *alloc_ep_req(struct usb_ep *ep, unsigned length)
> +{
> +	struct usb_request *req;
> +
> +	req = usb_ep_alloc_request(ep, 0);
> +	if (!req)
> +		return req;
> +
> +	req->length = length;
> +	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, length);
> +	if (!req->buf) {
> +		usb_ep_free_request(ep, req);
> +		req = NULL;
> +	}
> +
> +	return req;
> +}
> +
> +
> +static struct usb_request *sdp_start_ep(struct usb_ep *ep)
> +{
> +	struct usb_request *req;
> +
> +	req = alloc_ep_req(ep, 64);
> +	debug("%s: ep:%p req:%p\n", __func__, ep, req);
> +
> +	if (!req)
> +		return NULL;
> +
> +	memset(req->buf, 0, req->length);
> +	req->complete = sdp_tx_complete;
> +
> +	return req;
> +}
> +static int sdp_set_alt(struct usb_function *f, unsigned intf, unsigned alt)
> +{
> +	struct f_sdp *sdp = func_to_sdp(f);
> +	struct usb_composite_dev *cdev = f->config->cdev;
> +	int result;
> +
> +	debug("%s: intf: %d alt: %d\n", __func__, intf, alt);
> +
> +	result = usb_ep_enable(sdp->in_ep, &in_desc);
> +	if (result)
> +		return result;
> +	sdp->in_req = sdp_start_ep(sdp->in_ep);
> +	sdp->in_req->context = sdp;
> +
> +	sdp->in_ep->driver_data = cdev; /* claim */
> +
> +	sdp->altsetting = alt;
> +	sdp->state = SDP_STATE_IDLE;
> +
> +	return 0;
> +}
> +
> +static int sdp_get_alt(struct usb_function *f, unsigned intf)
> +{
> +	struct f_sdp *sdp = func_to_sdp(f);
> +
> +	return sdp->altsetting;
> +}
> +
> +static void sdp_disable(struct usb_function *f)
> +{
> +	struct f_sdp *sdp = func_to_sdp(f);
> +
> +	usb_ep_disable(sdp->in_ep);
> +
> +	if (sdp->in_req) {
> +		free(sdp->in_req);
> +		sdp->in_req = NULL;
> +	}
> +}
> +
> +static int sdp_bind_config(struct usb_configuration *c)
> +{
> +	int status;
> +
> +	if (!sdp_func) {
> +		sdp_func = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*sdp_func));
> +		if (!sdp_func)
> +			return -ENOMEM;
> +	}
> +
> +	memset(sdp_func, 0, sizeof(*sdp_func));
> +
> +	sdp_func->usb_function.name = "sdp";
> +	sdp_func->usb_function.hs_descriptors = sdp_runtime_descs;
> +	sdp_func->usb_function.descriptors = sdp_runtime_descs;
> +	sdp_func->usb_function.bind = sdp_bind;
> +	sdp_func->usb_function.unbind = sdp_unbind;
> +	sdp_func->usb_function.set_alt = sdp_set_alt;
> +	sdp_func->usb_function.get_alt = sdp_get_alt;
> +	sdp_func->usb_function.disable = sdp_disable;
> +	sdp_func->usb_function.strings = sdp_generic_strings;
> +	sdp_func->usb_function.setup = sdp_setup;
> +
> +	status = usb_add_function(c, &sdp_func->usb_function);
> +
> +	return status;
> +}
> +
> +int sdp_init(int controller_index)
> +{
> +	printf("SDP: initialize...\n");
> +	while (!sdp_func->configuration_done) {
> +		if (ctrlc()) {
> +			puts("\rCTRL+C - Operation aborted.\n");
> +			return 1;
> +		}
> +		usb_gadget_handle_interrupts(controller_index);
> +	}
> +
> +	return 0;
> +}
> +
> +static u32 sdp_jump_imxheader(void *address)
> +{
> +	flash_header_v2_t *headerv2 = address;
> +	ulong (*entry)(void);
> +
> +	if (headerv2->header.tag != IVT_HEADER_TAG) {
> +		printf("Header Tag is not an IMX image\n");
> +		return SDP_ERROR_IMXHEADER;
> +	}
> +
> +	printf("Jumping to 0x%08x\n", headerv2->entry);
> +	entry = (void *)headerv2->entry;
> +	entry();
> +
> +	/* The image probably never returns hence we won't reach that point */
> +	return 0;
> +}
> +
> +static void sdp_handle_in_ep(void)
> +{
> +	u8 *data = sdp_func->in_req->buf;
> +	u32 status;
> +	int datalen;
> +
> +	switch (sdp_func->state) {
> +	case SDP_STATE_TX_SEC_CONF:
> +		debug("Report 3: HAB security\n");
> +		data[0] = 3;
> +
> +		status = SDP_SECURITY_OPEN;
> +		memcpy(&data[1], &status, 4);
> +		sdp_func->in_req->length = 5;
> +		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
> +		sdp_func->state = SDP_STATE_TX_SEC_CONF_BUSY;
> +		break;
> +
> +	case SDP_STATE_TX_STATUS:
> +		debug("Report 4: Status\n");
> +		data[0] = 4;
> +
> +		memcpy(&data[1], &sdp_func->error_status, 4);
> +		sdp_func->in_req->length = 65;
> +		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
> +		sdp_func->state = SDP_STATE_TX_STATUS_BUSY;
> +		break;
> +	case SDP_STATE_TX_REGISTER:
> +		debug("Report 4: Register Values\n");
> +		data[0] = 4;
> +
> +		datalen = sdp_func->dnl_bytes_remaining;
> +
> +		if (datalen > 64)
> +			datalen = 64;
> +
> +		memcpy(&data[1], (void *)sdp_func->dnl_address, datalen);
> +		sdp_func->in_req->length = 65;
> +
> +		sdp_func->dnl_bytes_remaining -= datalen;
> +		sdp_func->dnl_address += datalen;
> +
> +		usb_ep_queue(sdp_func->in_ep, sdp_func->in_req, 0);
> +		sdp_func->state = SDP_STATE_TX_REGISTER_BUSY;
> +		break;
> +	case SDP_STATE_JUMP:
> +		printf("Checking imxheader at 0x%08x\n", f_sdp->jmp_address);
> +		status = sdp_jump_imxheader((void *)f_sdp->jmp_address);
> +
> +		sdp_func->next_state = SDP_STATE_IDLE;
> +		sdp_func->error_status = status;
> +
> +		/* Only send Report 4 if there was an error */
> +		if (status)
> +			sdp_func->state = SDP_STATE_TX_STATUS;
> +		else
> +			sdp_func->state = SDP_STATE_IDLE;
> +		break;
> +	default:
> +		break;
> +	};
> +}
> +
> +void sdp_handle(int controller_index)
> +{
> +	printf("SDP: handle requests...\n");
> +	while (1) {
> +		if (ctrlc()) {
> +			puts("\rCTRL+C - Operation aborted.\n");
> +			return;
> +		}
> +
> +		usb_gadget_handle_interrupts(controller_index);
> +
> +		sdp_handle_in_ep();
> +	}
> +}
> +
> +int sdp_add(struct usb_configuration *c)
> +{
> +	int id;
> +
> +	id = usb_string_id(c->cdev);
> +	if (id < 0)
> +		return id;
> +	strings_sdp_generic[0].id = id;
> +	sdp_intf_runtime.iInterface = id;
> +
> +	debug("%s: cdev: %p gadget: %p gadget->ep0: %p\n", __func__,
> +	      c->cdev, c->cdev->gadget, c->cdev->gadget->ep0);
> +
> +	return sdp_bind_config(c);
> +}
> +
> +DECLARE_GADGET_BIND_CALLBACK(usb_dnl_sdp, sdp_add);
> diff --git a/include/sdp.h b/include/sdp.h
> new file mode 100644
> index 0000000000..f476bab8f1
> --- /dev/null
> +++ b/include/sdp.h
> @@ -0,0 +1,16 @@
> +/*
> + * sdp.h - Serial Download Protocol
> + *
> + * Copyright (C) 2017 Toradex
> + * Author: Stefan Agner <stefan.agner@toradex.com>
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __SDP_H_
> +#define __SDP_H_
> +
> +int sdp_init(int controller_index);
> +void sdp_handle(int controller_index);
> +
> +#endif /* __SDP_H_ */
> 


-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver
  2017-08-17 13:49   ` Stefano Babic
@ 2017-08-17 13:54     ` Marek Vasut
  2017-08-17 13:59       ` Stefano Babic
  2017-08-17 14:01       ` Łukasz Majewski
  0 siblings, 2 replies; 28+ messages in thread
From: Marek Vasut @ 2017-08-17 13:54 UTC (permalink / raw)
  To: u-boot

On 08/17/2017 03:49 PM, Stefano Babic wrote:
> On 16/08/2017 20:00, Stefan Agner wrote:
>> From: Stefan Agner <stefan.agner@toradex.com>
>>
>> Add SDP (Serial Downloader Protocol) implementation for U-Boot. The
>> protocol is used in NXP SoC's boot ROM and allows to download program
>> images. Beside that, it can also be used to read/write registers and
>> download complete Device Configuration Data (DCD) sets. This basic
>> implementation supports downloading images with the imx header format
>> reading and writing registers.
>>
>> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
> 
> Reviewed by : Stefano Babic ysbabic at denx.de>
> 
> Marek, this is related to USB. Anyway, I will prefer that the whole
> patchset will be merged at once, and not split between u-boot-imx and
> u-boot-usb. If you agree (and after the patchset is ok for you, of
> course !), I will propose that I will merge the whole patchset into
> u-boot-imx to avoid breakages.

This is gadget stuff, so it's Lukasz's call, not mine.

-- 
Best regards,
Marek Vasut

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver
  2017-08-17 13:54     ` Marek Vasut
@ 2017-08-17 13:59       ` Stefano Babic
  2017-08-17 14:01       ` Łukasz Majewski
  1 sibling, 0 replies; 28+ messages in thread
From: Stefano Babic @ 2017-08-17 13:59 UTC (permalink / raw)
  To: u-boot

On 17/08/2017 15:54, Marek Vasut wrote:
> On 08/17/2017 03:49 PM, Stefano Babic wrote:
>> On 16/08/2017 20:00, Stefan Agner wrote:
>>> From: Stefan Agner <stefan.agner@toradex.com>
>>>
>>> Add SDP (Serial Downloader Protocol) implementation for U-Boot. The
>>> protocol is used in NXP SoC's boot ROM and allows to download program
>>> images. Beside that, it can also be used to read/write registers and
>>> download complete Device Configuration Data (DCD) sets. This basic
>>> implementation supports downloading images with the imx header format
>>> reading and writing registers.
>>>
>>> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
>>
>> Reviewed by : Stefano Babic ysbabic at denx.de>
>>
>> Marek, this is related to USB. Anyway, I will prefer that the whole
>> patchset will be merged at once, and not split between u-boot-imx and
>> u-boot-usb. If you agree (and after the patchset is ok for you, of
>> course !), I will propose that I will merge the whole patchset into
>> u-boot-imx to avoid breakages.
> 
> This is gadget stuff, so it's Lukasz's call, not mine.

Sorry for noise, you're right.

Lukasz, is it ok for you ?

Regards,
Stefano

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver
  2017-08-17 13:54     ` Marek Vasut
  2017-08-17 13:59       ` Stefano Babic
@ 2017-08-17 14:01       ` Łukasz Majewski
  1 sibling, 0 replies; 28+ messages in thread
From: Łukasz Majewski @ 2017-08-17 14:01 UTC (permalink / raw)
  To: u-boot

On 08/17/2017 03:54 PM, Marek Vasut wrote:
> On 08/17/2017 03:49 PM, Stefano Babic wrote:
>> On 16/08/2017 20:00, Stefan Agner wrote:
>>> From: Stefan Agner <stefan.agner@toradex.com>
>>>
>>> Add SDP (Serial Downloader Protocol) implementation for U-Boot. The
>>> protocol is used in NXP SoC's boot ROM and allows to download program
>>> images. Beside that, it can also be used to read/write registers and
>>> download complete Device Configuration Data (DCD) sets. This basic
>>> implementation supports downloading images with the imx header format
>>> reading and writing registers.
>>>
>>> Signed-off-by: Stefan Agner <stefan.agner@toradex.com>
>>
>> Reviewed by : Stefano Babic ysbabic at denx.de>
>>
>> Marek, this is related to USB. Anyway, I will prefer that the whole
>> patchset will be merged at once, and not split between u-boot-imx and
>> u-boot-usb. If you agree (and after the patchset is ok for you, of
>> course !), I will propose that I will merge the whole patchset into
>> u-boot-imx to avoid breakages.
>
> This is gadget stuff, so it's Lukasz's call, not mine.

I'm fine with this approach (as I've already reviewed those patches).

Stefano, please merge it to your's -imx tree.

>


-- 
Best regards,

Lukasz Majewski

--

DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd at denx.de

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
                   ` (7 preceding siblings ...)
  2017-08-16 18:00 ` [U-Boot] [PATCH v2 8/8] apalis/colibri_imx6: enable SDP by default Stefan Agner
@ 2017-08-23  8:43 ` Stefano Babic
  2017-08-23 12:28   ` Fabio Estevam
  2017-09-01 16:48 ` Fabio Estevam
  9 siblings, 1 reply; 28+ messages in thread
From: Stefano Babic @ 2017-08-23  8:43 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

On 16/08/2017 20:00, Stefan Agner wrote:
> From: Stefan Agner <stefan.agner@toradex.com>
> 
> This series adds NXP's Serial Download Protocol (SDP) support via
> USB for SPL/U-Boot. It allows to download U-Boot via USB from a
> (recovered) SPL using the same tools used to download SPL itself
> (specifically imx_usb, but also sb_loader seems to work).
> 
> The idea has been brought up when the first targets started to make
> use of SPL for DDR initialization, see:
> https://lists.denx.de/pipermail/u-boot/2015-July/220330.html
> 
> The initial SDP implementation (patch 2) requires the payload to
> have the imx specific headers (hence the move of the imx header
> file in patch 1).
> 
> Patch 3 extends image header support beyond the SDP specification,
> specifically implements also support for U-Boot headers. This
> allows to use the same SPL/U-Boot binaries for recovery as used on
> the regular boot device (SD/eMMC). For that to work also the host
> side imx_usb tools needed an extension, currently available here:
> 
> https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored
> 
> (in case this patchset gets accepted in U-Boot, I plan to push
> these imx_usb changes upstream as well)
> 
> The full patchset allows to download SPL and U-Boot over USB to a
> target in recovery mode using the same usb_imx utility. Refer to
> the new README.sdp for details how to use usb_imx in combination
> with this implementation.
> 
> Changes in v2:
> - Changed function signature of sdp_init/sdp_handle to allow specifying
>   which USB controller should be used.
> - Use #defines for security mode
> - Improved types used in format strings
> - Changed function signature of sdp_init/sdp_handle
> - Use BOOT_DEVICE_BOARD
> 
> Stefan Agner (8):
>   imx: move imximage header to common location
>   usb: gadget: add SDP driver
>   usb: gadget: sdp: extend images compatible for jumps
>   cmd: add sdp command
>   spl: add serial download protocol (SDP) support
>   doc: add Serial Download Protocol documentation
>   apalis/colibri_imx6: use independent USB PID for SPL
>   apalis/colibri_imx6: enable SDP by default
> 

I have merged the whole series to u-boot-imx. Many thanks for your
effort, this was in the TODO list for i.MX since a long time !

Best regards,
Stefano Babic

-- 
=====================================================================
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany
Phone: +49-8142-66989-53 Fax: +49-8142-66989-80 Email: sbabic at denx.de
=====================================================================

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-08-23  8:43 ` [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefano Babic
@ 2017-08-23 12:28   ` Fabio Estevam
  0 siblings, 0 replies; 28+ messages in thread
From: Fabio Estevam @ 2017-08-23 12:28 UTC (permalink / raw)
  To: u-boot

On Wed, Aug 23, 2017 at 5:43 AM, Stefano Babic <sbabic@denx.de> wrote:

> I have merged the whole series to u-boot-imx. Many thanks for your
> effort, this was in the TODO list for i.MX since a long time !

Yes, very nice job, Stefan!

I will be using it soon on mx6sabresd, thanks!

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
                   ` (8 preceding siblings ...)
  2017-08-23  8:43 ` [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefano Babic
@ 2017-09-01 16:48 ` Fabio Estevam
  2017-09-01 18:19   ` Stefan Agner
  9 siblings, 1 reply; 28+ messages in thread
From: Fabio Estevam @ 2017-09-01 16:48 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

On Wed, Aug 16, 2017 at 3:00 PM, Stefan Agner <stefan@agner.ch> wrote:
> From: Stefan Agner <stefan.agner@toradex.com>
>
> This series adds NXP's Serial Download Protocol (SDP) support via
> USB for SPL/U-Boot. It allows to download U-Boot via USB from a
> (recovered) SPL using the same tools used to download SPL itself
> (specifically imx_usb, but also sb_loader seems to work).
>
> The idea has been brought up when the first targets started to make
> use of SPL for DDR initialization, see:
> https://lists.denx.de/pipermail/u-boot/2015-July/220330.html
>
> The initial SDP implementation (patch 2) requires the payload to
> have the imx specific headers (hence the move of the imx header
> file in patch 1).
>
> Patch 3 extends image header support beyond the SDP specification,
> specifically implements also support for U-Boot headers. This
> allows to use the same SPL/U-Boot binaries for recovery as used on
> the regular boot device (SD/eMMC). For that to work also the host
> side imx_usb tools needed an extension, currently available here:
>
> https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored
>
> (in case this patchset gets accepted in U-Boot, I plan to push
> these imx_usb changes upstream as well)
>
> The full patchset allows to download SPL and U-Boot over USB to a
> target in recovery mode using the same usb_imx utility. Refer to
> the new README.sdp for details how to use usb_imx in combination
> with this implementation.

I am trying to use this feature on a imx6qsabresd board.

Here are the changes I made (against u-boot-imx latest tree):

diff --git a/board/freescale/mx6sabresd/mx6sabresd.c
b/board/freescale/mx6sabresd/mx6sabresd.c
index 5b50bc8..6ca2485 100644
--- a/board/freescale/mx6sabresd/mx6sabresd.c
+++ b/board/freescale/mx6sabresd/mx6sabresd.c
@@ -29,6 +29,7 @@
 #include <power/pfuze100_pmic.h>
 #include "../common/pfuze.h"
 #include <usb.h>
+#include <g_dnl.h>

 DECLARE_GLOBAL_DATA_PTR;

@@ -1033,6 +1034,19 @@ static void spl_dram_init(void)
                ddr_init(mx6dl_dcd_table, ARRAY_SIZE(mx6dl_dcd_table));
 }

+#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
+#define FSL_USB_PRODUCT_NUM_OFFSET        0xa4a5
+int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
+{
+       unsigned short usb_pid;
+
+       usb_pid = FSL_USB_PRODUCT_NUM_OFFSET + 0xff;
+       put_unaligned(usb_pid, &dev->idProduct);
+
+       return 0;
+}
+#endif
+
 void board_init_f(ulong dummy)
 {
        /* DDR initialization */
diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig
index 7949c5e..1c08639 100644
--- a/configs/mx6sabresd_defconfig
+++ b/configs/mx6sabresd_defconfig
@@ -19,6 +19,9 @@ CONFIG_SPL=y
 CONFIG_SPL_EXT_SUPPORT=y
 CONFIG_SPL_I2C_SUPPORT=y
 CONFIG_SPL_OS_BOOT=y
+CONFIG_SPL_USB_HOST_SUPPORT=y
+CONFIG_SPL_USB_GADGET_SUPPORT=y
+CONFIG_SPL_USB_SDP_SUPPORT=y
 CONFIG_HUSH_PARSER=y
 CONFIG_CMD_BOOTZ=y
 # CONFIG_CMD_IMLS is not set
@@ -32,6 +35,7 @@ CONFIG_CMD_PART=y
 CONFIG_CMD_PCI=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_USB_SDP=y
 CONFIG_CMD_DHCP=y
 CONFIG_CMD_MII=y
 CONFIG_CMD_PING=y

Then I use the imx_usb tool from
https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored

I remove the SD card, so that the board goes to SDP and then run:

sudo ./imx_usb SPL

and then I see in the board console:

U-Boot SPL 2017.09-rc2-36996-g63af4b0-dirty (Sep 01 2017 - 13:42:55)
Trying to boot from MMC1
MMC: no card present
mmc_init: -123, time 1
spl: mmc init failed with error: -123
SPL: failed to boot from all boot devices
### ERROR ### Please RESET the board ###

I was expecting to see:

  Trying to boot from USB SDP
  SDP: initialize...
  SDP: handle requests...

as per the README.sdp

Any ideas as to what I am missing?

Thanks

^ permalink raw reply related	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-01 16:48 ` Fabio Estevam
@ 2017-09-01 18:19   ` Stefan Agner
  2017-09-01 18:54     ` Fabio Estevam
  0 siblings, 1 reply; 28+ messages in thread
From: Stefan Agner @ 2017-09-01 18:19 UTC (permalink / raw)
  To: u-boot

On 2017-09-01 09:48, Fabio Estevam wrote:
> Hi Stefan,
> 
> On Wed, Aug 16, 2017 at 3:00 PM, Stefan Agner <stefan@agner.ch> wrote:
>> From: Stefan Agner <stefan.agner@toradex.com>
>>
>> This series adds NXP's Serial Download Protocol (SDP) support via
>> USB for SPL/U-Boot. It allows to download U-Boot via USB from a
>> (recovered) SPL using the same tools used to download SPL itself
>> (specifically imx_usb, but also sb_loader seems to work).
>>
>> The idea has been brought up when the first targets started to make
>> use of SPL for DDR initialization, see:
>> https://lists.denx.de/pipermail/u-boot/2015-July/220330.html
>>
>> The initial SDP implementation (patch 2) requires the payload to
>> have the imx specific headers (hence the move of the imx header
>> file in patch 1).
>>
>> Patch 3 extends image header support beyond the SDP specification,
>> specifically implements also support for U-Boot headers. This
>> allows to use the same SPL/U-Boot binaries for recovery as used on
>> the regular boot device (SD/eMMC). For that to work also the host
>> side imx_usb tools needed an extension, currently available here:
>>
>> https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored
>>
>> (in case this patchset gets accepted in U-Boot, I plan to push
>> these imx_usb changes upstream as well)
>>
>> The full patchset allows to download SPL and U-Boot over USB to a
>> target in recovery mode using the same usb_imx utility. Refer to
>> the new README.sdp for details how to use usb_imx in combination
>> with this implementation.
> 
> I am trying to use this feature on a imx6qsabresd board.
> 
> Here are the changes I made (against u-boot-imx latest tree):
> 
> diff --git a/board/freescale/mx6sabresd/mx6sabresd.c
> b/board/freescale/mx6sabresd/mx6sabresd.c
> index 5b50bc8..6ca2485 100644
> --- a/board/freescale/mx6sabresd/mx6sabresd.c
> +++ b/board/freescale/mx6sabresd/mx6sabresd.c
> @@ -29,6 +29,7 @@
>  #include <power/pfuze100_pmic.h>
>  #include "../common/pfuze.h"
>  #include <usb.h>
> +#include <g_dnl.h>
> 
>  DECLARE_GLOBAL_DATA_PTR;
> 
> @@ -1033,6 +1034,19 @@ static void spl_dram_init(void)
>                 ddr_init(mx6dl_dcd_table, ARRAY_SIZE(mx6dl_dcd_table));
>  }
> 
> +#ifdef CONFIG_SPL_USB_GADGET_SUPPORT
> +#define FSL_USB_PRODUCT_NUM_OFFSET        0xa4a5
> +int g_dnl_bind_fixup(struct usb_device_descriptor *dev, const char *name)
> +{
> +       unsigned short usb_pid;
> +
> +       usb_pid = FSL_USB_PRODUCT_NUM_OFFSET + 0xff;
> +       put_unaligned(usb_pid, &dev->idProduct);
> +
> +       return 0;
> +}
> +#endif
> +
>  void board_init_f(ulong dummy)
>  {
>         /* DDR initialization */
> diff --git a/configs/mx6sabresd_defconfig b/configs/mx6sabresd_defconfig
> index 7949c5e..1c08639 100644
> --- a/configs/mx6sabresd_defconfig
> +++ b/configs/mx6sabresd_defconfig
> @@ -19,6 +19,9 @@ CONFIG_SPL=y
>  CONFIG_SPL_EXT_SUPPORT=y
>  CONFIG_SPL_I2C_SUPPORT=y
>  CONFIG_SPL_OS_BOOT=y
> +CONFIG_SPL_USB_HOST_SUPPORT=y
> +CONFIG_SPL_USB_GADGET_SUPPORT=y
> +CONFIG_SPL_USB_SDP_SUPPORT=y
>  CONFIG_HUSH_PARSER=y
>  CONFIG_CMD_BOOTZ=y
>  # CONFIG_CMD_IMLS is not set
> @@ -32,6 +35,7 @@ CONFIG_CMD_PART=y
>  CONFIG_CMD_PCI=y
>  CONFIG_CMD_SF=y
>  CONFIG_CMD_USB=y
> +CONFIG_CMD_USB_SDP=y
>  CONFIG_CMD_DHCP=y
>  CONFIG_CMD_MII=y
>  CONFIG_CMD_PING=y
> 
> Then I use the imx_usb tool from
> https://github.com/toradex/imx_loader/tree/imx_usb_batch_mode_refactored
> 
> I remove the SD card, so that the board goes to SDP and then run:
> 
> sudo ./imx_usb SPL
> 
> and then I see in the board console:
> 
> U-Boot SPL 2017.09-rc2-36996-g63af4b0-dirty (Sep 01 2017 - 13:42:55)
> Trying to boot from MMC1
> MMC: no card present
> mmc_init: -123, time 1
> spl: mmc init failed with error: -123
> SPL: failed to boot from all boot devices
> ### ERROR ### Please RESET the board ###
> 
> I was expecting to see:
> 
>   Trying to boot from USB SDP
>   SDP: initialize...
>   SDP: handle requests...
> 
> as per the README.sdp
> 
> Any ideas as to what I am missing?


That is the issue I am describing here:
https://lists.denx.de/pipermail/u-boot/2017-August/301952.html

Either enter recovery mode explicitly (by setting the BMODE pins or
using the bmode command)

Or you can use the USB PHY method which indicates whether the ROM used
serial downloader. We use this in our downstream U-Boot (NXP used that
method to go into "mgfr" mode...)
http://git.toradex.com/cgit/u-boot-toradex.git/commit/?h=2016.11-toradex-next&id=0d069117614b590848b490e348488362443c5547
http://git.toradex.com/cgit/u-boot-toradex.git/commit/?h=2016.11-toradex-next&id=80c3bd6c2750c3c2843537f015c0d675b1b74a58

--
Stefan

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-01 18:19   ` Stefan Agner
@ 2017-09-01 18:54     ` Fabio Estevam
  2017-09-01 19:25       ` Fabio Estevam
  0 siblings, 1 reply; 28+ messages in thread
From: Fabio Estevam @ 2017-09-01 18:54 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

On Fri, Sep 1, 2017 at 3:19 PM, Stefan Agner <stefan@agner.ch> wrote:

> That is the issue I am describing here:
> https://lists.denx.de/pipermail/u-boot/2017-August/301952.html
>
> Either enter recovery mode explicitly (by setting the BMODE pins or
> using the bmode command)

On imx6qsabresd it is not possible to put the boot pins into serial
download mode.

>
> Or you can use the USB PHY method which indicates whether the ROM used
> serial downloader. We use this in our downstream U-Boot (NXP used that
> method to go into "mgfr" mode...)
> http://git.toradex.com/cgit/u-boot-toradex.git/commit/?h=2016.11-toradex-next&id=0d069117614b590848b490e348488362443c5547
> http://git.toradex.com/cgit/u-boot-toradex.git/commit/?h=2016.11-toradex-next&id=80c3bd6c2750c3c2843537f015c0d675b1b74a58

I have tested this method and it works, thanks.

Do you plan to usptream this method?

Thanks

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-01 18:54     ` Fabio Estevam
@ 2017-09-01 19:25       ` Fabio Estevam
  2017-09-01 20:09         ` Stefan Agner
  0 siblings, 1 reply; 28+ messages in thread
From: Fabio Estevam @ 2017-09-01 19:25 UTC (permalink / raw)
  To: u-boot

On Fri, Sep 1, 2017 at 3:54 PM, Fabio Estevam <festevam@gmail.com> wrote:

> I have tested this method and it works, thanks.
>
> Do you plan to usptream this method?

Or I can also put your patch as part of my series that adds SDP
support for imx6qsabresd if you prefer.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-01 19:25       ` Fabio Estevam
@ 2017-09-01 20:09         ` Stefan Agner
  2017-09-08  8:27           ` Vincent Prince
  0 siblings, 1 reply; 28+ messages in thread
From: Stefan Agner @ 2017-09-01 20:09 UTC (permalink / raw)
  To: u-boot



On September 1, 2017 12:25:44 PM PDT, Fabio Estevam <festevam@gmail.com> wrote:
>On Fri, Sep 1, 2017 at 3:54 PM, Fabio Estevam <festevam@gmail.com>
>wrote:
>
>> I have tested this method and it works, thanks.
>>
>> Do you plan to usptream this method?
>
>Or I can also put your patch as part of my series that adds SDP
>support for imx6qsabresd if you prefer.

Let me do a separate, I guess it could be controversial...

--
Stefan
-- 
Sent from my Android device with K-9 Mail. Please excuse my brevity.

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-01 20:09         ` Stefan Agner
@ 2017-09-08  8:27           ` Vincent Prince
  2017-09-08 16:37             ` Stefan Agner
  0 siblings, 1 reply; 28+ messages in thread
From: Vincent Prince @ 2017-09-08  8:27 UTC (permalink / raw)
  To: u-boot

Hi everyone,

I managed to get SDP protocol to work with on my custom i.MX6 board,
so big thanks to Stefan for your work!

I'm now trying to load swupdate ramdisk with u-boot sdp command,
without success.
Is it a possible use case ?

Here my steps:

In u-boot:
=> sdp 0

On Host,
$ imx_usb

config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\imx_usb.conf>
vid=0x15a2 pid=0x0061 file_name=mx6_usb_rom.conf -> vid=0x0525
pid=0xb4a4 file_name=mx6_usb_sdp_spl.conf
vid=0x0525 pid=0xa4a5 file_name=mx6_usb_uboot.conf
config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf>
parse C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf
Trying to open device vid=0x0525 pid=0xa4a5.........................
Could not open device vid=0x0525 pid=0xa4a5

VID/PID in imx_usb.conf are correctly detected, and correct
configuration file is launched (mx6_usb_uboot.conf),
it contains:

mx6_usb_sdp_uboot
hid,1024,0x10000000,1G,0x00907000,0x31000
test.txt:load 0x12100000

My imx_usb.conf is the following:

#vid:pid, config_file
0x15a2:0x0061, mx6_usb_rom.conf, 0x0525:0xb4a4, mx6_usb_sdp_spl.conf
0x0525:0xa4a5, mx6_usb_uboot.conf

Am I missing something,
Thanks,
Vincent

2017-09-01 22:09 GMT+02:00 Stefan Agner <stefan@agner.ch>:
>
>
> On September 1, 2017 12:25:44 PM PDT, Fabio Estevam <festevam@gmail.com> wrote:
>>On Fri, Sep 1, 2017 at 3:54 PM, Fabio Estevam <festevam@gmail.com>
>>wrote:
>>
>>> I have tested this method and it works, thanks.
>>>
>>> Do you plan to usptream this method?
>>
>>Or I can also put your patch as part of my series that adds SDP
>>support for imx6qsabresd if you prefer.
>
> Let me do a separate, I guess it could be controversial...
>
> --
> Stefan
> --
> Sent from my Android device with K-9 Mail. Please excuse my brevity.
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-08  8:27           ` Vincent Prince
@ 2017-09-08 16:37             ` Stefan Agner
  2017-09-11 14:15               ` Vincent Prince
  0 siblings, 1 reply; 28+ messages in thread
From: Stefan Agner @ 2017-09-08 16:37 UTC (permalink / raw)
  To: u-boot

Hi Vincent,

On 2017-09-08 01:27, Vincent Prince wrote:
> Hi everyone,
> 
> I managed to get SDP protocol to work with on my custom i.MX6 board,
> so big thanks to Stefan for your work!
> 
> I'm now trying to load swupdate ramdisk with u-boot sdp command,
> without success.
> Is it a possible use case ?

Yes it should work, we use the U-Boot sdp command to download a squashfs
based ramdisk in our Toradex Easy Installer:
http://developer.toradex.com/software/toradex-easy-installer

> 
> Here my steps:
> 
> In u-boot:
> => sdp 0
> 
> On Host,
> $ imx_usb
> 
> config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\imx_usb.conf>
> vid=0x15a2 pid=0x0061 file_name=mx6_usb_rom.conf -> vid=0x0525
> pid=0xb4a4 file_name=mx6_usb_sdp_spl.conf
> vid=0x0525 pid=0xa4a5 file_name=mx6_usb_uboot.conf
> config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf>
> parse C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf
> Trying to open device vid=0x0525 pid=0xa4a5.........................
> Could not open device vid=0x0525 pid=0xa4a5

Is VID/PID showing up in Device Manager?

We did saw some problems with certain USB host implementation, so it
might be a device dependency... I would also try a different
machine/maybe Linux machine...

> 
> VID/PID in imx_usb.conf are correctly detected, and correct
> configuration file is launched (mx6_usb_uboot.conf),
> it contains:
> 
> mx6_usb_sdp_uboot
> hid,1024,0x10000000,1G,0x00907000,0x31000
> test.txt:load 0x12100000
> 
> My imx_usb.conf is the following:
> 
> #vid:pid, config_file
> 0x15a2:0x0061, mx6_usb_rom.conf, 0x0525:0xb4a4, mx6_usb_sdp_spl.conf
> 0x0525:0xa4a5, mx6_usb_uboot.conf

Yeah assuming you use the Toradex branch of imx_loader currently this
should work.

Our script looks like this:
mx6_usb_sdp_uboot
#hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat
valid ram areas)
hid,1024,0x10000000,1G,0x00907000,0x31000
#Load complete FIT image to $ramdisk_addr_r
tezi.itb:load 0x12100000
#Load script to $loadaddr and jump to it
boot-sdp.scr:load 0x12000000,jump 0x12000000

--
Stefan


> 
> Am I missing something,
> Thanks,
> Vincent
> 
> 2017-09-01 22:09 GMT+02:00 Stefan Agner <stefan@agner.ch>:
>>
>>
>> On September 1, 2017 12:25:44 PM PDT, Fabio Estevam <festevam@gmail.com> wrote:
>>>On Fri, Sep 1, 2017 at 3:54 PM, Fabio Estevam <festevam@gmail.com>
>>>wrote:
>>>
>>>> I have tested this method and it works, thanks.
>>>>
>>>> Do you plan to usptream this method?
>>>
>>>Or I can also put your patch as part of my series that adds SDP
>>>support for imx6qsabresd if you prefer.
>>
>> Let me do a separate, I guess it could be controversial...
>>
>> --
>> Stefan
>> --
>> Sent from my Android device with K-9 Mail. Please excuse my brevity.
>> _______________________________________________
>> U-Boot mailing list
>> U-Boot at lists.denx.de
>> https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-08 16:37             ` Stefan Agner
@ 2017-09-11 14:15               ` Vincent Prince
  2017-09-11 16:19                 ` Stefan Agner
  0 siblings, 1 reply; 28+ messages in thread
From: Vincent Prince @ 2017-09-11 14:15 UTC (permalink / raw)
  To: u-boot

Hi Stefan,

It was probably a Windows bug as it is almost working now.
I was wondering why sdp command is expecting a jump ?
Is it necessary to jump after USB transfer, or we should download
anything we want and jump if asked ?

Regards,
Vincent


2017-09-08 18:37 GMT+02:00 Stefan Agner <stefan@agner.ch>:
> Hi Vincent,
>
> On 2017-09-08 01:27, Vincent Prince wrote:
>> Hi everyone,
>>
>> I managed to get SDP protocol to work with on my custom i.MX6 board,
>> so big thanks to Stefan for your work!
>>
>> I'm now trying to load swupdate ramdisk with u-boot sdp command,
>> without success.
>> Is it a possible use case ?
>
> Yes it should work, we use the U-Boot sdp command to download a squashfs
> based ramdisk in our Toradex Easy Installer:
> http://developer.toradex.com/software/toradex-easy-installer
>
>>
>> Here my steps:
>>
>> In u-boot:
>> => sdp 0
>>
>> On Host,
>> $ imx_usb
>>
>> config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\imx_usb.conf>
>> vid=0x15a2 pid=0x0061 file_name=mx6_usb_rom.conf -> vid=0x0525
>> pid=0xb4a4 file_name=mx6_usb_sdp_spl.conf
>> vid=0x0525 pid=0xa4a5 file_name=mx6_usb_uboot.conf
>> config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf>
>> parse C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf
>> Trying to open device vid=0x0525 pid=0xa4a5.........................
>> Could not open device vid=0x0525 pid=0xa4a5
>
> Is VID/PID showing up in Device Manager?
>
> We did saw some problems with certain USB host implementation, so it
> might be a device dependency... I would also try a different
> machine/maybe Linux machine...
>
>>
>> VID/PID in imx_usb.conf are correctly detected, and correct
>> configuration file is launched (mx6_usb_uboot.conf),
>> it contains:
>>
>> mx6_usb_sdp_uboot
>> hid,1024,0x10000000,1G,0x00907000,0x31000
>> test.txt:load 0x12100000
>>
>> My imx_usb.conf is the following:
>>
>> #vid:pid, config_file
>> 0x15a2:0x0061, mx6_usb_rom.conf, 0x0525:0xb4a4, mx6_usb_sdp_spl.conf
>> 0x0525:0xa4a5, mx6_usb_uboot.conf
>
> Yeah assuming you use the Toradex branch of imx_loader currently this
> should work.
>
> Our script looks like this:
> mx6_usb_sdp_uboot
> #hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat
> valid ram areas)
> hid,1024,0x10000000,1G,0x00907000,0x31000
> #Load complete FIT image to $ramdisk_addr_r
> tezi.itb:load 0x12100000
> #Load script to $loadaddr and jump to it
> boot-sdp.scr:load 0x12000000,jump 0x12000000
>
> --
> Stefan
>
>
>>
>> Am I missing something,
>> Thanks,
>> Vincent
>>
>> 2017-09-01 22:09 GMT+02:00 Stefan Agner <stefan@agner.ch>:
>>>
>>>
>>> On September 1, 2017 12:25:44 PM PDT, Fabio Estevam <festevam@gmail.com> wrote:
>>>>On Fri, Sep 1, 2017 at 3:54 PM, Fabio Estevam <festevam@gmail.com>
>>>>wrote:
>>>>
>>>>> I have tested this method and it works, thanks.
>>>>>
>>>>> Do you plan to usptream this method?
>>>>
>>>>Or I can also put your patch as part of my series that adds SDP
>>>>support for imx6qsabresd if you prefer.
>>>
>>> Let me do a separate, I guess it could be controversial...
>>>
>>> --
>>> Stefan
>>> --
>>> Sent from my Android device with K-9 Mail. Please excuse my brevity.
>>> _______________________________________________
>>> U-Boot mailing list
>>> U-Boot at lists.denx.de
>>> https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 28+ messages in thread

* [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support
  2017-09-11 14:15               ` Vincent Prince
@ 2017-09-11 16:19                 ` Stefan Agner
  0 siblings, 0 replies; 28+ messages in thread
From: Stefan Agner @ 2017-09-11 16:19 UTC (permalink / raw)
  To: u-boot

On 2017-09-11 07:15, Vincent Prince wrote:
> Hi Stefan,
> 
> It was probably a Windows bug as it is almost working now.

Yeah with Windows the multiple re-enumeration is sometimes a bit
strange, it leads to rather long running driver search on first connect.

> I was wondering why sdp command is expecting a jump ?
> Is it necessary to jump after USB transfer, or we should download
> anything we want and jump if asked ?

You don't have to jump, you can also go back to the console using
Ctrl+C. The jump just allows you to remotely continue booting with a
specific script...

--
Stefan

> 
> Regards,
> Vincent
> 
> 
> 2017-09-08 18:37 GMT+02:00 Stefan Agner <stefan@agner.ch>:
>> Hi Vincent,
>>
>> On 2017-09-08 01:27, Vincent Prince wrote:
>>> Hi everyone,
>>>
>>> I managed to get SDP protocol to work with on my custom i.MX6 board,
>>> so big thanks to Stefan for your work!
>>>
>>> I'm now trying to load swupdate ramdisk with u-boot sdp command,
>>> without success.
>>> Is it a possible use case ?
>>
>> Yes it should work, we use the U-Boot sdp command to download a squashfs
>> based ramdisk in our Toradex Easy Installer:
>> http://developer.toradex.com/software/toradex-easy-installer
>>
>>>
>>> Here my steps:
>>>
>>> In u-boot:
>>> => sdp 0
>>>
>>> On Host,
>>> $ imx_usb
>>>
>>> config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\imx_usb.conf>
>>> vid=0x15a2 pid=0x0061 file_name=mx6_usb_rom.conf -> vid=0x0525
>>> pid=0xb4a4 file_name=mx6_usb_sdp_spl.conf
>>> vid=0x0525 pid=0xa4a5 file_name=mx6_usb_uboot.conf
>>> config file <C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf>
>>> parse C:\Users\vpr\IMXUSBLOADER2\delivery\\mx6_usb_uboot.conf
>>> Trying to open device vid=0x0525 pid=0xa4a5.........................
>>> Could not open device vid=0x0525 pid=0xa4a5
>>
>> Is VID/PID showing up in Device Manager?
>>
>> We did saw some problems with certain USB host implementation, so it
>> might be a device dependency... I would also try a different
>> machine/maybe Linux machine...
>>
>>>
>>> VID/PID in imx_usb.conf are correctly detected, and correct
>>> configuration file is launched (mx6_usb_uboot.conf),
>>> it contains:
>>>
>>> mx6_usb_sdp_uboot
>>> hid,1024,0x10000000,1G,0x00907000,0x31000
>>> test.txt:load 0x12100000
>>>
>>> My imx_usb.conf is the following:
>>>
>>> #vid:pid, config_file
>>> 0x15a2:0x0061, mx6_usb_rom.conf, 0x0525:0xb4a4, mx6_usb_sdp_spl.conf
>>> 0x0525:0xa4a5, mx6_usb_uboot.conf
>>
>> Yeah assuming you use the Toradex branch of imx_loader currently this
>> should work.
>>
>> Our script looks like this:
>> mx6_usb_sdp_uboot
>> #hid/bulk,[old_header,]max packet size, {ram start, ram size}(repeat
>> valid ram areas)
>> hid,1024,0x10000000,1G,0x00907000,0x31000
>> #Load complete FIT image to $ramdisk_addr_r
>> tezi.itb:load 0x12100000
>> #Load script to $loadaddr and jump to it
>> boot-sdp.scr:load 0x12000000,jump 0x12000000
>>
>> --
>> Stefan
>>
>>
>>>
>>> Am I missing something,
>>> Thanks,
>>> Vincent
>>>
>>> 2017-09-01 22:09 GMT+02:00 Stefan Agner <stefan@agner.ch>:
>>>>
>>>>
>>>> On September 1, 2017 12:25:44 PM PDT, Fabio Estevam <festevam@gmail.com> wrote:
>>>>>On Fri, Sep 1, 2017 at 3:54 PM, Fabio Estevam <festevam@gmail.com>
>>>>>wrote:
>>>>>
>>>>>> I have tested this method and it works, thanks.
>>>>>>
>>>>>> Do you plan to usptream this method?
>>>>>
>>>>>Or I can also put your patch as part of my series that adds SDP
>>>>>support for imx6qsabresd if you prefer.
>>>>
>>>> Let me do a separate, I guess it could be controversial...
>>>>
>>>> --
>>>> Stefan
>>>> --
>>>> Sent from my Android device with K-9 Mail. Please excuse my brevity.
>>>> _______________________________________________
>>>> U-Boot mailing list
>>>> U-Boot at lists.denx.de
>>>> https://lists.denx.de/listinfo/u-boot

^ permalink raw reply	[flat|nested] 28+ messages in thread

end of thread, other threads:[~2017-09-11 16:19 UTC | newest]

Thread overview: 28+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-16 18:00 [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefan Agner
2017-08-16 18:00 ` [U-Boot] [PATCH v2 1/8] imx: move imximage header to common location Stefan Agner
2017-08-16 18:00 ` [U-Boot] [PATCH v2 2/8] usb: gadget: add SDP driver Stefan Agner
2017-08-17 10:04   ` Łukasz Majewski
2017-08-17 13:49   ` Stefano Babic
2017-08-17 13:54     ` Marek Vasut
2017-08-17 13:59       ` Stefano Babic
2017-08-17 14:01       ` Łukasz Majewski
2017-08-16 18:00 ` [U-Boot] [PATCH v2 3/8] usb: gadget: sdp: extend images compatible for jumps Stefan Agner
2017-08-16 18:00 ` [U-Boot] [PATCH v2 4/8] cmd: add sdp command Stefan Agner
2017-08-16 18:00 ` [U-Boot] [PATCH v2 5/8] spl: add serial download protocol (SDP) support Stefan Agner
2017-08-17 10:10   ` Łukasz Majewski
2017-08-16 18:00 ` [U-Boot] [PATCH v2 6/8] doc: add Serial Download Protocol documentation Stefan Agner
2017-08-17 10:21   ` Łukasz Majewski
2017-08-16 18:00 ` [U-Boot] [PATCH v2 7/8] apalis/colibri_imx6: use independent USB PID for SPL Stefan Agner
2017-08-17 10:23   ` Łukasz Majewski
2017-08-16 18:00 ` [U-Boot] [PATCH v2 8/8] apalis/colibri_imx6: enable SDP by default Stefan Agner
2017-08-23  8:43 ` [U-Boot] [PATCH v2 0/8] imx: add USB Serial Download Protocol (SDP) support Stefano Babic
2017-08-23 12:28   ` Fabio Estevam
2017-09-01 16:48 ` Fabio Estevam
2017-09-01 18:19   ` Stefan Agner
2017-09-01 18:54     ` Fabio Estevam
2017-09-01 19:25       ` Fabio Estevam
2017-09-01 20:09         ` Stefan Agner
2017-09-08  8:27           ` Vincent Prince
2017-09-08 16:37             ` Stefan Agner
2017-09-11 14:15               ` Vincent Prince
2017-09-11 16:19                 ` Stefan Agner

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.