summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile1
-rw-r--r--common/cmd_bdinfo.c20
-rw-r--r--common/cmd_cache.c14
-rw-r--r--common/cmd_flash.c15
-rw-r--r--common/cmd_jffs2.c6
-rw-r--r--common/cmd_mem.c47
-rw-r--r--common/cmd_misc.c43
-rw-r--r--common/cmd_mtdparts.c91
-rw-r--r--common/cmd_nand.c34
-rw-r--r--common/cmd_nvedit.c12
-rw-r--r--common/cmd_yaffs2.c153
-rw-r--r--common/env_common.c17
-rw-r--r--common/env_nand.c161
-rw-r--r--common/lcd.c500
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(&current_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(&current_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(&current_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