
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_ */