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 <common.h> 9 #include <dm.h> 10 #include <usb.h> 11 #include <asm/gpio.h> 12 #include <fdt_support.h> 13 #include <asm/arch/dram.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 /* pointer to the device tree ammended by the firmware */ 18 extern void *fw_dtb; 19 20 void *board_fdt_blob_setup(void) 21 { 22 if (fdt_magic(fw_dtb) != FDT_MAGIC) { 23 printf("Firmware provided invalid dtb!\n"); 24 return NULL; 25 } 26 27 return fw_dtb; 28 } 29 30 int dram_init(void) 31 { 32 gd->ram_size = PHYS_SDRAM_1_SIZE; 33 34 return 0; 35 } 36 37 int dram_init_banksize(void) 38 { 39 gd->bd->bi_dram[0].start = PHYS_SDRAM_1; 40 gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE; 41 42 return 0; 43 } 44 45 int board_prepare_usb(enum usb_init_type type) 46 { 47 static struct udevice *pmic_gpio; 48 static struct gpio_desc hub_reset, usb_sel; 49 int ret = 0, node; 50 51 if (!pmic_gpio) { 52 ret = uclass_get_device_by_name(UCLASS_GPIO, 53 "pm8916_gpios@c000", 54 &pmic_gpio); 55 if (ret < 0) { 56 printf("Failed to find pm8916_gpios@c000 node.\n"); 57 return ret; 58 } 59 } 60 61 /* Try to request gpios needed to start usb host on dragonboard */ 62 if (!dm_gpio_is_valid(&hub_reset)) { 63 node = fdt_subnode_offset(gd->fdt_blob, 64 dev_of_offset(pmic_gpio), 65 "usb_hub_reset_pm"); 66 if (node < 0) { 67 printf("Failed to find usb_hub_reset_pm dt node.\n"); 68 return node; 69 } 70 ret = gpio_request_by_name_nodev(offset_to_ofnode(node), 71 "gpios", 0, &hub_reset, 0); 72 if (ret < 0) { 73 printf("Failed to request usb_hub_reset_pm gpio.\n"); 74 return ret; 75 } 76 } 77 78 if (!dm_gpio_is_valid(&usb_sel)) { 79 node = fdt_subnode_offset(gd->fdt_blob, 80 dev_of_offset(pmic_gpio), 81 "usb_sw_sel_pm"); 82 if (node < 0) { 83 printf("Failed to find usb_sw_sel_pm dt node.\n"); 84 return 0; 85 } 86 ret = gpio_request_by_name_nodev(offset_to_ofnode(node), 87 "gpios", 0, &usb_sel, 0); 88 if (ret < 0) { 89 printf("Failed to request usb_sw_sel_pm gpio.\n"); 90 return ret; 91 } 92 } 93 94 if (type == USB_INIT_HOST) { 95 /* Start USB Hub */ 96 dm_gpio_set_dir_flags(&hub_reset, 97 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 98 mdelay(100); 99 /* Switch usb to host connectors */ 100 dm_gpio_set_dir_flags(&usb_sel, 101 GPIOD_IS_OUT | GPIOD_IS_OUT_ACTIVE); 102 mdelay(100); 103 } else { /* Device */ 104 /* Disable hub */ 105 dm_gpio_set_dir_flags(&hub_reset, GPIOD_IS_OUT); 106 /* Switch back to device connector */ 107 dm_gpio_set_dir_flags(&usb_sel, GPIOD_IS_OUT); 108 } 109 110 return 0; 111 } 112 113 /* Check for vol- button - if pressed - stop autoboot */ 114 int misc_init_r(void) 115 { 116 struct udevice *pon; 117 struct gpio_desc resin; 118 int node, ret; 119 120 ret = uclass_get_device_by_name(UCLASS_GPIO, "pm8916_pon@800", &pon); 121 if (ret < 0) { 122 printf("Failed to find PMIC pon node. Check device tree\n"); 123 return 0; 124 } 125 126 node = fdt_subnode_offset(gd->fdt_blob, dev_of_offset(pon), 127 "key_vol_down"); 128 if (node < 0) { 129 printf("Failed to find key_vol_down node. Check device tree\n"); 130 return 0; 131 } 132 133 if (gpio_request_by_name_nodev(offset_to_ofnode(node), "gpios", 0, 134 &resin, 0)) { 135 printf("Failed to request key_vol_down button.\n"); 136 return 0; 137 } 138 139 if (dm_gpio_get_value(&resin)) { 140 env_set("bootdelay", "-1"); 141 printf("Power button pressed - dropping to console.\n"); 142 } 143 144 return 0; 145 } 146 147 int board_init(void) 148 { 149 return 0; 150 } 151 152 int ft_board_setup(void *blob, bd_t *bd) 153 { 154 int offset, len, i; 155 const char *mac; 156 struct { 157 const char *compatible; 158 const char *property; 159 } fix[] = { 160 [0] = { 161 /* update the kernel's dtb with wlan mac */ 162 .compatible = "qcom,wcnss-wlan", 163 .property = "local-mac-address", 164 }, 165 [1] = { 166 /* update the kernel's dtb with bt mac */ 167 .compatible = "qcom,wcnss-bt", 168 .property = "local-bd-address", 169 }, 170 }; 171 172 for (i = 0; i < sizeof(fix) / sizeof(fix[0]); i++) { 173 offset = fdt_node_offset_by_compatible(gd->fdt_blob, -1, 174 fix[i].compatible); 175 if (offset < 0) 176 continue; 177 178 mac = fdt_getprop(gd->fdt_blob, offset, fix[i].property, &len); 179 if (mac) 180 do_fixup_by_compat(blob, fix[i].compatible, 181 fix[i].property, mac, ARP_HLEN, 1); 182 } 183 184 msm_fixup_memory(blob); 185 186 return 0; 187 } 188 189 void reset_cpu(ulong addr) 190 { 191 psci_system_reset(); 192 } 193