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