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