Browse Source

Merge git://git.denx.de/u-boot-usb

Tom Rini 7 years ago
parent
commit
e38c66edae

+ 7 - 0
MAINTAINERS

@@ -488,6 +488,13 @@ S:	Maintained
 T:	git git://git.denx.de/u-boot-usb.git topic-xhci
 T:	git git://git.denx.de/u-boot-usb.git topic-xhci
 F:	drivers/usb/host/xhci*
 F:	drivers/usb/host/xhci*
 
 
+ROCKUSB
+M:	Eddie Cai <eddie.cai.linux@gmail.com>
+S:	Maintained
+F:	drivers/usb/gadget/f_rockusb.c
+F:	cmd/rockusb.c
+F:	doc/README.rockusb
+
 VIDEO
 VIDEO
 M:	Anatolij Gustschin <agust@denx.de>
 M:	Anatolij Gustschin <agust@denx.de>
 S:	Maintained
 S:	Maintained

+ 5 - 0
arch/arm/dts/fsl-ls1012a-qds.dtsi

@@ -121,3 +121,8 @@
 &duart0 {
 &duart0 {
 	status = "okay";
 	status = "okay";
 };
 };
+
+&usb0 {
+	status = "okay";
+	phy_type = "ulpi";
+};

+ 133 - 0
arch/arm/include/asm/arch-rockchip/f_rockusb.h

@@ -0,0 +1,133 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <eddie.cai.linux@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef _F_ROCKUSB_H_
+#define _F_ROCKUSB_H_
+#include <blk.h>
+
+#define ROCKUSB_VERSION		"0.1"
+
+#define ROCKUSB_INTERFACE_CLASS	0xff
+#define ROCKUSB_INTERFACE_SUB_CLASS	0x06
+#define ROCKUSB_INTERFACE_PROTOCOL	0x05
+
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_2_0  0x0200
+#define RX_ENDPOINT_MAXIMUM_PACKET_SIZE_1_1  0x0040
+#define TX_ENDPOINT_MAXIMUM_PACKET_SIZE      0x0040
+
+#define EP_BUFFER_SIZE			4096
+/*
+ * EP_BUFFER_SIZE must always be an integral multiple of maxpacket size
+ * (64 or 512 or 1024), else we break on certain controllers like DWC3
+ * that expect bulk OUT requests to be divisible by maxpacket size.
+ */
+
+#define RKUSB_BUF_SIZE		EP_BUFFER_SIZE * 2
+
+#define RKUSB_STATUS_IDLE			0
+#define RKUSB_STATUS_CMD			1
+#define RKUSB_STATUS_RXDATA			2
+#define RKUSB_STATUS_TXDATA			3
+#define RKUSB_STATUS_CSW			4
+#define RKUSB_STATUS_RXDATA_PREPARE		5
+#define RKUSB_STATUS_TXDATA_PREPARE		6
+
+enum rkusb_command {
+K_FW_TEST_UNIT_READY	= 0x00,
+K_FW_READ_FLASH_ID = 0x01,
+K_FW_SET_DEVICE_ID = 0x02,
+K_FW_TEST_BAD_BLOCK = 0x03,
+K_FW_READ_10 = 0x04,
+K_FW_WRITE_10 = 0x05,
+K_FW_ERASE_10 = 0x06,
+K_FW_WRITE_SPARE = 0x07,
+K_FW_READ_SPARE = 0x08,
+
+K_FW_ERASE_10_FORCE = 0x0b,
+K_FW_GET_VERSION = 0x0c,
+
+K_FW_LBA_READ_10 = 0x14,
+K_FW_LBA_WRITE_10 = 0x15,
+K_FW_ERASE_SYS_DISK = 0x16,
+K_FW_SDRAM_READ_10 = 0x17,
+K_FW_SDRAM_WRITE_10 = 0x18,
+K_FW_SDRAM_EXECUTE = 0x19,
+K_FW_READ_FLASH_INFO = 0x1A,
+K_FW_GET_CHIP_VER = 0x1B,
+K_FW_LOW_FORMAT = 0x1C,
+K_FW_SET_RESET_FLAG = 0x1E,
+K_FW_SPI_READ_10 = 0x21,
+K_FW_SPI_WRITE_10 = 0x22,
+
+K_FW_SESSION = 0X30,
+K_FW_RESET = 0xff,
+};
+
+#define CBW_DIRECTION_OUT		0x00
+#define CBW_DIRECTION_IN		0x80
+
+struct cmd_dispatch_info {
+	enum rkusb_command cmd;
+	/* call back function to handle rockusb command */
+	void (*cb)(struct usb_ep *ep, struct usb_request *req);
+};
+
+/* Bulk-only data structures */
+
+/* Command Block Wrapper */
+struct fsg_bulk_cb_wrap {
+	__le32  signature;              /* Contains 'USBC' */
+	u32     tag;                    /* Unique per command id */
+	__le32  data_transfer_length;   /* Size of the data */
+	u8      flags;                  /* Direction in bit 7 */
+	u8      lun;                    /* lun (normally 0) */
+	u8      length;                 /* Of the CDB, <= MAX_COMMAND_SIZE */
+	u8      CDB[16];                /* Command Data Block */
+};
+
+#define USB_BULK_CB_WRAP_LEN    31
+#define USB_BULK_CB_SIG         0x43425355      /* Spells out USBC */
+#define USB_BULK_IN_FLAG        0x80
+
+/* Command status Wrapper */
+struct bulk_cs_wrap {
+	__le32  signature;              /* Should = 'USBS' */
+	u32     tag;                    /* Same as original command */
+	__le32  residue;                /* Amount not transferred */
+	u8      status;                 /* See below */
+};
+
+#define USB_BULK_CS_WRAP_LEN    13
+#define USB_BULK_CS_SIG         0x53425355      /* Spells out 'USBS' */
+#define USB_STATUS_PASS         0
+#define USB_STATUS_FAIL         1
+#define USB_STATUS_PHASE_ERROR  2
+
+#define CSW_GOOD                0x00
+#define CSW_FAIL                0x01
+
+struct f_rockusb {
+	struct usb_function usb_function;
+	struct usb_ep *in_ep, *out_ep;
+	struct usb_request *in_req, *out_req;
+	char *dev_type;
+	unsigned int dev_index;
+	unsigned int tag;
+	unsigned int lba;
+	unsigned int dl_size;
+	unsigned int dl_bytes;
+	struct blk_desc *desc;
+	int reboot_flag;
+	void *buf;
+	void *buf_head;
+};
+
+/* init rockusb device, tell rockusb which device you want to read/write*/
+void rockusb_dev_init(char *dev_type, int dev_index);
+#endif /* _F_ROCKUSB_H_ */
+

