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