uboot/board/ait/cam_enc_4xx/cam_enc_4xx.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2009 Texas Instruments Incorporated
   3 *
   4 * Copyright (C) 2011
   5 * Heiko Schocher, DENX Software Engineering, hs@denx.de.
   6 *
   7 * SPDX-License-Identifier:     GPL-2.0+
   8 */
   9
  10#include <common.h>
  11#include <errno.h>
  12#include <hush.h>
  13#include <linux/mtd/nand.h>
  14#include <nand.h>
  15#include <miiphy.h>
  16#include <netdev.h>
  17#include <asm/io.h>
  18#include <asm/arch/hardware.h>
  19#include <asm/arch/nand_defs.h>
  20#include <asm/arch/davinci_misc.h>
  21#ifdef CONFIG_DAVINCI_MMC
  22#include <mmc.h>
  23#include <asm/arch/sdmmc_defs.h>
  24#endif
  25
  26DECLARE_GLOBAL_DATA_PTR;
  27
  28#ifndef CONFIG_SPL_BUILD
  29static struct davinci_timer *timer =
  30        (struct davinci_timer *)DAVINCI_TIMER3_BASE;
  31
  32static unsigned long get_timer_val(void)
  33{
  34        unsigned long now = readl(&timer->tim34);
  35
  36        return now;
  37}
  38
  39static int timer_running(void)
  40{
  41        return readl(&timer->tcr) &
  42                (DV_TIMER_TCR_ENAMODE_MASK << DV_TIMER_TCR_ENAMODE34_SHIFT);
  43}
  44
  45static void stop_timer(void)
  46{
  47        writel(0x0, &timer->tcr);
  48        return;
  49}
  50
  51int checkboard(void)
  52{
  53        printf("Board: AIT CAM ENC 4XX\n");
  54        return 0;
  55}
  56
  57int board_init(void)
  58{
  59        gd->bd->bi_boot_params = PHYS_SDRAM_1 + 0x100;
  60
  61        return 0;
  62}
  63
  64#ifdef CONFIG_DRIVER_TI_EMAC
  65static int cam_enc_4xx_check_network(void)
  66{
  67        char *s;
  68
  69        s = getenv("ethaddr");
  70        if (!s)
  71                return -EINVAL;
  72
  73        if (!is_valid_ether_addr((const u8 *)s))
  74                return -EINVAL;
  75
  76        s = getenv("ipaddr");
  77        if (!s)
  78                return -EINVAL;
  79
  80        s = getenv("netmask");
  81        if (!s)
  82                return -EINVAL;
  83
  84        s = getenv("serverip");
  85        if (!s)
  86                return -EINVAL;
  87
  88        s = getenv("gatewayip");
  89        if (!s)
  90                return -EINVAL;
  91
  92        return 0;
  93}
  94int board_eth_init(bd_t *bis)
  95{
  96        int ret;
  97
  98        ret = cam_enc_4xx_check_network();
  99        if (ret)
 100                return ret;
 101
 102        davinci_emac_initialize();
 103
 104        return 0;
 105}
 106#endif
 107
 108#ifdef CONFIG_NAND_DAVINCI
 109static int
 110davinci_std_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip,
 111                                   uint8_t *buf, int oob_required, int page)
 112{
 113        struct nand_chip *this = mtd->priv;
 114        int i, eccsize = chip->ecc.size;
 115        int eccbytes = chip->ecc.bytes;
 116        int eccsteps = chip->ecc.steps;
 117        uint8_t *p = buf;
 118        uint8_t *oob = chip->oob_poi;
 119
 120        chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
 121
 122        chip->read_buf(mtd, oob, mtd->oobsize);
 123
 124        chip->cmdfunc(mtd, NAND_CMD_READ0, 0x0, page & this->pagemask);
 125
 126
 127        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 128                int stat;
 129
 130                chip->ecc.hwctl(mtd, NAND_ECC_READ);
 131                chip->read_buf(mtd, p, eccsize);
 132                chip->ecc.hwctl(mtd, NAND_ECC_READSYN);
 133
 134                if (chip->ecc.prepad)
 135                        oob += chip->ecc.prepad;
 136
 137                stat = chip->ecc.correct(mtd, p, oob, NULL);
 138
 139                if (stat == -1)
 140                        mtd->ecc_stats.failed++;
 141                else
 142                        mtd->ecc_stats.corrected += stat;
 143
 144                oob += eccbytes;
 145
 146                if (chip->ecc.postpad)
 147                        oob += chip->ecc.postpad;
 148        }
 149
 150        /* Calculate remaining oob bytes */
 151        i = mtd->oobsize - (oob - chip->oob_poi);
 152        if (i)
 153                chip->read_buf(mtd, oob, i);
 154
 155        return 0;
 156}
 157
 158static int davinci_std_write_page_syndrome(struct mtd_info *mtd,
 159                                    struct nand_chip *chip, const uint8_t *buf,
 160                                    int oob_required)
 161{
 162        unsigned char davinci_ecc_buf[NAND_MAX_OOBSIZE];
 163        struct nand_chip *this = mtd->priv;
 164        int i, eccsize = chip->ecc.size;
 165        int eccbytes = chip->ecc.bytes;
 166        int eccsteps = chip->ecc.steps;
 167        int chunk = chip->ecc.bytes + chip->ecc.prepad + chip->ecc.postpad;
 168        int offset = 0;
 169        const uint8_t *p = buf;
 170        uint8_t *oob = chip->oob_poi;
 171
 172        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
 173                chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
 174                chip->write_buf(mtd, p, eccsize);
 175
 176                /* Calculate ECC without prepad */
 177                chip->ecc.calculate(mtd, p, oob + chip->ecc.prepad);
 178
 179                if (chip->ecc.prepad) {
 180                        offset = (chip->ecc.steps - eccsteps) * chunk;
 181                        memcpy(&davinci_ecc_buf[offset], oob, chip->ecc.prepad);
 182                        oob += chip->ecc.prepad;
 183                }
 184
 185                offset = ((chip->ecc.steps - eccsteps) * chunk) +
 186                                chip->ecc.prepad;
 187                memcpy(&davinci_ecc_buf[offset], oob, eccbytes);
 188                oob += eccbytes;
 189
 190                if (chip->ecc.postpad) {
 191                        offset = ((chip->ecc.steps - eccsteps) * chunk) +
 192                                        chip->ecc.prepad + eccbytes;
 193                        memcpy(&davinci_ecc_buf[offset], oob,
 194                                chip->ecc.postpad);
 195                        oob += chip->ecc.postpad;
 196                }
 197        }
 198
 199        /*
 200         * Write the sparebytes into the page once
 201         * all eccsteps have been covered
 202         */
 203        for (i = 0; i < mtd->oobsize; i++)
 204                writeb(davinci_ecc_buf[i], this->IO_ADDR_W);
 205
 206        /* Calculate remaining oob bytes */
 207        i = mtd->oobsize - (oob - chip->oob_poi);
 208        if (i)
 209                chip->write_buf(mtd, oob, i);
 210        return 0;
 211}
 212
 213static int davinci_std_write_oob_syndrome(struct mtd_info *mtd,
 214                                   struct nand_chip *chip, int page)
 215{
 216        int pos, status = 0;
 217        const uint8_t *bufpoi = chip->oob_poi;
 218
 219        pos = mtd->writesize;
 220
 221        chip->cmdfunc(mtd, NAND_CMD_SEQIN, pos, page);
 222
 223        chip->write_buf(mtd, bufpoi, mtd->oobsize);
 224
 225        chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 226        status = chip->waitfunc(mtd, chip);
 227
 228        return status & NAND_STATUS_FAIL ? -1 : 0;
 229}
 230
 231static int davinci_std_read_oob_syndrome(struct mtd_info *mtd,
 232        struct nand_chip *chip, int page)
 233{
 234        struct nand_chip *this = mtd->priv;
 235        uint8_t *buf = chip->oob_poi;
 236        uint8_t *bufpoi = buf;
 237
 238        chip->cmdfunc(mtd, NAND_CMD_READOOB, 0x0, page & this->pagemask);
 239
 240        chip->read_buf(mtd, bufpoi, mtd->oobsize);
 241
 242        return 0;
 243}
 244
 245static void nand_dm365evm_select_chip(struct mtd_info *mtd, int chip)
 246{
 247        struct nand_chip        *this = mtd->priv;
 248        unsigned long           wbase = (unsigned long) this->IO_ADDR_W;
 249        unsigned long           rbase = (unsigned long) this->IO_ADDR_R;
 250
 251        if (chip == 1) {
 252                __set_bit(14, &wbase);
 253                __set_bit(14, &rbase);
 254        } else {
 255                __clear_bit(14, &wbase);
 256                __clear_bit(14, &rbase);
 257        }
 258        this->IO_ADDR_W = (void *)wbase;
 259        this->IO_ADDR_R = (void *)rbase;
 260}
 261
 262int board_nand_init(struct nand_chip *nand)
 263{
 264        davinci_nand_init(nand);
 265        nand->select_chip = nand_dm365evm_select_chip;
 266
 267        return 0;
 268}
 269
 270struct nand_ecc_ctrl org_ecc;
 271static int notsaved = 1;
 272
 273static int nand_switch_hw_func(int mode)
 274{
 275        struct nand_chip *nand;
 276        struct mtd_info *mtd;
 277
 278        if (nand_curr_device < 0 ||
 279            nand_curr_device >= CONFIG_SYS_MAX_NAND_DEVICE ||
 280            !nand_info[nand_curr_device].name) {
 281                printf("Error: Can't switch hw functions," \
 282                        " no devices available\n");
 283                return -1;
 284        }
 285
 286        mtd = &nand_info[nand_curr_device];
 287        nand = mtd->priv;
 288
 289        if (mode == 0) {
 290                if (notsaved == 0) {
 291                        printf("switching to uboot hw functions.\n");
 292                        memcpy(&nand->ecc, &org_ecc,
 293                                sizeof(struct nand_ecc_ctrl));
 294                }
 295        } else {
 296                /* RBL */
 297                printf("switching to RBL hw functions.\n");
 298                if (notsaved == 1) {
 299                        memcpy(&org_ecc, &nand->ecc,
 300                                sizeof(struct nand_ecc_ctrl));
 301                        notsaved = 0;
 302                }
 303                nand->ecc.mode = NAND_ECC_HW_SYNDROME;
 304                nand->ecc.prepad = 6;
 305                nand->ecc.read_page = davinci_std_read_page_syndrome;
 306                nand->ecc.write_page = davinci_std_write_page_syndrome;
 307                nand->ecc.read_oob = davinci_std_read_oob_syndrome;
 308                nand->ecc.write_oob = davinci_std_write_oob_syndrome;
 309        }
 310        return mode;
 311}
 312
 313static int hwmode;
 314
 315static int do_switch_ecc(cmd_tbl_t *cmdtp, int flag, int argc,
 316                char *const argv[])
 317{
 318        if (argc != 2)
 319                goto usage;
 320        if (strncmp(argv[1], "rbl", 2) == 0)
 321                hwmode = nand_switch_hw_func(1);
 322        else if (strncmp(argv[1], "uboot", 2) == 0)
 323                hwmode = nand_switch_hw_func(0);
 324        else
 325                goto usage;
 326
 327        return 0;
 328
 329usage:
 330        printf("Usage: nandrbl %s\n", cmdtp->usage);
 331        return 1;
 332}
 333
 334U_BOOT_CMD(
 335        nandrbl, 2, 1,  do_switch_ecc,
 336        "switch between rbl/uboot NAND ECC calculation algorithm",
 337        "[rbl/uboot] - Switch between rbl/uboot NAND ECC algorithm"
 338);
 339
 340
 341#endif /* #ifdef CONFIG_NAND_DAVINCI */
 342
 343#ifdef CONFIG_DAVINCI_MMC
 344static struct davinci_mmc mmc_sd0 = {
 345        .reg_base       = (struct davinci_mmc_regs *)DAVINCI_MMC_SD0_BASE,
 346        .input_clk      = 121500000,
 347        .host_caps      = MMC_MODE_4BIT,
 348        .voltages       = MMC_VDD_32_33 | MMC_VDD_33_34,
 349        .version        = MMC_CTLR_VERSION_2,
 350};
 351
 352int board_mmc_init(bd_t *bis)
 353{
 354        int err;
 355
 356        /* Add slot-0 to mmc subsystem */
 357        err = davinci_mmc_init(bis, &mmc_sd0);
 358
 359        return err;
 360}
 361#endif
 362
 363int board_late_init(void)
 364{
 365        struct davinci_gpio *gpio = davinci_gpio_bank45;
 366
 367        /* 24MHz InputClock / 15 prediv -> 1.6 MHz timer running */
 368        while ((get_timer_val() < CONFIG_AIT_TIMER_TIMEOUT) &&
 369                timer_running())
 370                ;
 371
 372        /* 1 sec reached -> stop timer, clear all LED */
 373        stop_timer();
 374        clrbits_le32(&gpio->out_data, CONFIG_CAM_ENC_LED_MASK);
 375        return 0;
 376}
 377
 378void reset_phy(void)
 379{
 380        char *name = "GENERIC @ 0x00";
 381
 382        /* reset the phy */
 383        miiphy_reset(name, 0x0);
 384}
 385
 386#else /* #ifndef CONFIG_SPL_BUILD */
 387static void cam_enc_4xx_set_all_led(void)
 388{
 389        struct davinci_gpio *gpio = davinci_gpio_bank45;
 390
 391        setbits_le32(&gpio->out_data, CONFIG_CAM_ENC_LED_MASK);
 392}
 393
 394/*
 395 * TIMER 0 is used for tick
 396 */
 397static struct davinci_timer *timer =
 398        (struct davinci_timer *)DAVINCI_TIMER3_BASE;
 399
 400#define TIMER_LOAD_VAL  0xffffffff
 401#define TIM_CLK_DIV     16
 402
 403static int cam_enc_4xx_timer_init(void)
 404{
 405        /* We are using timer34 in unchained 32-bit mode, full speed */
 406        writel(0x0, &timer->tcr);
 407        writel(0x0, &timer->tgcr);
 408        writel(0x06 | ((TIM_CLK_DIV - 1) << 8), &timer->tgcr);
 409        writel(0x0, &timer->tim34);
 410        writel(TIMER_LOAD_VAL, &timer->prd34);
 411        writel(2 << 22, &timer->tcr);
 412        return 0;
 413}
 414
 415void board_gpio_init(void)
 416{
 417        struct davinci_gpio *gpio;
 418
 419        cam_enc_4xx_set_all_led();
 420        cam_enc_4xx_timer_init();
 421        gpio = davinci_gpio_bank01;
 422        clrbits_le32(&gpio->dir, ~0xfdfffffe);
 423        /* clear LED D14 = GPIO25 */
 424        clrbits_le32(&gpio->out_data, 0x02000000);
 425        gpio = davinci_gpio_bank23;
 426        clrbits_le32(&gpio->dir, ~0x5ff0afef);
 427        /* set GPIO61 to 1 -> intern UART0 as Console */
 428        setbits_le32(&gpio->out_data, 0x20000000);
 429        /*
 430         * PHY out of reset GIO 50 = 1
 431         * NAND WP off GIO 51 = 1
 432         */
 433        setbits_le32(&gpio->out_data, 0x000c0004);
 434        gpio = davinci_gpio_bank45;
 435        clrbits_le32(&gpio->dir, ~(0xdb2fffff) | CONFIG_CAM_ENC_LED_MASK);
 436        /*
 437         * clear LED:
 438         * D17 = GPIO86
 439         * D11 = GPIO87
 440         * GPIO88
 441         * GPIO89
 442         * D13 = GPIO90
 443         * GPIO91
 444         */
 445        clrbits_le32(&gpio->out_data, CONFIG_CAM_ENC_LED_MASK);
 446        gpio = davinci_gpio_bank67;
 447        clrbits_le32(&gpio->dir, ~0x000007ff);
 448}
 449
 450/*
 451 * functions for the post memory test.
 452 */
 453int arch_memory_test_prepare(u32 *vstart, u32 *size, phys_addr_t *phys_offset)
 454{
 455        *vstart = CONFIG_SYS_SDRAM_BASE;
 456        *size = PHYS_SDRAM_1_SIZE;
 457        *phys_offset = 0;
 458        return 0;
 459}
 460
 461void arch_memory_failure_handle(void)
 462{
 463        cam_enc_4xx_set_all_led();
 464        puts("mem failure\n");
 465        while (1)
 466                ;
 467}
 468#endif
 469#if defined(CONFIG_MENU)
 470#include "menu.h"
 471
 472#define MENU_EXIT               -1
 473#define MENU_EXIT_BOOTCMD       -2
 474#define MENU_STAY               0
 475#define MENU_MAIN               1
 476#define MENU_UPDATE             2
 477#define MENU_NETWORK            3
 478#define MENU_LOAD               4
 479
 480static int menu_start;
 481
 482#define FIT_SUBTYPE_UNKNOWN             0
 483#define FIT_SUBTYPE_UBL_HEADER          1
 484#define FIT_SUBTYPE_SPL_IMAGE           2
 485#define FIT_SUBTYPE_UBOOT_IMAGE         3
 486#define FIT_SUBTYPE_DF_ENV_IMAGE        4
 487#define FIT_SUBTYPE_RAMDISK_IMAGE       5
 488
 489struct fit_images_info {
 490        u_int8_t type;
 491        int subtype;
 492        char desc[200];
 493        const void *data;
 494        size_t size;
 495};
 496
 497static struct fit_images_info imgs[10];
 498
 499struct menu_display {
 500        char    title[50];
 501        int     timeout; /* in sec */
 502        int     id; /* MENU_* */
 503        char    **menulist;
 504        int (*menu_evaluate)(char *choice);
 505};
 506
 507char *menu_main[] = {
 508        "(1) Boot",
 509        "(2) Update Software",
 510        "(3) Reset to default setting and boot",
 511        "(4) Enter U-Boot console",
 512        NULL
 513};
 514
 515char *menu_update[] = {
 516        "(1) Network settings",
 517        "(2) load image",
 518        "(3) back to main",
 519        NULL
 520};
 521
 522char *menu_load[] = {
 523        "(1) install image",
 524        "(2) cancel",
 525        NULL
 526};
 527
 528char *menu_network[] = {
 529        "(1) ipaddr   ",
 530        "(2) netmask  ",
 531        "(3) serverip ",
 532        "(4) gatewayip",
 533        "(5) tftp image name",
 534        "(6) back to update software",
 535        NULL
 536};
 537
 538static void ait_menu_print(void *data)
 539{
 540        printf("%s\n", (char *)data);
 541        return;
 542}
 543
 544static char *menu_handle(struct menu_display *display)
 545{
 546        struct menu *m;
 547        int i;
 548        void *choice = NULL;
 549        char key[2];
 550        int ret;
 551        char *s;
 552        char temp[6][200];
 553
 554        m = menu_create(display->title, display->timeout, 1, ait_menu_print,
 555                        NULL, NULL);
 556
 557        for (i = 0; display->menulist[i]; i++) {
 558                sprintf(key, "%d", i + 1);
 559                if (display->id == MENU_NETWORK) {
 560                        switch (i) {
 561                        case 0:
 562                                s = getenv("ipaddr");
 563                                break;
 564                        case 1:
 565                                s = getenv("netmask");
 566                                break;
 567                        case 2:
 568                                s = getenv("serverip");
 569                                break;
 570                        case 3:
 571                                s = getenv("gatewayip");
 572                                break;
 573                        case 4:
 574                                s = getenv("img_file");
 575                                break;
 576                        default:
 577                                s = NULL;
 578                                break;
 579                        }
 580                        if (s) {
 581                                sprintf(temp[i], "%s: %s",
 582                                        display->menulist[i], s);
 583                                ret = menu_item_add(m, key, temp[i]);
 584                        } else {
 585                                ret = menu_item_add(m, key,
 586                                        display->menulist[i]);
 587                        }
 588                } else {
 589                        ret = menu_item_add(m, key, display->menulist[i]);
 590                }
 591
 592                if (ret != 1) {
 593                        printf("failed to add item!");
 594                        menu_destroy(m);
 595                        return NULL;
 596                }
 597        }
 598        sprintf(key, "%d", 1);
 599        menu_default_set(m, key);
 600
 601        if (menu_get_choice(m, &choice) != 1)
 602                debug("Problem picking a choice!\n");
 603
 604        menu_destroy(m);
 605
 606        return choice;
 607}
 608
 609static int ait_menu_show(struct menu_display *display, int bootdelay)
 610{
 611        int end = MENU_STAY;
 612        char *choice;
 613
 614        if ((menu_start == 0) && (display->id == MENU_MAIN))
 615                display->timeout = bootdelay;
 616        else
 617                display->timeout = 0;
 618
 619        while (end == MENU_STAY) {
 620                choice = menu_handle(display);
 621                if (choice)
 622                        end = display->menu_evaluate(choice);
 623
 624                if (end == display->id)
 625                        end = MENU_STAY;
 626                if (display->id == MENU_MAIN) {
 627                        if (menu_start == 0)
 628                                end = MENU_EXIT_BOOTCMD;
 629                        else
 630                                display->timeout = 0;
 631                }
 632        }
 633        return end;
 634}
 635
 636static int ait_writeublheader(void)
 637{
 638        char s[20];
 639        unsigned long i;
 640        int ret;
 641
 642        for (i = CONFIG_SYS_NAND_BLOCK_SIZE;
 643                i < CONFIG_SYS_NAND_U_BOOT_OFFS;
 644                i += CONFIG_SYS_NAND_BLOCK_SIZE) {
 645                sprintf(s, "%lx", i);
 646                ret = setenv("header_addr", s);
 647                if (ret == 0)
 648                        ret = run_command("run img_writeheader", 0);
 649                if (ret != 0)
 650                        break;
 651        }
 652        return ret;
 653}
 654
 655static int ait_menu_install_images(void)
 656{
 657        int ret = 0;
 658        int count = 0;
 659        char s[100];
 660        char *t;
 661
 662        /*
 663         * possible image types:
 664         * FIT_SUBTYPE_UNKNOWN
 665         * FIT_SUBTYPE_UBL_HEADER
 666         * FIT_SUBTYPE_SPL_IMAGE
 667         * FIT_SUBTYPE_UBOOT_IMAGE
 668         * FIT_SUBTYPE_DF_ENV_IMAGE
 669         * FIT_SUBTYPE_RAMDISK_IMAGE
 670         *
 671         * use Envvariables:
 672         * img_addr_r: image start addr
 673         * header_addr: addr where to write to UBL header
 674         * img_writeheader: write ubl header to nand
 675         * img_writespl: write spl to nand
 676         * img_writeuboot: write uboot to nand
 677         * img_writedfenv: write default environment to ubi volume
 678         * img_volume: which ubi volume should be updated with img_writeramdisk
 679         * filesize: size of data for updating ubi volume
 680         * img_writeramdisk: write ramdisk to ubi volume
 681         */
 682
 683        while (imgs[count].type != IH_TYPE_INVALID) {
 684                printf("Installing %s\n",
 685                        genimg_get_type_name(imgs[count].type));
 686                sprintf(s, "%p", imgs[count].data);
 687                setenv("img_addr_r", s);
 688                sprintf(s, "%lx", (unsigned long)imgs[count].size);
 689                setenv("filesize", s);
 690                switch (imgs[count].subtype) {
 691                case FIT_SUBTYPE_DF_ENV_IMAGE:
 692                        ret = run_command("run img_writedfenv", 0);
 693                        break;
 694                case FIT_SUBTYPE_RAMDISK_IMAGE:
 695                        t = getenv("img_volume");
 696                        if (!t) {
 697                                ret = setenv("img_volume", "rootfs1");
 698                        } else {
 699                                /* switch to other volume */
 700                                if (strncmp(t, "rootfs1", 7) == 0)
 701                                        ret = setenv("img_volume", "rootfs2");
 702                                else
 703                                        ret = setenv("img_volume", "rootfs1");
 704                        }
 705                        if (ret != 0)
 706                                break;
 707
 708                        ret = run_command("run img_writeramdisk", 0);
 709                        break;
 710                case FIT_SUBTYPE_SPL_IMAGE:
 711                        ret = run_command("run img_writespl", 0);
 712                        break;
 713                case FIT_SUBTYPE_UBL_HEADER:
 714                        ret = ait_writeublheader();
 715                        break;
 716                case FIT_SUBTYPE_UBOOT_IMAGE:
 717                        ret = run_command("run img_writeuboot", 0);
 718                        break;
 719                default:
 720                        /* not supported type */
 721                        break;
 722                }
 723                count++;
 724        }
 725        /* now save dvn_* and img_volume env vars to new values */
 726        if (ret == 0) {
 727                t = getenv("x_dvn_boot_vers");
 728                if (t)
 729                        setenv("dvn_boot_vers", t);
 730
 731                t = getenv("x_dvn_app_vers");
 732                if (t)
 733                        setenv("dvn_boot_vers", t);
 734
 735                setenv("x_dvn_boot_vers", NULL);
 736                setenv("x_dvn_app_vers", NULL);
 737                ret = run_command("run savenewvers", 0);
 738        }
 739
 740        return ret;
 741}
 742
 743static int ait_menu_evaluate_load(char *choice)
 744{
 745        if (!choice)
 746                return -1;
 747
 748        switch (choice[1]) {
 749        case '1':
 750                /* install image */
 751                ait_menu_install_images();
 752                break;
 753        case '2':
 754                /* cancel, back to main */
 755                setenv("x_dvn_boot_vers", NULL);
 756                setenv("x_dvn_app_vers", NULL);
 757                break;
 758        }
 759
 760        return MENU_MAIN;
 761}
 762
 763struct menu_display ait_load = {
 764        .title = "AIT load image",
 765        .timeout = 0,
 766        .id = MENU_LOAD,
 767        .menulist = menu_load,
 768        .menu_evaluate = ait_menu_evaluate_load,
 769};
 770
 771static void ait_menu_read_env(char *name)
 772{
 773        char output[CONFIG_SYS_CBSIZE];
 774        char cbuf[CONFIG_SYS_CBSIZE];
 775        int readret;
 776        int ret;
 777
 778        sprintf(output, "%s old: %s value: ", name, getenv(name));
 779        memset(cbuf, 0, CONFIG_SYS_CBSIZE);
 780        readret = readline_into_buffer(output, cbuf, 0);
 781
 782        if (readret >= 0) {
 783                ret = setenv(name, cbuf);
 784                if (ret) {
 785                        printf("Error setting %s\n", name);
 786                        return;
 787                }
 788        }
 789        return;
 790}
 791
 792static int ait_menu_evaluate_network(char *choice)
 793{
 794        if (!choice)
 795                return MENU_MAIN;
 796
 797        switch (choice[1]) {
 798        case '1':
 799                ait_menu_read_env("ipaddr");
 800                break;
 801        case '2':
 802                ait_menu_read_env("netmask");
 803                break;
 804        case '3':
 805                ait_menu_read_env("serverip");
 806                break;
 807        case '4':
 808                ait_menu_read_env("gatewayip");
 809                break;
 810        case '5':
 811                ait_menu_read_env("img_file");
 812                break;
 813        case '6':
 814                return MENU_UPDATE;
 815                break;
 816        }
 817
 818        return MENU_STAY;
 819}
 820
 821struct menu_display ait_network = {
 822        .title = "AIT network settings",
 823        .timeout = 0,
 824        .id = MENU_NETWORK,
 825        .menulist = menu_network,
 826        .menu_evaluate = ait_menu_evaluate_network,
 827};
 828
 829static int fit_get_subtype(const void *fit, int noffset, char **subtype)
 830{
 831        int len;
 832
 833        *subtype = (char *)fdt_getprop(fit, noffset, "subtype", &len);
 834        if (*subtype == NULL)
 835                return -1;
 836
 837        return 0;
 838}
 839
 840static int ait_subtype_nr(char *subtype)
 841{
 842        int ret = FIT_SUBTYPE_UNKNOWN;
 843
 844        if (!strncmp("ublheader", subtype, strlen("ublheader")))
 845                return FIT_SUBTYPE_UBL_HEADER;
 846        if (!strncmp("splimage", subtype, strlen("splimage")))
 847                return FIT_SUBTYPE_SPL_IMAGE;
 848        if (!strncmp("ubootimage", subtype, strlen("ubootimage")))
 849                return FIT_SUBTYPE_UBOOT_IMAGE;
 850        if (!strncmp("dfenvimage", subtype, strlen("dfenvimage")))
 851                return FIT_SUBTYPE_DF_ENV_IMAGE;
 852
 853        return ret;
 854}
 855
 856static int ait_menu_check_image(void)
 857{
 858        char *s;
 859        unsigned long fit_addr;
 860        void *addr;
 861        int format;
 862        char *desc;
 863        char *subtype;
 864        int images_noffset;
 865        int noffset;
 866        int ndepth;
 867        int count = 0;
 868        int ret;
 869        int i;
 870        int found_uboot = -1;
 871        int found_ramdisk = -1;
 872
 873        memset(imgs, 0, sizeof(imgs));
 874        s = getenv("fit_addr_r");
 875        fit_addr = s ? (unsigned long)simple_strtol(s, NULL, 16) : \
 876                        CONFIG_BOARD_IMG_ADDR_R;
 877
 878        addr = (void *)fit_addr;
 879        /* check if it is a FIT image */
 880        format = genimg_get_format(addr);
 881        if (format != IMAGE_FORMAT_FIT)
 882                return -EINVAL;
 883
 884        if (!fit_check_format(addr))
 885                return -EINVAL;
 886
 887        /* print the FIT description */
 888        ret = fit_get_desc(addr, 0, &desc);
 889        printf("FIT description: ");
 890        if (ret)
 891                printf("unavailable\n");
 892        else
 893                printf("%s\n", desc);
 894
 895        /* find images */
 896        images_noffset = fdt_path_offset(addr, FIT_IMAGES_PATH);
 897        if (images_noffset < 0) {
 898                printf("Can't find images parent node '%s' (%s)\n",
 899                        FIT_IMAGES_PATH, fdt_strerror(images_noffset));
 900                return -EINVAL;
 901        }
 902
 903        /* Process its subnodes, print out component images details */
 904        for (ndepth = 0, count = 0,
 905                noffset = fdt_next_node(addr, images_noffset, &ndepth);
 906                (noffset >= 0) && (ndepth > 0);
 907                noffset = fdt_next_node(addr, noffset, &ndepth)) {
 908                if (ndepth == 1) {
 909                        /*
 910                         * Direct child node of the images parent node,
 911                         * i.e. component image node.
 912                         */
 913                        printf("Image %u (%s)\n", count,
 914                                        fit_get_name(addr, noffset, NULL));
 915
 916                        fit_image_print(addr, noffset, "");
 917
 918                        fit_image_get_type(addr, noffset,
 919                                &imgs[count].type);
 920                        /* Mandatory properties */
 921                        ret = fit_get_desc(addr, noffset, &desc);
 922                        printf("Description:  ");
 923                        if (ret)
 924                                printf("unavailable\n");
 925                        else
 926                                printf("%s\n", desc);
 927
 928                        ret = fit_get_subtype(addr, noffset, &subtype);
 929                        printf("Subtype:  ");
 930                        if (ret) {
 931                                printf("unavailable\n");
 932                        } else {
 933                                imgs[count].subtype = ait_subtype_nr(subtype);
 934                                printf("%s %d\n", subtype,
 935                                        imgs[count].subtype);
 936                        }
 937
 938                        sprintf(imgs[count].desc, "%s", desc);
 939
 940                        ret = fit_image_get_data(addr, noffset,
 941                                &imgs[count].data,
 942                                &imgs[count].size);
 943
 944                        printf("Data Size:    ");
 945                        if (ret)
 946                                printf("unavailable\n");
 947                        else
 948                                genimg_print_size(imgs[count].size);
 949                        printf("Data @ %p\n", imgs[count].data);
 950                        count++;
 951                }
 952        }
 953
 954        for (i = 0; i < count; i++) {
 955                if (imgs[i].subtype == FIT_SUBTYPE_UBOOT_IMAGE)
 956                        found_uboot = i;
 957                if (imgs[i].type == IH_TYPE_RAMDISK) {
 958                        found_ramdisk = i;
 959                        imgs[i].subtype = FIT_SUBTYPE_RAMDISK_IMAGE;
 960                }
 961        }
 962
 963        /* dvn_* env var update, if the FIT descriptors are different */
 964        if (found_uboot >= 0) {
 965                s = getenv("dvn_boot_vers");
 966                if (s) {
 967                        ret = strcmp(s, imgs[found_uboot].desc);
 968                        if (ret != 0) {
 969                                setenv("x_dvn_boot_vers",
 970                                        imgs[found_uboot].desc);
 971                        } else {
 972                                found_uboot = -1;
 973                                printf("no new uboot version\n");
 974                        }
 975                } else {
 976                        setenv("dvn_boot_vers", imgs[found_uboot].desc);
 977                }
 978        }
 979        if (found_ramdisk >= 0) {
 980                s = getenv("dvn_app_vers");
 981                if (s) {
 982                        ret = strcmp(s, imgs[found_ramdisk].desc);
 983                        if (ret != 0) {
 984                                setenv("x_dvn_app_vers",
 985                                        imgs[found_ramdisk].desc);
 986                        } else {
 987                                found_ramdisk = -1;
 988                                printf("no new ramdisk version\n");
 989                        }
 990                } else {
 991                        setenv("dvn_app_vers", imgs[found_ramdisk].desc);
 992                }
 993        }
 994        if ((found_uboot == -1) && (found_ramdisk == -1))
 995                return -EINVAL;
 996
 997        return 0;
 998}
 999
