aboutsummaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
Diffstat (limited to 'common')
-rw-r--r--common/Makefile8
-rw-r--r--common/cmd_bdinfo.c36
-rw-r--r--common/cmd_bootm.c3
-rw-r--r--common/cmd_load.c2
-rw-r--r--common/cmd_mdcom.c1360
-rw-r--r--common/cmd_mem.c26
-rw-r--r--common/cmd_misc.c692
-rw-r--r--common/cmd_mmc.c310
-rw-r--r--common/cmd_mtdparts.c388
-rw-r--r--common/cmd_nand.c406
-rw-r--r--common/cmd_net.c39
-rw-r--r--common/cmd_nvedit.c20
-rw-r--r--common/cmd_onenand.c2
-rw-r--r--common/cmd_sata.c9
-rw-r--r--common/cmd_test.c217
-rw-r--r--common/cmd_ubi.c296
-rw-r--r--common/cmd_usb.c3
-rw-r--r--common/cmd_version.c2
-rw-r--r--common/cmd_yaffs2.c383
-rw-r--r--common/env_onenand.c2
-rw-r--r--common/env_remote.c79
-rw-r--r--common/hush.c2
-rw-r--r--common/image.c14
-rw-r--r--common/main.c83
-rw-r--r--common/usb.c25
-rw-r--r--common/usb_hub.c27
-rw-r--r--common/usb_storage.c59
27 files changed, 4117 insertions, 376 deletions
diff --git a/common/Makefile b/common/Makefile
index d9f10f3f6e..7c828fc587 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -59,6 +59,7 @@ COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o
COBJS-$(CONFIG_ENV_IS_IN_NVRAM) += env_nvram.o
COBJS-$(CONFIG_ENV_IS_IN_ONENAND) += env_onenand.o
COBJS-$(CONFIG_ENV_IS_IN_SPI_FLASH) += env_sf.o
+COBJS-$(CONFIG_ENV_IS_IN_REMOTE) += env_remote.o
COBJS-$(CONFIG_ENV_IS_NOWHERE) += env_nowhere.o
# command
@@ -123,6 +124,7 @@ ifdef CONFIG_PHYLIB
COBJS-$(CONFIG_CMD_MII) += cmd_mdio.o
endif
COBJS-$(CONFIG_CMD_MISC) += cmd_misc.o
+COBJS-$(CONFIG_CMD_MDCOM) += cmd_mdcom.o
COBJS-$(CONFIG_CMD_MMC) += cmd_mmc.o
COBJS-$(CONFIG_CMD_MMC_SPI) += cmd_mmc_spi.o
COBJS-$(CONFIG_MP) += cmd_mp.o
@@ -189,6 +191,7 @@ endif
ifdef CONFIG_SPL_BUILD
COBJS-$(CONFIG_SPL_YMODEM_SUPPORT) += xyzModem.o
+COBJS-$(CONFIG_SPL_IMAGE_SUPPORT) += image.o
endif
COBJS-y += console.o
COBJS-y += dlmalloc.o
@@ -204,6 +207,11 @@ XOBJS := $(addprefix $(obj),$(XCOBJS))
CPPFLAGS += -I..
+ifeq ($(REBOOT_WHEN_CRASH),1)
+CPPFLAGS_common/cmd_misc.o += -DREBOOT_WHEN_CRASH
+CPPFLAGS_common/main.o += -DREBOOT_WHEN_CRASH
+endif
+
all: $(LIB) $(XOBJS)
$(LIB): $(obj).depend $(OBJS)
diff --git a/common/cmd_bdinfo.c b/common/cmd_bdinfo.c
index 5359a47859..42f08fdd0d 100644
--- a/common/cmd_bdinfo.c
+++ b/common/cmd_bdinfo.c
@@ -119,6 +119,14 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
print_mhz("pevfreq", bd->bi_pevfreq);
#endif
+#ifdef CONFIG_ENABLE_36BIT_PHYS
+#ifdef CONFIG_PHYS_64BIT
+ puts("addressing = 36-bit\n");
+#else
+ puts("addressing = 32-bit\n");
+#endif
+#endif
+
print_eth(0);
#if defined(CONFIG_HAS_ETH1)
print_eth(1);
@@ -139,7 +147,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#ifdef CONFIG_HERMES
print_mhz("ethspeed", bd->bi_ethspeed);
#endif
- printf("IP addr = %pI4\n", &bd->bi_ip_addr);
+ printf("IP addr = %s\n", getenv("ipaddr"));
printf("baudrate = %6ld bps\n", bd->bi_baudrate);
print_num("relocaddr", gd->relocaddr);
return 0;
@@ -164,7 +172,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %ld bps\n", bd->bi_baudrate);
@@ -188,7 +196,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#endif
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %ld bps\n", (ulong)bd->bi_baudrate);
return 0;
@@ -221,7 +229,7 @@ int do_bdinfo(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %6ld bps\n", bd->bi_baudrate);
return 0;
@@ -267,7 +275,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
print_eth(3);
#endif
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %ld bps\n", bd->bi_baudrate);
@@ -295,7 +303,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
print_num("flashoffset", (ulong)bd->bi_flashoffset);
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
printf("baudrate = %d bps\n", bd->bi_baudrate);
return 0;
@@ -315,7 +323,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
print_num("flashoffset", (ulong)bd->bi_flashoffset);
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
printf("baudrate = %d bps\n", bd->bi_baudrate);
return 0;
@@ -335,7 +343,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
print_num("flashoffset", (ulong)bd->bi_flashoffset);
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
printf("baudrate = %lu bps\n", bd->bi_baudrate);
return 0;
@@ -359,7 +367,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %d bps\n", bd->bi_baudrate);
#if !(defined(CONFIG_SYS_ICACHE_OFF) && defined(CONFIG_SYS_DCACHE_OFF))
@@ -395,7 +403,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %ld bps\n", (ulong)bd->bi_baudrate);
return 0;
@@ -428,7 +436,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
print_mhz("ethspeed", bd->bi_ethspeed);
#endif
printf("baudrate = %d bps\n", bd->bi_baudrate);
@@ -453,7 +461,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
print_num("FB base ", gd->fb_base);
return 0;
@@ -477,7 +485,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %d bps\n", bd->bi_baudrate);
@@ -498,7 +506,7 @@ int do_bdinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#if defined(CONFIG_CMD_NET)
print_eth(0);
- printf("ip_addr = %pI4\n", &bd->bi_ip_addr);
+ printf("ip_addr = %s\n", getenv("ipaddr"));
#endif
printf("baudrate = %ld bps\n", bd->bi_baudrate);
diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c
index 5685232892..45e726af8b 100644
--- a/common/cmd_bootm.c
+++ b/common/cmd_bootm.c
@@ -1587,7 +1587,6 @@ static int bootz_start(cmd_tbl_t *cmdtp, int flag, int argc,
static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- ulong iflag;
bootm_headers_t images;
if (bootz_start(cmdtp, flag, argc, argv, &images))
@@ -1598,7 +1597,7 @@ static int do_bootz(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
* overwrite all exception vector code, so we cannot easily
* recover from any failures any more...
*/
- iflag = disable_interrupts();
+ disable_interrupts();
#if defined(CONFIG_CMD_USB)
/*
diff --git a/common/cmd_load.c b/common/cmd_load.c
index f4d66deae3..cd00ad1251 100644
--- a/common/cmd_load.c
+++ b/common/cmd_load.c
@@ -975,7 +975,7 @@ static ulong load_serial_ymodem (ulong offset)
ulong addr = 0;
size = 0;
- info.mode = xyzModem_ymodem;
+ info.mode = xyzModem_xmodem;
res = xyzModem_stream_open (&info, &err);
if (!res) {
diff --git a/common/cmd_mdcom.c b/common/cmd_mdcom.c
new file mode 100644
index 0000000000..a2bc1bac59
--- /dev/null
+++ b/common/cmd_mdcom.c
@@ -0,0 +1,1360 @@
+/*
+ * (C) Copyright 2001
+ * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*
+ * Misc functions
+ */
+#include <common.h>
+#include <command.h>
+#include <usb/usbserial.h>
+#include <nand.h>
+#include <jffs2/jffs2.h>
+#include <asm/arch/mdcom.h>
+#include <asm/arch/hwcfg.h>
+#include <asm/arch/factory.h>
+#include <asm/arch/prdinfo.h>
+#include <asm/arch/rda_sys.h>
+#include <part.h>
+#include <mmc.h>
+#include <mmc/mmcpart.h>
+#include <nand.h>
+#include <malloc.h>
+#include <linux/mtd/nand.h>
+#include <mtd/nand/rda_nand.h>
+
+
+#if 1
+#define bb_dbg(fmt, args...) printf(fmt, ##args)
+#else
+#define bb_dbg(fmt, args...) do {} while(0)
+#endif
+
+#define RDA_ADD_ROUNDUP(x) (((x) + 3) & ~3)
+#define RDA_CHN_BUF_LEN 140
+
+struct rda_sys_hdr {
+ u16 magic;
+ u16 mod_id;
+ u32 req_id;
+ u32 ret_val;
+ u16 msg_id;
+ u16 ext_len;
+ u8 ext_data[];
+};
+
+struct rda_bp_info {
+ u32 bm_ver;
+ u32 bm_commit_rev;
+ u32 bm_build_date;
+ u32 bs_ver;
+ u32 bs_commit_rev;
+ u32 bs_build_date;
+};
+
+extern int mtdparts_init_default(void);
+extern int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part);
+
+#ifdef REBOOT_WHEN_CRASH
+#define ROLLBACK_TO_RECOVERY_MODE 0
+#endif
+
+/*
+ * Syntax:
+ * mdcom_send {channel} {adress} {size} [{timeout} {mode}]
+ */
+int do_mdcom_send(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ unsigned int channel;
+ void *buf;
+ int size;
+ int timeout = 0;
+ int mode = 0;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ channel = simple_strtoul(argv[1], NULL, 10);
+ buf = (void*) simple_strtoul(argv[2], NULL, 16);
+ size = simple_strtoul(argv[3], NULL, 10);
+ if (argc >4)
+ timeout = simple_strtoul(argv[4], NULL, 10);
+ if (argc >5)
+ mode = simple_strtoul(argv[5], NULL, 10);
+
+ if (mode) {
+ bb_dbg("MDCOM send %d bytes stream to channel %d with returned value %d.\n",
+ size, channel, rda_mdcom_channel_buf_send_stream(channel, buf,
+ size, timeout));
+ } else {
+ bb_dbg("MDCOM send %d bytes dgram to channel %d with returned value %d.\n",
+ size, channel, rda_mdcom_channel_buf_send_dgram(channel, buf,
+ size, timeout));
+ }
+
+ rda_mdcom_channel_show(channel);
+ return 0;
+}
+
+/*
+ * Syntax:
+ * mdcom_recv {channel} {adress} {size} [{timeout} {mode}]
+ */
+int do_mdcom_recv(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ unsigned int channel;
+ void *buf;
+ int size;
+ int timeout = 0;
+ int mode = 0;
+
+ if (argc < 4)
+ return CMD_RET_USAGE;
+
+ channel = simple_strtoul(argv[1], NULL, 10);
+ buf = (void*) simple_strtoul(argv[2], NULL, 16);
+ size = simple_strtoul(argv[3], NULL, 10);
+ if (argc >4)
+ timeout = simple_strtoul(argv[4], NULL, 10);
+ if (argc >5)
+ mode = simple_strtoul(argv[5], NULL, 10);
+
+ if (mode) {
+ bb_dbg("MDCOM receive %d bytes stream from channel %d with returned value %d.\n",
+ size, channel, rda_mdcom_channel_buf_recv_stream(channel, buf,
+ size, timeout));
+ } else {
+ bb_dbg("MDCOM receive %d bytes dgram from channel %d with returned value %d.\n",
+ size, channel, rda_mdcom_channel_buf_recv_dgram(channel, buf,
+ size, timeout));
+ }
+
+ rda_mdcom_channel_show(channel);
+ return 0;
+}
+
+static int rda_image_verify_header(const image_header_t *hdr)
+{
+ bb_dbg(" Verifying Image Header ... ");
+ if (!image_check_magic(hdr)) {
+ bb_dbg("Bad Magic Number\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (!image_check_hcrc(hdr)) {
+ bb_dbg("Bad Header Checksum\n");
+ return CMD_RET_FAILURE;
+ }
+ bb_dbg("OK\n");
+
+ image_print_contents(hdr);
+
+ return CMD_RET_SUCCESS;
+}
+
+static int rda_image_verify_data(const image_header_t *hdr)
+{
+ bb_dbg(" Verifying Data Checksum ... ");
+ if (!image_check_dcrc(hdr)) {
+ bb_dbg("Bad Data CRC\n");
+ return CMD_RET_FAILURE;
+ }
+ bb_dbg("OK\n");
+
+ return CMD_RET_SUCCESS;
+}
+
+static int rda_image_verify(const image_header_t *hdr)
+{
+ int ret;
+
+ ret = rda_image_verify_header(hdr);
+ if (ret == CMD_RET_SUCCESS) {
+ ret = rda_image_verify_data(hdr);
+ }
+ return ret;
+}
+
+int rda_modem_image_load(const image_header_t *hdr, int cal_en)
+{
+ u32 pc, param;
+ u32 modem_load_addr = image_get_load(hdr);
+ u32 ap_load_addr = rda_mdcom_address_modem2ap(modem_load_addr);
+
+ bb_dbg("%08x (AP address %08x) ...\n", modem_load_addr, ap_load_addr);
+
+ memcpy((void *)ap_load_addr, (const void *)image_get_data(hdr),
+ image_get_size(hdr));
+
+ pc = image_get_ep(hdr);
+ param = cal_en ? 0xCA1BCA1B : 0;
+ if (rda_mdcom_setup_run_env(pc, param))
+ return -1;
+
+ bb_dbg(" pc = %08x\n", pc);
+ bb_dbg(" param = %08x\n", param);
+ bb_dbg("Done\n");
+
+ return 0;
+}
+
+int rda_modem_cal_save(void)
+{
+ u32 addr, size;
+ int ret;
+
+ /* update all data to factorydata part. */
+ rda_mdcom_get_calib_section(&addr, &size);
+ factory_set_modem_calib((unsigned char *)addr);
+ rda_mdcom_get_ext_calib_section(&addr, &size);
+ factory_set_modem_ext_calib((unsigned char *)addr);
+ rda_mdcom_get_factory_section(&addr, &size);
+ factory_set_modem_factory((unsigned char *)addr);
+ rda_mdcom_get_ap_factory_section(&addr, &size);
+ factory_set_ap_factory((unsigned char *)addr);
+
+ ret = factory_burn();
+ if (ret) {
+ bb_dbg("Error when saving calibration data\n");
+ return ret;
+ }
+ return 0;
+}
+
+static void rda_modem_handle_syscmd(void)
+{
+ u8 md_com_buf[RDA_CHN_BUF_LEN / sizeof(u8)];
+ struct rda_sys_hdr *phdr = (struct rda_sys_hdr *)md_com_buf;
+
+#ifdef TEST_SYS
+ static int test_num = 0;
+ u8 tx_buf[RDA_CHN_BUF_LEN / sizeof(u8)];
+ struct rda_sys_hdr *ptx_hdr;
+ u32 *pext;
+ int ret;
+
+ if (test_num < 40) {
+ ptx_hdr = (struct rda_sys_hdr *) tx_buf;
+
+ ptx_hdr->magic = 0xA8B1;
+ ptx_hdr->mod_id = 0x1;
+ ptx_hdr->msg_id = 0x2000 + test_num;
+ ptx_hdr->req_id = 0xA1234567;
+ ptx_hdr->ret_val = 0xF7654321;
+
+ ptx_hdr->ext_len = 4;
+ pext = (u32 *)ptx_hdr->ext_data;
+ pext[0] = 0x1000123F;
+
+ ret = rda_mdcom_channel_buf_send_dgram(RDA_MDCOM_CHANNEL_SYSTEM, tx_buf, 16, 0);
+ if (!ret) {
+ rda_mdcom_line_set(RDA_MDCOM_PORT1, 2);
+ test_num++;
+ }
+ }
+#endif /* TEST_SYS */
+
+ if (!rda_mdcom_tstc(RDA_MDCOM_CHANNEL_SYSTEM))
+ return;
+
+ if (rda_mdcom_channel_buf_recv_dgram(
+ RDA_MDCOM_CHANNEL_SYSTEM,
+ md_com_buf,
+ 16,
+ usec2ticks(1000)))
+ return;
+
+ if (phdr->magic == 0xA8B1) {
+ u16 len;
+ u8 *pdata;
+ u32 i;
+ u32 *pret;
+
+ len = phdr->ext_len;
+
+ bb_dbg("## RECEIVED SYSTEM CMD:\n");
+ bb_dbg("MODID - 0x%04x\n", phdr->mod_id);
+ bb_dbg("REQID - 0x%08x\n", phdr->req_id);
+ bb_dbg("RETVAL - 0x%08x\n", phdr->ret_val);
+ bb_dbg("MSGID - 0x%04x\n", phdr->msg_id);
+ bb_dbg("LEN - 0x%04x\n", phdr->ext_len);
+
+ if (len) {
+ pdata = phdr->ext_data;
+
+ if (len > 128) {
+ bb_dbg("Length is invalid!\n");
+ } else if (len != rda_mdcom_channel_buf_recv_stream(
+ RDA_MDCOM_CHANNEL_SYSTEM, pdata, len, 0)) {
+ bb_dbg("Read Parameters Failed!\n");
+ } else {
+ bb_dbg("Params - ");
+ for (i = 0; i < len; i++) {
+ bb_dbg("%02x ", pdata[i]);
+ }
+ bb_dbg("\n\n");
+ }
+ } else {
+ if ((phdr->mod_id == 1) && (phdr->msg_id == 2)) {
+ bb_dbg("Calibration done\n");
+ phdr->msg_id = 0x1001;
+ phdr->ext_len = 4;
+ pret = (u32 *) phdr->ext_data;
+
+ if (rda_modem_cal_save()) {
+ pret[0] = 0x0;
+ bb_dbg("Calibration data save failed\n");
+ } else {
+ pret[0] = 0x1;
+ bb_dbg("Calibration data save succeed\n");
+ prdinfo_set_cali_result(1);
+ }
+
+ rda_mdcom_channel_buf_send_dgram(
+ RDA_MDCOM_CHANNEL_SYSTEM, md_com_buf, 20, 0);
+ rda_mdcom_line_set(RDA_MDCOM_PORT1, 2);
+ }
+ }
+ }
+}
+
+static void rda_modem_handle_trace(void)
+{
+ u8 md_com_buf[RDA_CHN_BUF_LEN / sizeof(u8)];
+ int ch;
+
+ while (rda_mdcom_tstc(RDA_MDCOM_CHANNEL_TRACE)) {
+ int len = rda_mdcom_channel_buf_recv_stream(
+ RDA_MDCOM_CHANNEL_TRACE,
+ md_com_buf,
+ 128,
+ 0);
+ usbser_write(USB_ACM_CHAN_0, (unsigned char *) md_com_buf, len);
+ }
+
+ while (usbser_tstc(USB_ACM_CHAN_0) &&
+ rda_mdcom_channel_buf_send_available(RDA_MDCOM_CHANNEL_TRACE)) {
+ ch = usbser_getc(USB_ACM_CHAN_0);
+ rda_mdcom_putc((char) ch, RDA_MDCOM_CHANNEL_TRACE);
+ }
+}
+
+static void rda_modem_handle_atcmd(void)
+{
+ u8 md_com_buf[RDA_CHN_BUF_LEN / sizeof(u8)];
+ if (!rda_mdcom_tstc(RDA_MDCOM_CHANNEL_AT))
+ return;
+
+ bb_dbg("## RECEIVED AT CMD:");
+ do {
+ unsigned short len = rda_mdcom_channel_buf_recv_stream(
+ RDA_MDCOM_CHANNEL_AT,
+ md_com_buf,
+ 128,
+ 0);
+ *((char*) md_com_buf + len) = 0;
+ puts((const char *) md_com_buf);
+ } while (rda_mdcom_tstc(RDA_MDCOM_CHANNEL_AT));
+ bb_dbg("\n");
+}
+
+int rda_modem_cal_load(void)
+{
+ u32 addr, size;
+ const u8 *data;
+
+ /* extended calibration data */
+ rda_mdcom_get_ext_calib_section(&addr, &size);
+ data = factory_get_modem_ext_calib();
+ memcpy((u8 *)addr, data, size);
+ bb_dbg("MOMEM EXT CALIB address %08x ...\n", addr);
+
+ /* calibration data */
+ rda_mdcom_get_calib_section(&addr, &size);
+ data = factory_get_modem_calib();
+ memcpy((u8 *)addr, data, size);
+ bb_dbg("MOMEM CALIB address %08x ...\n", addr);
+
+ /* modem fact data */
+ rda_mdcom_get_factory_section(&addr, &size);
+ data = factory_get_modem_factory();
+ memcpy((u8 *)addr, data, size);
+ bb_dbg("MOMEM FACT address %08x ...\n", addr);
+
+ /* ap fact data */
+ rda_mdcom_get_ap_factory_section(&addr, &size);
+ data = factory_get_ap_factory();
+ memcpy((u8 *)addr, data, size);
+ bb_dbg("AP FACT address %08x ...\n", addr);
+
+ return 0;
+}
+
+static int rda_check_ap_calib_msg(void)
+{
+ unsigned int msg_id = 0;
+ unsigned int msg_size = 0;
+ unsigned char *msg_data = malloc(RDA_AP_CALIB_MSG_DATA_LEN);
+
+ if (!msg_data)
+ return -1;
+
+ if (factory_get_ap_calib_msg(&msg_id, &msg_size, msg_data)) {
+ free(msg_data);
+ return -1;
+ }
+
+ if (msg_id & RDA_AP_CALIB_MSG_SET_PRDINFO)
+ prdinfo_set_data((struct prdinfo *)msg_data);
+
+ free(msg_data);
+ return 0;
+}
+
+/* use this function after factorydata is loaded */
+static int rda_send_prdinfo_data(void)
+{
+ unsigned int msg_id = 0;
+ unsigned int msg_size = 0;
+ unsigned char *msg_data = malloc(RDA_AP_CALIB_MSG_DATA_LEN);
+
+ if (!msg_data)
+ return -1;
+
+ memset(msg_data, 0, RDA_AP_CALIB_MSG_DATA_LEN);
+ prdinfo_get_data((struct prdinfo *)msg_data);
+
+ msg_id = RDA_AP_CALIB_MSG_GET_PRDINFO;
+ msg_size = sizeof(struct prdinfo);
+ factory_set_ap_calib_msg(msg_id, msg_size, msg_data);
+ free(msg_data);
+ return 0;
+}
+
+void rda_modem_cal_loop(void)
+{
+ /* send prdinfo data to calib tool */
+ rda_send_prdinfo_data();
+
+ while (1) {
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ WATCHDOG_RESET();
+#endif
+ /* check Ctrl-C */
+ ctrlc();
+ if ((had_ctrlc())) {
+ bb_dbg("\n## ABORT MANUALLY!\n\n");
+ return;
+ }
+
+ rda_modem_handle_syscmd();
+
+ rda_modem_handle_trace();
+
+ rda_modem_handle_atcmd();
+
+ /* check message to u-boot from PC calib tool*/
+ rda_check_ap_calib_msg();
+ }
+}
+
+int rda_modem_bbimages_load_from_nand(const image_header_t **hdrInit,
+ const image_header_t **hdrWork)
+{
+ struct mtd_info *nand;
+ struct mtd_device *dev;
+ struct part_info *part;
+ size_t page_size, block_size;
+ loff_t offset;
+ size_t read_size, image_size;
+ u8 pnum;
+ int ret;
+ u_char *buffer;
+ image_header_t *hdr;
+ u32 bad_blocks;
+ char buf[256];
+ u32 ih_len;
+ int i;
+
+ ret = mtdparts_init_default();
+ if (ret != 0) {
+ bb_dbg("mtdparts init error\n");
+ return ret;
+ }
+
+ ret = find_dev_and_part("modem", &dev, &pnum, &part);
+ if (ret) {
+ bb_dbg("unknown partition name - modem\n");
+ return ret;
+ } else if (dev->id->type != MTD_DEV_TYPE_NAND) {
+ bb_dbg("mtd dev type error");
+ return CMD_RET_FAILURE;
+ }
+ bb_dbg("found modem part '%s' offset: 0x%llx length: 0x%llx\n",
+ part->name, part->offset, part->size);
+
+ nand = &nand_info[dev->id->num];
+ page_size = nand->writesize;
+ block_size = nand->erasesize;
+
+ bb_dbg("\n## Checking Modem Code Image ...\n\n");
+
+ for (i = 0; i < 2; ++i) {
+ if (i == 0) {
+ offset = part->offset;
+ buffer = (u_char *)SCRATCH_ADDR;
+ hdr = (image_header_t *)buffer;
+ } else {
+ hdr = (image_header_t *)((u8 *)hdr + image_size);
+ }
+
+ if (buffer < (u8 *)hdr + sizeof(image_header_t)) {
+ read_size = (u8 *)hdr + sizeof(image_header_t) - buffer;
+ if (is_power_of_2(page_size))
+ read_size = ROUND(read_size, page_size);
+ else
+ read_size = roundup(read_size, page_size);
+ bad_blocks = 0;
+
+ bb_dbg("read 0x%x bytes from '%s' offset: 0x%08x\n",
+ read_size, part->name, (u32)offset);
+ ret = nand_read_skip_bad_new(nand, offset, &read_size,
+ buffer, &bad_blocks);
+ if (ret) {
+ bb_dbg("nand read fail\n");
+ return ret;
+ }
+
+ offset += read_size + block_size * bad_blocks;
+ buffer += read_size;
+ }
+
+ ret = rda_image_verify_header(hdr);
+ if (ret)
+ return ret;
+
+ image_size = image_get_image_size(hdr);
+
+ if (buffer < (u8 *)hdr + image_size) {
+ read_size = (u8 *)hdr + image_size - buffer;
+ if (is_power_of_2(page_size))
+ read_size = ROUND(read_size, page_size);
+ else
+ read_size = roundup(read_size, page_size);
+
+ bb_dbg("\nread 0x%x bytes from '%s' offset: 0x%08x\n",
+ read_size, part->name, (u32)offset);
+ ret = nand_read_skip_bad_new(nand, offset, &read_size,
+ buffer, &bad_blocks);
+ if (ret) {
+ bb_dbg("nand read fail\n");
+ return ret;
+ }
+
+ offset += read_size + block_size * bad_blocks;
+ buffer += read_size;
+ }
+
+ ret = rda_image_verify_data(hdr);
+ if (ret)
+ return ret;
+
+ if (i == 0) {
+ ih_len = min(sizeof(buf), IH_NMLEN);
+ strncpy(buf, (const char *)hdr->ih_name, ih_len);
+ buf[ih_len - 1] = '\0';
+ }
+ if (i == 0 && strstr(buf, "raminit")) {
+ bb_dbg("## Raminit Image Detected\n");
+ bb_dbg("\n");
+ *hdrInit = hdr;
+ } else {
+ bb_dbg("## Work Image Detected\n");
+ bb_dbg("\n");
+ *hdrWork = hdr;
+ break;;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+int rda_modem_bbimages_load_from_mmc(const image_header_t **hdrInit,
+ const image_header_t **hdrWork)
+{
+ u64 offset = 0;
+ size_t read_size, image_size;
+ u_char *buffer;
+ image_header_t *hdr;
+ char buf[256];
+ u32 ih_len;
+ int i;
+ int ret;
+ disk_partition_t *ptn;
+ block_dev_desc_t *mmc_blkdev;
+ struct mmc *mmc;
+
+ mmc_blkdev = get_dev_by_name(CONFIG_MMC_DEV_NAME);
+ if (mmc_blkdev)
+ mmc = container_of(mmc_blkdev, struct mmc, block_dev);
+ else
+ return CMD_RET_FAILURE;
+
+ if (!mmc) {
+ bb_dbg("mmc doesn't exist");
+ return CMD_RET_FAILURE;
+ }
+
+ ptn = partition_find_ptn("modem");
+ if(ptn == 0) {
+ bb_dbg("mmc partition table doesn't exist");
+ return -1;
+ }
+
+ bb_dbg("found modem part offset: 0x%lx\n", ptn->start);
+
+ bb_dbg("\n## Checking Modem Code Image ...\n\n");
+
+ for (i = 0; i < 2; ++i) {
+ if (i == 0) {
+ offset = ptn->start * ptn->blksz;
+ buffer = (u_char *)SCRATCH_ADDR;
+ hdr = (image_header_t *)buffer;
+ } else {
+ hdr = (image_header_t *)((u8 *)hdr + image_size);
+ }
+
+ if (buffer < (u8 *)hdr + sizeof(image_header_t)) {
+ read_size = (u8 *)hdr + sizeof(image_header_t) - buffer;
+ read_size = ROUND(read_size, 512);
+
+ bb_dbg("read 0x%x bytes offset: 0x%08x\n",
+ read_size, (u32)offset);
+ ret = mmc_read(mmc, offset, buffer, read_size);
+ if (ret <= 0) {
+ bb_dbg("mmc read fail\n");
+ return ret;
+ }
+
+ offset += read_size;
+ buffer += read_size;
+ }
+
+ ret = rda_image_verify_header(hdr);
+ if (ret)
+ return ret;
+
+ image_size = image_get_image_size(hdr);
+
+ if (buffer < (u8 *)hdr + image_size) {
+ read_size = (u8 *)hdr + image_size - buffer;
+ read_size = ROUND(read_size, 512);
+
+ bb_dbg("\nread 0x%x bytes offset: 0x%08x\n",
+ read_size, (u32)offset);
+ ret = mmc_read(mmc, offset, buffer, read_size);
+ if (ret <= 0) {
+ bb_dbg("mmc read fail\n");
+ return ret;
+ }
+
+ offset += read_size;
+ buffer += read_size;
+ }
+
+ ret = rda_image_verify_data(hdr);
+ if (ret)
+ return ret;
+
+ if (i == 0) {
+ ih_len = min(sizeof(buf), IH_NMLEN);
+ strncpy(buf, (const char *)hdr->ih_name, ih_len);
+ buf[ih_len - 1] = '\0';
+ }
+ if (i == 0 && strstr(buf, "raminit")) {
+ bb_dbg("## Raminit Image Detected\n");
+ bb_dbg("\n");
+ *hdrInit = hdr;
+ } else {
+ bb_dbg("## Work Image Detected\n");
+ bb_dbg("\n");
+ *hdrWork = hdr;
+ break;;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+void rdaHexPuts(char* p, int l)
+{
+ char strBuf[64];
+ char* s = strBuf;
+ if (l > 20)
+ l = 20;
+
+ while (l--) {
+ unsigned char c = (unsigned char) *p++;
+ *s = ((c >> 4) & 0xF) + '0';
+ if (*s > '9')
+ *s = *s + 'A' - '9' - 1;
+
+ *++s = (c & 0xF) + '0';
+ if (*s > '9')
+ *s = *s + 'A' - '9' - 1;
+
+ *++s = ' ';
+ ++s;
+ }
+ *s = '\r';
+ *++s = '\n';
+ *++s = 0;
+ puts((const char *) strBuf);
+}
+
+void rda_modem_cal_test(void)
+{
+ char cmdbuf[16];
+ unsigned long long end_time = get_ticks();
+
+ while (1) {
+#if defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)
+ WATCHDOG_RESET();
+#endif
+ /* check Ctrl-C */
+ ctrlc();
+ if ((had_ctrlc())) {
+ bb_dbg("\n## ABORT MANUALLY!\n\n");
+ return;
+ }
+
+ if (end_time < get_ticks()) {
+ char* p = cmdbuf;
+ *p++ = 0xad;
+ *p++ = 0x00;
+ *p++ = 0x0a;
+ *p++ = 0xFF;
+ *p++ = 0x82;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x82;
+ *p++ = (char)((end_time >> 0) & 0xFF);
+ *p++ = (char)((end_time >> 8) & 0xFF);
+ *p++ = (char)((end_time >> 16) & 0xFF);
+ *p++ = (char)((end_time >> 24) & 0xFF);
+ *p++ = 0xFF;
+ bb_dbg("## Send write cmd to modem: ");
+ rdaHexPuts(cmdbuf, rda_mdcom_channel_buf_send_stream(
+ RDA_MDCOM_CHANNEL_TRACE, cmdbuf, 14, 0));
+
+ p = cmdbuf;
+ *p++ = 0xad;
+ *p++ = 0x00;
+ *p++ = 0x07;
+ *p++ = 0xFF;
+ *p++ = 0x02;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x00;
+ *p++ = 0x82;
+ *p++ = (char)((end_time >> 24) & 0xFF);
+ *p++ = 0xFF;
+ bb_dbg("## Send read cmd to modem: ");
+ rdaHexPuts(cmdbuf, rda_mdcom_channel_buf_send_stream(
+ RDA_MDCOM_CHANNEL_TRACE, cmdbuf, 11, 0));
+
+ end_time = get_ticks() + usec2ticks(20000);
+ }
+
+ if (rda_mdcom_tstc(RDA_MDCOM_CHANNEL_TRACE)) {
+ bb_dbg("## received from modem:");
+ do {
+ rdaHexPuts(cmdbuf, rda_mdcom_channel_buf_recv_stream(
+ RDA_MDCOM_CHANNEL_TRACE, cmdbuf,
+ sizeof(cmdbuf), 0));
+ } while (rda_mdcom_tstc(RDA_MDCOM_CHANNEL_TRACE));
+ }
+ }
+}
+
+static void rda_show_modem_exception(void)
+{
+ char *addr;
+ unsigned int len;
+ char buf[256];
+
+ rda_mdcom_get_modem_exception_info((u32 *)&addr, &len);
+ snprintf(buf, sizeof(buf), "%s\n", addr);
+ buf[sizeof(buf) - 1] = '\0';
+ puts("\n");
+ if (addr) {
+ puts("Modem exception info:\n");
+ puts("---------------------\n");
+ puts(buf);
+ puts("---------------------\n");
+ } else {
+ puts("No valid modem exception info\n");
+ }
+}
+
+extern void shutdown_system(void);
+
+static void rda_modem_shutdown_system(void)
+{
+ struct rda_sys_hdr hdr;
+
+ bb_dbg("\n## System is being shutdown ... ");
+
+ hdr.magic = 0xA8B1;
+ hdr.mod_id = 0x0;
+ hdr.msg_id = 0x1001;
+ hdr.req_id = 0x0;
+ hdr.ret_val = 0x0;
+ hdr.ext_len = 0;
+
+ rda_mdcom_channel_buf_send_dgram(
+ RDA_MDCOM_CHANNEL_SYSTEM, &hdr, sizeof(hdr),
+ usec2ticks(100000));
+ rda_mdcom_line_set(RDA_MDCOM_PORT1, 2);
+ /* Wait sometime until modem shutdowns the system (about 1.8s) */
+ udelay(5000000);
+ /* Modem is in trouble. Shutdown the system directly. */
+ bb_dbg("\n## Bootloader directly shutdown ... ");
+ shutdown_system();
+}
+
+int bbimages_get_header(const u8 *p_image, const image_header_t **hdrInit,
+ const image_header_t **hdrWork)
+{
+ int retVal;
+ char buf[256];
+ u32 ih_len;
+ int i;
+ image_header_t *hdr;
+
+ for (i = 0; i < 2; i++) {
+ hdr = (image_header_t *) RDA_ADD_ROUNDUP((int) p_image);
+
+ bb_dbg("\n## Checking Modem Code Image at %08x ...\n",
+ (unsigned int)hdr);
+ retVal = rda_image_verify(hdr);
+ if (retVal) {
+ /* If there is no image, we initialize channels
+ * still. Otherwise kernel would not be
+ * loaded. */
+ rda_mdcom_channel_all_init();
+ return retVal;
+ }
+
+ if (i == 0) {
+ ih_len = min(sizeof(buf), IH_NMLEN);
+ strncpy(buf, (const char *)hdr->ih_name, ih_len);
+ buf[ih_len - 1] = '\0';
+ }
+ if (i == 0 && strstr(buf, "raminit")) {
+ bb_dbg("## Raminit Image Detected\n");
+ p_image += image_get_image_size(hdr);
+ *hdrInit = hdr;
+ } else {
+ bb_dbg("## Work Image Detected\n");
+ *hdrWork = hdr;
+ break;
+ }
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+int mdcom_check_and_wait_modem(int check_boot_key)
+{
+ int shutdown = 0;
+ unsigned long long end_time;
+ u32 reset_cause;
+ u32 itf_version;
+
+ /* Set a timeout of 2 seconds to wait for BP */
+ bb_dbg("\n## Waiting for modem response ... ");
+
+ end_time = get_ticks() + usec2ticks(2000000);
+ while (!rda_mdcom_line_set_wait(RDA_MDCOM_PORT0,
+ RDA_MDCOM_LINE_CMD_START, 100)) {
+ /* check exception */
+ if (rda_mdcom_line_set_check(RDA_MDCOM_PORT0,
+ RDA_MDCOM_LINE_EXCEPTION)) {
+ bb_dbg("\n\n");
+ bb_dbg("**********************************\n");
+ bb_dbg("*** Error: Detect modem exception!\n");
+ rda_show_modem_exception();
+#ifdef REBOOT_WHEN_CRASH
+ bb_dbg("Rebooting ...\n\n\n");
+ udelay(5000);
+ disable_interrupts();
+ if (ROLLBACK_TO_RECOVERY_MODE)
+ rda_reboot(REBOOT_TO_RECOVERY_MODE);
+ else
+ rda_reboot(REBOOT_TO_NORMAL_MODE);
+#endif
+ return CMD_RET_FAILURE;
+ }
+ /* check timeout */
+ if (get_ticks() > end_time) {
+#ifdef REBOOT_WHEN_CRASH
+ bb_dbg("\n\n## Error: Timeout when waiting for "
+ "modem response. Rebooting ...\n\n\n");
+ udelay(5000);
+ disable_interrupts();
+ if (ROLLBACK_TO_RECOVERY_MODE)
+ rda_reboot(REBOOT_TO_RECOVERY_MODE);
+ else
+ rda_reboot(REBOOT_TO_NORMAL_MODE);
+#else
+ end_time = -1;
+ bb_dbg("\n\n## Warning: Timeout when waiting for "
+ "modem response. Press Ctrl-C to abort.\n");
+#endif
+ }
+ /* check Ctrl-C */
+ ctrlc();
+ if ((had_ctrlc())) {
+ bb_dbg("\n## ABORT MANUALLY!\n\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ bb_dbg("Done\n");
+
+ reset_cause = rda_mdcom_get_reset_cause();
+ itf_version = rda_mdcom_get_interface_version();
+ bb_dbg("\n## Reset cause : 0x%08x\n", reset_cause);
+ bb_dbg("\n## Communication interface version : 0x%08x\n", itf_version);
+ if (itf_version != RDA_BP_VER) {
+ bb_dbg("*** Error: Unsupported version. 0x%08x is expected.\n",
+ RDA_BP_VER);
+ return CMD_RET_FAILURE;
+ }
+
+ if (reset_cause == RDA_RESET_CAUSE_NORMAL) {
+ /* Check power-on key status */
+ if (check_boot_key && !get_saved_boot_key_state()) {
+ shutdown = 0;
+ bb_dbg("\n## Power-on key is not pressed for normal boot.");
+ bb_dbg("\n## ****** Shutdown is needed later ******\n");
+ }
+ }
+
+ bb_dbg("\n## Init mdcom channels ... ");
+ rda_mdcom_channel_all_init();
+ rda_mdcom_line_clear(RDA_MDCOM_PORT0, RDA_MDCOM_LINE_CMD_START);
+ bb_dbg("Done\n");
+
+ /* Check if shutdown is needed after modem fully starts up */
+ if (shutdown)
+ rda_modem_shutdown_system();
+
+ /* rda_mdcom_show_software_version(); */
+ return CMD_RET_SUCCESS;
+}
+
+static int do_check_and_wait_modem(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int check_boot_key = 0;
+
+ if (argc >= 2)
+ check_boot_key = (int) simple_strtoul(argv[1], NULL, 10);
+
+ return mdcom_check_and_wait_modem(check_boot_key);
+}
+
+int bbimages_load(const image_header_t *hdrInit, const image_header_t *hdrWork,
+ int cal_en)
+{
+ unsigned long long end_time;
+ u32 addr, len;
+ char buf[256];
+ int update_calib = 0, update_factory = 0, update_ap_factory = 0;
+ u32 modem_load_addr = image_get_load(hdrWork);
+
+ /* set modem logic base address for modem side,
+ by the work code loading address in image header */
+ rda_mdcom_set_logic_base_addr(modem_load_addr);
+
+ bb_dbg("\n## Init mdcom ports ... ");
+ rda_mdcom_init_port(RDA_MDCOM_PORT0);
+ rda_mdcom_init_port(RDA_MDCOM_PORT1);
+ bb_dbg("Done\n");
+
+ if (hdrInit) {
+ bb_dbg("\n## Load Raminit Code to modem at ");
+ rda_modem_image_load(hdrInit, 0);
+
+ bb_dbg("\n## Start modem and waiting for response ... ");
+ rda_mdcom_line_set(RDA_MDCOM_PORT0, RDA_MDCOM_LINE_DL_HANDSHAKE);
+ /* Set a timeout of 2 seconds to wait for BP */
+ end_time = get_ticks() + usec2ticks(2000000);
+ while (!rda_mdcom_line_set_wait(RDA_MDCOM_PORT0,
+ RDA_MDCOM_LINE_DL_HANDSHAKE, 100)) {
+ /* check timeout */
+ if (get_ticks() > end_time) {
+#ifdef REBOOT_WHEN_CRASH
+ bb_dbg("\n\n## Error: Timeout when waiting for "
+ "modem response. Rebooting ...\n\n\n");
+ udelay(5000);
+ disable_interrupts();
+ if (ROLLBACK_TO_RECOVERY_MODE)
+ rda_reboot(REBOOT_TO_RECOVERY_MODE);
+ else
+ rda_reboot(REBOOT_TO_NORMAL_MODE);
+#else
+ end_time = -1;
+ bb_dbg("\n\n## Warning: Timeout when waiting for "
+ "modem response. Press Ctrl-C to abort.\n");
+#endif
+ }
+ /* check Ctrl-C */
+ ctrlc();
+ if ((had_ctrlc())) {
+ bb_dbg("\n## ABORT MANUALLY!\n\n");
+ return CMD_RET_FAILURE;
+ }
+ }
+ rda_mdcom_line_clear(RDA_MDCOM_PORT0, RDA_MDCOM_LINE_DL_HANDSHAKE);
+ bb_dbg("Done\n");
+ }
+
+ /* Check whether modem crashed in the last run */
+ if (rda_mdcom_modem_crashed_before()) {
+ rda_mdcom_get_modem_exception_info(&addr, &len);
+ buf[0] = '\0';
+ if (addr) {
+ snprintf(buf, sizeof(buf), "%s", (char *)addr);
+ buf[sizeof(buf) - 1] = '\0';
+ /* TODO: Save the exception info to nand/sdmmc */
+ }
+ rda_mdcom_get_modem_log_info(&addr, &len);
+ if (addr) {
+ /* TODO: Save the log info to nand/sdmmc */
+ /* NOTE: The log is in binary format! */
+ }
+ }
+ /* Check whether to udpate modem calib and factory data */
+ if (system_rebooted()) {
+ update_calib = rda_mdcom_calib_update_cmd_valid();
+ if (update_calib) {
+ bb_dbg("\n## Detect calib update command\n");
+ rda_mdcom_get_calib_section(&addr, &len);
+ factory_set_modem_calib((unsigned char *)addr);
+ rda_mdcom_get_ext_calib_section(&addr, &len);
+ factory_set_modem_ext_calib((unsigned char *)addr);
+ }
+ update_factory = rda_mdcom_factory_update_cmd_valid();
+ if (update_factory) {
+ bb_dbg("\n## Detect factory update command\n");
+ rda_mdcom_get_factory_section(&addr, &len);
+ factory_set_modem_factory((unsigned char *)addr);
+ }
+ update_ap_factory = rda_mdcom_ap_factory_update_cmd_valid();
+ if (update_ap_factory) {
+ bb_dbg("\n## Detect AP factory update command\n");
+ rda_mdcom_get_ap_factory_section(&addr, &len);
+ factory_set_ap_factory((unsigned char *)addr);
+ }
+ if (update_calib || update_factory || update_ap_factory) {
+ bb_dbg("\n## Burn calib and/or factory data\n");
+ if (factory_burn())
+ bb_dbg("\n** Error when burning data\n");
+ }
+ }
+ /* Init all log info and some magic numbers */
+ rda_mdcom_init_all_log_info();
+
+ bb_dbg("\n## Load Work Code to modem at ");
+ if (rda_modem_image_load(hdrWork, cal_en)) {
+ printf("\n## Load modem failed!\n");
+ return CMD_RET_FAILURE;
+ }
+
+ bb_dbg("\n## Load Calib Data to modem at ");
+ rda_modem_cal_load();
+
+ bb_dbg("\n## Start modem ...\n");
+ rda_mdcom_line_set(RDA_MDCOM_PORT0, RDA_MDCOM_LINE_DL_HANDSHAKE);
+
+ return CMD_RET_SUCCESS;
+}
+
+int mdcom_load_from_mem(const u8 *data, int cal_en)
+{
+ const image_header_t *hdrInit = NULL;
+ const image_header_t *hdrWork = NULL;
+
+ if (bbimages_get_header(data, &hdrInit, &hdrWork)) {
+ /* If there is no image, we initialize channels still.
+ * Otherwise kernel would not be loaded. */
+ rda_mdcom_channel_all_init();
+ return CMD_RET_FAILURE;
+ }
+
+ return bbimages_load(hdrInit, hdrWork, cal_en);
+}
+
+int mdcom_load_from_flash(int cal_en)
+{
+ int ret;
+ const image_header_t *hdrInit = NULL;
+ const image_header_t *hdrWork = NULL;
+
+ /*
+ * Save the boot key state now.
+ * It takes about 1.9s to run into here if boot delay is 1s.
+ */
+ save_current_boot_key_state();
+
+ if (rda_media_get() == MEDIA_MMC)
+ ret = rda_modem_bbimages_load_from_mmc(&hdrInit, &hdrWork);
+ else
+ ret = rda_modem_bbimages_load_from_nand(&hdrInit, &hdrWork);
+
+ if (ret) {
+ /*
+ * If there is no image, we initialize channels still.
+ * Otherwise kernel would not be loaded.
+ */
+ rda_mdcom_channel_all_init();
+ return CMD_RET_FAILURE;
+ }
+ return bbimages_load(hdrInit, hdrWork, cal_en);
+}
+
+/*
+ * Syntax:
+ * mdcom_loadm {adress} [cal_en]
+ */
+int do_mdcom_loadm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int cal_en = 0;
+ const u8 *data;
+
+ if (argc < 2)
+ return CMD_RET_USAGE;
+ if (argc >= 3)
+ cal_en = (int) simple_strtoul(argv[2], NULL, 10);
+
+ data = (const u8 *)simple_strtoul(argv[1], NULL, 16);
+
+ return mdcom_load_from_mem(data, cal_en);
+}
+
+int do_mdcom_cal_loadm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ const u8 *data;
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ data = (const u8 *)simple_strtoul(argv[1], NULL, 16);
+ if (rda_image_verify_header((const image_header_t *)data))
+ return CMD_RET_FAILURE;
+
+ if (factory_copy_from_mem(data))
+ return CMD_RET_FAILURE;
+
+ return CMD_RET_SUCCESS;
+}
+
+/*
+ * Syntax:
+ * mdcom_loadf [cal_en]
+ */
+int do_mdcom_loadf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int cal_en = 0;
+
+ if (argc >= 2)
+ cal_en = (int) simple_strtoul(argv[1], NULL, 10);
+
+ return mdcom_load_from_flash(cal_en);
+}
+
+int do_mdcom_cal_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ rda_modem_cal_test();
+ return CMD_RET_SUCCESS;
+}
+
+int do_mdcom_cal(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ drv_usbser_init();
+ rda_modem_cal_loop();
+ return CMD_RET_SUCCESS;
+}
+
+int do_mdcom_ch_show(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ bb_dbg("\n## MDCOM Channel AT Show:\n");
+ rda_mdcom_channel_show(RDA_MDCOM_CHANNEL_AT);
+ bb_dbg("\n## MDCOM Channel SYS Show:\n");
+ rda_mdcom_channel_show(RDA_MDCOM_CHANNEL_SYSTEM);
+ bb_dbg("\n## MDCOM Channel TRACE Show:\n");
+ rda_mdcom_channel_show(RDA_MDCOM_CHANNEL_TRACE);
+ return CMD_RET_SUCCESS;
+}
+
+int do_mdcom_cal_save(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (rda_modem_cal_save())
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+
+int do_mdcom_cal_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (rda_modem_cal_load())
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+
+int do_mdcom_diag(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ rda_mdcom_show_xcpu_info();
+ return CMD_RET_SUCCESS;
+}
+
+int do_mdcom_ver(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ rda_mdcom_show_software_version();
+ return CMD_RET_SUCCESS;
+}
+
+U_BOOT_CMD(
+ mdcom_send , 6, 1, do_mdcom_send,
+ "send data to mdCom channels",
+ "Syntax:\n"
+ " - mdcom_send {channel} {adress} {size} [{timeout} {mode}]"
+ "Parameters:\n"
+ " - channel: the mdcom channel number\n"
+ " - adress: the address of the data buffer to send\n"
+ " - size: the size of the sending buffer\n"
+ " - timeout: (optional) the timeout with unit ms\n"
+ " - mode: (optional) 0 - stream mode; else - dgram mode\n"
+);
+
+U_BOOT_CMD(
+ mdcom_recv , 6, 1, do_mdcom_recv,
+ "send data to mdCom channels",
+ "Syntax:\n"
+ " - mdcom_recv {channel} {address} {size} [{timeout} {mode}]\n"
+ "Parameters:\n"
+ " - channel: the mdcom channel number\n"
+ " - adress: the address of the buffer to receive data\n"
+ " - size: the size of the receiving buffer\n"
+ " - timeout: (optional) the timeout with unit ms\n"
+ " - mode: (optional) 0 - stream mode; else - dgram mode\n"
+);
+
+U_BOOT_CMD(
+ mdcom_cal_loadm , 2, 1, do_mdcom_cal_loadm,
+ "load modem calibration data from memory",
+ "Syntax:\n"
+ " - mdcom_cal_loadm {address} \n"
+ "Parameters:\n"
+ " - address: the address of the buffer to receive data\n"
+);
+
+U_BOOT_CMD(
+ mdcom_loadm , 3, 1, do_mdcom_loadm,
+ "load modem codes from memory",
+ "Syntax:\n"
+ " - mdcom_loadm {adress} [{cal_en}] \n"
+ "Parameters:\n"
+ " - address: the address of the buffer to receive data\n"
+ " - cal_en: enable calibration\n"
+);
+
+U_BOOT_CMD(
+ mdcom_loadf , 2, 1, do_mdcom_loadf,
+ "load modem codes from flash",
+ "Syntax:\n"
+ " - mdcom_loadf [{cal_en}] \n"
+ "Parameters:\n"
+ " - cal_en: enable calibration\n"
+);
+
+U_BOOT_CMD(
+ mdcom_calt , 1, 1, do_mdcom_cal_test,
+ "modem calibration test",
+ "Syntax:\n"
+ " - mdcom_calt\n"
+);
+
+U_BOOT_CMD(
+ mdcom_cal , 1, 1, do_mdcom_cal,
+ "modem calibration",
+ "Syntax:\n"
+ " - mdcom_cal\n"
+);
+
+U_BOOT_CMD(
+ mdcom_show , 1, 1, do_mdcom_ch_show,
+ "show mdcom all channels",
+ "Syntax:\n"
+ " - mdcom_show\n"
+);
+
+U_BOOT_CMD(
+ mdcom_cal_save , 1, 1, do_mdcom_cal_save,
+ "modem calibration data save",
+ "Syntax:\n"
+ " - mdcom_cal_save\n"
+);
+
+U_BOOT_CMD(
+ mdcom_cal_load , 1, 1, do_mdcom_cal_load,
+ "modem calibration data load",
+ "Syntax:\n"
+ " - mdcom_cal_load\n"
+);
+
+U_BOOT_CMD(
+ mdcom_diag, 1, 1, do_mdcom_diag,
+ "Show modem XCPU diagostic information",
+ "Syntax:\n"
+ " - mdcom_diag\n"
+);
+
+U_BOOT_CMD(
+ mdcom_ver, 1, 1, do_mdcom_ver,
+ "Show modem software versions",
+ "Syntax:\n"
+ " - mdcom_ver\n"
+);
+
+U_BOOT_CMD(
+ mdcom_check, 2, 1, do_check_and_wait_modem,
+ "check modem status, may wait",
+ "Syntax:\n"
+ " - mdcom_check {[check_boot_key]}\n"
+ "Parameters:\n"
+ " - check_boot_key: whether to check boot key status\n"
+);
+
diff --git a/common/cmd_mem.c b/common/cmd_mem.c
index fa6f5991a5..38e4fa264e 100644
--- a/common/cmd_mem.c
+++ b/common/cmd_mem.c
@@ -261,7 +261,7 @@ int do_mem_mwc ( cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- ulong addr1, addr2, count, ngood;
+ ulong addr1, addr2, count, ngood, nbad;
int size;
int rcode = 0;
@@ -296,6 +296,7 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
#endif
ngood = 0;
+ nbad = 0;
while (count-- > 0) {
if (size == 4) {
@@ -306,7 +307,8 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
"!= word at 0x%08lx (0x%08lx)\n",
addr1, word1, addr2, word2);
rcode = 1;
- break;
+ nbad++;
+ //break;
}
}
else if (size == 2) {
@@ -317,7 +319,8 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
"!= halfword at 0x%08lx (0x%04x)\n",
addr1, hword1, addr2, hword2);
rcode = 1;
- break;
+ nbad++;
+ //break;
}
}
else {
@@ -328,10 +331,20 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
"!= byte at 0x%08lx (0x%02x)\n",
addr1, byte1, addr2, byte2);
rcode = 1;
- break;
+ nbad++;
+ // break;
}
}
- ngood++;
+
+ if(rcode == 1){
+ rcode = 0;
+ if(nbad > 100){
+ return 1;
+ }
+ }
+ else
+ ngood++;
+
addr1 += size;
addr2 += size;
@@ -343,6 +356,9 @@ int do_mem_cmp (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("Total of %ld %s%s were the same\n",
ngood, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
ngood == 1 ? "" : "s");
+ printf("Total of %ld %s%s were different\n",
+ nbad, size == 4 ? "word" : size == 2 ? "halfword" : "byte",
+ nbad == 1 ? "" : "s");
return rcode;
}
diff --git a/common/cmd_misc.c b/common/cmd_misc.c
index 973b1c2082..5d2a0a30e9 100644
--- a/common/cmd_misc.c
+++ b/common/cmd_misc.c
@@ -26,8 +26,39 @@
*/
#include <common.h>
#include <command.h>
+#include <usb/usbserial.h>
+#include <nand.h>
+#include <jffs2/jffs2.h>
+#include <asm/arch/mdcom.h>
+#include <asm/arch/hwcfg.h>
+#include <asm/arch/factory.h>
+#include <asm/arch/prdinfo.h>
+#include <asm/arch/rda_sys.h>
+#include <part.h>
+#include <mmc.h>
+#include <mmc/mmcpart.h>
+#include <nand.h>
+#include <linux/mtd/nand.h>
+#include <mtd/nand/rda_nand.h>
+#include <android/android_boot.h>
+#include <android/android_bootimg.h>
+#include <rda/tgt_ap_panel_setting.h>
+#include <asm/arch/spl_board_info.h>
-int do_sleep (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+#ifdef FLASH_PAGE_SIZE
+#undef FLASH_PAGE_SIZE
+#endif
+#define FLASH_PAGE_SIZE 2048
+
+#define rda_dbg(fmt, args...) printf(fmt, ##args)
+
+extern int mtdparts_init_default(void);
+extern int find_dev_and_part(const char *id, struct mtd_device **dev,
+ u8 *part_num, struct part_info **part);
+
+static int rollback_to_recovery_mode = 0;
+
+int do_sleep(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
ulong start = get_timer(0);
ulong delay;
@@ -38,18 +69,673 @@ int do_sleep (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
delay = simple_strtoul(argv[1], NULL, 10) * CONFIG_SYS_HZ;
while (get_timer(start) < delay) {
- if (ctrlc ())
+ if (ctrlc())
return (-1);
- udelay (100);
+ udelay(100);
+ }
+
+ return 0;
+}
+
+int do_flush_dcache(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ unsigned long start_addr = 0;
+ unsigned long end_addr = 0;
+
+ if (argc < 3) {
+ printf("do flush dcache all...\n");
+ flush_dcache_all();
+ return 0;
+ }
+
+ start_addr = simple_strtoul(argv[1], NULL, 16);
+ end_addr = simple_strtoul(argv[2], NULL, 16);
+
+ printf("flush dcache %#x -> %#x\n", (unsigned int)start_addr, (unsigned int)end_addr);
+ flush_dcache_range(start_addr, end_addr);
+ return 0;
+}
+
+
+int do_mytest(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ ulong usec;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ usec = simple_strtoul(argv[1], NULL, 10) * 1000000;
+
+ udelay(usec);
+
+ return 0;
+}
+
+int do_rdaswcfg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ u16 swcfg;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+
+ swcfg = (u16)simple_strtoul(argv[1], NULL, 10);
+ rda_swcfg_reg_set(swcfg);
+
+ return 0;
+}
+
+int do_rdahwcfg(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ printf("RDA: HW_CFG 0x%04x\n", rda_hwcfg_get());
+ return 0;
+}
+
+int do_rdabm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ printf("RDA: Boot_Mode %d\n", rda_bm_get());
+ return 0;
+}
+
+int do_rdabminit(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ rda_bm_init();
+
+ return 0;
+}
+
+static int get_lcd_name(void)
+{
+ char lcd_paras[50] = "lcd=";
+ char *lcd_name = (char *)factory_get_lcd_name();
+
+#define PANEL_PARM "lcd="PANEL_NAME
+
+ setenv("lcd", PANEL_PARM);
+ if (!lcd_name || strlen(lcd_name) == 0) {
+ rda_dbg("factorydata does not contain lcd name, using default\n");
+ return 0;
+ }
+
+ if (strstr(RDA_PANEL_SUPPORT_LIST, lcd_name) == NULL) {
+ rda_dbg("RDA does not support %s lcd panel\n", lcd_name);
+ rda_dbg("Using default, please contact RDA.n");
+ return 0;
+ }
+
+ strncat(lcd_paras, lcd_name, 50);
+ setenv("lcd", lcd_paras);
+ return 0;
+}
+
+
+static int get_bootlogo_name(void)
+{
+ char logo_paras[50] = "bootlogo=";
+#ifdef CONFIG_MACH_RDA8810E//need debug in future
+ char *name = NULL;//(char *)factory_get_bootlogo_name();
+#else
+ char *name = (char *)factory_get_bootlogo_name();
+#endif
+
+ if (!name || strlen(name) == 0) {
+ rda_dbg("Does not find bootlogo name, using default\n");
+ return 0;
}
+ strncat(logo_paras, name, 50);
+ setenv("bootlogo", logo_paras);
return 0;
}
+int do_get_bootlogo_name(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (get_bootlogo_name())
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+
+int do_ap_factory_use(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ u8* addr;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ addr = (u8*)simple_strtoul(argv[1], NULL, 16);
+
+ if (factory_set_ap_factory(addr))
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+
+int do_ap_factory_update(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ u8* addr;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ addr = (u8*)simple_strtoul(argv[1], NULL, 16);
+
+ if (factory_update_ap_factory(addr))
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+
+int do_get_lcd_name(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (get_lcd_name())
+ return CMD_RET_FAILURE;
+ else
+ return CMD_RET_SUCCESS;
+}
+
+int do_get_emmc_id(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ struct spl_emmc_info * emmc_info = get_bd_spl_emmc_info();
+ char emmc_id[16] = {0};
+
+ if(CONFIG_MMC_DEV_NUM == 0)
+ return CMD_RET_SUCCESS;
+
+ sprintf(emmc_id, "emmc_id=%d", emmc_info->manufacturer_id);
+
+ setenv("emmc_id", emmc_id);
+
+ return CMD_RET_SUCCESS;
+}
+
+extern int rda_flash_intf_is_spi(void);
+
+static int do_get_flash_intf(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ if (rda_media_get() == MEDIA_MMC ) {
+#ifdef CONFIG_SDMMC_BOOT
+ setenv("flash_if", "flash_if=sdcard");
+#else
+ setenv("flash_if", "flash_if=emmc");
+#endif
+ } else {
+ if(rda_flash_intf_is_spi())
+ setenv("flash_if", "flash_if=spi");
+ else
+ setenv("flash_if", "flash_if=normal");
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+extern int hal_BoardSetup(void);
+
+static int do_board_mux_config(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+#ifdef CONFIG_RDA_MUX_CONFIG
+ int ret = 0;
+ ret = hal_BoardSetup();
+ if(ret == CMD_RET_SUCCESS)
+ puts("Board Mux : Done. \n");
+ else
+ puts("Board Mux : Error. \n");
+
+ return ret;
+#else
+ puts("Board Mux : Bypass bootloader board mux config. \n");
+ return CMD_RET_SUCCESS;
+#endif
+}
+
+static int do_get_android_bm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ enum rda_bm_type bm;
+ u32 reset_cause;
+
+ setenv("chargerboot", "0");
+ bm = rda_bm_get();
+ switch (bm) {
+ case RDA_BM_RECOVERY:
+ setenv("androidboot", "androidboot.mode=recovery");
+ break;
+ case RDA_BM_FACTORY:
+ setenv("androidboot", "androidboot.mode=factory");
+ break;
+ default:
+ reset_cause = rda_mdcom_get_reset_cause();
+ if (reset_cause == RDA_RESET_CAUSE_CHARGER) {
+ setenv("androidboot", "androidboot.mode=charger");
+#ifdef CHARGER_IN_RECOVERY
+/* only move charger to recovery partition after aosp 4.4 (including)*/
+ setenv("chargerboot", "1");
+#endif
+ } else {
+ setenv("androidboot", "androidboot.mode=normal");
+ }
+ break;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static u8 *recovery_image = (u8 *)SCRATCH_ADDR;
+
+static int load_recovery_from_nand(void)
+{
+ void *data = (void *)recovery_image;
+ struct mtd_info *nand;
+ struct mtd_device *dev;
+ struct part_info *part;
+ size_t size = 0;
+ u8 pnum;
+ int ret;
+
+ ret = find_dev_and_part("recovery", &dev, &pnum, &part);
+ if (ret) {
+ serial_printf("unknown partition name");
+ return CMD_RET_FAILURE;
+ } else if (dev->id->type != MTD_DEV_TYPE_NAND) {
+ serial_printf("mtd dev type error");
+ return CMD_RET_FAILURE;
+ }
+ nand = &nand_info[dev->id->num];
+ serial_printf("found part '%s' offset: 0x%llx length: 0x%llx\n",
+ part->name, part->offset, part->size);
+
+ size = part->size;
+
+ serial_printf("read 0x%x bytes from '%s' offset: 0x%llx\n",
+ size, part->name, part->offset);
+ ret = nand_read_skip_bad(nand, part->offset, &size, (u_char *) data);
+ if (ret) {
+ serial_printf("nand read fail");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int load_recovery_from_mmc(void)
+{
+ void *data = (void *)recovery_image;
+ disk_partition_t *ptn;
+ block_dev_desc_t *mmc_blkdev;
+ loff_t size = 0;
+
+ serial_printf("%s\n", __func__);
+ mmc_blkdev = get_dev_by_name(CONFIG_MMC_DEV_NAME);
+ ptn = partition_find_ptn("recovery");
+
+ if (ptn == 0) {
+ serial_printf("mmc partition table doesn't exist");
+ puts("Board Mux : Done. \n");
+ return CMD_RET_FAILURE;
+ }
+
+ size = ptn->size * ptn->blksz;
+
+ serial_printf("read 0x%x bytes from recovery offset: %lx\n", (unsigned int)size,
+ ptn->start);
+ if (partition_read_bytes(mmc_blkdev, ptn, &size, data)) {
+ serial_printf("mmc read failure");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int check_recovery_image(void)
+{
+ boot_img_hdr *hdr;
+
+ /* Check recovery image header */
+ hdr = (boot_img_hdr *)recovery_image;
+ if (memcmp(hdr->magic, BOOT_MAGIC, BOOT_MAGIC_SIZE)) {
+ serial_printf("Invalid magic\n");
+ return CMD_RET_FAILURE;
+ }
+
+ if (hdr->page_size != FLASH_PAGE_SIZE) {
+ serial_printf("Invalid page size: %d (expecting %d)\n",
+ hdr->page_size, FLASH_PAGE_SIZE);
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+
+static int load_ap_recovery(void)
+{
+ int ret = CMD_RET_SUCCESS;
+ enum media_type media;
+
+ media = rda_media_get();
+ if (media == MEDIA_MMC)
+ ret = load_recovery_from_mmc();
+ else if ((media == MEDIA_NAND) || media == MEDIA_SPINAND)
+ ret = load_recovery_from_nand();
+ else {
+ serial_printf("%s can't find boot media\n", __func__);
+ ret = CMD_RET_FAILURE;
+ }
+
+ if (ret != CMD_RET_SUCCESS) {
+ serial_printf("%s failed, ret is %d\n", __func__, ret);
+ return ret;
+ }
+ ret = check_recovery_image();
+
+ return ret;
+}
+
+/*
+ * For moving charger to recovery image to save 500KB in ramdisk
+ * CHARGER BOOT mode will need to load recovery kernel and rootfs
+ * 1. load modem from boot image and normal boot image first, so no extra delay
+ * for normal boot. (rda_mdcom_get_reset_cause only works after modem is up)
+ * 2. after modem is up and CHARGER MODE detected, load recovery image
+ */
+static int do_load_ap_recovery(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ return load_ap_recovery();
+}
+
+extern int mdcom_load_from_flash(int cal_en);
+extern int mdcom_load_from_mem(const u8 *data, int cal_en);
+extern int mdcom_check_and_wait_modem(int check_boot_key);
+
+static int do_load_recovery(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int ret = CMD_RET_SUCCESS;
+ enum rda_bm_type bm;
+ boot_img_hdr *hdr;
+ unsigned kernel_actual;
+ unsigned ramdisk_actual;
+ unsigned second_actual;
+ unsigned size;
+
+ /* Load recovery modem only in recovery mode, and
+ * load normal modem in factory mode */
+ bm = rda_bm_get();
+ if (bm != RDA_BM_RECOVERY) {
+ rollback_to_recovery_mode = 1;
+ ret = mdcom_load_from_flash(0);
+ if (ret != CMD_RET_SUCCESS) {
+ serial_printf("Bad modem image. Try recovery mode\n");
+ udelay(5000);
+ rda_reboot(REBOOT_TO_RECOVERY_MODE);
+ }
+ }
+
+ ret = load_ap_recovery();
+ if (ret != CMD_RET_SUCCESS)
+ return ret;
+
+
+ if (bm == RDA_BM_RECOVERY) {
+ hdr = (boot_img_hdr *)recovery_image;
+ kernel_actual = ROUND(hdr->kernel_size, FLASH_PAGE_SIZE);
+ ramdisk_actual = ROUND(hdr->ramdisk_size, FLASH_PAGE_SIZE);
+ second_actual = ROUND(hdr->second_size, FLASH_PAGE_SIZE);
+ size = FLASH_PAGE_SIZE + kernel_actual + ramdisk_actual +
+ second_actual;
+
+ ret = mdcom_load_from_mem(recovery_image + size, 0);
+
+ if (ret != CMD_RET_SUCCESS)
+ return ret;
+ }
+
+ ret = mdcom_check_and_wait_modem(0);
+ if (ret != CMD_RET_SUCCESS && bm != RDA_BM_RECOVERY) {
+ serial_printf("Modem no response. Try recovery mode\n");
+ udelay(5000);
+ rda_reboot(REBOOT_TO_RECOVERY_MODE);
+ }
+
+ return ret;
+}
+
+int load_boot_from_nand(void)
+{
+ boot_img_hdr *hdr;
+ void *data = (void *)SCRATCH_ADDR;
+ struct mtd_info *nand;
+ struct mtd_device *dev;
+ struct part_info *part;
+ size_t size = 0;
+ u8 pnum;
+ unsigned kernel_actual;
+ unsigned ramdisk_actual;
+ int ret;
+
+ ret = find_dev_and_part("boot", &dev, &pnum, &part);
+ if (ret) {
+ rda_dbg("unknown partition name\n");
+ return CMD_RET_FAILURE;
+ } else if (dev->id->type != MTD_DEV_TYPE_NAND) {
+ rda_dbg("mtd dev type error\n");
+ return CMD_RET_FAILURE;
+ }
+ nand = &nand_info[dev->id->num];
+ rda_dbg("found part '%s' offset: 0x%llx length: 0x%llx\n",
+ part->name, part->offset, part->size);
+
+ /* get hdr first */
+ size = ROUND(2048, FLASH_PAGE_SIZE);
+ rda_dbg("read 0x%x bytes from '%s' offset: 0x%llx\n",
+ size, part->name, part->offset);
+
+ ret = nand_read_skip_bad(nand, part->offset, &size, (u_char *) data);
+ if (ret) {
+ rda_dbg("nand read fail\n");
+ return CMD_RET_FAILURE;
+ }
+
+ /* get size from hdr */
+ hdr = (boot_img_hdr *) data;
+ kernel_actual = ROUND(hdr->kernel_size, FLASH_PAGE_SIZE);
+ ramdisk_actual = ROUND(hdr->ramdisk_size, FLASH_PAGE_SIZE);
+ size = 2048 + kernel_actual + ramdisk_actual;
+
+ /* load whole boot.img */
+ rda_dbg("read 0x%x bytes from '%s' offset: 0x%llx\n",
+ size, part->name, part->offset);
+ ret = nand_read_skip_bad(nand, part->offset, &size, (u_char *) data);
+ if (ret) {
+ rda_dbg("nand read fail\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static block_dev_desc_t *mmc_blkdev;
+int load_boot_from_mmc(void)
+{
+ void *data = (void *)SCRATCH_ADDR;
+ disk_partition_t *ptn;
+ loff_t size = 0;
+
+ rda_dbg("%s\n", __func__);
+ mmc_blkdev = get_dev_by_name(CONFIG_MMC_DEV_NAME);
+ ptn = partition_find_ptn("boot");
+
+ if (ptn == 0) {
+ rda_dbg("mmc partition table doesn't exist\n");
+ return CMD_RET_FAILURE;
+ }
+
+ size = ptn->size * ptn->blksz;
+
+ rda_dbg("read 0x%x bytes from boot offset: %lx\n", (unsigned int)size,
+ ptn->start);
+ if (partition_read_bytes(mmc_blkdev, ptn, &size, data)) {
+ rda_dbg("mmc read failure\n");
+ return CMD_RET_FAILURE;
+ }
+
+ return CMD_RET_SUCCESS;
+}
+
+static int do_load_boot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int ret = CMD_RET_FAILURE;
+ enum media_type media;
+
+ media = rda_media_get();
+ serial_printf("load boot image ...\n");
+ if (media == MEDIA_MMC)
+ ret = load_boot_from_mmc();
+ else if ((media == MEDIA_NAND) || (media == MEDIA_SPINAND))
+ ret = load_boot_from_nand();
+ else
+ serial_printf("load_boot can't find boot media\n");
+
+ return ret;
+}
+
+static int do_adjust_bootdelay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int bootmode;
+
+ bootmode = rda_bm_get();
+ if (bootmode == RDA_BM_FASTBOOT)
+ setenv("bootdelay", "3");
+
+ return CMD_RET_SUCCESS;
+}
U_BOOT_CMD(
sleep , 2, 1, do_sleep,
"delay execution for some time",
"N\n"
" - delay execution for N seconds (N is _decimal_ !!!)"
);
+
+U_BOOT_CMD(
+ flush_dcache , 3, 1, do_flush_dcache,
+ "flush dcache",
+ "start_addr end_addr\n"
+ " - flush dcache from [start_addr] to [end_addr]"
+);
+
+U_BOOT_CMD(
+ mytest , 2, 1, do_mytest,
+ "exec certain test routine",
+ "arg\n"
+ " - exec with arg (arg is _decimal_ !!!)"
+);
+
+U_BOOT_CMD(
+ rdaswcfg , 2, 1, do_rdaswcfg,
+ "set rda swcfg",
+ "Syntax:\n"
+ " - rdaswcfg swcfg\n"
+);
+
+U_BOOT_CMD(
+ rdahwcfg , 1, 1, do_rdahwcfg,
+ "get rda hwcfg",
+ "Syntax:\n"
+ " - rdahwcfg\n"
+);
+
+U_BOOT_CMD(
+ rdabm , 1, 1, do_rdabm,
+ "get rda boot_mode",
+ "Syntax:\n"
+ " - rdabm\n"
+);
+
+U_BOOT_CMD(
+ rdabminit , 1, 1, do_rdabminit,
+ "init rda boot_mode",
+ "Syntax:\n"
+ " - rdabminit\n"
+);
+
+U_BOOT_CMD(
+ ap_factory_use , 2, 1, do_ap_factory_use,
+ "use ap factory data from specified memory",
+ "Syntax:\n"
+ " - factory_use addr\n"
+);
+
+
+U_BOOT_CMD(
+ ap_factory_update , 2, 1, do_ap_factory_update,
+ "update ap factory data from specified memory",
+ "Syntax:\n"
+ " - factory_update addr\n"
+);
+
+U_BOOT_CMD(
+ get_lcd_name , 1, 1, do_get_lcd_name,
+ "ap find lcd panel name",
+ "Syntax:\n"
+ " - find_lcd_name\n"
+);
+
+U_BOOT_CMD(
+ get_flash_intf, 1, 1, do_get_flash_intf,
+ "ap find flash interface",
+ "Syntax:\n"
+ " - get_flash_intf\n"
+);
+
+U_BOOT_CMD(
+ get_emmc_id, 1, 1, do_get_emmc_id,
+ "ap find emmc manufacturer id and pass it to kernel",
+ "Syntax:\n"
+ " - get_emmc_id\n"
+);
+
+U_BOOT_CMD(
+ mux_config, 1, 1, do_board_mux_config,
+ "check and set board mux config (pinmux,io drive,io pin mode...)",
+ "Syntax:\n"
+ " - mux_config\n"
+);
+
+U_BOOT_CMD(
+ get_android_bm, 1, 1, do_get_android_bm,
+ "get android bootmode",
+ "Syntax:\n"
+ " - get_android_bm \n"
+);
+
+U_BOOT_CMD(
+ load_ap_recovery, 1, 1, do_load_ap_recovery,
+ "load recovery kernel and ramdisk to address",
+ "Syntax:\n"
+ " - load_ap_recovery address \n"
+);
+
+U_BOOT_CMD(
+ load_recovery, 1, 1, do_load_recovery,
+ "load recovery image to address",
+ "Syntax:\n"
+ " - load_recovery address \n"
+);
+
+U_BOOT_CMD(
+ load_boot, 1, 1, do_load_boot,
+ "load boot image to address",
+ "Syntax:\n"
+ " - load_boot address \n"
+);
+
+U_BOOT_CMD(
+ get_bootlogo_name , 1, 1, do_get_bootlogo_name,
+ "find bootlogo name",
+ "Syntax:\n"
+ " - get_bootlogo_name\n"
+);
+
+U_BOOT_CMD(
+ adjust_bootdelay , 1, 1, do_adjust_bootdelay,
+ "re-adjust bootdelay according to bootmode",
+ "Syntax:\n"
+ " - adjust_bootdelay\n"
+);
diff --git a/common/cmd_mmc.c b/common/cmd_mmc.c
index 750509da5e..674c1f5a7e 100644
--- a/common/cmd_mmc.c
+++ b/common/cmd_mmc.c
@@ -2,23 +2,7 @@
* (C) Copyright 2003
* Kyle Harris, kharris@nexus-tech.net
*
- * See file CREDITS for list of people who contributed to this
- * project.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of
- * the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
- * MA 02111-1307 USA
+ * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
@@ -92,6 +76,8 @@ enum mmc_state {
MMC_READ,
MMC_WRITE,
MMC_ERASE,
+ MMC_ERASE_PART,
+ MMC_TEST,
};
static void print_mmcinfo(struct mmc *mmc)
{
@@ -106,7 +92,7 @@ static void print_mmcinfo(struct mmc *mmc)
printf("Rd Block Len: %d\n", mmc->read_bl_len);
printf("%s version %d.%d\n", IS_SD(mmc) ? "SD" : "MMC",
- (mmc->version >> 4) & 0xf, mmc->version & 0xf);
+ (mmc->version >> 8) & 0xf, mmc->version & 0xff);
printf("High Capacity: %s\n", mmc->high_capacity ? "Yes" : "No");
puts("Capacity: ");
@@ -115,13 +101,13 @@ static void print_mmcinfo(struct mmc *mmc)
printf("Bus Width: %d-bit\n", mmc->bus_width);
}
-int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+static int do_mmcinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
struct mmc *mmc;
if (curr_device < 0) {
if (get_mmc_num() > 0)
- curr_device = 0;
+ curr_device = 1;
else {
puts("No MMC device available\n");
return 1;
@@ -144,11 +130,40 @@ int do_mmcinfo (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
U_BOOT_CMD(
mmcinfo, 1, 0, do_mmcinfo,
"display MMC info",
- " - device number of the device to dislay info of\n"
- ""
+ "- display info of the current MMC device"
);
-int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+static int boot_part_access(struct mmc *mmc, u8 ack, u8 part_num, u8 access)
+{
+ int err;
+ err = mmc_boot_part_access(mmc, ack, part_num, access);
+
+ if ((err == 0) && (access != 0)) {
+ printf("\t\t\t!!!Notice!!!\n");
+
+ printf("!You must close EMMC boot Partition");
+ printf("after all images are written\n");
+
+ printf("!EMMC boot partition has continuity");
+ printf("at image writing time.\n");
+
+ printf("!So, do not close the boot partition");
+ printf("before all images are written.\n");
+ return 0;
+ } else if ((err == 0) && (access == 0))
+ return 0;
+ else if ((err != 0) && (access != 0)) {
+ printf("EMMC boot partition-%d OPEN Failed.\n", part_num);
+ return 1;
+ } else {
+ printf("EMMC boot partition-%d CLOSE Failed.\n", part_num);
+ return 1;
+ }
+}
+#endif
+
+static int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
enum mmc_state state;
@@ -157,7 +172,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (curr_device < 0) {
if (get_mmc_num() > 0)
- curr_device = 0;
+ curr_device = 1;
else {
puts("No MMC device available\n");
return 1;
@@ -165,8 +180,12 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
if (strcmp(argv[1], "rescan") == 0) {
- struct mmc *mmc = find_mmc_device(curr_device);
+ struct mmc *mmc;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ mmc = find_mmc_device(curr_device);
if (!mmc) {
printf("no mmc device at slot %x\n", curr_device);
return 1;
@@ -180,8 +199,12 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
return 0;
} else if (strncmp(argv[1], "part", 4) == 0) {
block_dev_desc_t *mmc_dev;
- struct mmc *mmc = find_mmc_device(curr_device);
+ struct mmc *mmc;
+
+ if (argc != 2)
+ return CMD_RET_USAGE;
+ mmc = find_mmc_device(curr_device);
if (!mmc) {
printf("no mmc device at slot %x\n", curr_device);
return 1;
@@ -197,8 +220,56 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
puts("get mmc type error!\n");
return 1;
} else if (strcmp(argv[1], "list") == 0) {
+ if (argc != 2)
+ return CMD_RET_USAGE;
print_mmc_devices('\n');
return 0;
+ } else if (strncmp(argv[1], "speed", 5) == 0) {
+ struct mmc *mmc;
+ int ret;
+ u64 offset;
+ unsigned long long start_clock, end_clock;
+ unsigned long duration, mmc_read_speed, mmc_write_speed;
+ u_char *datbuf;
+ size_t test_data_size;
+
+ if (argc < 5) {
+ datbuf = (u_char *)(0x80000000);
+ offset = (u64)(0x00100000);
+ test_data_size = (size_t)(0x00A00000);
+ } else {
+ datbuf = (u_char *)simple_strtoul(argv[2], NULL, 16);
+ offset = (u64)simple_strtoul(argv[3], NULL, 16);
+ test_data_size = (size_t)simple_strtoul(argv[4], NULL, 16);
+ }
+
+ mmc = find_mmc_device(curr_device);
+ mmc_init(mmc);
+
+ start_clock = get_ticks();
+ ret = mmc_read(mmc, offset, datbuf, test_data_size);
+ end_clock = get_ticks();
+ duration = (unsigned long)(end_clock - start_clock);
+ mmc_read_speed = (unsigned long)(test_data_size / (duration * 1000 / get_tbclk()) * 1000 / 1024);
+ if (ret == test_data_size)
+ printf("\nMmc Read speed = %ld Kbyte/s\n", mmc_read_speed);
+ else {
+ printf("\nRead data from Mmc failed\n");
+ return 1;
+ }
+
+ start_clock = get_ticks();
+ ret = mmc_write(mmc, offset, datbuf, test_data_size);
+ end_clock = get_ticks();
+ duration = (unsigned long)(end_clock - start_clock);
+ mmc_write_speed = (unsigned long)(test_data_size / (duration * 1000 / get_tbclk()) * 1000 / 1024);
+ if (ret == test_data_size)
+ printf("\nMmc Write speed = %ld Kbyte/s\n", mmc_write_speed);
+ else {
+ printf("\nWrite data to Mmc failed\n");
+ return 1;
+ }
+ return 0;
} else if (strcmp(argv[1], "dev") == 0) {
int dev, part = -1;
struct mmc *mmc;
@@ -237,7 +308,7 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
if (!ret)
mmc->part_num = part;
- printf("switch to partions #%d, %s\n",
+ printf("switch to partitions #%d, %s\n",
part, (!ret) ? "OK" : "ERROR");
}
}
@@ -249,41 +320,132 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
curr_device, mmc->part_num);
return 0;
- }
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+ } else if ((strcmp(argv[1], "open") == 0) ||
+ (strcmp(argv[1], "close") == 0)) {
+ int dev;
+ struct mmc *mmc;
+ u8 part_num, access = 0;
- if (strcmp(argv[1], "read") == 0)
+ if (argc == 4) {
+ dev = simple_strtoul(argv[2], NULL, 10);
+ part_num = simple_strtoul(argv[3], NULL, 10);
+ } else {
+ return CMD_RET_USAGE;
+ }
+
+ mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("no mmc device at slot %x\n", dev);
+ return 1;
+ }
+
+ if (IS_SD(mmc)) {
+ printf("SD device cannot be opened/closed\n");
+ return 1;
+ }
+
+ if ((part_num <= 0) || (part_num > MMC_NUM_BOOT_PARTITION)) {
+ printf("Invalid boot partition number:\n");
+ printf("Boot partition number cannot be <= 0\n");
+ printf("EMMC44 supports only 2 boot partitions\n");
+ return 1;
+ }
+
+ if (strcmp(argv[1], "open") == 0)
+ access = part_num; /* enable R/W access to boot part*/
+ else
+ access = 0; /* No access to boot partition */
+
+ /* acknowledge to be sent during boot operation */
+ return boot_part_access(mmc, 1, part_num, access);
+
+ } else if (strcmp(argv[1], "bootpart") == 0) {
+ int dev;
+ dev = simple_strtoul(argv[2], NULL, 10);
+
+ u32 bootsize = simple_strtoul(argv[3], NULL, 10);
+ u32 rpmbsize = simple_strtoul(argv[4], NULL, 10);
+ struct mmc *mmc = find_mmc_device(dev);
+ if (!mmc) {
+ printf("no mmc device at slot %x\n", dev);
+ return 1;
+ }
+
+ if (IS_SD(mmc)) {
+ printf("It is not a EMMC device\n");
+ return 1;
+ }
+
+ if (0 == mmc_boot_partition_size_change(mmc,
+ bootsize, rpmbsize)) {
+ printf("EMMC boot partition Size %d MB\n", bootsize);
+ printf("EMMC RPMB partition Size %d MB\n", rpmbsize);
+ return 0;
+ } else {
+ printf("EMMC boot partition Size change Failed.\n");
+ return 1;
+ }
+#endif /* CONFIG_SUPPORT_EMMC_BOOT */
+ }
+ state = MMC_INVALID;
+ if (argc == 5 && strcmp(argv[1], "read") == 0)
state = MMC_READ;
- else if (strcmp(argv[1], "write") == 0)
+ else if (argc == 5 && strcmp(argv[1], "write") == 0)
state = MMC_WRITE;
- else if (strcmp(argv[1], "erase") == 0)
+ else if (argc == 6 && strcmp(argv[1], "test") == 0)
+ state = MMC_TEST;
+ else if (argc == 4 && strcmp(argv[1], "erase") == 0)
state = MMC_ERASE;
- else
- state = MMC_INVALID;
+ else if (argc == 3 && strcmp(argv[1], "erase.part") == 0)
+ state = MMC_ERASE_PART;
if (state != MMC_INVALID) {
struct mmc *mmc = find_mmc_device(curr_device);
int idx = 2;
u32 blk, cnt, n;
- void *addr;
-
- if (state != MMC_ERASE) {
- addr = (void *)simple_strtoul(argv[idx], NULL, 16);
- ++idx;
- } else
- addr = 0;
- blk = simple_strtoul(argv[idx], NULL, 16);
- cnt = simple_strtoul(argv[idx + 1], NULL, 16);
+ void *addr = NULL;
+ int times = 10;
if (!mmc) {
printf("no mmc device at slot %x\n", curr_device);
return 1;
}
- printf("\nMMC %s: dev # %d, block # %d, count %d ... ",
- argv[1], curr_device, blk, cnt);
-
mmc_init(mmc);
+ if ((state == MMC_WRITE || state == MMC_ERASE)) {
+ if (mmc_getwp(mmc) == 1) {
+ printf("Error: card is write protected!\n");
+ return 1;
+ }
+ }
+
+ if (state == MMC_ERASE_PART) {
+ disk_partition_t *ptn;
+ ptn = partition_find_ptn(argv[idx]);
+ if (!ptn) {
+ printf("Error: not found part [%s]\n", argv[idx]);
+ return 1;
+ }
+ blk = ptn->start;
+ cnt = ptn->size;
+ state = MMC_ERASE;
+
+ } else {
+ if (state != MMC_ERASE) {
+ addr = (void *)simple_strtoul(argv[idx], NULL, 16);
+ ++idx;
+ }
+ blk = simple_strtoul(argv[idx], NULL, 16);
+ cnt = simple_strtoul(argv[idx + 1], NULL, 16);
+ if (state == MMC_TEST)
+ times = simple_strtoul(argv[idx + 2], NULL, 10);
+ }
+
+ printf("\nMMC %s: dev # %d, block # %d, count %d ... ",
+ argv[1], curr_device, blk, cnt);
+
switch (state) {
case MMC_READ:
n = mmc->block_dev.block_read(curr_device, blk,
@@ -298,6 +460,51 @@ int do_mmcops(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
case MMC_ERASE:
n = mmc->block_dev.block_erase(curr_device, blk, cnt);
break;
+ case MMC_TEST:
+ {
+ u32 pat = 0x5a5a1234;
+ u32 *dat = addr;
+ u32 crc1 = 0, crc2 = 0;
+ u32 siz = cnt * 512;
+ int i, t;
+
+ /* test write/read */
+ n = cnt;
+ printf("\nTest start...\n");
+ for(t = 1; t <= times; t++)
+ {
+ /* fill buffer by pattern */
+ dat = addr;
+ for(i = 0; i < siz; i += 4)
+ {
+ *dat++ = pat;
+ pat += 0x10001;
+ }
+ crc1 = crc32(0, (void *)addr, siz);
+ pat = ~pat;
+
+ /* write to device */
+ mmc->block_dev.block_write(curr_device, blk, cnt, addr);
+
+ /* clear buffer */
+ memset((void*)addr, 0, siz);
+
+ /* read back */
+ mmc->block_dev.block_read(curr_device, blk, cnt, addr);
+ flush_cache((ulong)addr, cnt * 512);
+
+ /* compare and show result */
+ crc2 = crc32(0, (void *)addr, siz);
+ printf("Test %02d: expect crc = 0x%08x, got = 0x%08x, %s\n",
+ t, crc1, crc2,
+ (crc1==crc2) ? "SUCCESS!" : "FAIL!");
+
+ /* make fail tag */
+ if(crc1 != crc2)
+ n = cnt - 1;
+ }
+ }
+ break;
default:
BUG();
}
@@ -315,9 +522,20 @@ U_BOOT_CMD(
"MMC sub system",
"read addr blk# cnt\n"
"mmc write addr blk# cnt\n"
+ "mmc test addr blk# cnt times\n"
"mmc erase blk# cnt\n"
+ "mmc erase.part part_name\n"
"mmc rescan\n"
"mmc part - lists available partition on current mmc device\n"
"mmc dev [dev] [part] - show or set current mmc device [partition]\n"
- "mmc list - lists available devices");
+ "mmc list - lists available devices\n"
+#ifdef CONFIG_SUPPORT_EMMC_BOOT
+ "mmc open <dev> <boot_partition>\n"
+ " - Enable boot_part for booting and enable R/W access of boot_part\n"
+ "mmc close <dev> <boot_partition>\n"
+ " - Enable boot_part for booting and disable access to boot_part\n"
+ "mmc bootpart <device num> <boot part size MB> <RPMB part size MB>\n"
+ " - change sizes of boot and RPMB partitions of specified device\n"
#endif
+ );
+#endif /* !CONFIG_GENERIC_MMC */
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index 22688293ae..add0585037 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -99,6 +99,7 @@
#if defined(CONFIG_CMD_NAND)
#include <linux/mtd/nand.h>
#include <nand.h>
+#include <mtd/nand/rda_nand.h>
#endif
#if defined(CONFIG_CMD_ONENAND)
@@ -325,7 +326,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
{
struct mtd_info *mtd = NULL;
int i, j;
- ulong start;
+ u64 start;
if (get_mtd_info(id->type, id->num, &mtd))
return 1;
@@ -337,7 +338,7 @@ static int part_validate_eraseblock(struct mtdids *id, struct part_info *part)
* Only one eraseregion (NAND, OneNAND or uniform NOR),
* checking for alignment is easy here
*/
- if ((unsigned long)part->offset % mtd->erasesize) {
+ if (part->offset % (u64)mtd->erasesize) {
printf("%s%d: partition (%s) start offset"
"alignment incorrect\n",
MTD_DEV_TYPE(id->type), id->num, part->name);
@@ -412,19 +413,20 @@ static int part_validate(struct mtdids *id, struct part_info *part)
part->size = id->size - part->offset;
if (part->offset > id->size) {
- printf("%s: offset %08x beyond flash size %08x\n",
+ printf("%s: offset %llx beyond flash size 0x%llx\n",
id->mtd_id, part->offset, id->size);
return 1;
}
- if ((part->offset + part->size) <= part->offset) {
+ if (((u64)part->offset + (u64)part->size) <= (u64)part->offset) {
printf("%s%d: partition (%s) size too big\n",
MTD_DEV_TYPE(id->type), id->num, part->name);
return 1;
}
if (part->offset + part->size > id->size) {
- printf("%s: partitioning exceeds flash size\n", id->mtd_id);
+ printf("%s: partitioning exceeds flash size %llx, part %llx+%llx\n",
+ id->mtd_id, id->size, part->offset, part->size);
return 1;
}
@@ -462,7 +464,7 @@ static int part_del(struct mtd_device *dev, struct part_info *part)
if (curr_pi == part) {
printf("current partition deleted, resetting current to 0\n");
current_mtd_partnum = 0;
- } else if (part->offset <= curr_pi->offset) {
+ } else if (part->offset <= (u64)curr_pi->offset) {
current_mtd_partnum--;
}
current_save_needed = 1;
@@ -595,8 +597,7 @@ static int part_add(struct mtd_device *dev, struct part_info *part)
static int part_parse(const char *const partdef, const char **ret, struct part_info **retpart)
{
struct part_info *part;
- unsigned long size;
- unsigned long offset;
+ u64 size, offset;
const char *name;
int name_len;
unsigned int mask_flags;
@@ -615,7 +616,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
} else {
size = memsize_parse(p, &p);
if (size < MIN_PART_SIZE) {
- printf("partition size too small (%lx)\n", size);
+ printf("partition size too small (%llx)\n", size);
return 1;
}
}
@@ -680,6 +681,8 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
part->offset = offset;
part->mask_flags = mask_flags;
part->name = (char *)(part + 1);
+ /*we set the mtdpart is dirty and force erase before program if needed*/
+ part->dirty = 1;
if (name) {
/* copy user provided name */
@@ -687,14 +690,14 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
part->auto_name = 0;
} else {
/* auto generated name in form of size@offset */
- sprintf(part->name, "0x%08lx@0x%08lx", size, offset);
+ sprintf(part->name, "0x%llx@0x%llx", size, offset);
part->auto_name = 1;
}
part->name[name_len - 1] = '\0';
INIT_LIST_HEAD(&part->link);
- debug("+ partition: name %-22s size 0x%08x offset 0x%08x mask flags %d\n",
+ debug("+ partition: name %-22s size 0x%llx offset 0x%llx mask flags %d\n",
part->name, part->size,
part->offset, part->mask_flags);
@@ -710,7 +713,7 @@ static int part_parse(const char *const partdef, const char **ret, struct part_i
* @param size a pointer to the size of the mtd device (output)
* @return 0 if device is valid, 1 otherwise
*/
-int mtd_device_validate(u8 type, u8 num, u32 *size)
+int mtd_device_validate(u8 type, u8 num, u64 *size)
{
struct mtd_info *mtd = NULL;
@@ -843,7 +846,7 @@ static int device_parse(const char *const mtd_dev, const char **ret, struct mtd_
LIST_HEAD(tmp_list);
struct list_head *entry, *n;
u16 num_parts;
- u32 offset;
+ u64 offset;
int err = 1;
debug("===device_parse===\n");
@@ -1087,7 +1090,8 @@ static int generate_mtdparts(char *buf, u32 buflen)
struct part_info *part, *prev_part;
char *p = buf;
char tmpbuf[32];
- u32 size, offset, len, part_cnt;
+ u64 size, offset;
+ u32 len, part_cnt;
u32 maxlen = buflen - 1;
debug("--- generate_mtdparts ---\n");
@@ -1274,7 +1278,7 @@ static void print_partition_table(void)
part = list_entry(pentry, struct part_info, link);
net_size = net_part_size(mtd, part);
size_note = part->size == net_size ? " " : " (!)";
- printf("%2d: %-20s0x%08x\t0x%08x%s\t0x%08x\t%d\n",
+ printf("%2d: %-20s0x%llx\t0x%08x%s\t0x%llx\t%d\n",
part_num, part->name, part->size,
net_size, size_note, part->offset,
part->mask_flags);
@@ -1286,7 +1290,7 @@ static void print_partition_table(void)
list_for_each(pentry, &dev->parts) {
part = list_entry(pentry, struct part_info, link);
- printf("%2d: %-20s0x%08x\t0x%08x\t%d\n",
+ printf("%2d: %-20s0x%llx\t0x%llx\t%d\n",
part_num, part->name, part->size,
part->offset, part->mask_flags);
#endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
@@ -1299,6 +1303,41 @@ static void print_partition_table(void)
}
/**
+ * Given nand partition number find the partition info and
+ * corresponding nand device
+ *
+ * @param part_num nand partition number
+ * @param part pointer to requested partition (output)
+ * @param nand pointer to the nand device (output)
+ * @return 0 on success, -1 otherwise
+ */
+int find_nand_part_info(int part_num, struct part_info **part,
+ struct mtd_info **nand)
+{
+ struct list_head *dentry;
+ struct mtd_device *dev;
+
+ if (list_empty(&devices)) {
+ printf("no partitions defined\n");
+ return -1;
+ }
+
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+ /* list partitions for given device */
+
+ if (dev->id->type == MTD_DEV_TYPE_NAND) {
+ *part = mtd_part_info(dev, part_num);
+ if (!part)
+ return -1;
+ *nand = &nand_info[dev->id->num];
+ return 0;
+ }
+ }
+
+ return -1;
+}
+/**
* Format and print out a partition list for each device from global device
* list.
*/
@@ -1313,7 +1352,7 @@ static void list_partitions(void)
if (current_mtd_dev) {
part = mtd_part_info(current_mtd_dev, current_mtd_partnum);
if (part) {
- printf("\nactive partition: %s%d,%d - (%s) 0x%08x @ 0x%08x\n",
+ printf("\nactive partition: %s%d,%d - (%s) 0x%llx @ 0x%llx\n",
MTD_DEV_TYPE(current_mtd_dev->id->type),
current_mtd_dev->id->num, current_mtd_partnum,
part->name, part->size, part->offset);
@@ -1413,7 +1452,7 @@ static int delete_partition(const char *id)
if (find_dev_and_part(id, &dev, &pnum, &part) == 0) {
- debug("delete_partition: device = %s%d, partition %d = (%s) 0x%08x@0x%08x\n",
+ debug("delete_partition: device = %s%d, partition %d = (%s) 0x%llx@0x%llx\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num, pnum,
part->name, part->size, part->offset);
@@ -1502,7 +1541,7 @@ static int spread_partitions(void)
part = list_entry(pentry, struct part_info, link);
debug("spread_partitions: device = %s%d, partition %d ="
- " (%s) 0x%08x@0x%08x\n",
+ " (%s) 0x%08x@0x%llx\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num,
part_num, part->name, part->size,
part->offset);
@@ -1599,7 +1638,7 @@ static int parse_mtdids(const char *const ids)
struct list_head *entry, *n;
struct mtdids *id_tmp;
u8 type, num;
- u32 size;
+ u64 size;
int ret = 1;
debug("\n---parse_mtdids---\nmtdids = %s\n\n", ids);
@@ -1673,7 +1712,7 @@ static int parse_mtdids(const char *const ids)
id->mtd_id[mtd_id_len - 1] = '\0';
INIT_LIST_HEAD(&id->link);
- debug("+ id %s%d\t%16d bytes\t%s\n",
+ debug("+ id %s%d\t%lld bytes\t%s\n",
MTD_DEV_TYPE(id->type), id->num,
id->size, id->mtd_id);
@@ -1829,6 +1868,296 @@ int mtdparts_init(void)
return 0;
}
+/* Load mtd partition table from flash */
+static int mtdparts_ptbl_read(char *data)
+{
+ nand_info_t *nand;
+ int dev = nand_curr_device;
+ int ret = 0;
+ char *buff;
+ size_t rsize;
+ u32 offs = CONFIG_MTD_PTBL_OFFS;
+ u32 data_size, data_crc;
+
+ if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+ !nand_info[dev].name) {
+ printf("%s: nand not init.\n", __func__);
+ return -1;
+ }
+ nand = &nand_info[dev];
+
+ {
+ struct nand_chip *this = nand->priv;
+ struct rda_nand_info *info = this->priv;
+ offs = (offs * info->spl_adjust_ratio) / 2;
+ }
+
+ buff = malloc(CONFIG_MTD_PTBL_SIZE);
+ if(!buff) {
+ printf("%s: can't malloc memory.\n", __func__);
+ return -1;
+ }
+
+ /* calculate read size */
+ rsize = nand->erasesize - (offs % nand->erasesize);
+ if(rsize > CONFIG_MTD_PTBL_SIZE) {
+ rsize = CONFIG_MTD_PTBL_SIZE;
+ }
+
+ /* read data from flash */
+ ret = nand_read_skip_bad(nand, offs, &rsize, (u_char *)buff);
+ if(ret) {
+ printf("%s: flash read error %d\n", __func__, ret);
+ ret = -1;
+ goto exit;
+ }
+
+ memcpy((void*)&data_size, (void*)&buff[0], 4);
+ memcpy((void*)&data_crc, (void*)&buff[4], 4);
+ if(!data_size || data_size > (CONFIG_MTD_PTBL_SIZE - 8)) {
+ printf("%s: partition table is invalid.\n", __func__);
+ ret = -1;
+ goto exit;
+ }
+
+ /* crc checking */
+ if(data_crc != crc32(0, (const unsigned char *)(&buff[8]), data_size)) {
+ printf("%s: crc checking failed.\n", __func__);
+ ret = -1;
+ goto exit;
+ }
+
+ memcpy(data, (void*)&buff[8], data_size);
+ printf("%s: load partition table from %#x\n", __func__, offs);
+ printf("partition table: %s\n", data);
+
+exit:
+ free(buff);
+ return ret;
+}
+
+/* save mtd partition table to flash */
+static int mtdparts_ptbl_write(char *data, int need_erase)
+{
+ nand_info_t *nand;
+ int dev = nand_curr_device;
+ int ret = 0;
+ size_t wsize, rsize;
+ char *buff;
+ u32 offs = CONFIG_MTD_PTBL_OFFS;
+ nand_erase_options_t opts;
+ u32 data_size = strlen(data) + 1;
+ u32 data_crc;
+
+ buff = malloc(CONFIG_MTD_PTBL_SIZE);
+ if(!buff) {
+ printf("%s: can't malloc memory.\n", __func__);
+ return -1;
+ }
+
+ /* check if the new table is same as old */
+ if(mtdparts_ptbl_read(buff) == 0) {
+ if(strcmp(buff, data) == 0) {
+ printf("%s: same as old, do nothing.\n", __func__);
+ free(buff);
+ return 0;
+ }
+ }
+ free(buff);
+
+ if (dev < 0 || dev >= CONFIG_SYS_MAX_NAND_DEVICE ||
+ !nand_info[dev].name) {
+ printf("%s: nand not init.\n", __func__);
+ return -1;
+ }
+ nand = &nand_info[dev];
+
+ {
+ printf("mtdparts_ptbl_write0: offs = 0x%x \n", offs);
+ struct nand_chip *this = nand->priv;
+ struct rda_nand_info *info = this->priv;
+ offs = (offs * info->spl_adjust_ratio) / 2;
+ printf("mtdparts_ptbl_write1: offs = 0x%x \n", offs);
+ }
+
+ printf("%s: save partition table to %#x\n", __func__, offs);
+ printf("%s: %s\n", __func__, data);
+
+ /* Limit data in one block */
+ if(data_size > (CONFIG_MTD_PTBL_SIZE - 8) ||
+ data_size > (nand->erasesize - (offs % nand->erasesize) - 8)) {
+ printf("%s: data size is too large.\n", __func__);
+ return -1;
+ }
+
+ buff = malloc(nand->erasesize);
+ if(!buff) {
+ printf("%s: can't malloc memory.\n", __func__);
+ return -1;
+ }
+
+ /* not need to do erase */
+ if(!need_erase) {
+ /* fill buffer */
+ data_crc = crc32(0, (const unsigned char *)data, data_size);
+ memcpy((void *)(buff), &data_size, 4);
+ memcpy((void *)(buff+4), &data_crc, 4);
+ memcpy((void *)(buff+8), data, data_size);
+
+ /* write data to flash */
+ wsize = data_size + 8;
+ ret = nand_write_skip_bad(nand, offs, &wsize, (u_char *)buff, 0);
+ if(ret) {
+ printf("%s: flash write error %d\n", __func__, ret);
+ }
+ goto exit;
+ }
+
+ /* need to do erase */
+
+ memset(&opts, 0, sizeof(opts));
+ opts.offset = (loff_t) (offs - (offs % nand->erasesize));
+ opts.length = (loff_t) nand->erasesize;
+ opts.jffs2 = 0;
+ opts.quiet = 0;
+
+ /* Read this block data to buffer */
+ rsize = nand->erasesize;
+ ret = nand_read_skip_bad(nand, opts.offset, &rsize, (u_char *)buff);
+ if(ret) {
+ printf("%s: flash read error %d\n", __func__, ret);
+ goto exit;
+ }
+
+ /* erase block */
+ ret = nand_erase_opts(nand, &opts);
+ if(ret) {
+ printf("%s: flash erase error %d\n", __func__, ret);
+ goto exit;
+ }
+
+ /* fill buffer */
+ data_crc = crc32(0, (const unsigned char *)data, data_size);
+ memcpy((void *)(buff+(offs % nand->erasesize)), &data_size, 4);
+ memcpy((void *)(buff+(offs % nand->erasesize)+4), &data_crc, 4);
+ memcpy((void *)(buff+(offs % nand->erasesize)+8), data, data_size);
+
+ /* write data to flash */
+ wsize = nand->erasesize;
+ ret = nand_write_skip_bad(nand, opts.offset, &wsize, (u_char *)buff, 0);
+ if(ret) {
+ printf("%s: flash write error %d\n", __func__, ret);
+ }
+
+exit:
+ free(buff);
+ return ret;
+}
+
+int mtdparts_init_from_ptbl(void)
+{
+ char *mtdparts_str = malloc(CONFIG_MTD_PTBL_SIZE);
+
+ setenv("mtdparts", (char *)mtdparts_default);
+
+ /* load partition table from flash */
+ if(mtdparts_str){
+ if(mtdparts_ptbl_read(mtdparts_str) == 0) {
+ setenv("mtdparts", mtdparts_str);
+ }
+ free(mtdparts_str);
+ }
+
+ setenv("mtdids", (char *)mtdids_default);
+ setenv("partition", NULL);
+
+ return mtdparts_init();
+}
+
+int mtdparts_save_ptbl(int need_erase)
+{
+ if(mtdparts_ptbl_write((char *)mtdparts_default, need_erase)){
+ printf("%s: save partition table failed.\n", __func__);
+ return -1;
+ }
+ return 0;
+}
+
+int mtdparts_init_default(void)
+{
+ setenv("mtdids", (char *)mtdids_default);
+ setenv("mtdparts", (char *)mtdparts_default);
+ setenv("partition", NULL);
+
+ return mtdparts_init();
+}
+
+/* Check if the partition table is same with the table stored in flash */
+int mtdparts_ptbl_check(int *same)
+{
+ int ret;
+ char *buff;
+
+ if(!same) return -1;
+ *same = 0;
+
+ if(!mtdparts_default) {
+ return -1;
+ }
+
+ buff = malloc(CONFIG_MTD_PTBL_SIZE);
+ if(!buff) {
+ printf("%s: can't malloc memory.\n", __func__);
+ return -1;
+ }
+
+ ret = mtdparts_ptbl_read(buff);
+ if(!ret) {
+ printf("mtdparts_default: %s\n", mtdparts_default);
+ printf("mtdparts_in_flash: %s\n", buff);
+ if(strcmp(buff, mtdparts_default) == 0) {
+ *same = 1;
+ }
+ }
+
+ free(buff);
+ return ret;
+}
+
+/* Check if the part(bootloader & factorydata) of partition
+ table is same with the table stored in flash */
+int mtdparts_ptbl_check_factorydata(int *same)
+{
+ int ret;
+ char *buff;
+
+ if(!same) return -1;
+ *same = 0;
+
+ if(!mtdparts_default) {
+ return -1;
+ }
+
+ buff = malloc(CONFIG_MTD_PTBL_SIZE);
+ if(!buff) {
+ printf("%s: can't malloc memory.\n", __func__);
+ return -1;
+ }
+
+ ret = mtdparts_ptbl_read(buff);
+ if(!ret) {
+ int len = strstr(buff, "factorydata") - buff;
+ //printf("mtdparts_default: %s\n", mtdparts_default);
+ //printf("mtdparts_in_flash: %s\n", buff);
+ if(strncmp(buff, mtdparts_default, len) == 0) {
+ *same = 1;
+ }
+ }
+
+ free(buff);
+ return ret;
+}
+
/**
* Return pointer to the partition of a requested number from a requested
* device.
@@ -1870,6 +2199,23 @@ static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part
return NULL;
}
+int mtdparts_clear_all_dirty(struct mtd_device *dev)
+{
+ struct list_head *entry;
+ struct part_info *part;
+
+ if(!dev)
+ return -1;
+
+ printf("clear all %d mtdparts's dirty\n", dev->num_parts);
+ list_for_each(entry, &dev->parts) {
+ part = list_entry(entry, struct part_info, link);
+ if (part)
+ part->dirty = 0;
+ }
+ return 0;
+
+}
/***************************************************/
/* U-boot commands */
/***************************************************/
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index bae630dfb6..cdd1258b1b 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -11,7 +11,7 @@
* Added 16-bit nand support
* (C) 2004 Texas Instruments
*
- * Copyright 2010 Freescale Semiconductor
+ * Copyright 2010, 2012 Freescale Semiconductor
* The portions of this file whose copyright is held by Freescale and which
* are not considered a derived work of GPL v2-only code may be distributed
* and/or modified under the terms of the GNU General Public License as
@@ -27,6 +27,7 @@
#include <asm/byteorder.h>
#include <jffs2/jffs2.h>
#include <nand.h>
+#include <mtd/nand/rda_nand.h>
#if defined(CONFIG_CMD_MTDPARTS)
@@ -37,11 +38,17 @@ int find_dev_and_part(const char *id, struct mtd_device **dev,
u8 *part_num, struct part_info **part);
#endif
-static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
+static int nand_dump(nand_info_t *nand, uint64_t off, int only_oob, int repeat)
{
int i;
u_char *datbuf, *oobbuf, *p;
static loff_t last;
+ struct nand_chip *chip = nand->priv;
+ struct rda_nand_info *info = chip->priv;
+
+ /* just for dump nand first 16k bytes in nand driver V3,*/
+ /* no care to nand driver V1. */
+ info->dump_debug_flag = 1;
if (repeat)
off = last + nand->writesize;
@@ -54,7 +61,13 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
puts("No memory for page buffer\n");
return 1;
}
- off &= ~(nand->writesize - 1);
+
+ /* off is 64 bit*/
+ if(chip->page_shift == 0)
+ off = (loff_t)mtd_div_by_ws(off, nand) * nand->writesize;
+ else
+ off &= ~((loff_t)nand->writesize - 1);
+
loff_t addr = (loff_t) off;
struct mtd_oob_ops ops;
memset(&ops, 0, sizeof(ops));
@@ -65,12 +78,12 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
ops.mode = MTD_OOB_RAW;
i = nand->read_oob(nand, addr, &ops);
if (i < 0) {
- printf("Error (%d) reading page %08lx\n", i, off);
+ printf("Error (%d) reading page 0x%llx\n", i, off);
free(datbuf);
free(oobbuf);
return 1;
}
- printf("Page %08lx dump:\n", off);
+ printf("Page 0x%llx dump:\n", off);
i = nand->writesize >> 4;
p = datbuf;
@@ -91,6 +104,8 @@ static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]);
p += 8;
}
+
+ info->dump_debug_flag = 0;
free(datbuf);
free(oobbuf);
@@ -191,7 +206,7 @@ static int arg_off_size(int argc, char *const argv[], int *idx,
loff_t *off, loff_t *size)
{
int ret;
- loff_t maxsize;
+ loff_t maxsize = 0;
if (argc == 0) {
*off = 0;
@@ -277,6 +292,7 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
int ret;
uint32_t oob_buf[ENV_OFFSET_SIZE/sizeof(uint32_t)];
nand_info_t *nand = &nand_info[0];
+ struct nand_chip *chip = nand->priv;
char *cmd = argv[1];
if (CONFIG_SYS_MAX_NAND_DEVICE == 0 || !nand->name) {
@@ -319,9 +335,16 @@ int do_nand_env_oob(cmd_tbl_t *cmdtp, int argc, char *const argv[])
return 1;
}
- if ((addr & (nand->erasesize - 1)) != 0) {
- printf("Environment offset must be block-aligned\n");
- return 1;
+ if (chip->bbt_erase_shift == 0) {
+ if(mtd_mod_by_eb(addr, nand) != 0){
+ printf("Environment offset must be block-aligned\n");
+ return 1;
+ }
+ } else {
+ if ((addr & (nand->erasesize - 1)) != 0) {
+ printf("Environment offset must be block-aligned\n");
+ return 1;
+ }
}
ops.datbuf = NULL;
@@ -390,6 +413,47 @@ static void nand_print_and_set_info(int idx)
setenv("nand_erasesize", buf);
}
+static void nand_print_ID(void)
+{
+ nand_info_t *nand = &nand_info[0];
+ struct nand_chip *chip = nand->priv;
+
+ chip->read_nand_ID(nand);
+}
+
+static int raw_access(nand_info_t *nand, ulong addr, loff_t off, ulong count,
+ int read)
+{
+ int ret = 0;
+
+ while (count--) {
+ /* Raw access */
+ mtd_oob_ops_t ops = {
+ .datbuf = (u8 *)addr,
+ .oobbuf = ((u8 *)addr) + nand->writesize,
+ .len = nand->writesize,
+ .ooblen = nand->oobsize,
+ .mode = MTD_OOB_RAW
+ };
+
+ if (read)
+ ret = nand->read_oob(nand, off, &ops);
+ else
+ ret = nand->write_oob(nand, off, &ops);
+
+ if (ret) {
+ printf("%s: error at offset %llx, ret %d\n",
+ __func__, (long long)off, ret);
+ break;
+ }
+
+ addr += nand->writesize + nand->oobsize;
+ off += nand->writesize;
+ }
+
+ return ret;
+}
+
int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
int i, ret = 0;
@@ -429,6 +493,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
return 0;
}
+ if (strcmp(cmd, "id") == 0 || strcmp(cmd, "ID") == 0) {
+ nand_print_ID();
+ return 0;
+ }
+
if (strcmp(cmd, "device") == 0) {
if (argc < 3) {
putc('\n');
@@ -560,15 +629,75 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
if (argc < 3)
goto usage;
- off = (int)simple_strtoul(argv[2], NULL, 16);
+ off = simple_strtoull(argv[2], NULL, 16);
ret = nand_dump(nand, off, !strcmp(&cmd[4], ".oob"), repeat);
return ret == 0 ? 1 : 0;
}
+ if (strncmp(cmd, "speed", 5) == 0) {
+
+ unsigned long long start_clock, end_clock;
+ unsigned long duration, nand_speed;
+ u_char *datbuf;
+ nand_erase_options_t opts;
+ uint32_t test_data_size;
+
+ if (argc < 5){
+ datbuf = (u_char *)(0x80000000);
+ off = (ulong)(0x00100000);
+ test_data_size = (ulong)(0x00A00000);
+ } else {
+ datbuf = (u_char *)simple_strtoul(argv[2], NULL, 16);
+ off = (ulong)simple_strtoul(argv[3], NULL, 16);
+ test_data_size = (ulong)simple_strtoul(argv[4], NULL, 16);
+ }
+
+ start_clock = get_ticks();
+ ret = nand_read_skip_bad(nand, off, &test_data_size, datbuf);
+ end_clock = get_ticks();
+ duration = (unsigned long)(end_clock - start_clock);
+ nand_speed = (unsigned long)(test_data_size / (duration * 1000 / get_tbclk()) * 1000 / 1024);
+ if (!ret)
+ printf("\nNand Read speed = %ld Kbyte/s\n\n", nand_speed);
+ else {
+ printf("\nRead data from Nand failed\n");
+ return 1;
+ }
+
+ /* set nand erasing parameters */
+ memset(&opts, 0, sizeof(opts));
+ opts.offset = off;
+ opts.length = test_data_size;
+ opts.jffs2 = 0;
+ opts.quiet = 0;
+ opts.spread = 0;
+
+ /* erase flash */
+ start_clock = get_ticks();
+ ret = nand_erase_opts(nand, &opts);
+ if(ret != 0) {
+ printf("erase nand flash error, returned value: ret = %d\n", ret);
+ return 1;
+ }
+ ret = nand_write_skip_bad(nand, off, &test_data_size, datbuf, 0);
+ end_clock = get_ticks();
+ duration = (unsigned long)(end_clock - start_clock);
+ nand_speed = (unsigned long)(test_data_size / (duration * 1000 / get_tbclk()) * 1000 / 1024);
+ if (!ret)
+ printf("\nNand Write speed = %ld Kbyte/s\n", nand_speed);
+ else {
+ printf("\nWrite data to Nand failed\n");
+ return 1;
+ }
+ return ret == 0 ? 0 : 1;
+ }
+
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
size_t rwsize;
+ ulong pagecount = 1;
int read;
+ int raw;
if (argc < 4)
goto usage;
@@ -577,13 +706,36 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
printf("\nNAND %s: ", read ? "read" : "write");
- if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size) != 0)
- return 1;
nand = &nand_info[dev];
- rwsize = size;
s = strchr(cmd, '.');
+
+ if (!strcmp(s, ".raw")) {
+ raw = 1;
+
+ if (arg_off(argv[3], &dev, &off, &size))
+ return 1;
+
+ if (argc > 4 && !str2long(argv[4], &pagecount)) {
+ printf("'%s' is not a number\n", argv[4]);
+ return 1;
+ }
+
+ if (pagecount * nand->writesize > size) {
+ puts("Size exceeds partition or device limit\n");
+ return -1;
+ }
+
+ rwsize = pagecount * (nand->writesize + nand->oobsize);
+ } else {
+ if (arg_off_size(argc - 3, argv + 3, &dev,
+ &off, &size) != 0)
+ return 1;
+
+ rwsize = size;
+ }
+
if (!s || !strcmp(s, ".jffs2") ||
!strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
@@ -609,7 +761,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
return 1;
}
ret = nand_write_skip_bad(nand, off, &rwsize,
- (u_char *)addr, WITH_YAFFS_OOB);
+ (u_char *)addr,
+ WITH_YAFFS_OOB); // WITH_INLINE_OOB); ???
#endif
} else if (!strcmp(s, ".oob")) {
/* out-of-band data */
@@ -623,22 +776,8 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
ret = nand->read_oob(nand, off, &ops);
else
ret = nand->write_oob(nand, off, &ops);
- } else if (!strcmp(s, ".raw")) {
- /* Raw access */
- mtd_oob_ops_t ops = {
- .datbuf = (u8 *)addr,
- .oobbuf = ((u8 *)addr) + nand->writesize,
- .len = nand->writesize,
- .ooblen = nand->oobsize,
- .mode = MTD_OOB_RAW
- };
-
- rwsize = nand->writesize + nand->oobsize;
-
- if (read)
- ret = nand->read_oob(nand, off, &ops);
- else
- ret = nand->write_oob(nand, off, &ops);
+ } else if (raw) {
+ ret = raw_access(nand, addr, off, pagecount, read);
} else {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
@@ -726,15 +865,16 @@ usage:
U_BOOT_CMD(
nand, CONFIG_SYS_MAXARGS, 1, do_nand,
"NAND sub-system",
+ "id or ID - print nand ID \n"
"info - show available NAND devices\n"
"nand device [dev] - show or set current device\n"
"nand read - addr off|partition size\n"
"nand write - addr off|partition size\n"
" read/write 'size' bytes starting at offset 'off'\n"
" to/from memory address 'addr', skipping bad blocks.\n"
- "nand read.raw - addr off|partition\n"
- "nand write.raw - addr off|partition\n"
- " Use read.raw/write.raw to avoid ECC and access the page as-is.\n"
+ "nand read.raw - addr off|partition [count]\n"
+ "nand write.raw - addr off|partition [count]\n"
+ " Use read.raw/write.raw to avoid ECC and access the flash as-is.\n"
#ifdef CONFIG_CMD_NAND_TRIMFFS
"nand write.trimffs - addr off|partition size\n"
" write 'size' bytes starting at offset 'off' from memory address\n"
@@ -754,6 +894,7 @@ U_BOOT_CMD(
"nand erase.chip [clean] - erase entire chip'\n"
"nand bad - show bad blocks\n"
"nand dump[.oob] off - dump page\n"
+ "nand speed [-addr -off -test data length]- show read speed and write speed of NAND\n"
"nand scrub [-y] off size | scrub.part partition | scrub.chip\n"
" really clean NAND erasing bad blocks (UNSAFE)\n"
"nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
@@ -936,3 +1077,202 @@ U_BOOT_CMD(nboot, 4, 1, do_nandboot,
"boot from NAND device",
"[partition] | [[[loadAddr] dev] offset]"
);
+
+static char test_buf[4096 + 224];
+static char temp_buf[4096 + 224];
+
+int erase_block(nand_info_t *nand, loff_t off)
+{
+ int ret;
+ nand_erase_options_t opts;
+ struct nand_chip *chip = nand->priv;
+
+ if (chip->phys_erase_shift == 0) {
+ if(mtd_mod_by_eb(off, nand) != 0){
+ printf("not aligned erase size\n");
+ return 1;
+ }
+ } else {
+ if ((off & (nand->erasesize - 1)) != 0 ) {
+ printf("not aligned erase size\n");
+ return 1;
+ }
+ }
+
+ memset(&opts, 0, sizeof(opts));
+ opts.offset = off;
+ opts.length = nand->erasesize;
+ opts.jffs2 = 0;
+ opts.quiet = 0;
+ opts.spread = 0;
+
+ ret = nand_erase_opts(nand, &opts);
+ printf("%s\n", ret ? "ERROR" : "OK");
+
+ return ret == 0 ? 0 : 1;
+}
+
+static void dump_flash_buf(nand_info_t *nand, char *new)
+{
+ int i;
+
+ printf("flash data:\n");
+ for (i = 0; i < nand->writesize; i+=8)
+ printf("%04x: %2x %2x %2x %2x %2x %2x %2x %2x\n",i, new[i], new[i+1], new[i+2],
+ new[i+3], new[i+4], new[i+5], new[i+6], new[i+7]);
+
+ printf("flash oob:\n");
+ for (; i < (nand->writesize + nand->oobsize); i+=8)
+ printf("%04x: %2x %2x %2x %2x %2x %2x %2x %2x\n",i, new[i], new[i+1], new[i+2],
+ new[i+3], new[i+4], new[i+5], new[i+6], new[i+7]);
+}
+
+/*
+ * use lcd backlight as trigger of digital analyzer
+ */
+#include <asm/arch/reg_nand.h>
+#include <asm/io.h>
+static void trigger_gpio(int high)
+{
+#define RDA_GPIO_DIR (RDA_GPIO_A_BASE + 0x04)
+#define RDA_GPIO_VAL (RDA_GPIO_A_BASE + 0x0c)
+#define RDA_GPIO_SET (RDA_GPIO_A_BASE + 0x10)
+#define RDA_GPIO_CLR (RDA_GPIO_A_BASE + 0x14)
+
+ __raw_writel(0xffffffff, RDA_GPIO_DIR);
+ if (high) {
+ __raw_writel(0x0f, RDA_GPIO_SET);
+ } else {
+ __raw_writel(0x0f, RDA_GPIO_CLR);
+ }
+}
+int do_nandstress(cmd_tbl_t * cmdtp, int flag, int argc, char *const argv[])
+{
+ int i;
+ int dev = nand_curr_device;
+ int ret;
+ nand_info_t *nand;
+ unsigned long long count_h, count_l;
+ loff_t off = 0;
+ char * s;
+ int need_erase = 1;
+
+ if (argc < 2)
+ goto usage;
+
+ off = simple_strtoul(argv[1], NULL, 16);
+ printf("nand stress test offset %llx\n", off);
+ s = argv[2];
+
+ /*
+ DANGROUS!!!!!!!
+ if you dont erase the block and write/read
+ the page, the page maybe damaged for ever.
+ this test used as test the hardware ecc functions:
+ write the page repeatedly until the page error, and test if
+ the handware ecc can detect and correct them;
+ */
+ if (!strcmp(s, "noerase")) {
+ const char *noerase_warning =
+ "!!!!!DANGROUS test!!!!!!\n"
+ "This may damage the flash page for ever ....y/N\n";
+ puts(noerase_warning);
+ if (getc() == 'y') {
+ puts("y");
+ if (getc() == '\r') {
+ printf("\nwill don't erase the block anyway...\n");
+ need_erase = 0;
+ }
+ }
+ }
+
+ printf("nand stress test erase/write/read ....\n");
+
+ count_h = 0;
+ count_l = 0;
+ nand = &nand_info[dev];
+
+ for (i = 0; i < (nand->writesize + nand->oobsize); i++) {
+ test_buf[i] = i+255;
+ }
+
+ trigger_gpio(1);
+ while (1) {
+ int error_count;
+ /* Raw access */
+ mtd_oob_ops_t ops_w= {
+ .datbuf = (u8 *)test_buf,
+ .oobbuf = ((u8 *)test_buf) + nand->writesize,
+ .len = nand->writesize,
+ .ooblen = nand->oobsize,
+ .mode = MTD_OOB_RAW
+ };
+ mtd_oob_ops_t ops_r= {
+ .datbuf = (u8 *)temp_buf,
+ .oobbuf = ((u8 *)temp_buf) + nand->writesize,
+ .len = nand->writesize,
+ .ooblen = nand->oobsize,
+ .mode = MTD_OOB_RAW
+ };
+
+ if (need_erase) {
+ if (erase_block(nand, off)){
+ trigger_gpio(0);
+ printf("oops, erase error\n");
+ goto error;
+ }
+ }
+ ret = nand->write_oob(nand, off, &ops_w);
+ if (ret) {
+ trigger_gpio(0);
+ printf("%s: error at offset %llx, ret %d\n",
+ __func__, (long long)off, ret);
+ goto error;
+ }
+ ret = nand->read_oob(nand, off, &ops_r);
+ if (ret) {
+ printf("%s: error at offset %llx, ret %d\n",
+ __func__, (long long)off, ret);
+ goto error;
+ }
+
+ error_count = 0;
+ //for (i = 0; i < (nand->writesize + nand->oobsize); i++) {
+ for (i = 0; i < (nand->writesize); i++) {
+ if(test_buf[i] != temp_buf[i]) {
+ trigger_gpio(0);
+ printf("oops, read/write is error at %x, source %02x, flash %02x\n",
+ i, test_buf[i], temp_buf[i]);
+ printf("nand interrupt stauts %x\n",__raw_readl(NANDFC_REG_INT_STAT));
+ printf("nand busy flag %x\n",__raw_readl(NANDFC_REG_BUSY_FLAG));
+ error_count ++;
+ }
+ }
+
+ if (error_count) {
+ printf("oops, error num %d, \n",error_count);
+ dump_flash_buf(nand, temp_buf);
+ printf("read nand fifo \n");
+ goto error;
+ }
+ count_l++;
+ if (count_l == 0) {
+ count_h++;
+ }
+ printf("###################NAND testing... the loop is:high %lld, low %lld\n"
+ , count_h, count_l);
+ };
+
+ return 1;
+usage:
+ return CMD_RET_USAGE;
+error:
+ printf("NAND stress test end, the loop is:high %lld, low %lld\n", count_h, count_l);
+ return 1;
+}
+
+U_BOOT_CMD(nandstress, 3, 1, do_nandstress,
+ "nand stress test for one page read/write: nandstress off",
+ "[ off ]\n"
+ " - test nand from page offset 'off'"
+);
diff --git a/common/cmd_net.c b/common/cmd_net.c
index 65f32bceef..a9ade8b927 100644
--- a/common/cmd_net.c
+++ b/common/cmd_net.c
@@ -153,12 +153,16 @@ static void netboot_update_env (void)
ip_to_string (NetOurIP, tmp);
setenv ("ipaddr", tmp);
}
-
+#if !defined(CONFIG_BOOTP_SERVERIP)
+ /*
+ * Only attempt to change serverip if net/bootp.c:BootpCopyNetParams()
+ * could have set it
+ */
if (NetServerIP) {
ip_to_string (NetServerIP, tmp);
setenv ("serverip", tmp);
}
-
+#endif
if (NetOurDNSIP) {
ip_to_string (NetOurDNSIP, tmp);
setenv ("dnsip", tmp);
@@ -424,3 +428,34 @@ U_BOOT_CMD(
);
#endif /* CONFIG_CMD_DNS */
+
+#if defined(CONFIG_CMD_LINK_LOCAL)
+static int do_link_local(cmd_tbl_t *cmdtp, int flag, int argc,
+ char * const argv[])
+{
+ char tmp[22];
+
+ if (NetLoop(LINKLOCAL) < 0)
+ return 1;
+
+ NetOurGatewayIP = 0;
+ ip_to_string(NetOurGatewayIP, tmp);
+ setenv("gatewayip", tmp);
+
+ ip_to_string(NetOurSubnetMask, tmp);
+ setenv("netmask", tmp);
+
+ ip_to_string(NetOurIP, tmp);
+ setenv("ipaddr", tmp);
+ setenv("llipaddr", tmp); /* store this for next time */
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ linklocal, 1, 1, do_link_local,
+ "acquire a network IP address using the link-local protocol",
+ ""
+);
+
+#endif /* CONFIG_CMD_LINK_LOCAL */
diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c
index b1494dcb0c..271200266c 100644
--- a/common/cmd_nvedit.c
+++ b/common/cmd_nvedit.c
@@ -66,9 +66,10 @@ DECLARE_GLOBAL_DATA_PTR;
!defined(CONFIG_ENV_IS_IN_NVRAM) && \
!defined(CONFIG_ENV_IS_IN_ONENAND) && \
!defined(CONFIG_ENV_IS_IN_SPI_FLASH) && \
+ !defined(CONFIG_ENV_IS_IN_REMOTE) && \
!defined(CONFIG_ENV_IS_NOWHERE)
# error Define one of CONFIG_ENV_IS_IN_{EEPROM|FLASH|DATAFLASH|ONENAND|\
-SPI_FLASH|MG_DISK|NVRAM|MMC|FAT} or CONFIG_ENV_IS_NOWHERE
+SPI_FLASH|MG_DISK|NVRAM|MMC|FAT|REMOTE} or CONFIG_ENV_IS_NOWHERE
#endif
#define XMK_STR(x) #x
@@ -203,7 +204,6 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,
*/
int _do_env_set(int flag, int argc, char * const argv[])
{
- bd_t *bd = gd->bd;
int i, len;
int console = -1;
char *name, *value, *s;
@@ -342,21 +342,7 @@ int _do_env_set(int flag, int argc, char * const argv[])
* Some variables should be updated when the corresponding
* entry in the environment is changed
*/
- if (strcmp(name, "ipaddr") == 0) {
- char *s = argv[2]; /* always use only one arg */
- char *e;
- unsigned long addr;
- bd->bi_ip_addr = 0;
- for (addr = 0, i = 0; i < 4; ++i) {
- ulong val = s ? simple_strtoul(s, &e, 10) : 0;
- addr <<= 8;
- addr |= val & 0xFF;
- if (s)
- s = *e ? e + 1 : e;
- }
- bd->bi_ip_addr = htonl(addr);
- return 0;
- } else if (strcmp(argv[1], "loadaddr") == 0) {
+ if (strcmp(argv[1], "loadaddr") == 0) {
load_addr = simple_strtoul(argv[2], NULL, 16);
return 0;
}
diff --git a/common/cmd_onenand.c b/common/cmd_onenand.c
index 0f2e208717..a0d25e5521 100644
--- a/common/cmd_onenand.c
+++ b/common/cmd_onenand.c
@@ -13,7 +13,7 @@
#include <command.h>
#include <malloc.h>
-#include <linux/mtd/compat.h>
+#include <linux/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
diff --git a/common/cmd_sata.c b/common/cmd_sata.c
index 7b1703fe41..3f98235a38 100644
--- a/common/cmd_sata.c
+++ b/common/cmd_sata.c
@@ -48,9 +48,12 @@ int __sata_initialize(void)
sata_dev_desc[i].block_write = sata_write;
rc = init_sata(i);
- rc = scan_sata(i);
- if ((sata_dev_desc[i].lba > 0) && (sata_dev_desc[i].blksz > 0))
- init_part(&sata_dev_desc[i]);
+ if (!rc) {
+ rc = scan_sata(i);
+ if (!rc && (sata_dev_desc[i].lba > 0) &&
+ (sata_dev_desc[i].blksz > 0))
+ init_part(&sata_dev_desc[i]);
+ }
}
sata_curr_device = 0;
return rc;
diff --git a/common/cmd_test.c b/common/cmd_test.c
index fcb5ef2f71..cd9a1a2836 100644
--- a/common/cmd_test.c
+++ b/common/cmd_test.c
@@ -171,3 +171,220 @@ U_BOOT_CMD(
"do nothing, successfully",
NULL
);
+
+#ifdef CONFIG_VPU_TEST
+#include <asm/arch/hw_test.h>
+int do_vpu_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+ if(argc > 1) {
+ times = simple_strtoul(argv[1], NULL, 10);
+ }
+ vpu_sta_test(times);
+ return 0;
+}
+U_BOOT_CMD(
+ vpu_test, CONFIG_SYS_MAXARGS, 1, do_vpu_test,
+ "vpu test",
+ NULL
+);
+
+#ifdef CONFIG_VPU_MD5_TEST
+int do_vpu_md5_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+ if(argc > 1) {
+ times = simple_strtoul(argv[1], NULL, 10);
+ }
+ vpu_md5_test(times);
+ return 0;
+}
+U_BOOT_CMD(
+ vpu_md5_test, CONFIG_SYS_MAXARGS, 1, do_vpu_md5_test,
+ "vpu md5 test",
+ NULL
+);
+#endif //CONFIG_VPU_MD5_TEST
+#endif //CONFIG_VPU_TEST
+
+#ifdef CONFIG_CPU_TEST
+#include <asm/arch/hw_test.h>
+int do_cpu_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+ if(argc > 1) {
+ times = simple_strtoul(argv[1], NULL, 10);
+ }
+ cpu_pll_test(times);
+ return 0;
+}
+U_BOOT_CMD(
+ cpu_test, CONFIG_SYS_MAXARGS, 1, do_cpu_test,
+ "cpu test",
+ NULL
+);
+#endif //CONFIG_VPU_TEST
+
+#ifdef CONFIG_DDR_TEST
+#include <asm/arch/hw_test.h>
+int do_ddr_mem_copy_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+ unsigned int src_addr = 0x80000000,des_addr = 0x83000000,n = 0x10;
+
+ if(argc > 1) {
+ times = simple_strtoul(argv[1], NULL, 10);
+ }
+ if(argc > 2) {
+ src_addr = simple_strtoul(argv[2],NULL,16);
+ }
+ if(argc > 3) {
+ des_addr = simple_strtoul(argv[3],NULL,16);
+ }
+ if(argc > 4) {
+ n = simple_strtoul(argv[4],NULL,16);
+ }
+ ddr_mem_copy_test(times,src_addr,des_addr,n);
+ return 0;
+}
+
+U_BOOT_CMD(
+ ddr_mem_cp, 5, 1, do_ddr_mem_copy_test,
+ "ddr memory copy test",
+ NULL
+);
+#endif //CONFIG_DDR_TEST
+
+#ifdef CONFIG_TIMER_TEST
+#include <asm/arch/hw_test.h>
+int do_timer_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+ unsigned int timer_id = 0;
+
+ if(argc > 1) {
+ timer_id = simple_strtoul(argv[1], NULL, 10);
+ }
+ if(argc > 2) {
+ times = simple_strtoul(argv[2],NULL,16);
+ }
+ tim_test(timer_id,times);
+ return 0;
+}
+
+U_BOOT_CMD(
+ timer_test, 5, 1, do_timer_test,
+ "timer_test timer_id(0~2) times",
+ NULL
+);
+#endif /* CONFIG_TIMER_TEST */
+
+#ifdef CONFIG_UART_TEST
+#include <asm/arch/hw_test.h>
+int do_uart_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+ unsigned int uart_id = 2;// uart3 as default test port
+
+ if(argc > 1) {
+ uart_id = simple_strtoul(argv[1], NULL, 10);
+ }
+ if(argc > 2) {
+ times = simple_strtoul(argv[2],NULL,16);
+ }
+ uart_test(uart_id,times);
+ return 0;
+}
+
+U_BOOT_CMD(
+ uart_test, 5, 1, do_uart_test,
+ "uart_test uart_id(0~2) times",
+ NULL
+);
+#endif /* CONFIG_UART_TEST */
+
+#ifdef CONFIG_GIC_TEST
+#include <asm/arch/hw_test.h>
+int do_gic_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+
+ if(argc > 1) {
+ times = simple_strtoul(argv[1], NULL, 10);
+ }
+ gic_test(times);
+ return 0;
+}
+
+U_BOOT_CMD(
+ gic_test, 5, 1, do_gic_test,
+ "gic_test times",
+ NULL
+);
+#endif /* CONFIG_GIC_TEST */
+
+#ifdef CONFIG_CACHE_TEST
+#include <asm/arch/hw_test.h>
+int do_cache_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+
+ if(argc > 1) {
+ times = simple_strtoul(argv[1], NULL, 10);
+ }
+ cpu_cache_test(times);
+ return 0;
+}
+
+U_BOOT_CMD(
+ cache_test, 5, 1, do_cache_test,
+ "cpu L1/L2 D-cache I-cache test",
+ NULL
+);
+#endif /* CONFIG_CACHE_TEST */
+
+#ifdef CONFIG_MIPI_LOOP_TEST
+#include<asm/arch/hw_test.h>
+int do_mipi_loop_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+
+ if (argc > 1)
+ times = simple_strtoull(argv[1], NULL, 10);
+ if (times < 1) {
+ printf("Invalid parameter\n");
+ return 1;
+ }
+ test_dsi_csi_loop(times);
+
+ return 0;
+}
+
+U_BOOT_CMD(
+ mipi_loop, 5, 5, do_mipi_loop_test,
+ "mipi loop test",
+ NULL
+);
+#endif /* CONFIG_MIPI_LOOP_TEST */
+
+#ifdef CONFIG_I2C_TEST
+#include<asm/arch/hw_test.h>
+int do_i2c_test(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int times = 1;
+ int id = 2; /* I2C id number:0,1,2,I2C 2 is default device */
+
+ if(argc > 1)
+ times = simple_strtoull(argv[1], NULL, 10);
+ if(argc > 2)
+ id = simple_strtoul(argv[2],NULL,10);
+ test_i2c(id,times);
+ return 0;
+}
+
+U_BOOT_CMD(
+ i2c_test, 5, 5, do_i2c_test,
+ "i2c test",
+ NULL
+);
+#endif /* CONFIG_I2C_TET */
diff --git a/common/cmd_ubi.c b/common/cmd_ubi.c
index 35b1d31f9c..aff6d69de5 100644
--- a/common/cmd_ubi.c
+++ b/common/cmd_ubi.c
@@ -149,7 +149,10 @@ static int verify_mkvol_req(const struct ubi_device *ubi,
if (req->alignment > ubi->leb_size)
goto bad;
- n = req->alignment % ubi->min_io_size;
+ if (is_power_of_2(ubi->min_io_size))
+ n = req->alignment & (ubi->min_io_size -1);
+ else
+ n = req->alignment % ubi->min_io_size;
if (req->alignment != 1 && n)
goto bad;
@@ -164,7 +167,7 @@ bad:
return err;
}
-static int ubi_create_vol(char *volume, int size, int dynamic)
+static int ubi_create_vol(const char *volume, int64_t size, int dynamic)
{
struct ubi_mkvol_req req;
int err;
@@ -188,13 +191,13 @@ static int ubi_create_vol(char *volume, int size, int dynamic)
printf("verify_mkvol_req failed %d\n", err);
return err;
}
- printf("Creating %s volume %s of size %d\n",
+ printf("Creating %s volume %s of size 0x%llx\n",
dynamic ? "dynamic" : "static", volume, size);
/* Call real ubi create volume */
return ubi_create_volume(ubi, &req);
}
-static struct ubi_volume *ubi_find_volume(char *volume)
+static struct ubi_volume *ubi_find_volume(const char *volume)
{
struct ubi_volume *vol = NULL;
int i;
@@ -209,7 +212,7 @@ static struct ubi_volume *ubi_find_volume(char *volume)
return NULL;
}
-static int ubi_remove_vol(char *volume)
+static int ubi_remove_vol(const char *volume)
{
int err, reserved_pebs, i;
struct ubi_volume *vol;
@@ -263,7 +266,7 @@ out_err:
return err;
}
-static int ubi_volume_write(char *volume, void *buf, size_t size)
+static int ubi_volume_write(const char *volume, void *buf, size_t size)
{
int err = 1;
int rsvd_bytes = 0;
@@ -313,13 +316,12 @@ static int ubi_volume_write(char *volume, void *buf, size_t size)
return 0;
}
-static int ubi_volume_read(char *volume, char *buf, size_t size)
+static int ubi_volume_read(const char *volume, loff_t offp, char *buf, size_t size)
{
int err, lnum, off, len, tbuf_size;
void *tbuf;
unsigned long long tmp;
struct ubi_volume *vol;
- loff_t offp = 0;
vol = ubi_find_volume(volume);
if (vol == NULL)
@@ -349,8 +351,12 @@ static int ubi_volume_read(char *volume, char *buf, size_t size)
size = vol->used_bytes - offp;
tbuf_size = vol->usable_leb_size;
- if (size < tbuf_size)
- tbuf_size = ALIGN(size, ubi->min_io_size);
+ if (size < tbuf_size) {
+ if (is_power_of_2(ubi->min_io_size))
+ tbuf_size = ALIGN(size, ubi->min_io_size);
+ else
+ tbuf_size = roundup(size, ubi->min_io_size);
+ }
tbuf = malloc(tbuf_size);
if (!tbuf) {
printf("NO MEM\n");
@@ -390,7 +396,7 @@ static int ubi_volume_read(char *volume, char *buf, size_t size)
return err;
}
-static int ubi_dev_scan(struct mtd_info *info, char *ubidev,
+static int ubi_dev_scan(struct mtd_info *info, const char *ubidev,
const char *vid_header_offset)
{
struct mtd_device *dev;
@@ -431,6 +437,272 @@ static int ubi_dev_scan(struct mtd_info *info, char *ubidev,
return 0;
}
+#ifdef MTDPARTS_UBI_DEF
+int ubi_part_scan(const char *part_name)
+{
+ struct mtd_info *info;
+ struct mtd_device *dev;
+ struct part_info *part;
+ nand_erase_options_t opts;
+ char mtd_dev[20];
+ u8 pnum;
+ int ret = 0;
+
+ if(ubi_initialized){
+ ubi = ubi_devices[0];
+ return 0;
+ }
+ /*
+ * Search the mtd device number where this partition
+ * is located
+ */
+ if (find_dev_and_part(part_name, &dev, &pnum, &part)) {
+ printf("Partition %s not found!\n", part_name);
+ return -1;
+ }
+ sprintf(mtd_dev, "%s%d", MTD_DEV_TYPE(dev->id->type), dev->id->num);
+ info = get_mtd_device_nm(mtd_dev);
+ if (IS_ERR(info)) {
+ printf("Partition %s not found on device %s!\n", part_name, mtd_dev);
+ return 1;
+ }
+ printf("found part '%s' offset: 0x%llx length: 0x%llx id: %d\n",
+ part->name, part->offset, part->size, dev->id->num);
+
+ ret = ubi_dev_scan(info, part_name, NULL);
+ /* if fail, erase the part, try again */
+ if(ret) {
+ memset(&opts, 0, sizeof(opts));
+ opts.offset = (loff_t) part->offset;
+ opts.length = (loff_t) part->size;
+ opts.jffs2 = 0;
+ opts.quiet = 0;
+
+ ret = nand_erase_opts(info, &opts);
+ if(ret)
+ return ret;
+ ret = ubi_dev_scan(info, part_name, NULL);
+ if(ret)
+ return ret;
+ }
+
+ ubi = ubi_devices[0];
+ return ret;
+}
+
+struct ubi_vol_info {
+ char name[20];
+ size_t size;
+};
+static int ubi_parse_ubi_str(const char *ubi_default_str,
+ struct ubi_vol_info **ubivol_info, int *ubivol_count)
+{
+ char *def_str = malloc(strlen(ubi_default_str)+1);
+ char *p = def_str;
+ char *q;
+ int i = 0;
+ struct ubi_vol_info *info;
+
+ if(!def_str)
+ return -1;
+ strcpy(def_str, ubi_default_str);
+
+ while(1) {
+ q = strstr(p, "M(");
+ if(!q) {
+ q = strstr(p, "-(");
+ if(!q)
+ break;
+ }
+ i++;
+ p = q + 2;
+ }
+
+ info = (struct ubi_vol_info *)malloc(sizeof(struct ubi_vol_info) * i);
+ *ubivol_info = info;
+ *ubivol_count = i;
+
+ p = def_str;
+ i = 0;
+ while(1) {
+ /* size */
+ q = strstr(p, "M(");
+ if(q) {
+ *q = '\0';
+ info[i].size = simple_strtoul(p, NULL, 10) * 1024 * 1024;
+ p = q + 2;
+ } else {
+ q = strstr(p, "-(");
+ if(q) {
+ info[i].size = 0;
+ p = q + 2;
+ } else {
+ break;
+ }
+ }
+
+ /* name */
+ q = strstr(p, ")");
+ if(q)
+ *q = '\0';
+ strcpy(info[i].name, p);
+ if(!q)
+ break;
+ p = q + 1;
+ if(*p == ',')
+ p++;
+
+ i++;
+ }
+ free(def_str);
+ return 0;
+}
+
+int ubi_check_default_vols(const char *ubi_default_str)
+{
+ int ret = 0;
+ struct ubi_vol_info *info = NULL;
+ int count = 0, i;
+ int checked = 1;
+ struct ubi_volume *vol;
+
+ if(ubi_parse_ubi_str(ubi_default_str, &info, &count))
+ return -1;
+ if(count <= 0 || !info)
+ return -1;
+
+ for(i = 0; i < count; i++) {
+ vol = ubi_find_volume(info[i].name);
+ if(vol == NULL) {
+ checked = 0;
+ break;
+ }
+ }
+
+ /* format */
+ if(!checked) {
+ /* remove all volumes */
+ for(i = 0; i < (ubi->vtbl_slots + 1); i++) {
+ if(!ubi->volumes[i])
+ continue;
+ ret = ubi_remove_vol(ubi->volumes[i]->name);
+ if(ret) break;
+ }
+ /* create new volumes */
+ for(i = 0; i < count; i++) {
+ /* Use maximum available size */
+ if (!info[i].size) {
+ info[i].size = ubi->avail_pebs * ubi->leb_size;
+ printf("No size specified -> Using max size (%u)\n", info[i].size);
+ }
+ ret = ubi_create_vol(info[i].name, info[i].size, 1);
+ if(ret) break;
+ }
+ }
+
+ free(info);
+ return ret;
+}
+
+int ubi_erase_vol(const char *vol_name)
+{
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(vol_name);
+ if(vol == NULL) { /* not need to erase */
+ return 0;
+ }
+ return ubi_volume_write(vol_name, "", 0);
+}
+
+int ubi_read_vol(const char *vol_name, loff_t offp, void *buf, size_t size)
+{
+ return ubi_volume_read(vol_name, offp, buf, size);
+}
+
+int ubi_prepare_write_vol(const char *volume, size_t size)
+{
+ int err = 1;
+ int rsvd_bytes = 0;
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(volume);
+ if (vol == NULL)
+ return -ENODEV;
+
+ rsvd_bytes = vol->reserved_pebs * (ubi->leb_size - vol->data_pad);
+ if (size < 0 || size > rsvd_bytes) {
+ printf("size > volume size! Aborting!\n");
+ return -EINVAL;
+ }
+
+ err = ubi_start_update(ubi, vol, size);
+ if (err < 0) {
+ printf("Cannot start volume update\n");
+ return err;
+ }
+
+ printf("prepare to write %d bytes to volume %s\n", size, volume);
+ return 0;
+}
+
+int ubi_do_write_vol(const char *volume, void *buf, size_t size)
+{
+ int err = 1;
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(volume);
+ if (vol == NULL)
+ return -ENODEV;
+
+ err = ubi_more_update_data(ubi, vol, buf, size);
+ if (err < 0) {
+ printf("Couldnt or partially wrote data\n");
+ return err;
+ }
+
+ printf("%d bytes written to volume %s\n", size, volume);
+ return 0;
+}
+
+int ubi_finish_write_vol(const char *volume)
+{
+ int err = 1;
+ struct ubi_volume *vol;
+
+ vol = ubi_find_volume(volume);
+ if (vol == NULL)
+ return -ENODEV;
+
+ err = ubi_check_volume(ubi, vol->vol_id);
+ if (err < 0)
+ return err;
+
+ if (err) {
+ ubi_warn("volume %d on UBI device %d is corrupted",
+ vol->vol_id, ubi->ubi_num);
+ vol->corrupted = 1;
+ }
+
+ vol->checked = 1;
+ ubi_gluebi_updated(vol);
+
+ printf("finish to write volume %s\n", volume);
+ return 0;
+}
+
+int ubi_update_vol(const char *vol_name, void *buf, size_t size)
+{
+ return ubi_volume_write(vol_name, buf, size);
+}
+
+size_t ubi_sizeof_vol(const char *vol_name)
+{
+ struct ubi_volume *vol = ubi_find_volume(vol_name);
+ return vol->used_bytes;
+}
+#endif /* MTDPARTS_UBI_DEF */
+
static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
size_t size = 0;
@@ -598,7 +870,7 @@ static int do_ubi(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
}
if (argc == 3)
- return ubi_volume_read(argv[3], (char *)addr, size);
+ return ubi_volume_read(argv[3], 0, (char *)addr, size);
}
printf("Please see usage\n");
diff --git a/common/cmd_usb.c b/common/cmd_usb.c
index 9eba2713ea..a8e3ae5b67 100644
--- a/common/cmd_usb.c
+++ b/common/cmd_usb.c
@@ -150,7 +150,8 @@ void usb_display_class_sub(unsigned char dclass, unsigned char subclass,
void usb_display_string(struct usb_device *dev, int index)
{
- char buffer[256];
+ ALLOC_CACHE_ALIGN_BUFFER(char, buffer, 256);
+
if (index != 0) {
if (usb_string(dev, index, &buffer[0], 256) > 0)
printf("String: \"%s\"", buffer);
diff --git a/common/cmd_version.c b/common/cmd_version.c
index e4b2ac1efc..bdb476df94 100644
--- a/common/cmd_version.c
+++ b/common/cmd_version.c
@@ -25,6 +25,8 @@
#include <command.h>
#include <version.h>
#include <linux/compiler.h>
+#include <timestamp.h>
+#include "generated/version_autogenerated.h"
const char __weak version_string[] = U_BOOT_VERSION_STRING;
diff --git a/common/cmd_yaffs2.c b/common/cmd_yaffs2.c
index 0e22d90e7a..d43a9d444c 100644
--- a/common/cmd_yaffs2.c
+++ b/common/cmd_yaffs2.c
@@ -1,18 +1,37 @@
+/* Yaffs commands.
+ * Modified by Charles Manning by adding ydevconfig command.
+ *
+ * Use ydevconfig to configure a mountpoint before use.
+ * For example:
+ * # Configure mountpt xxx using nand device 0 using blocks 100-500
+ * ydevconfig xxx 0 100 500
+ * # Mount it
+ * ymount xxx
+ * # yls, yrdm etc
+ * yls -l xxx
+ * yrdm xxx/boot-image 82000000
+ * ...
+ */
+
#include <common.h>
#include <config.h>
#include <command.h>
-#ifdef YAFFS2_DEBUG
-#define PRINTF(fmt,args...) printf (fmt ,##args)
+#ifdef YAFFS2_DEBUG
+#define PRINTF(fmt, args...) printf(fmt, ##args)
#else
-#define PRINTF(fmt,args...)
+#define PRINTF(fmt, args...) do { } while (0)
#endif
+extern void cmd_yaffs_dev_ls(void);
+extern void cmd_yaffs_tracemask(unsigned set, unsigned mask);
+extern void cmd_yaffs_devconfig(char *mp, int flash_dev,
+ int start_block, int end_block);
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_write_file(char *fn, char bval, int sizeOfFile);
extern void cmd_yaffs_ls(const char *mountpt, int longlist);
extern void cmd_yaffs_mwrite_file(char *fn, char *addr, int size);
extern void cmd_yaffs_mread_file(char *fn, char *addr);
@@ -21,193 +40,287 @@ extern void cmd_yaffs_rmdir(const char *dir);
extern void cmd_yaffs_rm(const char *path);
extern void cmd_yaffs_mv(const char *oldPath, const char *newPath);
-extern int yaffs_DumpDevStruct(const char *path);
+extern int yaffs_dump_dev(const char *path);
+
+/* ytrace - show/set yaffs trace mask */
+int do_ytrace(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ if (argc > 1)
+ cmd_yaffs_tracemask(1, simple_strtol(argv[1], NULL, 16));
+ else
+ cmd_yaffs_tracemask(0, 0);
+ return 0;
+}
-int do_ymount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+/* ydevls - lists yaffs mount points. */
+int do_ydevls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *mtpoint = argv[1];
- cmd_yaffs_mount(mtpoint);
+ cmd_yaffs_dev_ls();
- return(0);
+ return 0;
}
-int do_yumount (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+/* ydevconfig mount_pt mtd_dev_num start_block end_block */
+int do_ydevconfig(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *mtpoint = argv[1];
- cmd_yaffs_umount(mtpoint);
+ char *mtpoint;
+ int mtd_dev;
+ int start_block;
+ int end_block;
+
+ if (argc != 5) {
+ printf
+ ("Bad arguments: ydevconfig mount_pt mtd_dev start_block end_block\n");
+ return -1;
+ }
+
+ mtpoint = argv[1];
+ mtd_dev = simple_strtol(argv[2], NULL, 16);
+ start_block = simple_strtol(argv[3], NULL, 16);
+ end_block = simple_strtol(argv[4], NULL, 16);
- return(0);
+ cmd_yaffs_devconfig(mtpoint, mtd_dev, start_block, end_block);
+
+ return 0;
}
-int do_yls (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_ymount(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *dirname = argv[argc-1];
+ char *mtpoint;
+
+ if (argc != 2) {
+ printf("Bad arguments: ymount mount_pt\n");
+ return -1;
+ }
+
+ mtpoint = argv[1];
+ printf("Mounting yaffs2 mount point %s\n", mtpoint);
- cmd_yaffs_ls(dirname, (argc>2)?1:0);
+ cmd_yaffs_mount(mtpoint);
- return(0);
+ return 0;
}
-int do_yrd (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 *filename = argv[1];
- printf ("Reading file %s ", filename);
+ char *mtpoint;
- cmd_yaffs_read_file(filename);
+ if (argc != 2) {
+ printf("Bad arguments: yumount mount_pt\n");
+ return -1;
+ }
- printf ("done\n");
- return(0);
+ mtpoint = argv[1];
+ printf("Unmounting yaffs2 mount point %s\n", mtpoint);
+ cmd_yaffs_umount(mtpoint);
+
+ return 0;
}
-int do_ywr (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];
- ulong value = simple_strtoul(argv[2], NULL, 16);
- ulong numValues = simple_strtoul(argv[3], NULL, 16);
+ char *dirname;
+
+ if (argc < 2 || argc > 3 || (argc == 3 && strcmp(argv[1], "-l"))) {
+ printf("Bad arguments: yls [-l] dir\n");
+ return -1;
+ }
- printf ("Writing value (%lx) %lx times to %s... ", value, numValues, filename);
+ dirname = argv[argc - 1];
- cmd_yaffs_write_file(filename,value,numValues);
+ cmd_yaffs_ls(dirname, (argc > 2) ? 1 : 0);
- printf ("done\n");
- return(0);
+ return 0;
}
-int do_yrdm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_yrd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *filename = argv[1];
- ulong addr = simple_strtoul(argv[2], NULL, 16);
+ char *filename;
+
+ if (argc != 2) {
+ printf("Bad arguments: yrd file_name\n");
+ return -1;
+ }
- cmd_yaffs_mread_file(filename, (char *)addr);
+ filename = argv[1];
- return(0);
+ printf("Reading file %s ", filename);
+
+ cmd_yaffs_read_file(filename);
+
+ printf("done\n");
+ return 0;
}
-int do_ywrm (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_ywr(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 value;
+ ulong numValues;
+
+ if (argc != 4) {
+ printf("Bad arguments: ywr file_name value n_values\n");
+ return -1;
+ }
- cmd_yaffs_mwrite_file(filename, (char *)addr, size);
+ filename = argv[1];
+ value = simple_strtoul(argv[2], NULL, 16);
+ numValues = simple_strtoul(argv[3], NULL, 16);
- return(0);
+ printf("Writing value (%lx) %lx times to %s... ", value, numValues,
+ filename);
+
+ cmd_yaffs_write_file(filename, value, numValues);
+
+ printf("done\n");
+ return 0;
}
-int do_ymkdir (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_yrdm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *dirname = argv[1];
+ char *filename;
+ ulong addr;
+
+ if (argc != 3) {
+ printf("Bad arguments: yrdm file_name addr\n");
+ return -1;
+ }
- cmd_yaffs_mkdir(dirname);
+ filename = argv[1];
+ addr = simple_strtoul(argv[2], NULL, 16);
- return(0);
+ cmd_yaffs_mread_file(filename, (char *)addr);
+
+ return 0;
}
-int do_yrmdir (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_ywrm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *dirname = argv[1];
+ char *filename;
+ ulong addr;
+ ulong size;
+
+ if (argc != 4) {
+ printf("Bad arguments: ywrm file_name addr size\n");
+ return -1;
+ }
+
+ filename = argv[1];
+ addr = simple_strtoul(argv[2], NULL, 16);
+ size = simple_strtoul(argv[3], NULL, 16);
- cmd_yaffs_rmdir(dirname);
+ cmd_yaffs_mwrite_file(filename, (char *)addr, size);
- return(0);
+ return 0;
}
-int do_yrm (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 *path = argv[1];
+ char *dirname;
- cmd_yaffs_rm(path);
+ if (argc != 2) {
+ printf("Bad arguments: ymkdir dir_name\n");
+ return -1;
+ }
- return(0);
+ dirname = argv[1];
+ cmd_yaffs_mkdir(dirname);
+
+ return 0;
}
-int do_ymv (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_yrmdir(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *oldPath = argv[1];
- char *newPath = argv[2];
+ char *dirname;
+
+ if (argc != 2) {
+ printf("Bad arguments: yrmdir dir_name\n");
+ return -1;
+ }
- cmd_yaffs_mv(newPath, oldPath);
+ dirname = argv[1];
+ cmd_yaffs_rmdir(dirname);
- return(0);
+ return 0;
}
-int do_ydump (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+int do_yrm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- char *dirname = argv[1];
- if (yaffs_DumpDevStruct(dirname) != 0)
- printf("yaffs_DumpDevStruct returning error when dumping path: , %s\n", dirname);
- return 0;
+ char *name;
+
+ if (argc != 2) {
+ printf("Bad arguments: yrm name\n");
+ return -1;
+ }
+
+ name = argv[1];
+
+ cmd_yaffs_rm(name);
+
+ return 0;
+}
+
+int do_ymv(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ char *oldPath;
+ char *newPath;
+
+ if (argc != 3) {
+ printf("Bad arguments: ymv old_path new_path\n");
+ return -1;
+ }
+
+ oldPath = argv[1];
+ newPath = argv[2];
+
+ cmd_yaffs_mv(newPath, oldPath);
+
+ return 0;
}
-U_BOOT_CMD(
- ymount, 3, 0, do_ymount,
- "mount yaffs",
- ""
-);
-
-U_BOOT_CMD(
- yumount, 3, 0, do_yumount,
- "unmount yaffs",
- ""
-);
-
-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"
-);
-
-U_BOOT_CMD(
- ywr, 4, 0, do_ywr,
- "write file to yaffs",
- "filename value num_vlues"
-);
-
-U_BOOT_CMD(
- yrdm, 3, 0, do_yrdm,
- "read file to memory from yaffs",
- "filename offset"
-);
-
-U_BOOT_CMD(
- ywrm, 4, 0, do_ywrm,
- "write file from memory to yaffs",
- "filename offset size"
-);
-
-U_BOOT_CMD(
- ymkdir, 2, 0, do_ymkdir,
- "YAFFS mkdir",
- "dirname"
-);
-
-U_BOOT_CMD(
- yrmdir, 2, 0, do_yrmdir,
- "YAFFS rmdir",
- "dirname"
-);
-
-U_BOOT_CMD(
- yrm, 2, 0, do_yrm,
- "YAFFS rm",
- "path"
-);
-
-U_BOOT_CMD(
- ymv, 4, 0, do_ymv,
- "YAFFS mv",
- "oldPath newPath"
-);
-
-U_BOOT_CMD(
- ydump, 2, 0, do_ydump,
- "YAFFS device struct",
- "dirname"
-);
+U_BOOT_CMD(ytrace, 2, 0, do_ytrace,
+ "show/set yaffs trace mask",
+ "ytrace [new_mask] show/set yaffs trace mask");
+
+U_BOOT_CMD(ydevls, 1, 0, do_ydevls,
+ "list yaffs mount points", "list yaffs mount points");
+
+U_BOOT_CMD(ydevconfig, 5, 0, do_ydevconfig,
+ "configure yaffs mount point",
+ "ydevconfig mtpoint mtd_id start_block end_block configures a yaffs2 mount point");
+
+U_BOOT_CMD(ymount, 2, 0, do_ymount,
+ "mount yaffs", "ymount mtpoint mounts a yaffs2 mount point");
+
+U_BOOT_CMD(yumount, 2, 0, do_yumount,
+ "unmount yaffs", "yunmount mtpoint unmounts a yaffs2 mount point");
+
+U_BOOT_CMD(yls, 3, 0, do_yls, "yaffs ls", "yls [-l] dirname");
+
+U_BOOT_CMD(yrd, 2, 0, do_yrd,
+ "read file from yaffs", "yrd path read file from yaffs");
+
+U_BOOT_CMD(ywr, 4, 0, do_ywr,
+ "write file to yaffs",
+ "ywr filename value num_vlues write values to yaffs file");
+
+U_BOOT_CMD(yrdm, 3, 0, do_yrdm,
+ "read file to memory from yaffs",
+ "yrdm filename offset reads yaffs file into memory");
+
+U_BOOT_CMD(ywrm, 4, 0, do_ywrm,
+ "write file from memory to yaffs",
+ "ywrm filename offset size writes memory to yaffs file");
+
+U_BOOT_CMD(ymkdir, 2, 0, do_ymkdir,
+ "YAFFS mkdir", "ymkdir dir create a yaffs directory");
+
+U_BOOT_CMD(yrmdir, 2, 0, do_yrmdir,
+ "YAFFS rmdir", "yrmdir dirname removes a yaffs directory");
+
+U_BOOT_CMD(yrm, 2, 0, do_yrm, "YAFFS rm", "yrm path removes a yaffs file");
+
+U_BOOT_CMD(ymv, 4, 0, do_ymv,
+ "YAFFS mv",
+ "ymv old_path new_path moves/rename files within a yaffs mount point");
diff --git a/common/env_onenand.c b/common/env_onenand.c
index 652665a189..7197ab6585 100644
--- a/common/env_onenand.c
+++ b/common/env_onenand.c
@@ -33,7 +33,7 @@
#include <errno.h>
#include <onenand_uboot.h>
-#include <linux/mtd/compat.h>
+#include <linux/compat.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/onenand.h>
diff --git a/common/env_remote.c b/common/env_remote.c
new file mode 100644
index 0000000000..3bf0f957b3
--- /dev/null
+++ b/common/env_remote.c
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 2011-2012 Freescale Semiconductor, Inc.
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* #define DEBUG */
+
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <linux/stddef.h>
+
+char *env_name_spec = "Remote";
+
+#ifdef ENV_IS_EMBEDDED
+env_t *env_ptr = &environment;
+#else /* ! ENV_IS_EMBEDDED */
+env_t *env_ptr = (env_t *)CONFIG_ENV_ADDR;
+#endif /* ENV_IS_EMBEDDED */
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#if !defined(CONFIG_ENV_OFFSET)
+#define CONFIG_ENV_OFFSET 0
+#endif
+
+uchar env_get_char_spec(int index)
+{
+ return *((uchar *)(gd->env_addr + index));
+}
+
+int env_init(void)
+{
+ if (crc32(0, env_ptr->data, ENV_SIZE) == env_ptr->crc) {
+ gd->env_addr = (ulong)&(env_ptr->data);
+ gd->env_valid = 1;
+ return 0;
+ }
+
+ gd->env_addr = (ulong)default_environment;
+ gd->env_valid = 0;
+ return 0;
+}
+
+#ifdef CONFIG_CMD_SAVEENV
+int saveenv(void)
+{
+#ifdef CONFIG_SRIOBOOT_SLAVE
+ printf("Can not support the 'saveenv' when boot from SRIO!\n");
+ return 1;
+#else
+ return 0;
+#endif
+}
+#endif /* CONFIG_CMD_SAVEENV */
+
+void env_relocate_spec(void)
+{
+#ifndef ENV_IS_EMBEDDED
+ env_import((char *)env_ptr, 1);
+#endif
+}
diff --git a/common/hush.c b/common/hush.c
index 672ab9e157..888c4a1a32 100644
--- a/common/hush.c
+++ b/common/hush.c
@@ -1042,7 +1042,7 @@ static void get_user_input(struct in_str *i)
else {
if (console_buffer[0] != '\n') {
strcpy(the_command,console_buffer);
- flag_repeat = 1;
+ /* flag_repeat = 1; */
}
else {
do_repeat = 1;
diff --git a/common/image.c b/common/image.c
index 342b315918..ba6f010ac6 100644
--- a/common/image.c
+++ b/common/image.c
@@ -78,12 +78,13 @@ static const table_entry_t uimage_arch[] = {
{ IH_ARCH_INVALID, NULL, "Invalid ARCH", },
{ IH_ARCH_ALPHA, "alpha", "Alpha", },
{ IH_ARCH_ARM, "arm", "ARM", },
+ { IH_ARCH_MIPS, "mips", "MIPS", },
+ { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", },
+#ifndef CONFIG_SPL_BUILD
{ IH_ARCH_I386, "x86", "Intel x86", },
{ IH_ARCH_IA64, "ia64", "IA64", },
{ IH_ARCH_M68K, "m68k", "M68K", },
{ IH_ARCH_MICROBLAZE, "microblaze", "MicroBlaze", },
- { IH_ARCH_MIPS, "mips", "MIPS", },
- { IH_ARCH_MIPS64, "mips64", "MIPS 64 Bit", },
{ IH_ARCH_NIOS2, "nios2", "NIOS II", },
{ IH_ARCH_PPC, "powerpc", "PowerPC", },
{ IH_ARCH_PPC, "ppc", "PowerPC", },
@@ -95,19 +96,21 @@ static const table_entry_t uimage_arch[] = {
{ IH_ARCH_AVR32, "avr32", "AVR32", },
{ IH_ARCH_NDS32, "nds32", "NDS32", },
{ IH_ARCH_OPENRISC, "or1k", "OpenRISC 1000",},
+#endif
{ -1, "", "", },
};
static const table_entry_t uimage_os[] = {
{ IH_OS_INVALID, NULL, "Invalid OS", },
{ IH_OS_LINUX, "linux", "Linux", },
+ { IH_OS_U_BOOT, "u-boot", "U-Boot", },
+#ifndef CONFIG_SPL_BUILD
#if defined(CONFIG_LYNXKDI) || defined(USE_HOSTCC)
{ IH_OS_LYNXOS, "lynxos", "LynxOS", },
#endif
{ IH_OS_NETBSD, "netbsd", "NetBSD", },
{ IH_OS_OSE, "ose", "Enea OSE", },
{ IH_OS_RTEMS, "rtems", "RTEMS", },
- { IH_OS_U_BOOT, "u-boot", "U-Boot", },
#if defined(CONFIG_CMD_ELF) || defined(USE_HOSTCC)
{ IH_OS_QNX, "qnx", "QNX", },
{ IH_OS_VXWORKS, "vxworks", "VxWorks", },
@@ -128,6 +131,7 @@ static const table_entry_t uimage_os[] = {
{ IH_OS_SOLARIS, "solaris", "Solaris", },
{ IH_OS_SVR4, "svr4", "SVR4", },
#endif
+#endif
{ -1, "", "", },
};
@@ -1829,7 +1833,7 @@ static int fit_parse_spec(const char *spec, char sepc, ulong addr_curr,
* addr and conf_name are set accordingly
* 0 otherwise
*/
-inline int fit_parse_conf(const char *spec, ulong addr_curr,
+int fit_parse_conf(const char *spec, ulong addr_curr,
ulong *addr, const char **conf_name)
{
return fit_parse_spec(spec, '#', addr_curr, addr, conf_name);
@@ -1855,7 +1859,7 @@ inline int fit_parse_conf(const char *spec, ulong addr_curr,
* addr and image_name are set accordingly
* 0 otherwise
*/
-inline int fit_parse_subimage(const char *spec, ulong addr_curr,
+int fit_parse_subimage(const char *spec, ulong addr_curr,
ulong *addr, const char **image_name)
{
return fit_parse_spec(spec, ':', addr_curr, addr, image_name);
diff --git a/common/main.c b/common/main.c
index 3b9e39a980..8b7fd8fffe 100644
--- a/common/main.c
+++ b/common/main.c
@@ -43,6 +43,8 @@
#include <linux/ctype.h>
#include <menu.h>
+/* #define DEBUG_BOOTKEYS 1 */
+
#if defined(CONFIG_SILENT_CONSOLE) || defined(CONFIG_POST) || defined(CONFIG_CMDLINE_EDITING)
DECLARE_GLOBAL_DATA_PTR;
#endif
@@ -50,7 +52,7 @@ DECLARE_GLOBAL_DATA_PTR;
/*
* Board-specific Platform code can reimplement show_boot_progress () if needed
*/
-void inline __show_boot_progress (int val) {}
+void __show_boot_progress (int val) {}
void show_boot_progress (int val) __attribute__((weak, alias("__show_boot_progress")));
#if defined(CONFIG_UPDATE_TFTP)
@@ -95,7 +97,7 @@ static inline
int abortboot(int bootdelay)
{
int abort = 0;
- uint64_t etime = endtick(bootdelay);
+ uint64_t etime = endtick(1);
struct {
char* str;
u_int len;
@@ -113,10 +115,6 @@ int abortboot(int bootdelay)
u_int presskey_max = 0;
u_int i;
-# ifdef CONFIG_AUTOBOOT_PROMPT
- printf(CONFIG_AUTOBOOT_PROMPT);
-# endif
-
# ifdef CONFIG_AUTOBOOT_DELAY_STR
if (delaykey[0].str == NULL)
delaykey[0].str = CONFIG_AUTOBOOT_DELAY_STR;
@@ -134,6 +132,10 @@ int abortboot(int bootdelay)
delaykey[3].str = CONFIG_AUTOBOOT_STOP_STR2;
# endif
+# if DEBUG_BOOTKEYS
+ printf("\n");
+# endif
+
for (i = 0; i < sizeof(delaykey) / sizeof(delaykey[0]); i ++) {
delaykey[i].len = delaykey[i].str == NULL ?
0 : strlen (delaykey[i].str);
@@ -144,16 +146,46 @@ int abortboot(int bootdelay)
presskey_max : delaykey[i].len;
# if DEBUG_BOOTKEYS
- printf("%s key:<%s>\n",
- delaykey[i].retry ? "delay" : "stop",
- delaykey[i].str ? delaykey[i].str : "NULL");
+ u_int j;
+ printf("%s key: <", delaykey[i].retry ? "Delay" : "Stop ");
+ if (delaykey[i].str) {
+ for (j = 0; j < delaykey[i].len; j++) {
+ if (delaykey[i].str[j] < 0x80 &&
+ isprint(delaykey[i].str[j])) {
+ printf("%c", delaykey[i].str[j]);
+ } else {
+ printf("\\x%02X", delaykey[i].str[j]);
+ }
+ }
+ } else {
+ printf("NULL");
+ }
+ printf(">\n");
# endif
}
+# if DEBUG_BOOTKEYS
+ printf("\n");
+# endif
+
+# ifdef CONFIG_AUTOBOOT_PROMPT
+ printf(CONFIG_AUTOBOOT_PROMPT);
+# else
+ printf("Hit delay/stop key to delay/stop autoboot: %2d ", bootdelay);
+# endif
+
/* In order to keep up with incoming data, check timeout only
* when catch up.
*/
- do {
+ while (!abort && bootdelay > 0) {
+ if (get_ticks() > etime) {
+ etime = endtick(1);
+ --bootdelay;
+# ifndef CONFIG_AUTOBOOT_PROMPT
+ printf("\b\b\b%2d ", bootdelay);
+# endif
+ }
+
if (tstc()) {
if (presskey_len < presskey_max) {
presskey [presskey_len ++] = getc();
@@ -172,11 +204,14 @@ int abortboot(int bootdelay)
memcmp (presskey + presskey_len - delaykey[i].len,
delaykey[i].str,
delaykey[i].len) == 0) {
+# ifndef CONFIG_AUTOBOOT_PROMPT
+ puts("\n");
+# endif
# if DEBUG_BOOTKEYS
- printf("got %skey\n",
+ printf("Got %s key\n",
delaykey[i].retry ? "delay" : "stop");
# endif
-
+ puts("\n");
# ifdef CONFIG_BOOT_RETRY_TIME
/* don't retry auto boot */
if (! delaykey[i].retry)
@@ -185,12 +220,17 @@ int abortboot(int bootdelay)
abort = 1;
}
}
- } while (!abort && get_ticks() <= etime);
+ }
+ if (!abort) {
+# ifndef CONFIG_AUTOBOOT_PROMPT
+ puts("\n");
+# endif
# if DEBUG_BOOTKEYS
- if (!abort)
- puts("key timeout\n");
+ puts("Key timeout\n");
# endif
+ puts("\n");
+ }
#ifdef CONFIG_SILENT_CONSOLE
if (abort)
@@ -227,7 +267,9 @@ int abortboot(int bootdelay)
if (bootdelay >= 0) {
if (tstc()) { /* we got a key press */
(void) getc(); /* consume input */
+#ifndef CONFIG_MENUPROMPT
puts ("\b\b\b 0");
+#endif
abort = 1; /* don't auto boot */
}
}
@@ -252,7 +294,9 @@ int abortboot(int bootdelay)
udelay(10000);
}
+#ifndef CONFIG_MENUPROMPT
printf("\b\b\b%2d ", bootdelay);
+#endif
}
putc('\n');
@@ -271,6 +315,7 @@ int abortboot(int bootdelay)
void main_loop (void)
{
+ int autoboot;
#ifndef CONFIG_SYS_HUSH_PARSER
static char lastcommand[CONFIG_SYS_CBSIZE] = { 0, };
int len;
@@ -376,7 +421,12 @@ void main_loop (void)
debug ("### main_loop: bootcmd=\"%s\"\n", s ? s : "<UNDEFINED>");
- if (bootdelay >= 0 && s && !abortboot (bootdelay)) {
+# ifdef REBOOT_WHEN_CRASH
+ autoboot = (s != NULL);
+# else
+ autoboot = (bootdelay >= 0 && s && !abortboot (bootdelay));
+# endif
+ if (autoboot) {
# ifdef CONFIG_AUTOBOOT_KEYED
int prev = disable_ctrlc(1); /* disable Control C checking */
# endif
@@ -973,7 +1023,6 @@ int readline_into_buffer(const char *const prompt, char *buffer, int timeout)
#ifdef CONFIG_SHOW_ACTIVITY
while (!tstc()) {
- extern void show_activity(int arg);
show_activity(0);
WATCHDOG_RESET();
}
diff --git a/common/usb.c b/common/usb.c
index 1ec30bc058..c80155ce76 100644
--- a/common/usb.c
+++ b/common/usb.c
@@ -47,6 +47,7 @@
#include <common.h>
#include <command.h>
#include <asm/processor.h>
+#include <linux/compiler.h>
#include <linux/ctype.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
@@ -169,7 +170,7 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
unsigned short value, unsigned short index,
void *data, unsigned short size, int timeout)
{
- struct devrequest setup_packet;
+ ALLOC_CACHE_ALIGN_BUFFER(struct devrequest, setup_packet, 1);
if ((timeout == 0) && (!asynch_allowed)) {
/* request for a asynch control pipe is not allowed */
@@ -177,17 +178,17 @@ int usb_control_msg(struct usb_device *dev, unsigned int pipe,
}
/* set setup command */
- setup_packet.requesttype = requesttype;
- setup_packet.request = request;
- setup_packet.value = cpu_to_le16(value);
- setup_packet.index = cpu_to_le16(index);
- setup_packet.length = cpu_to_le16(size);
+ setup_packet->requesttype = requesttype;
+ setup_packet->request = request;
+ setup_packet->value = cpu_to_le16(value);
+ setup_packet->index = cpu_to_le16(index);
+ setup_packet->length = cpu_to_le16(size);
USB_PRINTF("usb_control_msg: request: 0x%X, requesttype: 0x%X, " \
"value 0x%X index 0x%X length 0x%X\n",
request, requesttype, value, index, size);
dev->status = USB_ST_NOT_PROC; /*not yet processed */
- submit_control_msg(dev, pipe, data, size, &setup_packet);
+ submit_control_msg(dev, pipe, data, size, setup_packet);
if (timeout == 0)
return (int)size;
@@ -261,7 +262,7 @@ int usb_maxpacket(struct usb_device *dev, unsigned long pipe)
*
* NOTE: Similar behaviour was observed with GCC4.6 on ARMv5.
*/
-static void __attribute__((noinline))
+static void noinline
usb_set_maxpacket_ep(struct usb_device *dev, int if_idx, int ep_idx)
{
int b;
@@ -681,7 +682,7 @@ static int usb_string_sub(struct usb_device *dev, unsigned int langid,
*/
int usb_string(struct usb_device *dev, int index, char *buf, size_t size)
{
- unsigned char mybuf[USB_BUFSIZ];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, mybuf, USB_BUFSIZ);
unsigned char *tbuf;
int err;
unsigned int u, idx;
@@ -781,7 +782,7 @@ int usb_new_device(struct usb_device *dev)
{
int addr, err;
int tmp;
- unsigned char tmpbuf[USB_BUFSIZ];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, tmpbuf, USB_BUFSIZ);
/* We still haven't set the Address yet */
addr = dev->devnum;
@@ -908,8 +909,8 @@ int usb_new_device(struct usb_device *dev)
le16_to_cpus(&dev->descriptor.idProduct);
le16_to_cpus(&dev->descriptor.bcdDevice);
/* only support for one config for now */
- usb_get_configuration_no(dev, &tmpbuf[0], 0);
- usb_parse_config(dev, &tmpbuf[0], 0);
+ usb_get_configuration_no(dev, tmpbuf, 0);
+ usb_parse_config(dev, tmpbuf, 0);
usb_set_maxpacket(dev);
/* we set the default configuration here */
if (usb_set_configuration(dev, dev->config.desc.bConfigurationValue)) {
diff --git a/common/usb_hub.c b/common/usb_hub.c
index e0edaad56b..f35ad95324 100644
--- a/common/usb_hub.c
+++ b/common/usb_hub.c
@@ -153,7 +153,7 @@ int hub_port_reset(struct usb_device *dev, int port,
unsigned short *portstat)
{
int tries;
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus, portchange;
USB_HUB_PRINTF("hub_port_reset: resetting port %d...\n", port);
@@ -162,13 +162,13 @@ int hub_port_reset(struct usb_device *dev, int port,
usb_set_port_feature(dev, port + 1, USB_PORT_FEAT_RESET);
mdelay(200);
- if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, port + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed status %lX\n",
dev->status);
return -1;
}
- portstatus = le16_to_cpu(portsts.wPortStatus);
- portchange = le16_to_cpu(portsts.wPortChange);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
+ portchange = le16_to_cpu(portsts->wPortChange);
USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus, portchange,
@@ -206,19 +206,19 @@ int hub_port_reset(struct usb_device *dev, int port,
void usb_hub_port_connect_change(struct usb_device *dev, int port)
{
struct usb_device *usb;
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus;
/* Check status */
- if (usb_get_port_status(dev, port + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, port + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed\n");
return;
}
- portstatus = le16_to_cpu(portsts.wPortStatus);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
USB_HUB_PRINTF("portstatus %x, change %x, %s\n",
portstatus,
- le16_to_cpu(portsts.wPortChange),
+ le16_to_cpu(portsts->wPortChange),
portspeed(portstatus));
/* Clear the connection change status */
@@ -267,7 +267,8 @@ void usb_hub_port_connect_change(struct usb_device *dev, int port)
static int usb_hub_configure(struct usb_device *dev)
{
int i;
- unsigned char buffer[USB_BUFSIZ], *bitmap;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buffer, USB_BUFSIZ);
+ unsigned char *bitmap;
struct usb_hub_descriptor *descriptor;
struct usb_hub_device *hub;
#ifdef USB_HUB_DEBUG
@@ -389,16 +390,16 @@ static int usb_hub_configure(struct usb_device *dev)
usb_hub_power_on(hub);
for (i = 0; i < dev->maxchild; i++) {
- struct usb_port_status portsts;
+ ALLOC_CACHE_ALIGN_BUFFER(struct usb_port_status, portsts, 1);
unsigned short portstatus, portchange;
- if (usb_get_port_status(dev, i + 1, &portsts) < 0) {
+ if (usb_get_port_status(dev, i + 1, portsts) < 0) {
USB_HUB_PRINTF("get_port_status failed\n");
continue;
}
- portstatus = le16_to_cpu(portsts.wPortStatus);
- portchange = le16_to_cpu(portsts.wPortChange);
+ portstatus = le16_to_cpu(portsts->wPortStatus);
+ portchange = le16_to_cpu(portsts->wPortChange);
USB_HUB_PRINTF("Port %d Status %X Change %X\n",
i + 1, portstatus, portchange);
diff --git a/common/usb_storage.c b/common/usb_storage.c
index 12083337b0..faad23706f 100644
--- a/common/usb_storage.c
+++ b/common/usb_storage.c
@@ -79,8 +79,7 @@ static const unsigned char us_direction[256/8] = {
};
#define US_DIRECTION(x) ((us_direction[x>>3] >> (x & 7)) & 1)
-static unsigned char usb_stor_buf[512];
-static ccb usb_ccb;
+static ccb usb_ccb __attribute__((aligned(ARCH_DMA_MINALIGN)));
/*
* CBI style
@@ -210,17 +209,17 @@ int usb_stor_info(void)
static unsigned int usb_get_max_lun(struct us_data *us)
{
int len;
- unsigned char result;
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, result, 1);
len = usb_control_msg(us->pusb_dev,
usb_rcvctrlpipe(us->pusb_dev, 0),
US_BBB_GET_MAX_LUN,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
0, us->ifnum,
- &result, sizeof(result),
+ result, sizeof(char),
USB_CNTL_TIMEOUT * 5);
USB_STOR_PRINTF("Get Max LUN -> len = %i, result = %i\n",
- len, (int) result);
- return (len > 0) ? result : 0;
+ len, (int) *result);
+ return (len > 0) ? *result : 0;
}
/*******************************************************************************
@@ -233,9 +232,6 @@ int usb_stor_scan(int mode)
unsigned char i;
struct usb_device *dev;
- /* GJ */
- memset(usb_stor_buf, 0, sizeof(usb_stor_buf));
-
if (mode == 1)
printf(" scanning bus for storage devices... ");
@@ -499,7 +495,7 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
int actlen;
int dir_in;
unsigned int pipe;
- umass_bbb_cbw_t cbw;
+ ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_cbw_t, cbw, 1);
dir_in = US_DIRECTION(srb->cmd[0]);
@@ -522,16 +518,16 @@ int usb_stor_BBB_comdat(ccb *srb, struct us_data *us)
/* always OUT to the ep */
pipe = usb_sndbulkpipe(us->pusb_dev, us->ep_out);
- cbw.dCBWSignature = cpu_to_le32(CBWSIGNATURE);
- cbw.dCBWTag = cpu_to_le32(CBWTag++);
- cbw.dCBWDataTransferLength = cpu_to_le32(srb->datalen);
- cbw.bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
- cbw.bCBWLUN = srb->lun;
- cbw.bCDBLength = srb->cmdlen;
+ cbw->dCBWSignature = cpu_to_le32(CBWSIGNATURE);
+ cbw->dCBWTag = cpu_to_le32(CBWTag++);
+ cbw->dCBWDataTransferLength = cpu_to_le32(srb->datalen);
+ cbw->bCBWFlags = (dir_in ? CBWFLAGS_IN : CBWFLAGS_OUT);
+ cbw->bCBWLUN = srb->lun;
+ cbw->bCDBLength = srb->cmdlen;
/* copy the command data into the CBW command data buffer */
/* DST SRC LEN!!! */
- memcpy(cbw.CBWCDB, srb->cmd, srb->cmdlen);
- result = usb_bulk_msg(us->pusb_dev, pipe, &cbw, UMASS_BBB_CBW_SIZE,
+ memcpy(cbw->CBWCDB, srb->cmd, srb->cmdlen);
+ result = usb_bulk_msg(us->pusb_dev, pipe, cbw, UMASS_BBB_CBW_SIZE,
&actlen, USB_CNTL_TIMEOUT * 5);
if (result < 0)
USB_STOR_PRINTF("usb_stor_BBB_comdat:usb_bulk_msg error\n");
@@ -675,7 +671,7 @@ int usb_stor_BBB_transport(ccb *srb, struct us_data *us)
int dir_in;
int actlen, data_actlen;
unsigned int pipe, pipein, pipeout;
- umass_bbb_csw_t csw;
+ ALLOC_CACHE_ALIGN_BUFFER(umass_bbb_csw_t, csw, 1);
#ifdef BBB_XPORT_TRACE
unsigned char *ptr;
int index;
@@ -733,7 +729,7 @@ st:
retry = 0;
again:
USB_STOR_PRINTF("STATUS phase\n");
- result = usb_bulk_msg(us->pusb_dev, pipein, &csw, UMASS_BBB_CSW_SIZE,
+ result = usb_bulk_msg(us->pusb_dev, pipein, csw, UMASS_BBB_CSW_SIZE,
&actlen, USB_CNTL_TIMEOUT*5);
/* special handling of STALL in STATUS phase */
@@ -753,28 +749,28 @@ again:
return USB_STOR_TRANSPORT_FAILED;
}
#ifdef BBB_XPORT_TRACE
- ptr = (unsigned char *)&csw;
+ ptr = (unsigned char *)csw;
for (index = 0; index < UMASS_BBB_CSW_SIZE; index++)
printf("ptr[%d] %#x ", index, ptr[index]);
printf("\n");
#endif
/* misuse pipe to get the residue */
- pipe = le32_to_cpu(csw.dCSWDataResidue);
+ pipe = le32_to_cpu(csw->dCSWDataResidue);
if (pipe == 0 && srb->datalen != 0 && srb->datalen - data_actlen != 0)
pipe = srb->datalen - data_actlen;
- if (CSWSIGNATURE != le32_to_cpu(csw.dCSWSignature)) {
+ if (CSWSIGNATURE != le32_to_cpu(csw->dCSWSignature)) {
USB_STOR_PRINTF("!CSWSIGNATURE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if ((CBWTag - 1) != le32_to_cpu(csw.dCSWTag)) {
+ } else if ((CBWTag - 1) != le32_to_cpu(csw->dCSWTag)) {
USB_STOR_PRINTF("!Tag\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus > CSWSTATUS_PHASE) {
+ } else if (csw->bCSWStatus > CSWSTATUS_PHASE) {
USB_STOR_PRINTF(">PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus == CSWSTATUS_PHASE) {
+ } else if (csw->bCSWStatus == CSWSTATUS_PHASE) {
USB_STOR_PRINTF("=PHASE\n");
usb_stor_BBB_reset(us);
return USB_STOR_TRANSPORT_FAILED;
@@ -782,7 +778,7 @@ again:
USB_STOR_PRINTF("transferred %dB instead of %ldB\n",
data_actlen, srb->datalen);
return USB_STOR_TRANSPORT_FAILED;
- } else if (csw.bCSWStatus == CSWSTATUS_FAILED) {
+ } else if (csw->bCSWStatus == CSWSTATUS_FAILED) {
USB_STOR_PRINTF("FAILED\n");
return USB_STOR_TRANSPORT_FAILED;
}
@@ -1343,7 +1339,8 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
block_dev_desc_t *dev_desc)
{
unsigned char perq, modi;
- unsigned long cap[2];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned long, cap, 2);
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, usb_stor_buf, 36);
unsigned long *capacity, *blksz;
ccb *pccb = &usb_ccb;
@@ -1367,9 +1364,9 @@ int usb_stor_get_info(struct usb_device *dev, struct us_data *ss,
/* drive is removable */
dev_desc->removable = 1;
}
- memcpy(&dev_desc->vendor[0], &usb_stor_buf[8], 8);
- memcpy(&dev_desc->product[0], &usb_stor_buf[16], 16);
- memcpy(&dev_desc->revision[0], &usb_stor_buf[32], 4);
+ memcpy(&dev_desc->vendor[0], (const void *) &usb_stor_buf[8], 8);
+ memcpy(&dev_desc->product[0], (const void *) &usb_stor_buf[16], 16);
+ memcpy(&dev_desc->revision[0], (const void *) &usb_stor_buf[32], 4);
dev_desc->vendor[8] = 0;
dev_desc->product[16] = 0;
dev_desc->revision[4] = 0;