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