1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2013 SAMSUNG Electronics 4 * Rajeshwari Shinde <rajeshwari.s@samsung.com> 5 */ 6 7 #include <common.h> 8 #include <cros_ec.h> 9 #include <errno.h> 10 #include <fdtdec.h> 11 #include <spi.h> 12 #include <tmu.h> 13 #include <netdev.h> 14 #include <asm/io.h> 15 #include <asm/gpio.h> 16 #include <asm/arch/board.h> 17 #include <asm/arch/cpu.h> 18 #include <asm/arch/dwmmc.h> 19 #include <asm/arch/mmc.h> 20 #include <asm/arch/pinmux.h> 21 #include <asm/arch/power.h> 22 #include <asm/arch/system.h> 23 #include <asm/arch/sromc.h> 24 #include <lcd.h> 25 #include <i2c.h> 26 #include <usb.h> 27 #include <dwc3-uboot.h> 28 #include <samsung/misc.h> 29 #include <dm/pinctrl.h> 30 #include <dm.h> 31 32 DECLARE_GLOBAL_DATA_PTR; 33 34 __weak int exynos_early_init_f(void) 35 { 36 return 0; 37 } 38 39 __weak int exynos_power_init(void) 40 { 41 return 0; 42 } 43 44 #if defined CONFIG_EXYNOS_TMU 45 /* Boot Time Thermal Analysis for SoC temperature threshold breach */ 46 static void boot_temp_check(void) 47 { 48 int temp; 49 50 switch (tmu_monitor(&temp)) { 51 case TMU_STATUS_NORMAL: 52 break; 53 case TMU_STATUS_TRIPPED: 54 /* 55 * Status TRIPPED ans WARNING means corresponding threshold 56 * breach 57 */ 58 puts("EXYNOS_TMU: TRIPPING! Device power going down ...\n"); 59 set_ps_hold_ctrl(); 60 hang(); 61 break; 62 case TMU_STATUS_WARNING: 63 puts("EXYNOS_TMU: WARNING! Temperature very high\n"); 64 break; 65 case TMU_STATUS_INIT: 66 /* 67 * TMU_STATUS_INIT means something is wrong with temperature 68 * sensing and TMU status was changed back from NORMAL to INIT. 69 */ 70 puts("EXYNOS_TMU: WARNING! Temperature sensing not done\n"); 71 break; 72 default: 73 debug("EXYNOS_TMU: Unknown TMU state\n"); 74 } 75 } 76 #endif 77 78 int board_init(void) 79 { 80 gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL); 81 #if defined CONFIG_EXYNOS_TMU 82 if (tmu_init(gd->fdt_blob) != TMU_STATUS_NORMAL) { 83 debug("%s: Failed to init TMU\n", __func__); 84 return -1; 85 } 86 boot_temp_check(); 87 #endif 88 #ifdef CONFIG_TZSW_RESERVED_DRAM_SIZE 89 /* The last few MB of memory can be reserved for secure firmware */ 90 ulong size = CONFIG_TZSW_RESERVED_DRAM_SIZE; 91 92 gd->ram_size -= size; 93 gd->bd->bi_dram[CONFIG_NR_DRAM_BANKS - 1].size -= size; 94 #endif 95 return exynos_init(); 96 } 97 98 int dram_init(void) 99 { 100 unsigned int i; 101 unsigned long addr; 102 103 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 104 addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); 105 gd->ram_size += get_ram_size((long *)addr, SDRAM_BANK_SIZE); 106 } 107 return 0; 108 } 109 110 int dram_init_banksize(void) 111 { 112 unsigned int i; 113 unsigned long addr, size; 114 115 for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { 116 addr = CONFIG_SYS_SDRAM_BASE + (i * SDRAM_BANK_SIZE); 117 size = get_ram_size((long *)addr, SDRAM_BANK_SIZE); 118 119 gd->bd->bi_dram[i].start = addr; 120 gd->bd->bi_dram[i].size = size; 121 } 122 123 return 0; 124 } 125 126 static int board_uart_init(void) 127 { 128 #ifndef CONFIG_PINCTRL_EXYNOS 129 int err, uart_id, ret = 0; 130 131 for (uart_id = PERIPH_ID_UART0; uart_id <= PERIPH_ID_UART3; uart_id++) { 132 err = exynos_pinmux_config(uart_id, PINMUX_FLAG_NONE); 133 if (err) { 134 debug("UART%d not configured\n", 135 (uart_id - PERIPH_ID_UART0)); 136 ret |= err; 137 } 138 } 139 return ret; 140 #else 141 return 0; 142 #endif 143 } 144 145 #ifdef CONFIG_BOARD_EARLY_INIT_F 146 int board_early_init_f(void) 147 { 148 int err; 149 #ifdef CONFIG_BOARD_TYPES 150 set_board_type(); 151 #endif 152 err = board_uart_init(); 153 if (err) { 154 debug("UART init failed\n"); 155 return err; 156 } 157 158 #ifdef CONFIG_SYS_I2C_INIT_BOARD 159 board_i2c_init(gd->fdt_blob); 160 #endif 161 162 return exynos_early_init_f(); 163 } 164 #endif 165 166 #if defined(CONFIG_POWER) || defined(CONFIG_DM_PMIC) 167 int power_init_board(void) 168 { 169 set_ps_hold_ctrl(); 170 171 return exynos_power_init(); 172 } 173 #endif 174 175 #ifdef CONFIG_SMC911X 176 static int decode_sromc(const void *blob, struct fdt_sromc *config) 177 { 178 int err; 179 int node; 180 181 node = fdtdec_next_compatible(blob, 0, COMPAT_SAMSUNG_EXYNOS5_SROMC); 182 if (node < 0) { 183 debug("Could not find SROMC node\n"); 184 return node; 185 } 186 187 config->bank = fdtdec_get_int(blob, node, "bank", 0); 188 config->width = fdtdec_get_int(blob, node, "width", 2); 189 190 err = fdtdec_get_int_array(blob, node, "srom-timing", config->timing, 191 FDT_SROM_TIMING_COUNT); 192 if (err < 0) { 193 debug("Could not decode SROMC configuration Error: %s\n", 194 fdt_strerror(err)); 195 return -FDT_ERR_NOTFOUND; 196 } 197 return 0; 198 } 199 #endif 200 201 int board_eth_init(bd_t *bis) 202 { 203 #ifdef CONFIG_SMC911X 204 u32 smc_bw_conf, smc_bc_conf; 205 struct fdt_sromc config; 206 fdt_addr_t base_addr; 207 int node; 208 209 node = decode_sromc(gd->fdt_blob, &config); 210 if (node < 0) { 211 debug("%s: Could not find sromc configuration\n", __func__); 212 return 0; 213 } 214 node = fdtdec_next_compatible(gd->fdt_blob, node, COMPAT_SMSC_LAN9215); 215 if (node < 0) { 216 debug("%s: Could not find lan9215 configuration\n", __func__); 217 return 0; 218 } 219 220 /* We now have a node, so any problems from now on are errors */ 221 base_addr = fdtdec_get_addr(gd->fdt_blob, node, "reg"); 222 if (base_addr == FDT_ADDR_T_NONE) { 223 debug("%s: Could not find lan9215 address\n", __func__); 224 return -1; 225 } 226 227 /* Ethernet needs data bus width of 16 bits */ 228 if (config.width != 2) { 229 debug("%s: Unsupported bus width %d\n", __func__, 230 config.width); 231 return -1; 232 } 233 smc_bw_conf = SROMC_DATA16_WIDTH(config.bank) 234 | SROMC_BYTE_ENABLE(config.bank); 235 236 smc_bc_conf = SROMC_BC_TACS(config.timing[FDT_SROM_TACS]) | 237 SROMC_BC_TCOS(config.timing[FDT_SROM_TCOS]) | 238 SROMC_BC_TACC(config.timing[FDT_SROM_TACC]) | 239 SROMC_BC_TCOH(config.timing[FDT_SROM_TCOH]) | 240 SROMC_BC_TAH(config.timing[FDT_SROM_TAH]) | 241 SROMC_BC_TACP(config.timing[FDT_SROM_TACP]) | 242 SROMC_BC_PMC(config.timing[FDT_SROM_PMC]); 243 244 /* Select and configure the SROMC bank */ 245 exynos_pinmux_config(PERIPH_ID_SROMC, config.bank); 246 s5p_config_sromc(config.bank, smc_bw_conf, smc_bc_conf); 247 return smc911x_initialize(0, base_addr); 248 #endif 249 return 0; 250 } 251 252 #ifdef CONFIG_DISPLAY_BOARDINFO 253 int checkboard(void) 254 { 255 if (IS_ENABLED(CONFIG_BOARD_TYPES)) { 256 const char *board_info = get_board_type(); 257 258 if (board_info) 259 printf("Type: %s\n", board_info); 260 } 261 262 return 0; 263 } 264 #endif 265 266 #ifdef CONFIG_BOARD_LATE_INIT 267 int board_late_init(void) 268 { 269 struct udevice *dev; 270 int ret; 271 272 stdio_print_current_devices(); 273 ret = uclass_first_device_err(UCLASS_CROS_EC, &dev); 274 if (ret && ret != -ENODEV) { 275 /* Force console on */ 276 gd->flags &= ~GD_FLG_SILENT; 277 278 printf("cros-ec communications failure %d\n", ret); 279 puts("\nPlease reset with Power+Refresh\n\n"); 280 panic("Cannot init cros-ec device"); 281 return -1; 282 } 283 return 0; 284 } 285 #endif 286 287 #ifdef CONFIG_MISC_INIT_R 288 int misc_init_r(void) 289 { 290 #ifdef CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG 291 set_board_info(); 292 #endif 293 #ifdef CONFIG_LCD_MENU 294 keys_init(); 295 check_boot_mode(); 296 #endif 297 #ifdef CONFIG_CMD_BMP 298 if (panel_info.logo_on) 299 draw_logo(); 300 #endif 301 return 0; 302 } 303 #endif 304 305 void reset_misc(void) 306 { 307 struct gpio_desc gpio = {}; 308 int node; 309 310 node = fdt_node_offset_by_compatible(gd->fdt_blob, 0, 311 "samsung,emmc-reset"); 312 if (node < 0) 313 return; 314 315 gpio_request_by_name_nodev(offset_to_ofnode(node), "reset-gpio", 0, 316 &gpio, GPIOD_IS_OUT); 317 318 if (dm_gpio_is_valid(&gpio)) { 319 /* 320 * Reset eMMC 321 * 322 * FIXME: Need to optimize delay time. Minimum 1usec pulse is 323 * required by 'JEDEC Standard No.84-A441' (eMMC) 324 * document but real delay time is expected to greater 325 * than 1usec. 326 */ 327 dm_gpio_set_value(&gpio, 0); 328 mdelay(10); 329 dm_gpio_set_value(&gpio, 1); 330 } 331 } 332 333 int board_usb_cleanup(int index, enum usb_init_type init) 334 { 335 #ifdef CONFIG_USB_DWC3 336 dwc3_uboot_exit(index); 337 #endif 338 return 0; 339 } 340