gk7205v200-uboot/cmd/usbtftp.c
2025-08-07 17:13:54 +08:00

420 lines
9.2 KiB
C
Executable File

/*
* Copyright (c) Hunan Goke,Chengdu Goke,Shandong Goke. 2021. All rights reserved.
*/
#include "../drivers/usb/gadget/udc3/usb3_drv.h"
#include "common.h"
#include <common.h>
#include <malloc.h>
#include <command.h>
#include <spi.h>
#include <spi_flash.h>
#include <jffs2/jffs2.h>
#include <linux/mtd/mtd.h>
static unsigned int usb_open_flag = 0;
static char command[256] = {0};
static int udc_request(void)
{
extern int get_eventbuf_count(usb3_device_t *dev);
extern void dcache_disable(void);
extern void usb3_common_init(usb3_device_t *dev, volatile uint8_t *base);
extern void phy_usb_init(int index);
extern void usb3_init(usb3_device_t *dev);
extern void dcache_enable(void);
extern int usb_stop(void);
extern void usb3_handle_event(usb3_device_t *dev);
dcache_disable();
usb3_device_t *usb3_dev;
struct usb_device_descriptor *usb3_dev_desc;
usb3_dev = (usb3_device_t *)malloc(sizeof(usb3_device_t));
if (usb3_dev == NULL) {
debug("usb3_dev: out of memory\n");
return -ENOMEM;
}
usb3_memset((void *)usb3_dev, 0, sizeof(usb3_device_t));
usb3_dev_desc = (usb_device_descriptor_t *)malloc(sizeof(
struct usb_device_descriptor));
usb3_pcd_t *pcd = &usb3_dev->pcd;
usb3_pcd_ep_t *ep = &pcd->in_ep;
usb3_pcd_req_t *req = &ep->req;
req->bufdma = (uint8_t *)malloc(512);
usb_info("size of usb3_dev %d\n", sizeof(*usb3_dev));
usb3_dev->base = (volatile uint8_t *)USB3_CTRL_REG_BASE;
uint8_t string_manu[] = {'G', 0, 'o', 0, 'k', 0, 'e', 0};
uint8_t string_prod[] = {'U', 0, 'S', 0, 'B', 0, 'B', 0, 'u', 0, 'r', 0, 'n', 0};
usb3_dev->string_manu_len = sizeof(string_manu);
usb3_dev->string_prod_len = sizeof(string_prod);
usb3_dev->dev_desc = usb3_dev_desc;
memcpy(usb3_dev->string_manu, string_manu, usb3_dev->string_manu_len);
memcpy(usb3_dev->string_prod, string_prod, usb3_dev->string_prod_len);
usb3_dev->pcd.ep0_setup_desc = (usb3_dma_desc_t *)
((uintptr_t)(usb3_dev->pcd.ep0_setup + 15) & (uint32_t)(~15));
usb3_dev->pcd.ep0_in_desc = (usb3_dma_desc_t *)
((uintptr_t)(usb3_dev->pcd.ep0_in + 15) & (uint32_t)(~15));
usb3_dev->pcd.ep0_out_desc = (usb3_dma_desc_t *)
((uintptr_t)(usb3_dev->pcd.ep0_out + 15) & (uint32_t)(~15));
usb3_dev->pcd.in_ep.ep_desc = (usb3_dma_desc_t *)
((uintptr_t)(usb3_dev->pcd.in_ep.epx_desc + 15) & (uint32_t)(~15));
usb3_dev->pcd.out_ep.ep_desc = (usb3_dma_desc_t *)
((uintptr_t)(usb3_dev->pcd.out_ep.epx_desc + 15) & (uint32_t)(~15));
/* Release usb3.0 controller */
phy_usb_init(0);
/* Get usb3.0 version number */
usb3_dev->snpsid = usb3_rd32((volatile uint32_t *)
(usb3_dev->base + USB3_CORE_REG_BASE + USB3_CORE_GSNPSID_REG_OFFSET));
/* Initialize usb3.0 core */
usb3_common_init(usb3_dev, usb3_dev->base + USB3_CORE_REG_BASE);
/* Initialize usb3.0 pcd */
usb3_init(usb3_dev);
usb_info("usb init done\n");
ulong time_start = get_timer(0);
/* inital the send buffer */
extern char tx_state[200];
memset(tx_state, 0, sizeof(tx_state));
while (usb_open_flag) {
usb3_handle_event(usb3_dev);
if (0 != get_eventbuf_count(usb3_dev)) {
time_start = get_timer(0);
continue;
}
if (get_timer(time_start) > 5000) {
printf("the USB has no data for about 5s, stop the USB Device\n");
break;
}
}
usb_open_flag = 0;
phy_usb_init(0);
usb_stop();
if (req->bufdma != NULL) {
free(req->bufdma);
req->bufdma = NULL;
}
if (usb3_dev_desc != NULL) {
free(usb3_dev_desc);
usb3_dev_desc = NULL;
}
if (usb3_dev != NULL) {
free(usb3_dev);
usb3_dev = NULL;
}
dcache_enable();
return 0;
}
static int do_usbtftp_download(int argc, char *const argv[])
{
if (strlen(argv[1]) + strlen(argv[2]) + 15 >= 256)
return -1;
char *endp = NULL;
(void)simple_strtoul(argv[1], &endp, 16);
if (*argv[1] == 0 || *endp != 0)
return -1;
if (usb_open_flag == 1) {
printf("usbtftp is running.\n");
return 1;
}
memset(command, 0, sizeof(command));
sprintf(command, "usbtftp %s %s", argv[1], argv[2]);
usb_open_flag = 1;
(void)udc_request();
return 0;
}
#ifndef CONFIG_MMC
static struct spi_flash *spiflash = NULL;
static int do_flash_probe(void)
{
unsigned int bus = CONFIG_SF_DEFAULT_BUS;
unsigned int cs = CONFIG_SF_DEFAULT_CS;
unsigned int speed = CONFIG_SF_DEFAULT_SPEED;
unsigned int mode = CONFIG_SF_DEFAULT_MODE;
#ifdef CONFIG_DM_SPI_FLASH
struct udevice *new = NULL;
struct udevice *bus_dev = NULL;
int ret;
/* In DM mode defaults will be taken from DT */
speed = 0, mode = 0;
#else
struct spi_flash *new = NULL;
#endif
#ifdef CONFIG_DM_SPI_FLASH
/* Remove the old device, otherwise probe will just be a nop */
ret = spi_find_bus_and_cs(bus, cs, &bus_dev, &new);
if (!ret)
device_remove(new);
spiflash = NULL;
ret = spi_flash_probe_bus_cs(bus, cs, speed, mode, &new);
if (ret) {
printf("Failed to initialize SPI flash at %u:%u (error %d)\n", bus, cs, ret);
return 1;
}
spiflash = dev_get_uclass_priv(new);
#else
if (spiflash)
spi_flash_free(spiflash);
new = spi_flash_probe(bus, cs, speed, mode);
if (!new) {
printf("Failed to initialize SPI flash at %u:%u\n", bus, cs);
return 1;
}
spiflash = new;
#endif
return 0;
}
static unsigned char *membuf = NULL;
static unsigned int mem_len = 0;
static int do_spi_flash_read(int argc, char *const argv[])
{
unsigned long size;
char *endp = NULL;
int ret;
int dev = 0;
loff_t offset, len, maxsize;
if (argc < 3)
return -1;
if (spiflash == NULL) {
printf("error, spiflash is null!\n");
return -1;
}
if (mtd_arg_off(argv[1], &dev, &offset, &len, &maxsize, MTD_DEV_TYPE_NOR,
spiflash->size)) {
return -1;
}
size = simple_strtoul(argv[3], &endp, 16);
if (*argv[3] == 0 || *endp != 0)
return -1;
/* Consistency checking */
if (offset + size > spiflash->size) {
printf("ERROR: attempting %s past flash size (%#x)\n", argv[0], spiflash->size);
return 1;
}
len = size;
membuf = (unsigned char *)malloc(size);
if (!membuf) {
puts("Failed to malloc memory\n");
return 1;
}
ret = spi_flash_read(spiflash, offset, len, (void *)membuf);
mem_len = size;
return ret == 0 ? 0 : 1;
}
static int frame_count = 0;
#define FRAME_LENGTH (200)
static int do_upload(uint8_t *const buff, unsigned int *bufflen)
{
unsigned char *head = (unsigned char *)buff;
*bufflen = 0;
/* the tail frame has been sent, send again */
if (frame_count == -1) {
head[0] = 0xED;
*bufflen = 1;
return 0;
}
if (frame_count == 0) {
head[0] = 0xFE;
head[1] = (mem_len >> 24) & 0xFF;
head[2] = (mem_len >> 16) & 0xFF;
head[3] = (mem_len >> 8) & 0xFF;
head[4] = mem_len & 0xFF;
head[5] = (FRAME_LENGTH >> 24) & 0xFF;
head[6] = (FRAME_LENGTH >> 16) & 0xFF;
head[7] = (FRAME_LENGTH >> 8) & 0xFF;
head[8] = FRAME_LENGTH & 0xFF;
*bufflen = 9;
frame_count++;
return 0;
}
if (FRAME_LENGTH * frame_count <= mem_len) {
head[0] = 0xDA;
*bufflen = FRAME_LENGTH;
} else if ((FRAME_LENGTH * frame_count > mem_len) &&
(FRAME_LENGTH * (frame_count - 1) < mem_len)) {
head[0] = 0xDA;
*bufflen = mem_len - FRAME_LENGTH * (frame_count - 1);
} else if ((FRAME_LENGTH * (frame_count - 1) >= mem_len)) {
head[0] = 0xED;
*bufflen = 0;
frame_count = -1;
}
if (*bufflen != 0) {
memcpy(head + 1, membuf +
FRAME_LENGTH * (frame_count - 1), *bufflen);
frame_count++;
}
/* cmd is one byte */
*bufflen = *bufflen + 1;
return 0;
}
#endif
static int do_usbtftp_upload(int argc, char *const argv[])
{
if (strlen(argv[1]) + strlen(argv[2]) + 15 >= 256)
return -1;
if (usb_open_flag == 1) {
printf("usbtftp is running.\n");
return -1;
}
#ifndef CONFIG_MMC
int ret;
ret = do_flash_probe();
if (ret != 0)
goto done;
ret = do_spi_flash_read(argc, argv);
if (ret != 0)
goto done;
frame_count = 0;
typedef int (*USB3_HANDLE_REQUEST)(uint8_t *const buff,
unsigned int *bufflen);
extern void SetUSB3CallBackFunc(USB3_HANDLE_REQUEST func);
SetUSB3CallBackFunc(do_upload);
memset(command, 0, sizeof(command));
sprintf(command, "usbtftp %s %s %s", argv[1], argv[2], argv[3]);
usb_open_flag = 1;
(void)udc_request();
frame_count = 0;
SetUSB3CallBackFunc(NULL);
done:
#ifdef CONFIG_DM_SPI_FLASH
spiflash = NULL;
#else
if (spiflash) {
spi_flash_free(spiflash);
spiflash = NULL;
}
#endif
if (membuf) {
free(membuf);
membuf = NULL;
}
mem_len = 0;
return ret;
#else
printf("usbtftp upoload can not support emmc now.\n");
return -1;
#endif
}
static int do_usbtftp(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
int ret = 0;
if (strncmp(argv[1], "start", 5) == 0) {
if (usb_open_flag == 0)
goto usage;
printf(" %s\n", command);
goto done;
}
if (strncmp(argv[1], "error", 5) == 0) {
if (usb_open_flag == 0)
goto usage;
usb_open_flag = 0;
printf("usbtftp error\n");
goto done;
}
if (strncmp(argv[1], "end", 3) == 0) {
if (usb_open_flag == 0)
goto usage;
usb_open_flag = 0;
printf("usbtftp end\n");
goto done;
}
if (argc == 3) {
ret = do_usbtftp_download(argc, argv);
goto done;
}
if (argc == 4) {
ret = do_usbtftp_upload(argc, argv);
goto done;
}
usage:
return CMD_RET_USAGE;
done:
return ret;
}
U_BOOT_CMD(
usbtftp, 4, 0, do_usbtftp,
"download or upload image using USB protocol",
"command to download or upload image using USB protocol\n"
"usbtftp addr file len - upload `len(hex)' bytes starting at addr to file\n"
"usbtftp addr file - download file to addr\n"
);