+ 2 - 0
arch/arm/mach-rockchip/Kconfig

@@ -61,6 +61,8 @@ config ROCKCHIP_RK3288
 	select SPL_BOARD_INIT if SPL
 	select SPL_BOARD_INIT if SPL
 	select SUPPORT_SPL
 	select SUPPORT_SPL
 	select SPL
 	select SPL
+	imply USB_FUNCTION_ROCKUSB
+	imply CMD_ROCKUSB
 	help
 	help
 	  The Rockchip RK3288 is a ARM-based SoC with a quad-core Cortex-A17
 	  The Rockchip RK3288 is a ARM-based SoC with a quad-core Cortex-A17
 	  including NEON and GPU, 1MB L2 cache, Mali-T7 graphics, two
 	  including NEON and GPU, 1MB L2 cache, Mali-T7 graphics, two

+ 8 - 0
cmd/Kconfig

@@ -914,6 +914,14 @@ config CMD_USB_SDP
 	help
 	help
 	  Enables the command "sdp" which is used to have U-Boot emulating the
 	  Enables the command "sdp" which is used to have U-Boot emulating the
 	  Serial Download Protocol (SDP) via USB.
 	  Serial Download Protocol (SDP) via USB.
+config CMD_ROCKUSB
+	bool "rockusb"
+	depends on USB_FUNCTION_ROCKUSB
+	help
+          Rockusb protocol is widely used by Rockchip SoC based devices. It can
+	  read/write info, image to/from devices. This enable rockusb command
+	  support to communication with rockusb device. for more detail about
+	  this command, please read doc/README.rockusb.
 
 
 config CMD_USB_MASS_STORAGE
 config CMD_USB_MASS_STORAGE
 	bool "UMS usb mass storage"
 	bool "UMS usb mass storage"

+ 1 - 0
cmd/Makefile

@@ -105,6 +105,7 @@ obj-$(CONFIG_CMD_READ) += read.o
 obj-$(CONFIG_CMD_REGINFO) += reginfo.o
 obj-$(CONFIG_CMD_REGINFO) += reginfo.o
 obj-$(CONFIG_CMD_REISER) += reiser.o
 obj-$(CONFIG_CMD_REISER) += reiser.o
 obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
 obj-$(CONFIG_CMD_REMOTEPROC) += remoteproc.o
+obj-$(CONFIG_CMD_ROCKUSB) += rockusb.o
 obj-$(CONFIG_SANDBOX) += host.o
 obj-$(CONFIG_SANDBOX) += host.o
 obj-$(CONFIG_CMD_SATA) += sata.o
 obj-$(CONFIG_CMD_SATA) += sata.o
 obj-$(CONFIG_CMD_NVME) += nvme.o
 obj-$(CONFIG_CMD_NVME) += nvme.o

+ 74 - 0
cmd/rockusb.c

@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2017 Eddie Cai <eddie.cai.linux@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <console.h>
+#include <g_dnl.h>
+#include <usb.h>
+#include <asm/arch/f_rockusb.h>
+
+static int do_rockusb(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+	int controller_index, dev_index;
+	char *usb_controller;
+	char *devtype;
+	char *devnum;
+	int ret;
+
+	if (argc < 2)
+		return CMD_RET_USAGE;
+
+	usb_controller = argv[1];
+	controller_index = simple_strtoul(usb_controller, NULL, 0);
+
+	if (argc >= 4) {
+		devtype = argv[2];
+		devnum  = argv[3];
+	} else {
+		return CMD_RET_USAGE;
+	}
+	dev_index = simple_strtoul(devnum, NULL, 0);
+	rockusb_dev_init(devtype, dev_index);
+
+	ret = board_usb_init(controller_index, USB_INIT_DEVICE);
+	if (ret) {
+		printf("USB init failed: %d\n", ret);
+		return CMD_RET_FAILURE;
+	}
+
+	g_dnl_clear_detach();
+	ret = g_dnl_register("usb_dnl_rockusb");
+	if (ret)
+		return CMD_RET_FAILURE;
+
+	if (!g_dnl_board_usb_cable_connected()) {
+		puts("\rUSB cable not detected, Command exit.\n");
+		ret = CMD_RET_FAILURE;
+		goto exit;
+	}
+
+	while (1) {
+		if (g_dnl_detach())
+			break;
+		if (ctrlc())
+			break;
+		usb_gadget_handle_interrupts(controller_index);
+	}
+	ret = CMD_RET_SUCCESS;
+
+exit:
+	g_dnl_unregister();
+	g_dnl_clear_detach();
+	board_usb_cleanup(controller_index, USB_INIT_DEVICE);
+
+	return ret;
+}
+
+U_BOOT_CMD(rockusb, 4, 1, do_rockusb,
+	   "use the rockusb protocol",
+	   "<USB_controller> <devtype> <dev[:part]>  e.g. rockusb 0 mmc 0\n"
+);

+ 7 - 0
configs/chromebit_mickey_defconfig

@@ -22,6 +22,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIME=y
@@ -78,6 +79,7 @@ CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_STORAGE=y
 CONFIG_DM_VIDEO=y
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_VIDEO_ROCKCHIP=y
@@ -86,3 +88,8 @@ CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
 # CONFIG_SPL_OF_LIBFDT is not set
 # CONFIG_SPL_OF_LIBFDT is not set
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 7 - 0
configs/chromebook_jerry_defconfig

@@ -24,6 +24,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIME=y
@@ -79,6 +80,7 @@ CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_STORAGE=y
 CONFIG_DM_VIDEO=y
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_VIDEO_ROCKCHIP=y
@@ -88,3 +90,8 @@ CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
 # CONFIG_SPL_OF_LIBFDT is not set
 # CONFIG_SPL_OF_LIBFDT is not set
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 7 - 0
configs/chromebook_minnie_defconfig

@@ -23,6 +23,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SF_TEST=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIME=y
@@ -78,6 +79,7 @@ CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_STORAGE=y
 CONFIG_DM_VIDEO=y
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_VIDEO_ROCKCHIP=y
@@ -88,3 +90,8 @@ CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
 # CONFIG_SPL_OF_LIBFDT is not set
 # CONFIG_SPL_OF_LIBFDT is not set
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 9 - 0
configs/evb-rk3288_defconfig

