diff options
author | Justin Waters <justin.waters@timesys.com> | 2013-04-24 17:41:45 -0400 |
---|---|---|
committer | Justin Waters <justin.waters@timesys.com> | 2013-04-24 17:41:45 -0400 |
commit | 18282017b14c0b32b4aa6fd05df58ba5cff0b472 (patch) | |
tree | 24344ef4d64f38baee4f5b56a9b44cc775ab4b62 | |
parent | 75c641ece39c136001340df61f0ad57028ce4ffc (diff) |
LogicPD Support for OMAP3/DM3/AM3 boards 2.2 Update
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 18133d876d0..81df64d82a3 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 598457610f0..09bce91bba9 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 def013768c2..94f53c41b4b 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 cb45504c228..8c4f364d01a 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 08e6acb2615..b0f3a5eca17 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 e1f03db2ce1..f5e70c50d2c 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 ba4633bf891..dfcfb61cba7 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 3142511d973..edc440945f2 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 b6c16b1d402..82ee77ce15c 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 14290392206..69a2e2b3ca2 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 f3ad4bdd63b..bb23c0af006 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 00000000000..97d1c232170 --- /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 32d6c899d14..a32762f5f21 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 9b7a0a73e3a..509c85e3036 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 85a946828e5..3b89d4e0ef9 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 1092a797321..f37d45bdc4c 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 1a636cad236..865065e03b3 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 b62ed176d25..92c8fd75b59 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 6f6ed61d08b..3ebdcf1daf4 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 9ba1e937116..146a1c12b0c 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 5dfeb9bb724..6c91462576a 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 00000000000..5bf06b3f32f --- /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 7d549d957fe..4b2da4c61a7 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 62390399b0b..69d5a61b985 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 87e2882c697..9f383eece2e 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 d135927a293..0b87ca3260d 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 ec6bc827743..271a7d2a187 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 be808fd516b..efd5b9eaab1 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 41716364b31..d46fa06789c 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 b375b8124a9..24391d24ee8 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 |