[U-Boot] [PATCH 3/6] usb:g_dnl:thor: THOR protocol back end support for f_usbd_thor function
Lukasz Majewski
l.majewski at samsung.com
Thu Apr 12 09:17:26 CEST 2012
Support for THOR download protocol. Those files are necessary for
proper f_usbd_thor function proper work.
Signed-off-by: Lukasz Majewski <l.majewski at samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park at samsung.com>
Cc: Marek Vasut <marex at 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 at 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 at 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 at samsung.com>
+ * Sanghee Kim <sh0130.kim at samsung.com>
+ * Lukasz Majewski <l.majewski at 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_ */
--
1.7.2.3
More information about the U-Boot
mailing list