@@ -20,6 +20,7 @@ CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIME=y
@@ -74,6 +75,14 @@ CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_VIDEO_ROCKCHIP_MAX_YRES=1200
 CONFIG_VIDEO_ROCKCHIP_MAX_YRES=1200
 CONFIG_DISPLAY_ROCKCHIP_MIPI=y
 CONFIG_DISPLAY_ROCKCHIP_MIPI=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 5 - 0
configs/fennec-rk3288_defconfig

@@ -78,3 +78,8 @@ CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 7 - 0
configs/firefly-rk3288_defconfig

@@ -21,6 +21,7 @@ CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_USB=y
 CONFIG_CMD_USB=y
+CONFIG_CMD_ROCKUSB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIME=y
@@ -80,6 +81,7 @@ CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_HOST_ETHER=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_ASIX=y
 CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_USB_FUNCTION_ROCKUSB=y
 CONFIG_DM_VIDEO=y
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_VIDEO_ROCKCHIP=y
@@ -88,3 +90,8 @@ CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 5 - 0
configs/miqi-rk3288_defconfig

@@ -83,3 +83,8 @@ CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 6 - 0
configs/phycore-rk3288_defconfig

@@ -69,6 +69,7 @@ CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_SYSRESET=y
 CONFIG_USB=y
 CONFIG_USB=y
+CONFIG_USB_DWC2=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_STORAGE=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET=y
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
@@ -81,3 +82,8 @@ CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 5 - 0
configs/popmetal-rk3288_defconfig

@@ -78,3 +78,8 @@ CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 8 - 0
configs/rock2_defconfig

@@ -20,6 +20,7 @@ CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SF=y
 CONFIG_CMD_SPI=y
 CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIME=y
@@ -70,6 +71,8 @@ CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_VENDOR_NUM=0x2207
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
 CONFIG_USB_GADGET_DWC2_OTG=y
 CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
 CONFIG_DM_VIDEO=y
 CONFIG_DM_VIDEO=y
 CONFIG_DISPLAY=y
 CONFIG_DISPLAY=y
 CONFIG_VIDEO_ROCKCHIP=y
 CONFIG_VIDEO_ROCKCHIP=y
@@ -78,3 +81,8 @@ CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 5 - 0
configs/tinker-rk3288_defconfig

@@ -81,3 +81,8 @@ CONFIG_USB_ETHER_SMSC95XX=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 25 - 0
configs/vyasa-rk3288_defconfig

@@ -17,6 +17,9 @@ CONFIG_CMD_GPIO=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_GPT=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_I2C=y
 CONFIG_CMD_MMC=y
 CONFIG_CMD_MMC=y
+CONFIG_CMD_SF=y
+CONFIG_CMD_SPI=y
+CONFIG_CMD_USB=y
 # CONFIG_CMD_SETEXPR is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_CACHE=y
 CONFIG_CMD_TIME=y
 CONFIG_CMD_TIME=y
@@ -59,6 +62,28 @@ CONFIG_DEBUG_UART_CLOCK=24000000
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_DEBUG_UART_SHIFT=2
 CONFIG_SYS_NS16550=y
 CONFIG_SYS_NS16550=y
 CONFIG_SYSRESET=y
 CONFIG_SYSRESET=y
+CONFIG_USB=y
+CONFIG_USB_DWC2=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_KEYBOARD=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_GADGET_MANUFACTURER="Rockchip"
+CONFIG_USB_GADGET_VENDOR_NUM=0x2207
+CONFIG_USB_GADGET_PRODUCT_NUM=0x320a
+CONFIG_USB_GADGET_DWC2_OTG=y
+CONFIG_USB_HOST_ETHER=y
+CONFIG_USB_ETHER_ASIX=y
+CONFIG_USB_ETHER_SMSC95XX=y
+CONFIG_DM_VIDEO=y
+CONFIG_DISPLAY=y
+CONFIG_VIDEO_ROCKCHIP=y
+CONFIG_DISPLAY_ROCKCHIP_HDMI=y
+CONFIG_CONSOLE_SCROLL_LINES=10
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_USE_TINY_PRINTF=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_CMD_DHRYSTONE=y
 CONFIG_ERRNO_STR=y
 CONFIG_ERRNO_STR=y
+CONFIG_USB_GADGET_DOWNLOAD=y
+CONFIG_USB_GADGET_VBUS_DRAW=0
+CONFIG_G_DNL_MANUFACTURER="Rockchip"
+CONFIG_G_DNL_VENDOR_NUM=0x2207
+CONFIG_G_DNL_PRODUCT_NUM=0x320a

+ 51 - 0
doc/README.rockusb

