diff --git a/board/davinci/sysmobts_v2/sysmobts_v2.c b/board/davinci/sysmobts_v2/sysmobts_v2.c index dbea937fa7..c40358a9b0 100644 --- a/board/davinci/sysmobts_v2/sysmobts_v2.c +++ b/board/davinci/sysmobts_v2/sysmobts_v2.c @@ -32,6 +32,7 @@ #include #include #include +#include #define DAVINCI_PLLM (0x01C40910) /* PLL 1 Multiplier */ #define DAVINCI_AWCCR (0x01E00004) /* EMIF-A async wait cycle config register. */ @@ -139,12 +140,24 @@ int board_init(void) lpsc_on(DAVINCI_LPSC_TIMER1); timer_init(); - /* configure LEDs */ - status_led_set(0, CONFIG_LED_STATUS_OFF); - return(0); } +int board_late_init(void) +{ +#ifdef CONFIG_PREBOOT + /* remember if we are in reset */ + if (gpio_get_value(38) == 0) { + setenv("preboot", "run_recovery"); + status_led_set(0, CONFIG_LED_STATUS_ON); + } else { + /* configure LEDs */ + status_led_set(0, CONFIG_LED_STATUS_OFF); + } +#endif + return 0; +} + int misc_init_r(void) { uint8_t eeprom_enetaddr[6]; diff --git a/common/Makefile b/common/Makefile index 86225f1564..43549a7d55 100644 --- a/common/Makefile +++ b/common/Makefile @@ -63,6 +63,7 @@ ifdef CONFIG_CMD_USB obj-y += usb.o usb_hub.o obj-$(CONFIG_USB_STORAGE) += usb_storage.o endif +obj-$(CONFIG_CMD_RECOVERY) += cmd_recovery.o # others obj-$(CONFIG_BOOTSTAGE) += bootstage.o diff --git a/common/cmd_recovery.c b/common/cmd_recovery.c new file mode 100644 index 0000000000..5ba5b9e576 --- /dev/null +++ b/common/cmd_recovery.c @@ -0,0 +1,144 @@ +/* + * Copyright (C) 2012, 2013, 2015, 2017 sysmocom s.f.m.c. GmbH + * Author: Holger Hans Peter Freyther + + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include +#include +#include +#include + +#include + +#define BLINK_LED(LEN) \ + do { \ + int i; \ + for (i = 0; i < LEN; ++i) { \ + status_led_set(0, CONFIG_LED_STATUS_OFF); \ + udelay(900); \ + status_led_set(0, CONFIG_LED_STATUS_ON); \ + } \ + status_led_set(0, CONFIG_LED_STATUS_OFF); \ + } while(0); + +static int enable_netconsole(void) +{ + printf("Enabling the network console.\n"); + + /* reset in 60s if it is not interrupted */ + return run_command("setenv stdout nc; setenv stdin nc", 0); +} + +static int env_failed(void) +{ + printf("Environment clearing failed.\n"); + + BLINK_LED(7); + return -1; +} + +static int dhcp_failed(void) +{ + printf("DHCP failed. Giving up on recovery.\n"); + + BLINK_LED(10); + return -1; +} + +static int tftp_failed(void) +{ + printf("TFTP failed.\n"); + BLINK_LED(13); + enable_netconsole(); + return -1; +} + +static int flash_failed(void) +{ + printf("Flash failed.\n"); + BLINK_LED(15); + enable_netconsole(); + return -1; +} + +/** + * This will run the recovery process. + * 1.) Enable the LED to give instant feedback. + * 2.) Clear the environment in case of bad configuration. + * 3.) Get a DHCP lease. + * 4.) Try to tftpboot + * 5.) Try to tftpboot with a different server + * 6.) Flash + * 7.) Reset or enter netconsole + */ +static int do_run_recovery(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) +{ + int rc; + + status_led_set(0, CONFIG_LED_STATUS_ON); + printf("Starting the recovery process.\n"); + + /* Wait a bit and check if the reset button is still pressed */ + if (argc == 2 && strcmp(argv[1], "force") == 0) { + printf("Forcing the recovery process.\n"); + } else { + run_command("sleep 5", 0); + if (gpio_get_value(38) != 0) { + printf("Recovery process aborted.\n"); + run_command("dhcp", 0); + enable_netconsole(); + BLINK_LED(4); + return 0; + } + } + + BLINK_LED(5); + status_led_set(0, CONFIG_LED_STATUS_ON); + + rc = run_command("mtdpart default; " + "nand erase.part U-Boot-Environment", 0); + if (rc != 0) + return env_failed(); + + rc = run_command("setenv autoload no; setenv netretry no; dhcp", 0); + if (rc != 0) + return dhcp_failed(); + + rc = run_command("setenv filesize 0; " + "tftp 85000000 sysmocom-recovery.ubi", 0); + if (rc != 0) { + rc = run_command("setenv filesize 0; " + "setenv serverip 255.255.255.255; " + "tftp 85000000 sysmocom-recovery.ubi", 0); + } + + if (rc != 0) + return tftp_failed(); + + rc = run_command("nand erase.part RootFs; " + "nand write 85000000 RootFs ${filesize} ", 0); + if (rc != 0) + return flash_failed(); + + return run_command("reset", 0); +} + +U_BOOT_CMD( + run_recovery, CONFIG_SYS_MAXARGS, 1, do_run_recovery, + "Run the sysmocom sysmoBTS recovery process", + "[force]" +); diff --git a/include/configs/davinci_sysmobts_v2.h b/include/configs/davinci_sysmobts_v2.h index e9826f4785..21517a1901 100644 --- a/include/configs/davinci_sysmobts_v2.h +++ b/include/configs/davinci_sysmobts_v2.h @@ -189,6 +189,14 @@ #define CONFIG_DM644X_GPIO #define CONFIG_CMD_GPIO +/*=======================*/ +/* Recovery handling */ +/*=======================*/ +#define CONFIG_PREBOOT +#define CONFIG_CMD_RECOVERY +#define CONFIG_NETCONSOLE +#define CONFIG_BOARD_LATE_INIT + /* bdinfo should show the clocks */ #ifdef CONFIG_CMD_BDI diff --git a/scripts/config_whitelist.txt b/scripts/config_whitelist.txt index 98d135283f..0ec067b00b 100644 --- a/scripts/config_whitelist.txt +++ b/scripts/config_whitelist.txt @@ -526,6 +526,7 @@ CONFIG_CMD_PCI_ENUM CONFIG_CMD_PCMCIA CONFIG_CMD_PORTIO CONFIG_CMD_READ +CONFIG_CMD_RECOVERY CONFIG_CMD_REGINFO CONFIG_CMD_REISER CONFIG_CMD_SANDBOX