14b61fc7dfda80c3e2502258ba07fda04eac8aaa
[platform/kernel/u-boot.git] / arch / arm / mach-uniphier / board_late_init.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2014      Panasonic Corporation
4  * Copyright (C) 2015-2016 Socionext Inc.
5  *   Author: Masahiro Yamada <yamada.masahiro@socionext.com>
6  */
7
8 #include <common.h>
9 #include <env.h>
10 #include <spl.h>
11 #include <linux/libfdt.h>
12 #include <nand.h>
13 #include <stdio.h>
14 #include <linux/io.h>
15 #include <linux/printk.h>
16 #include <../drivers/mtd/nand/raw/denali.h>
17
18 #include "init.h"
19
20 static void nand_denali_wp_disable(void)
21 {
22 #ifdef CONFIG_NAND_DENALI
23         /*
24          * Since the boot rom enables the write protection for NAND boot mode,
25          * it must be disabled somewhere for "nand write", "nand erase", etc.
26          * The workaround is here to not disturb the Denali NAND controller
27          * driver just for a really SoC-specific thing.
28          */
29         void __iomem *denali_reg = (void __iomem *)CONFIG_SYS_NAND_REGS_BASE;
30
31         writel(WRITE_PROTECT__FLAG, denali_reg + WRITE_PROTECT);
32 #endif
33 }
34
35 static void uniphier_set_env_fdt_file(void)
36 {
37         DECLARE_GLOBAL_DATA_PTR;
38         const char *compat;
39         char dtb_name[256];
40         int buf_len = sizeof(dtb_name);
41         int ret;
42
43         if (env_get("fdtfile"))
44                 return;         /* do nothing if it is already set */
45
46         compat = fdt_stringlist_get(gd->fdt_blob, 0, "compatible", 0, NULL);
47         if (!compat)
48                 goto fail;
49
50         /* rip off the vendor prefix "socionext,"  */
51         compat = strchr(compat, ',');
52         if (!compat)
53                 goto fail;
54         compat++;
55
56         strncpy(dtb_name, compat, buf_len);
57         buf_len -= strlen(compat);
58
59         strncat(dtb_name, ".dtb", buf_len);
60
61         ret = env_set("fdtfile", dtb_name);
62         if (ret)
63                 goto fail;
64
65         return;
66 fail:
67         pr_warn("\"fdt_file\" environment variable was not set correctly\n");
68 }
69
70 static void uniphier_set_env_addr(const char *env, const char *offset_env)
71 {
72         unsigned long offset = 0;
73         const char *str;
74         char *end;
75         int ret;
76
77         if (env_get(env))
78                 return;         /* do nothing if it is already set */
79
80         if (offset_env) {
81                 str = env_get(offset_env);
82                 if (!str)
83                         goto fail;
84
85                 offset = simple_strtoul(str, &end, 16);
86                 if (*end)
87                         goto fail;
88         }
89
90         ret = env_set_hex(env, gd->ram_base + offset);
91         if (ret)
92                 goto fail;
93
94         return;
95
96 fail:
97         pr_warn("\"%s\" environment variable was not set correctly\n", env);
98 }
99
100 int board_late_init(void)
101 {
102         puts("MODE:  ");
103
104         switch (uniphier_boot_device_raw()) {
105         case BOOT_DEVICE_MMC1:
106                 printf("eMMC Boot");
107                 env_set("bootdev", "emmc");
108                 break;
109         case BOOT_DEVICE_MMC2:
110                 printf("SD Boot");
111                 env_set("bootdev", "sd");
112                 break;
113         case BOOT_DEVICE_NAND:
114                 printf("NAND Boot");
115                 env_set("bootdev", "nand");
116                 nand_denali_wp_disable();
117                 break;
118         case BOOT_DEVICE_NOR:
119                 printf("NOR Boot");
120                 env_set("bootdev", "nor");
121                 break;
122         case BOOT_DEVICE_USB:
123                 printf("USB Boot");
124                 env_set("bootdev", "usb");
125                 break;
126         default:
127                 printf("Unknown");
128                 break;
129         }
130
131         if (uniphier_have_internal_stm())
132                 printf(" (STM: %s)",
133                        uniphier_boot_from_backend() ? "OFF" : "ON");
134
135         printf("\n");
136
137         uniphier_set_env_fdt_file();
138
139         uniphier_set_env_addr("dram_base", NULL);
140
141         uniphier_set_env_addr("loadaddr", "loadaddr_offset");
142
143         uniphier_set_env_addr("kernel_addr_r", "kernel_addr_r_offset");
144         uniphier_set_env_addr("ramdisk_addr_r", "ramdisk_addr_r_offset");
145         uniphier_set_env_addr("fdt_addr_r", "fdt_addr_r_offset");
146
147         return 0;
148 }