From mboxrd@z Thu Jan 1 00:00:00 1970 From: Marek Vasut Date: Sat, 14 Apr 2012 12:00:30 +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-4-git-send-email-l.majewski@samsung.com> References: <1334215049-20362-1-git-send-email-l.majewski@samsung.com> <1334215049-20362-4-git-send-email-l.majewski@samsung.com> Message-ID: <201204141200.30899.marex@denx.de> List-Id: MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit To: u-boot@lists.denx.de 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 > 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); 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 > + * > + * 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_ */