@@ -0,0 +1,51 @@
+Rockusb (Rockchip USB protocol)
+=====================================================
+
+Overview
+--------
+
+Rockusb protocol is widely used by Rockchip SoC based devices. It can
+read/write info, image to/from devices. This document briefly describes how to
+use Rockusb for upgrading firmware (e.g. kernel, u-boot, rootfs, etc.).
+
+Tools
+--------
+There are many tools can support Rockusb protocol. rkdeveloptool
+(https://github.com/rockchip-linux/rkdeveloptool) is open source,
+It is maintained by Rockchip. People don't want to build from source
+can download from here
+(https://github.com/rockchip-linux/rkbin/blob/master/tools/rkdeveloptool)
+
+Usage
+--------
+The Usage of Rockusb command is:
+
+rockusb <USB_controller> <devtype> <dev[:part]>
+
+e.g. rockusb 0 mmc 0
+
+On your U-Boot console, type this command to enter rockusb mode.
+On your host PC. use lsusb command. you should see a usb device
+using 0x2207 as its USB verdor id.
+
+for more detail about the rkdeveloptool. please read the usage.
+
+rkdeveloptool -h
+
+use rkdeveloptool wl command to write lba. BeginSec is the lba on device
+you want to write.
+
+sudo rkdeveloptool wl  <BeginSec> <File>
+
+to flash U-Boot image use below command. U-Boot binary is made by mkimage.
+see doc/README.rockchip for more detail about how to get U-Boot binary.
+
+sudo rkdeveloptool wl  64 <U-Boot binary>
+
+There are plenty of Rockusb command. but wl(write lba) and
+rd(reboot) command. These two command can let people flash
+image to device.
+
+To do
+-----
+* Fully support Rockusb protocol

+ 8 - 0
drivers/usb/gadget/Kconfig

@@ -134,6 +134,14 @@ config USB_FUNCTION_SDP
 	  allows to download images into memory and execute (jump to) them
 	  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.
 	  using the same protocol as implemented by the i.MX family's boot ROM.
 
 
+config USB_FUNCTION_ROCKUSB
+        bool "Enable USB rockusb gadget"
+        help
+          Rockusb protocol is widely used by Rockchip SoC based devices. It can
+          read/write info, image to/from devices. This enables the USB part of
+          the rockusb gadget.for more detail about Rockusb protocol, please see
+          doc/README.rockusb
+
 endif # USB_GADGET_DOWNLOAD
 endif # USB_GADGET_DOWNLOAD
 
 
 config USB_ETHER
 config USB_ETHER

+ 1 - 0
drivers/usb/gadget/Makefile

@@ -30,6 +30,7 @@ obj-$(CONFIG_USB_FUNCTION_DFU) += f_dfu.o
 obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
 obj-$(CONFIG_USB_FUNCTION_MASS_STORAGE) += f_mass_storage.o
 obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
 obj-$(CONFIG_USB_FUNCTION_FASTBOOT) += f_fastboot.o
 obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
 obj-$(CONFIG_USB_FUNCTION_SDP) += f_sdp.o
+obj-$(CONFIG_USB_FUNCTION_ROCKUSB) += f_rockusb.o
 endif
 endif
 endif
 endif
 ifdef CONFIG_USB_ETHER
 ifdef CONFIG_USB_ETHER

+ 718 - 0
drivers/usb/gadget/f_rockusb.c

@@ -0,0 +1,718 @@
+/*
+ * (C) Copyright 2017
+ *
+ * Eddie Cai <eddie.cai.linux@gmail.com>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+#include <config.h>
+#include <common.h>
+#include <errno.h>
+#include <malloc.h>
+#include <memalign.h>
+#include <linux/usb/ch9.h>
+#include <linux/usb/gadget.h>
+#include <linux/usb/composite.h>
+#include <linux/compiler.h>
+#include <version.h>
+#include <g_dnl.h>
+#include <asm/arch/f_rockusb.h>
+
+static inline struct f_rockusb *func_to_rockusb(struct usb_function *f)
+{
+	return container_of(f, struct f_rockusb, usb_function);
+}
+
+static struct usb_endpoint_descriptor fs_ep_in = {
+	.bLength            = USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType    = USB_DT_ENDPOINT,
+	.bEndpointAddress   = USB_DIR_IN,
+	.bmAttributes       = USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize     = cpu_to_le16(64),
+};
+
+static struct usb_endpoint_descriptor fs_ep_out = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(64),
+};
+
+static struct usb_endpoint_descriptor hs_ep_in = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_IN,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(512),
+};
+
+static struct usb_endpoint_descriptor hs_ep_out = {
+	.bLength		= USB_DT_ENDPOINT_SIZE,
+	.bDescriptorType	= USB_DT_ENDPOINT,
+	.bEndpointAddress	= USB_DIR_OUT,
+	.bmAttributes		= USB_ENDPOINT_XFER_BULK,
+	.wMaxPacketSize		= cpu_to_le16(512),
+};
+
+static struct usb_interface_descriptor interface_desc = {
+	.bLength		= USB_DT_INTERFACE_SIZE,
+	.bDescriptorType	= USB_DT_INTERFACE,
+	.bInterfaceNumber	= 0x00,
+	.bAlternateSetting	= 0x00,
+	.bNumEndpoints		= 0x02,
+	.bInterfaceClass	= ROCKUSB_INTERFACE_CLASS,
+	.bInterfaceSubClass	= ROCKUSB_INTERFACE_SUB_CLASS,
+	.bInterfaceProtocol	= ROCKUSB_INTERFACE_PROTOCOL,
+};
+
+static struct usb_descriptor_header *rkusb_fs_function[] = {
+	(struct usb_descriptor_header *)&interface_desc,
+	(struct usb_descriptor_header *)&fs_ep_in,
+	(struct usb_descriptor_header *)&fs_ep_out,
+};
+
+static struct usb_descriptor_header *rkusb_hs_function[] = {
+	(struct usb_descriptor_header *)&interface_desc,
+	(struct usb_descriptor_header *)&hs_ep_in,
+	(struct usb_descriptor_header *)&hs_ep_out,
+	NULL,
+};
+
+static const char rkusb_name[] = "Rockchip Rockusb";
+
+static struct usb_string rkusb_string_defs[] = {
+	[0].s = rkusb_name,
+	{  }			/* end of list */
+};
+
+static struct usb_gadget_strings stringtab_rkusb = {
+	.language	= 0x0409,	/* en-us */
+	.strings	= rkusb_string_defs,
+};
+
+static struct usb_gadget_strings *rkusb_strings[] = {
+	&stringtab_rkusb,
+	NULL,
+};
+
+static struct f_rockusb *rockusb_func;
+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req);
+static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size);
+
+struct f_rockusb *get_rkusb(void)
+{
+	struct f_rockusb *f_rkusb = rockusb_func;
+
+	if (!f_rkusb) {
+		f_rkusb = memalign(CONFIG_SYS_CACHELINE_SIZE, sizeof(*f_rkusb));
+		if (!f_rkusb)
+			return 0;
+
+		rockusb_func = f_rkusb;
+		memset(f_rkusb, 0, sizeof(*f_rkusb));
+	}
+
+	if (!f_rkusb->buf_head) {
+		f_rkusb->buf_head = memalign(CONFIG_SYS_CACHELINE_SIZE,
+					     RKUSB_BUF_SIZE);
+		if (!f_rkusb->buf_head)
+			return 0;
+
+		f_rkusb->buf = f_rkusb->buf_head;
+		memset(f_rkusb->buf_head, 0, RKUSB_BUF_SIZE);
+	}
+	return f_rkusb;
+}
+
+static struct usb_endpoint_descriptor *rkusb_ep_desc(
+struct usb_gadget *g,
+struct usb_endpoint_descriptor *fs,
+struct usb_endpoint_descriptor *hs)
+{
+	if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
+		return hs;
+	return fs;
+}
+
+static void rockusb_complete(struct usb_ep *ep, struct usb_request *req)
+{
+	int status = req->status;
+
+	if (!status)
+		return;
+	debug("status: %d ep '%s' trans: %d\n", status, ep->name, req->actual);
+}
+
+/* config the rockusb device*/
+static int rockusb_bind(struct usb_configuration *c, struct usb_function *f)
+{
+	int id;
+	struct usb_gadget *gadget = c->cdev->gadget;
+	struct f_rockusb *f_rkusb = func_to_rockusb(f);
+	const char *s;
+
+	id = usb_interface_id(c, f);
+	if (id < 0)
+		return id;
+	interface_desc.bInterfaceNumber = id;
+
+	id = usb_string_id(c->cdev);
+	if (id < 0)
+		return id;
+
+	rkusb_string_defs[0].id = id;
+	interface_desc.iInterface = id;
+
+	f_rkusb->in_ep = usb_ep_autoconfig(gadget, &fs_ep_in);
+	if (!f_rkusb->in_ep)
+		return -ENODEV;
+	f_rkusb->in_ep->driver_data = c->cdev;
+
+	f_rkusb->out_ep = usb_ep_autoconfig(gadget, &fs_ep_out);
+	if (!f_rkusb->out_ep)
+		return -ENODEV;
+	f_rkusb->out_ep->driver_data = c->cdev;
+
+	f->descriptors = rkusb_fs_function;
+
+	if (gadget_is_dualspeed(gadget)) {
+		hs_ep_in.bEndpointAddress = fs_ep_in.bEndpointAddress;
+		hs_ep_out.bEndpointAddress = fs_ep_out.bEndpointAddress;
+		f->hs_descriptors = rkusb_hs_function;
+	}
+
+	s = env_get("serial#");
+	if (s)
+		g_dnl_set_serialnumber((char *)s);
+
+	return 0;
+}
+
+static void rockusb_unbind(struct usb_configuration *c, struct usb_function *f)
+{
+	/* clear the configuration*/
+	memset(rockusb_func, 0, sizeof(*rockusb_func));
+}
+
+static void rockusb_disable(struct usb_function *f)
+{
+	struct f_rockusb *f_rkusb = func_to_rockusb(f);
+
+	usb_ep_disable(f_rkusb->out_ep);
+	usb_ep_disable(f_rkusb->in_ep);
+
+	if (f_rkusb->out_req) {
+		free(f_rkusb->out_req->buf);
+		usb_ep_free_request(f_rkusb->out_ep, f_rkusb->out_req);
+		f_rkusb->out_req = NULL;
+	}
+	if (f_rkusb->in_req) {
+		free(f_rkusb->in_req->buf);
+		usb_ep_free_request(f_rkusb->in_ep, f_rkusb->in_req);
+		f_rkusb->in_req = NULL;
+	}
+	if (f_rkusb->buf_head) {
+		free(f_rkusb->buf_head);
+		f_rkusb->buf_head = NULL;
+		f_rkusb->buf = NULL;
+	}
+}
+
+static struct usb_request *rockusb_start_ep(struct usb_ep *ep)
+{
+	struct usb_request *req;
+
+	req = usb_ep_alloc_request(ep, 0);
+	if (!req)
+		return NULL;
+
+	req->length = EP_BUFFER_SIZE;
+	req->buf = memalign(CONFIG_SYS_CACHELINE_SIZE, EP_BUFFER_SIZE);
+	if (!req->buf) {
+		usb_ep_free_request(ep, req);
+		return NULL;
+	}
+	memset(req->buf, 0, req->length);
+
+	return req;
+}
+
+static int rockusb_set_alt(struct usb_function *f, unsigned int interface,
+			   unsigned int alt)
+{
+	int ret;
+	struct usb_composite_dev *cdev = f->config->cdev;
+	struct usb_gadget *gadget = cdev->gadget;
+	struct f_rockusb *f_rkusb = func_to_rockusb(f);
+	const struct usb_endpoint_descriptor *d;
+
+	debug("%s: func: %s intf: %d alt: %d\n",
+	      __func__, f->name, interface, alt);
+
+	d = rkusb_ep_desc(gadget, &fs_ep_out, &hs_ep_out);
+	ret = usb_ep_enable(f_rkusb->out_ep, d);
+	if (ret) {
+		printf("failed to enable out ep\n");
+		return ret;
+	}
+
+	f_rkusb->out_req = rockusb_start_ep(f_rkusb->out_ep);
+	if (!f_rkusb->out_req) {
+		printf("failed to alloc out req\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	f_rkusb->out_req->complete = rx_handler_command;
+
+	d = rkusb_ep_desc(gadget, &fs_ep_in, &hs_ep_in);
+	ret = usb_ep_enable(f_rkusb->in_ep, d);
+	if (ret) {
+		printf("failed to enable in ep\n");
+		goto err;
+	}
+
+	f_rkusb->in_req = rockusb_start_ep(f_rkusb->in_ep);
+	if (!f_rkusb->in_req) {
+		printf("failed alloc req in\n");
+		ret = -EINVAL;
+		goto err;
+	}
+	f_rkusb->in_req->complete = rockusb_complete;
+
+	ret = usb_ep_queue(f_rkusb->out_ep, f_rkusb->out_req, 0);
+	if (ret)
+		goto err;
+
+	return 0;
+err:
+	rockusb_disable(f);
+	return ret;
+}
+
+static int rockusb_add(struct usb_configuration *c)
+{
+	struct f_rockusb *f_rkusb = get_rkusb();
+	int status;
+
+	debug("%s: cdev: 0x%p\n", __func__, c->cdev);
+
+	f_rkusb->usb_function.name = "f_rockusb";
+	f_rkusb->usb_function.bind = rockusb_bind;
+	f_rkusb->usb_function.unbind = rockusb_unbind;
+	f_rkusb->usb_function.set_alt = rockusb_set_alt;
+	f_rkusb->usb_function.disable = rockusb_disable;
+	f_rkusb->usb_function.strings = rkusb_strings;
+
+	status = usb_add_function(c, &f_rkusb->usb_function);
+	if (status) {
+		free(f_rkusb);
+		rockusb_func = f_rkusb;
+	}
+	return status;
+}
+
+void rockusb_dev_init(char *dev_type, int dev_index)
+{
+	struct f_rockusb *f_rkusb = get_rkusb();
+
+	f_rkusb->dev_type = dev_type;
+	f_rkusb->dev_index = dev_index;
+}
+
+DECLARE_GADGET_BIND_CALLBACK(usb_dnl_rockusb, rockusb_add);
+
+static int rockusb_tx_write(const char *buffer, unsigned int buffer_size)
+{
+	struct usb_request *in_req = rockusb_func->in_req;
+	int ret;
+
+	memcpy(in_req->buf, buffer, buffer_size);
+	in_req->length = buffer_size;
+	usb_ep_dequeue(rockusb_func->in_ep, in_req);
+	ret = usb_ep_queue(rockusb_func->in_ep, in_req, 0);
+	if (ret)
+		printf("Error %d on queue\n", ret);
+	return 0;
+}
+
+static int rockusb_tx_write_str(const char *buffer)
+{
+	return rockusb_tx_write(buffer, strlen(buffer));
+}
+
+#ifdef DEBUG
+static void printcbw(char *buf)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
+				 sizeof(struct fsg_bulk_cb_wrap));
+
+	memcpy((char *)cbw, buf, USB_BULK_CB_WRAP_LEN);
+
+	debug("cbw: signature:%x\n", cbw->signature);
+	debug("cbw: tag=%x\n", cbw->tag);
+	debug("cbw: data_transfer_length=%d\n", cbw->data_transfer_length);
+	debug("cbw: flags=%x\n", cbw->flags);
+	debug("cbw: lun=%d\n", cbw->lun);
+	debug("cbw: length=%d\n", cbw->length);
+	debug("cbw: ucOperCode=%x\n", cbw->CDB[0]);
+	debug("cbw: ucReserved=%x\n", cbw->CDB[1]);
+	debug("cbw: dwAddress:%x %x %x %x\n", cbw->CDB[5], cbw->CDB[4],
+	      cbw->CDB[3], cbw->CDB[2]);
+	debug("cbw: ucReserved2=%x\n", cbw->CDB[6]);
+	debug("cbw: uslength:%x %x\n", cbw->CDB[8], cbw->CDB[7]);
+}
+
+static void printcsw(char *buf)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw,
+				 sizeof(struct bulk_cs_wrap));
+	memcpy((char *)csw, buf, USB_BULK_CS_WRAP_LEN);
+	debug("csw: signature:%x\n", csw->signature);
+	debug("csw: tag:%x\n", csw->tag);
+	debug("csw: residue:%x\n", csw->residue);
+	debug("csw: status:%x\n", csw->status);
+}
+#endif
+
+static int rockusb_tx_write_csw(u32 tag, int residue, u8 status, int size)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct bulk_cs_wrap, csw,
+				 sizeof(struct bulk_cs_wrap));
+	csw->signature = cpu_to_le32(USB_BULK_CS_SIG);
+	csw->tag = tag;
+	csw->residue = cpu_to_be32(residue);
+	csw->status = status;
+#ifdef DEBUG
+	printcsw((char *)&csw);
+#endif
+	return rockusb_tx_write((char *)csw, size);
+}
+
+static unsigned int rx_bytes_expected(struct usb_ep *ep)
+{
+	struct f_rockusb *f_rkusb = get_rkusb();
+	int rx_remain = f_rkusb->dl_size - f_rkusb->dl_bytes;
+	unsigned int rem;
+	unsigned int maxpacket = ep->maxpacket;
+
+	if (rx_remain <= 0)
+		return 0;
+	else if (rx_remain > EP_BUFFER_SIZE)
+		return EP_BUFFER_SIZE;
+
+	rem = rx_remain % maxpacket;
+	if (rem > 0)
+		rx_remain = rx_remain + (maxpacket - rem);
+
+	return rx_remain;
+}
+
+/* usb_request complete call back to handle down load image */
+static void rx_handler_dl_image(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_rockusb *f_rkusb = get_rkusb();
+	unsigned int transfer_size = 0;
+	const unsigned char *buffer = req->buf;
+	unsigned int buffer_size = req->actual;
+
+	transfer_size = f_rkusb->dl_size - f_rkusb->dl_bytes;
+	if (!f_rkusb->desc) {
+		char *type = f_rkusb->dev_type;
+		int index = f_rkusb->dev_index;
+
+		f_rkusb->desc = blk_get_dev(type, index);
+		if (!f_rkusb->desc ||
+		    f_rkusb->desc->type == DEV_TYPE_UNKNOWN) {
+			puts("invalid mmc device\n");
+			rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
+					     USB_BULK_CS_WRAP_LEN);
+			return;
+		}
+	}
+
+	if (req->status != 0) {
+		printf("Bad status: %d\n", req->status);
+		rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
+				     USB_BULK_CS_WRAP_LEN);
+		return;
+	}
+
+	if (buffer_size < transfer_size)
+		transfer_size = buffer_size;
+
+	memcpy((void *)f_rkusb->buf, buffer, transfer_size);
+	f_rkusb->dl_bytes += transfer_size;
+	int blks = 0, blkcnt = transfer_size  / 512;
+
+	debug("dl %x bytes, %x blks, write lba %x, dl_size:%x, dl_bytes:%x, ",
+	      transfer_size, blkcnt, f_rkusb->lba, f_rkusb->dl_size,
+	      f_rkusb->dl_bytes);
+	blks = blk_dwrite(f_rkusb->desc, f_rkusb->lba, blkcnt, f_rkusb->buf);
+	if (blks != blkcnt) {
+		printf("failed writing to device %s: %d\n", f_rkusb->dev_type,
+		       f_rkusb->dev_index);
+		rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_FAIL,
+				     USB_BULK_CS_WRAP_LEN);
+		return;
+	}
+	f_rkusb->lba += blkcnt;
+
+	/* Check if transfer is done */
+	if (f_rkusb->dl_bytes >= f_rkusb->dl_size) {
+		req->complete = rx_handler_command;
+		req->length = EP_BUFFER_SIZE;
+		f_rkusb->buf = f_rkusb->buf_head;
+		printf("transfer 0x%x bytes done\n", f_rkusb->dl_size);
+		f_rkusb->dl_size = 0;
+		rockusb_tx_write_csw(f_rkusb->tag, 0, CSW_GOOD,
+				     USB_BULK_CS_WRAP_LEN);
+	} else {
+		req->length = rx_bytes_expected(ep);
+		if (f_rkusb->buf == f_rkusb->buf_head)
+			f_rkusb->buf = f_rkusb->buf_head + EP_BUFFER_SIZE;
+		else
+			f_rkusb->buf = f_rkusb->buf_head;
+
+		debug("remain %x bytes, %x sectors\n", req->length,
+		      req->length / 512);
+	}
+
+	req->actual = 0;
+	usb_ep_queue(ep, req, 0);
+}
+
+static void cb_test_unit_ready(struct usb_ep *ep, struct usb_request *req)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
+				 sizeof(struct fsg_bulk_cb_wrap));
+
+	memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+
+	rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length,
+			     CSW_GOOD, USB_BULK_CS_WRAP_LEN);
+}
+
+static void cb_read_storage_id(struct usb_ep *ep, struct usb_request *req)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
+				 sizeof(struct fsg_bulk_cb_wrap));
+	char emmc_id[] = "EMMC ";
+
+	printf("read storage id\n");
+	memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	rockusb_tx_write_str(emmc_id);
+	rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD,
+			     USB_BULK_CS_WRAP_LEN);
+}
+
+static void cb_write_lba(struct usb_ep *ep, struct usb_request *req)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
+				 sizeof(struct fsg_bulk_cb_wrap));
+	struct f_rockusb *f_rkusb = get_rkusb();
+	int sector_count;
+
+	memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	sector_count = (int)get_unaligned_be16(&cbw->CDB[7]);
+	f_rkusb->lba = get_unaligned_be32(&cbw->CDB[2]);
+	f_rkusb->dl_size = sector_count * 512;
+	f_rkusb->dl_bytes = 0;
+	f_rkusb->tag = cbw->tag;
+	debug("require write %x bytes, %x sectors to lba %x\n",
+	      f_rkusb->dl_size, sector_count, f_rkusb->lba);
+
+	if (f_rkusb->dl_size == 0)  {
+		rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length,
+				     CSW_FAIL, USB_BULK_CS_WRAP_LEN);
+	} else {
+		req->complete = rx_handler_dl_image;
+		req->length = rx_bytes_expected(ep);
+	}
+}
+
+void __weak rkusb_set_reboot_flag(int flag)
+{
+	struct f_rockusb *f_rkusb = get_rkusb();
+
+	printf("rockkusb set reboot flag: %d\n", f_rkusb->reboot_flag);
+}
+
+static void compl_do_reset(struct usb_ep *ep, struct usb_request *req)
+{
+	struct f_rockusb *f_rkusb = get_rkusb();
+
+	rkusb_set_reboot_flag(f_rkusb->reboot_flag);
+	do_reset(NULL, 0, 0, NULL);
+}
+
+static void cb_reboot(struct usb_ep *ep, struct usb_request *req)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
+				 sizeof(struct fsg_bulk_cb_wrap));
+	struct f_rockusb *f_rkusb = get_rkusb();
+
+	f_rkusb->reboot_flag = 0;
+	memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	f_rkusb->reboot_flag = cbw->CDB[1];
+	rockusb_func->in_req->complete = compl_do_reset;
+	rockusb_tx_write_csw(cbw->tag, cbw->data_transfer_length, CSW_GOOD,
+			     USB_BULK_CS_WRAP_LEN);
+}
+
+static void cb_not_support(struct usb_ep *ep, struct usb_request *req)
+{
+	ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
+				 sizeof(struct fsg_bulk_cb_wrap));
+
+	memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+	printf("Rockusb command %x not support yet\n", cbw->CDB[0]);
+	rockusb_tx_write_csw(cbw->tag, 0, CSW_FAIL, USB_BULK_CS_WRAP_LEN);
+}
+
+static const struct cmd_dispatch_info cmd_dispatch_info[] = {
+	{
+		.cmd = K_FW_TEST_UNIT_READY,
+		.cb = cb_test_unit_ready,
+	},
+	{
+		.cmd = K_FW_READ_FLASH_ID,
+		.cb = cb_read_storage_id,
+	},
+	{
+		.cmd = K_FW_SET_DEVICE_ID,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_TEST_BAD_BLOCK,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_WRITE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_ERASE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_WRITE_SPARE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_READ_SPARE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_ERASE_10_FORCE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_GET_VERSION,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_LBA_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_LBA_WRITE_10,
+		.cb = cb_write_lba,
+	},
+	{
+		.cmd = K_FW_ERASE_SYS_DISK,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SDRAM_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SDRAM_WRITE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SDRAM_EXECUTE,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_READ_FLASH_INFO,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_GET_CHIP_VER,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_LOW_FORMAT,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SET_RESET_FLAG,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SPI_READ_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SPI_WRITE_10,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_SESSION,
+		.cb = cb_not_support,
+	},
+	{
+		.cmd = K_FW_RESET,
+		.cb = cb_reboot,
+	},
+};
+
+static void rx_handler_command(struct usb_ep *ep, struct usb_request *req)
+{
+	void (*func_cb)(struct usb_ep *ep, struct usb_request *req) = NULL;
+
+	ALLOC_CACHE_ALIGN_BUFFER(struct fsg_bulk_cb_wrap, cbw,
+				 sizeof(struct fsg_bulk_cb_wrap));
+	char *cmdbuf = req->buf;
+	int i;
+
+	if (req->status || req->length == 0)
+		return;
+
+	memcpy((char *)cbw, req->buf, USB_BULK_CB_WRAP_LEN);
+#ifdef DEBUG
+	printcbw(req->buf);
+#endif
+
+	for (i = 0; i < ARRAY_SIZE(cmd_dispatch_info); i++) {
+		if (cmd_dispatch_info[i].cmd == cbw->CDB[0]) {
+			func_cb = cmd_dispatch_info[i].cb;
+			break;
+		}
+	}
+
+	if (!func_cb) {
+		printf("unknown command: %s\n", (char *)req->buf);
+		rockusb_tx_write_str("FAILunknown command");
+	} else {
+		if (req->actual < req->length) {
+			u8 *buf = (u8 *)req->buf;
+
+			buf[req->actual] = 0;
+			func_cb(ep, req);
+		} else {
+			puts("buffer overflow\n");
+			rockusb_tx_write_str("FAILbuffer overflow");
+		}
+	}
+
+	*cmdbuf = '\0';
+	req->actual = 0;
+	usb_ep_queue(ep, req, 0);
+}

