1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2024-11-29 13:16:16 +02:00

more cleanup

This commit is contained in:
Lars-Peter Clausen 2010-01-08 03:35:59 +01:00
parent 836fade868
commit 9aa52b7947
12 changed files with 434 additions and 378 deletions

View File

@ -31,56 +31,48 @@
#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 */
@ -91,13 +83,14 @@ void init_cfg(struct ingenic_dev *dev)
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");
@ -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);
return -1; if (size < 0) {
printf("FOOBAR");
return size;
}
if (usb_ingenic_upload(dev, 2) < 1) if (usb_ingenic_upload(dev, 2, code_buf, size) < 0)
return -1; return -1;
printf("Booted successfully!\n"); printf("Booted successfully!\n");
} }
usleep(100); usleep(100);
init_cfg(dev); init_cfg(dev);
return 1; return 0;
} }
@ -177,29 +175,28 @@ int debug_memory(struct ingenic_dev *dev, int obj, unsigned int start, unsigned
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);

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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,182 +108,120 @@ 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),
@ -291,135 +230,188 @@ int usb_ingenic_start(struct ingenic_dev *ingenic_dev, int rqst, int stage_addr)
/* 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; /* tell the device the length of the file to be uploaded */
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);
if (ret != 0) {
fprintf(stderr, "Error - "
"can't set data length on Ingenic device: %d\n", ret);
}
return ret;
}
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;
}
int stage_addr = (stage == 1 ? 0x80002000 : stage2_addr);
int rqst = VR_PROGRAM_START1;
usb_send_data_address_to_ingenic(ingenic_dev, stage_addr); usb_send_data_address_to_ingenic(ingenic_dev, stage_addr);
printf("Download stage %d program and execute at 0x%08x\n", printf("Download stage %d program and execute at 0x%08x\n",
stage, (stage_addr)); stage, stage_addr);
usb_send_data_to_ingenic(ingenic_dev, ingenic_dev->file_buff, usb_send_data_to_ingenic(ingenic_dev, buf, size);
ingenic_dev->file_len);
if (stage == 2) { if (stage == 2) {
if (usb_get_ingenic_cpu(ingenic_dev) < 1) ret = usb_get_ingenic_cpu(ingenic_dev);
return -1; if (ret < 0)
return ret;
usb_ingenic_flush_cache(ingenic_dev); usb_ingenic_flush_cache(ingenic_dev);
rqst = VR_PROGRAM_START2;
} }
if (usb_ingenic_start(ingenic_dev, rqst, stage_addr) < 1) ret = usb_ingenic_start(ingenic_dev, request, stage_addr);
return -1; if (ret)
if (usb_get_ingenic_cpu(ingenic_dev) < 1) return ret;
return -1; ret = usb_get_ingenic_cpu(ingenic_dev);
if (ret)
return ret;
return 1; 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) {
if (ingenic_dev->interface) {
usb_release_interface(ingenic_dev->usb_handle, usb_release_interface(ingenic_dev->usb_handle,
ingenic_dev->interface); ingenic_dev->interface);
}
if (ingenic_dev->usb_handle)
usb_close(ingenic_dev->usb_handle); usb_close(ingenic_dev->usb_handle);
} }
int usb_ingenic_nand_ops(struct ingenic_dev *ingenic_dev, int ops) }
static int usb_ingenic_ops(struct ingenic_dev *ingenic_dev, uint32_t type,
uint32_t ops)
{ {
int status; int ret;
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 */ VR_NAND_OPS, /* bRequest */ type,
/* wValue */ ops & 0xffff, /* wValue */ ops,
/* wIndex */ 0, /* wIndex */ 0,
/* Data */ 0, /* Data */ 0,
/* wLength */ 0, /* wLength */ 0,
USB_TIMEOUT); USB_TIMEOUT);
if (status != 0) { return ret;
fprintf(stderr, "Error - "
"can't set Ingenic device nand ops: %i\n", status);
return -1;
} }
return 1; 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 ret;
ret = usb_ingenic_ops(ingenic_dev, VR_NAND_OPS, ops);
if (ret != 0) {
fprintf(stderr, "Error - "
"can't set Ingenic device nand ops: %d\n", ret);
}
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;
} }

View File

@ -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__ */

View File

@ -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=";";

View File

@ -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;
} }

View File

@ -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,

View File

@ -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
{ {

View File

@ -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 */
} }

View File

@ -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();

View File

@ -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. */