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 <common.h>
8 #include <dm.h>
9 #include <env.h>
10 #include <init.h>
11 #include <asm/global_data.h>
12 #include <asm/io.h>
13 
14 DECLARE_GLOBAL_DATA_PTR;
15 
16 #define MPFS_SYSREG_SOFT_RESET		((unsigned int *)0x20002088)
17 #define MPFS_SYS_SERVICE_CR		((unsigned int *)0x37020050)
18 #define MPFS_SYS_SERVICE_SR		((unsigned int *)0x37020054)
19 #define MPFS_SYS_SERVICE_MAILBOX	((unsigned char *)0x37020800)
20 
21 #define PERIPH_RESET_VALUE		0x1e8u
22 #define SERVICE_CR_REQ			0x1u
23 #define SERVICE_SR_BUSY			0x2u
24 
read_device_serial_number(u8 * response,u8 response_size)25 static void read_device_serial_number(u8 *response, u8 response_size)
26 {
27 	u8 idx;
28 	u8 *response_buf;
29 	unsigned int val;
30 
31 	response_buf = (u8 *)response;
32 
33 	writel(SERVICE_CR_REQ, MPFS_SYS_SERVICE_CR);
34 	/*
35 	 * REQ bit will remain set till the system controller starts
36 	 * processing.
37 	 */
38 	do {
39 		val = readl(MPFS_SYS_SERVICE_CR);
40 	} while (SERVICE_CR_REQ == (val & SERVICE_CR_REQ));
41 
42 	/*
43 	 * Once system controller starts processing the busy bit will
44 	 * go high and service is completed when busy bit is gone low
45 	 */
46 	do {
47 		val = readl(MPFS_SYS_SERVICE_SR);
48 	} while (SERVICE_SR_BUSY == (val & SERVICE_SR_BUSY));
49 
50 	for (idx = 0; idx < response_size; idx++)
51 		response_buf[idx] = readb(MPFS_SYS_SERVICE_MAILBOX + idx);
52 }
53 
board_init(void)54 int board_init(void)
55 {
56 	/* For now nothing to do here. */
57 
58 	return 0;
59 }
60 
board_early_init_f(void)61 int board_early_init_f(void)
62 {
63 	unsigned int val;
64 
65 	/* Reset uart, mmc peripheral */
66 	val = readl(MPFS_SYSREG_SOFT_RESET);
67 	val = (val & ~(PERIPH_RESET_VALUE));
68 	writel(val, MPFS_SYSREG_SOFT_RESET);
69 
70 	return 0;
71 }
72 
board_late_init(void)73 int board_late_init(void)
74 {
75 	u32 ret;
76 	u32 node;
77 	u8 idx;
78 	u8 device_serial_number[16] = { 0 };
79 	unsigned char mac_addr[6];
80 	char icicle_mac_addr[20];
81 	void *blob = (void *)gd->fdt_blob;
82 
83 	node = fdt_path_offset(blob, "ethernet0");
84 	if (node < 0) {
85 		printf("No ethernet0 path offset\n");
86 		return -ENODEV;
87 	}
88 
89 	ret = fdtdec_get_byte_array(blob, node, "local-mac-address", mac_addr, 6);
90 	if (ret) {
91 		printf("No local-mac-address property\n");
92 		return -EINVAL;
93 	}
94 
95 	read_device_serial_number(device_serial_number, 16);
96 
97 	/* Update MAC address with device serial number */
98 	mac_addr[0] = 0x00;
99 	mac_addr[1] = 0x04;
100 	mac_addr[2] = 0xA3;
101 	mac_addr[3] = device_serial_number[2];
102 	mac_addr[4] = device_serial_number[1];
103 	mac_addr[5] = device_serial_number[0];
104 
105 	ret = fdt_setprop(blob, node, "local-mac-address", mac_addr, 6);
106 	if (ret) {
107 		printf("Error setting local-mac-address property\n");
108 		return -ENODEV;
109 	}
110 
111 	icicle_mac_addr[0] = '[';
112 
113 	sprintf(&icicle_mac_addr[1], "%pM", mac_addr);
114 
115 	icicle_mac_addr[18] = ']';
116 	icicle_mac_addr[19] = '\0';
117 
118 	for (idx = 0; idx < 20; idx++) {
119 		if (icicle_mac_addr[idx] == ':')
120 			icicle_mac_addr[idx] = ' ';
121 	}
122 	env_set("icicle_mac_addr", icicle_mac_addr);
123 
124 	return 0;
125 }
126