diff options
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile | 1 | ||||
-rw-r--r-- | common/cmd_bdinfo.c | 20 | ||||
-rw-r--r-- | common/cmd_cache.c | 14 | ||||
-rw-r--r-- | common/cmd_flash.c | 15 | ||||
-rw-r--r-- | common/cmd_jffs2.c | 6 | ||||
-rw-r--r-- | common/cmd_mem.c | 47 | ||||
-rw-r--r-- | common/cmd_misc.c | 43 | ||||
-rw-r--r-- | common/cmd_mtdparts.c | 91 | ||||
-rw-r--r-- | common/cmd_nand.c | 34 | ||||
-rw-r--r-- | common/cmd_nvedit.c | 12 | ||||
-rw-r--r-- | common/cmd_yaffs2.c | 153 | ||||
-rw-r--r-- | common/env_common.c | 17 | ||||
-rw-r--r-- | common/env_nand.c | 161 | ||||
-rw-r--r-- | common/lcd.c | 500 |
14 files changed, 929 insertions, 185 deletions
diff --git a/common/Makefile b/common/Makefile index 224b7cc7127..f3ad4bdd63b 100644 --- a/common/Makefile +++ b/common/Makefile @@ -160,6 +160,7 @@ COBJS-$(CONFIG_USB_STORAGE) += usb_storage.o endif COBJS-$(CONFIG_CMD_XIMG) += cmd_ximg.o COBJS-$(CONFIG_YAFFS2) += cmd_yaffs2.o +COBJS-$(CONFIG_YAFFS2_NEW) += cmd_yaffs2.o # others COBJS-$(CONFIG_DDR_SPD) += ddr_spd.o diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c index 75924f8aac6..a5a2930c40b 100644 --- a/common/cmd_bdinfo.c +++ b/common/cmd_bdinfo.c @@ -350,6 +350,11 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #endif print_num("relocaddr", gd->relocaddr); print_num("reloc off", gd->reloc_off); +#ifdef CONFIG_GDB_SECTION_STARTS + print_num("data_start", gd->data_start); + print_num("rodata_start", gd->rodata_start); + print_num("bss_start", gd->bss_start); +#endif print_num("irq_sp", gd->irq_sp); /* irq stack pointer */ print_num("sp start ", gd->start_addr_sp); print_num("FB base ", gd->fb_base); @@ -462,3 +467,18 @@ U_BOOT_CMD( "print Board Info structure", "" ); + +#ifdef CONFIG_GDB_SECTION_STARTS +int do_gdb_debug(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + printf("add-symbol-file u-boot %#lx -s .data %#lx \\\n\t-s .rodata %#lx -s .bss %#lx\n", + gd->relocaddr, gd->data_start, gd->rodata_start, gd->bss_start); + return 0; +} + +U_BOOT_CMD( + gdb_debug, 1, 1, do_gdb_debug, + "print gdb 'add-symbol-file' command", + "" +); +#endif diff --git a/common/cmd_cache.c b/common/cmd_cache.c index 5cdd8341f28..5ece6572849 100644 --- a/common/cmd_cache.c +++ b/common/cmd_cache.c @@ -59,6 +59,15 @@ int do_dcache ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) break; case 1: dcache_enable (); break; + default: +#ifdef CONFIG_ARM + if (!strcmp(argv[1], "flush")) { + /* Flush all of memory */ + flush_cache(0, ~0); + return 0; + } +#endif + return cmd_usage(cmdtp); } /* FALL TROUGH */ case 1: /* get status */ @@ -93,6 +102,11 @@ U_BOOT_CMD( U_BOOT_CMD( dcache, 2, 1, do_dcache, "enable or disable data cache", +#ifdef CONFIG_ARM + "[on, off, flush]\n" + " - enable, disable, or flush data (writethrough) cache" +#else "[on, off]\n" " - enable or disable data (writethrough) cache" +#endif ); diff --git a/common/cmd_flash.c b/common/cmd_flash.c index bd49b796c64..1b954619e98 100644 --- a/common/cmd_flash.c +++ b/common/cmd_flash.c @@ -33,12 +33,7 @@ #if defined(CONFIG_CMD_MTDPARTS) #include <jffs2/jffs2.h> - -/* partition handling routines */ -int mtdparts_init(void); -int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num); -int find_dev_and_part(const char *id, struct mtd_device **dev, - u8 *part_num, struct part_info **part); +#include "mtd_parts.h" #endif #ifndef CONFIG_SYS_NO_FLASH @@ -359,9 +354,9 @@ int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #if defined(CONFIG_CMD_MTDPARTS) /* erase <part-id> - erase partition */ - if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num) == 0)) { + if ((argc == 2) && (mtd_id_parse(argv[1], NULL, &dev_type, &dev_num, 0) == 0)) { mtdparts_init(); - if (find_dev_and_part(argv[1], &dev, &pnum, &part) == 0) { + if (find_dev_and_part(argv[1], &dev, &pnum, &part, 0) == 0) { if (dev->id->type == MTD_DEV_TYPE_NOR) { bank = dev->id->num; info = &flash_info[bank]; @@ -555,9 +550,9 @@ int do_protect (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) #if defined(CONFIG_CMD_MTDPARTS) /* protect on/off <part-id> */ - if ((argc == 3) && (mtd_id_parse(argv[2], NULL, &dev_type, &dev_num) == 0)) { + if ((argc == 3) && (mtd_id_parse(argv[2], NULL, &dev_type, &dev_num, 0) == 0)) { mtdparts_init(); - if (find_dev_and_part(argv[2], &dev, &pnum, &part) == 0) { + if (find_dev_and_part(argv[2], &dev, &pnum, &part, 0) == 0) { if (dev->id->type == MTD_DEV_TYPE_NOR) { bank = dev->id->num; info = &flash_info[bank]; diff --git a/common/cmd_jffs2.c b/common/cmd_jffs2.c index 27296ddd7d6..ecb70908298 100644 --- a/common/cmd_jffs2.c +++ b/common/cmd_jffs2.c @@ -106,6 +106,8 @@ #include <onenand_uboot.h> #endif +#include "mtd_parts.h" + /* enable/disable debugging messages */ #define DEBUG_JFFS #undef DEBUG_JFFS @@ -205,6 +207,7 @@ static int mtd_device_validate(u8 type, u8 num, u32 *size) return 1; } +#if 0 /** * Parse device id string <dev-id> := 'nand'|'nor'|'onenand'<dev-num>, * return device type and number. @@ -244,6 +247,7 @@ static int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *d *ret_id = p; return 0; } +#endif /* * 'Static' version of command line mtdparts_init() routine. Single partition on @@ -378,7 +382,7 @@ int mtdparts_init(void) dev_name = "nor0"; #endif - if ((mtd_id_parse(dev_name, NULL, &id->type, &id->num) != 0) || + if ((mtd_id_parse(dev_name, NULL, &id->type, &id->num, 0) != 0) || (mtd_device_validate(id->type, id->num, &size) != 0)) { printf("incorrect device: %s%d\n", MTD_DEV_TYPE(id->type), id->num); free(current_mtd_dev); diff --git a/common/cmd_mem.c b/common/cmd_mem.c index a5576aaab00..b6804dd87e7 100644 --- a/common/cmd_mem.c +++ b/common/cmd_mem.c @@ -1264,3 +1264,50 @@ U_BOOT_CMD( "[.b, .w, .l] address value delay(ms)" ); #endif /* CONFIG_MX_CYCLIC */ + +#ifdef CONFIG_CMD_HEXDUMP +#include <linux/ctype.h> + +int do_hd ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + char *src; + int i, j, len; + if (argc < 3) { + cmd_usage(cmdtp); + return 1; + } + + src = (char *)simple_strtoul(argv[1], NULL, 16); + len = simple_strtoul(argv[2], NULL, 16); + + while (len > 0) { + printf("%p ", src); + j = (len > 16) ? 16 : len; + for (i=0; i<16; ++i) { + if (i < j) + printf("%02x ", src[i]); + else + printf(" "); + if (i == 7) + printf(" "); + } + printf(" |"); + for (i=0; i<j; ++i) { + if (isascii(src[i]) && isprint(src[i])) + printf("%c", src[i]); + else + printf("."); + } + printf("|\n"); + src += j; + len -= j; + } + return 0; +} + +U_BOOT_CMD( + hd, 3, 1, do_hd, + "hexdump a memory region", + "srcaddr length" +); +#endif diff --git a/common/cmd_misc.c b/common/cmd_misc.c index 061b1bbad01..c4d266c3e80 100644 --- a/common/cmd_misc.c +++ b/common/cmd_misc.c @@ -53,3 +53,46 @@ U_BOOT_CMD( "N\n" " - delay execution for N seconds (N is _decimal_ !!!)" ); + +#ifdef CONFIG_CMD_TIME +int do_time (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + ulong start; + ulong delta; + cmd_tbl_t *cmdtp2; + int ret; + unsigned int secs, msecs; + + if (argc < 2) { + cmd_usage(cmdtp); + return 1; + } + + cmdtp2 = find_cmd(argv[1]); + if (!cmdtp2) { + printf ("Unknown command '%s' - try help\n", argv[1]); + return 1; + } + + start = get_timer(0); + + /* Execute command */ + ret = (cmdtp2->cmd)(cmdtp2, flag, argc-1, argv+1); + + delta = get_timer(start); + + secs = (delta * 1000) / CONFIG_SYS_HZ; + msecs = secs % 1000; + secs /= 1000; + + printf("'%s' took %u.%03u seconds\n", argv[1], secs, msecs); + return ret; +} + +U_BOOT_CMD( + time , CONFIG_SYS_MAXARGS, 1, do_time, + "time execution of command", + "command to time\n" + " - time execution of command in seconds" +); +#endif diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c index 5481c885d3e..d0639f6cd21 100644 --- a/common/cmd_mtdparts.c +++ b/common/cmd_mtdparts.c @@ -106,6 +106,8 @@ #include <onenand_uboot.h> #endif +#include "mtd_parts.h" + /* special size referring to all the remaining space in a partition */ #define SIZE_REMAINING 0xFFFFFFFF @@ -1037,9 +1039,10 @@ static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_ * @param ret_id output pointer to next char after parse completes (output) * @param dev_type parsed device type (output) * @param dev_num parsed device number (output) - * @return 0 on success, 1 otherwise + * @param quiet non-zero to suppress messages + * @return 0 on success, -ERRNO otherwise */ -int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num) +int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num, int quiet) { const char *p = id; @@ -1054,13 +1057,15 @@ int mtd_id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num) *dev_type = MTD_DEV_TYPE_ONENAND; p += 7; } else { - printf("incorrect device type in %s\n", id); - return 1; + if (!quiet) + printf("incorrect device type in %s\n", id); + return -ENODEV; } if (!isdigit(*p)) { - printf("incorrect device number in %s\n", id); - return 1; + if (!quiet) + printf("incorrect device number in %s\n", id); + return -ERANGE; } *dev_num = simple_strtoul(p, (char **)&p, 0); @@ -1340,14 +1345,16 @@ static void list_partitions(void) * @param dev pointer to the requested device (output) * @param part_num verified partition number (output) * @param part pointer to requested partition (output) + * @param quiet non-zero to suppress messages * @return 0 on success, 1 otherwise */ int find_dev_and_part(const char *id, struct mtd_device **dev, - u8 *part_num, struct part_info **part) + u8 *part_num, struct part_info **part, int quiet) { struct list_head *dentry, *pentry; u8 type, dnum, pnum; const char *p; + int ret; debug("--- find_dev_and_part ---\nid = %s\n", id); @@ -1367,26 +1374,31 @@ int find_dev_and_part(const char *id, struct mtd_device **dev, *part = NULL; *part_num = 0; - if (mtd_id_parse(p, &p, &type, &dnum) != 0) - return 1; + ret = mtd_id_parse(p, &p, &type, &dnum, quiet); + if (ret != 0) + return ret; if ((*p++ != ',') || (*p == '\0')) { - printf("no partition number specified\n"); + if (!quiet) + printf("no partition number specified\n"); return 1; } pnum = simple_strtoul(p, (char **)&p, 0); if (*p != '\0') { - printf("unexpected trailing character '%c'\n", *p); + if (!quiet) + printf("unexpected trailing character '%c'\n", *p); return 1; } if ((*dev = device_find(type, dnum)) == NULL) { - printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum); + if (!quiet) + printf("no such device %s%d\n", MTD_DEV_TYPE(type), dnum); return 1; } if ((*part = mtd_part_info(*dev, pnum)) == NULL) { - printf("no such partition\n"); + if (!quiet) + printf("no such partition\n"); *dev = NULL; return 1; } @@ -1408,7 +1420,7 @@ static int delete_partition(const char *id) struct mtd_device *dev; struct part_info *part; - if (find_dev_and_part(id, &dev, &pnum, &part) == 0) { + if (find_dev_and_part(id, &dev, &pnum, &part, 0) == 0) { debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08x@0x%08x\n", MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum, @@ -1615,7 +1627,7 @@ static int parse_mtdids(const char *const ids) ret = 1; /* parse 'nor'|'nand'|'onenand'<dev-num> */ - if (mtd_id_parse(p, &p, &type, &num) != 0) + if (mtd_id_parse(p, &p, &type, &num, 0) != 0) break; if (*p != '=') { @@ -1813,7 +1825,7 @@ int mtdparts_init(void) debug("--- getting current partition: %s\n", tmp_ep); - if (find_dev_and_part(tmp_ep, &cdev, &pnum, &p) == 0) { + if (find_dev_and_part(tmp_ep, &cdev, &pnum, &p, 0) == 0) { current_mtd_dev = cdev; current_mtd_partnum = pnum; current_save(); @@ -1896,7 +1908,7 @@ int do_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) return 1; } - if (find_dev_and_part(argv[1], &dev, &pnum, &part) != 0) + if (find_dev_and_part(argv[1], &dev, &pnum, &part, 0) != 0) return 1; current_mtd_dev = dev; @@ -1963,7 +1975,7 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct mtdids *id; struct part_info *p; - if (mtd_id_parse(argv[2], NULL, &type, &num) != 0) + if (mtd_id_parse(argv[2], NULL, &type, &num, 0) != 0) return 1; if ((id = id_find(type, num)) == NULL) { @@ -2090,3 +2102,46 @@ U_BOOT_CMD( "<ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)" ); /***************************************************/ + +int mtd_get_part_priv(const char *partname, int *idx, struct mtd_device **dev, loff_t *off, loff_t *size, void **cookie, void **priv, int quiet) +{ + int ret; + u8 pnum; + struct mtd_device *mtd_dev; + struct part_info *part; + + ret = mtdparts_init(); + if (ret) + return ret; + + ret = find_dev_and_part(partname, &mtd_dev, &pnum, &part, quiet); + if (ret) + return ret; + + if (mtd_dev->id->type != MTD_DEV_TYPE_NAND) { + if (!quiet) + puts("not a NAND device\n"); + return -1; + } + + *off = part->offset; + *dev = mtd_dev; + *size = part->size; + *idx = mtd_dev->id->num; + + *cookie = part; + *priv = part->jffs2_priv; + + ret = nand_set_dev(*idx); + if (ret) + return ret; + + return 0; +} + +void mtd_set_part_priv(void *cookie, void *priv) +{ + struct part_info *part = cookie; + + part->jffs2_priv = priv; +} diff --git a/common/cmd_nand.c b/common/cmd_nand.c index 44c4d1f89ce..9b7a0a73e3a 100644 --- a/common/cmd_nand.c +++ b/common/cmd_nand.c @@ -29,12 +29,7 @@ #include <nand.h> #if defined(CONFIG_CMD_MTDPARTS) - -/* partition handling routines */ -int mtdparts_init(void); -int id_parse(const char *id, const char **ret_id, u8 *dev_type, u8 *dev_num); -int find_dev_and_part(const char *id, struct mtd_device **dev, - u8 *part_num, struct part_info **part); +#include "mtd_parts.h" #endif static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) @@ -98,7 +93,7 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat) /* ------------------------------------------------------------------------- */ -static int set_dev(int dev) +int nand_set_dev(int dev) { if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE || !nand_info[dev].name) { @@ -148,7 +143,7 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size) if (ret) return ret; - ret = find_dev_and_part(partname, &dev, &pnum, &part); + ret = find_dev_and_part(partname, &dev, &pnum, &part, 0); if (ret) return ret; @@ -161,7 +156,7 @@ static int get_part(const char *partname, int *idx, loff_t *off, loff_t *size) *size = part->size; *idx = dev->id->num; - ret = set_dev(*idx); + ret = nand_set_dev(*idx); if (ret) return ret; @@ -283,7 +278,7 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[]) return 1; } - set_dev(0); + nand_set_dev(0); if (!strcmp(cmd, "get")) { ret = get_nand_env_oob(nand, &nand_env_oob_offset); @@ -423,7 +418,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) } dev = (int)simple_strtoul(argv[2], NULL, 10); - set_dev(dev); + nand_set_dev(dev); return 0; } @@ -637,6 +632,17 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) return 1; } +#ifdef CONFIG_MTD_DEBUG + if (strcmp(cmd, "debug") == 0) { + if (argc == 3) { + ulong val = simple_strtoul(argv[2], NULL, 16); + mtd_debug_verbose = val; + } else + printf("%d\n", mtd_debug_verbose); + return 1; + } +#endif + #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK if (strcmp(cmd, "lock") == 0) { int tight = 0; @@ -718,6 +724,10 @@ U_BOOT_CMD( "nand env.oob set off|partition - set enviromnent offset\n" "nand env.oob get - get environment offset" #endif +#ifdef CONFIG_MTD_DEBUG + "\n" + "nand debug [level] - display or set the MTD debug level" +#endif ); static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand, @@ -827,7 +837,7 @@ int do_nandboot(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) if (argc >= 2) { char *p = (argc == 2) ? argv[1] : argv[2]; if (!(str2long(p, &addr)) && (mtdparts_init() == 0) && - (find_dev_and_part(p, &dev, &pnum, &part) == 0)) { + (find_dev_and_part(p, &dev, &pnum, &part, 0) == 0)) { if (dev->id->type != MTD_DEV_TYPE_NAND) { puts("Not a NAND device\n"); return 1; diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index b2c88babc41..91728f7109e 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -381,6 +381,13 @@ int do_env_set(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (argc < 2) return cmd_usage(cmdtp); +#ifdef CONFIG_CHECK_SETENV + if (setenv_reserved_name(argv[1])) { + printf("## Error: can not set variable \"%s\"\n", argv[1]); + return 1; + } +#endif + return _do_env_set(flag, argc, argv); } @@ -584,6 +591,11 @@ static int do_env_default(cmd_tbl_t *cmdtp, int flag, int argc, char * const arg return cmd_usage(cmdtp); set_default_env("## Resetting to default environment\n"); +#if defined(CONFIG_TOUCHUP_ENV) + /* On a restored environment, need to initialise board + * specific variables */ + touchup_env(); +#endif return 0; } diff --git a/common/cmd_yaffs2.c b/common/cmd_yaffs2.c index 7c01ea2a251..9fd037afb2f 100644 --- a/common/cmd_yaffs2.c +++ b/common/cmd_yaffs2.c @@ -11,11 +11,10 @@ extern void cmd_yaffs_mount(char *mp); extern void cmd_yaffs_umount(char *mp); -extern void cmd_yaffs_read_file(char *fn); -extern void cmd_yaffs_write_file(char *fn,char bval,int sizeOfFile); extern void cmd_yaffs_ls(const char *mountpt, int longlist); +extern int cmd_yaffs_df(const char *path, loff_t *size); extern void cmd_yaffs_mwrite_file(char *fn, char *addr, int size); -extern void cmd_yaffs_mread_file(char *fn, char *addr); +extern void cmd_yaffs_mread_file(char *fn, char *addr, long *size); extern void cmd_yaffs_mkdir(const char *dir); extern void cmd_yaffs_rmdir(const char *dir); extern void cmd_yaffs_rm(const char *path); @@ -26,69 +25,81 @@ extern int yaffs_DumpDevStruct(const char *path); int do_ymount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *mtpoint = argv[1]; - cmd_yaffs_mount(mtpoint); + if (argc < 2) + return cmd_usage(cmdtp); - return(0); -} - -int do_yumount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) -{ - char *mtpoint = argv[1]; - cmd_yaffs_umount(mtpoint); + cmd_yaffs_mount(argv[1]); return(0); } -int do_yls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_yumount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *dirname = argv[argc-1]; + if (argc < 2) + return cmd_usage(cmdtp); - cmd_yaffs_ls(dirname, (argc>2)?1:0); + cmd_yaffs_umount(argv[1]); return(0); } -int do_yrd (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_yls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = argv[1]; - printf ("Reading file %s ", filename); - - cmd_yaffs_read_file(filename); + if (argc < 2) + return cmd_usage(cmdtp); + cmd_yaffs_ls(argv[argc-1], (argc>2)?1:0); - printf ("done\n"); return(0); } -int do_ywr (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +int do_ydf (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = argv[1]; - ulong value = simple_strtoul(argv[2], NULL, 16); - ulong numValues = simple_strtoul(argv[3], NULL, 16); + loff_t space; + int ret; - printf ("Writing value (%x) %x times to %s... ", value, numValues, filename); + if (argc < 2) + return cmd_usage(cmdtp); - cmd_yaffs_write_file(filename,value,numValues); + ret = cmd_yaffs_df(argv[1], &space); + if (!ret) + printf("Free Space: %lluKiB\n", space / 1024); - printf ("done\n"); - return(0); + return !!ret; } + int do_yrdm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = argv[1]; - ulong addr = simple_strtoul(argv[2], NULL, 16); + long size; + char buf[12]; + char *filename; + ulong addr; + + if (argc < 3) + return cmd_usage(cmdtp); + + filename = argv[2]; + addr = simple_strtoul(argv[1], NULL, 16); - cmd_yaffs_mread_file(filename, (char *)addr); + cmd_yaffs_mread_file(filename, (char *)addr, &size); + sprintf(buf, "%lX", size); + setenv("filesize", buf); return(0); } int do_ywrm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *filename = argv[1]; - ulong addr = simple_strtoul(argv[2], NULL, 16); - ulong size = simple_strtoul(argv[3], NULL, 16); + char *filename; + ulong addr; + ulong size; + + if (argc < 4) + return cmd_usage(cmdtp); + + filename = argv[1]; + addr = simple_strtoul(argv[2], NULL, 16); + size = simple_strtoul(argv[3], NULL, 16); cmd_yaffs_mwrite_file(filename, (char *)addr, size); @@ -97,35 +108,44 @@ int do_ywrm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int do_ymkdir (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *dirname = argv[1]; - - cmd_yaffs_mkdir(dirname); + if (argc < 2) + return cmd_usage(cmdtp); + + cmd_yaffs_mkdir(argv[1]); return(0); } int do_yrmdir (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *dirname = argv[1]; + if (argc < 2) + return cmd_usage(cmdtp); - cmd_yaffs_rmdir(dirname); + cmd_yaffs_rmdir(argv[1]); return(0); } int do_yrm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *path = argv[1]; + if (argc < 2) + return cmd_usage(cmdtp); - cmd_yaffs_rm(path); + cmd_yaffs_rm(argv[1]); return(0); } int do_ymv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *oldPath = argv[1]; - char *newPath = argv[2]; + char *oldPath; + char *newPath; + + if (argc < 3) + return cmd_usage(cmdtp); + + oldPath = argv[1]; + newPath = argv[2]; cmd_yaffs_mv(newPath, oldPath); @@ -134,7 +154,12 @@ int do_ymv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) int do_ydump (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { - char *dirname = argv[1]; + char *dirname; + + if (argc < 2) + return cmd_usage(cmdtp); + + dirname = argv[1]; if (yaffs_DumpDevStruct(dirname) != 0) printf("yaffs_DumpDevStruct returning error when dumping path: , %s\n", dirname); return 0; @@ -142,62 +167,56 @@ int do_ydump (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) U_BOOT_CMD( ymount, 3, 0, do_ymount, - "mount yaffs", - "" + "YAFFS mount", + "<partition>" ); U_BOOT_CMD( yumount, 3, 0, do_yumount, - "unmount yaffs", - "" + "YAFFS unmount", + "<partition>" ); U_BOOT_CMD( yls, 4, 0, do_yls, - "yaffs ls", - "[-l] name" -); - -U_BOOT_CMD( - yrd, 2, 0, do_yrd, - "read file from yaffs", - "filename" + "YAFFS ls", + "[-l] <name>" ); U_BOOT_CMD( - ywr, 4, 0, do_ywr, - "write file to yaffs", - "filename value num_vlues" + ydf, 2, 0, do_ydf, + "YAFFS disk free", + "[-l] <dirname>" ); U_BOOT_CMD( yrdm, 3, 0, do_yrdm, - "read file to memory from yaffs", - "filename offset" + "YAFFS read file to memory", + "<addr> <filename>" ); U_BOOT_CMD( ywrm, 4, 0, do_ywrm, - "write file from memory to yaffs", - "filename offset size" + "YAFFS write file from memory", + "<filename> <addr> <size>" ); U_BOOT_CMD( ymkdir, 2, 0, do_ymkdir, "YAFFS mkdir", - "dirname" + "<dirname>" ); U_BOOT_CMD( yrmdir, 2, 0, do_yrmdir, "YAFFS rmdir", - "dirname" + "<dirname>" ); U_BOOT_CMD( yrm, 2, 0, do_yrm, "YAFFS rm", - "path" + "<path>" ); U_BOOT_CMD( diff --git a/common/env_common.c b/common/env_common.c index c3e6388ac0b..04a947e92ba 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -196,6 +196,14 @@ void set_default_env(const char *s) gd->flags |= GD_FLG_ENV_READY; } +int env_check_valid(const char *buf) +{ + env_t *ep = (env_t *)buf; + uint32_t crc; + + memcpy(&crc, &ep->crc, sizeof(crc)); + return crc32(0, ep->data, ENV_SIZE) == crc; +} /* * Check if CRC is valid and (if yes) import the environment. * Note that "buf" may or may not be aligned. @@ -205,11 +213,7 @@ int env_import(const char *buf, int check) env_t *ep = (env_t *)buf; if (check) { - uint32_t crc; - - memcpy(&crc, &ep->crc, sizeof(crc)); - - if (crc32(0, ep->data, ENV_SIZE) != crc) { + if (!env_check_valid(buf)) { set_default_env("!bad CRC"); return 0; } @@ -244,6 +248,9 @@ void env_relocate (void) } else { env_relocate_spec (); } +#ifdef CONFIG_TOUCHUP_ENV + touchup_env(); +#endif } #ifdef CONFIG_AUTO_COMPLETE diff --git a/common/env_nand.c b/common/env_nand.c index 14446a6a579..facb4b3016f 100644 --- a/common/env_nand.c +++ b/common/env_nand.c @@ -153,30 +153,64 @@ int env_init(void) * The legacy NAND code saved the environment in the first NAND device i.e., * nand_dev_desc + 0. This is also the behaviour using the new NAND code. */ -int writeenv(size_t offset, u_char *buf) +static int writeenv(size_t offset, u_char *buf) { size_t end = offset + CONFIG_ENV_RANGE; size_t amount_saved = 0; size_t blocksize, len; - + int ret, ncopies = 0; u_char *char_ptr; +#if defined(CONFIG_NAND_MULTIPLE_ECC) + int current_ecc_method; +#endif + +#if defined(CONFIG_NAND_MULTIPLE_ECC) + nand_switch_ecc_default(¤t_ecc_method); +#endif blocksize = nand_info[0].erasesize; len = min(blocksize, CONFIG_ENV_SIZE); - while (amount_saved < CONFIG_ENV_SIZE && offset < end) { + while (offset < end) { if (nand_block_isbad(&nand_info[0], offset)) { offset += blocksize; } else { char_ptr = &buf[amount_saved]; - if (nand_write(&nand_info[0], offset, &len, - char_ptr)) - return 1; - offset += blocksize; - amount_saved += len; + /* Data written can not straddle a block in case + one of the two blocks goes bad */ + if ((offset & ~(blocksize - 1)) != ((offset + len - 1) & ~(blocksize - 1))) + offset = (offset + blocksize - 1) & ~(blocksize-1); + + if (offset >= end) + break; + + ret = nand_write(&nand_info[0], offset, &len, + char_ptr); + + if (ret) { + /* Need to move offset forward by len, + * then to the start of the next block, + * reset amount_amount saved to start + * at the beginning of the environment */ + offset += len; + offset = (offset + blocksize - 1) & ~(blocksize - 1); + amount_saved = 0; + } else { + amount_saved += len; + if (amount_saved >= CONFIG_ENV_SIZE) { + ncopies++; + amount_saved = 0; + } + } + offset += len; } } - if (amount_saved != CONFIG_ENV_SIZE) + +#if defined(CONFIG_NAND_MULTIPLE_ECC) + nand_switch_ecc_method(current_ecc_method); +#endif + + if (!ncopies) return 1; return 0; @@ -211,8 +245,9 @@ int saveenv(void) if(gd->env_valid == 1) { puts("Erasing redundant NAND...\n"); nand_erase_options.offset = CONFIG_ENV_OFFSET_REDUND; - if (nand_erase_opts(&nand_info[0], &nand_erase_options)) + if (nand_erase_opts(&nand_info[0], &nand_erase_options)) { return 1; + } puts("Writing to redundant NAND... "); ret = writeenv(CONFIG_ENV_OFFSET_REDUND, @@ -220,8 +255,9 @@ int saveenv(void) } else { puts("Erasing NAND...\n"); nand_erase_options.offset = CONFIG_ENV_OFFSET; - if (nand_erase_opts(&nand_info[0], &nand_erase_options)) + if (nand_erase_opts(&nand_info[0], &nand_erase_options)) { return 1; + } puts("Writing to NAND... "); ret = writeenv(CONFIG_ENV_OFFSET, @@ -263,8 +299,9 @@ int saveenv(void) env_new.crc = crc32(0, env_new.data, ENV_SIZE); puts("Erasing Nand...\n"); - if (nand_erase_opts(&nand_info[0], &nand_erase_options)) + if (nand_erase_opts(&nand_info[0], &nand_erase_options)) { return 1; + } puts("Writing to Nand... "); if (writeenv(CONFIG_ENV_OFFSET, (u_char *)&env_new)) { @@ -273,40 +310,123 @@ int saveenv(void) } puts("done\n"); + return ret; } #endif /* CONFIG_ENV_OFFSET_REDUND */ #endif /* CMD_SAVEENV */ -int readenv(size_t offset, u_char * buf) +#ifdef CONFIG_ENV_OFFSET_REDUND +static int readenv(size_t offset, u_char * buf) { size_t end = offset + CONFIG_ENV_RANGE; size_t amount_loaded = 0; size_t blocksize, len; - u_char *char_ptr; +#if defined(CONFIG_NAND_MULTIPLE_ECC) + int current_ecc_method; +#endif blocksize = nand_info[0].erasesize; if (!blocksize) return 1; len = min(blocksize, CONFIG_ENV_SIZE); +#if defined(CONFIG_NAND_MULTIPLE_ECC) + nand_switch_ecc_default(¤t_ecc_method); +#endif + while (amount_loaded < CONFIG_ENV_SIZE && offset < end) { if (nand_block_isbad(&nand_info[0], offset)) { offset += blocksize; } else { char_ptr = &buf[amount_loaded]; - if (nand_read_skip_bad(&nand_info[0], offset, &len, char_ptr)) + if (nand_read_skip_bad(&nand_info[0], offset, &len, char_ptr)) { +#if defined(CONFIG_NAND_MULTIPLE_ECC) + nand_switch_ecc_method(current_ecc_method); +#endif + return 1; + } offset += blocksize; amount_loaded += len; } } +#if defined(CONFIG_NAND_MULTIPLE_ECC) + nand_switch_ecc_method(current_ecc_method); +#endif if (amount_loaded != CONFIG_ENV_SIZE) return 1; return 0; } +#else /* ! CONFIG_ENV_OFFSET_REDUND */ +/* Read the environment, checking along the way. return 0 if valid + * environment or no environment is found, negative on error */ +static int readenv(size_t offset, u_char * buf) +{ + size_t end = offset + CONFIG_ENV_RANGE; + size_t amount_loaded = 0; + size_t blocksize, len; + u_char *char_ptr; + int ret; +#if defined(CONFIG_NAND_MULTIPLE_ECC) + int current_ecc_method; +#endif + + blocksize = nand_info[0].erasesize; + if (!blocksize) + return -1; + len = min(blocksize, CONFIG_ENV_SIZE); + +#if defined(CONFIG_NAND_MULTIPLE_ECC) + nand_switch_ecc_default(¤t_ecc_method); +#endif + + while (offset < end) { + if (nand_block_isbad(&nand_info[0], offset)) { + offset += blocksize; + } else { + char_ptr = &buf[amount_loaded]; + /* Data read can not straddle a block in case + one of the two blocks goes bad */ + if ((offset & ~(blocksize - 1)) != ((offset + len - 1) & ~(blocksize - 1))) + offset = (offset + blocksize - 1) & ~(blocksize-1); + if (offset >= end) + break; + + ret = nand_read(&nand_info[0], offset, &len, char_ptr); + + if (ret) { + /* Need to move offset forward by len, + * then to the start of the next block, + * reset amount_amount saved to start + * at the beginning of the environment */ + offset += len; + offset = (offset + blocksize - 1) & ~(blocksize - 1); + amount_loaded = 0; + } else { + amount_loaded += len; + if (amount_loaded >= CONFIG_ENV_SIZE) { + if (env_check_valid(buf)) + goto found; + amount_loaded = 0; + } + } + offset += len; + } + } + +found: +#if defined(CONFIG_NAND_MULTIPLE_ECC) + nand_switch_ecc_method(current_ecc_method); +#endif + if (amount_loaded != CONFIG_ENV_SIZE) + return 0; + + return 1; +} +#endif #ifdef CONFIG_ENV_OFFSET_OOB int get_nand_env_oob(nand_info_t *nand, unsigned long *result) @@ -346,6 +466,7 @@ void env_relocate_spec(void) #if !defined(ENV_IS_EMBEDDED) int crc1_ok = 0, crc2_ok = 0; env_t *ep, *tmp_env1, *tmp_env2; + int ret; tmp_env1 = (env_t *)malloc(CONFIG_ENV_SIZE); tmp_env2 = (env_t *)malloc(CONFIG_ENV_SIZE); @@ -358,11 +479,11 @@ void env_relocate_spec(void) return; } - if (readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1)) - puts("No Valid Environment Area found\n"); + ret = readenv(CONFIG_ENV_OFFSET, (u_char *) tmp_env1); + printf("%sValid Environment Area found\n", ret ? "No ":""); - if (readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2)) - puts("No Valid Redundant Environment Area found\n"); + ret = readenv(CONFIG_ENV_OFFSET_REDUND, (u_char *) tmp_env2); + printf("%sValid Redundant Environment Area found\n", ret ? "No ":""); crc1_ok = (crc32(0, tmp_env1->data, ENV_SIZE) == tmp_env1->crc); crc2_ok = (crc32(0, tmp_env2->data, ENV_SIZE) == tmp_env2->crc); @@ -433,7 +554,7 @@ void env_relocate_spec (void) #endif ret = readenv(CONFIG_ENV_OFFSET, (u_char *)buf); - if (ret) { + if (ret < 0) { set_default_env("!readenv() failed"); return; } diff --git a/common/lcd.c b/common/lcd.c index 0555ab4fb72..85a946828e5 100644 --- a/common/lcd.c +++ b/common/lcd.c @@ -35,12 +35,16 @@ #include <stdarg.h> #include <linux/types.h> #include <stdio_dev.h> +#include <div64.h> +#include <malloc.h> #if defined(CONFIG_POST) #include <post.h> #endif #include <lcd.h> #include <watchdog.h> +int console_color_black, console_color_white; + #if defined CONFIG_PXA250 || defined CONFIG_PXA27X || defined CONFIG_CPU_MONAHANS #include <asm/byteorder.h> #endif @@ -63,20 +67,22 @@ /************************************************************************/ #ifdef CONFIG_LCD_LOGO # include <bmp_logo.h> /* Get logo data, width and height */ -# if (CONSOLE_COLOR_WHITE >= BMP_LOGO_OFFSET) && (LCD_BPP != LCD_COLOR16) -# error Default Color Map overlaps with Logo Color Map -# endif #endif DECLARE_GLOBAL_DATA_PTR; ulong lcd_setmem (ulong addr); -static void lcd_drawchars (ushort x, ushort y, uchar *str, int count); +static void lcd_drawchars_16 (ushort x, ushort y, uchar *str, int count); +static void lcd_drawchars_24 (ushort x, ushort y, uchar *str, int count); +static void lcd_drawchars_x (ushort x, ushort y, uchar *str, int count); + +static void (*lcd_drawchars) (ushort x, ushort y, uchar *str, int count); static inline void lcd_puts_xy (ushort x, ushort y, uchar *s); static inline void lcd_putc_xy (ushort x, ushort y, uchar c); static int lcd_init (void *lcdbase); +static int lcd_init_colors (void); static int lcd_clear (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]); static void *lcd_logo (void); @@ -139,12 +145,9 @@ static inline void console_newline (void) /*----------------------------------------------------------------------*/ -void lcd_putc (const char c) +void _lcd_putc (const char c) { - if (!lcd_is_enabled) { - serial_putc(c); - return; - } + int i; switch (c) { case '\r': console_col = 0; @@ -165,6 +168,13 @@ void lcd_putc (const char c) case '\b': console_back(); return; + case '\f': /* Clear to EOL */ + for (i=console_col; i < CONSOLE_COLS; ++i) + lcd_putc_xy (i * VIDEO_FONT_WIDTH, + console_row * VIDEO_FONT_HEIGHT, + ' '); + return; + default: lcd_putc_xy (console_col * VIDEO_FONT_WIDTH, console_row * VIDEO_FONT_HEIGHT, c); @@ -176,6 +186,15 @@ void lcd_putc (const char c) /* NOTREACHED */ } +void lcd_putc (const char c) +{ + if (!lcd_is_enabled) { + serial_putc(c); + return; + } + _lcd_putc(c); +} + /*----------------------------------------------------------------------*/ void lcd_puts (const char *s) @@ -204,11 +223,152 @@ void lcd_printf(const char *fmt, ...) lcd_puts(buf); } +#define NUM_ANCHORS 5 +struct anchors { + int row, col; +} anchors[NUM_ANCHORS]; + +void output_lcd_string(char *p) +{ + char c; + int row,col; + int tmp; + char *s, *r; + int idx; + + while ((c = *p++) != '\0') { + if (c == '/' && *p) { + switch(*p) { + case 'g': + /* Set cursor to anchor idx+'A' */ + if (p[1]) { + idx = p[1]-'A'; + if (idx >= 0 && idx < NUM_ANCHORS) { + console_row = anchors[idx].row; + console_col = anchors[idx].col; + } + p++; + } else { + _lcd_putc('/'); + _lcd_putc(*p); + } + break; + case 'a': + /* Set anchor idx+'A' to cursor */ + if (p[1]) { + idx = p[1]-'A'; + if (idx >= 0 && idx < NUM_ANCHORS) { + anchors[idx].row = console_row; + anchors[idx].col = console_col; + } + p++; + } else { + _lcd_putc('/'); + _lcd_putc(*p); + } + break; + case 'A': + /* Goto the lcd_anchor in environment */ + s = getenv("lcd_anchor"); + if (s) { + row = simple_strtoul(s, &r, 0); + if (r && *r==',') { + col = simple_strtoul(r+1, &r, 0); + if (r && !*r) { + if (row >= CONSOLE_ROWS) + row = CONSOLE_ROWS - 1; + if (row >= CONSOLE_COLS) + row = CONSOLE_COLS - 1; + console_row = row; + console_col = col; + } + } + } + break; + case 'p': + /* Cursor position, pos+'A' */ + if (p[1] && p[2]) { + console_row = p[1]-'A'; + console_col = p[2]-'A'; + p+=2; + } else { + _lcd_putc('/'); + _lcd_putc(*p); + } + break; + case 'i': + /* Invert video */ + tmp = lcd_color_fg; + lcd_color_fg = lcd_color_bg; + lcd_color_bg = tmp; + break; + case 'b': + /* Back up the display */ + _lcd_putc('\b'); + break; + case 'r': + /* Carriage return */ + _lcd_putc('\r'); + break; + case 'n': + /* Line feed */ + _lcd_putc('\n'); + break; + case 'k': + /* Clear to end of line */ + _lcd_putc('\f'); + break; + default: + _lcd_putc('/'); + _lcd_putc(*p); + break; + } + p++; + } else { + _lcd_putc(c); + } + } + +#ifdef CONFIG_ARM + /* Flush the cache to make sure display tracks content of memory */ + flush_cache(0, ~0); +#endif +} + +int do_echo_lcd(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int i; + + for (i = 1; i < argc; i++) { + if (i > 1) + _lcd_putc(' '); + output_lcd_string(argv[i]); + } + + return 0; +} + +U_BOOT_CMD( + echo_lcd, CONFIG_SYS_MAXARGS, 1, do_echo_lcd, + "echo args to LCD", + "[args..]\n" + " - echo args to LCD, following escape sequences:\n" +" /pRC - goto row 'R' ('A'+row), column 'C' ('A'+col)\n" +" /aN - save the current position as anchor 'N' ('A'+n)\n" +" /gN - set cursor position to anchor point 'N' ('A'+n)\n" +" /i - invert video colors\n" +" /b - backspace\n" +" /r - carriage return\n" +" /n - carriage return + linefeed\n" +" /k - clear to end of line\n" +" /A - goto lcd_anchor value in environment (R,C in decimal)\n" +); + /************************************************************************/ /* ** Low-Level Graphics Routines */ /************************************************************************/ -static void lcd_drawchars (ushort x, ushort y, uchar *str, int count) +static void lcd_drawchars_unknown (ushort x, ushort y, uchar *str, int count) { uchar *dest; ushort off, row; @@ -261,6 +421,64 @@ static void lcd_drawchars (ushort x, ushort y, uchar *str, int count) } } +static void lcd_drawchars_16 (ushort x, ushort y, uchar *str, int count) +{ + uchar *dest; + ushort off, row; + + dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_COLOR16) / 8); + off = x * (1 << LCD_COLOR16) % 8; + + for (row=0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) { + uchar *s = str; + int i; + ushort *d = (ushort *)dest; + + for (i=0; i<count; ++i) { + uchar c, bits; + + c = *s++; + bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row]; + + for (c=0; c<8; ++c) { + *d++ = (bits & 0x80) ? + lcd_color_fg : lcd_color_bg; + bits <<= 1; + } + } + } +} + +static void lcd_drawchars_24 (ushort x, ushort y, uchar *str, int count) +{ + uchar *dest; + ushort off, row; + + dest = (uchar *)(lcd_base + y * lcd_line_length + x * (1 << LCD_COLOR24) / 8); + off = x * (1 << LCD_COLOR24) % 8; + + for (row=0; row < VIDEO_FONT_HEIGHT; ++row, dest += lcd_line_length) { + uchar *s = str; + int i; + uint *d = (uint *)dest; + + for (i=0; i<count; ++i) { + uchar c, bits; + + c = *s++; + bits = video_fontdata[c * VIDEO_FONT_HEIGHT + row]; + + for (c=0; c<8; ++c) { + *d++ = (bits & 0x80) ? + lcd_color_fg : lcd_color_bg; + bits <<= 1; + } + } + } +} + + + /*----------------------------------------------------------------------*/ static inline void lcd_puts_xy (ushort x, ushort y, uchar *s) @@ -331,10 +549,33 @@ int drv_lcd_init (void) lcd_base = (void *)(gd->fb_base); + debug("%s: lcd_base %p\n", __FUNCTION__, lcd_base); + lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8; + debug("%s: vl_col %u vl_bpix %u lcd_line_length %u\n", __FUNCTION__, + panel_info.vl_col, panel_info.vl_bpix, lcd_line_length); + lcd_init (lcd_base); /* LCD initialization */ + /* lcd_init may setup panel_info structure */ + lcd_line_length = (panel_info.vl_col * NBITS (panel_info.vl_bpix)) / 8; + + debug("%s: vl_col %u vl_bpix %u lcd_line_length %u\n", __FUNCTION__, + panel_info.vl_col, panel_info.vl_bpix, lcd_line_length); + + switch(panel_info.vl_bpix) { + case LCD_COLOR16: + lcd_drawchars = lcd_drawchars_16; + break; + case LCD_COLOR24: + lcd_drawchars = lcd_drawchars_24; + break; + default: + lcd_drawchars = lcd_drawchars_unknown; + break; + } + /* Device initialization */ memset (&lcddev, 0, sizeof (lcddev)); @@ -352,35 +593,21 @@ int drv_lcd_init (void) /*----------------------------------------------------------------------*/ static int lcd_clear (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) { -#if LCD_BPP == LCD_MONOCHROME - /* Setting the palette */ - lcd_initcolregs(); + lcd_init_colors(); -#elif LCD_BPP == LCD_COLOR8 - /* Setting the palette */ - lcd_setcolreg (CONSOLE_COLOR_BLACK, 0, 0, 0); - lcd_setcolreg (CONSOLE_COLOR_RED, 0xFF, 0, 0); - lcd_setcolreg (CONSOLE_COLOR_GREEN, 0, 0xFF, 0); - lcd_setcolreg (CONSOLE_COLOR_YELLOW, 0xFF, 0xFF, 0); - lcd_setcolreg (CONSOLE_COLOR_BLUE, 0, 0, 0xFF); - lcd_setcolreg (CONSOLE_COLOR_MAGENTA, 0xFF, 0, 0xFF); - lcd_setcolreg (CONSOLE_COLOR_CYAN, 0, 0xFF, 0xFF); - lcd_setcolreg (CONSOLE_COLOR_GREY, 0xAA, 0xAA, 0xAA); - lcd_setcolreg (CONSOLE_COLOR_WHITE, 0xFF, 0xFF, 0xFF); -#endif - -#ifndef CONFIG_SYS_WHITE_ON_BLACK - lcd_setfgcolor (CONSOLE_COLOR_BLACK); - lcd_setbgcolor (CONSOLE_COLOR_WHITE); +#ifdef CONFIG_SYS_WHITE_ON_BLACK + lcd_setfgcolor (console_color_white); + lcd_setbgcolor (console_color_black); #else - lcd_setfgcolor (CONSOLE_COLOR_WHITE); - lcd_setbgcolor (CONSOLE_COLOR_BLACK); + lcd_setfgcolor (console_color_black); + lcd_setbgcolor (console_color_white); #endif /* CONFIG_SYS_WHITE_ON_BLACK */ #ifdef LCD_TEST_PATTERN test_pattern(); #else - /* set framebuffer to background color */ + /* set framebuffer to background color (only works if depth is 8 + * or background is black) */ memset ((char *)lcd_base, COLOR_MASK(lcd_getbgcolor()), lcd_line_length*panel_info.vl_row); @@ -401,6 +628,45 @@ U_BOOT_CMD( "" ); +static int lcd_init_colors(void) +{ + if (panel_info.vl_bpix == LCD_MONOCHROME) { + /* Setting the palette */ + lcd_initcolregs(); + console_color_black = 0; + console_color_white = 1; + } else if (panel_info.vl_bpix == LCD_COLOR8) { + /* Setting the palette */ + lcd_setcolreg (0, 0, 0, 0); /* black */ + lcd_setcolreg (1, 0xFF, 0, 0); /* red */ + lcd_setcolreg (2, 0, 0xFF, 0); /* green */ + lcd_setcolreg (3, 0xFF, 0xFF, 0); /* yellow */ + lcd_setcolreg (4, 0, 0, 0xFF); /* blue */ + lcd_setcolreg (5, 0xFF, 0, 0xFF); /* magenta */ + lcd_setcolreg (6, 0, 0xFF, 0xFF); /* cyan */ + lcd_setcolreg (14, 0xAA, 0xAA, 0xAA); /* grey */ + lcd_setcolreg (15, 0xFF, 0xFF, 0xFF); /* white */ + console_color_black = 0; + console_color_white = 15; + } else if (panel_info.vl_bpix == LCD_COLOR16) { + console_color_white = 0xffff; + console_color_black = 0x0000; + } else if (panel_info.vl_bpix == LCD_COLOR24) { + console_color_white = 0x00ffffff; + console_color_black = 0x00000000; + } + +#ifdef CONFIG_LCD_LOGO + if (panel_info.vl_bpix != LCD_COLOR16) { + if (console_color_white >= BMP_LOGO_OFFSET) { + printf("Default Color Map overlaps with Logo Color Map!\n"); + return -1; + } + } +#endif + return 0; +} + /*----------------------------------------------------------------------*/ static int lcd_init (void *lcdbase) @@ -409,6 +675,15 @@ static int lcd_init (void *lcdbase) debug ("[LCD] Initializing LCD frambuffer at %p\n", lcdbase); lcd_ctrl_init (lcdbase); + + + /* If no panel setup then return an error */ + if (!panel_info.vl_row || !panel_info.vl_col) + return -1; + + if (lcd_init_colors() < 0) + return -1; + lcd_is_enabled = 1; lcd_clear (NULL, 1, 1, NULL); /* dummy args */ lcd_enable (); @@ -435,6 +710,15 @@ static int lcd_init (void *lcdbase) * * Note that this is running from ROM, so no write access to global data. */ +#ifdef CONFIG_BOARD_LCD_SETMEM +ulong lcd_setmem (ulong addr) +{ + ulong size; + size = board_lcd_setmem(addr); + addr -= size; + return addr; +} +#else ulong lcd_setmem (ulong addr) { ulong size; @@ -455,6 +739,7 @@ ulong lcd_setmem (ulong addr) return (addr); } +#endif /*----------------------------------------------------------------------*/ @@ -608,7 +893,7 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) ushort *cmap_base = NULL; ushort i, j; uchar *fb; - bmp_image_t *bmp=(bmp_image_t *)bmp_image; + bmp_image_t *bmp; uchar *bmap; ushort padded_line; unsigned long width, height, byte_width; @@ -622,6 +907,10 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) volatile cpm8xx_t *cp = &(immr->im_cpm); #endif + if (!bmp_image) + return 1; + bmp = (bmp_image_t *)bmp_image; + if (!((bmp->header.signature[0]=='B') && (bmp->header.signature[1]=='M'))) { printf ("Error: no valid bmp image at %lx\n", bmp_image); @@ -636,14 +925,14 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) bpix = NBITS(panel_info.vl_bpix); - if ((bpix != 1) && (bpix != 8) && (bpix != 16)) { + if ((bpix != 1) && (bpix != 8) && (bpix != 16) && (bpix != 32)) { printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", bpix, bmp_bpix); return 1; } /* We support displaying 8bpp BMPs on 16bpp LCDs */ - if (bpix != bmp_bpix && (bmp_bpix != 8 || bpix != 16)) { + if (bpix != bmp_bpix && (bmp_bpix != 8 || bpix != 16) && (bmp_bpix != 16 || bpix != 32)) { printf ("Error: %d bit/pixel mode, but BMP has %d bit/pixel\n", bpix, le16_to_cpu(bmp->header.bit_count)); @@ -714,14 +1003,15 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) #ifdef CONFIG_SPLASH_SCREEN_ALIGN if (x == BMP_ALIGN_CENTER) - x = max(0, (pwidth - width) / 2); + x = max(0, ((int)pwidth - (int)width) / 2); else if (x < 0) - x = max(0, pwidth - width + x + 1); + x = max(0, (int)pwidth - (int)width + x + 1); if (y == BMP_ALIGN_CENTER) - y = max(0, (panel_info.vl_row - height) / 2); + y = max(0, ((int)panel_info.vl_row - (int)height) / 2); else if (y < 0) - y = max(0, panel_info.vl_row - height + y + 1); + y = max(0, (int)panel_info.vl_row - (int)height + y + 1); + #endif /* CONFIG_SPLASH_SCREEN_ALIGN */ if ((x + width)>pwidth) @@ -762,22 +1052,42 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) #if defined(CONFIG_BMP_16BPP) case 16: - for (i = 0; i < height; ++i) { - WATCHDOG_RESET(); - for (j = 0; j < width; j++) { + if (bpix == 32) { + for (i = 0; i < height; ++i) { + WATCHDOG_RESET(); + for (j = 0; j < width; j++) { + uint32_t color; + + /* Convert bmp from 16bpp->32bpp */ + /* Red */ + color = (bmap[1] << 8) | bmap[0]; + fb[2] = (color >> 8) & 0xf8; + fb[1] = (color >> 3) & 0xfc; + fb[0] = (color << 3) & 0xf8; + fb += 4; + bmap+=2; + } + bmap += (padded_line - width) * 2; + fb -= (width * 4 + lcd_line_length); + } + } else { + for (i = 0; i < height; ++i) { + WATCHDOG_RESET(); + for (j = 0; j < width; j++) { #if defined(CONFIG_ATMEL_LCD_BGR555) - *(fb++) = ((bmap[0] & 0x1f) << 2) | - (bmap[1] & 0x03); - *(fb++) = (bmap[0] & 0xe0) | - ((bmap[1] & 0x7c) >> 2); - bmap += 2; + *(fb++) = ((bmap[0] & 0x1f) << 2) | + (bmap[1] & 0x03); + *(fb++) = (bmap[0] & 0xe0) | + ((bmap[1] & 0x7c) >> 2); + bmap += 2; #else - *(fb++) = *(bmap++); - *(fb++) = *(bmap++); + *(fb++) = *(bmap++); + *(fb++) = *(bmap++); #endif + } + bmap += (padded_line - width) * 2; + fb -= (width * 2 + lcd_line_length); } - bmap += (padded_line - width) * 2; - fb -= (width * 2 + lcd_line_length); } break; #endif /* CONFIG_BMP_16BPP */ @@ -786,6 +1096,10 @@ int lcd_display_bitmap(ulong bmp_image, int x, int y) break; }; +#ifdef CONFIG_ARM + /* Flush the cache to make sure display tracks content of memory */ + flush_cache(0, ~0); +#endif return (0); } #endif @@ -796,6 +1110,7 @@ static void *lcd_logo (void) char *s; ulong addr; static int do_splash = 1; + int ret; if (do_splash && (s = getenv("splashimage")) != NULL) { int x = 0, y = 0; @@ -828,7 +1143,12 @@ static void *lcd_logo (void) } #endif - if (lcd_display_bitmap (addr, x, y) == 0) { + ret = lcd_display_bitmap (addr, x, y); +#ifdef CONFIG_VIDEO_BMP_GZIP + if ((unsigned long)bmp != addr) + free((void *)addr); +#endif + if (ret == 0) { return ((void *)lcd_base); } } @@ -853,3 +1173,79 @@ static void *lcd_logo (void) /************************************************************************/ /************************************************************************/ + +#ifdef CONFIG_LCD_PERCENT +#define PERCENT_BUF_SIZE 128 +static struct { + int size; + int total; + ulong now, when; + int percent; + char string[PERCENT_BUF_SIZE]; +} percent_data; + +void lcd_percent_init(int size) +{ + percent_data.size = 0; + percent_data.percent = -1; + percent_data.total = size; + percent_data.when = get_timer(0); +} + +void lcd_percent_update(int size) +{ + int percent; + char buf[PERCENT_BUF_SIZE]; + char *src, *dst; + + if (percent_data.string[0]) { + unsigned long long n = size * 100ULL; + do_div(n, percent_data.total); + percent = (int)n; + percent_data.now = get_timer(0); + if (percent != percent_data.percent) { + if (percent == 100 + || !percent_data.size + || ((percent_data.now - percent_data.when) > (CONFIG_SYS_HZ/4))) { + percent_data.percent = percent; + /* copy string into buf, replace '/P' with percent value */ + dst = buf; + src = percent_data.string; + while (*src && (dst < &buf[PERCENT_BUF_SIZE-10])) { + if (src[0] == '/' && src[1] == 'P') { + dst += sprintf(dst, "%d", percent); + src+=2; + } else + *dst++ = *src++; + } + *dst = '\0'; + output_lcd_string(buf); + percent_data.when = percent_data.now; + } + } + percent_data.size = size; + } +} + +static int do_lcd_percent (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[]) +{ + if (argc > 1) + strncpy(percent_data.string, argv[1], sizeof(percent_data.string) - 1); + else + percent_data.string[0] = '\0'; + return 0; +} + +U_BOOT_CMD( + lcd_percent, 2, 1, do_lcd_percent, + "setup percentage output on LCD", + " - string to print when percent changes (/P is replaced with percent)" +); +#else +void lcd_percent_init(int total_size) +{ +} +void lcd_percent_update(int size) +{ +} +#endif |