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