summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJustin Waters <justin.waters@timesys.com>2013-04-24 17:41:45 -0400
committerJustin Waters <justin.waters@timesys.com>2013-04-24 17:41:45 -0400
commit18282017b14c0b32b4aa6fd05df58ba5cff0b472 (patch)
tree24344ef4d64f38baee4f5b56a9b44cc775ab4b62
parent75c641ece39c136001340df61f0ad57028ce4ffc (diff)
LogicPD Support for OMAP3/DM3/AM3 boards 2.2 Update
-rw-r--r--arch/arm/cpu/armv7/omap3/board.c38
-rw-r--r--arch/arm/cpu/armv7/omap3/sys_info.c82
-rw-r--r--arch/arm/include/asm/arch-omap3/cpu.h2
-rw-r--r--arch/arm/include/asm/arch-omap3/sys_proto.h3
-rw-r--r--arch/arm/lib/reset.c8
-rw-r--r--board/ti/logic/logic-at24.c2
-rw-r--r--board/ti/logic/logic-data.c4
-rw-r--r--board/ti/logic/logic-product-id.c11
-rw-r--r--board/ti/logic/logic.c78
-rw-r--r--board/ti/logic/prod-id/query.c2
-rw-r--r--common/Makefile1
-rw-r--r--common/cmd_fastboot.c1114
-rw-r--r--common/cmd_mtdparts.c336
-rw-r--r--common/cmd_nand.c149
-rw-r--r--common/lcd.c2
-rw-r--r--drivers/mtd/nand/nand_base.c2
-rw-r--r--drivers/mtd/nand/omap_gpmc.c76
-rw-r--r--drivers/power/twl4030.c2
-rw-r--r--drivers/usb/musb/musb_udc.c30
-rw-r--r--include/common.h1
-rw-r--r--include/configs/omap3logic.h428
-rw-r--r--include/fastboot.h377
-rw-r--r--include/jffs2/load_kernel.h13
-rw-r--r--include/linux/string.h3
-rw-r--r--include/mtd_parts.h1
-rw-r--r--include/nand.h5
-rw-r--r--include/twl4030.h1
-rw-r--r--include/usb/musb_udc.h4
-rw-r--r--include/usbdevice.h8
-rw-r--r--lib/string.c23
30 files changed, 2497 insertions, 309 deletions
diff --git a/arch/arm/cpu/armv7/omap3/board.c b/arch/arm/cpu/armv7/omap3/board.c
index 18133d876d..81df64d82a 100644
--- a/arch/arm/cpu/armv7/omap3/board.c
+++ b/arch/arm/cpu/armv7/omap3/board.c
@@ -248,7 +248,7 @@ void abort(void)
/******************************************************************************
* OMAP3 specific command to switch between NAND HW and SW ecc
*****************************************************************************/
-static int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+int do_switch_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
struct mtd_info *mtd;
struct nand_chip *nand;
@@ -308,6 +308,42 @@ U_BOOT_CMD(
"[hw/sw/chip] - Switch between NAND hardware (hw), software (sw),\n in-chip (chip) ecc algorithm, or BCH (bch) ecc algorithm"
);
+#ifdef CONFIG_CMD_NAND_CHIP_ECC
+int do_switch_chip_ecc(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+{
+ int set, get, enable;
+
+ if (argc == 1) {
+ get = 1;
+ } else if (argc == 2) {
+ get = 0;
+ if (!strcmp(argv[1], "on"))
+ enable = 1;
+ else if (!strcmp(argv[1], "off"))
+ enable = 0;
+ else
+ goto usage;
+ }
+ set = omap_nand_switch_chip_ecc(get, enable);
+ if (set < 0) {
+ printf("NAND chip does not have internal ECC engine\n");
+ return 1;
+ }
+ if (get)
+ printf("in-chip ECC: %s\n", set?"on":"off");
+ return 0;
+
+ usage:
+ printf ("Usage: nandchip_ecc %s\n", cmdtp->usage);
+ return 1;
+}
+
+U_BOOT_CMD(
+ nandchip_ecc, 2, 1, do_switch_chip_ecc,
+ "enable/disable Micron in-chip ECC engine",
+ "[on/off] - Enable/disable in-chip ECC engine"
+);
+#endif
#endif /* CONFIG_NAND_OMAP_GPMC */
#ifdef CONFIG_DISPLAY_BOARDINFO
diff --git a/arch/arm/cpu/armv7/omap3/sys_info.c b/arch/arm/cpu/armv7/omap3/sys_info.c
index 598457610f..09bce91bba 100644
--- a/arch/arm/cpu/armv7/omap3/sys_info.c
+++ b/arch/arm/cpu/armv7/omap3/sys_info.c
@@ -264,12 +264,88 @@ u32 get_device_type(void)
}
#ifdef CONFIG_DISPLAY_CPUINFO
+
+static int extract_sys_clk(u32 clksel)
+{
+ clksel &= 0x7;
+ switch(clksel) {
+ case 0:
+ return 12000000;
+ case 1:
+ return 13000000;
+ case 2:
+ return 19200000;
+ case 3:
+ return 26000000;
+ case 4:
+ return 38400000;
+ case 5:
+ return 16800000;
+ default:
+ return 0;
+ }
+}
+
+/* Find the speed the SDRC (in Hz) is current setup for */
+unsigned int extract_l3_ick(void)
+{
+ struct prcm *prcm_base = (struct prcm *)PRCM_BASE;
+ u32 osc_clk;
+ u32 sysclkdiv;
+ u32 fsys_clk;
+ u32 fclkout;
+ u32 l3_ick;
+ u32 fcore_clk;
+ u32 m, n, m2, div_l3;
+ u32 reg;
+
+ /* Get pk_clksel and use to find crystal speed */
+ reg = __raw_readl(PRM_CLKSEL);
+ osc_clk = extract_sys_clk(reg);
+ osc_clk /= 1000; /* Scale down by KHz to keep in scale */
+
+ /* Find sys clock divisor */
+ sysclkdiv = __raw_readl(PRM_CLKSRC_CTRL);
+ sysclkdiv >>= 6;
+ sysclkdiv &= 0x3;
+
+ fsys_clk = osc_clk / sysclkdiv;
+
+ reg = __raw_readl((u32)&prcm_base->clksel1_pll);
+ m = reg >> 16;
+ m &= 0x7ff;
+ n = reg >> 8;
+ n &= 0x7f;
+
+ fclkout = (fsys_clk * m) / (n + 1);
+
+ div_l3 = __raw_readl((u32)&prcm_base->clksel_core);
+ div_l3 &= 0x3;
+
+ l3_ick = fclkout / div_l3;
+
+ m2 = __raw_readl((u32)&prcm_base->clksel1_pll);
+ m2 >>= 27;
+ m2 &= 0x3f;
+
+ fcore_clk = fclkout / m2;
+
+#if 0
+ printf("DPLL3:\n");
+ printf("\tfclkout = (%u * %u) / (%u + 1) = %u\n", fsys_clk * 1000, m, n, fclkout * 1000);
+ printf("\tL3_ick: %u\n", l3_ick * 1000);
+ printf("\tfcore_clk: %u\n", fcore_clk * 1000);
+#endif
+ return l3_ick * 1000;
+}
+
/**
* Print CPU information
*/
int print_cpuinfo (void)
{
char *cpu_family_s, *cpu_s, *sec_s, *max_clk;
+ u32 l3_ick;
switch (get_cpu_family()) {
case CPU_OMAP34XX:
@@ -348,9 +424,11 @@ int print_cpuinfo (void)
sec_s = "?";
}
- printf("%s%s-%s ES%s, CPU-OPP2, L3-165MHz, Max CPU Clock %s\n",
+ l3_ick = extract_l3_ick() / 1000000;
+
+ printf("%s%s-%s ES%s, CPU-OPP2, L3-%uMHz, Max CPU Clock %s\n",
cpu_family_s, cpu_s, sec_s,
- rev_s[get_cpu_rev()], max_clk);
+ rev_s[get_cpu_rev()], l3_ick, max_clk);
return 0;
}
diff --git a/arch/arm/include/asm/arch-omap3/cpu.h b/arch/arm/include/asm/arch-omap3/cpu.h
index def013768c..94f53c41b4 100644
--- a/arch/arm/include/asm/arch-omap3/cpu.h
+++ b/arch/arm/include/asm/arch-omap3/cpu.h
@@ -417,6 +417,8 @@ struct prcm {
#endif /* __KERNEL_STRICT_NAMES */
#define PRM_BASE 0x48306000
+#define PRM_CLKSEL 0x48306d40
+#define PRM_CLKSRC_CTRL 0x48307270
#ifndef __KERNEL_STRICT_NAMES
#ifndef __ASSEMBLY__
diff --git a/arch/arm/include/asm/arch-omap3/sys_proto.h b/arch/arm/include/asm/arch-omap3/sys_proto.h
index cb45504c22..8c4f364d01 100644
--- a/arch/arm/include/asm/arch-omap3/sys_proto.h
+++ b/arch/arm/include/asm/arch-omap3/sys_proto.h
@@ -70,6 +70,9 @@ enum omap_nand_ecc_mode {
OMAP_ECC_SOFT_BCH,
};
extern void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode);
+#ifdef CONFIG_CMD_NAND_CHIP_ECC
+extern int omap_nand_switch_chip_ecc(int get, int enable);
+#endif
extern enum omap_nand_ecc_mode omap_nand_current_ecc_method(void);
int omap_nand_chip_has_ecc(void);
diff --git a/arch/arm/lib/reset.c b/arch/arm/lib/reset.c
index 08e6acb261..b0f3a5eca1 100644
--- a/arch/arm/lib/reset.c
+++ b/arch/arm/lib/reset.c
@@ -38,11 +38,17 @@
*/
#include <common.h>
-
+#include <nand.h>
int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
puts ("resetting ...\n");
+#ifdef CONFIG_OMAP3_LOGIC
+ /* Disable the in-chip ECC since reset doesn't cause the PoP NAND
+ * to internally reset */
+ nand_disable_in_chip_ecc();
+#endif
+
udelay (50000); /* wait 50 ms */
disable_interrupts();
diff --git a/board/ti/logic/logic-at24.c b/board/ti/logic/logic-at24.c
index e1f03db2ce..f5e70c50d2 100644
--- a/board/ti/logic/logic-at24.c
+++ b/board/ti/logic/logic-at24.c
@@ -65,6 +65,8 @@ int at24_shutdown(void)
gpio_i2c_config_pin(GPIO_I2C_SCLK, GPIO_I2C_INPUT);
/* Restore pins back to their intended use */
gpio_i2c_restore_pins();
+
+ return 0;
}
/* Send the offset to the AT24 chip */
diff --git a/board/ti/logic/logic-data.c b/board/ti/logic/logic-data.c
index ba4633bf89..dfcfb61cba 100644
--- a/board/ti/logic/logic-data.c
+++ b/board/ti/logic/logic-data.c
@@ -589,10 +589,14 @@ void _dump_production_data(void)
extract_model_number_revision(&product_id_data, buf, sizeof(buf));
if (strlen(buf))
+ {
printf("Model Name : %s\n", buf);
+ setenv("logic_model", buf);
+ }
extract_serial_number(&product_id_data, buf, sizeof(buf));
printf("Serial Number: %s\n", buf);
+ setenv("logic_serial", buf);
ret = extract_mac_address(&product_id_data, 0, mac);
if (!ret) {
diff --git a/board/ti/logic/logic-product-id.c b/board/ti/logic/logic-product-id.c
index 3142511d97..edc440945f 100644
--- a/board/ti/logic/logic-product-id.c
+++ b/board/ti/logic/logic-product-id.c
@@ -189,9 +189,9 @@ int logic_dump_serialization_info(void)
int ret;
struct id_cookie cookie;
int part_number;
- u8 model_name[32];
+ u8 model_name[33];
u32 model_name_size;
- u8 serial_number[10];
+ u8 serial_number[11];
u32 serial_number_size;
if (!found_id_data) {
@@ -212,7 +212,7 @@ int logic_dump_serialization_info(void)
}
/* Find serial_number */
- serial_number_size = sizeof(serial_number);
+ serial_number_size = sizeof(serial_number) - 1;
ret = id_find_string(&cookie, ID_KEY_serial_number, serial_number, &serial_number_size);
if (ret != ID_EOK) {
printf("%s:%d ret %d\n", __FUNCTION__, __LINE__, ret);
@@ -241,13 +241,16 @@ int logic_dump_serialization_info(void)
}
/* Find model name */
- model_name_size = sizeof(model_name);
+ model_name_size = sizeof(model_name) - 1;
ret = id_find_string(&cookie, ID_KEY_model_name, model_name, &model_name_size);
if (ret != ID_EOK) {
printf("%s:%d ret %d\n", __FUNCTION__, __LINE__, ret);
return ret;
}
+ model_name[model_name_size] = '\0';
+ serial_number[serial_number_size] = '\0';
+
printf("Part Number : %u\n", part_number);
printf("Model Name : %.*s\n", model_name_size, model_name);
printf("Serial Number: %.*s\n", serial_number_size, serial_number);
diff --git a/board/ti/logic/logic.c b/board/ti/logic/logic.c
index b6c16b1d40..82ee77ce15 100644
--- a/board/ti/logic/logic.c
+++ b/board/ti/logic/logic.c
@@ -196,6 +196,38 @@ char *get_mtdids_default(void)
return omap3logic_mtdids_default;
}
+char *get_mtdflags_default(void)
+{
+#if defined(MTDFLAGS_NAND_DEFAULT) || defined(MTDFLAGS_NOR_DEFAULT)
+ static char str[
+# ifdef MTDFLAGS_NOR_DEFAULT
+ ARRAY_SIZE(MTDFLAGS_NOR_DEFAULT) +
+# endif
+# ifdef MTDFLAGS_NAND_DEFAULT
+ ARRAY_SIZE(MTDFLAGS_NAND_DEFAULT) +
+# endif
+ 10] = "";
+
+ if (str[0] == '\0') {
+ str[0] = '\0';
+#ifdef MTDFLAGS_NAND_DEFAULT
+ if (nand_size())
+ strcpy(str, MTDFLAGS_NAND_DEFAULT);
+#endif
+#ifdef MTDFLAGS_NOR_DEFAULT
+ if (omap3logic_nor_exists) {
+ if (strlen(str))
+ strcat(str, ";");
+ strcat(str, MTDFLAGS_NOR_DEFAULT);
+ }
+#endif
+ }
+ return str;
+#else
+ return NULL;
+#endif
+}
+
/*
* Touchup the environment, specificaly "defaultecc", the display,
* and mtdids/mtdparts on default environment
@@ -218,6 +250,7 @@ void touchup_env(int initial_env)
/* Need to set mdtids/mtdparts to computed defaults */
setenv("mtdparts", get_mtdparts_default());
setenv("mtdids", get_mtdids_default());
+ setenv("mtdflags", get_mtdflags_default());
}
}
@@ -331,35 +364,6 @@ int board_late_init(void)
return 0;
}
-/* Turn on VAUX1 voltage to 3.0 volts to drive level shifters and
- * power 3.0v parts (tsc2004 and Product ID chip) */
-#define I2C_TRITON2 0x4b /* Address of Triton power group */
-
-void init_vaux1_voltage(void)
-{
-#ifdef CONFIG_DRIVER_OMAP34XX_I2C
- unsigned char data;
- unsigned short msg;
-
- /* Select the output voltage */
- data = 0x04;
- i2c_write(I2C_TRITON2, 0x72, 1, &data, 1);
- /* Select the Processor resource group */
- data = 0x20;
- i2c_write(I2C_TRITON2, 0x72, 1, &data, 1);
- /* Enable I2C access to the Power bus */
- data = 0x02;
- i2c_write(I2C_TRITON2, 0x4a, 1, &data, 1);
- /* Send message MSB */
- msg = (1<<13) | (1<<4) | (0xd<<0); /* group(process_grp1):resource(vaux1):res_active; */
- data = msg >> 8;
- i2c_write(I2C_TRITON2, 0x4b, 1, &data, 1);
- /* Send message LSB */
- data = msg & 0xff;
- i2c_write(I2C_TRITON2, 0x4c, 1, &data, 1);
-#endif
-}
-
/* Mux I2C bus pins appropriately for this board */
int i2c_mux_bux_pins(int bus)
{
@@ -410,10 +414,15 @@ static void check_sysconfig_regs(void)
*/
int misc_init_r(void)
{
- /* Turn on vaux1 to make sure voltage is to the product ID chip.
- * Extract production data from ID chip, used to selectively
+ /* Turn on VAUX1 voltage to 3.0 volts to drive level shifters and
+ * power 3.0v parts (tsc2004 and Product ID chip) */
+ twl4030_pmrecv_vsel_cfg(TWL4030_PM_RECEIVER_VAUX1_DEDICATED,
+ TWL4030_PM_RECEIVER_VAUX1_VSEL_30,
+ TWL4030_PM_RECEIVER_VAUX1_DEV_GRP,
+ TWL4030_PM_RECEIVER_DEV_GRP_P1);
+
+ /** Extract production data from ID chip, used to selectively
* initialize portions of the system */
- init_vaux1_voltage();
fetch_production_data();
#if defined(CONFIG_CMD_NET)
@@ -1173,6 +1182,7 @@ void set_muxconf_regs(void)
MUX_VAL(CP(UART3_RTS_SD), (IEN | PTD | EN | M7)); /*UART3_RTS_SD */
MUX_VAL(CP(UART3_RX_IRRX), (IEN | PTD | EN | M7)); /*UART3_RX_IRRX*/
MUX_VAL(CP(UART3_TX_IRTX), (IEN | PTD | EN | M7)); /*UART3_TX_IRTX*/
+#if 0
MUX_VAL(CP(HSUSB0_CLK), (IEN | PTD | EN | M7)); /*HSUSB0_CLK*/
MUX_VAL(CP(HSUSB0_STP), (IEN | PTD | EN | M7)); /*HSUSB0_STP*/
MUX_VAL(CP(HSUSB0_DIR), (IEN | PTD | EN | M7)); /*HSUSB0_DIR*/
@@ -1185,6 +1195,7 @@ void set_muxconf_regs(void)
MUX_VAL(CP(HSUSB0_DATA5), (IEN | PTD | EN | M7)); /*HSUSB0_DATA5*/
MUX_VAL(CP(HSUSB0_DATA6), (IEN | PTD | EN | M7)); /*HSUSB0_DATA6*/
MUX_VAL(CP(HSUSB0_DATA7), (IEN | PTD | EN | M7)); /*HSUSB0_DATA7*/
+#endif
#else
MUX_VAL(CP(MCBSP4_CLKX), (IDIS | PTD | DIS | M4)); /*GPIO_152*/
/* - LCD_INI*/
@@ -1207,6 +1218,7 @@ void set_muxconf_regs(void)
MUX_VAL(CP(UART3_RTS_SD), (IDIS | PTD | DIS | M0)); /*UART3_RTS_SD */
MUX_VAL(CP(UART3_RX_IRRX), (IEN | PTD | DIS | M0)); /*UART3_RX_IRRX*/
MUX_VAL(CP(UART3_TX_IRTX), (IDIS | PTD | DIS | M0)); /*UART3_TX_IRTX*/
+#endif
MUX_VAL(CP(HSUSB0_CLK), (IEN | PTD | DIS | M0)); /*HSUSB0_CLK*/
MUX_VAL(CP(HSUSB0_STP), (IDIS | PTU | EN | M0)); /*HSUSB0_STP*/
MUX_VAL(CP(HSUSB0_DIR), (IEN | PTD | DIS | M0)); /*HSUSB0_DIR*/
@@ -1219,7 +1231,7 @@ void set_muxconf_regs(void)
MUX_VAL(CP(HSUSB0_DATA5), (IEN | PTD | DIS | M0)); /*HSUSB0_DATA5*/
MUX_VAL(CP(HSUSB0_DATA6), (IEN | PTD | DIS | M0)); /*HSUSB0_DATA6*/
MUX_VAL(CP(HSUSB0_DATA7), (IEN | PTD | DIS | M0)); /*HSUSB0_DATA7*/
-#endif
+
MUX_VAL(CP(I2C1_SCL), (IEN | PTU | EN | M0)); /*I2C1_SCL*/
MUX_VAL(CP(I2C1_SDA), (IEN | PTU | EN | M0)); /*I2C1_SDA*/
#ifdef SAFE_MODE_PINS_5
diff --git a/board/ti/logic/prod-id/query.c b/board/ti/logic/prod-id/query.c
index 1429039220..69a2e2b3ca 100644
--- a/board/ti/logic/prod-id/query.c
+++ b/board/ti/logic/prod-id/query.c
@@ -21,7 +21,7 @@ int id_dict_find_key(struct id_cookie *cookie, id_keys_t key)
{
int err;
unsigned int size;
- id_keys_t d_key;
+ id_keys_t d_key = (id_keys_t)-1;
idenum_t type;
struct id_cookie d_cookie = *cookie;
struct id_cookie t_cookie;
diff --git a/common/Makefile b/common/Makefile
index f3ad4bdd63..bb23c0af00 100644
--- a/common/Makefile
+++ b/common/Makefile
@@ -90,6 +90,7 @@ COBJS-$(CONFIG_CMD_EEPROM) += cmd_eeprom.o
COBJS-$(CONFIG_CMD_ELF) += cmd_elf.o
COBJS-$(CONFIG_SYS_HUSH_PARSER) += cmd_exit.o
COBJS-$(CONFIG_CMD_EXT2) += cmd_ext2.o
+COBJS-$(CONFIG_CMD_FASTBOOT) += cmd_fastboot.o
COBJS-$(CONFIG_CMD_FAT) += cmd_fat.o
COBJS-$(CONFIG_CMD_FDC)$(CONFIG_CMD_FDOS) += cmd_fdc.o
COBJS-$(CONFIG_OF_LIBFDT) += cmd_fdt.o fdt_support.o
diff --git a/common/cmd_fastboot.c b/common/cmd_fastboot.c
new file mode 100644
index 0000000000..97d1c23217
--- /dev/null
+++ b/common/cmd_fastboot.c
@@ -0,0 +1,1114 @@
+/*
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * Author : Mohammed Afzal M A <afzal@ti.com>
+ *
+ * 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
+ *
+ *
+ * Fastboot is implemented using gadget stack, many of the ideas are
+ * derived from fastboot implemented in OmapZoom by
+ * Tom Rix <Tom.Rix@windriver.com>, and portion of the code has been
+ * ported from OmapZoom.
+ *
+ * Part of OmapZoom was copied from Android project, Android source
+ * (legacy bootloader) was used indirectly here by using OmapZoom.
+ *
+ * This is Android's Copyright:
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <common.h>
+#include <command.h>
+#include <fastboot.h>
+#include <asm/sizes.h>
+#include <jffs2/load_kernel.h>
+
+#define ERR
+#define WARN
+#define INFO
+//#define DEBUG
+
+void output_lcd_string(char *p);
+
+#ifdef DEBUG
+#define FBTDBG(fmt,args...)\
+ printf("DEBUG: [%s]: %d: \n"fmt, __FUNCTION__, __LINE__,##args)
+#else
+#define FBTDBG(fmt,args...) do{}while(0)
+#endif
+
+#ifdef INFO
+#define FBTINFO(fmt,args...)\
+ printf("INFO: [%s]: "fmt, __FUNCTION__, ##args)
+#else
+#define FBTINFO(fmt,args...) do{}while(0)
+#endif
+
+#ifdef WARN
+#define FBTWARN(fmt,args...)\
+ printf("WARNING: [%s]: "fmt, __FUNCTION__, ##args)
+#else
+#define FBTWARN(fmt,args...) do{}while(0)
+#endif
+
+#ifdef ERR
+#define FBTERR(fmt,args...)\
+ printf("ERROR: [%s]: "fmt, __FUNCTION__, ##args)
+#else
+#define FBTERR(fmt,args...) do{}while(0)
+#endif
+
+#ifdef FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING
+#include <nand.h>
+#include <environment.h>
+#endif
+
+/* USB specific */
+
+#include <usb_defs.h>
+
+#if defined(CONFIG_PPC)
+#include <usb/mpc8xx_udc.h>
+#elif defined(CONFIG_OMAP1510)
+#include <usb/omap1510_udc.h>
+#elif defined(CONFIG_MUSB_UDC)
+#include <usb/musb_udc.h>
+#elif defined(CONFIG_PXA27X)
+#include <usb/pxa27x_udc.h>
+#elif defined(CONFIG_SPEAR3XX) || defined(CONFIG_SPEAR600)
+#include <usb/spr_udc.h>
+#endif
+
+#define STR_LANG 0x00
+#define STR_MANUFACTURER 0x01
+#define STR_PRODUCT 0x02
+#define STR_SERIAL 0x03
+#define STR_CONFIGURATION 0x04
+#define STR_INTERFACE 0x05
+#define STR_COUNT 0x06
+
+#define CONFIG_USBD_CONFIGURATION_STR "Android Fastboot Configuration"
+#define CONFIG_USBD_INTERFACE_STR "Android Fastboot Interface"
+
+#define USBFBT_BCD_DEVICE 0x00
+#define USBFBT_MAXPOWER 0x32
+
+#define NUM_CONFIGS 1
+#define NUM_INTERFACES 1
+#define NUM_ENDPOINTS 2
+
+#define RX_EP_INDEX 1
+#define TX_EP_INDEX 2
+
+struct _fbt_config_desc {
+ struct usb_configuration_descriptor configuration_desc;
+ struct usb_interface_descriptor interface_desc;
+ struct usb_endpoint_descriptor endpoint_desc[NUM_ENDPOINTS];
+};
+
+static int fbt_handle_response(void);
+
+/* defined and used by gadget/ep0.c */
+extern struct usb_string_descriptor **usb_strings;
+
+static struct cmd_fastboot_interface priv;
+
+/* USB Descriptor Strings */
+static char serial_number[28]; /* what should be the length ?, 28 ? */
+static char product_name[32];
+static u8 wstr_lang[4] = {4,USB_DT_STRING,0x9,0x4};
+static u8 wstr_manufacturer[2 + 2*(sizeof(CONFIG_USBD_MANUFACTURER)-1)];
+static u8 wstr_product[2 + 2*(sizeof(product_name) - 1)];
+static u8 wstr_serial[2 + 2*(sizeof(serial_number) - 1)];
+static u8 wstr_configuration[2 + 2*(sizeof(CONFIG_USBD_CONFIGURATION_STR)-1)];
+static u8 wstr_interface[2 + 2*(sizeof(CONFIG_USBD_INTERFACE_STR)-1)];
+
+/* USB descriptors */
+static struct usb_device_descriptor device_descriptor = {
+ .bLength = sizeof(struct usb_device_descriptor),
+ .bDescriptorType = USB_DT_DEVICE,
+ .bcdUSB = cpu_to_le16(USB_BCD_VERSION),
+ .bDeviceClass = 0xFF,
+ .bDeviceSubClass = 0x00,
+ .bDeviceProtocol = 0x00,
+ .bMaxPacketSize0 = EP0_MAX_PACKET_SIZE,
+ .idVendor = cpu_to_le16(CONFIG_USBD_VENDORID),
+ .bcdDevice = cpu_to_le16(USBFBT_BCD_DEVICE),
+ .iManufacturer = STR_MANUFACTURER,
+ .iProduct = STR_PRODUCT,
+ .iSerialNumber = STR_SERIAL,
+ .bNumConfigurations = NUM_CONFIGS
+};
+
+static struct _fbt_config_desc fbt_config_desc = {
+ .configuration_desc = {
+ .bLength = sizeof(struct usb_configuration_descriptor),
+ .bDescriptorType = USB_DT_CONFIG,
+ .wTotalLength = cpu_to_le16(sizeof(struct _fbt_config_desc)),
+ .bNumInterfaces = NUM_INTERFACES,
+ .bConfigurationValue = 1,
+ .iConfiguration = STR_CONFIGURATION,
+ .bmAttributes = BMATTRIBUTE_SELF_POWERED | BMATTRIBUTE_RESERVED,
+ .bMaxPower = USBFBT_MAXPOWER,
+ },
+ .interface_desc = {
+ .bLength = sizeof(struct usb_interface_descriptor),
+ .bDescriptorType = USB_DT_INTERFACE,
+ .bInterfaceNumber = 0,
+ .bAlternateSetting = 0,
+ .bNumEndpoints = 0x2,
+ .bInterfaceClass = FASTBOOT_INTERFACE_CLASS,
+ .bInterfaceSubClass = FASTBOOT_INTERFACE_SUB_CLASS,
+ .bInterfaceProtocol = FASTBOOT_INTERFACE_PROTOCOL,
+ .iInterface = STR_INTERFACE,
+ },
+ .endpoint_desc = {
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ /* XXX: can't the address start from 0x1, currently
+ seeing problem with "epinfo" */
+ .bEndpointAddress = RX_EP_INDEX | USB_DIR_OUT,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .bInterval = 0xFF,
+ },
+ {
+ .bLength = sizeof(struct usb_endpoint_descriptor),
+ .bDescriptorType = USB_DT_ENDPOINT,
+ /* XXX: can't the address start from 0x1, currently
+ seeing problem with "epinfo" */
+ .bEndpointAddress = TX_EP_INDEX | USB_DIR_IN,
+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
+ .bInterval = 0xFF,
+ },
+ },
+};
+
+static struct usb_interface_descriptor interface_descriptors[NUM_INTERFACES];
+static struct usb_endpoint_descriptor *ep_descriptor_ptrs[NUM_ENDPOINTS];
+
+static struct usb_string_descriptor *fbt_string_table[STR_COUNT];
+static struct usb_device_instance device_instance[1];
+static struct usb_bus_instance bus_instance[1];
+static struct usb_configuration_instance config_instance[NUM_CONFIGS];
+static struct usb_interface_instance interface_instance[NUM_INTERFACES];
+static struct usb_alternate_instance alternate_instance[NUM_INTERFACES];
+static struct usb_endpoint_instance endpoint_instance[NUM_ENDPOINTS + 1];
+
+/* FASBOOT specific */
+
+#define GETVARLEN 30
+#define SECURE "no"
+
+/* U-boot version */
+extern char version_string[];
+
+static struct cmd_fastboot_interface priv =
+{
+ .transfer_buffer = (void *)CONFIG_FASTBOOT_TRANSFER_BUFFER,
+ .transfer_buffer_size = CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE,
+};
+
+static int fbt_init_endpoints (void);
+
+#ifdef FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING
+/* Use do_bootm and do_go for fastboot's 'boot' command */
+extern int do_go (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+/* Use do_env_set and do_env_save to permenantly save data */
+extern int do_env_save (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+extern int do_env_set ( cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+extern int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
+extern int do_flerase (cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+#endif /* FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING */
+
+static int fbt_lastidle;
+
+static void fbt_pokeidle(void)
+{
+ fbt_lastidle = get_ticks();
+}
+
+static int fbt_getidle(void)
+{
+ return get_ticks() - fbt_lastidle;
+}
+
+/* USB specific */
+
+/* utility function for converting char* to wide string used by USB */
+static void str2wide (char *str, u16 * wide)
+{
+ int i;
+ for (i = 0; i < strlen (str) && str[i]; i++){
+ #if defined(__LITTLE_ENDIAN)
+ wide[i] = (u16) str[i];
+ #elif defined(__BIG_ENDIAN)
+ wide[i] = ((u16)(str[i])<<8);
+ #else
+ #error "__LITTLE_ENDIAN or __BIG_ENDIAN undefined"
+ #endif
+ }
+}
+
+/* fastboot_init has to be called before this fn to get correct serial string */
+static int fbt_init_strings(void)
+{
+ struct usb_string_descriptor *string;
+ const char *model = getenv("logic_model");
+ fbt_string_table[STR_LANG] =
+ (struct usb_string_descriptor*)wstr_lang;
+
+ string = (struct usb_string_descriptor *) wstr_manufacturer;
+ string->bLength = sizeof(wstr_manufacturer);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_MANUFACTURER, string->wData);
+ fbt_string_table[STR_MANUFACTURER] = string;
+
+ string = (struct usb_string_descriptor *) wstr_product;
+ string->bLength = sizeof(wstr_product);
+ string->bDescriptorType = USB_DT_STRING;
+
+ if(model)
+ {
+ strncpy (product_name, model, sizeof(product_name));
+ } else {
+ // Otherwise, populate generically.
+ strncpy (product_name, "LogicPD SOM", sizeof(product_name));
+ }
+ product_name[sizeof(product_name)-1] = '\0';
+ str2wide (product_name, string->wData);
+ fbt_string_table[STR_PRODUCT] = string;
+
+ string = (struct usb_string_descriptor *) wstr_serial;
+ string->bLength = sizeof(wstr_serial);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (serial_number, string->wData);
+ fbt_string_table[STR_SERIAL] = string;
+
+ string = (struct usb_string_descriptor *) wstr_configuration;
+ string->bLength = sizeof(wstr_configuration);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_CONFIGURATION_STR, string->wData);
+ fbt_string_table[STR_CONFIGURATION] = string;
+
+ string = (struct usb_string_descriptor *) wstr_interface;
+ string->bLength = sizeof(wstr_interface);
+ string->bDescriptorType = USB_DT_STRING;
+ str2wide (CONFIG_USBD_INTERFACE_STR, string->wData);
+ fbt_string_table[STR_INTERFACE] = string;
+
+ /* Now, initialize the string table for ep0 handling */
+ usb_strings = fbt_string_table;
+
+ return 0;
+}
+
+static void fbt_event_handler (struct usb_device_instance *device,
+ usb_device_event_t event, int data)
+{
+ switch (event) {
+ case DEVICE_RESET:
+ case DEVICE_BUS_INACTIVE:
+ output_lcd_string("/pAA/kFastboot is waiting for connection from PC/pBA/k/pCA/k");
+
+ priv.configured = 0;
+
+ // Clear active transfers and flags.
+ priv.flag = 0;
+ priv.d_size = 0;
+ priv.d_bytes = 0;
+ priv.u_size = 0;
+ priv.u_bytes = 0;
+ break;
+ case DEVICE_CONFIGURED:
+ priv.configured = 1;
+ break;
+
+ case DEVICE_ADDRESS_ASSIGNED:
+ output_lcd_string("/pAA/kFastboot is connected to PC");
+
+ fbt_init_endpoints ();
+
+ default:
+ break;
+ }
+}
+
+/* fastboot_init has to be called before this fn to get correct serial string */
+static int fbt_init_instances(void)
+{
+ int i;
+
+ /* initialize device instance */
+ memset (device_instance, 0, sizeof (struct usb_device_instance));
+ device_instance->device_state = STATE_INIT;
+ device_instance->device_descriptor = &device_descriptor;
+ device_instance->event = fbt_event_handler;
+ device_instance->cdc_recv_setup = NULL;
+ device_instance->bus = bus_instance;
+ device_instance->configurations = NUM_CONFIGS;
+ device_instance->configuration_instance_array = config_instance;
+
+ /* XXX: what is this bus instance for ?, can't it be removed by moving
+ endpoint_array and serial_number_str is moved to device instance */
+ /* initialize bus instance */
+ memset (bus_instance, 0, sizeof (struct usb_bus_instance));
+ bus_instance->device = device_instance;
+ bus_instance->endpoint_array = endpoint_instance;
+ /* XXX: what is the relevance of max_endpoints & maxpacketsize ? */
+ bus_instance->max_endpoints = 1;
+ bus_instance->maxpacketsize = 64;
+ bus_instance->serial_number_str = serial_number;
+
+ /* configuration instance */
+ memset (config_instance, 0,
+ sizeof (struct usb_configuration_instance));
+ config_instance->interfaces = NUM_INTERFACES;
+ config_instance->configuration_descriptor =
+ (struct usb_configuration_descriptor *)&fbt_config_desc;
+ config_instance->interface_instance_array = interface_instance;
+
+ /* XXX: is alternate instance required in case of no alternate ? */
+ /* interface instance */
+ memset (interface_instance, 0,
+ sizeof (struct usb_interface_instance));
+ interface_instance->alternates = 1;
+ interface_instance->alternates_instance_array = alternate_instance;
+
+ /* alternates instance */
+ memset (alternate_instance, 0,
+ sizeof (struct usb_alternate_instance));
+ alternate_instance->interface_descriptor = interface_descriptors;
+ alternate_instance->endpoints = NUM_ENDPOINTS;
+ alternate_instance->endpoints_descriptor_array = ep_descriptor_ptrs;
+
+ /* endpoint instances */
+ memset (&endpoint_instance[0], 0,
+ sizeof (struct usb_endpoint_instance));
+ endpoint_instance[0].endpoint_address = 0;
+ endpoint_instance[0].rcv_packetSize = EP0_MAX_PACKET_SIZE;
+ endpoint_instance[0].rcv_attributes = USB_ENDPOINT_XFER_CONTROL;
+ endpoint_instance[0].tx_packetSize = EP0_MAX_PACKET_SIZE;
+ endpoint_instance[0].tx_attributes = USB_ENDPOINT_XFER_CONTROL;
+ /* XXX: following statement to done along with other endpoints
+ at another place ? */
+ udc_setup_ep (device_instance, 0, &endpoint_instance[0]);
+
+ for (i = 1; i <= NUM_ENDPOINTS; i++) {
+ memset (&endpoint_instance[i], 0,
+ sizeof (struct usb_endpoint_instance));
+
+ endpoint_instance[i].endpoint_address =
+ ep_descriptor_ptrs[i - 1]->bEndpointAddress;
+
+ endpoint_instance[i].rcv_attributes =
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+ endpoint_instance[i].rcv_packetSize =
+ le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+
+ endpoint_instance[i].tx_attributes =
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+ endpoint_instance[i].tx_packetSize =
+ le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+
+ endpoint_instance[i].tx_attributes =
+ ep_descriptor_ptrs[i - 1]->bmAttributes;
+
+ urb_link_init (&endpoint_instance[i].rcv);
+ urb_link_init (&endpoint_instance[i].rdy);
+ urb_link_init (&endpoint_instance[i].tx);
+ urb_link_init (&endpoint_instance[i].done);
+
+ if (endpoint_instance[i].endpoint_address & USB_DIR_IN)
+ endpoint_instance[i].tx_urb =
+ usbd_alloc_urb (device_instance,
+ &endpoint_instance[i]);
+ else
+ endpoint_instance[i].rcv_urb =
+ usbd_alloc_urb (device_instance,
+ &endpoint_instance[i]);
+ }
+
+ return 0;
+}
+
+/* XXX: ep_descriptor_ptrs can be removed by making better use of
+ fbt_config_desc.endpoint_desc */
+static int fbt_init_endpoint_ptrs(void)
+{
+ ep_descriptor_ptrs[0] = &fbt_config_desc.endpoint_desc[0];
+ ep_descriptor_ptrs[1] = &fbt_config_desc.endpoint_desc[1];
+
+ return 0;
+}
+
+static int fbt_init_endpoints(void)
+{
+ int i;
+
+ /* XXX: should it be moved to some other function ? */
+ bus_instance->max_endpoints = NUM_ENDPOINTS + 1;
+
+ /* XXX: is this for loop required ?, yes for MUSB it is */
+ for (i = 1; i <= NUM_ENDPOINTS; i++) {
+
+ /* configure packetsize based on HS negotiation status */
+ if (device_instance->speed == USB_SPEED_FULL) {
+ FBTINFO("setting up FS USB device ep%x\n",
+ endpoint_instance[i].endpoint_address);
+ ep_descriptor_ptrs[i - 1]->wMaxPacketSize =
+ CONFIG_USBD_FASTBOOT_BULK_PKTSIZE_FS;
+ } else if (device_instance->speed == USB_SPEED_HIGH) {
+ FBTINFO("setting up HS USB device ep%x\n",
+ endpoint_instance[i].endpoint_address);
+ ep_descriptor_ptrs[i - 1]->wMaxPacketSize =
+ CONFIG_USBD_FASTBOOT_BULK_PKTSIZE_HS;
+ }
+
+ endpoint_instance[i].tx_packetSize =
+ le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+ endpoint_instance[i].rcv_packetSize =
+ le16_to_cpu(ep_descriptor_ptrs[i - 1]->wMaxPacketSize);
+
+ udc_setup_ep (device_instance, i, &endpoint_instance[i]);
+
+ }
+
+ return 0;
+}
+
+static struct urb *next_urb (struct usb_device_instance *device,
+ struct usb_endpoint_instance *endpoint)
+{
+ struct urb *current_urb = NULL;
+ int space;
+
+ /* If there's a queue, then we should add to the last urb */
+ if (!endpoint->tx_queue) {
+ current_urb = endpoint->tx_urb;
+ } else {
+ /* Last urb from tx chain */
+ current_urb =
+ p2surround (struct urb, link, endpoint->tx.prev);
+ }
+
+ /* Make sure this one has enough room */
+ space = current_urb->buffer_length - current_urb->actual_length;
+ if (space > 0) {
+ return current_urb;
+ } else { /* No space here */
+ /* First look at done list */
+ current_urb = first_urb_detached (&endpoint->done);
+ if (!current_urb) {
+ current_urb = usbd_alloc_urb (device, endpoint);
+ }
+
+ urb_append (&endpoint->tx, current_urb);
+ endpoint->tx_queue++;
+ }
+ return current_urb;
+}
+
+/* FASBOOT specific */
+static void set_env(char *var, char *val)
+{
+ char *setenv[4] = { "setenv", NULL, NULL, NULL, };
+
+ setenv[1] = var;
+ setenv[2] = val;
+
+ do_env_set(NULL, 0, 3, setenv);
+}
+
+int do_lcd_percent (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[]);
+
+void set_lcd_percent_string(char *string)
+{
+ char *lcd_percent[] = { "lcd_percent", string};
+
+ do_lcd_percent (NULL, 0, ARRAY_SIZE(lcd_percent), lcd_percent);
+}
+
+static void set_serial_number(void)
+{
+ char *dieid = getenv("logic_serial");
+ if (dieid == NULL) {
+ priv.serial_no = "00123";
+ } else {
+ int len;
+
+ memset(&serial_number[0], 0, 28);
+ len = strlen(dieid);
+ if (len > 28)
+ len = 26;
+
+ strncpy(&serial_number[0], dieid, len);
+
+ priv.serial_no = &serial_number[0];
+ }
+}
+
+static int fbt_fastboot_init(void)
+{
+ priv.flag = 0;
+ priv.d_size = 0;
+ priv.d_bytes = 0;
+ priv.u_size = 0;
+ priv.u_bytes = 0;
+ priv.exit = 0;
+
+ priv.product_name = FASTBOOT_PRODUCT_NAME;
+ set_serial_number();
+
+ return 0;
+}
+
+#ifdef FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING
+
+static int get_part_size(const char *partname, u8 *dev_type)
+{
+#ifdef CONFIG_CMD_MTDPARTS
+ struct mtd_device *dev;
+ struct part_info *part;
+ u8 pnum;
+ int ret;
+
+ ret = mtdparts_init();
+ if (ret)
+ return ret;
+
+ ret = find_dev_and_part(partname, &dev, &pnum, &part, 0);
+ if (ret)
+ return ret;
+
+ if(dev_type)
+ *dev_type = dev->id->type;
+
+ return part->size;
+#else
+ return 0;
+#endif
+}
+
+static int fbt_nandpart_erase(char *part)
+{
+ char *erase[] = { "nand", "erase.part", part};
+ return do_nand(NULL, 0, ARRAY_SIZE(erase), erase);
+}
+
+static int fbt_nandpart_write(char *part, void *address, int size)
+{
+ char addr_str[32], size_str[32];
+ char *write[] = { "nand", "write.auto", addr_str, part, size_str };
+
+ // Prep command line arguments
+ sprintf(addr_str, "0x%x", (unsigned int)address);
+ sprintf(size_str, "0x%x", size);
+
+ return do_nand(NULL, 0, ARRAY_SIZE(write), write);
+}
+
+static int fbt_handle_erase(char *cmdbuf)
+{
+ int status;
+
+ if((status = fbt_nandpart_erase(cmdbuf + 6)))
+ sprintf(priv.response, "FAILfailed to erase partition");
+ else
+ sprintf(priv.response, "OKAY");
+ return status;
+}
+
+static int fbt_handle_flash(char *cmdbuf)
+{
+ int status = 0;
+
+ if (priv.d_bytes) {
+ u8 dev_type = 0;
+ char *part = cmdbuf + 6;
+ int size = get_part_size(part, &dev_type);
+
+ if(size < 0)
+ {
+ sprintf(priv.response, "FAILpartition does not exist");
+ return status;
+ } else if(priv.d_bytes > size)
+ {
+ sprintf(priv.response, "FAILimage too large for partition");
+ return status;
+ }
+
+ FBTINFO("Flashing '%s'\n", part);
+ switch(dev_type)
+ {
+ case MTD_DEV_TYPE_NOR:
+ FBTINFO("Fastboot currently doesn't support NOR\n");
+ sprintf(priv.response, "FAILUnsupported partition type (nor)");
+ return 1;
+ break;
+ case MTD_DEV_TYPE_NAND:
+ if(fbt_nandpart_erase(part) ||
+ fbt_nandpart_write(part, priv.transfer_buffer, priv.d_bytes))
+ {
+ FBTINFO("Failed flashing '%s'\n", part);
+ sprintf(priv.response, "FAILFailed erasing or writing partition");
+ return 1;
+ }
+ break;
+ case MTD_DEV_TYPE_ONENAND:
+ FBTINFO("Fastboot currently doesn't support ONENAND.\n");
+ sprintf(priv.response, "FAILUnsupported partition type (onenand)");
+ return 1;
+ }
+ FBTINFO("Done flashing '%s'\n", part);
+ sprintf(priv.response, "OKAY");
+ } else {
+ sprintf(priv.response, "FAILno image downloaded");
+ }
+
+ return status;
+}
+#endif /* FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING */
+
+
+static int fbt_handle_getvar(char *cmdbuf)
+{
+ strcpy(priv.response, "OKAY");
+ if(!strcmp(cmdbuf + strlen("getvar:"), "version")) {
+ FBTDBG("getvar version\n");
+ strcpy(priv.response + 4, FASTBOOT_VERSION);
+ } else if(!strcmp(cmdbuf + strlen("getvar:"), "version-bootloader")) {
+ strncpy(priv.response + 4, version_string,
+ min(strlen(version_string), GETVARLEN));
+ } else if(!strcmp(cmdbuf + strlen("getvar:"), "secure")) {
+ strcpy(priv.response + 4, SECURE);
+ } else if(!strcmp(cmdbuf + strlen("getvar:"), "product")) {
+ if (priv.product_name)
+ strcpy(priv.response + 4, priv.product_name);
+ } else if(!strcmp(cmdbuf + strlen("getvar:"), "serialno")) {
+ if (priv.serial_no)
+ strcpy(priv.response + 4, priv.serial_no);
+ }
+ return 0;
+}
+
+static int fbt_handle_reboot(char *cmdbuf)
+{
+ strcpy(priv.response,"OKAY");
+ priv.flag |= FASTBOOT_FLAG_RESPONSE;
+ fbt_handle_response();
+ udelay (1000000); /* 1 sec */
+
+ do_reset (NULL, 0, 0, NULL);
+
+ return 0;
+}
+
+static int fbt_handle_boot(char *cmdbuf)
+{
+ if ((priv.d_bytes) &&
+ (CONFIG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE < priv.d_bytes)) {
+ char start[32];
+ char *bootm[3] = { "bootm", NULL, NULL, };
+ char *go[3] = { "go", NULL, NULL, };
+
+ /*
+ * Use this later to determine if a command line was passed
+ * for the kernel.
+ */
+ struct fastboot_boot_img_hdr *fb_hdr =
+ (struct fastboot_boot_img_hdr *) priv.transfer_buffer;
+
+ /* Skip the mkbootimage header */
+ image_header_t *hdr = (image_header_t *)
+ &priv.transfer_buffer[CONFIG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE];
+
+ bootm[1] = go[1] = start;
+ sprintf (start, "0x%x", (unsigned int)hdr);
+
+ /* Execution should jump to kernel so send the response
+ now and wait a bit. */
+ sprintf(priv.response, "OKAY");
+ priv.flag |= FASTBOOT_FLAG_RESPONSE;
+ fbt_handle_response();
+ output_lcd_string("/pCA/k/pBA/kFastboot is booting uploaded image");
+ udelay (1000000); /* 1 sec */
+ udc_disconnect();
+
+ if (ntohl(hdr->ih_magic) == IH_MAGIC) {
+ /* Looks like a kernel.. */
+ FBTINFO("Booting kernel..\n");
+
+ /*
+ * Check if the user sent a bootargs down.
+ * If not, do not override what is already there
+ */
+ if (strlen ((char *) &fb_hdr->cmdline[0]))
+ set_env ("bootargs", (char *) &fb_hdr->cmdline[0]);
+
+ do_bootm (NULL, 0, 2, bootm);
+ } else {
+ /* Raw image, maybe another uboot */
+ FBTINFO("Booting raw image..\n");
+
+ do_go (NULL, 0, 2, go);
+ }
+
+ FBTERR("booting failed, reset the board\n");
+ }
+ sprintf(priv.response, "FAILinvalid boot image");
+
+ return 0;
+}
+
+/* XXX: Replace magic number & strings with macros */
+static int fbt_rx_process(unsigned char *buffer, int length)
+{
+ /* Generic failed response */
+ strcpy(priv.response, "FAIL");
+
+ if (!priv.d_size) {
+ /* command */
+ char *cmdbuf = (char *) buffer;
+
+ FBTDBG("command\n");
+ output_lcd_string("/pCA/k/pBA/kFastboot is processing command ");
+ output_lcd_string(cmdbuf);
+
+ set_lcd_percent_string("");
+
+ if(memcmp(cmdbuf, "getvar:", 7) == 0) {
+ FBTDBG("getvar\n");
+ fbt_handle_getvar(cmdbuf);
+ }
+
+ if(memcmp(cmdbuf, "erase:", 6) == 0) {
+ FBTDBG("erase\n");
+ set_lcd_percent_string("/pCA/kErasing is /P% done");
+ fbt_handle_erase(cmdbuf);
+ }
+
+ if(memcmp(cmdbuf, "flash:", 6) == 0) {
+ FBTDBG("flash\n");
+ set_lcd_percent_string("/pCA/kFlashing is /P% done");
+ fbt_handle_flash(cmdbuf);
+ }
+
+ if((memcmp(cmdbuf, "reboot", 6) == 0) ||
+ (memcmp(cmdbuf, "reboot-bootloader", 17) == 0)) {
+ FBTDBG("reboot/reboot-bootloader\n");
+ fbt_handle_reboot(cmdbuf);
+ }
+
+ if(memcmp(cmdbuf, "continue", 8) == 0) {
+ FBTDBG("continue\n");
+ strcpy(priv.response,"OKAY");
+ priv.exit = 1;
+ }
+
+ if(memcmp(cmdbuf, "boot", 4) == 0) {
+ FBTDBG("boot\n");
+ output_lcd_string("/pAA/kFastboot is continuing boot (timeout)/pBA/k/pCA/k");
+ fbt_handle_boot(cmdbuf);
+ }
+
+ if(memcmp(cmdbuf, "download:", 9) == 0) {
+ FBTDBG("download\n");
+
+ /* XXX: need any check for size & bytes ? */
+ priv.d_size =
+ simple_strtoul (cmdbuf + 9, NULL, 16);
+ priv.d_bytes = 0;
+
+ FBTINFO ("starting download of %d bytes\n",
+ priv.d_size);
+
+ if (priv.d_size == 0) {
+ strcpy(priv.response, "FAILdata invalid size");
+ } else if (priv.d_size >
+ priv.transfer_buffer_size) {
+ priv.d_size = 0;
+ strcpy(priv.response, "FAILdata too large");
+ } else {
+ sprintf(priv.response, "DATA%08x", priv.d_size);
+ }
+
+ set_lcd_percent_string("/pCA/kDownload /P% done");
+ lcd_percent_init(priv.d_size);
+ }
+
+ if((memcmp(cmdbuf, "upload:", 7) == 0) ||
+ (memcmp(cmdbuf, "uploadraw", 10) == 0)) {
+ FBTDBG("upload/uploadraw\n");
+
+ set_lcd_percent_string("/pCA/kUpload /P% done");
+ sprintf(priv.response, "FAILUpload not supported");
+ }
+ priv.flag |= FASTBOOT_FLAG_RESPONSE;
+ } else {
+ if (length) {
+ unsigned int xfr_size;
+
+ xfr_size = priv.d_size - priv.d_bytes;
+ if (xfr_size > length)
+ xfr_size = length;
+ memcpy(priv.transfer_buffer + priv.d_bytes,
+ buffer, xfr_size);
+ priv.d_bytes += xfr_size;
+
+ lcd_percent_update(priv.d_bytes);
+
+#ifdef INFO
+ /* Inform via prompt that download is happening */
+ if (! (priv.d_bytes % (16 * 0x1000)))
+ printf(".");
+ if (! (priv.d_bytes % (80 * 16 * 0x1000)))
+ printf("\n");
+#endif
+ if (priv.d_bytes >= priv.d_size) {
+ priv.d_size = 0;
+ strcpy(priv.response, "OKAY");
+ priv.flag |= FASTBOOT_FLAG_RESPONSE;
+#ifdef INFO
+ printf(".\n");
+#endif
+ FBTINFO("downloaded %d bytes\n", priv.d_bytes);
+ }
+ } else
+ FBTWARN("empty buffer download\n");
+ }
+
+ return 0;
+}
+
+static int fbt_handle_rx(void)
+{
+ struct usb_endpoint_instance *ep = &endpoint_instance[RX_EP_INDEX];
+
+ /* XXX: Or update status field, if so,
+ "usbd_rcv_complete" [gadget/core.c] also need to be modified */
+ if (ep->rcv_urb->actual_length) {
+ FBTDBG("rx length: %u\n", ep->rcv_urb->actual_length);
+ fbt_rx_process(ep->rcv_urb->buffer, ep->rcv_urb->actual_length);
+ /* Required to poison rx urb buffer as in omapzoom ?,
+ yes, as fastboot command are sent w/o NULL termination.
+ Attempt is made here to reduce poison length, may be safer
+ to posion the whole buffer, also it is assumed that at
+ the time of creation of urb it is poisoned */
+ memset(ep->rcv_urb->buffer, 0, ep->rcv_urb->actual_length);
+ ep->rcv_urb->actual_length = 0;
+ }
+
+ return 0;
+}
+
+static int fbt_response_process(void)
+{
+ struct usb_endpoint_instance *ep = &endpoint_instance[TX_EP_INDEX];
+ struct urb *current_urb = NULL;
+ unsigned char *dest = NULL;
+ int n, ret = 0;
+
+ current_urb = next_urb (device_instance, ep);
+ if (!current_urb) {
+ FBTERR("%s: current_urb NULL", __func__);
+ return -1;
+ }
+
+ dest = current_urb->buffer + current_urb->actual_length;
+ n = MIN (64, strlen(priv.response));
+ memcpy(dest, priv.response, n);
+ current_urb->actual_length += n;
+ FBTDBG("response urb length: %u\n", current_urb->actual_length);
+ if (ep->last == 0) {
+ ret = udc_endpoint_write (ep);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int fbt_handle_response(void)
+{
+ if (priv.flag & FASTBOOT_FLAG_RESPONSE) {
+ if(!strncmp(priv.response, "FAIL", 4))
+ {
+ output_lcd_string("/pCA/kCommand failed");
+ } else
+ if(!strncmp(priv.response, "OKAY", 4))
+ {
+ output_lcd_string("/pCA/k/pBA/kFastboot is idle");
+ }
+ fbt_response_process();
+ priv.flag &= ~FASTBOOT_FLAG_RESPONSE;
+ }
+
+ return 0;
+}
+
+static int fbt_tx_process(void)
+{
+ struct usb_endpoint_instance *ep = &endpoint_instance[TX_EP_INDEX];
+ struct urb *current_urb = NULL;
+ unsigned char *dest = NULL;
+ int n = 0, ret = 0;
+
+ current_urb = next_urb (device_instance, ep);
+ if (!current_urb) {
+ FBTERR("%s: current_urb NULL", __func__);
+ return -1;
+ }
+
+ dest = current_urb->buffer + current_urb->actual_length;
+ n = MIN (64, priv.u_size - priv.u_bytes);
+ memcpy(dest, priv.transfer_buffer + priv.u_bytes, n);
+ current_urb->actual_length += n;
+ if (ep->last == 0) {
+ ret = udc_endpoint_write (ep);
+ /* XXX: "ret = n" should be done iff n bytes has been
+ * transmitted, "udc_endpoint_write" to be changed for it,
+ * now it always return 0.
+ */
+ return n;
+ }
+
+ return ret;
+}
+
+static int fbt_handle_tx(void)
+{
+ if (priv.u_size) {
+ int bytes_written = fbt_tx_process();
+
+ if (bytes_written > 0) {
+ /* XXX: is this the right way to update priv.u_bytes ?,
+ * may be "udc_endpoint_write()" can be modified to
+ * return number of bytes transmitted or error and
+ * update based on hence obtained value
+ */
+ priv.u_bytes += bytes_written;
+
+ lcd_percent_update(priv.u_bytes);
+#ifdef INFO
+ /* Inform via prompt that upload is happening */
+ if (! (priv.d_bytes % (16 * 0x1000)))
+ printf(".");
+ if (! (priv.d_bytes % (80 * 16 * 0x1000)))
+ printf("\n");
+#endif
+ if (priv.u_bytes >= priv.u_size)
+#ifdef INFO
+ printf(".\n");
+#endif
+ priv.u_size = priv.u_bytes = 0;
+ FBTINFO("data upload finished\n");
+ } else {
+ FBTERR("bytes_written: %d\n", bytes_written);
+ return -1;
+ }
+
+ }
+
+ return 0;
+}
+
+/* command */
+int do_fastboot(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int ret = -1;
+ int timeout = 0;
+
+ ret = fbt_fastboot_init();
+ ret = fbt_init_endpoint_ptrs();
+
+ if ((ret = udc_init()) < 0) {
+ FBTERR("%s: MUSB UDC init failure\n", __func__);
+ return ret;
+ }
+
+ ret = fbt_init_strings();
+ ret = fbt_init_instances();
+
+ udc_startup_events (device_instance);
+ udc_connect();
+
+ FBTINFO("fastboot initialized\n");
+ output_lcd_string("/pAA/kFastboot is waiting for connection from PC");
+
+ if(argc > 1)
+ {
+ timeout = simple_strtoul(argv[1], NULL, 10) * get_tbclk();
+ fbt_pokeidle();
+ }
+
+ while(1) {
+ udc_irq();
+ if (priv.configured) {
+ fbt_pokeidle();
+ fbt_handle_rx();
+ fbt_handle_response();
+ fbt_handle_tx();
+ }
+ priv.exit |= ctrlc();
+ if (priv.exit) {
+ output_lcd_string("/pAA/kFastboot is continuing boot/pBA/k/pCA/k");
+ set_lcd_percent_string("");
+ FBTINFO("fastboot end\n");
+ break;
+ }
+ if(timeout && fbt_getidle() > timeout)
+ {
+ output_lcd_string("/pAA/kFastboot is continuing boot (timeout)/pBA/k/pCA/k");
+ FBTINFO("Timed out\n");
+ break;
+ }
+ }
+
+ udc_disconnect();
+
+ return ret;
+}
+
+U_BOOT_CMD(fastboot, 2, 1, do_fastboot,
+ "fastboot [timeout in seconds] - use USB Fastboot protocol\n", NULL);
diff --git a/common/cmd_mtdparts.c b/common/cmd_mtdparts.c
index 32d6c899d1..a32762f5f2 100644
--- a/common/cmd_mtdparts.c
+++ b/common/cmd_mtdparts.c
@@ -132,6 +132,12 @@ static const char *const mtdids_default = MTDIDS_DEFAULT;
static const char *const mtdids_default = NULL;
#endif
+#if defined(MTDFLAGS_DEFAULT)
+staitc const char *const mtdflags_default = MTDFLAGS_DEFAULT;
+#else
+staitc const char *const mtdflags_default = NULL;
+#endif
+
#if defined(MTDPARTS_DEFAULT)
static const char *const mtdparts_default = MTDPARTS_DEFAULT;
#else
@@ -145,6 +151,10 @@ char *get_mtdids_default(void)
{
return (char *)mtdids_default;
}
+char *get_mtdflags_default(void)
+{
+ return (char *)mtdflags_default;
+}
#endif
/* copies of last seen 'mtdids', 'mtdparts' and 'partition' env variables */
@@ -153,7 +163,9 @@ char *get_mtdids_default(void)
#define PARTITION_MAXLEN 16
static char last_ids[MTDIDS_MAXLEN];
static char last_parts[MTDPARTS_MAXLEN];
+static char last_flags[MTDPARTS_MAXLEN];
static char last_partition[PARTITION_MAXLEN];
+static int mtdflags_defaultmask;
/* low level jffs2 cache cleaning routine */
extern void jffs2_free_cache(struct part_info *part);
@@ -173,6 +185,7 @@ static struct part_info* mtd_part_info(struct mtd_device *dev, unsigned int part
/* command line only routines */
static struct mtdids* id_find_by_mtd_id(const char *mtd_id, unsigned int mtd_id_len);
static int device_del(struct mtd_device *dev);
+static char *mtdflags_tostring(int flags, int parenth);
/**
* Parses a string into a number. The number stored at ptr is
@@ -1233,6 +1246,79 @@ static int generate_mtdparts_save(char *buf, u32 buflen)
return ret;
}
+/**
+ * Process all devices and generate corresponding mtdparts string describing
+ * all partitions on all devices.
+ *
+ * @param buf output buffer holding generated mtdparts string (output)
+ * @param buflen buffer size
+ * @return 0 on success, 1 otherwise
+ */
+static int generate_mtdflags(char *buf, u32 buflen)
+{
+ struct list_head *pentry, *dentry;
+ struct mtd_device *dev;
+ struct part_info *part;
+ char *p = buf;
+ u32 maxlen = buflen - 1;
+ int needs_semicolon=0;
+
+ debug("--- generate_mtdflags ---\n");
+
+ if (list_empty(&devices)) {
+ buf[0] = '\0';
+ return 0;
+ }
+
+ buf[0] = '\0';
+
+ if(mtdflags_defaultmask)
+ {
+ p = stpncpy(p, "default=", maxlen - (p - buf));
+ p = stpncpy(p, mtdflags_tostring(mtdflags_defaultmask, 0), maxlen - (p - buf));
+ needs_semicolon = 1;
+ }
+
+ list_for_each(dentry, &devices) {
+ dev = list_entry(dentry, struct mtd_device, link);
+ list_for_each(pentry, &dev->parts) {
+ part = list_entry(pentry, struct part_info, link);
+
+ if(part->mtdflags_mask)
+ {
+ // Append the name
+ if(needs_semicolon)
+ p = stpncpy(p, ";", maxlen - (p - buf));
+ p = stpncpy(p, part->name, maxlen - (p - buf));
+ p = stpncpy(p, "=", maxlen - (p - buf));
+ p = stpncpy(p, mtdflags_tostring(part->mtdflags_mask, 0), maxlen - (p - buf));
+ needs_semicolon=1;
+ }
+ }
+ }
+
+ /* we still have at least one char left, as we decremented maxlen at
+ * the begining */
+ *p = '\0';
+
+ return 0;
+}
+
+
+static int generate_mtdflags_save(char *buf, u32 buflen)
+{
+ int ret;
+
+ ret = generate_mtdflags(buf, buflen);
+
+ if ((buf[0] != '\0') && (ret == 0))
+ setenv("mtdflags", buf);
+ else
+ setenv("mtdflags", NULL);
+
+ return ret;
+}
+
#if defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES)
/**
* Get the net size (w/o bad blocks) of the given partition.
@@ -1277,7 +1363,7 @@ static void print_partition_table(void)
printf("\ndevice %s%d <%s>, # parts = %d\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num,
dev->id->mtd_id, dev->num_parts);
- printf(" #: name\t\tsize\t\tnet size\toffset\t\tmask_flags\n");
+ printf(" #: name\t\tsize\t\tnet size\toffset\t\tmask_flags\tnand_flags\n");
list_for_each(pentry, &dev->parts) {
u32 net_size;
@@ -1286,21 +1372,24 @@ 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%08x\t0x%08x%s\t0x%08x\t%d\t\t%s\n",
part_num, part->name, part->size,
net_size, size_note, part->offset,
- part->mask_flags);
+ part->mask_flags,
+ mtdflags_tostring(part->mtdflags_mask, 1)
+ );
#else /* !defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
printf("\ndevice %s%d <%s>, # parts = %d\n",
MTD_DEV_TYPE(dev->id->type), dev->id->num,
dev->id->mtd_id, dev->num_parts);
- printf(" #: name\t\tsize\t\toffset\t\tmask_flags\n");
+ printf(" #: name\t\tsize\t\toffset\t\tmask_flags\tnand_flags\n");
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%08x\t0x%08x\t%d\t\t%s\n",
part_num, part->name, part->size,
- part->offset, part->mask_flags);
+ part->offset, part->mask_flags,
+ mtdflags_tostring(part->mtdflags_mask, 1));
#endif /* defined(CONFIG_CMD_MTDPARTS_SHOW_NET_SIZES) */
part_num++;
}
@@ -1317,7 +1406,7 @@ static void print_partition_table(void)
static void list_partitions(void)
{
struct part_info *part;
- char *mtdids_default, *mtdparts_default;
+ char *mtdids_default, *mtdparts_default, *mtdflags_default;
debug("\n---list_partitions---\n");
print_partition_table();
@@ -1345,9 +1434,12 @@ static void list_partitions(void)
* printbuffer. Use puts() to prevent system crashes.
*/
mtdparts_default = get_mtdparts_default();
- puts("mtdparts: ");
- puts(mtdparts_default ? mtdparts_default : "none");
- puts("\n");
+ printf("mtdparts: %s\n",
+ mtdparts_default ? mtdparts_default : "none");
+
+ mtdflags_default = get_mtdflags_default();
+ printf("mtdflags: %s\n",
+ mtdflags_default ? mtdflags_default : "none");
}
/**
@@ -1432,6 +1524,7 @@ static int delete_partition(const char *id)
u8 pnum;
struct mtd_device *dev;
struct part_info *part;
+ int ret;
if (find_dev_and_part(id, &dev, &pnum, &part, 0) == 0) {
@@ -1443,10 +1536,14 @@ static int delete_partition(const char *id)
return 1;
if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ ret = 1;
printf("generated mtdparts too long, reseting to null\n");
- return 1;
}
- return 0;
+ if (generate_mtdflags_save(last_flags, ARRAY_SIZE(last_flags)) != 0) {
+ ret = 1;
+ printf("generated mtdflags too long, resetting to null\n");
+ }
+ return ret;
}
printf("partition %s not found\n", id);
@@ -1511,6 +1608,7 @@ static int spread_partitions(void)
struct mtd_info *mtd;
int part_num;
uint64_t cur_offs;
+ int ret = 0;
list_for_each(dentry, &devices) {
dev = list_entry(dentry, struct mtd_device, link);
@@ -1541,10 +1639,14 @@ static int spread_partitions(void)
index_partitions();
if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ ret = 1;
printf("generated mtdparts too long, reseting to null\n");
- return 1;
}
- return 0;
+ if (generate_mtdflags_save(last_flags, ARRAY_SIZE(last_flags)) != 0) {
+ ret = 1;
+ printf("generated mtdflags too long, resetting to null\n");
+ }
+ return ret;
}
#endif /* CONFIG_CMD_MTDPARTS_SPREAD */
@@ -1604,6 +1706,160 @@ static int parse_mtdparts(const char *const mtdparts)
return 0;
}
+/*
+ * mtdflags - partitionid1=flag1,flag2,flag3;partitionid2=flag1,flag2,flag3;...
+
+
+setenv mtdflags 'default=ecc_chip;x-loader=ecc_hw,repeat;system=yaffs;userdata=yaffs;cache=yaffs'
+mtdparts ecc x-loader
+
+ */
+const char *const mtdflags_strings[] = {
+ [MTDFLAGS_ECC_SW] = "ecc_sw",
+ [MTDFLAGS_ECC_HW] = "ecc_hw",
+ [MTDFLAGS_ECC_CHIP] = "ecc_chip",
+ [MTDFLAGS_ECC_BCH] = "ecc_bch",
+ [MTDFLAGS_YAFFS] = "yaffs",
+ [MTDFLAGS_REPEAT] = "repeat",
+};
+
+static int validate_mtdflags(int mask)
+{
+ int ecccnt = 0;
+ if((1 << MTDFLAGS_ECC_SW) & mask)
+ ecccnt++;
+ if((1 << MTDFLAGS_ECC_HW) & mask)
+ ecccnt++;
+ if((1 << MTDFLAGS_ECC_CHIP) & mask)
+ ecccnt++;
+ if((1 << MTDFLAGS_ECC_BCH) & mask)
+ ecccnt++;
+
+ return ecccnt <= 1;
+}
+
+static int parse_mtdflags_findmask(const char *const flags, int len)
+{
+ int i;
+
+ for(i=0;i<ARRAY_SIZE(mtdflags_strings);++i)
+ {
+ if(mtdflags_strings[i] &&
+ strlen(mtdflags_strings[i]) == len &&
+ strncmp(mtdflags_strings[i], flags, len) == 0)
+ {
+ return 1 << i;
+ }
+ }
+ return 0;
+}
+
+static char *mtdflags_tostring(int flags, int include_defaults)
+{
+ static char str[64];
+ char *cur = str;
+ int i;
+ int comma = 0;
+ int from_common = mtdflags_defaultmask;
+
+ if(flags & MTDFLAGS_DEFAULT_PERMITTED)
+ {
+ from_common = 0;
+ }
+
+ str[0] = '\0';
+
+ for(i=0;i < ARRAY_SIZE(mtdflags_strings);++i)
+ {
+ if(include_defaults && ((1 << i) & from_common))
+ {
+ if(comma)
+ cur = stpncpy(cur, ",", ARRAY_SIZE(str) - (cur - str));
+ cur = stpncpy(cur, "(", ARRAY_SIZE(str) - (cur - str));
+ cur = stpncpy(cur, mtdflags_strings[i], ARRAY_SIZE(str) - (cur - str));
+ cur = stpncpy(cur, ")", ARRAY_SIZE(str) - (cur - str));
+ comma=1;
+ }
+ if((1 << i) & flags)
+ {
+ if(comma)
+ cur = stpncpy(cur, ",", ARRAY_SIZE(str) - (cur - str));
+ cur = stpncpy(cur, mtdflags_strings[i], ARRAY_SIZE(str) - (cur - str));
+ comma=1;
+ }
+ }
+ str[ARRAY_SIZE(str) - 1] = '\0';
+ return str;
+}
+
+static int parse_mtdflags(const char *const mtdflags)
+{
+ const char *part, *part_end;
+ const char *flags, *flags_end;
+
+ if(!mtdflags)
+ return 1;
+
+ part = flags_end = mtdflags;
+
+ while(*part != '\0')
+ {
+ // Bring the pointer "part" past all blank items
+ for(part=flags_end;*part && (*part == ';' || *part == ' ');++part);
+ // Bring the pointer "flags" past the equals sign
+ for(part_end=part;*part_end && *part_end != '=';++part_end);
+ for(flags=part_end;*flags && *flags == '=';++flags);
+ // Bring the pointer "p" to the next partition
+ for(flags_end=flags;*flags_end && *flags_end != ';';++flags_end);
+
+ // Now, make sure it's sane
+ if(part != part_end && flags != flags_end && part != flags_end)
+ {
+ struct list_head *dentry, *pentry;
+ struct mtd_device *dev;
+ struct part_info *parti;
+ int mask = 0;
+
+ while(flags < flags_end)
+ {
+ const char *cur = flags;
+
+ for(;flags < flags_end && *flags != ',';++flags);
+ mask |= parse_mtdflags_findmask(cur, flags - cur);
+ for(;flags < flags_end && *flags == ',';++flags);
+ }
+ if(!validate_mtdflags(mask))
+ {
+ return 1;
+ }
+ if(strncmp(part, "default", 7) == 0)
+ {
+ mtdflags_defaultmask = mask & MTDFLAGS_DEFAULT_PERMITTED;
+ continue;
+ }
+
+ list_for_each(dentry, &devices)
+ {
+ dev = list_entry(dentry, struct mtd_device, link);
+ list_for_each(pentry, &dev->parts)
+ {
+ parti = list_entry(pentry, struct part_info, link);
+ if(strlen(parti->name) == part_end - part &&
+ strncmp(parti->name, part, part_end - part) == 0)
+ {
+ parti->mtdflags_mask = mask;
+ goto cont;
+ }
+ }
+ }
+ return 1;
+ cont:
+ continue;
+ }
+ }
+ return 0;
+}
+
/**
* Parse provided string describing mtdids mapping (see file header for mtdids
* variable format). Allocate memory for each entry and add all found entries
@@ -1724,11 +1980,11 @@ static int parse_mtdids(const char *const ids)
int mtdparts_init(void)
{
static int initialized = 0;
- const char *ids, *parts;
+ const char *ids, *parts, *flags;
const char *current_partition;
int ids_changed;
char tmp_ep[PARTITION_MAXLEN];
- char *mtdids_default, *mtdparts_default;
+ char *mtdids_default;
debug("\n---mtdparts_init---\n");
if (!initialized) {
@@ -1743,6 +1999,7 @@ int mtdparts_init(void)
/* get variables */
ids = getenv("mtdids");
parts = getenv("mtdparts");
+ flags = getenv("mtdflags");
current_partition = getenv("partition");
/* save it for later parsing, cannot rely on current partition pointer
@@ -1802,10 +2059,19 @@ int mtdparts_init(void)
}
/* parse partitions if either mtdparts or mtdids were updated */
- if (parts && ((last_parts[0] == '\0') || ((strcmp(last_parts, parts) != 0)) || ids_changed)) {
+ if (parts && (last_parts[0] == '\0' ||
+ strcmp(last_parts, parts) != 0 ||
+ ids_changed ||
+ (flags && strcmp(last_flags, flags) != 0))) {
if (parse_mtdparts(parts) != 0)
return 1;
+ if(flags && parse_mtdflags(flags))
+ {
+ printf("Bad mtdflags.\n");
+ return 1;
+ }
+
if (list_empty(&devices)) {
printf("mtdparts_init: no valid partitions\n");
return 1;
@@ -1813,6 +2079,10 @@ int mtdparts_init(void)
/* ok it's good, save new parts */
strncpy(last_parts, parts, MTDPARTS_MAXLEN);
+ if(flags)
+ strncpy(last_flags, flags, MTDPARTS_MAXLEN);
+ else
+ last_flags[0] = '\0';
/* reset first partition from first dev from the list as current */
current_mtd_dev = list_entry(devices.next, struct mtd_device, link);
@@ -1853,6 +2123,14 @@ int mtdparts_init(void)
return 0;
}
+int mtd_part_getmask(struct part_info *part)
+{
+ if(part->mtdflags_mask & MTDFLAGS_DEFAULT_PERMITTED)
+ return part->mtdflags_mask;
+ else
+ return part->mtdflags_mask | mtdflags_defaultmask;
+}
+
/**
* Return pointer to the partition of a requested number from a requested
* device.
@@ -1948,14 +2226,17 @@ int do_chpart(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
*/
int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
{
- char *mtdids_default, *mtdparts_default;
+ char *mtdids_default, *mtdparts_default, *mtdflags_default;
+ int ret = 0;
if (argc == 2) {
if (strcmp(argv[1], "default") == 0) {
mtdids_default = get_mtdids_default();
mtdparts_default = get_mtdparts_default();
+ mtdflags_default = get_mtdflags_default();
setenv("mtdids", (char *)mtdids_default);
setenv("mtdparts", (char *)mtdparts_default);
+ setenv("mtdflags", (char *)mtdflags_default);
setenv("partition", NULL);
mtdparts_init();
@@ -2044,11 +2325,15 @@ int do_mtdparts(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
}
if (generate_mtdparts_save(last_parts, MTDPARTS_MAXLEN) != 0) {
+ ret = 1;
printf("generated mtdparts too long, reseting to null\n");
- return 1;
+ }
+ if (generate_mtdflags_save(last_flags, ARRAY_SIZE(last_flags)) != 0) {
+ ret = 1;
+ printf("generated mtdflags too long, resetting to null\n");
}
- return 0;
+ return ret;
}
/* mtdparts del part-id */
@@ -2119,6 +2404,17 @@ U_BOOT_CMD(
"<offset> := partition start offset within the device\n"
"<name> := '(' NAME ')'\n"
"<ro-flag> := when set to 'ro' makes partition read-only (not used, passed to kernel)"
+ "mtdflags=<flag-def>[;<flag-def>...]\n\n"
+ "<flag-def> := <part-def>=<flag>[,<flag>...]\n"
+ "Flags affecting ECC modes (only applicable when \"nandecc auto\" is selected):\n"
+ " ecc_sw = Select SW ECC for NAND writes\n"
+ " ecc_hw = Select HW ECC for NAND writes\n"
+ " ecc_chip = Select ON-Chip ECC for NAND writes\n"
+ " ecc_bch = Select SW BCH ECC for NAND writes\n"
+ "Flags affecting nand write.auto\n"
+ " <blank> = Use nand write\n"
+ " yaffs = Use nand write.yaffs\n"
+ " repeat = Use nand.write.repeat\n"
);
/***************************************************/
diff --git a/common/cmd_nand.c b/common/cmd_nand.c
index 9b7a0a73e3..509c85e303 100644
--- a/common/cmd_nand.c
+++ b/common/cmd_nand.c
@@ -28,10 +28,74 @@
#include <jffs2/jffs2.h>
#include <nand.h>
+#include <asm/arch-omap3/sys_proto.h>
+
#if defined(CONFIG_CMD_MTDPARTS)
#include "mtd_parts.h"
#endif
+extern int omap_nand_ecc_auto;
+
+static int switch_ecc_bypart(const char *id)
+{
+ struct mtd_info *mtd_info;
+ struct nand_chip *nand;
+ struct mtd_device *mtd;
+ struct part_info *part;
+ int flags = 0;
+ u8 part_num;
+
+ if(mtdparts_init() == 0 && find_dev_and_part(id, &mtd, &part_num, &part, 0) == 0)
+ {
+ if(mtd->id->type != MTD_DEV_TYPE_NAND)
+ {
+ printf("Automatic ECC selection only works against NAND partitions.\n");
+ return -1;
+ }
+
+ if(mtd->id->num < 0 ||
+ mtd->id->num >= CONFIG_SYS_MAX_NAND_DEVICE ||
+ !nand_info[nand_curr_device].name)
+ {
+ printf("\nNo NAND device found\n");
+ return -1;
+ }
+
+ // Use the default flags if needed for decisions below
+ flags = mtd_part_getmask(part);
+ mtd_info = &nand_info[mtd->id->num];
+ nand = mtd_info->priv;
+
+ if(flags & (1 << MTDFLAGS_ECC_SW))
+ {
+ if(nand->ecc.mode != NAND_ECC_SOFT)
+ omap_nand_switch_ecc(OMAP_ECC_SOFT);
+ } else if(flags & (1 << MTDFLAGS_ECC_HW))
+ {
+ if(nand->ecc.mode != NAND_ECC_HW)
+ omap_nand_switch_ecc(OMAP_ECC_HW);
+ } else if(flags & (1 << MTDFLAGS_ECC_CHIP))
+ {
+ if(!nand->has_chip_ecc)
+ {
+ printf("NAND Chip doesn't support in-chip ECC\n");
+ return -1;
+ }
+ if(nand->ecc.mode != NAND_ECC_CHIP)
+ omap_nand_switch_ecc(OMAP_ECC_CHIP);
+ printf("Here\n");
+ } else if(flags & (1 << MTDFLAGS_ECC_BCH))
+ {
+ if(nand->ecc.mode != NAND_ECC_SOFT_BCH)
+ omap_nand_switch_ecc(OMAP_ECC_SOFT_BCH);
+ } else {
+ printf("Unknown ECC mode for %s\n", id);
+ }
+ }
+
+ return flags;
+}
+
static int nand_dump(nand_info_t *nand, ulong off, int only_oob, int repeat)
{
int i;
@@ -182,10 +246,13 @@ static int arg_off(const char *arg, int *idx, loff_t *off, loff_t *maxsize)
}
static int arg_off_size(int argc, char *const argv[], int *idx,
- loff_t *off, loff_t *size)
+ loff_t *off, loff_t *size, loff_t *maxsize)
{
+ loff_t int_maxsize;
int ret;
- loff_t maxsize;
+
+ if(maxsize == NULL)
+ maxsize = &int_maxsize;
if (argc == 0) {
*off = 0;
@@ -193,12 +260,12 @@ static int arg_off_size(int argc, char *const argv[], int *idx,
goto print;
}
- ret = arg_off(argv[0], idx, off, &maxsize);
+ ret = arg_off(argv[0], idx, off, maxsize);
if (ret)
return ret;
if (argc == 1) {
- *size = maxsize;
+ *size = *maxsize;
goto print;
}
@@ -207,7 +274,7 @@ static int arg_off_size(int argc, char *const argv[], int *idx,
return -1;
}
- if (*size > maxsize) {
+ if (*size > *maxsize) {
puts("Size exceeds partition or device limit\n");
return -1;
}
@@ -450,6 +517,11 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
return 0;
}
+ if (strcmp(cmd, "ecc") == 0 && argc == 3) {
+ switch_ecc_bypart(argv[2]);
+ return 0;
+ }
+
/*
* Syntax is:
* 0 1 2 3 4
@@ -490,7 +562,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
printf("\nNAND %s: ", cmd);
/* skip first two or three arguments, look for offset and size */
- if (arg_off_size(argc - o, argv + o, &dev, &off, &size) != 0)
+ if (arg_off_size(argc - o, argv + o, &dev, &off, &size, NULL) != 0)
return 1;
nand = &nand_info[dev];
@@ -545,7 +617,9 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
}
if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
+ int rw_mode = 0;
size_t rwsize;
+ loff_t maxsize;
int read;
if (argc < 4)
@@ -555,14 +629,25 @@ 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)
+ if (arg_off_size(argc - 3, argv + 3, &dev, &off, &size, &maxsize) != 0)
return 1;
nand = &nand_info[dev];
rwsize = size;
s = strchr(cmd, '.');
- if (!s || !strcmp(s, ".jffs2") ||
+ if(s && !strcmp(s, ".auto"))
+ {
+ int flags = switch_ecc_bypart(argv[3]);
+ if(flags == -1)
+ return 1;
+ rw_mode = 1;
+ if((flags & (1 << MTDFLAGS_YAFFS)) && !read)
+ rw_mode = 2;
+ if((flags & (1 << MTDFLAGS_REPEAT)) && !read)
+ rw_mode = 3;
+ }
+ if (!s || rw_mode == 1 || !strcmp(s, ".jffs2") ||
!strcmp(s, ".e") || !strcmp(s, ".i")) {
if (read)
ret = nand_read_skip_bad(nand, off, &rwsize,
@@ -571,11 +656,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
ret = nand_write_skip_bad(nand, off, &rwsize,
(u_char *)addr, 0);
#ifdef CONFIG_CMD_NAND_YAFFS
- } else if (!strcmp(s, ".yaffs")) {
- if (read) {
- printf("Unknown nand command suffix '%s'.\n", s);
- return 1;
- }
+ } else if (!read && (rw_mode == 2 || !strcmp(s, ".yaffs"))) {
ret = nand_write_skip_bad(nand, off, &rwsize, (u_char *)addr, 1);
#endif
} else if (!strcmp(s, ".oob")) {
@@ -590,6 +671,38 @@ 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 (!read && (rw_mode == 3 || !strcmp(s, ".repeat"))) {
+ int off_max = off + maxsize;
+ loff_t tmp;
+ if (str2off(argv[3], &tmp))
+ {
+ printf("nand write.repeat does _NOT_ support nand offsets.\n");
+ printf("(e.g. you MUST use a partition name)\n");
+ return 0;
+ }
+ if ((off & (nand->writesize - 1)) != 0) {
+ ret = 1;
+ } else {
+ if(size > nand->erasesize)
+ {
+ printf("Cannot write larger than block size for write.repeat (%i > %i)\n",
+ (unsigned int)size, nand->erasesize);
+ return 1;
+ }
+ printf("\n");
+ for(;off < off_max;off += nand->erasesize)
+ {
+ rwsize = size;
+ if(!nand_block_isbad(nand, off))
+ {
+ printf("Writing %i bytes to %x ", rwsize, (unsigned int)off);
+ ret = nand_write(nand, off, &rwsize, (u_char *)addr);
+ printf("(wrote %i bytes)\n", (unsigned int)rwsize);
+ } else {
+ printf("Skipping bad block %x\n", (unsigned int)off);
+ }
+ }
+ }
} else {
printf("Unknown nand command suffix '%s'.\n", s);
return 1;
@@ -667,7 +780,7 @@ int do_nand(cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
}
if (strcmp(cmd, "unlock") == 0) {
- if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size) < 0)
+ if (arg_off_size(argc - 2, argv + 2, &dev, &off, &size, NULL) < 0)
return 1;
if (!nand_unlock(&nand_info[dev], off, size)) {
@@ -699,6 +812,10 @@ U_BOOT_CMD(
" write 'size' bytes starting at offset 'off' with yaffs format\n"
" from memory address 'addr', skipping bad blocks.\n"
#endif
+ "nand write.repeat - addr off|partition size\n"
+ " write 'size' bytes starting at offset 'off'\n"
+ " from memory address 'addr', repeating the write for\n"
+ " every block in the partition\n"
"nand erase[.spread] [clean] off size - erase 'size' bytes "
"from offset 'off'\n"
" With '.spread', erase enough for given file size, otherwise,\n"
@@ -728,6 +845,10 @@ U_BOOT_CMD(
"\n"
"nand debug [level] - display or set the MTD debug level"
#endif
+ "nand write.auto addr partition [size]\n"
+ " write 'size' bytes to partition. Auto-picks ECC and\n"
+ " write.yaffs or write.repeat variants based on mtdflags\n"
+ " for the given partition.\n"
);
static int nand_load_image(cmd_tbl_t *cmdtp, nand_info_t *nand,
diff --git a/common/lcd.c b/common/lcd.c
index 85a946828e..3b89d4e0ef 100644
--- a/common/lcd.c
+++ b/common/lcd.c
@@ -1227,7 +1227,7 @@ void lcd_percent_update(int size)
}
}
-static int do_lcd_percent (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
+int do_lcd_percent (cmd_tbl_t * cmdtp, int flag, int argc, char * const argv[])
{
if (argc > 1)
strncpy(percent_data.string, argv[1], sizeof(percent_data.string) - 1);
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 1092a79732..f37d45bdc4 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2024,7 +2024,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
uint8_t *wbuf = buf;
/* Partial page write ? */
- if (unlikely(column || writelen < (mtd->writesize - 1))) {
+ if (unlikely(column || writelen < mtd->writesize)) {
cached = 0;
bytes = min_t(int, bytes - column, (int) writelen);
chip->pagebuf = -1;
diff --git a/drivers/mtd/nand/omap_gpmc.c b/drivers/mtd/nand/omap_gpmc.c
index 1a636cad23..865065e03b 100644
--- a/drivers/mtd/nand/omap_gpmc.c
+++ b/drivers/mtd/nand/omap_gpmc.c
@@ -390,6 +390,35 @@ static void micron_set_chip_ecc(struct mtd_info *mtd, int enable)
#endif
}
+void nand_disable_in_chip_ecc(void)
+{
+ struct nand_chip *nand;
+ struct mtd_info *mtd;
+
+ if (nand_curr_device < 0 ||
+ nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
+ !nand_info[nand_curr_device].name)
+ return;
+
+ mtd = &nand_info[nand_curr_device];
+ nand = mtd->priv;
+
+ /* If the NAND has in-chip ECC, disable it! */
+ if (nand->has_chip_ecc)
+ micron_set_chip_ecc(mtd, 0);
+}
+
+#ifdef CONFIG_CMD_NAND_CHIP_ECC
+static int micron_get_chip_ecc(struct mtd_info *mtd)
+{
+ uint8_t params[4];
+
+ nand_get_features(mtd, 0x90, params);
+
+ return ((params[0] & 0x08) != 0);
+}
+#endif
+
/**
* nand_read_oob_chipecc - read; get status to seeif chip ECC error
* @mtd: mtd info structure
@@ -610,6 +639,7 @@ void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode)
{
struct nand_chip *nand;
struct mtd_info *mtd;
+ int in_chip_ecc = 0;
if (nand_curr_device < 0 ||
nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
@@ -619,6 +649,12 @@ void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode)
mtd = &nand_info[nand_curr_device];
nand = mtd->priv;
+ if (mode == OMAP_ECC_CHIP && !nand->has_chip_ecc)
+ {
+ printf("NAND: Chip does not have internal ECC!\n");
+ return;
+ }
+
nand->options |= NAND_OWN_BUFFERS;
/* Reset ecc interface */
@@ -683,20 +719,12 @@ void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode)
nand->ecc.calculate = omap_calculate_ecc;
omap_hwecc_init(nand);
printf("NAND: HW ECC selected\n");
- if (nand->has_chip_ecc)
- micron_set_chip_ecc(mtd, 0);
} else if (mode == OMAP_ECC_SOFT) {
nand->ecc.mode = NAND_ECC_SOFT;
/* Use mtd default settings */
nand->ecc.layout = NULL;
printf("NAND: SW ECC selected\n");
- if (nand->has_chip_ecc)
- micron_set_chip_ecc(mtd, 0);
} else if (mode == OMAP_ECC_CHIP) {
- if (!nand->has_chip_ecc) {
- printf("NAND: Chip does not have internal ECC!\n");
- return;
- }
nand->ecc.bytes = 0;
nand->ecc.size = 2048;
nand->ecc.calculate = omap_calculate_chip_hwecc;
@@ -716,13 +744,17 @@ void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode)
nand->cmdfunc = omap_nand_command_lp;
else
printf("%s: Huh? not 16-bit wide\n", __FUNCTION__);
- micron_set_chip_ecc(mtd, 1);
printf("NAND: Internal to NAND ECC selected\n");
+ in_chip_ecc = 1;
} else {
printf("NAND: unknown ECC mode %d\n", mode);
return;
}
+ /* Enable/disable the in-chip ECC engine appropriately */
+ if (nand->has_chip_ecc)
+ micron_set_chip_ecc(mtd, in_chip_ecc);
+
current_ecc_method = mode;
/* Update NAND handling after ECC mode switch */
@@ -731,6 +763,32 @@ void omap_nand_switch_ecc(enum omap_nand_ecc_mode mode)
nand->options &= ~NAND_OWN_BUFFERS;
}
+#ifdef CONFIG_CMD_NAND_CHIP_ECC
+int omap_nand_switch_chip_ecc(int get, int enable)
+{
+ struct nand_chip *nand;
+ struct mtd_info *mtd;
+
+ if (nand_curr_device < 0 ||
+ nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
+ !nand_info[nand_curr_device].name)
+ return -1;
+
+ mtd = &nand_info[nand_curr_device];
+ nand = mtd->priv;
+
+ /* If no in-chip ECC, punt! */
+ if (!nand->has_chip_ecc)
+ return -1;
+
+ if (get)
+ return micron_get_chip_ecc(mtd);
+
+ micron_set_chip_ecc(mtd, enable);
+ return 0;
+}
+#endif
+
/*
* Board-specific NAND initialization. The following members of the
* argument are board-specific:
diff --git a/drivers/power/twl4030.c b/drivers/power/twl4030.c
index b62ed176d2..92c8fd75b5 100644
--- a/drivers/power/twl4030.c
+++ b/drivers/power/twl4030.c
@@ -136,7 +136,7 @@ U_BOOT_CMD(poweroff, 1, 1, do_poweroff,
/* Enable the battery backup charger */
int twl4030_enable_bb_charging(unsigned int millivolts, unsigned int microamps)
{
- u8 val;
+ u8 val = 0;
if (millivolts >= 3200)
val = 0x0c;
diff --git a/drivers/usb/musb/musb_udc.c b/drivers/usb/musb/musb_udc.c
index 6f6ed61d08..3ebdcf1daf 100644
--- a/drivers/usb/musb/musb_udc.c
+++ b/drivers/usb/musb/musb_udc.c
@@ -180,11 +180,15 @@ static void musb_peri_softconnect(void)
/* Power on MUSB */
power = readb(&musbr->power);
power |= MUSB_POWER_SOFTCONN;
+#if USB_BCD_VERSION == 0x0200
+ power |= MUSB_POWER_HSENAB;
+#else
/*
* The usb device interface is usb 1.1
* Disable 2.0 high speed by clearring the hsenable bit.
*/
power &= ~MUSB_POWER_HSENAB;
+#endif
writeb(power, &musbr->power);
/* Check if device is in b-peripheral mode */
@@ -786,6 +790,9 @@ void udc_irq(void)
if (intrtx)
musb_peri_tx(intrtx);
} else {
+ udc_device->speed =
+ (readb(&musbr->power) & MUSB_POWER_HSMODE) ?
+ USB_SPEED_HIGH : USB_SPEED_FULL;
if (MUSB_INTR_SOF & intrusb) {
u8 faddr;
faddr = readb(&musbr->faddr);
@@ -881,10 +888,10 @@ void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
ep_addr = endpoint->endpoint_address;
if (USB_DIR_IN == (ep_addr & USB_ENDPOINT_DIR_MASK)) {
/* IN */
- epinfo[(id * 2) + 1].epsize = endpoint->tx_packetSize;
+ epinfo[((id - 1) * 2) + 1].epsize = endpoint->tx_packetSize;
} else {
/* OUT */
- epinfo[id * 2].epsize = endpoint->rcv_packetSize;
+ epinfo[(id - 1) * 2].epsize = endpoint->rcv_packetSize;
}
musb_configure_ep(&epinfo[0],
@@ -899,12 +906,27 @@ void udc_setup_ep(struct usb_device_instance *device, unsigned int id,
void udc_connect(void)
{
- /* noop */
+ musb_peri_softconnect();
}
void udc_disconnect(void)
{
- /* noop */
+ u8 power, intrusb;
+ u16 intrrx, intrtx;
+
+ /* If musbr Null, never initialized MUSB! */
+ if (!musbr)
+ return;
+
+ /* Power off MUSB */
+ power = readb(&musbr->power);
+ power &= ~MUSB_POWER_SOFTCONN;
+ writeb(power, &musbr->power);
+
+ /* Read intr to clear */
+ intrusb = readb(&musbr->intrusb);
+ intrrx = readw(&musbr->intrrx);
+ intrtx = readw(&musbr->intrtx);
}
void udc_enable(struct usb_device_instance *device)
diff --git a/include/common.h b/include/common.h
index 9ba1e93711..146a1c12b0 100644
--- a/include/common.h
+++ b/include/common.h
@@ -768,6 +768,7 @@ int cpu_release(int nr, int argc, char * const argv[]);
#ifdef CONFIG_MTDPARTS_DYNAMIC_DEFAULT
extern char *get_mtdids_default(void);
extern char *get_mtdparts_default(void);
+extern char *get_mtdflags_default(void);
#endif /* CONFIG_MTDPARTS_DYNAMIC_DEFAULT */
#endif /* __ASSEMBLY__ */
diff --git a/include/configs/omap3logic.h b/include/configs/omap3logic.h
index 5dfeb9bb72..6c91462576 100644
--- a/include/configs/omap3logic.h
+++ b/include/configs/omap3logic.h
@@ -125,6 +125,12 @@
/* DDR - I use Micron DDR */
#define CONFIG_OMAP3_MICRON_DDR 1
+#define CONFIG_USB_OMAP3 1
+#define CONFIG_MUSB_UDC 1
+#define CONFIG_FASTBOOT 1
+#define CONFIG_TWL4030_USB 1
+#define CONFIG_USB_DEVICE 1
+
#if 0
/* USB
* Enable CONFIG_MUSB_HCD for Host functionalities MSC, keyboard
@@ -152,15 +158,34 @@
#endif /* CONFIG_MUSB_HCD */
#ifdef CONFIG_MUSB_UDC
+# ifdef CONFIG_FASTBOOT
+# define CONFIG_CMD_FASTBOOT
+# define CONFIG_FASTBOOT_TRANSFER_BUFFER (PHYS_SDRAM_1 + SZ_16M)
+# define CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE (SZ_128M - SZ_16M)
+ /* if already present, use already existing NAND macros for block & oob size */
+# define FASTBOOT_NAND_BLOCK_SIZE 2048
+# define FASTBOOT_NAND_OOB_SIZE 64
+ /* Fastboot product name */
+# define FASTBOOT_PRODUCT_NAME "dm3730logic"
+ /* Use HS */
+# define USB_BCD_VERSION 0x0200
+
+# define CONFIG_USBD_VENDORID 0x0451
+# define CONFIG_USBD_PRODUCTID 0x5678
+# define CONFIG_USBD_MANUFACTURER "LogicPD"
+# define CONFIG_USBD_PRODUCT_NAME "EVM"
+//# define CONFIG_USBD_PRODUCT_NAME getenv("logic_model")
+# else
/* USB device configuration */
-#define CONFIG_USB_DEVICE 1
-#define CONFIG_USB_TTY 1
-#define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
+# define CONFIG_USB_DEVICE 1
+# define CONFIG_USB_TTY 1
+# define CONFIG_SYS_CONSOLE_IS_IN_ENV 1
/* Change these to suit your needs */
-#define CONFIG_USBD_VENDORID 0x0451
-#define CONFIG_USBD_PRODUCTID 0x5678
-#define CONFIG_USBD_MANUFACTURER "Texas Instruments"
-#define CONFIG_USBD_PRODUCT_NAME "EVM"
+# define CONFIG_USBD_VENDORID 0x0451
+# define CONFIG_USBD_PRODUCTID 0x5678
+# define CONFIG_USBD_MANUFACTURER "Texas Instruments"
+# define CONFIG_USBD_PRODUCT_NAME "EVM"
+# endif /* CONFIG_FASTBOOT */
#endif /* CONFIG_MUSB_UDC */
#endif /* CONFIG_USB_OMAP3 */
@@ -178,6 +203,7 @@
#define CONFIG_CMD_I2C /* I2C serial bus support */
#define CONFIG_CMD_MMC /* MMC support */
#define CONFIG_CMD_NAND /* NAND support */
+#undef CONFIG_CMD_NAND_CHIP_ECC /* nandecc_chip command */
#define CONFIG_MTD_DEVICE /* needed for MTD mtdparts support */
#define CONFIG_CMD_MTDPARTS /* MTD partition support */
#define MTDIDS_NAND_DEFAULT "nand0=omap2-nand.0"
@@ -185,6 +211,7 @@
#define MTDPARTS_NAND_DEFAULT "mtdparts=omap2-nand.0:512k(x-loader),"\
"1664k(u-boot),384k(u-boot-env),"\
"5m(kernel),20m(ramdisk),-(fs)"
+#define MTDFLAGS_NAND_DEFAULT "default=ecc_chip;x-loader=ecc_hw,repeat;fs=yaffs"
#define MTDPARTS_NOR_DEFAULT "physmap-flash.0:-(nor)"
@@ -211,7 +238,7 @@
#define CONFIG_CMD_FLASH /* flinfo, erase, protect */
#undef CONFIG_CMD_FPGA /* FPGA configuration Support */
-#undef CONFIG_CMD_IMI /* iminfo */
+#define CONFIG_CMD_IMI /* iminfo */
#undef CONFIG_CMD_IMLS /* List all found images */
#define CONFIG_CMD_GPMC_CONFIG /* gpmc_config */
@@ -267,33 +294,35 @@
#define CONFIG_BOOTFILE uImage
#define CONFIG_PREBOOT \
- "echo ; " \
- "echo =================================== NOTICE ===================================;" \
- "echo \"The U-Boot environment was not found. If the display is not set properly \";"\
- "echo \"linux will not have video support.\";" \
- "echo ; " \
- "echo \"Valid display options are:\";" \
- "echo \" 2 == LQ121S1DG31 TFT SVGA (12.1) Sharp\";" \
- "echo \" 3 == LQ036Q1DA01 TFT QVGA (3.6) Sharp w/ASIC\";" \
- "echo \" 5 == LQ064D343 TFT VGA (6.4) Sharp\";" \
- "echo \" 7 == LQ10D368 TFT VGA (10.4) Sharp\";" \
- "echo \" 15 == LQ043T1DG01 TFT WQVGA (4.3) Sharp (DEFAULT)\";" \
- "echo \" vga[-16 OR -24] LCD VGA 640x480\";" \
- "echo \" svga[-16 OR -24] LCD SVGA 800x600\";" \
- "echo \" xga[-16 OR -24] LCD XGA 1024x768\";" \
- "echo \" 720p[-16 OR -24] LCD 720P 1280x720\";" \
- "echo \" sxga[-16 OR -24] LCD SXGA 1280x1024\";" \
- "echo \" uxga[-16 OR -24] LCD UXGA 1600x1200\";" \
- "echo ; " \
- "echo \"Default `display` environment variable is now being set to: 15\";" \
- "setenv display 15;" \
- "setenv preboot;" \
- "echo ; " \
- "echo \"At the U-Boot prompt type commands: `setenv display <num>`, then type\";" \
- "echo \"`saveenv` to save the environment to NAND flash. This will avoid seeing\";" \
- "echo \"this notice on future boots\" ; " \
- "echo =================================== NOTICE ===================================;" \
- "echo ; "
+ "if true;then\n" \
+ " echo\n" \
+ " echo =================================== NOTICE ===================================\n" \
+ " echo \"The U-Boot environment was not found. If the display is not set properly \"\n"\
+ " echo \"linux will not have video support.\"\n" \
+ " echo \n" \
+ " echo \"Valid display options are:\"\n" \
+ " echo \" 2 == LQ121S1DG31 TFT SVGA (12.1) Sharp\"\n" \
+ " echo \" 3 == LQ036Q1DA01 TFT QVGA (3.6) Sharp w/ASIC\"\n" \
+ " echo \" 5 == LQ064D343 TFT VGA (6.4) Sharp\"\n" \
+ " echo \" 7 == LQ10D368 TFT VGA (10.4) Sharp\"\n" \
+ " echo \" 15 == LQ043T1DG01 TFT WQVGA (4.3) Sharp (DEFAULT)\"\n" \
+ " echo \" vga[-16 OR -24] LCD VGA 640x480\"\n" \
+ " echo \" svga[-16 OR -24] LCD SVGA 800x600\"\n" \
+ " echo \" xga[-16 OR -24] LCD XGA 1024x768\"\n" \
+ " echo \" 720p[-16 OR -24] LCD 720P 1280x720\"\n" \
+ " echo \" sxga[-16 OR -24] LCD SXGA 1280x1024\"\n" \
+ " echo \" uxga[-16 OR -24] LCD UXGA 1600x1200\"\n" \
+ " echo \n " \
+ " echo \"Default `display` environment variable is now being set to: 15\"\n" \
+ " setenv display 15\n" \
+ " setenv preboot\n" \
+ " echo \n " \
+ " echo \"At the U-Boot prompt type commands: `setenv display <num>`, then type\"\n" \
+ " echo \"`saveenv` to save the environment to NAND flash. This will avoid seeing\"\n" \
+ " echo \"this notice on future boots\" \n " \
+ " echo =================================== NOTICE ===================================\n" \
+ " echo \n " \
+ "fi"
#ifdef CONFIG_USB_TTY
#define OMAP3LOGIC_USBTTY "usbtty=cdc_acm\0"
@@ -403,171 +432,153 @@
"nfsrootpath=/opt/nfs-exports/ltib-omap\0" \
"nfsoptions=,wsize=1500,rsize=1500\0" \
"rotation=0\0" \
- "autoboot=echo \"\n== Checking mmc1 for alternate boot script " CONFIG_MMC_BOOTSCRIPT_NAME " ==\";" \
+ "autoboot=run _autoboot\0_autoboot=echo \"\n== Checking mmc1 for alternate boot script " CONFIG_MMC_BOOTSCRIPT_NAME " ==\";" \
" if mmc init; then \n" \
- " if run loadbootscript; then \n" \
+ " if run _loadbootscript; then \n" \
" echo \"\"; \n" \
" echo \"== Found script on mmc 1, starting ==\"; \n" \
" run bootscript; \n" \
" else \n" \
" echo \"\"; \n" \
" echo \"== Script not found on mmc 1, proceeding with defaultboot ==\"; \n" \
- " run defaultboot;\n" \
+ " run _defaultboot;\n" \
" fi; \n" \
- " else run defaultboot; fi\0" \
- "loadbootscript=fatload mmc 1 $mmc_bootscript_addr " CONFIG_MMC_BOOTSCRIPT_NAME "\0" \
+ " else run _defaultboot; fi\0" \
+ "_loadbootscript=fatload mmc 1 $mmc_bootscript_addr " CONFIG_MMC_BOOTSCRIPT_NAME "\0" \
"bootscript=source ${mmc_bootscript_addr}\0" \
- "vrfb_arg=if itest ${rotation} -ne 0; then \n" \
- "setenv bootargs ${bootargs} omapfb.vrfb=y omapfb.rotate=${rotation}; \n" \
- "fi\0" \
+ "_vrfb_arg=if itest ${rotation} -ne 0; then \n" \
+ " setenv bootargs ${bootargs} omapfb.vrfb=y omapfb.rotate=${rotation}; \n" \
+ " fi\0" \
"dump_bootargs=echo \"\"; echo \"== Kernel bootargs ==\"; echo $bootargs; echo \"\"; \0" \
- "dump_boot_sources=echo \"kernel_location: $kernel_location, " \
+ "_dump_boot_sources=echo \"kernel_location: $kernel_location, " \
"rootfs_location: $rootfs_location, " \
"rootfs_type: $rootfs_type\"; " \
"echo \"\"; " \
"\0" \
- "load_kernel=if test $kernel_location = 'ram'; then \n" \
- " echo \"== kernel located at $loadaddr ==\"; \n" \
- " echo \"\"; \n" \
- " setenv bootm_arg1 ${loadaddr};\n" \
- " else \n" \
- " if test $kernel_location = 'nand'; then \n" \
- " echo \"== Loading kernel from nand to $loadaddr ==\"; \n" \
- " nand read.i $loadaddr $kernel_partition; \n" \
+ \
+ /* load_kernel_* targets */ \
+ "_load_kernel_ram=if true;then;\n" \
+ " echo \"== kernel located at $Loadaddr ==\n\"\n" \
+ " setenv bootm_arg1 ${loadaddr}\n" \
+ " fi\0" \
+ "_load_kernel_nand=if true;then;\n" \
+ " echo \"== Loading kernel from nand to $loadaddr ==\"; \n" \
+ " nand read.i $loadaddr $kernel_partition; \n" \
+ " echo \"\"; \n" \
+ " setenv bootm_arg1 ${loadaddr};\n" \
+ " fi\0" \
+ "_load_kernel_nand-part=if true;then;\n" \
+ " echo \"== Loading kernel from nand partition $kernel_partition to $loadaddr ==\"; \n" \
+ " nboot $loadaddr $kernel_partition; \n" \
+ " echo \"\"; \n" \
+ " setenv bootm_arg1 ${loadaddr};\n" \
+ " fi\0" \
+ "_load_kernel_mmc=if true;then;\n" \
+ " echo \"== Loading kernel file $kernelimage to $loadaddr ==\"; \n" \
+ " mmc init; \n" \
+ " fatload mmc 1 $loadaddr $kernelimage; \n" \
+ " echo \"\"; \n" \
+ " setenv bootm_arg1 ${loadaddr};\n" \
+ " fi\0" \
+ "_load_kernel_tftp=if true;then;\n" \
+ " echo \"== Loading kernel file $tftpdir$kernelimage to $loadaddr ==\"; \n" \
+ " tftpboot $loadaddr $tftpdir$kernelimage; \n" \
+ " echo \"\"; \n" \
+ " setenv bootm_arg1 ${loadaddr};\n" \
+ " fi\0" \
+ "_load_kernel=setenv bootm_arg1;if run _load_kernel_$kernel_location; then;else \n" \
+ " echo \"\033[31m== kernel_location must be set to ram, nand, mmc, or tftp!! ==\033[0m\"; \n" \
" echo \"\"; \n" \
- " setenv bootm_arg1 ${loadaddr};\n" \
- " else \n" \
- " if test $kernel_location = 'nand-part'; then \n" \
- " echo \"== Loading kernel from nand partition $kernel_partition to $loadaddr ==\"; \n" \
- " nboot $loadaddr $kernel_partition; \n" \
- " echo \"\"; \n" \
- " setenv bootm_arg1 ${loadaddr};\n" \
- " else \n" \
- " if test $kernel_location = 'mmc'; then \n" \
- " echo \"== Loading kernel file $kernelimage to $loadaddr ==\"; \n" \
- " mmc init; \n" \
- " fatload mmc 1 $loadaddr $kernelimage; \n" \
+ " fi\n\0" \
+ \
+ /* load_rootfs_* targets */ \
+ "_load_rootfs_ram=if true;then;\n" \
+ " echo \"== rootfs located at $ramdiskaddr ==\"; \n" \
" echo \"\"; \n" \
- " setenv bootm_arg1 ${loadaddr};\n" \
- " else \n" \
- " if test $kernel_location = 'tftp'; then \n" \
- " echo \"== Loading kernel file $tftpdir$kernelimage to $loadaddr ==\"; \n" \
- " tftpboot $loadaddr $tftpdir$kernelimage; \n" \
- " echo \"\"; \n" \
- " setenv bootm_arg1 ${loadaddr};\n" \
- " else \n" \
- " echo \"== kernel_location must be set to ram, nand, mmc, or tftp!! ==\"; \n" \
- " echo \"\"; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi\n " \
- "\0" \
- "load_rootfs=if test $rootfs_location = 'ram'; then \n" \
- " echo \"== rootfs located at $ramdiskaddr ==\"; \n" \
- " echo \"\"; \n" \
- " setenv bootm_arg2 ${ramdiskaddr}; \n" \
- " else \n" \
- " if test $rootfs_location = 'tftp'; then \n" \
- " echo \"== Loading rootfs file $tftpdir$ramdiskimage to $ramdiskaddr ==\"; \n" \
- " tftpboot $ramdiskaddr $tftpdir$ramdiskimage;\n" \
- " echo \"\"; \n" \
- " setenv bootm_arg2 ${ramdiskaddr}; \n" \
- " else \n" \
- " if test $rootfs_location = '/dev'; then \n" \
- " echo \"== rootfs located in $rootfs_device ==\"; \n" \
- " echo \"\"; \n" \
- " setenv bootargs ${bootargs} root=${rootfs_device}; \n" \
- " setenv bootm_arg2; \n" \
- " else \n" \
- " if test $rootfs_location = 'nfs'; then \n" \
+ " setenv bootm_arg2 ${ramdiskaddr}; \n" \
+ " fi\0" \
+ "_load_rootfs_tftp=if true;then;\n" \
+ " echo \"== Loading rootfs file $tftpdir$ramdiskimage to $ramdiskaddr ==\"; \n" \
+ " tftpboot $ramdiskaddr $tftpdir$ramdiskimage;\n" \
+ " echo \"\"; \n" \
+ " setenv bootm_arg2 ${ramdiskaddr}; \n" \
+ " fi\0" \
+ "_load_rootfs_/dev=if true;then;\n" \
+ " echo \"== rootfs located in $rootfs_device ==\"; \n" \
+ " echo \"\"; \n" \
+ " setenv bootargs ${bootargs} root=${rootfs_device}; \n" \
+ " fi\0" \
+ "_load_rootfs_nfs=if true;then;\n" \
" echo \"== rootfs located at $nfsrootpath on server $serverip ==\"; \n" \
" echo \"\"; \n" \
" setenv bootargs ${bootargs} root=/dev/nfs; \n" \
- " setenv bootm_arg2; \n" \
- " else \n" \
- " if test $rootfs_location = 'mmc'; then\n " \
- " echo \"== Loading rootfs file $ramdiskimage to $ramdiskaddr ==\"; \n" \
- " fatload mmc 1 ${ramdiskaddr} ${ramdiskimage}; \n"\
- " setenv bootm_arg2 ${ramdiskaddr}; \n" \
- " else \n" \
- " if test $rootfs_location = 'nand'; then \n" \
- " echo \"== Loading rootfs from nand to $ramdiskaddr ==\"; \n" \
- " nand read.i $ramdiskaddr $ramdisk_partition; \n" \
- " setenv bootm_arg2 ${ramdiskaddr}; \n" \
- " else \n"\
- " if test $rootfs_location = 'nand-part'; then \n" \
+ " fi\0" \
+ "_load_rootfs_mmc=if true;then;\n" \
+ " echo \"== Loading rootfs file $ramdiskimage to $ramdiskaddr ==\"; \n" \
+ " fatload mmc 1 ${ramdiskaddr} ${ramdiskimage}; \n"\
+ " setenv bootm_arg2 ${ramdiskaddr}; \n" \
+ " fi\0" \
+ "_load_rootfs_nand=if true;then;\n" \
+ " echo \"== Loading rootfs from nand to $ramdiskaddr ==\"; \n" \
+ " nand read.i $ramdiskaddr $ramdisk_partition; \n" \
+ " setenv bootm_arg2 ${ramdiskaddr}; \n" \
+ " fi\0" \
+ "_load_rootfs_nand-part=if true;then;\n" \
" echo \"== Loading rootfs from nand partition $ramdisk_partition to $ramdiskaddr ==\"; \n" \
" nand read.i $ramdiskaddr $ramdisk_partition; \n" \
" setenv bootm_arg2 ${ramdiskaddr}; \n" \
- " else \n"\
- " echo \"== rootfs_location must be set to ram, tftp, /dev, nfs, mmc, nand-part or nand!! == \"; \n" \
- " echo \"\"; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi" \
- "\0" \
- "set_rootfs_type=if test $rootfs_type = 'ramdisk'; then \n" \
- " setenv bootargs ${bootargs} root=/dev/ram rw ramdisk_size=${ramdisksize}; \n" \
- " else \n" \
- " if test $rootfs_type = 'jffs'; then \n" \
- " setenv bootargs ${bootargs} rw rootfstype=jffs2;\n" \
- " else \n" \
- " if test $rootfs_type = 'yaffs'; then \n" \
- " setenv bootargs ${bootargs} rw rootfstype=yaffs2;\n" \
- " else \n" \
- " if test $rootfs_type = 'ext3'; then \n" \
- " setenv bootargs ${bootargs} rw rootfstype=ext3 rootwait; \n" \
- " else \n" \
- " if test $rootfs_type = 'nfs'; then \n" \
- " setenv bootargs ${bootargs} rw nfsroot=${serverip}:${nfsrootpath}${nfsoptions} ip=dhcp; \n" \
- " else \n"\
- " echo \"$rootfs_type must be set to ramdisk, jffs, yaffs, ext3, or nfs\"; \n" \
- " echo \"\"; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi; \n" \
- " fi" \
- "\0" \
- "addmtdparts=setenv bootargs ${bootargs} ${mtdparts} \0" \
- "common_bootargs=" \
- " setenv bootargs ${bootargs} display=${display} ${otherbootargs}; " \
- " run addmtdparts; " \
- " run vrfb_arg; " \
- "\0" \
- "dump_run_bootm=" \
- " echo \"bootm $bootm_arg1 $bootm_arg2\"; " \
- " echo \"\"; " \
- " bootm $bootm_arg1 $bootm_arg2\0" \
- "defaultboot=" \
- " run dump_boot_sources; " \
- " run setconsole; setenv bootargs console=${console}; " \
- " run common_bootargs; " \
- " run load_kernel; " \
- " run load_rootfs; " \
- " run set_rootfs_type; " \
- " run dump_bootargs; " \
- " run dump_run_bootm; " \
- "\0" \
- "nfsboot=" \
- " setenv kernel_location tftp; " \
- " setenv rootfs_location nfs; " \
- " setenv rootfs_type nfs; " \
- " run defaultboot; " \
- "\0" \
- "ramboot=" \
- " setenv kernel_location tftp; " \
- " setenv rootfs_location tftp; " \
- " setenv rootfs_type ramdisk; " \
- " run defaultboot; " \
- "\0" \
- "checkerror=if test $error = '';\n" \
+ " fi\0" \
+ "_load_rootfs=setenv bootm_arg2;if run _load_rootfs_$rootfs_location; then;else \n" \
+ " echo \"\033[31m== rootfs_location must be set to ram, tftp, /dev, nfs, mmc, nand-part or nand!! == \033[0m\"; \n" \
+ " echo \"\"; \n" \
+ " fi\n\0" \
+ \
+ /* set_rootfs_type_* targets */ \
+ "_set_rootfs_type_ramdisk=setenv bootargs ${bootargs} root=/dev/ram rw ramdisk_size=${ramdisksize}\0" \
+ "_set_rootfs_type_jffs=setenv bootargs ${bootargs} rw rootfstype=jffs2\0" \
+ "_set_rootfs_type_yaffs=setenv bootargs ${bootargs} rw rootfstype=yaffs2\0" \
+ "_set_rootfs_type_ext3=setenv bootargs ${bootargs} rw rootfstype=ext3 rootwait\0" \
+ "_set_rootfs_type_nfs=setenv bootargs ${bootargs} rw nfsroot=${serverip}:${nfsrootpath}${nfsoptions} ip=dhcp\0" \
+ "_set_rootfs_type=if run _set_rootfs_type_${rootfs_type}; then;else \n" \
+ " echo \"\033[31m== $rootfs_type must be set to ramdisk, jffs, yaffs, ext3, or nfs ==\033[0m\"; \n" \
+ " echo \"\"; \n" \
+ " fi\0" \
+ \
+ /* Other misc. scripts */ \
+ "_addmtdparts=setenv bootargs ${bootargs} ${mtdparts} \0" \
+ "_common_bootargs=if true;then;\n" \
+ " setenv bootargs ${bootargs} display=${display} ${otherbootargs};\n" \
+ " run _addmtdparts;\n" \
+ " run _vrfb_arg;\n" \
+ " fi\0" \
+ "_dump_run_bootm=if true;then\n" \
+ " echo \"bootm $bootm_arg1 $bootm_arg2\";\n" \
+ " echo \"\";\n" \
+ " bootm $bootm_arg1 $bootm_arg2\n" \
+ " fi\0" \
+ "defaultboot=run _defaultboot\0_defaultboot=if true;then\n" \
+ " run _dump_boot_sources;\n" \
+ " run setconsole; setenv bootargs console=${console};\n" \
+ " run _common_bootargs;\n" \
+ " run _load_kernel;\n" \
+ " run _load_rootfs;\n" \
+ " run _set_rootfs_type;\n" \
+ " run dump_bootargs;\n" \
+ " run _dump_run_bootm;\n" \
+ " fi\0" \
+ "nfsboot=if true;then\n" \
+ " setenv kernel_location tftp\n" \
+ " setenv rootfs_location nfs\n" \
+ " setenv rootfs_type nfs\n" \
+ " run defaultboot\n" \
+ " fi\0" \
+ "ramboot=if true;then\n" \
+ " setenv kernel_location tftp\n" \
+ " setenv rootfs_location tftp\n" \
+ " setenv rootfs_type ramdisk\n" \
+ " run defaultboot\n" \
+ " fi\0" \
+ "_checkerror=if test $error = '';\n" \
" then\n" \
" echo \033[31m${error}\033[0m\n" \
" echo_lcd /pAA/k${error}\n" \
@@ -578,19 +589,19 @@
" echo_lcd /kand restart the devkit./n\n" \
" fi" \
"\0" \
- "initmmc=if test $error = '';then;else\n" \
+ "_initmmc=if test $error = '';then;else\n" \
" if mmc init;then;else;\n" \
" setenv error \"Failed to initialize MMC\"\n" \
" fi\n" \
" fi" \
"\0" \
- "checkmmcfile=if test $error = '';then;else\n" \
+ "_checkmmcfile=if test $error = '';then;else\n" \
" if fatload mmc 1 ${loadaddr} ${arg_filename} 1;then;else;\n" \
" setenv error \"Unable to load ${arg_filename}\";\n" \
" fi\n" \
" fi" \
"\0" \
- "burnfile=if test $error = '';then;else\n" \
+ "_burnfile=if test $error = '';then;else\n" \
" echo \"\033[1m== Loading ${arg_filename} ==\033[0m\"\n" \
" echo_lcd /pAA/kPartition ${arg_partition}:\n" \
" echo_lcd /pBA/kLoading ${arg_filename}/aC;lcd_percent \"/gC/k /P%...\"\n" \
@@ -599,7 +610,7 @@
" lcd_percent \"/pBA/kErasing Partition /P%...\"\n" \
" nand erase.part ${arg_partition}\n" \
" echo_lcd /pBA/kWriting ${arg_filename} to Partition/aC;lcd_percent \"/gC/k /P%...\"\n" \
- " nand ${arg_writecmd} ${loadaddr} ${arg_partition} ${filesize}\n" \
+ " nand write.auto ${loadaddr} ${arg_partition} ${filesize}\n" \
" lcd_percent \"\"\n" \
" echo_lcd /pAA/k/pAB/k\n" \
" else\n" \
@@ -607,51 +618,36 @@
" fi\n" \
" fi" \
"\0" \
- "burnmmcxloader=if test $error = '';then;else\n" \
- " nandecc hw;\n" \
- " arg_filename=${xloadimage};arg_partition=${xloader_partition};arg_writecmd=write.i;\n" \
- " run burnfile\n" \
- " if test $error = '';then;else\n" \
- " nand write.i ${loadaddr} 0x00020000 ${filesize}\n" \
- " nand write.i ${loadaddr} 0x00040000 ${filesize}\n" \
- " nand write.i ${loadaddr} 0x00060000 ${filesize}\n" \
- " fi\n" \
- " fi" \
- "\0" \
- "burncommon=if test $error = '';then;else\n" \
- " arg_filename=${xloadimage};run checkmmcfile;\n" \
- " arg_filename=${ubootimage};run checkmmcfile;\n" \
- " arg_filename=${kernelimage};run checkmmcfile;\n" \
- " run burnmmcxloader;\n" \
- " nandecc ${defaultecc};\n" \
- " arg_writecmd=write.i;\n" \
- " arg_filename=${ubootimage};arg_partition=${uboot_partition};run burnfile;\n" \
- " arg_filename=${kernelimage};arg_partition=${kernel_partition};run burnfile;\n" \
+ "_burncommon=if test $error = '';then;else\n" \
+ " arg_filename=${xloadimage};run _checkmmcfile;\n" \
+ " arg_filename=${ubootimage};run _checkmmcfile;\n" \
+ " arg_filename=${kernelimage};run _checkmmcfile;\n" \
+ " arg_filename=${xloadimage};arg_partition=${xloader_partition};run _burnfile;\n" \
+ " arg_filename=${ubootimage};arg_partition=${uboot_partition};run _burnfile;\n" \
+ " arg_filename=${kernelimage};arg_partition=${kernel_partition};run _burnfile;\n" \
" fi" \
"\0" \
- "makenandboot=if true;then;\n" \
+ "makenandboot=run _makenandboot\0_makenandboot=if true;then;\n" \
" setenv error;\n" \
- " run initmmc;\n" \
- " arg_filename=${ramdiskimage};run checkmmcfile;\n" \
- " run burncommon;\n" \
- " arg_filename=${ramdiskimage};arg_partition=${ramdisk_partition};arg_writecmd=write.i;\n" \
- " run burnfile;\n" \
+ " run _initmmc;\n" \
+ " arg_filename=${ramdiskimage};run _checkmmcfile;\n" \
+ " run _burncommon;\n" \
+ " arg_filename=${ramdiskimage};arg_partition=${ramdisk_partition};run _burnfile;\n" \
" if test $error = '';then;else\n" \
" setenv kernel_location nand-part\n" \
" setenv rootfs_location nand-part\n" \
" setenv rootfs_type ramdisk\n" \
" saveenv\n" \
" fi\n" \
- " run checkerror;\n" \
+ " run _checkerror;\n" \
" fi" \
"\0" \
- "makeyaffsboot=if true;then;\n" \
+ "makeyaffsboot=run _makeyaffsboot\0_makeyaffsboot=if true;then;\n" \
" setenv error;\n" \
- " run initmmc;\n" \
- " arg_filename=${yaffsimage};run checkmmcfile;\n" \
- " run burncommon;\n" \
- " arg_filename=${yaffsimage};arg_partition=${yaffs_partition};arg_writecmd=write.yaffs;\n" \
- " run burnfile;\n" \
+ " run _initmmc;\n" \
+ " arg_filename=${yaffsimage};run _checkmmcfile;\n" \
+ " run _burncommon;\n" \
+ " arg_filename=${yaffsimage};arg_partition=${yaffs_partition};run _burnfile\n" \
" if test $error = '';then;else\n" \
" setenv kernel_location nand-part\n" \
" setenv rootfs_location /dev\n" \
@@ -659,7 +655,7 @@
" setenv rootfs_device /dev/mtdblock5\n" \
" saveenv\n" \
" fi\n" \
- " run checkerror;\n" \
+ " run _checkerror;\n" \
" fi" \
"\0"
diff --git a/include/fastboot.h b/include/fastboot.h
new file mode 100644
index 0000000000..5bf06b3f32
--- /dev/null
+++ b/include/fastboot.h
@@ -0,0 +1,377 @@
+/*
+ * (C) Copyright 2008 - 2009
+ * Windriver, <www.windriver.com>
+ * Tom Rix <Tom.Rix@windriver.com>
+ *
+ * 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
+ *
+ * The logical naming of flash comes from the Android project
+ * Thse structures and functions that look like fastboot_flash_*
+ * They come from bootloader/legacy/include/boot/flash.h
+ *
+ * The boot_img_hdr structure and associated magic numbers also
+ * come from the Android project. They are from
+ * system/core/mkbootimg/bootimg.h
+ *
+ * Here are their copyrights
+ *
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef FASTBOOT_H
+#define FASTBOOT_H
+
+#include <common.h>
+#include <command.h>
+
+/* This is the interface file between the common cmd_fastboot.c and
+ the board specific support.
+
+ To use this interface, define CONFIG_FASTBOOT in your board config file.
+ An example is include/configs/omap3430labrador.h
+ ...
+ #define CONFIG_FASTBOOT 1 / * Using fastboot interface * /
+ ...
+
+ An example of the board specific spupport for omap3 is found at
+ cpu/omap3/fastboot.c
+
+*/
+
+/* From fastboot client.. */
+#define FASTBOOT_INTERFACE_CLASS 0xff
+#define FASTBOOT_INTERFACE_SUB_CLASS 0x42
+#define FASTBOOT_INTERFACE_PROTOCOL 0x03
+
+#define FASTBOOT_VERSION "0.5"
+
+/* The fastboot client uses a value of 2048 for the
+ page size of it boot.img file format.
+ Reset this in your board config file as needed. */
+#ifndef CONFIG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE
+#define CONFIG_FASTBOOT_MKBOOTIMAGE_PAGE_SIZE 2048
+#endif
+
+/* Fastboot bulk packet sizes */
+#define CONFIG_USBD_FASTBOOT_BULK_PKTSIZE_HS 512
+#define CONFIG_USBD_FASTBOOT_BULK_PKTSIZE_FS 64
+
+/* Flags */
+#define FASTBOOT_FLAG_RESPONSE 1
+#define FASTBOOT_FLAG_DOWNLOAD 1
+
+/* To change design of memory handling (SD/MMC, NAND) faster, if required */
+#define FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING
+/* To activate-deactivate fastboot upload command (not part of OmapZoom) */
+// #define FASTBOOT_UPLOAD
+
+struct cmd_fastboot_interface{
+
+ /* A getvar string for the product name
+ It can have a maximum of 60 characters
+
+ Set by board */
+ char *product_name;
+
+ /* A getvar string for the serial number
+ It can have a maximum of 60 characters
+
+ Set by board */
+ char *serial_no;
+
+ /* Nand block size
+ Supports the write option WRITE_NEXT_GOOD_BLOCK
+
+ Set by board */
+ unsigned int nand_block_size;
+
+ /* Nand oob size
+ Set by board */
+ unsigned int nand_oob_size;
+
+ /* Transfer buffer, for handling flash updates
+ Should be multiple of the nand_block_size
+ Care should be take so it does not overrun bootloader memory
+ Controlled by the configure variable CONFIG_FASTBOOT_TRANSFER_BUFFER
+
+ Set by board */
+ unsigned char *transfer_buffer;
+
+ /* How big is the transfer buffer
+ Controlled by the configure variable
+ CONFIG_FASTBOOT_TRANSFER_BUFFER_SIZE
+
+ Set by board */
+ unsigned int transfer_buffer_size;
+
+ /* Download size, if download has to be done. This can be checked to find
+ whether next packet is a command or a data */
+ unsigned int d_size;
+
+ /* Data downloaded so far */
+ unsigned int d_bytes;
+
+ /* Upload size, if download has to be done */
+ unsigned int u_size;
+
+ /* Data uploaded so far */
+ unsigned int u_bytes;
+
+ /* XXX: what should be the size, 64 or 65 ? */
+ char response[65];
+
+ /* Indicate response to be sent, data to be recieved */
+ unsigned int flag;
+
+ /* configuration status */
+ unsigned int configured;
+
+#ifdef FASTBOOT_PORT_OMAPZOOM_NAND_FLASHING
+ unsigned int download_bytes_unpadded;
+#endif
+
+ unsigned int exit;
+};
+
+/* Android-style flash naming */
+typedef struct fastboot_ptentry fastboot_ptentry;
+
+/* flash partitions are defined in terms of blocks
+** (flash erase units)
+*/
+struct fastboot_ptentry{
+
+ /* The logical name for this partition, null terminated */
+ char name[16];
+ /* The start wrt the nand part, must be multiple of nand block size */
+ unsigned int start;
+ /* The length of the partition, must be multiple of nand block size */
+ unsigned int length;
+ /* Controls the details of how operations are done on the partition
+ See the FASTBOOT_PTENTRY_FLAGS_*'s defined below */
+ unsigned int flags;
+};
+
+/* Lower byte shows if the read/write/erase operation in
+ repeated. The base address is incremented.
+ Either 0 or 1 is ok for a default */
+
+#define FASTBOOT_PTENTRY_FLAGS_REPEAT_MASK(n) (n & 0x0f)
+#define FASTBOOT_PTENTRY_FLAGS_REPEAT_4 0x00000004
+
+/* Writes happen a block at a time.
+ If the write fails, go to next block
+ NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_NEXT_GOOD_BLOCK 0x00000010
+
+/* Find a contiguous block big enough for a the whole file
+ NEXT_GOOD_BLOCK and CONTIGOUS_BLOCK can not both be set */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_CONTIGUOUS_BLOCK 0x00000020
+
+/* Sets the ECC to hardware before writing
+ HW and SW ECC should not both be set. */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_HW_ECC 0x00000040
+
+/* Sets the ECC to software before writing
+ HW and SW ECC should not both be set. */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_SW_ECC 0x00000080
+
+/* Write the file with write.i */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_I 0x00000100
+
+/* Write the file with write.jffs2 */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_JFFS2 0x00000200
+
+/* Write the file as a series of variable/value pairs
+ using the setenv and saveenv commands */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_ENV 0x00000400
+
+/* Sets the NANDECC to use Kernel/FS layout for writing */
+#define FASTBOOT_PTENTRY_FLAGS_HW_ECC_LAYOUT_1 0x00000800
+
+/* Sets the NANDECC to use X-loader/U-boot layout for writing */
+#define FASTBOOT_PTENTRY_FLAGS_HW_ECC_LAYOUT_2 0x00001000
+
+/* Sets the ECC to software before writing
+ HW and SW ECC should not both be set. */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_CHIP_ECC 0x00002000
+
+/* Write the file with write.yaffs */
+#define FASTBOOT_PTENTRY_FLAGS_WRITE_YAFFS 0x00004000
+
+/* Status values */
+#define FASTBOOT_OK 0
+#define FASTBOOT_ERROR -1
+#define FASTBOOT_DISCONNECT 1
+#define FASTBOOT_INACTIVE 2
+
+/* Android bootimage file format */
+#define FASTBOOT_BOOT_MAGIC "ANDROID!"
+#define FASTBOOT_BOOT_MAGIC_SIZE 8
+#define FASTBOOT_BOOT_NAME_SIZE 16
+#define FASTBOOT_BOOT_ARGS_SIZE 512
+
+struct fastboot_boot_img_hdr {
+ unsigned char magic[FASTBOOT_BOOT_MAGIC_SIZE];
+
+ unsigned kernel_size; /* size in bytes */
+ unsigned kernel_addr; /* physical load addr */
+
+ unsigned ramdisk_size; /* size in bytes */
+ unsigned ramdisk_addr; /* physical load addr */
+
+ unsigned second_size; /* size in bytes */
+ unsigned second_addr; /* physical load addr */
+
+ unsigned tags_addr; /* physical addr for kernel tags */
+ unsigned page_size; /* flash page size we assume */
+ unsigned unused[2]; /* future expansion: should be 0 */
+
+ unsigned char name[FASTBOOT_BOOT_NAME_SIZE]; /* asciiz product name */
+
+ unsigned char cmdline[FASTBOOT_BOOT_ARGS_SIZE];
+
+ unsigned id[8]; /* timestamp / checksum / sha1 / etc */
+};
+
+#ifdef CONFIG_CMD_FASTBOOT
+/* A board specific test if u-boot should go into the fastboot command
+ ahead of the bootcmd
+ Returns 0 to continue with normal u-boot flow
+ Returns 1 to execute fastboot */
+extern int fastboot_preboot(void);
+
+/* Initizes the board specific fastboot
+ Returns 0 on success
+ Returns 1 on failure */
+extern int fastboot_init(struct cmd_fastboot_interface *interface);
+
+/* Cleans up the board specific fastboot */
+extern void fastboot_shutdown(void);
+
+/*
+ * Handles board specific usb protocol exchanges
+ * Returns 0 on success
+ * Returns 1 on disconnects, break out of loop
+ * Returns 2 if no USB activity detected
+ * Returns -1 on failure, unhandled usb requests and other error conditions
+*/
+extern int fastboot_poll(void);
+
+/* Is this high speed (2.0) or full speed (1.1) ?
+ Returns 0 on full speed
+ Returns 1 on high speed */
+extern int fastboot_is_highspeed(void);
+
+/* Return the size of the fifo */
+extern int fastboot_fifo_size(void);
+
+/* Send a status reply to the client app
+ buffer does not have to be null terminated.
+ buffer_size must be not be larger than what is returned by
+ fastboot_fifo_size
+ Returns 0 on success
+ Returns 1 on failure */
+extern int fastboot_tx_status(const char *buffer, unsigned int buffer_size);
+
+/*
+ * Send some data to the client app
+ * buffer does not have to be null terminated.
+ * buffer_size can be larger than what is returned by
+ * fastboot_fifo_size
+ * Returns number of bytes written
+ */
+extern int fastboot_tx(unsigned char *buffer, unsigned int buffer_size);
+
+/* A board specific variable handler.
+ The size of the buffers is governed by the fastboot spec.
+ rx_buffer is at most 57 bytes
+ tx_buffer is at most 60 bytes
+ Returns 0 on success
+ Returns 1 on failure */
+extern int fastboot_getvar(const char *rx_buffer, char *tx_buffer);
+
+/* The Android-style flash handling */
+
+/* tools to populate and query the partition table */
+extern void fastboot_flash_add_ptn(fastboot_ptentry *ptn);
+extern fastboot_ptentry *fastboot_flash_find_ptn(const char *name);
+extern fastboot_ptentry *fastboot_flash_get_ptn(unsigned n);
+extern unsigned int fastboot_flash_get_ptn_count(void);
+extern void fastboot_flash_dump_ptn(void);
+
+extern int fastboot_flash_init(void);
+extern int fastboot_flash_erase(fastboot_ptentry *ptn);
+extern int fastboot_flash_read_ext(fastboot_ptentry *ptn,
+ unsigned extra_per_page, unsigned offset,
+ void *data, unsigned bytes);
+#define fastboot_flash_read(ptn, offset, data, bytes) \
+ flash_read_ext(ptn, 0, offset, data, bytes)
+extern int fastboot_flash_write(fastboot_ptentry *ptn, unsigned extra_per_page,
+ const void *data, unsigned bytes);
+
+
+#else
+
+/* Stubs for when CONFIG_FASTBOOT is not defined */
+#define fastboot_preboot() 0
+#define fastboot_init(a) 1
+#define fastboot_shutdown()
+#define fastboot_poll() 1
+#define fastboot_is_highspeed() 0
+#define fastboot_fifo_size() 0
+#define fastboot_tx_status(a, b) 1
+#define fastboot_getvar(a, b) 1
+#define fastboot_tx(a, b) 1
+
+#define fastboot_flash_add_ptn(a)
+#define fastboot_flash_find_ptn(a) NULL
+#define fastboot_flash_get_ptn(a) NULL
+#define fastboot_flash_get_ptn_count() 0
+#define fastboot_flash_dump_ptn()
+#define fastboot_flash_init()
+#define fastboot_flash_erase(a) 1
+#define fastboot_flash_read_ext(a, b, c, d, e) 0
+#define fastboot_flash_read(a, b, c, d, e) 0
+#define fastboot_flash_write(a, b, c, d) 0
+
+#endif /* CONFIG_FASTBOOT */
+#endif /* FASTBOOT_H */
diff --git a/include/jffs2/load_kernel.h b/include/jffs2/load_kernel.h
index 7d549d957f..4b2da4c61a 100644
--- a/include/jffs2/load_kernel.h
+++ b/include/jffs2/load_kernel.h
@@ -35,6 +35,18 @@
#define MTD_DEV_TYPE(type) ((type == MTD_DEV_TYPE_NAND) ? "nand" : \
(type == MTD_DEV_TYPE_ONENAND) ? "onenand" : "nor")
+enum mtdflags
+{
+ MTDFLAGS_ECC_SW,
+ MTDFLAGS_ECC_HW,
+ MTDFLAGS_ECC_CHIP,
+ MTDFLAGS_ECC_BCH,
+ MTDFLAGS_YAFFS,
+ MTDFLAGS_REPEAT,
+};
+
+#define MTDFLAGS_DEFAULT_PERMITTED ((1 << MTDFLAGS_ECC_SW) | (1 << MTDFLAGS_ECC_HW) | (1 << MTDFLAGS_ECC_CHIP) | (1 << MTDFLAGS_ECC_BCH))
+
struct mtd_device {
struct list_head link;
struct mtdids *id; /* parent mtd id entry */
@@ -51,6 +63,7 @@ struct part_info {
void *jffs2_priv; /* used internaly by jffs2 */
u32 mask_flags; /* kernel MTD mask flags */
u32 sector_size; /* size of sector */
+ u32 mtdflags_mask; /* (1 << enum mtdflags) mask */
struct mtd_device *dev; /* parent device */
};
diff --git a/include/linux/string.h b/include/linux/string.h
index 62390399b0..69d5a61b98 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -26,6 +26,9 @@ extern char * strcpy(char *,const char *);
#ifndef __HAVE_ARCH_STRNCPY
extern char * strncpy(char *,const char *, __kernel_size_t);
#endif
+#ifndef __HAVE_ARCH_STPNCPY
+extern char * stpncpy(char * dest,const char *src,size_t count);
+#endif
#ifndef __HAVE_ARCH_STRCAT
extern char * strcat(char *, const char *);
#endif
diff --git a/include/mtd_parts.h b/include/mtd_parts.h
index 87e2882c69..9f383eece2 100644
--- a/include/mtd_parts.h
+++ b/include/mtd_parts.h
@@ -32,4 +32,5 @@ extern void mtd_set_part_priv(void *cookie, void *priv);
extern int mtd_id_parse(const char *id, const char **ret_id,
u8 *dev_type, u8 *dev_num, int quiet);
extern int mtdparts_init(void);
+extern int mtd_part_getmask(struct part_info *part);
#endif
diff --git a/include/nand.h b/include/nand.h
index d135927a29..0b87ca3260 100644
--- a/include/nand.h
+++ b/include/nand.h
@@ -131,6 +131,11 @@ int nand_get_lock_status(nand_info_t *meminfo, loff_t offset);
int nand_get_features( nand_info_t *meminfo, uint8_t faddr, uint8_t *features);
int nand_set_features( nand_info_t *meminfo, uint8_t faddr, uint8_t *features);
+#if CONFIG_OMAP3_LOGIC
+/* Function to disable the NAND in-chip ECC (if applicable) */
+void nand_disable_in_chip_ecc(void);
+#endif
+
#ifdef CONFIG_SYS_NAND_SELECT_DEVICE
void board_nand_select_device(struct nand_chip *nand, int chip);
#endif
diff --git a/include/twl4030.h b/include/twl4030.h
index ec6bc82774..271a7d2a18 100644
--- a/include/twl4030.h
+++ b/include/twl4030.h
@@ -305,6 +305,7 @@
#define TWL4030_PM_RECEIVER_MAINREF_REMAP 0xF1
/* Voltage Selection in PM Receiver Module */
+#define TWL4030_PM_RECEIVER_VAUX1_VSEL_30 0x04
#define TWL4030_PM_RECEIVER_VAUX2_VSEL_18 0x05
#define TWL4030_PM_RECEIVER_VAUX3_VSEL_28 0x03
#define TWL4030_PM_RECEIVER_VPLL2_VSEL_18 0x05
diff --git a/include/usb/musb_udc.h b/include/usb/musb_udc.h
index be808fd516..efd5b9eaab 100644
--- a/include/usb/musb_udc.h
+++ b/include/usb/musb_udc.h
@@ -50,4 +50,8 @@ int udc_init(void);
#endif /* CONFIG_USB_TTY */
+#ifdef CONFIG_CMD_FASTBOOT
+#define EP0_MAX_PACKET_SIZE 64
+#endif /* CONFIG_FASTBOOT */
+
#endif /* __MUSB_UDC_H__ */
diff --git a/include/usbdevice.h b/include/usbdevice.h
index 41716364b3..d46fa06789 100644
--- a/include/usbdevice.h
+++ b/include/usbdevice.h
@@ -291,8 +291,9 @@ struct usb_bus_instance;
* USB Spec Release number
*/
+#ifndef USB_BCD_VERSION
#define USB_BCD_VERSION 0x0110
-
+#endif
/*
* Device Requests (c.f Table 9-2)
@@ -467,7 +468,11 @@ typedef struct urb_link {
* function driver to inform it that data has arrived.
*/
+#if USB_BCD_VERSION == 0x0200
+#define URB_BUF_SIZE 2048
+#else
#define URB_BUF_SIZE 128 /* in linux we'd malloc this, but in u-boot we prefer static data */
+#endif
struct urb {
struct usb_endpoint_instance *endpoint;
@@ -595,6 +600,7 @@ struct usb_device_instance {
unsigned long usbd_rxtx_timestamp;
unsigned long usbd_last_rxtx_timestamp;
+ unsigned int speed;
};
/* Bus Interface configuration structure
diff --git a/lib/string.c b/lib/string.c
index b375b8124a..24391d24ee 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -72,6 +72,29 @@ char * strcpy(char * dest,const char *src)
}
#endif
+#ifndef __HAVE_ARCH_STPNCPY
+/**
+ * strncpy - Copy a length-limited, %NUL-terminated string
+ * @dest: Where to copy the string to
+ * @src: Where to copy the string from
+ * @count: The maximum number of bytes to copy
+ *
+ * Note that unlike userspace strncpy, this does not %NUL-pad the buffer.
+ * However, the result is not %NUL-terminated if the source exceeds
+ * @count bytes.
+ */
+char * stpncpy(char * dest,const char *src,size_t count)
+{
+ while (count-- && (*dest++ = *src++) != '\0')
+ /* nothing */;
+
+ if(count)
+ return dest-1;
+ else
+ return dest;
+}
+#endif
+
#ifndef __HAVE_ARCH_STRNCPY
/**
* strncpy - Copy a length-limited, %NUL-terminated string