diff mbox

[U-Boot,3/6] usb:g_dnl:thor: THOR protocol back end support for f_usbd_thor function

Message ID 1334215049-20362-4-git-send-email-l.majewski@samsung.com
State Changes Requested
Delegated to: Marek Vasut
Headers show

Commit Message

Ɓukasz Majewski April 12, 2012, 7:17 a.m. UTC
Support for THOR download protocol. Those files are necessary for
proper f_usbd_thor function proper work.

Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Cc: Marek Vasut <marex@denx.de>
---
 drivers/usb/gadget/prot_thor.c |  247 ++++++++++++++++++++++++++++++++++++++++
 drivers/usb/gadget/prot_thor.h |  112 ++++++++++++++++++
 include/usbd_thor.h            |  108 +++++++++++++++++
 3 files changed, 467 insertions(+), 0 deletions(-)
 create mode 100644 drivers/usb/gadget/prot_thor.c
 create mode 100644 drivers/usb/gadget/prot_thor.h
 create mode 100644 include/usbd_thor.h

Comments

Marek Vasut April 14, 2012, 10 a.m. UTC | #1
Dear Lukasz Majewski,

> Support for THOR download protocol. Those files are necessary for
> proper f_usbd_thor function proper work.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---
>  drivers/usb/gadget/prot_thor.c |  247
> ++++++++++++++++++++++++++++++++++++++++ drivers/usb/gadget/prot_thor.h | 
> 112 ++++++++++++++++++
>  include/usbd_thor.h            |  108 +++++++++++++++++
>  3 files changed, 467 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/usb/gadget/prot_thor.c
>  create mode 100644 drivers/usb/gadget/prot_thor.h
>  create mode 100644 include/usbd_thor.h
> 
> diff --git a/drivers/usb/gadget/prot_thor.c
> b/drivers/usb/gadget/prot_thor.c new file mode 100644
> index 0000000..9b2610d
> --- /dev/null
> +++ b/drivers/usb/gadget/prot_thor.c
> @@ -0,0 +1,247 @@
> +/*
> + * prot_thor.c -- USB THOR Downloader protocol
> + *
> + * Copyright (C) 2012 Samsung Electronics
> + * Lukasz Majewski <l.majewski@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 
> USA + *
> + */
> +#undef DEBUG
> +#include <common.h>
> +#include <errno.h>
> +#include <g_dnl.h>
> +#include "prot_thor.h"
> +
> +static void send_rsp(const rsp_box *rsp)
> +{
> +	/* should be copy on dma duffer */
> +	memcpy(usbd_tx_data_buf, rsp, sizeof(rsp_box));
> +	pkt_upload(usbd_tx_data_buf, sizeof(rsp_box));
> +
> +	debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);

You should really unify these debug outputs