+ 6 - 0
drivers/usb/host/Kconfig

@@ -186,6 +186,12 @@ config USB_EHCI_GENERIC
 	---help---
 	---help---
 	  Enables support for generic EHCI controller.
 	  Enables support for generic EHCI controller.
 
 
+config USB_EHCI_FSL
+	bool  "Support for FSL on-chip EHCI USB controller"
+	default n
+	select  CONFIG_EHCI_HCD_INIT_AFTER_RESET
+	---help---
+	  Enables support for the on-chip EHCI controller on FSL chips.
 endif # USB_EHCI_HCD
 endif # USB_EHCI_HCD
 
 
 config USB_OHCI_HCD
 config USB_OHCI_HCD

+ 4 - 4
drivers/usb/host/ehci-fsl.c

@@ -106,14 +106,14 @@ static int ehci_fsl_probe(struct udevice *dev)
 	ehci = (struct usb_ehci *)priv->hcd_base;
 	ehci = (struct usb_ehci *)priv->hcd_base;
 	hccr = (struct ehci_hccr *)(&ehci->caplength);
 	hccr = (struct ehci_hccr *)(&ehci->caplength);
 	hcor = (struct ehci_hcor *)
 	hcor = (struct ehci_hcor *)
-		((u32)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+		((void *)hccr + HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
 
 	if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0)
 	if (ehci_fsl_init(priv, ehci, hccr, hcor) < 0)
 		return -ENXIO;
 		return -ENXIO;
 
 
-	debug("ehci-fsl: init hccr %x and hcor %x hc_length %d\n",
-	      (u32)hccr, (u32)hcor,
-	      (u32)HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
+	debug("ehci-fsl: init hccr %p and hcor %p hc_length %d\n",
+	      (void *)hccr, (void *)hcor,
+	      HC_LENGTH(ehci_readl(&hccr->cr_capbase)));
 
 
 	return ehci_register(dev, hccr, hcor, &fsl_ehci_ops, 0, USB_INIT_HOST);
 	return ehci_register(dev, hccr, hcor, &fsl_ehci_ops, 0, USB_INIT_HOST);
 }
 }