1000static int ait_menu_evaluate_update(char *choice)
1001{
1002        int ret;
1003
1004        if (!choice)
1005                return MENU_MAIN;
1006
1007        switch (choice[1]) {
1008        case '1':
1009                return ait_menu_show(&ait_network, 0);
1010                break;
1011        case '2':
1012                /* load image */
1013                ret = run_command("run load_img", 0);
1014                printf("ret: %d\n", ret);
1015                if (ret)
1016                        return MENU_UPDATE;
1017
1018                ret = ait_menu_check_image();
1019                if (ret)
1020                        return MENU_UPDATE;
1021
1022                return ait_menu_show(&ait_load, 0);
1023                break;
1024        case '3':
1025                return MENU_MAIN;
1026                break;
1027
1028        }
1029
1030        return MENU_MAIN;
1031}
1032
1033struct menu_display ait_update = {
1034        .title = "AIT Update Software",
1035        .timeout = 0,
1036        .id = MENU_UPDATE,
1037        .menulist = menu_update,
1038        .menu_evaluate = ait_menu_evaluate_update,
1039};
1040
1041static int ait_menu_evaluate_main(char *choice)
1042{
1043        if (!choice)
1044                return MENU_STAY;
1045
1046        menu_start = 1;
1047        switch (choice[1]) {
1048        case '1':
1049                /* run bootcmd */
1050                return MENU_EXIT_BOOTCMD;
1051                break;
1052        case '2':
1053                return ait_menu_show(&ait_update, 0);
1054                break;
1055        case '3':
1056                /* reset to default settings */
1057                setenv("app_reset", "yes");
1058                return MENU_EXIT_BOOTCMD;
1059                break;
1060        case '4':
1061                /* u-boot shell */
1062                return MENU_EXIT;
1063                break;
1064        }
1065
1066        return MENU_EXIT;
1067}
1068
1069struct menu_display ait_main = {
1070        .title = "AIT Main",
1071        .timeout = CONFIG_BOOTDELAY,
1072        .id = MENU_MAIN,
1073        .menulist = menu_main,
1074        .menu_evaluate = ait_menu_evaluate_main,
1075};
1076
1077int menu_show(int bootdelay)
1078{
1079        int ret;
1080
1081        run_command("run saveparms", 0);
1082        ret = ait_menu_show(&ait_main, bootdelay);
1083        run_command("run restoreparms", 0);
1084
1085        if (ret == MENU_EXIT_BOOTCMD)
1086                return 0;
1087
1088        return MENU_EXIT;
1089}
1090
1091void menu_display_statusline(struct menu *m)
1092{
1093        char *s1, *s2;
1094
1095        s1 = getenv("x_dvn_boot_vers");
1096        if (!s1)
1097                s1 = getenv("dvn_boot_vers");
1098
1099        s2 = getenv("x_dvn_app_vers");
1100        if (!s2)
1101                s2 = getenv("dvn_app_vers");
1102
1103        printf("State: dvn_boot_vers: %s dvn_app_vers: %s\n", s1, s2);
1104        return;
1105}
1106#endif
1107