> +}
> +
> +static void send_data_rsp(s32 ack, s32 count)
> +{
> +	data_rsp_box rsp;
> +
> +	rsp.ack = ack;
> +	rsp.count = count;
> +
> +	/* should be copy on dma duffer */
> +	memcpy(usbd_tx_data_buf, &rsp, sizeof(data_rsp_box));
> +	pkt_upload(usbd_tx_data_buf, sizeof(data_rsp_box));
> +
> +	debug("-DATA RSP: %d, %d\n", ack, count);
> +}
> +
> +static int process_rqt_info(const rqt_box *rqt)
> +{
> +	rsp_box rsp = {0, };
> +
> +	rsp.rsp = rqt->rqt;
> +	rsp.rsp_data = rqt->rqt_data;
> +
> +	switch (rqt->rqt_data) {
> +	case RQT_INFO_VER_PROTOCOL:
> +		rsp.int_data[0] = VER_PROTOCOL_MAJOR;
> +		rsp.int_data[1] = VER_PROTOCOL_MINOR;
> +		break;
> +	case RQT_INIT_VER_HW:
> +		sprintf(rsp.str_data[0], "%x", checkboard());
> +		break;
> +	case RQT_INIT_VER_BOOT:
> +		sprintf(rsp.str_data[0], "%s", getenv("ver"));
> +		break;
> +	case RQT_INIT_VER_KERNEL:
> +		sprintf(rsp.str_data[0], "%s", "k unknown");
> +		break;
> +	case RQT_INIT_VER_PLATFORM:
> +		sprintf(rsp.str_data[0], "%s", "p unknown");
> +		break;
> +	case RQT_INIT_VER_CSC:
> +		sprintf(rsp.str_data[0], "%s", "c unknown");
> +		break;
> +	default:
> +		return 0;
> +	}
> +
> +	send_rsp(&rsp);
> +	return 1;
> +}
> +
> +static int process_rqt_cmd(const rqt_box *rqt)
> +{
> +	rsp_box rsp = {0, };
> +
> +	rsp.rsp = rqt->rqt;
> +	rsp.rsp_data = rqt->rqt_data;
> +
> +	switch (rqt->rqt_data) {
> +	case RQT_CMD_REBOOT:
> +		debug("TARGET RESET\n");
> +		send_rsp(&rsp);
> +		run_command("reset", 0);
> +		break;
> +	case RQT_CMD_POWEROFF:
> +	case RQT_CMD_EFSCLEAR:
> +		send_rsp(&rsp);
> +	default:
> +		printf("Command not supported -> cmd: %d\n", rqt->rqt_data);
> +		return -1;
> +	}
> +
> +	return 0;
> +}
> +
> +static unsigned long download(unsigned int total, unsigned int
> packet_size, +			      struct g_dnl *dnl)
> +{
> +	int count = 0;
> +	unsigned int rcv_cnt;
> +	static int sect_start = 92160; /* Hardcoded -> will be fixed -> */
> +	unsigned int dma_buffer_address = CONFIG_SYS_DOWN_ADDR;
> +
> +	do {
> +		if (packet_size == PKT_DOWNLOAD_SIZE)
> +			dma_buffer_address =
> +				CONFIG_SYS_DOWN_ADDR + (count * packet_size);
> +
> +		usbd_set_dma((char *) dma_buffer_address,
> +			     packet_size);
> +
> +		rcv_cnt += usbd_rx_data();
> +		debug("RCV data count: %u\n", rcv_cnt);
> +
> +		/* Store data after receiving a "chunk" packet */
> +		if (packet_size == PKT_DOWNLOAD_CHUNK_SIZE &&
> +		    (rcv_cnt % PKT_DOWNLOAD_CHUNK_SIZE) == 0) {
> +			dnl->p = (sect_start + count *
> +				  (PKT_DOWNLOAD_CHUNK_SIZE >> 9));
> +			debug("DNL STORE dnl->p: %d\n", dnl->p);
> +			dnl->store(dnl, dnl->medium);
> +		}
> +		send_data_rsp(0, ++count);
> +	} while (rcv_cnt < total);
> +
> +	debug("rcv: %d dnl: %d\n", rcv_cnt, total);
> +
> +	return rcv_cnt;
> +}
> +
> +static int process_rqt_download(const rqt_box *rqt, struct g_dnl *dnl)
> +{
> +	static unsigned long download_total_size, cnt;
> +	static char f_name[F_NAME_BUF_SIZE];
> +	rsp_box rsp = {0, };
> +	int file_type;
> +	int ret = 1;
> +
> +	rsp.rsp = rqt->rqt;
> +	rsp.rsp_data = rqt->rqt_data;
> +
> +	switch (rqt->rqt_data) {
> +	case RQT_DL_INIT:
> +		download_total_size = rqt->int_data[0];
> +
> +		debug("INIT: total %d bytes\n", rqt->int_data[0]);
> +		break;
> +	case RQT_DL_FILE_INFO:
> +		file_type = rqt->int_data[0];
> +		if (file_type == FILE_TYPE_PIT) {
> +			puts("PIT table file - not supported\n");
> +			return -1;
> +		}
> +
> +		dnl->file_size = rqt->int_data[1];
> +		memcpy(f_name, rqt->str_data[0], sizeof(f_name));
> +
> +		debug("INFO: name(%s, %d), size(%d), type(%d)\n",
> +		       f_name, 0, dnl->file_size, file_type);
> +
> +		if (dnl->file_size > PKT_DOWNLOAD_CHUNK_SIZE)
> +			dnl->packet_size = PKT_DOWNLOAD_CHUNK_SIZE;
> +		else
> +			dnl->packet_size = PKT_DOWNLOAD_SIZE;
> +
> +		printf("%s: dnl->file_size: %d dnl->packet_size: %d\n",
> +		       __func__, dnl->file_size, dnl->packet_size);

Make this debug or sanitize?

> +
> +		rsp.int_data[0] = dnl->packet_size;
> +
> +		dnl->file_name = f_name;
> +		ret = 0;
> +
> +		break;
> +	case RQT_DL_FILE_START:
> +		send_rsp(&rsp);
> +
> +		cnt = download(download_total_size, dnl->packet_size, dnl);
> +
> +		dnl->store(dnl, dnl->medium);
> +
> +		return cnt;
> +	case RQT_DL_FILE_END:
> +		debug("DL FILE_END\n");
> +		break;
> +	case RQT_DL_EXIT:
> +		debug("DL EXIT\n");
> +		ret = 0;
> +
> +		break;
> +	default:
> +		printf("Operation not supported: %d\n", rqt->rqt_data);
> +		return -1;
> +	}
> +
> +	send_rsp(&rsp);
> +	return ret;
> +}
> +
> +int process_data(struct g_dnl *dnl)
> +{
> +	rqt_box rqt;
> +	int ret = 1;
> +
> +	memset(&rqt, 0, sizeof(rqt));
> +	memcpy(&rqt, usbd_rx_data_buf, sizeof(rqt));
> +
> +	debug("+RQT: %d, %d\n", rqt.rqt, rqt.rqt_data);
> +
> +	switch (rqt.rqt) {
> +	case RQT_INFO:
> +		ret = process_rqt_info(&rqt);
> +		break;
> +	case RQT_CMD:
> +		ret = process_rqt_cmd(&rqt);
> +		break;
> +	case RQT_DL:
> +		ret = process_rqt_download(&rqt, dnl);
> +		break;
> +	case RQT_UL:
> +		puts("RQT: UPLOAD not supported!\n");
> +		break;
> +	default:
> +		printf("unknown request (%d)\n", rqt.rqt);
> +		ret = 0;
> +	}
> +
> +	/* exit code: */
> +	/* 0 - success */
> +	/* < 0 - Error code */
> +
> +	return ret;
> +}
> diff --git a/drivers/usb/gadget/prot_thor.h
> b/drivers/usb/gadget/prot_thor.h new file mode 100644
> index 0000000..6e72c75
> --- /dev/null
> +++ b/drivers/usb/gadget/prot_thor.h
> @@ -0,0 +1,112 @@
> +/*
> + * THOR protocol internals
> + *
> + * Copyright (C) 2012 Samsung Electronics
> + * Lukasz Majewski <l.majewski@samsung.com>
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License as
> + * published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
> + * MA 02111-1307 USA
> + */
> +
> +#ifndef __PROT_THOR_H_
> +#define __PROT_THOR_H_
> +
> +#include <common.h>
> +#include <linux/usb/f_usbd_thor.h>
> +
> +#define VER_PROTOCOL_MAJOR	4
> +#define VER_PROTOCOL_MINOR	0
> +
> +enum rqt {
> +	RQT_INFO = 200,
> +	RQT_CMD,
> +	RQT_DL,
> +	RQT_UL,
> +};
> +
> +enum rqt_data {
> +	/* RQT_INFO */
> +	RQT_INFO_VER_PROTOCOL = 1,
> +	RQT_INIT_VER_HW,
> +	RQT_INIT_VER_BOOT,
> +	RQT_INIT_VER_KERNEL,
> +	RQT_INIT_VER_PLATFORM,
> +	RQT_INIT_VER_CSC,
> +
> +	/* RQT_CMD */
> +	RQT_CMD_REBOOT = 1,
> +	RQT_CMD_POWEROFF,
> +	RQT_CMD_EFSCLEAR,
> +
> +	/* RQT_DL */
> +	RQT_DL_INIT = 1,
> +	RQT_DL_FILE_INFO,
> +	RQT_DL_FILE_START,
> +	RQT_DL_FILE_END,
> +	RQT_DL_EXIT,
> +
> +	/* RQT_UL */
> +	RQT_UL_INIT = 1,
> +	RQT_UL_START,
> +	RQT_UL_END,
> +	RQT_UL_EXIT,
> +};
> +
> +typedef struct _rqt_box {	/* total: 256B */
> +	s32 rqt;		/* request id */
> +	s32 rqt_data;		/* request data id */
> +	s32 int_data[14];	/* int data */
> +	char str_data[5][32];	/* string data */
> +	char md5[32];		/* md5 checksum */
> +} __attribute__((packed)) rqt_box;
> +
> +typedef struct _rsp_box {	/* total: 128B */
> +	s32 rsp;		/* response id (= request id) */
> +	s32 rsp_data;		/* response data id */
> +	s32 ack;		/* ack */
> +	s32 int_data[5];	/* int data */
> +	char str_data[3][32];	/* string data */
> +} __attribute__((packed)) rsp_box;
> +
> +typedef struct _data_rsp_box {	/* total: 8B */
> +	s32 ack;		/* response id (= request id) */
> +	s32 count;		/* response data id */
> +} __attribute__((packed)) data_rsp_box;
> +
> +enum {
> +	FILE_TYPE_NORMAL,
> +	FILE_TYPE_PIT,
> +};
> +
> +#define F_NAME_BUF_SIZE 32
> +
> +/* download packet size */
> +#define PKT_DOWNLOAD_SIZE (1 << 20) /* 1 MiB */
> +#define PKT_DOWNLOAD_CHUNK_SIZE (32 << 20) /* 32 MiB */
> +
> +int process_data(struct g_dnl *dnl);
> +
> +static inline int pkt_download(void *dest, const int size)
> +{
> +	usbd_set_dma((char *)dest, size);
> +	return usbd_rx_data();
> +}
> +
> +static inline void pkt_upload(void *src, const int size)
> +{
> +	usbd_tx_data((char *)src, size);
> +}
> +
> +#endif /*  __PROT_THOR_H__ */
> diff --git a/include/usbd_thor.h b/include/usbd_thor.h
> new file mode 100644
> index 0000000..d31bb35
> --- /dev/null
> +++ b/include/usbd_thor.h
> @@ -0,0 +1,108 @@
> +/*
> + * USB Downloader for SLP
> + *
> + * Copyright (C) 2011-2012 Samsung Electronics
> + * Minkyu Kang <mk7.kang@samsung.com>
> + * Sanghee Kim <sh0130.kim@samsung.com>
> + * Lukasz Majewski  <l.majewski@samsung.com>
> + *
> + */
> +
> +#ifndef _USBD_H_
> +#define _USBD_H_
> +
> +#define msleep(a)	udelay(a * 1000)
> +
> +/*
> + * updateflag is consist of below bit.
> + * 7: RESERVED.
> + * 6: RESERVED.
> + * 5: RESERVED.
> + * 4: SLP_MMC_RESIZE_REQUIRED
> + * 3: SLP_ROOTFS_NEW
> + * 2: SLP_KERNEL_NEW
> + * 1: SLP_SBL_NEW
> + * 0: SLP_PBL_NEW
> + */
> +enum {
> +	SLP_PBL_NEW = 0,
> +	SLP_SBL_NEW,
> +	SLP_KERNEL_NEW,
> +	SLP_ROOTFS_NEW,
> +	SLP_MMC_RESIZE_REQUIRED
> +};
> +
> +/* status definition */
> +enum {
> +	STATUS_DONE = 0,
> +	STATUS_RETRY,
> +	STATUS_ERROR,
> +};
> +
> +/* download mode definition */
> +enum {
> +	MODE_NORMAL = 0,
> +	MODE_FORCE,
> +};
> +
> +/* end mode */
> +enum {
> +	END_BOOT = 0,
> +	END_RETRY,
> +	END_FAIL,
> +	END_NORMAL,
> +};
> +/*
> + * USB Downloader Operations
> + * All functions and valuable are mandatory
> + *
> + * usb_init	: initialize the USB Controller and check the connection
> + * usb_stop	: stop and release USB
> + * send_data	: send the data (BULK ONLY!!)
> + * recv_data	: receive the data and returns received size (BULK ONLY!!)
> + * recv_setup	: setup download address, length and DMA setting for 
receive
> + * tx_data	: send data address
> + * rx_data	: receive data address
> + * tx_len	: size of send data
> + * rx_len	: size of receive data
> + * ram_addr	: address of will be stored data on RAM
> + *
> + * mmc_dev	: device number of mmc
> + * mmc_max	: number of max blocks
> + * mmc_blk	: mmc block size
> + * mmc_total	: mmc total blocks
> + */
> +struct usbd_ops {
> +	int (*usb_init)(void);
> +	void (*usb_stop)(void);
> +	void (*send_data)(char *, int);
> +	int (*recv_data)(void);
> +	void (*recv_setup)(char *, int);
> +#ifdef CONFIG_USB_S5PC_DMA
> +	void (*prepare_dma)(void * , u32 , uchar);
> +	void (*dma_done)(int);
> +#endif
> +	char *tx_data;
> +	char *rx_data;
> +	ulong tx_len;
> +	ulong rx_len;
> +	ulong ram_addr;
> +
> +	/* mmc device info */
> +	uint mmc_dev;
> +	uint mmc_max;
> +	uint mmc_blk;
> +	uint mmc_total;
> +
> +	void (*set_logo)(char *, int);
> +	void (*set_progress)(int);
> +	void (*cpu_reset)(void);
> +	void (*down_start)(void);
> +	void (*down_cancel)(int);
> +};
> +
> +/* This function is interfaced between USB Device Controller and USB
> Downloader + * Must Implementation this function at USB Controller!! */
> +struct usbd_ops *usbd_set_interface(struct usbd_ops *);
> +
> +#endif /* _USBD_H_ */
Wolfgang Denk April 14, 2012, 1:30 p.m. UTC | #2
Dear Lukasz Majewski,

