1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * Copyright (C) 2019 Microchip Technology Inc.
4 * Padmarao Begari <padmarao.begari@microchip.com>
5 */
6
7 #include <asm/global_data.h>
8 #include <asm/io.h>
9 #include <asm/sections.h>
10 #include <dm.h>
11 #include <dm/devres.h>
12 #include <env.h>
13 #include <linux/compat.h>
14 #include <mpfs-mailbox.h>
15
16 DECLARE_GLOBAL_DATA_PTR;
17
18 #define MPFS_SYSREG_SOFT_RESET ((unsigned int *)0x20002088)
19 #define PERIPH_RESET_VALUE 0x1e8u
20
21 static unsigned char mac_addr[6];
22
23 #if defined(CONFIG_MULTI_DTB_FIT)
board_fit_config_name_match(const char * name)24 int board_fit_config_name_match(const char *name)
25 {
26 const void *fdt;
27 int list_len;
28
29 /*
30 * If there's not a HSS provided dtb, there's no point re-selecting
31 * since we'd just end up re-selecting the same dtb again.
32 */
33 if (!gd->arch.firmware_fdt_addr)
34 return -EINVAL;
35
36 fdt = (void *)gd->arch.firmware_fdt_addr;
37
38 list_len = fdt_stringlist_count(fdt, 0, "compatible");
39 if (list_len < 1)
40 return -EINVAL;
41
42 for (int i = 0; i < list_len; i++) {
43 int len, match;
44 const char *compat;
45 char copy[64];
46 char *devendored;
47
48 compat = fdt_stringlist_get(fdt, 0, "compatible", i, &len);
49 if (!compat)
50 return -EINVAL;
51
52 /*
53 * The naming scheme for compatibles doesn't produce anything
54 * close to this long.
55 */
56 if (len >= 64)
57 return -EINVAL;
58
59 strncpy(copy, compat, 64);
60 strtok(copy, ",");
61
62 devendored = strtok(NULL, ",");
63 if (!devendored)
64 return -EINVAL;
65
66 match = strcmp(devendored, name);
67 if (!match)
68 return 0;
69 }
70
71 return -EINVAL;
72 }
73 #endif
74
board_fdt_blob_setup(void ** fdtp)75 int board_fdt_blob_setup(void **fdtp)
76 {
77 fdtp = (void *)_end;
78
79 /*
80 * The devicetree provided by the previous stage is very minimal due to
81 * severe space constraints. The firmware performs no fixups etc.
82 * U-Boot, if providing a devicetree, almost certainly has a better
83 * more complete one than the firmware so that provided by the firmware
84 * is ignored for OF_SEPARATE.
85 */
86 if (IS_ENABLED(CONFIG_OF_BOARD) && !IS_ENABLED(CONFIG_MULTI_DTB_FIT)) {
87 if (gd->arch.firmware_fdt_addr)
88 fdtp = (void *)(uintptr_t)gd->arch.firmware_fdt_addr;
89 }
90
91 return 0;
92 }
93
board_init(void)94 int board_init(void)
95 {
96 /* For now nothing to do here. */
97
98 return 0;
99 }
100
board_early_init_f(void)101 int board_early_init_f(void)
102 {
103 unsigned int val;
104
105 /* Reset uart, mmc peripheral */
106 val = readl(MPFS_SYSREG_SOFT_RESET);
107 val = (val & ~(PERIPH_RESET_VALUE));
108 writel(val, MPFS_SYSREG_SOFT_RESET);
109
110 return 0;
111 }
112
board_late_init(void)113 int board_late_init(void)
114 {
115 u32 ret;
116 int node;
117 u8 device_serial_number[16] = {0};
118 void *blob = (void *)gd->fdt_blob;
119 struct udevice *dev;
120 struct mpfs_sys_serv *sys_serv_priv;
121
122 ret = uclass_get_device_by_name(UCLASS_MISC, "syscontroller", &dev);
123 if (ret) {
124 debug("%s: system controller setup failed\n", __func__);
125 return ret;
126 }
127
128 sys_serv_priv = kzalloc(sizeof(*sys_serv_priv), GFP_KERNEL);
129 if (!sys_serv_priv)
130 return -ENOMEM;
131
132 sys_serv_priv->dev = dev;
133
134 sys_serv_priv->sys_controller = mpfs_syscontroller_get(dev);
135 ret = IS_ERR(sys_serv_priv->sys_controller);
136 if (ret) {
137 debug("%s: Failed to register system controller sub device ret=%d\n", __func__, ret);
138 return -ENODEV;
139 }
140
141 ret = mpfs_syscontroller_read_sernum(sys_serv_priv, device_serial_number);
142 if (ret) {
143 printf("Cannot read device serial number\n");
144 return -EINVAL;
145 }
146
147 /* Update MAC address with device serial number */
148 mac_addr[0] = 0x00;
149 mac_addr[1] = 0x04;
150 mac_addr[2] = 0xA3;
151 mac_addr[3] = device_serial_number[2];
152 mac_addr[4] = device_serial_number[1];
153 mac_addr[5] = device_serial_number[0];
154
155 node = fdt_path_offset(blob, "/soc/ethernet@20112000");
156 if (node >= 0) {
157 ret = fdt_setprop(blob, node, "local-mac-address", mac_addr, 6);
158 if (ret) {
159 printf("Error setting local-mac-address property for ethernet@20112000\n");
160 return -ENODEV;
161 }
162 }
163
164 mac_addr[5] = device_serial_number[0] + 1;
165
166 node = fdt_path_offset(blob, "/soc/ethernet@20110000");
167 if (node >= 0) {
168 ret = fdt_setprop(blob, node, "local-mac-address", mac_addr, 6);
169 if (ret) {
170 printf("Error setting local-mac-address property for ethernet@20110000\n");
171 return -ENODEV;
172 }
173 }
174
175 return 0;
176 }
177
ft_board_setup(void * blob,struct bd_info * bd)178 int ft_board_setup(void *blob, struct bd_info *bd)
179 {
180 u32 ret;
181 int node;
182
183 node = fdt_path_offset(blob, "/soc/ethernet@20110000");
184 if (node >= 0) {
185 ret = fdt_setprop(blob, node, "local-mac-address", mac_addr, 6);
186 if (ret) {
187 printf("Error setting local-mac-address property for ethernet@20110000\n");
188 return -ENODEV;
189 }
190 }
191
192 mac_addr[5] -= 1;
193
194 node = fdt_path_offset(blob, "/soc/ethernet@20112000");
195 if (node >= 0) {
196 ret = fdt_setprop(blob, node, "local-mac-address", mac_addr, 6);
197 if (ret) {
198 printf("Error setting local-mac-address property for ethernet@20112000\n");
199 return -ENODEV;
200 }
201 }
202
203 return 0;
204 }
205