+ 6 - 3
drivers/usb/musb-new/sunxi.c

@@ -312,13 +312,16 @@ static int musb_usb_probe(struct udevice *dev)
 {
 {
 	struct musb_host_data *host = dev_get_priv(dev);
 	struct musb_host_data *host = dev_get_priv(dev);
 	struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
 	struct usb_bus_priv *priv = dev_get_uclass_priv(dev);
+	void *base = dev_read_addr_ptr(dev);
 	int ret;
 	int ret;
 
 
+	if (!base)
+		return -EINVAL;
+
 	priv->desc_before_addr = true;
 	priv->desc_before_addr = true;
 
 
 #ifdef CONFIG_USB_MUSB_HOST
 #ifdef CONFIG_USB_MUSB_HOST
-	host->host = musb_init_controller(&musb_plat, NULL,
-					  (void *)SUNXI_USB0_BASE);
+	host->host = musb_init_controller(&musb_plat, NULL, base);
 	if (!host->host)
 	if (!host->host)
 		return -EIO;
 		return -EIO;
 
 
@@ -326,7 +329,7 @@ static int musb_usb_probe(struct udevice *dev)
 	if (!ret)
 	if (!ret)
 		printf("Allwinner mUSB OTG (Host)\n");
 		printf("Allwinner mUSB OTG (Host)\n");
 #else
 #else
-	ret = musb_register(&musb_plat, NULL, (void *)SUNXI_USB0_BASE);
+	ret = musb_register(&musb_plat, NULL, base);
 	if (!ret)
 	if (!ret)
 		printf("Allwinner mUSB OTG (Peripheral)\n");
 		printf("Allwinner mUSB OTG (Peripheral)\n");
 #endif
 #endif

+ 0 - 11
include/configs/ls1012aqds.h

@@ -107,17 +107,6 @@
 #define CONFIG_SF_DEFAULT_BUS        1
 #define CONFIG_SF_DEFAULT_BUS        1
 #define CONFIG_SF_DEFAULT_CS         0
 #define CONFIG_SF_DEFAULT_CS         0
 
 
-/*
-* USB
-*/
-/* EHCI Support - disbaled by default */
-/*#define CONFIG_HAS_FSL_DR_USB*/
-
-#ifdef CONFIG_HAS_FSL_DR_USB
-#define CONFIG_USB_EHCI_FSL
-#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
-#endif
-
 /*  MMC  */
 /*  MMC  */
 #ifdef CONFIG_MMC
 #ifdef CONFIG_MMC
 #define CONFIG_FSL_ESDHC
 #define CONFIG_FSL_ESDHC

+ 0 - 11
include/configs/ls1021aqds.h

@@ -393,17 +393,6 @@ unsigned long get_board_ddr_clk(void);
 #endif
 #endif
 #endif
 #endif
 
 
-/*
- * USB
- */
-/* EHCI Support - disbaled by default */
-/*#define CONFIG_HAS_FSL_DR_USB*/
-
-#ifdef CONFIG_HAS_FSL_DR_USB
-#define CONFIG_USB_EHCI_FSL
-#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
-#endif
-
 /*
 /*
  * Video
  * Video
  */
  */

+ 0 - 20
include/configs/ls1021atwr.h

@@ -24,26 +24,6 @@
 #define CONFIG_SYS_INIT_RAM_ADDR	OCRAM_BASE_ADDR
 #define CONFIG_SYS_INIT_RAM_ADDR	OCRAM_BASE_ADDR
 #define CONFIG_SYS_INIT_RAM_SIZE	OCRAM_SIZE
 #define CONFIG_SYS_INIT_RAM_SIZE	OCRAM_SIZE
 
 
-/*
- * USB
- */
-
-/*
- * EHCI Support - disbaled by default as
- * there is no signal coming out of soc on
- * this board for this controller. However,
- * the silicon still has this controller,
- * and anyone can use this controller by
- * taking signals out on their board.
- */
-
-/*#define CONFIG_HAS_FSL_DR_USB*/
-
-#ifdef CONFIG_HAS_FSL_DR_USB
-#define CONFIG_USB_EHCI_FSL
-#define CONFIG_EHCI_HCD_INIT_AFTER_RESET
-#endif
-
 #define CONFIG_SYS_CLK_FREQ		100000000
 #define CONFIG_SYS_CLK_FREQ		100000000
 #define CONFIG_DDR_CLK_FREQ		100000000
 #define CONFIG_DDR_CLK_FREQ		100000000