In message <1334215049-20362-4-git-send-email-l.majewski@samsung.com> you wrote:
> Support for THOR download protocol. Those files are necessary for
> proper f_usbd_thor function proper work.
> 
> Signed-off-by: Lukasz Majewski <l.majewski@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Vasut <marex@denx.de>
> ---
>  drivers/usb/gadget/prot_thor.c |  247 ++++++++++++++++++++++++++++++++++++++++
>  drivers/usb/gadget/prot_thor.h |  112 ++++++++++++++++++
>  include/usbd_thor.h            |  108 +++++++++++++++++
>  3 files changed, 467 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/usb/gadget/prot_thor.c
>  create mode 100644 drivers/usb/gadget/prot_thor.h
>  create mode 100644 include/usbd_thor.h

Please see previous comments, and fix checkpatch warnings.

Best regards,

Wolfgang Denk
diff mbox

Patch

diff --git a/drivers/usb/gadget/prot_thor.c b/drivers/usb/gadget/prot_thor.c
new file mode 100644
index 0000000..9b2610d
--- /dev/null
+++ b/drivers/usb/gadget/prot_thor.c
@@ -0,0 +1,247 @@ 
+/*
+ * prot_thor.c -- USB THOR Downloader protocol
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#undef DEBUG
+#include <common.h>
+#include <errno.h>
+#include <g_dnl.h>
+#include "prot_thor.h"
+
+static void send_rsp(const rsp_box *rsp)
+{
+	/* should be copy on dma duffer */
+	memcpy(usbd_tx_data_buf, rsp, sizeof(rsp_box));
+	pkt_upload(usbd_tx_data_buf, sizeof(rsp_box));
+
+	debug("-RSP: %d, %d\n", rsp->rsp, rsp->rsp_data);
+}
+
+static void send_data_rsp(s32 ack, s32 count)
+{
+	data_rsp_box rsp;
+
+	rsp.ack = ack;
+	rsp.count = count;
+
+	/* should be copy on dma duffer */
+	memcpy(usbd_tx_data_buf, &rsp, sizeof(data_rsp_box));
+	pkt_upload(usbd_tx_data_buf, sizeof(data_rsp_box));
+
+	debug("-DATA RSP: %d, %d\n", ack, count);
+}
+
+static int process_rqt_info(const rqt_box *rqt)
+{
+	rsp_box rsp = {0, };
+
+	rsp.rsp = rqt->rqt;
+	rsp.rsp_data = rqt->rqt_data;
+
+	switch (rqt->rqt_data) {
+	case RQT_INFO_VER_PROTOCOL:
+		rsp.int_data[0] = VER_PROTOCOL_MAJOR;
+		rsp.int_data[1] = VER_PROTOCOL_MINOR;
+		break;
+	case RQT_INIT_VER_HW:
+		sprintf(rsp.str_data[0], "%x", checkboard());
+		break;
+	case RQT_INIT_VER_BOOT:
+		sprintf(rsp.str_data[0], "%s", getenv("ver"));
+		break;
+	case RQT_INIT_VER_KERNEL:
+		sprintf(rsp.str_data[0], "%s", "k unknown");
+		break;
+	case RQT_INIT_VER_PLATFORM:
+		sprintf(rsp.str_data[0], "%s", "p unknown");
+		break;
+	case RQT_INIT_VER_CSC:
+		sprintf(rsp.str_data[0], "%s", "c unknown");
+		break;
+	default:
+		return 0;
+	}
+
+	send_rsp(&rsp);
+	return 1;
+}
+
+static int process_rqt_cmd(const rqt_box *rqt)
+{
+	rsp_box rsp = {0, };
+
+	rsp.rsp = rqt->rqt;
+	rsp.rsp_data = rqt->rqt_data;
+
+	switch (rqt->rqt_data) {
+	case RQT_CMD_REBOOT:
+		debug("TARGET RESET\n");
+		send_rsp(&rsp);
+		run_command("reset", 0);
+		break;
+	case RQT_CMD_POWEROFF:
+	case RQT_CMD_EFSCLEAR:
+		send_rsp(&rsp);
+	default:
+		printf("Command not supported -> cmd: %d\n", rqt->rqt_data);
+		return -1;
+	}
+
+	return 0;
+}
+
+static unsigned long download(unsigned int total, unsigned int packet_size,
+			      struct g_dnl *dnl)
+{
+	int count = 0;
+	unsigned int rcv_cnt;
+	static int sect_start = 92160; /* Hardcoded -> will be fixed -> */
+	unsigned int dma_buffer_address = CONFIG_SYS_DOWN_ADDR;
+
+	do {
+		if (packet_size == PKT_DOWNLOAD_SIZE)
+			dma_buffer_address =
+				CONFIG_SYS_DOWN_ADDR + (count * packet_size);
+
+		usbd_set_dma((char *) dma_buffer_address,
+			     packet_size);
+
+		rcv_cnt += usbd_rx_data();
+		debug("RCV data count: %u\n", rcv_cnt);
+
+		/* Store data after receiving a "chunk" packet */
+		if (packet_size == PKT_DOWNLOAD_CHUNK_SIZE &&
+		    (rcv_cnt % PKT_DOWNLOAD_CHUNK_SIZE) == 0) {
+			dnl->p = (sect_start + count *
+				  (PKT_DOWNLOAD_CHUNK_SIZE >> 9));
+			debug("DNL STORE dnl->p: %d\n", dnl->p);
+			dnl->store(dnl, dnl->medium);
+		}
+		send_data_rsp(0, ++count);
+	} while (rcv_cnt < total);
+
+	debug("rcv: %d dnl: %d\n", rcv_cnt, total);
+
+	return rcv_cnt;
+}
+
+static int process_rqt_download(const rqt_box *rqt, struct g_dnl *dnl)
+{
+	static unsigned long download_total_size, cnt;
+	static char f_name[F_NAME_BUF_SIZE];
+	rsp_box rsp = {0, };
+	int file_type;
+	int ret = 1;
+
+	rsp.rsp = rqt->rqt;
+	rsp.rsp_data = rqt->rqt_data;
+
+	switch (rqt->rqt_data) {
+	case RQT_DL_INIT:
+		download_total_size = rqt->int_data[0];
+
+		debug("INIT: total %d bytes\n", rqt->int_data[0]);
+		break;
+	case RQT_DL_FILE_INFO:
+		file_type = rqt->int_data[0];
+		if (file_type == FILE_TYPE_PIT) {
+			puts("PIT table file - not supported\n");
+			return -1;
+		}
+
+		dnl->file_size = rqt->int_data[1];
+		memcpy(f_name, rqt->str_data[0], sizeof(f_name));
+
+		debug("INFO: name(%s, %d), size(%d), type(%d)\n",
+		       f_name, 0, dnl->file_size, file_type);
+
+		if (dnl->file_size > PKT_DOWNLOAD_CHUNK_SIZE)
+			dnl->packet_size = PKT_DOWNLOAD_CHUNK_SIZE;
+		else
+			dnl->packet_size = PKT_DOWNLOAD_SIZE;
+
+		printf("%s: dnl->file_size: %d dnl->packet_size: %d\n",
+		       __func__, dnl->file_size, dnl->packet_size);
+
+		rsp.int_data[0] = dnl->packet_size;
+
+		dnl->file_name = f_name;
+		ret = 0;
+
+		break;
+	case RQT_DL_FILE_START:
+		send_rsp(&rsp);
+
+		cnt = download(download_total_size, dnl->packet_size, dnl);
+
+		dnl->store(dnl, dnl->medium);
+
+		return cnt;
+	case RQT_DL_FILE_END:
+		debug("DL FILE_END\n");
+		break;
+	case RQT_DL_EXIT:
+		debug("DL EXIT\n");
+		ret = 0;
+
+		break;
+	default:
+		printf("Operation not supported: %d\n", rqt->rqt_data);
+		return -1;
+	}
+
+	send_rsp(&rsp);
+	return ret;
+}
+
+int process_data(struct g_dnl *dnl)
+{
+	rqt_box rqt;
+	int ret = 1;
+
+	memset(&rqt, 0, sizeof(rqt));
+	memcpy(&rqt, usbd_rx_data_buf, sizeof(rqt));
+
+	debug("+RQT: %d, %d\n", rqt.rqt, rqt.rqt_data);
+
+	switch (rqt.rqt) {
+	case RQT_INFO:
+		ret = process_rqt_info(&rqt);
+		break;
+	case RQT_CMD:
+		ret = process_rqt_cmd(&rqt);
+		break;
+	case RQT_DL:
+		ret = process_rqt_download(&rqt, dnl);
+		break;
+	case RQT_UL:
+		puts("RQT: UPLOAD not supported!\n");
+		break;
+	default:
+		printf("unknown request (%d)\n", rqt.rqt);
+		ret = 0;
+	}
+
+	/* exit code: */
+	/* 0 - success */
+	/* < 0 - Error code */
+
+	return ret;
+}
diff --git a/drivers/usb/gadget/prot_thor.h b/drivers/usb/gadget/prot_thor.h
new file mode 100644
index 0000000..6e72c75
--- /dev/null
+++ b/drivers/usb/gadget/prot_thor.h
@@ -0,0 +1,112 @@ 
+/*
+ * THOR protocol internals
+ *
+ * Copyright (C) 2012 Samsung Electronics
+ * Lukasz Majewski <l.majewski@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __PROT_THOR_H_
+#define __PROT_THOR_H_
+
+#include <common.h>
+#include <linux/usb/f_usbd_thor.h>
+
+#define VER_PROTOCOL_MAJOR	4
+#define VER_PROTOCOL_MINOR	0
+
+enum rqt {
+	RQT_INFO = 200,
+	RQT_CMD,
+	RQT_DL,
+	RQT_UL,
+};
+
+enum rqt_data {
+	/* RQT_INFO */
+	RQT_INFO_VER_PROTOCOL = 1,
+	RQT_INIT_VER_HW,
+	RQT_INIT_VER_BOOT,
+	RQT_INIT_VER_KERNEL,
+	RQT_INIT_VER_PLATFORM,
+	RQT_INIT_VER_CSC,
+
+	/* RQT_CMD */
+	RQT_CMD_REBOOT = 1,
+	RQT_CMD_POWEROFF,
+	RQT_CMD_EFSCLEAR,
+
+	/* RQT_DL */
+	RQT_DL_INIT = 1,
+	RQT_DL_FILE_INFO,
+	RQT_DL_FILE_START,
+	RQT_DL_FILE_END,
+	RQT_DL_EXIT,
+
+	/* RQT_UL */
+	RQT_UL_INIT = 1,
+	RQT_UL_START,
+	RQT_UL_END,
+	RQT_UL_EXIT,
+};
+
+typedef struct _rqt_box {	/* total: 256B */
+	s32 rqt;		/* request id */
+	s32 rqt_data;		/* request data id */
+	s32 int_data[14];	/* int data */
+	char str_data[5][32];	/* string data */
+	char md5[32];		/* md5 checksum */
+} __attribute__((packed)) rqt_box;
+
+typedef struct _rsp_box {	/* total: 128B */
+	s32 rsp;		/* response id (= request id) */
+	s32 rsp_data;		/* response data id */
+	s32 ack;		/* ack */
+	s32 int_data[5];	/* int data */
+	char str_data[3][32];	/* string data */
+} __attribute__((packed)) rsp_box;
+
+typedef struct _data_rsp_box {	/* total: 8B */
+	s32 ack;		/* response id (= request id) */
+	s32 count;		/* response data id */
+} __attribute__((packed)) data_rsp_box;
+
+enum {
+	FILE_TYPE_NORMAL,
+	FILE_TYPE_PIT,
+};
+
+#define F_NAME_BUF_SIZE 32
+
+/* download packet size */
+#define PKT_DOWNLOAD_SIZE (1 << 20) /* 1 MiB */
+#define PKT_DOWNLOAD_CHUNK_SIZE (32 << 20) /* 32 MiB */
+
+int process_data(struct g_dnl *dnl);
+
+static inline int pkt_download(void *dest, const int size)
+{
+	usbd_set_dma((char *)dest, size);
+	return usbd_rx_data();
+}
+
+static inline void pkt_upload(void *src, const int size)
+{
+	usbd_tx_data((char *)src, size);
+}
+
+#endif /*  __PROT_THOR_H__ */
diff --git a/include/usbd_thor.h b/include/usbd_thor.h
new file mode 100644
index 0000000..d31bb35
--- /dev/null
+++ b/include/usbd_thor.h
@@ -0,0 +1,108 @@ 
+/*
+ * USB Downloader for SLP
+ *
+ * Copyright (C) 2011-2012 Samsung Electronics
+ * Minkyu Kang <mk7.kang@samsung.com>
+ * Sanghee Kim <sh0130.kim@samsung.com>
+ * Lukasz Majewski  <l.majewski@samsung.com>
+ *
+ */
+
+#ifndef _USBD_H_
+#define _USBD_H_
+
+#define msleep(a)	udelay(a * 1000)
+
+/*
+ * updateflag is consist of below bit.
+ * 7: RESERVED.
+ * 6: RESERVED.
+ * 5: RESERVED.
+ * 4: SLP_MMC_RESIZE_REQUIRED
+ * 3: SLP_ROOTFS_NEW
+ * 2: SLP_KERNEL_NEW
+ * 1: SLP_SBL_NEW
+ * 0: SLP_PBL_NEW
+ */
+enum {
+	SLP_PBL_NEW = 0,
+	SLP_SBL_NEW,
+	SLP_KERNEL_NEW,
+	SLP_ROOTFS_NEW,
+	SLP_MMC_RESIZE_REQUIRED
+};
+
+/* status definition */
+enum {
+	STATUS_DONE = 0,
+	STATUS_RETRY,
+	STATUS_ERROR,
+};
+
+/* download mode definition */
+enum {
+	MODE_NORMAL = 0,
+	MODE_FORCE,
+};
+
+/* end mode */
+enum {
+	END_BOOT = 0,
+	END_RETRY,
+	END_FAIL,
+	END_NORMAL,
+};
+/*
+ * USB Downloader Operations
+ * All functions and valuable are mandatory
+ *
+ * usb_init	: initialize the USB Controller and check the connection
+ * usb_stop	: stop and release USB
+ * send_data	: send the data (BULK ONLY!!)
+ * recv_data	: receive the data and returns received size (BULK ONLY!!)
+ * recv_setup	: setup download address, length and DMA setting for receive
+ * tx_data	: send data address
+ * rx_data	: receive data address
+ * tx_len	: size of send data
+ * rx_len	: size of receive data
+ * ram_addr	: address of will be stored data on RAM
+ *
+ * mmc_dev	: device number of mmc
+ * mmc_max	: number of max blocks
+ * mmc_blk	: mmc block size
+ * mmc_total	: mmc total blocks
+ */
+struct usbd_ops {
+	int (*usb_init)(void);
+	void (*usb_stop)(void);
+	void (*send_data)(char *, int);
+	int (*recv_data)(void);
+	void (*recv_setup)(char *, int);
+#ifdef CONFIG_USB_S5PC_DMA
+	void (*prepare_dma)(void * , u32 , uchar);
+	void (*dma_done)(int);
+#endif
+	char *tx_data;
+	char *rx_data;
+	ulong tx_len;
+	ulong rx_len;
+	ulong ram_addr;
+
+	/* mmc device info */
+	uint mmc_dev;
+	uint mmc_max;
+	uint mmc_blk;
+	uint mmc_total;
+
+	void (*set_logo)(char *, int);
+	void (*set_progress)(int);
+	void (*cpu_reset)(void);
+	void (*down_start)(void);
+	void (*down_cancel)(int);
+};
+
+/* This function is interfaced between USB Device Controller and USB Downloader
+ * Must Implementation this function at USB Controller!! */
+struct usbd_ops *usbd_set_interface(struct usbd_ops *);
+
+#endif /* _USBD_H_ */