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