From mboxrd@z Thu Jan 1 00:00:00 1970 From: Lukasz Majewski Date: Thu, 12 Apr 2012 09:17:26 +0200 Subject: [U-Boot] [PATCH 3/6] usb:g_dnl:thor: THOR protocol back end support for f_usbd_thor function In-Reply-To: <1334215049-20362-1-git-send-email-l.majewski@samsung.com> References: <1334215049-20362-1-git-send-email-l.majewski@samsung.com> Message-ID: <1334215049-20362-4-git-send-email-l.majewski@samsung.com> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de Support for THOR download protocol. Those files are necessary for proper f_usbd_thor function proper work. Signed-off-by: Lukasz Majewski Signed-off-by: Kyungmin Park Cc: Marek Vasut --- 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 + * + * 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 +#include +#include +#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 + * + * 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 +#include + +#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 + * Sanghee Kim + * Lukasz Majewski + * + */ + +#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