1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * (C) Copyright 2018 Cisco Systems, Inc. 4 * 5 * Author: Thomas Fitzsimmons <fitzsim@fitzsim.org> 6 */ 7 8 #include <linux/types.h> 9 #include <common.h> 10 #include <asm/io.h> 11 #include <asm/bootm.h> 12 #include <mach/sdhci.h> 13 #include <mach/timer.h> 14 #include <mmc.h> 15 #include <fdtdec.h> 16 17 DECLARE_GLOBAL_DATA_PTR; 18 19 #define BCMSTB_DATA_SECTION __attribute__((section(".data"))) 20 21 struct bcmstb_boot_parameters bcmstb_boot_parameters BCMSTB_DATA_SECTION; 22 23 phys_addr_t prior_stage_fdt_address BCMSTB_DATA_SECTION; 24 25 union reg_value_union { 26 const char *data; 27 const phys_addr_t *address; 28 }; 29 30 int board_init(void) 31 { 32 return 0; 33 } 34 35 u32 get_board_rev(void) 36 { 37 return 0; 38 } 39 40 void reset_cpu(ulong ignored) 41 { 42 } 43 44 int print_cpuinfo(void) 45 { 46 return 0; 47 } 48 49 int dram_init(void) 50 { 51 if (fdtdec_setup_memory_size() != 0) 52 return -EINVAL; 53 54 return 0; 55 } 56 57 int dram_init_banksize(void) 58 { 59 fdtdec_setup_memory_banksize(); 60 61 /* 62 * On this SoC, U-Boot is running as an ELF file. Change the 63 * relocation address to CONFIG_SYS_TEXT_BASE, so that in 64 * setup_reloc, gd->reloc_off works out to 0, effectively 65 * disabling relocation. Otherwise U-Boot hangs in the setup 66 * instructions just before relocate_code in 67 * arch/arm/lib/crt0.S. 68 */ 69 gd->relocaddr = CONFIG_SYS_TEXT_BASE; 70 71 return 0; 72 } 73 74 void enable_caches(void) 75 { 76 /* 77 * This port assumes that the prior stage bootloader has 78 * enabled I-cache and D-cache already. Implementing this 79 * function silences the warning in the default function. 80 */ 81 } 82 83 static const phys_addr_t bcmstb_sdhci_address(u32 alias_index) 84 { 85 int node = 0; 86 int ret = 0; 87 char sdhci[16] = { 0 }; 88 const void *fdt = gd->fdt_blob; 89 const char *path = NULL; 90 struct fdt_resource resource = { 0 }; 91 92 if (!fdt) { 93 printf("%s: Invalid gd->fdt_blob\n", __func__); 94 return 0; 95 } 96 97 node = fdt_path_offset(fdt, "/aliases"); 98 if (node < 0) { 99 printf("%s: Failed to find /aliases node\n", __func__); 100 return 0; 101 } 102 103 sprintf(sdhci, "sdhci%d", alias_index); 104 path = fdt_getprop(fdt, node, sdhci, NULL); 105 if (!path) { 106 printf("%s: Failed to find alias for %s\n", __func__, sdhci); 107 return 0; 108 } 109 110 node = fdt_path_offset(fdt, path); 111 if (node < 0) { 112 printf("%s: Failed to resolve BCMSTB SDHCI alias\n", __func__); 113 return 0; 114 } 115 116 ret = fdt_get_named_resource(fdt, node, "reg", "reg-names", 117 "host", &resource); 118 if (ret) { 119 printf("%s: Failed to read BCMSTB SDHCI host resource\n", 120 __func__); 121 return 0; 122 } 123 124 return resource.start; 125 } 126 127 int board_mmc_init(bd_t *bis) 128 { 129 phys_addr_t sdhci_base_address = 0; 130 131 sdhci_base_address = bcmstb_sdhci_address(CONFIG_BCMSTB_SDHCI_INDEX); 132 133 if (!sdhci_base_address) { 134 sdhci_base_address = BCMSTB_SDHCI_BASE; 135 printf("%s: Assuming BCMSTB SDHCI address: 0x%p\n", 136 __func__, (void *)sdhci_base_address); 137 } 138 139 debug("BCMSTB SDHCI base address: 0x%p\n", (void *)sdhci_base_address); 140 141 bcmstb_sdhci_init(sdhci_base_address); 142 143 return 0; 144 } 145 146 int timer_init(void) 147 { 148 gd->arch.timer_rate_hz = readl(BCMSTB_TIMER_FREQUENCY); 149 150 return 0; 151 } 152 153 ulong get_tbclk(void) 154 { 155 return gd->arch.timer_rate_hz; 156 } 157 158 uint64_t get_ticks(void) 159 { 160 gd->timebase_h = readl(BCMSTB_TIMER_HIGH); 161 gd->timebase_l = readl(BCMSTB_TIMER_LOW); 162 163 return ((uint64_t)gd->timebase_h << 32) | gd->timebase_l; 164 } 165 166 int board_late_init(void) 167 { 168 debug("Arguments from prior stage bootloader:\n"); 169 debug("General Purpose Register 0: 0x%x\n", bcmstb_boot_parameters.r0); 170 debug("General Purpose Register 1: 0x%x\n", bcmstb_boot_parameters.r1); 171 debug("General Purpose Register 2: 0x%x\n", bcmstb_boot_parameters.r2); 172 debug("General Purpose Register 3: 0x%x\n", bcmstb_boot_parameters.r3); 173 debug("Stack Pointer Register: 0x%x\n", bcmstb_boot_parameters.sp); 174 debug("Link Register: 0x%x\n", bcmstb_boot_parameters.lr); 175 debug("Assuming timer frequency register at: 0x%p\n", 176 (void *)BCMSTB_TIMER_FREQUENCY); 177 debug("Read timer frequency (in Hz): %ld\n", gd->arch.timer_rate_hz); 178 debug("Prior stage provided DTB at: 0x%p\n", 179 (void *)prior_stage_fdt_address); 180 181 /* 182 * Set fdtcontroladdr in the environment so that scripts can 183 * refer to it, for example, to reuse it for fdtaddr. 184 */ 185 env_set_hex("fdtcontroladdr", prior_stage_fdt_address); 186 187 /* 188 * Do not set machid to the machine identifier value provided 189 * by the prior stage bootloader (bcmstb_boot_parameters.r1) 190 * because we're using a device tree to boot Linux. 191 */ 192 193 return 0; 194 } 195