1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Board init file for Dragonboard 410C
4  *
5  * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
6  */
7 
8 #include <button.h>
9 #include <cpu_func.h>
10 #include <dm.h>
11 #include <dm/pinctrl.h>
12 #include <env.h>
13 #include <init.h>
14 #include <mmc.h>
15 #include <net.h>
16 #include <usb.h>
17 #include <asm/cache.h>
18 #include <asm/global_data.h>
19 #include <asm/gpio.h>
20 #include <fdt_support.h>
21 #include <linux/delay.h>
22 
23 DECLARE_GLOBAL_DATA_PTR;
24 
msm_board_serial(void)25 static u32 msm_board_serial(void)
26 {
27 	struct mmc *mmc_dev;
28 
29 	mmc_dev = find_mmc_device(0);
30 	if (!mmc_dev)
31 		return 0;
32 
33 	if (mmc_init(mmc_dev))
34 		return 0;
35 
36 	/* MMC serial number */
37 	return mmc_dev->cid[2] << 16 | mmc_dev->cid[3] >> 16;
38 }
39 
msm_generate_mac_addr(u8 * mac)40 static void msm_generate_mac_addr(u8 *mac)
41 {
42 	/* use locally adminstrated pool */
43 	mac[0] = 0x02;
44 	mac[1] = 0x00;
45 
46 	/*
47 	 * Put the 32-bit serial number in the last 32-bit of the MAC address.
48 	 * Use big endian order so it is consistent with the serial number
49 	 * written as a hexadecimal string, e.g. 0x1234abcd -> 02:00:12:34:ab:cd
50 	 */
51 	put_unaligned_be32(msm_board_serial(), &mac[2]);
52 }
53 
qcom_late_init(void)54 int qcom_late_init(void)
55 {
56 	char serial[16];
57 
58 	memset(serial, 0, 16);
59 	snprintf(serial, 13, "%x", msm_board_serial());
60 	env_set("serial#", serial);
61 	return 0;
62 }
63 
64 /*
65  * Fixup of DTB for Linux Kernel
66  * 1. Fixup WLAN/BT Mac address:
67  *	First, check if MAC addresses for WLAN/BT exists as environemnt
68  *	variables wlanaddr,btaddr. if not, generate a unique address.
69  */
70 
ft_board_setup(void * blob,struct bd_info * bd)71 int ft_board_setup(void *blob, struct bd_info *bd)
72 {
73 	u8 mac[ARP_HLEN];
74 	int i;
75 
76 	if (!eth_env_get_enetaddr("wlanaddr", mac)) {
77 		msm_generate_mac_addr(mac);
78 	};
79 
80 	do_fixup_by_compat(blob, "qcom,wcnss-wlan",
81 			   "local-mac-address", mac, ARP_HLEN, 1);
82 
83 	if (!eth_env_get_enetaddr("btaddr", mac)) {
84 		msm_generate_mac_addr(mac);
85 
86 		/*
87 		 * The BD address is same as WLAN MAC address but with
88 		 * least significant bit flipped.
89 		 */
90 		mac[ARP_HLEN - 1] ^= 0x01;
91 	};
92 
93 	/*
94 	 * Reverse array since local-bd-address is formatted with least
95 	 * significant byte first (little endian).
96 	 */
97 	for (i = 0; i < ARP_HLEN / 2; ++i) {
98 		u8 tmp = mac[i];
99 
100 		mac[i] = mac[ARP_HLEN - 1 - i];
101 		mac[ARP_HLEN - 1 - i] = tmp;
102 	}
103 
104 	do_fixup_by_compat(blob, "qcom,wcnss-bt",
105 			   "local-bd-address", mac, ARP_HLEN, 1);
106 	return 0;
107 }
108