db410c: update wlan and bt mac addresses from firmware
[oweals/u-boot.git] / board / qualcomm / dragonboard410c / dragonboard410c.c
1 /*
2  * Board init file for Dragonboard 410C
3  *
4  * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <usb.h>
12 #include <asm/gpio.h>
13 #include <fdt_support.h>
14
15 DECLARE_GLOBAL_DATA_PTR;
16
17 /* pointer to the device tree ammended by the firmware */
18 extern const void *fw_dtb;
19
20 static char wlan_mac[ARP_HLEN];
21 static char bt_mac[ARP_HLEN];
22
23 int dram_init(void)
24 {
25         gd->ram_size = PHYS_SDRAM_1_SIZE;
26         return 0;
27 }
28
29 int dram_init_banksize(void)
30 {
31         gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
32         gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
33
34         return 0;
35 }
36
37 int board_prepare_usb(enum usb_init_type type)
38 {
39         static struct udevice *pmic_gpio;
40         static struct gpio_desc hub_reset, usb_sel;
41         int ret = 0, node;
42
43         if (!pmic_gpio) {
44                 ret = uclass_get_device_by_name(UCLASS_GPIO,
45                                                 "pm8916_gpios@c000",
46                                                 &pmic_gpio);
47                 if (ret < 0) {
48                         printf("Failed to find pm8916_gpios@c000 node.\n");
49                         return ret;
50                 }
51         }
52
53         /* Try to request gpios needed to start usb host on dragonboard */
54         if (!dm_gpio_is_valid(&hub_reset)) {
55                 node = fdt_subnode_offset(gd->fdt_blob,
56                                           dev_of_offset(pmic_gpio),
57                                           "usb_hub_reset_pm");
58                 if (node < 0) {
59                         printf("Failed to find usb_hub_reset_pm dt node.\n");
60                         return node;
61                 }
62                 ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
63                                                  "gpios", 0, &hub_reset, 0);
64                 if (ret < 0) {
65                         printf("Failed to request usb_hub_reset_pm gpio.\n");
66                         return ret;
67                 }
68         }
69
70         if (!dm_gpio_is_valid(&usb_sel)) {
71                 node = fdt_subnode_offset(gd->fdt_blob,
72                                           dev_of_offset(pmic_gpio),
73                                           "usb_sw_sel_pm");
74                 if (node < 0) {
75                         printf("Failed to find usb_sw_sel_pm dt node.\n");
76                         return 0;
77                 }
78                 ret = gpio_request_by_name_nodev(offset_to_ofnode(node),
79                                                  "gpios", 0, &usb_sel, 0);
80                 if (ret < 0) {
81                         printf("Failed to request usb_sw_sel_pm gpio.\n");
82                         return ret;
83                 }
84         }
85
86         if (type == USB_INIT_HOST) {
87                 /* Start USB Hub */
88                 dm_gpio_set_dir_flags(&hub_reset,
89                                       GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
90                 mdelay(100);
91                 /* Switch usb to host connectors */
92                 dm_gpio_set_dir_flags(&usb_sel,
93                                       GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE);
94                 mdelay(100);
95         } else { /* Device */
96                 /* Disable hub */
97                 dm_gpio_set_dir_flags(&hub_reset, GPIOD_IS_OUT);
98                 /* Switch back to device connector */
99                 dm_gpio_set_dir_flags(&usb_sel, GPIOD_IS_OUT);
100         }
101
102         return 0;
103 }
104
105 /* Check for vol- button - if pressed - stop autoboot */
106 int misc_init_r(void)
107 {
108         struct udevice *pon;
109         struct gpio_desc resin;
110         int node, ret;
111
112         ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8916_pon@800", &pon);
113         if (ret < 0) {
114                 printf("Failed to find PMIC pon node. Check device tree\n");
115                 return 0;
116         }
117
118         node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon),
119                                   "key_vol_down");
120         if (node < 0) {
121                 printf("Failed to find key_vol_down node. Check device tree\n");
122                 return 0;
123         }
124
125         if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0,
126                                        &resin, 0)) {
127                 printf("Failed to request key_vol_down button.\n");
128                 return 0;
129         }
130
131         if (dm_gpio_get_value(&resin)) {
132                 env_set("bootdelay", "-1");
133                 printf("Power button pressed - dropping to console.\n");
134         }
135
136         return 0;
137 }
138
139 int board_init(void)
140 {
141         int offset, len;
142         const char *mac;
143
144         /* take a copy of the firmware information (the user could unknownly
145            overwrite that DDR via tftp or other means)  */
146
147         offset = fdt_node_offset_by_compatible(fw_dtb, -1, "qcom,wcnss-wlan");
148         if (offset >= 0) {
149                 mac = fdt_getprop(fw_dtb, offset, "local-mac-address", &len);
150                 if (mac)
151                         memcpy(wlan_mac, mac, ARP_HLEN);
152         }
153
154         offset = fdt_node_offset_by_compatible(fw_dtb, -1, "qcom,wcnss-bt");
155         if (offset >= 0) {
156                 mac = fdt_getprop(fw_dtb, offset, "local-bd-address", &len);
157                 if (mac)
158                         memcpy(bt_mac, mac, ARP_HLEN);
159         }
160
161         return 0;
162 }
163
164 int ft_board_setup(void *blob, bd_t *bd)
165 {
166         do_fixup_by_compat(blob, "qcom,wcnss-wlan", "local-mac-address",
167                            wlan_mac, ARP_HLEN, 1);
168
169         do_fixup_by_compat(blob, "qcom,wcnss-bt", "local-bd-address",
170                            bt_mac, ARP_HLEN, 1);
171
172         return 0;
173 }