mirror of
git://projects.qi-hardware.com/xburst-tools.git
synced 2024-11-29 10:50:39 +02:00
more cleanup
This commit is contained in:
parent
836fade868
commit
9aa52b7947
@ -31,76 +31,69 @@
|
|||||||
#include "ingenic_usb.h"
|
#include "ingenic_usb.h"
|
||||||
#include "usb_boot_defines.h"
|
#include "usb_boot_defines.h"
|
||||||
|
|
||||||
struct hand hand;
|
|
||||||
struct sdram_in sdram_in;
|
struct sdram_in sdram_in;
|
||||||
|
|
||||||
unsigned int total_size;
|
unsigned int total_size;
|
||||||
static char code_buf[4 * 512 * 1024];
|
static char code_buf[4 * 512 * 1024];
|
||||||
static char ret[8];
|
static char ret[8];
|
||||||
|
|
||||||
|
static int load_file(struct ingenic_dev *dev, const char *file_path, char *buf)
|
||||||
static int load_file(struct ingenic_dev *ingenic_dev, const char *file_path)
|
|
||||||
{
|
{
|
||||||
struct stat fstat;
|
struct stat fstat;
|
||||||
int fd, status, res = -1;
|
int fd, status;
|
||||||
|
|
||||||
status = stat(file_path, &fstat);
|
status = stat(file_path, &fstat);
|
||||||
|
|
||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
fprintf(stderr, "Error - can't get file size from '%s': %s\n",
|
fprintf(stderr, "Error - can't get file size from '%s': %s\n",
|
||||||
file_path, strerror(errno));
|
file_path, strerror(errno));
|
||||||
goto out;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
ingenic_dev->file_len = fstat.st_size;
|
|
||||||
ingenic_dev->file_buff = code_buf;
|
|
||||||
|
|
||||||
fd = open(file_path, O_RDONLY);
|
fd = open(file_path, O_RDONLY);
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "Error - can't open file '%s': %s\n",
|
fprintf(stderr, "Error - can't open file '%s': %s\n",
|
||||||
file_path, strerror(errno));
|
file_path, strerror(errno));
|
||||||
goto out;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = read(fd, ingenic_dev->file_buff, ingenic_dev->file_len);
|
status = read(fd, buf, fstat.st_size);
|
||||||
|
|
||||||
if (status < (int)ingenic_dev->file_len) {
|
if (status < (int)fstat.st_size) {
|
||||||
fprintf(stderr, "Error - can't read file '%s': %s\n",
|
fprintf(stderr, "Error - can't read file '%s': %s\n",
|
||||||
file_path, strerror(errno));
|
file_path, strerror(errno));
|
||||||
goto close;
|
goto close;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* write args to code */
|
/* write args to code */
|
||||||
memcpy(ingenic_dev->file_buff + 8, &hand.fw_args,
|
memcpy(buf + 8, &dev->config.fw_args, sizeof(struct fw_args));
|
||||||
sizeof(struct fw_args));
|
|
||||||
|
|
||||||
res = 1;
|
|
||||||
|
|
||||||
close:
|
close:
|
||||||
close(fd);
|
close(fd);
|
||||||
out:
|
|
||||||
return res;
|
return fstat.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* after upload stage2. must init device */
|
/* after upload stage2. must init device */
|
||||||
void init_cfg(struct ingenic_dev *dev)
|
void init_cfg(struct ingenic_dev *dev)
|
||||||
{
|
{
|
||||||
if (usb_get_ingenic_cpu(dev) < 3) {
|
if (usb_get_ingenic_cpu(dev) < 3) {
|
||||||
printf(" XBurst CPU not booted yet, boot it first!\n");
|
printf("XBurst CPU not booted yet, boot it first!\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_send_data_to_ingenic(dev, (char*)&hand, sizeof(hand)) != 1)
|
if (usb_send_data_to_ingenic(dev, (char*)&dev->config, sizeof(dev->config))
|
||||||
|
< 0)
|
||||||
goto xout;
|
goto xout;
|
||||||
|
|
||||||
if (usb_ingenic_configration(dev, DS_hand) != 1)
|
if (usb_ingenic_configration(dev, DS_hand) < 0)
|
||||||
goto xout;
|
goto xout;
|
||||||
|
|
||||||
if (usb_read_data_from_ingenic(dev, ret, 8) != 1)
|
if (usb_read_data_from_ingenic(dev, ret, 8) < 0)
|
||||||
goto xout;
|
goto xout;
|
||||||
|
|
||||||
printf(" Configuring XBurst CPU succeeded.\n");
|
printf("Configuring XBurst CPU succeeded.\n");
|
||||||
return;
|
return;
|
||||||
xout:
|
xout:
|
||||||
printf("Configuring XBurst CPU failed.\n");
|
printf("Configuring XBurst CPU failed.\n");
|
||||||
@ -109,57 +102,62 @@ xout:
|
|||||||
int boot(struct ingenic_dev *dev, const char *stage1_path, const char *stage2_path)
|
int boot(struct ingenic_dev *dev, const char *stage1_path, const char *stage2_path)
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
int size;
|
||||||
|
|
||||||
status = usb_get_ingenic_cpu(dev);
|
status = usb_get_ingenic_cpu(dev);
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case 1: /* Jz4740v1 */
|
case INGENIC_CPU_JZ4740V1:
|
||||||
status = 0;
|
status = 0;
|
||||||
hand.fw_args.cpu_id = 0x4740;
|
dev->config.fw_args.cpu_id = 0x4740;
|
||||||
break;
|
break;
|
||||||
case 2: /* Jz4750v1 */
|
case INGENIC_CPU_JZ4750V1:
|
||||||
status = 0;
|
status = 0;
|
||||||
hand.fw_args.cpu_id = 0x4750;
|
dev->config.fw_args.cpu_id = 0x4750;
|
||||||
break;
|
break;
|
||||||
case 3: /* Boot4740 */
|
case INGENIC_CPU_JZ4740:
|
||||||
status = 1;
|
status = 1;
|
||||||
hand.fw_args.cpu_id = 0x4740;
|
dev->config.fw_args.cpu_id = 0x4740;
|
||||||
break;
|
break;
|
||||||
case 4: /* Boot4750 */
|
case INGENIC_CPU_JZ4750:
|
||||||
status = 1;
|
status = 1;
|
||||||
hand.fw_args.cpu_id = 0x4750;
|
dev->config.fw_args.cpu_id = 0x4750;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 1;
|
return (status < 0) ? status : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
printf(" Already booted.\n");
|
printf("Already booted.\n");
|
||||||
return 1;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
printf(" CPU not yet booted, now booting...\n");
|
printf("CPU not yet booted, now booting...\n");
|
||||||
|
|
||||||
/* now we upload the boot stage1 */
|
/* now we upload the boot stage1 */
|
||||||
printf(" Loading stage1 from '%s'\n", stage1_path);
|
printf("Loading stage1 from '%s'\n", stage1_path);
|
||||||
if (load_file(dev, stage1_path) < 1)
|
size = load_file(dev, stage1_path, code_buf);
|
||||||
return -1;
|
if (size < 0)
|
||||||
|
return size;
|
||||||
|
|
||||||
if (usb_ingenic_upload(dev, 1) < 1)
|
if (usb_ingenic_upload(dev, 1, code_buf, size) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* now we upload the boot stage2 */
|
/* now we upload the boot stage2 */
|
||||||
usleep(100);
|
usleep(100);
|
||||||
printf(" Loading stage2 from '%s'\n", stage2_path);
|
printf("Loading stage2 from '%s'\n", stage2_path);
|
||||||
if (load_file(dev, stage2_path) < 1)
|
size = load_file(dev, stage2_path, code_buf);
|
||||||
|
if (size < 0) {
|
||||||
|
printf("FOOBAR");
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usb_ingenic_upload(dev, 2, code_buf, size) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (usb_ingenic_upload(dev, 2) < 1)
|
printf("Booted successfully!\n");
|
||||||
return -1;
|
|
||||||
|
|
||||||
printf(" Booted successfully!\n");
|
|
||||||
}
|
}
|
||||||
usleep(100);
|
usleep(100);
|
||||||
init_cfg(dev);
|
init_cfg(dev);
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -171,51 +169,50 @@ int debug_memory(struct ingenic_dev *dev, int obj, unsigned int start, unsigned
|
|||||||
|
|
||||||
tmp = usb_get_ingenic_cpu(dev);
|
tmp = usb_get_ingenic_cpu(dev);
|
||||||
if (tmp > 2) {
|
if (tmp > 2) {
|
||||||
printf(" This command only run under UNBOOT state!\n");
|
printf("This command only run under UNBOOT state!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tmp) {
|
switch (tmp) {
|
||||||
case 1:
|
case 1:
|
||||||
tmp = 0;
|
dev->config.fw_args.cpu_id = 0x4740;
|
||||||
hand.fw_args.cpu_id = 0x4740;
|
|
||||||
break;
|
break;
|
||||||
case 2:
|
case 2:
|
||||||
tmp = 0;
|
dev->config.fw_args.cpu_id = 0x4750;
|
||||||
hand.fw_args.cpu_id = 0x4750;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hand.fw_args.debug_ops = 1;/* tell device it's memory debug */
|
dev->config.fw_args.debug_ops = 1;/* tell device it's memory debug */
|
||||||
hand.fw_args.start = start;
|
dev->config.fw_args.start = start;
|
||||||
|
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
hand.fw_args.size = total_size;
|
dev->config.fw_args.size = total_size;
|
||||||
else
|
else
|
||||||
hand.fw_args.size = size;
|
dev->config.fw_args.size = size;
|
||||||
|
|
||||||
printf(" Now test memory from 0x%x to 0x%x: \n",
|
printf("Now test memory from 0x%x to 0x%x: \n",
|
||||||
start, start + hand.fw_args.size);
|
start, start + dev->config.fw_args.size);
|
||||||
|
|
||||||
if (load_file(dev, STAGE1_FILE_PATH) < 1)
|
size = load_file(dev, STAGE1_FILE_PATH, code_buf);
|
||||||
return -1;
|
if (size < 0)
|
||||||
if (usb_ingenic_upload(dev, 1) < 1)
|
return size;
|
||||||
|
if (usb_ingenic_upload(dev, 1, code_buf, size) < 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
usleep(100);
|
usleep(100);
|
||||||
usb_read_data_from_ingenic(dev, buffer, 8);
|
usb_read_data_from_ingenic(dev, buffer, 8);
|
||||||
if (buffer[0] != 0)
|
if (buffer[0] != 0)
|
||||||
printf(" Test memory fail! Last error address is 0x%x !\n",
|
printf("Test memory fail! Last error address is 0x%x !\n",
|
||||||
buffer[0]);
|
buffer[0]);
|
||||||
else
|
else
|
||||||
printf(" Test memory pass!\n");
|
printf("Test memory pass!\n");
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int debug_go(struct ingenic_dev *dev, size_t argc, char *argv[])
|
int debug_go(struct ingenic_dev *dev, size_t argc, char *argv[])
|
||||||
{
|
{
|
||||||
unsigned int addr,obj;
|
unsigned int addr, obj;
|
||||||
if (argc < 3) {
|
if (argc < 3) {
|
||||||
printf(" Usage: go (1) (2) \n"
|
printf(" Usage: go (1) (2) \n"
|
||||||
" 1:start SDRAM address\n"
|
" 1:start SDRAM address\n"
|
||||||
@ -226,7 +223,7 @@ int debug_go(struct ingenic_dev *dev, size_t argc, char *argv[])
|
|||||||
addr = strtoul(argv[1], NULL, 0);
|
addr = strtoul(argv[1], NULL, 0);
|
||||||
obj = atoi(argv[2]);
|
obj = atoi(argv[2]);
|
||||||
|
|
||||||
printf(" Executing No.%d device at address 0x%x\n", obj, addr);
|
printf("Executing No.%d device at address 0x%x\n", obj, addr);
|
||||||
|
|
||||||
if (usb_ingenic_start(dev, VR_PROGRAM_START2, addr) < 1)
|
if (usb_ingenic_start(dev, VR_PROGRAM_START2, addr) < 1)
|
||||||
return -1;
|
return -1;
|
||||||
@ -237,12 +234,12 @@ int debug_go(struct ingenic_dev *dev, size_t argc, char *argv[])
|
|||||||
int sdram_load(struct ingenic_dev *dev, struct sdram_in *sdram_in)
|
int sdram_load(struct ingenic_dev *dev, struct sdram_in *sdram_in)
|
||||||
{
|
{
|
||||||
if (usb_get_ingenic_cpu(dev) < 3) {
|
if (usb_get_ingenic_cpu(dev) < 3) {
|
||||||
printf(" Device unboot! Boot it first!\n");
|
printf("Device unboot! Boot it first!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sdram_in->length > (unsigned int) MAX_LOAD_SIZE) {
|
if (sdram_in->length > (unsigned int) MAX_LOAD_SIZE) {
|
||||||
printf(" Image length too long!\n");
|
printf("Image length too long!\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,7 +249,7 @@ int sdram_load(struct ingenic_dev *dev, struct sdram_in *sdram_in)
|
|||||||
/* usb_ingenic_sdram_ops(dev, sdram_in);*/
|
/* usb_ingenic_sdram_ops(dev, sdram_in);*/
|
||||||
|
|
||||||
usb_read_data_from_ingenic(dev, ret, 8);
|
usb_read_data_from_ingenic(dev, ret, 8);
|
||||||
printf(" Load last address at 0x%x\n",
|
printf("Load last address at 0x%x\n",
|
||||||
((ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0)));
|
((ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0)));
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -283,8 +280,8 @@ int sdram_load_file(struct ingenic_dev *dev, struct sdram_in *sdram_in, char *fi
|
|||||||
j = flen % MAX_LOAD_SIZE;
|
j = flen % MAX_LOAD_SIZE;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
|
|
||||||
printf(" Total size to send in byte is :%d\n", flen);
|
printf("Total size to send in byte is :%d\n", flen);
|
||||||
printf(" Loading data to SDRAM :\n");
|
printf("Loading data to SDRAM :\n");
|
||||||
|
|
||||||
for (k = 0; k < m; k++) {
|
for (k = 0; k < m; k++) {
|
||||||
status = read(fd, sdram_in->buf, MAX_LOAD_SIZE);
|
status = read(fd, sdram_in->buf, MAX_LOAD_SIZE);
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "usb_boot_defines.h"
|
#include "usb_boot_defines.h"
|
||||||
#include "ingenic_usb.h"
|
#include "ingenic_usb.h"
|
||||||
#include "cmd.h"
|
#include "cmd.h"
|
||||||
@ -323,6 +326,11 @@ static size_t command_parse(char *cmd, char *argv[])
|
|||||||
return argc;
|
return argc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int nand_read_callback(void *data, const char *buf, size_t size)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int handle_nand_read(size_t argc, char *argv[])
|
static int handle_nand_read(size_t argc, char *argv[])
|
||||||
{
|
{
|
||||||
int mode;
|
int mode;
|
||||||
@ -354,27 +362,37 @@ static int handle_nand_read(size_t argc, char *argv[])
|
|||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return nand_read(&ingenic_dev, nand_idx, mode, start_page, num_pages, 0);
|
return nand_read(&ingenic_dev, nand_idx, mode, start_page, num_pages, 0,
|
||||||
|
nand_read_callback, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int nand_dump_callback(void *data, const char *buf, size_t size)
|
||||||
|
{
|
||||||
|
int fd = *(int*)(data);
|
||||||
|
|
||||||
|
write(fd, buf, size);
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_nand_dump(size_t argc, char *argv[])
|
static int handle_nand_dump(size_t argc, char *argv[])
|
||||||
{
|
{
|
||||||
int mode;
|
int mode;
|
||||||
uint32_t start_page, num_pages;
|
uint32_t start_page, num_pages;
|
||||||
unsigned int device_idx;
|
|
||||||
uint8_t nand_idx;
|
uint8_t nand_idx;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
int fd;
|
||||||
|
|
||||||
if (argc != 5) {
|
if (argc != 5) {
|
||||||
printf("Usage: %s <start page> <length> <filename> <mode>\n", argv[0]);
|
printf("Usage: %s <start page> <length> <filename> <mode>\n", argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strcmp(argv[5], "-n") == 0) {
|
if (strcmp(argv[4], "-n") == 0) {
|
||||||
mode = NAND_READ;
|
mode = NAND_READ;
|
||||||
} else if (strcmp(argv[5], "-e") == 0) {
|
} else if (strcmp(argv[4], "-e") == 0) {
|
||||||
mode = NAND_READ_RAW;
|
mode = NAND_READ_RAW;
|
||||||
} else if (strcmp(argv[5], "-o") == 0) {
|
} else if (strcmp(argv[4], "-o") == 0) {
|
||||||
mode = NAND_READ_OOB;
|
mode = NAND_READ_OOB;
|
||||||
} else {
|
} else {
|
||||||
return -1;
|
return -1;
|
||||||
@ -382,13 +400,19 @@ static int handle_nand_dump(size_t argc, char *argv[])
|
|||||||
|
|
||||||
start_page = parse_number_print_error(argv[1], &err);
|
start_page = parse_number_print_error(argv[1], &err);
|
||||||
num_pages = parse_number_print_error(argv[2], &err);
|
num_pages = parse_number_print_error(argv[2], &err);
|
||||||
device_idx = parse_number_print_error(argv[3], &err);
|
/* device_idx = parse_number_print_error(argv[3], &err);*/
|
||||||
nand_idx = parse_number_print_error(argv[4], &err);
|
nand_idx = 0;
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
return nand_read(&ingenic_dev, nand_idx, mode, start_page, num_pages, 0);
|
fd = creat(argv[3], 0644);
|
||||||
|
|
||||||
|
err = nand_read(&ingenic_dev, nand_idx, mode, start_page, num_pages, 0,
|
||||||
|
nand_dump_callback, &fd);
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int handle_nand_query(size_t argc, char *argv[])
|
static int handle_nand_query(size_t argc, char *argv[])
|
||||||
@ -417,7 +441,7 @@ static int handle_nand_prog(size_t argc, char *argv[])
|
|||||||
uint8_t nand_idx, mode = -1;
|
uint8_t nand_idx, mode = -1;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (argc != 5) {
|
if (argc != 6) {
|
||||||
printf("Usage: %s <start page> <filename> <device index> <nand chip index> <mode>\n", argv[0]);
|
printf("Usage: %s <start page> <filename> <device index> <nand chip index> <mode>\n", argv[0]);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -213,5 +213,5 @@ int parse_configure(struct hand *hand, char * file_path)
|
|||||||
if (check_dump_cfg(hand) < 1)
|
if (check_dump_cfg(hand) < 1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
|
|||||||
(usb_dev->descriptor.idProduct == PRODUCT_ID)) {
|
(usb_dev->descriptor.idProduct == PRODUCT_ID)) {
|
||||||
ingenic_dev->usb_dev = usb_dev;
|
ingenic_dev->usb_dev = usb_dev;
|
||||||
count++;
|
count++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -63,27 +63,27 @@ static int get_ingenic_interface(struct ingenic_dev *ingenic_dev)
|
|||||||
usb_config_desc = &ingenic_dev->usb_dev->config[config_index];
|
usb_config_desc = &ingenic_dev->usb_dev->config[config_index];
|
||||||
|
|
||||||
if (!usb_config_desc)
|
if (!usb_config_desc)
|
||||||
return 0;
|
return -1;
|
||||||
|
|
||||||
for (if_index = 0; if_index < usb_config_desc->bNumInterfaces;
|
for (if_index = 0; if_index < usb_config_desc->bNumInterfaces;
|
||||||
if_index++) {
|
if_index++) {
|
||||||
usb_if = &usb_config_desc->interface[if_index];
|
usb_if = &usb_config_desc->interface[if_index];
|
||||||
|
|
||||||
if (!usb_if)
|
if (!usb_if)
|
||||||
return 0;
|
return -1;
|
||||||
|
|
||||||
for (alt_index = 0; alt_index < usb_if->num_altsetting;
|
for (alt_index = 0; alt_index < usb_if->num_altsetting;
|
||||||
alt_index++) {
|
alt_index++) {
|
||||||
usb_if_desc = &usb_if->altsetting[alt_index];
|
usb_if_desc = &usb_if->altsetting[alt_index];
|
||||||
|
|
||||||
if (!usb_if_desc)
|
if (!usb_if_desc)
|
||||||
return 0;
|
return -1;
|
||||||
|
|
||||||
if ((usb_if_desc->bInterfaceClass == 0xff) &&
|
if ((usb_if_desc->bInterfaceClass == 0xff) &&
|
||||||
(usb_if_desc->bInterfaceSubClass == 0)) {
|
(usb_if_desc->bInterfaceSubClass == 0)) {
|
||||||
ingenic_dev->interface =
|
ingenic_dev->interface =
|
||||||
usb_if_desc->bInterfaceNumber;
|
usb_if_desc->bInterfaceNumber;
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,7 +94,8 @@ static int get_ingenic_interface(struct ingenic_dev *ingenic_dev)
|
|||||||
|
|
||||||
int usb_ingenic_init(struct ingenic_dev *ingenic_dev)
|
int usb_ingenic_init(struct ingenic_dev *ingenic_dev)
|
||||||
{
|
{
|
||||||
int num_ingenic, status = -1;
|
int num_ingenic;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
memset(ingenic_dev, 0, sizeof(struct ingenic_dev));
|
memset(ingenic_dev, 0, sizeof(struct ingenic_dev));
|
||||||
|
|
||||||
@ -107,319 +108,310 @@ int usb_ingenic_init(struct ingenic_dev *ingenic_dev)
|
|||||||
|
|
||||||
if (num_ingenic == 0) {
|
if (num_ingenic == 0) {
|
||||||
fprintf(stderr, "Error - no XBurst device found\n");
|
fprintf(stderr, "Error - no XBurst device found\n");
|
||||||
goto out;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (num_ingenic > 1) {
|
if (num_ingenic > 1) {
|
||||||
fprintf(stderr, "Error - too many XBurst devices found: %i\n",
|
fprintf(stderr, "Error - too many XBurst devices found: %d\n",
|
||||||
num_ingenic);
|
num_ingenic);
|
||||||
goto out;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
ingenic_dev->usb_handle = usb_open(ingenic_dev->usb_dev);
|
ingenic_dev->usb_handle = usb_open(ingenic_dev->usb_dev);
|
||||||
if (!ingenic_dev->usb_handle) {
|
if (!ingenic_dev->usb_handle) {
|
||||||
fprintf(stderr, "Error - can't open XBurst device: %s\n",
|
fprintf(stderr, "Error - can't open XBurst device: %s\n",
|
||||||
usb_strerror());
|
usb_strerror());
|
||||||
goto out;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (get_ingenic_interface(ingenic_dev) < 1) {
|
ret = get_ingenic_interface(ingenic_dev);
|
||||||
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error - can't find XBurst interface\n");
|
fprintf(stderr, "Error - can't find XBurst interface\n");
|
||||||
goto out;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_claim_interface(ingenic_dev->usb_handle, ingenic_dev->interface)
|
ret = usb_claim_interface(ingenic_dev->usb_handle, ingenic_dev->interface);
|
||||||
< 0) {
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error - can't claim XBurst interface: %s\n",
|
fprintf(stderr, "Error - can't claim XBurst interface: %s\n",
|
||||||
usb_strerror());
|
usb_strerror());
|
||||||
goto out;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = 1;
|
return 0;
|
||||||
|
err:
|
||||||
out:
|
return ret;
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev)
|
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
|
char buf[9];
|
||||||
memset(&ingenic_dev->cpu_info_buff, 0,
|
|
||||||
ARRAY_SIZE(ingenic_dev->cpu_info_buff));
|
|
||||||
|
|
||||||
sleep(1);
|
sleep(1);
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
ret = usb_control_msg(ingenic_dev->usb_handle,
|
||||||
/* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
|
/* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR |USB_RECIP_DEVICE,
|
||||||
/* bRequest */ VR_GET_CPU_INFO,
|
/* bRequest */ VR_GET_CPU_INFO,
|
||||||
/* wValue */ 0,
|
/* wValue */ 0,
|
||||||
/* wIndex */ 0,
|
/* wIndex */ 0,
|
||||||
/* Data */ ingenic_dev->cpu_info_buff,
|
/* Data */ buf,
|
||||||
/* wLength */ 8,
|
/* wLength */ 8,
|
||||||
USB_TIMEOUT);
|
USB_TIMEOUT);
|
||||||
|
|
||||||
if (status != sizeof(ingenic_dev->cpu_info_buff) - 1 ) {
|
if (ret != 8) {
|
||||||
fprintf(stderr, "Error - "
|
fprintf(stderr, "Error - "
|
||||||
"can't retrieve XBurst CPU information: %i\n", status);
|
"can't retrieve XBurst CPU information: %d\n", ret);
|
||||||
return status;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ingenic_dev->cpu_info_buff[8] = '\0';
|
buf[8] = '\0';
|
||||||
printf(" CPU data: %s\n", ingenic_dev->cpu_info_buff);
|
printf(" CPU data: %s\n", buf);
|
||||||
|
|
||||||
if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4740V1")) return 1;
|
if (!strcmp(buf, "JZ4740V1"))
|
||||||
if (!strcmp(ingenic_dev->cpu_info_buff,"JZ4750V1")) return 2;
|
return INGENIC_CPU_JZ4740V1;
|
||||||
if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4740")) return 3;
|
if (!strcmp(buf, "JZ4750V1"))
|
||||||
if (!strcmp(ingenic_dev->cpu_info_buff,"Boot4750")) return 4;
|
return INGENIC_CPU_JZ4750V1;
|
||||||
|
if (!strcmp(buf, "Boot4740"))
|
||||||
|
return INGENIC_CPU_JZ4740;
|
||||||
|
if (!strcmp(buf, "Boot4750"))
|
||||||
|
return INGENIC_CPU_JZ4750;
|
||||||
|
|
||||||
return 0;
|
return INGENIC_CPU_UNKOWN;
|
||||||
}
|
|
||||||
|
|
||||||
int usb_ingenic_flush_cache(struct ingenic_dev *ingenic_dev)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
||||||
/* bRequest */ VR_FLUSH_CACHES,
|
|
||||||
/* wValue */ 0,
|
|
||||||
/* wIndex */ 0,
|
|
||||||
/* Data */ 0,
|
|
||||||
/* wLength */ 0,
|
|
||||||
USB_TIMEOUT);
|
|
||||||
|
|
||||||
if (status != 0) {
|
|
||||||
fprintf(stderr, "Error - can't flush cache: %i\n", status);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, unsigned int len)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
/* tell the device the length of the file to be uploaded */
|
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
||||||
/* bRequest */ VR_SET_DATA_LENGTH,
|
|
||||||
/* wValue */ STAGE_ADDR_MSB(len),
|
|
||||||
/* wIndex */ STAGE_ADDR_LSB(len),
|
|
||||||
/* Data */ 0,
|
|
||||||
/* wLength */ 0,
|
|
||||||
USB_TIMEOUT);
|
|
||||||
|
|
||||||
if (status != 0) {
|
|
||||||
fprintf(stderr, "Error - "
|
|
||||||
"can't set data length on Ingenic device: %i\n", status);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev, uint32_t addr)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
/* tell the device the RAM address to store the file */
|
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
||||||
/* bRequest */ VR_SET_DATA_ADDRESS,
|
|
||||||
/* wValue */ STAGE_ADDR_MSB(addr),
|
|
||||||
/* wIndex */ STAGE_ADDR_LSB(addr),
|
|
||||||
/* Data */ 0,
|
|
||||||
/* wLength */ 0,
|
|
||||||
USB_TIMEOUT);
|
|
||||||
|
|
||||||
if (status != 0) {
|
|
||||||
fprintf(stderr, "Error - "
|
|
||||||
"can't set the address on Ingenic device: %i\n", status);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev, const char *data,
|
int usb_send_data_to_ingenic(struct ingenic_dev *ingenic_dev, const char *data,
|
||||||
int size)
|
int size)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
status = usb_bulk_write(ingenic_dev->usb_handle,
|
ret = usb_bulk_write(ingenic_dev->usb_handle,
|
||||||
/* endpoint */ INGENIC_OUT_ENDPOINT,
|
/* endpoint */ INGENIC_OUT_ENDPOINT,
|
||||||
/* bulk data */ data,
|
/* bulk data */ data,
|
||||||
/* bulk data length */ size,
|
/* bulk data length */ size,
|
||||||
USB_TIMEOUT);
|
USB_TIMEOUT);
|
||||||
if (status < size) {
|
|
||||||
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error - "
|
fprintf(stderr, "Error - "
|
||||||
"can't send bulk data to Ingenic CPU: %i\n", status);
|
"Can't send bulk data to Ingenic CPU: %d\n", ret);
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev,
|
int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev,
|
||||||
char *data, int size)
|
char *data, int size)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
status = usb_bulk_read(ingenic_dev->usb_handle,
|
ret = usb_bulk_read(ingenic_dev->usb_handle,
|
||||||
/* endpoint */ INGENIC_IN_ENDPOINT,
|
/* endpoint */ INGENIC_IN_ENDPOINT,
|
||||||
/* bulk data */ data,
|
/* bulk data */ data,
|
||||||
/* bulk data length */ size,
|
/* bulk data length */ size,
|
||||||
USB_TIMEOUT);
|
USB_TIMEOUT);
|
||||||
if (status < size) {
|
|
||||||
|
if (ret < 0) {
|
||||||
fprintf(stderr, "Error - "
|
fprintf(stderr, "Error - "
|
||||||
"can't read bulk data from Ingenic device:%i\n", status);
|
"Can't read bulk data from Ingenic device: %d\n", ret);
|
||||||
return -1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr)
|
int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
|
|
||||||
/* tell the device to start the uploaded device */
|
/* tell the device to start the uploaded device */
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
ret = usb_control_msg(ingenic_dev->usb_handle,
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||||
/* bRequest */ rqst,
|
/* bRequest */ rqst,
|
||||||
/* wValue */ STAGE_ADDR_MSB(stage_addr),
|
/* wValue */ STAGE_ADDR_MSB(stage_addr),
|
||||||
/* wIndex */ STAGE_ADDR_LSB(stage_addr),
|
/* wIndex */ STAGE_ADDR_LSB(stage_addr),
|
||||||
/* Data */ 0,
|
/* Data */ 0,
|
||||||
/* wLength */ 0,
|
/* wLength */ 0,
|
||||||
USB_TIMEOUT);
|
USB_TIMEOUT);
|
||||||
|
|
||||||
if (status != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "Error - can't start the uploaded binary "
|
fprintf(stderr, "Error - can't start the uploaded binary "
|
||||||
"on the Ingenic device: %i\n", status);
|
"on the Ingenic device: %d\n", ret);
|
||||||
return status;
|
|
||||||
}
|
}
|
||||||
return 1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage)
|
int usb_send_data_length_to_ingenic(struct ingenic_dev *ingenic_dev, unsigned int len)
|
||||||
{
|
{
|
||||||
unsigned int stage2_addr;
|
int ret;
|
||||||
stage2_addr = total_size + 0x80000000;
|
|
||||||
stage2_addr -= CODE_SIZE;
|
|
||||||
|
|
||||||
int stage_addr = (stage == 1 ? 0x80002000 : stage2_addr);
|
/* tell the device the length of the file to be uploaded */
|
||||||
int rqst = VR_PROGRAM_START1;
|
ret = usb_control_msg(ingenic_dev->usb_handle,
|
||||||
|
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||||
|
/* bRequest */ VR_SET_DATA_LENGTH,
|
||||||
|
/* wValue */ STAGE_ADDR_MSB(len),
|
||||||
|
/* wIndex */ STAGE_ADDR_LSB(len),
|
||||||
|
/* Data */ 0,
|
||||||
|
/* wLength */ 0,
|
||||||
|
USB_TIMEOUT);
|
||||||
|
|
||||||
usb_send_data_address_to_ingenic(ingenic_dev, stage_addr);
|
if (ret != 0) {
|
||||||
printf(" Download stage %d program and execute at 0x%08x\n",
|
fprintf(stderr, "Error - "
|
||||||
stage, (stage_addr));
|
"can't set data length on Ingenic device: %d\n", ret);
|
||||||
usb_send_data_to_ingenic(ingenic_dev, ingenic_dev->file_buff,
|
|
||||||
ingenic_dev->file_len);
|
|
||||||
|
|
||||||
if (stage == 2) {
|
|
||||||
if (usb_get_ingenic_cpu(ingenic_dev) < 1)
|
|
||||||
return -1;
|
|
||||||
usb_ingenic_flush_cache(ingenic_dev);
|
|
||||||
rqst = VR_PROGRAM_START2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_ingenic_start(ingenic_dev, rqst, stage_addr) < 1)
|
return ret;
|
||||||
return -1;
|
}
|
||||||
if (usb_get_ingenic_cpu(ingenic_dev) < 1)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 1;
|
int usb_send_data_address_to_ingenic(struct ingenic_dev *ingenic_dev, uint32_t addr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* tell the device the RAM address to store the file */
|
||||||
|
ret = usb_control_msg(ingenic_dev->usb_handle,
|
||||||
|
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||||
|
/* bRequest */ VR_SET_DATA_ADDRESS,
|
||||||
|
/* wValue */ STAGE_ADDR_MSB(addr),
|
||||||
|
/* wIndex */ STAGE_ADDR_LSB(addr),
|
||||||
|
/* Data */ 0,
|
||||||
|
/* wLength */ 0,
|
||||||
|
USB_TIMEOUT);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "Error - "
|
||||||
|
"Can't set the address on Ingenic device: %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage,
|
||||||
|
const char *buf, int size)
|
||||||
|
{
|
||||||
|
uint32_t stage_addr;
|
||||||
|
int request;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (stage == 1) {
|
||||||
|
stage_addr = 0x80002000;
|
||||||
|
request = VR_PROGRAM_START1;
|
||||||
|
} else {
|
||||||
|
stage_addr = 0x80000000 + total_size - CODE_SIZE;
|
||||||
|
request = VR_PROGRAM_START2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
usb_send_data_address_to_ingenic(ingenic_dev, stage_addr);
|
||||||
|
printf("Download stage %d program and execute at 0x%08x\n",
|
||||||
|
stage, stage_addr);
|
||||||
|
usb_send_data_to_ingenic(ingenic_dev, buf, size);
|
||||||
|
|
||||||
|
if (stage == 2) {
|
||||||
|
ret = usb_get_ingenic_cpu(ingenic_dev);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
usb_ingenic_flush_cache(ingenic_dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = usb_ingenic_start(ingenic_dev, request, stage_addr);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
ret = usb_get_ingenic_cpu(ingenic_dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev)
|
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev)
|
||||||
{
|
{
|
||||||
if ((ingenic_dev->usb_handle) && (ingenic_dev->interface))
|
if (ingenic_dev->usb_handle) {
|
||||||
usb_release_interface(ingenic_dev->usb_handle,
|
if (ingenic_dev->interface) {
|
||||||
ingenic_dev->interface);
|
usb_release_interface(ingenic_dev->usb_handle,
|
||||||
|
ingenic_dev->interface);
|
||||||
|
}
|
||||||
|
|
||||||
if (ingenic_dev->usb_handle)
|
|
||||||
usb_close(ingenic_dev->usb_handle);
|
usb_close(ingenic_dev->usb_handle);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int usb_ingenic_ops(struct ingenic_dev *ingenic_dev, uint32_t type,
|
||||||
|
uint32_t ops)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = usb_control_msg(ingenic_dev->usb_handle,
|
||||||
|
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
||||||
|
/* bRequest */ type,
|
||||||
|
/* wValue */ ops,
|
||||||
|
/* wIndex */ 0,
|
||||||
|
/* Data */ 0,
|
||||||
|
/* wLength */ 0,
|
||||||
|
USB_TIMEOUT);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int usb_ingenic_flush_cache(struct ingenic_dev *ingenic_dev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
ret = usb_ingenic_ops(ingenic_dev, VR_FLUSH_CACHES, 0);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "Error - can't flush cache: %d\n", ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops)
|
int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
ret = usb_ingenic_ops(ingenic_dev, VR_NAND_OPS, ops);
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
||||||
/* bRequest */ VR_NAND_OPS,
|
|
||||||
/* wValue */ ops & 0xffff,
|
|
||||||
/* wIndex */ 0,
|
|
||||||
/* Data */ 0,
|
|
||||||
/* wLength */ 0,
|
|
||||||
USB_TIMEOUT);
|
|
||||||
|
|
||||||
if (status != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "Error - "
|
fprintf(stderr, "Error - "
|
||||||
"can't set Ingenic device nand ops: %i\n", status);
|
"can't set Ingenic device nand ops: %d\n", ret);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_ingenic_mem_ops(struct ingenic_dev *ingenic_dev, int ops)
|
int usb_ingenic_mem_ops(struct ingenic_dev *ingenic_dev, int ops)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
ret = usb_ingenic_ops(ingenic_dev, VR_MEM_OPS, ops);
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
||||||
/* bRequest */ VR_MEM_OPS,
|
|
||||||
/* wValue */ ops & 0xffff,
|
|
||||||
/* wIndex */ 0,
|
|
||||||
/* Data */ 0,
|
|
||||||
/* wLength */ 0,
|
|
||||||
USB_TIMEOUT);
|
|
||||||
|
|
||||||
if (status != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "Error - "
|
fprintf(stderr, "Error - "
|
||||||
"can't set Ingenic device nand ops: %i\n", status);
|
"can't set Ingenic device nand ops: %d\n", ret);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops)
|
int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
ret = usb_ingenic_ops(ingenic_dev, VR_CONFIGURATION, ops);
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
||||||
/* bRequest */ VR_CONFIGRATION,
|
|
||||||
/* wValue */ ops,
|
|
||||||
/* wIndex */ 0,
|
|
||||||
/* Data */ 0,
|
|
||||||
/* wLength */ 0,
|
|
||||||
USB_TIMEOUT);
|
|
||||||
|
|
||||||
if (status != 0) {
|
if (ret != 0) {
|
||||||
fprintf(stderr, "Error - "
|
fprintf(stderr, "Error - "
|
||||||
"can't init Ingenic configration: %i\n", status);
|
"can't init Ingenic configration: %d\n", ret);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int usb_ingenic_sdram_ops(struct ingenic_dev *ingenic_dev, int ops)
|
int usb_ingenic_sdram_ops(struct ingenic_dev *ingenic_dev, int ops)
|
||||||
{
|
{
|
||||||
int status;
|
int ret;
|
||||||
status = usb_control_msg(ingenic_dev->usb_handle,
|
|
||||||
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
|
|
||||||
/* bRequest */ VR_SDRAM_OPS,
|
|
||||||
/* wValue */ ops,
|
|
||||||
/* wIndex */ 0,
|
|
||||||
/* Data */ 0,
|
|
||||||
/* wLength */ 0,
|
|
||||||
USB_TIMEOUT);
|
|
||||||
|
|
||||||
if (status != 0) {
|
ret = usb_ingenic_ops(ingenic_dev, VR_SDRAM_OPS, ops);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
fprintf(stderr, "Error - "
|
fprintf(stderr, "Error - "
|
||||||
"Device can't load file to sdram: %i\n", status);
|
"Device can't load file to sdram: %d\n", ret);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#define __INGENIC_USB_H__
|
#define __INGENIC_USB_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include "usb_boot_defines.h"
|
||||||
|
|
||||||
#define INGENIC_OUT_ENDPOINT 0x01
|
#define INGENIC_OUT_ENDPOINT 0x01
|
||||||
#define INGENIC_IN_ENDPOINT 0x81
|
#define INGENIC_IN_ENDPOINT 0x81
|
||||||
@ -34,7 +35,7 @@
|
|||||||
#define VR_NOR_OPS 0x06
|
#define VR_NOR_OPS 0x06
|
||||||
#define VR_NAND_OPS 0x07
|
#define VR_NAND_OPS 0x07
|
||||||
#define VR_SDRAM_OPS 0x08
|
#define VR_SDRAM_OPS 0x08
|
||||||
#define VR_CONFIGRATION 0x09
|
#define VR_CONFIGURATION 0x09
|
||||||
#define VR_MEM_OPS 0x0a
|
#define VR_MEM_OPS 0x0a
|
||||||
#define VR_GET_NUM 0x0b
|
#define VR_GET_NUM 0x0b
|
||||||
|
|
||||||
@ -56,14 +57,21 @@ struct ingenic_dev {
|
|||||||
struct usb_device *usb_dev;
|
struct usb_device *usb_dev;
|
||||||
struct usb_dev_handle *usb_handle;
|
struct usb_dev_handle *usb_handle;
|
||||||
uint8_t interface;
|
uint8_t interface;
|
||||||
char cpu_info_buff[9];
|
|
||||||
char *file_buff;
|
struct hand config;
|
||||||
int file_len;
|
};
|
||||||
|
|
||||||
|
enum ingenic_cpu_type {
|
||||||
|
INGENIC_CPU_UNKOWN,
|
||||||
|
INGENIC_CPU_JZ4740V1,
|
||||||
|
INGENIC_CPU_JZ4750V1,
|
||||||
|
INGENIC_CPU_JZ4740,
|
||||||
|
INGENIC_CPU_JZ4750,
|
||||||
};
|
};
|
||||||
|
|
||||||
int usb_ingenic_init(struct ingenic_dev *ingenic_dev);
|
int usb_ingenic_init(struct ingenic_dev *ingenic_dev);
|
||||||
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev);
|
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev);
|
||||||
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage);
|
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage, const char *buf, int size);
|
||||||
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev);
|
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev);
|
||||||
int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops);
|
int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops);
|
||||||
int usb_ingenic_mem_ops(struct ingenic_dev *ingenic_dev, int ops);
|
int usb_ingenic_mem_ops(struct ingenic_dev *ingenic_dev, int ops);
|
||||||
@ -78,6 +86,7 @@ int usb_read_data_from_ingenic(struct ingenic_dev *ingenic_dev, char *buffer,
|
|||||||
int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr);
|
int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr);
|
||||||
int usb_ingenic_sdram_ops(struct ingenic_dev *ingenic_dev, int ops);
|
int usb_ingenic_sdram_ops(struct ingenic_dev *ingenic_dev, int ops);
|
||||||
int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops);
|
int usb_ingenic_configration(struct ingenic_dev *ingenic_dev, int ops);
|
||||||
|
int usb_ingenic_flush_cache(struct ingenic_dev *ingenic_dev);
|
||||||
|
|
||||||
#endif /* __INGENIC_USB_H__ */
|
#endif /* __INGENIC_USB_H__ */
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
#define CONFIG_FILE_PATH "/etc/xburst-tools/usbboot.cfg"
|
#define CONFIG_FILE_PATH "/etc/xburst-tools/usbboot.cfg"
|
||||||
|
|
||||||
struct ingenic_dev ingenic_dev;
|
struct ingenic_dev ingenic_dev;
|
||||||
extern struct hand hand;
|
|
||||||
|
|
||||||
static void help(void)
|
static void help(void)
|
||||||
{
|
{
|
||||||
@ -98,11 +97,15 @@ int main(int argc, char **argv)
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
if (usb_ingenic_init(&ingenic_dev) < 1)
|
if (usb_ingenic_init(&ingenic_dev)) {
|
||||||
|
printf("A\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (parse_configure(&hand, cfgpath) < 1)
|
if (parse_configure(&ingenic_dev.config, cfgpath)) {
|
||||||
|
printf("B\n");
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
|
||||||
if (cmdpt) { /* direct run command */
|
if (cmdpt) { /* direct run command */
|
||||||
char *delim=";";
|
char *delim=";";
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
#include "ingenic_usb.h"
|
#include "ingenic_usb.h"
|
||||||
#include "usb_boot_defines.h"
|
#include "usb_boot_defines.h"
|
||||||
|
|
||||||
extern struct hand hand;
|
|
||||||
|
|
||||||
#define NAND_OP(idx, op, mode) (((mode << 12) & 0xf000) | ((idx << 4) & 0xff0) | op)
|
#define NAND_OP(idx, op, mode) (((mode << 12) & 0xf000) | ((idx << 4) & 0xff0) | op)
|
||||||
|
|
||||||
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
#define DIV_ROUND_UP(n,d) (((n) + (d) - 1) / (d))
|
||||||
@ -22,9 +20,13 @@ static const char IMAGE_TYPE[][30] = {
|
|||||||
"without oob",
|
"without oob",
|
||||||
};
|
};
|
||||||
|
|
||||||
static int error_check(const char *org, const char *obj, unsigned int size)
|
static int error_check(const char *a, const char *b, unsigned int size)
|
||||||
{
|
{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
const unsigned char *org = (const unsigned char *)a;
|
||||||
|
const unsigned char *obj= (const unsigned char *)b;
|
||||||
|
|
||||||
|
|
||||||
printf("Comparing %d bytes - ", size);
|
printf("Comparing %d bytes - ", size);
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
if (org[i] != obj[i]) {
|
if (org[i] != obj[i]) {
|
||||||
@ -65,8 +67,8 @@ int nand_markbad(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t block)
|
|||||||
(void)nand_idx;
|
(void)nand_idx;
|
||||||
|
|
||||||
if (usb_get_ingenic_cpu(dev) < 3) {
|
if (usb_get_ingenic_cpu(dev) < 3) {
|
||||||
printf("Device unboot! Boot it first!\n");
|
fprintf(stderr, "Device unboot! Boot it first!\n");
|
||||||
return -1;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
printf("Mark bad block : %d\n", block);
|
printf("Mark bad block : %d\n", block);
|
||||||
usb_send_data_address_to_ingenic(dev, block);
|
usb_send_data_address_to_ingenic(dev, block);
|
||||||
@ -75,7 +77,7 @@ int nand_markbad(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t block)
|
|||||||
printf("Mark bad block at %d\n",((ret[3] << 24) |
|
printf("Mark bad block at %d\n",((ret[3] << 24) |
|
||||||
(ret[2] << 16) |
|
(ret[2] << 16) |
|
||||||
(ret[1] << 8) |
|
(ret[1] << 8) |
|
||||||
(ret[0] << 0)) / hand.nand_ppb);
|
(ret[0] << 0)) / dev->config.nand_ppb);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -91,20 +93,20 @@ int nand_program_check(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
|
|
||||||
printf("Writing NAND page %u len %u...\n", start_page, length);
|
printf("Writing NAND page %u len %u...\n", start_page, length);
|
||||||
if (length > (unsigned int)MAX_TRANSFER_SIZE) {
|
if (length > (unsigned int)MAX_TRANSFER_SIZE) {
|
||||||
printf("Buffer size too long!\n");
|
fprintf(stderr, "Buffer size too long!\n");
|
||||||
return -ENOMEM;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_get_ingenic_cpu(dev) < 3) {
|
if (usb_get_ingenic_cpu(dev) < 3) {
|
||||||
printf("Device unboot! Boot it first!\n");
|
fprintf(stderr, "Device unboot! Boot it first!\n");
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
usb_send_data_to_ingenic(dev, data, length);
|
usb_send_data_to_ingenic(dev, data, length);
|
||||||
|
|
||||||
if (mode == NO_OOB)
|
if (mode == NO_OOB)
|
||||||
page_num = DIV_ROUND_UP(length, hand.nand_ps);
|
page_num = DIV_ROUND_UP(length, dev->config.nand_ps);
|
||||||
else
|
else
|
||||||
page_num = DIV_ROUND_UP(length, hand.nand_ps + hand.nand_os);
|
page_num = DIV_ROUND_UP(length, dev->config.nand_ps + dev->config.nand_os);
|
||||||
|
|
||||||
op = NAND_OP(nand_idx, NAND_PROGRAM, mode);
|
op = NAND_OP(nand_idx, NAND_PROGRAM, mode);
|
||||||
|
|
||||||
@ -117,14 +119,11 @@ int nand_program_check(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
length, start_page, page_num);
|
length, start_page, page_num);
|
||||||
|
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case NAND_READ:
|
case NO_OOB:
|
||||||
op = NAND_OP(nand_idx, NAND_READ, NO_OOB);
|
op = NAND_OP(nand_idx, NAND_READ, NO_OOB);
|
||||||
break;
|
break;
|
||||||
case NAND_READ_OOB:
|
default:
|
||||||
op = NAND_OP(nand_idx, NAND_READ_OOB, 0);
|
op = NAND_OP(nand_idx, NAND_READ_RAW, OOB_ECC);
|
||||||
break;
|
|
||||||
case NAND_READ_RAW:
|
|
||||||
op = NAND_OP(nand_idx, NAND_READ_RAW, NO_OOB);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -135,16 +134,16 @@ int nand_program_check(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
(ret[0] << 0);
|
(ret[0] << 0);
|
||||||
|
|
||||||
if (start_page < 1 &&
|
if (start_page < 1 &&
|
||||||
hand.nand_ps == 4096 &&
|
dev->config.nand_ps == 4096 &&
|
||||||
hand.fw_args.cpu_id == 0x4740) {
|
dev->config.fw_args.cpu_id == 0x4740) {
|
||||||
printf("no check! End at Page: %d\n", cur_page);
|
printf("no check! End at Page: %d\n", cur_page);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error_check(data, read_back_buf, length)) {
|
if (!error_check(data, read_back_buf, length)) {
|
||||||
// tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page?
|
// tbd: doesn't the other side skip bad blocks too? Can we just deduct 1 from cur_page?
|
||||||
// tbd: why do we only mark a block as bad if the last page in the block was written?
|
// tbd: why do we only mark a block as bad if the last page in the block was written?
|
||||||
if (cur_page % hand.nand_ppb == 0)
|
if (cur_page % dev->config.nand_ppb == 0)
|
||||||
nand_markbad(dev, nand_idx, (cur_page - 1) / hand.nand_ppb);
|
nand_markbad(dev, nand_idx, (cur_page - 1) / dev->config.nand_ppb);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("End at Page: %d\n", cur_page);
|
printf("End at Page: %d\n", cur_page);
|
||||||
@ -161,17 +160,17 @@ int nand_erase(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_block,
|
|||||||
static char ret[8];
|
static char ret[8];
|
||||||
|
|
||||||
if (start_block > (unsigned int)NAND_MAX_BLK_NUM) {
|
if (start_block > (unsigned int)NAND_MAX_BLK_NUM) {
|
||||||
printf("Start block number overflow!\n");
|
fprintf(stderr, "Start block number overflow!\n");
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (num_blocks > (unsigned int)NAND_MAX_BLK_NUM) {
|
if (num_blocks > (unsigned int)NAND_MAX_BLK_NUM) {
|
||||||
printf("Length block number overflow!\n");
|
fprintf(stderr, "Length block number overflow!\n");
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (usb_get_ingenic_cpu(dev) < 3) {
|
if (usb_get_ingenic_cpu(dev) < 3) {
|
||||||
printf("Device unboot! Boot it first!\n");
|
fprintf(stderr, "Device unboot! Boot it first!\n");
|
||||||
return -1;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Erasing No.%d device No.%d flash (start_blk %u blk_num %u)......\n",
|
printf("Erasing No.%d device No.%d flash (start_blk %u blk_num %u)......\n",
|
||||||
@ -187,10 +186,10 @@ int nand_erase(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_block,
|
|||||||
printf("Finish!");
|
printf("Finish!");
|
||||||
|
|
||||||
end_block = ((ret[3] << 24) | (ret[2] << 16) |
|
end_block = ((ret[3] << 24) | (ret[2] << 16) |
|
||||||
(ret[1] << 8) | (ret[0] << 0)) / hand.nand_ppb;
|
(ret[1] << 8) | (ret[0] << 0)) / dev->config.nand_ppb;
|
||||||
printf("Return: %02x %02x %02x %02x %02x %02x %02x %02x (position %d)\n",
|
printf("Return: %02x %02x %02x %02x %02x %02x %02x %02x (position %d)\n",
|
||||||
ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7], end_block);
|
ret[0], ret[1], ret[2], ret[3], ret[4], ret[5], ret[6], ret[7], end_block);
|
||||||
if (!hand.nand_force_erase) {
|
if (!dev->config.nand_force_erase) {
|
||||||
/* not force erase, show bad block infomation */
|
/* not force erase, show bad block infomation */
|
||||||
printf("There are marked bad blocks: %d\n",
|
printf("There are marked bad blocks: %d\n",
|
||||||
end_block - start_block - num_blocks );
|
end_block - start_block - num_blocks );
|
||||||
@ -217,7 +216,7 @@ int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
if (status < 0) {
|
if (status < 0) {
|
||||||
fprintf(stderr, "Error - can't get file size from '%s': %s\n",
|
fprintf(stderr, "Error - can't get file size from '%s': %s\n",
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
return -1;
|
return -EEXIST;
|
||||||
}
|
}
|
||||||
flen = fstat.st_size;
|
flen = fstat.st_size;
|
||||||
|
|
||||||
@ -225,7 +224,7 @@ int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
fprintf(stderr, "Error - can't open file '%s': %s\n",
|
fprintf(stderr, "Error - can't open file '%s': %s\n",
|
||||||
filename, strerror(errno));
|
filename, strerror(errno));
|
||||||
return -1;
|
return errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Programing No.%d device, flen %d, start page %d...\n", 0,
|
printf("Programing No.%d device, flen %d, start page %d...\n", 0,
|
||||||
@ -233,11 +232,12 @@ int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
|
|
||||||
/* printf("length %d flen %d\n", n_in.length, flen); */
|
/* printf("length %d flen %d\n", n_in.length, flen); */
|
||||||
if (mode == NO_OOB)
|
if (mode == NO_OOB)
|
||||||
transfer_size = (hand.nand_ppb * hand.nand_ps);
|
transfer_size = (dev->config.nand_ppb * dev->config.nand_ps);
|
||||||
else
|
else
|
||||||
transfer_size = (hand.nand_ppb * (hand.nand_ps + hand.nand_os));
|
transfer_size = (dev->config.nand_ppb * (dev->config.nand_ps +
|
||||||
|
dev->config.nand_os));
|
||||||
|
|
||||||
start_block = start_page / hand.nand_ppb;
|
start_block = start_page / dev->config.nand_ppb;
|
||||||
num_blocks = flen / (transfer_size - 1) + 1;
|
num_blocks = flen / (transfer_size - 1) + 1;
|
||||||
|
|
||||||
if (nand_erase(dev, nand_idx, start_block, num_blocks))
|
if (nand_erase(dev, nand_idx, start_block, num_blocks))
|
||||||
@ -247,13 +247,13 @@ int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
j = flen % transfer_size;
|
j = flen % transfer_size;
|
||||||
|
|
||||||
printf("Size to send %d, transfer_size %d\n", flen, transfer_size);
|
printf("Size to send %d, transfer_size %d\n", flen, transfer_size);
|
||||||
printf("Image type : %s\n", IMAGE_TYPE[mode]);
|
/* printf("Image type : %s\n", IMAGE_TYPE[mode]);*/
|
||||||
printf("It will cause %d times buffer transfer.\n", j == 0 ? m : m + 1);
|
printf("It will cause %d times buffer transfer.\n", j == 0 ? m : m + 1);
|
||||||
|
|
||||||
if (mode == NO_OOB)
|
if (mode == NO_OOB)
|
||||||
page_num = transfer_size / hand.nand_ps;
|
page_num = transfer_size / dev->config.nand_ps;
|
||||||
else
|
else
|
||||||
page_num = transfer_size / (hand.nand_ps + hand.nand_os);
|
page_num = transfer_size / (dev->config.nand_ps + dev->config.nand_os);
|
||||||
|
|
||||||
|
|
||||||
offset = 0;
|
offset = 0;
|
||||||
@ -269,7 +269,7 @@ int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
if (nand_program_check(dev, nand_idx, start_page, code_buf, code_len, mode) == -1)
|
if (nand_program_check(dev, nand_idx, start_page, code_buf, code_len, mode) == -1)
|
||||||
goto close;
|
goto close;
|
||||||
|
|
||||||
/* if (start_page - nand_in->start > hand.nand_ppb)
|
/* if (start_page - nand_in->start > dev->config.nand_ppb)
|
||||||
printf("Skip a old bad block !\n");*/
|
printf("Skip a old bad block !\n");*/
|
||||||
|
|
||||||
offset += code_len ;
|
offset += code_len ;
|
||||||
@ -277,8 +277,8 @@ int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
|
|
||||||
if (j) {
|
if (j) {
|
||||||
code_len = j;
|
code_len = j;
|
||||||
if (j % hand.nand_ps)
|
if (j % dev->config.nand_ps)
|
||||||
j += hand.nand_ps - (j % hand.nand_ps);
|
j += dev->config.nand_ps - (j % dev->config.nand_ps);
|
||||||
memset(code_buf, 0, j); /* set all to null */
|
memset(code_buf, 0, j); /* set all to null */
|
||||||
|
|
||||||
status = read(fd, code_buf, code_len);
|
status = read(fd, code_buf, code_len);
|
||||||
@ -293,7 +293,7 @@ int nand_program_file(struct ingenic_dev *dev, uint8_t nand_idx,
|
|||||||
goto close;
|
goto close;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
if (start_page - nand_in->start > hand.nand_ppb)
|
if (start_page - nand_in->start > dev->config.nand_ppb)
|
||||||
printf("Skip a old bad block !");
|
printf("Skip a old bad block !");
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
@ -305,7 +305,7 @@ close:
|
|||||||
int nand_prog(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_page,
|
int nand_prog(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_page,
|
||||||
const char *filename, int mode)
|
const char *filename, int mode)
|
||||||
{
|
{
|
||||||
if (hand.nand_plane > 1)
|
if (dev->config.nand_plane > 1)
|
||||||
printf("ERROR");
|
printf("ERROR");
|
||||||
else
|
else
|
||||||
nand_program_file(dev, nand_idx, start_page, filename, mode);
|
nand_program_file(dev, nand_idx, start_page, filename, mode);
|
||||||
@ -316,11 +316,12 @@ int nand_prog(struct ingenic_dev *dev, uint8_t nand_idx, uint32_t start_page,
|
|||||||
int nand_query(struct ingenic_dev *dev, uint8_t nand_idx)
|
int nand_query(struct ingenic_dev *dev, uint8_t nand_idx)
|
||||||
{
|
{
|
||||||
uint16_t op;
|
uint16_t op;
|
||||||
char ret[8];
|
char ret[8] = {0,0,0,0,0,0,0,0};
|
||||||
|
int ret2;
|
||||||
|
|
||||||
if (usb_get_ingenic_cpu(dev) < 3) {
|
if (usb_get_ingenic_cpu(dev) < 3) {
|
||||||
printf("Device unboot! Boot it first!\n");
|
fprintf(stderr, "Device unboot! Boot it first!\n");
|
||||||
return -1;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ID of No.%u device No.%u flash: \n", 0, nand_idx);
|
printf("ID of No.%u device No.%u flash: \n", 0, nand_idx);
|
||||||
@ -328,7 +329,11 @@ int nand_query(struct ingenic_dev *dev, uint8_t nand_idx)
|
|||||||
op = NAND_OP(nand_idx, NAND_QUERY, 0);
|
op = NAND_OP(nand_idx, NAND_QUERY, 0);
|
||||||
|
|
||||||
usb_ingenic_nand_ops(dev, op);
|
usb_ingenic_nand_ops(dev, op);
|
||||||
usb_read_data_from_ingenic(dev, ret, ARRAY_SIZE(ret));
|
ret2 = usb_read_data_from_ingenic(dev, ret, ARRAY_SIZE(ret));
|
||||||
|
|
||||||
|
if (ret2 < 0)
|
||||||
|
return ret2;
|
||||||
|
|
||||||
printf("Vendor ID :0x%x \n", (unsigned char)ret[0]);
|
printf("Vendor ID :0x%x \n", (unsigned char)ret[0]);
|
||||||
printf("Product ID :0x%x \n", (unsigned char)ret[1]);
|
printf("Product ID :0x%x \n", (unsigned char)ret[1]);
|
||||||
printf("Chip ID :0x%x \n", (unsigned char)ret[2]);
|
printf("Chip ID :0x%x \n", (unsigned char)ret[2]);
|
||||||
@ -342,7 +347,8 @@ int nand_query(struct ingenic_dev *dev, uint8_t nand_idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode,
|
int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode,
|
||||||
uint32_t start_page, uint32_t length, uint32_t ram_addr)
|
uint32_t start_page, uint32_t length, uint32_t ram_addr,
|
||||||
|
nand_read_cb_t callback, void *userdata)
|
||||||
{
|
{
|
||||||
uint16_t op;
|
uint16_t op;
|
||||||
uint32_t page;
|
uint32_t page;
|
||||||
@ -350,18 +356,18 @@ int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode,
|
|||||||
uint32_t pages_per_request;
|
uint32_t pages_per_request;
|
||||||
char ret[8];
|
char ret[8];
|
||||||
char *buf;
|
char *buf;
|
||||||
int fd;
|
int ret2;
|
||||||
|
|
||||||
if (start_page > NAND_MAX_PAGE_NUM) {
|
if (start_page > NAND_MAX_PAGE_NUM) {
|
||||||
printf("Page number overflow!\n");
|
fprintf(stderr, "Page number overflow!\n");
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (usb_get_ingenic_cpu(dev) < 3) {
|
if (usb_get_ingenic_cpu(dev) < 3) {
|
||||||
printf("Device unboot! Boot it first!\n");
|
fprintf(stderr, "Device unboot! Boot it first!\n");
|
||||||
return -1;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
if (nand_idx >= 16)
|
if (nand_idx >= 16)
|
||||||
return -1;
|
return -EINVAL;
|
||||||
|
|
||||||
printf("Reading from No.%u device No.%u flash....\n", 0, nand_idx);
|
printf("Reading from No.%u device No.%u flash....\n", 0, nand_idx);
|
||||||
|
|
||||||
@ -374,46 +380,43 @@ int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode,
|
|||||||
op = NAND_OP(nand_idx, NAND_READ_OOB, 0);
|
op = NAND_OP(nand_idx, NAND_READ_OOB, 0);
|
||||||
break;
|
break;
|
||||||
case NAND_READ_RAW:
|
case NAND_READ_RAW:
|
||||||
op = NAND_OP(nand_idx, NAND_READ_RAW, NO_OOB);
|
op = NAND_OP(nand_idx, NAND_READ_RAW, OOB_ECC);
|
||||||
break;
|
break;
|
||||||
case NAND_READ_TO_RAM:
|
case NAND_READ_TO_RAM:
|
||||||
op = NAND_OP(nand_idx, NAND_READ_TO_RAM, NO_OOB);
|
op = NAND_OP(nand_idx, NAND_READ_TO_RAM, NO_OOB);
|
||||||
printf("Reading nand to RAM: 0x%x\n", ram_addr);
|
|
||||||
usb_ingenic_start(dev, VR_PROGRAM_START1, ram_addr);
|
usb_ingenic_start(dev, VR_PROGRAM_START1, ram_addr);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("unknow mode!\n");
|
return -EINVAL;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pages_per_request = 1;
|
pages_per_request = 1;
|
||||||
request_length = hand.nand_ps * pages_per_request;
|
if (mode == NAND_READ_OOB || mode == NAND_READ_RAW)
|
||||||
|
request_length = (dev->config.nand_ps + dev->config.nand_os) * pages_per_request;
|
||||||
|
else
|
||||||
|
request_length = dev->config.nand_ps * pages_per_request;
|
||||||
|
|
||||||
page = start_page;
|
page = start_page;
|
||||||
|
|
||||||
buf = malloc(request_length);
|
buf = malloc(request_length);
|
||||||
|
|
||||||
fd = open("/tmp/dump.bin", O_WRONLY | O_TRUNC | O_CREAT);
|
|
||||||
if (fd < 0) {
|
|
||||||
printf("Failed to open file\n");
|
|
||||||
return errno;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (length > 0) {
|
while (length > 0) {
|
||||||
if (request_length > length)
|
if (request_length > length)
|
||||||
request_length = length;
|
request_length = length;
|
||||||
|
|
||||||
nand_read_pages(dev, page, pages_per_request, buf, request_length, op, ret);
|
nand_read_pages(dev, page, pages_per_request, buf, request_length, op, ret);
|
||||||
|
|
||||||
write(fd, buf, request_length);
|
ret2 = callback(userdata, buf, request_length);
|
||||||
|
if (ret2)
|
||||||
|
return ret2;
|
||||||
|
|
||||||
length -= request_length;
|
length -= request_length;
|
||||||
page += pages_per_request;
|
page += pages_per_request;
|
||||||
}
|
}
|
||||||
close(fd);
|
|
||||||
printf("Operation end position : %u \n",
|
printf("Operation end position : %u \n",
|
||||||
(ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0));
|
(ret[3]<<24)|(ret[2]<<16)|(ret[1]<<8)|(ret[0]<<0));
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
return 1;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -6,11 +6,12 @@
|
|||||||
|
|
||||||
struct ingenic_dev;
|
struct ingenic_dev;
|
||||||
|
|
||||||
|
typedef int (*nand_read_cb_t)(void *userdata, const char *buf, size_t size);
|
||||||
|
|
||||||
int nand_query(struct ingenic_dev *dev, uint8_t nand_idx);
|
int nand_query(struct ingenic_dev *dev, uint8_t nand_idx);
|
||||||
int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode,
|
int nand_read(struct ingenic_dev *dev, uint8_t nand_idx, int mode,
|
||||||
uint32_t start_page, uint32_t length, uint32_t ram_addr);
|
uint32_t start_page, uint32_t length, uint32_t ram_addr,
|
||||||
int nand_dump(struct ingenic_dev *dev, uint8_t nand_idx,
|
nand_read_cb_t callbcallback, void *userdata);
|
||||||
uint32_t start_page, uint32_t length, const char *filename);
|
|
||||||
int nand_erase(struct ingenic_dev *dev, uint8_t nand_idx,
|
int nand_erase(struct ingenic_dev *dev, uint8_t nand_idx,
|
||||||
uint32_t start_block, uint32_t num_blocks);
|
uint32_t start_block, uint32_t num_blocks);
|
||||||
int nand_prog(struct ingenic_dev *dev, uint8_t nand_idx,
|
int nand_prog(struct ingenic_dev *dev, uint8_t nand_idx,
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
#ifndef __USB_BOOT_H__
|
#ifndef __USB_BOOT_H__
|
||||||
#define __USB_BOOT_H__
|
#define __USB_BOOT_H__
|
||||||
|
|
||||||
#define BULK_BUF_SIZE (128 * 4096)
|
#define BULK_BUF_SIZE (128 * (4096 + 128))
|
||||||
|
|
||||||
enum UDC_STATE
|
enum UDC_STATE
|
||||||
{
|
{
|
||||||
|
@ -121,17 +121,27 @@ void sdram_init_4740(void)
|
|||||||
|
|
||||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
|
||||||
|
|
||||||
|
if (SDRAM_BW16 == 0xff) {
|
||||||
|
serial_puts("hura");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
serial_put_hex(0xf00);
|
||||||
cpu_clk = CFG_CPU_SPEED;
|
cpu_clk = CFG_CPU_SPEED;
|
||||||
mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
|
mem_clk = cpu_clk * div[__cpm_get_cdiv()] / div[__cpm_get_mdiv()];
|
||||||
|
serial_put_hex(0xf01);
|
||||||
|
|
||||||
REG_EMC_BCR = 0; /* Disable bus release */
|
REG_EMC_BCR = 0; /* Disable bus release */
|
||||||
|
serial_put_hex(0xf02);
|
||||||
REG_EMC_RTCSR = 0; /* Disable clock for counting */
|
REG_EMC_RTCSR = 0; /* Disable clock for counting */
|
||||||
|
serial_put_hex(0xf03);
|
||||||
|
|
||||||
/* Fault DMCR value for mode register setting*/
|
/* Fault DMCR value for mode register setting*/
|
||||||
#define SDRAM_ROW0 11
|
#define SDRAM_ROW0 11
|
||||||
#define SDRAM_COL0 8
|
#define SDRAM_COL0 8
|
||||||
#define SDRAM_BANK40 0
|
#define SDRAM_BANK40 0
|
||||||
|
|
||||||
|
serial_put_hex(0xf04);
|
||||||
dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
|
dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) |
|
||||||
((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
|
((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) |
|
||||||
(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
|
(SDRAM_BANK40<<EMC_DMCR_BA_BIT) |
|
||||||
@ -139,6 +149,7 @@ void sdram_init_4740(void)
|
|||||||
EMC_DMCR_EPIN |
|
EMC_DMCR_EPIN |
|
||||||
cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
|
cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
|
||||||
|
|
||||||
|
serial_put_hex(0xf05);
|
||||||
/* Basic DMCR value */
|
/* Basic DMCR value */
|
||||||
dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
|
dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) |
|
||||||
((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
|
((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) |
|
||||||
@ -147,6 +158,7 @@ void sdram_init_4740(void)
|
|||||||
EMC_DMCR_EPIN |
|
EMC_DMCR_EPIN |
|
||||||
cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
|
cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
|
||||||
|
|
||||||
|
serial_put_hex(0xf06);
|
||||||
/* SDRAM timimg */
|
/* SDRAM timimg */
|
||||||
ns = 1000000000 / mem_clk;
|
ns = 1000000000 / mem_clk;
|
||||||
tmp = SDRAM_TRAS/ns;
|
tmp = SDRAM_TRAS/ns;
|
||||||
@ -172,23 +184,33 @@ void sdram_init_4740(void)
|
|||||||
EMC_SDMR_BL_4 |
|
EMC_SDMR_BL_4 |
|
||||||
cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
|
cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
|
||||||
|
|
||||||
|
serial_put_hex(0xf07);
|
||||||
/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
|
/* Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0 */
|
||||||
|
serial_put_hex(dmcr);
|
||||||
|
serial_put_hex(REG_EMC_DMCR);
|
||||||
REG_EMC_DMCR = dmcr;
|
REG_EMC_DMCR = dmcr;
|
||||||
REG8(EMC_SDMR0|sdmode) = 0;
|
REG8(EMC_SDMR0|sdmode) = 0;
|
||||||
|
|
||||||
/* Wait for precharge, > 200us */
|
/* Wait for precharge, > 200us */
|
||||||
tmp = (cpu_clk / 1000000) * 1000;
|
tmp = (cpu_clk / 1000000) * 1000;
|
||||||
while (tmp--);
|
while (tmp--);
|
||||||
|
serial_put_hex(0xf08);
|
||||||
|
|
||||||
/* Stage 2. Enable auto-refresh */
|
/* Stage 2. Enable auto-refresh */
|
||||||
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
|
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH;
|
||||||
|
serial_put_hex(0xf09);
|
||||||
tmp = SDRAM_TREF/ns;
|
tmp = SDRAM_TREF/ns;
|
||||||
|
serial_put_hex(0xf10);
|
||||||
tmp = tmp/64 + 1;
|
tmp = tmp/64 + 1;
|
||||||
|
serial_put_hex(0xf11);
|
||||||
if (tmp > 0xff) tmp = 0xff;
|
if (tmp > 0xff) tmp = 0xff;
|
||||||
REG_EMC_RTCOR = tmp;
|
serial_put_hex(tmp);
|
||||||
|
/* REG_EMC_RTCOR = tmp;*/
|
||||||
|
serial_put_hex(0xf10);
|
||||||
REG_EMC_RTCNT = 0;
|
REG_EMC_RTCNT = 0;
|
||||||
|
serial_put_hex(0xf11);
|
||||||
REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
|
REG_EMC_RTCSR = EMC_RTCSR_CKS_64; /* Divisor is 64, CKO/64 */
|
||||||
|
serial_put_hex(0xf12);
|
||||||
|
|
||||||
/* Wait for number of auto-refresh cycles */
|
/* Wait for number of auto-refresh cycles */
|
||||||
tmp = (cpu_clk / 1000000) * 1000;
|
tmp = (cpu_clk / 1000000) * 1000;
|
||||||
@ -198,9 +220,10 @@ void sdram_init_4740(void)
|
|||||||
REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
REG_EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
||||||
REG8(EMC_SDMR0|sdmode) = 0;
|
REG8(EMC_SDMR0|sdmode) = 0;
|
||||||
|
|
||||||
|
serial_put_hex(0xf11);
|
||||||
/* Set back to basic DMCR value */
|
/* Set back to basic DMCR value */
|
||||||
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
REG_EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET;
|
||||||
|
serial_put_hex(0xf12);
|
||||||
/* everything is ok now */
|
/* everything is ok now */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ void load_args(void)
|
|||||||
CFG_CPU_SPEED = 192000000;
|
CFG_CPU_SPEED = 192000000;
|
||||||
}
|
}
|
||||||
PHM_DIV = fw_args->phm_div;
|
PHM_DIV = fw_args->phm_div;
|
||||||
if (fw_args->use_uart > 3)
|
if (fw_args->use_uart > 3)
|
||||||
fw_args->use_uart = 0;
|
fw_args->use_uart = 0;
|
||||||
UART_BASE = UART0_BASE + fw_args->use_uart * 0x1000;
|
UART_BASE = UART0_BASE + fw_args->use_uart * 0x1000;
|
||||||
CONFIG_BAUDRATE = fw_args->boudrate;
|
CONFIG_BAUDRATE = fw_args->boudrate;
|
||||||
@ -88,10 +88,12 @@ void c_main(void)
|
|||||||
do_debug();
|
do_debug();
|
||||||
return ;
|
return ;
|
||||||
}
|
}
|
||||||
|
/* serial_put_hex(0xf00);*/
|
||||||
|
|
||||||
switch (CPU_ID) {
|
switch (CPU_ID) {
|
||||||
case 0x4740:
|
case 0x4740:
|
||||||
gpio_init_4740();
|
gpio_init_4740();
|
||||||
|
/* serial_put_hex(0xf01);*/
|
||||||
pll_init_4740();
|
pll_init_4740();
|
||||||
serial_init();
|
serial_init();
|
||||||
sdram_init_4740();
|
sdram_init_4740();
|
||||||
|
@ -440,6 +440,8 @@ u32 nand_read_4740(void *buf, u32 startpage, u32 pagecount, int option)
|
|||||||
tmpbuf = buf;
|
tmpbuf = buf;
|
||||||
handshake_PKT[3] = 0;
|
handshake_PKT[3] = 0;
|
||||||
|
|
||||||
|
return cur_page + pagecount;
|
||||||
|
|
||||||
while (cnt < pagecount) {
|
while (cnt < pagecount) {
|
||||||
select_chip(cnt / ppb);
|
select_chip(cnt / ppb);
|
||||||
/* If this is the first page of the block, check for bad. */
|
/* If this is the first page of the block, check for bad. */
|
||||||
|
Loading…
Reference in New Issue
Block a user