Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 | // SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2016 Freescale Semiconductor, Inc. * Copyright 2021 NXP */ #include <config.h> #include <command.h> #include <fdt_support.h> #include <hang.h> #include <i2c.h> #include <asm/cache.h> #include <init.h> #include <asm/global_data.h> #include <asm/io.h> #include <asm/arch/clock.h> #include <asm/arch/fsl_serdes.h> #include <asm/arch/mmu.h> #include <asm/arch/soc.h> #include <hwconfig.h> #include <ahci.h> #include <mmc.h> #include <scsi.h> #include <fsl_esdhc.h> #include <env_internal.h> #include <fsl_mmdc.h> #include <netdev.h> #include <net/pfe_eth/pfe/pfe_hw.h> DECLARE_GLOBAL_DATA_PTR; #define BOOT_FROM_UPPER_BANK 0x2 #define BOOT_FROM_LOWER_BANK 0x1 int checkboard(void) { #ifdef CONFIG_TARGET_LS1012ARDB u8 in1; int ret, bus_num = 0; puts("Board: LS1012ARDB "); /* Initialize i2c early for Serial flash bank information */ #if CONFIG_IS_ENABLED(DM_I2C) struct udevice *dev; ret = i2c_get_chip_for_busnum(bus_num, I2C_MUX_IO_ADDR, 1, &dev); if (ret) { printf("%s: Cannot find udev for a bus %d\n", __func__, bus_num); return -ENXIO; } ret = dm_i2c_read(dev, I2C_MUX_IO_1, &in1, 1); #else /* Non DM I2C support - will be removed */ i2c_set_bus_num(bus_num); ret = i2c_read(I2C_MUX_IO_ADDR, I2C_MUX_IO_1, 1, &in1, 1); #endif if (ret < 0) { printf("Error reading i2c boot information!\n"); return 0; /* Don't want to hang() on this error */ } puts("Version"); switch (in1 & SW_REV_MASK) { case SW_REV_A: puts(": RevA"); break; case SW_REV_B: puts(": RevB"); break; case SW_REV_C: puts(": RevC"); break; case SW_REV_C1: puts(": RevC1"); break; case SW_REV_C2: puts(": RevC2"); break; case SW_REV_D: puts(": RevD"); break; case SW_REV_E: puts(": RevE"); break; default: puts(": unknown"); break; } printf(", boot from QSPI"); if ((in1 & SW_BOOT_MASK) == SW_BOOT_EMU) puts(": emu\n"); else if ((in1 & SW_BOOT_MASK) == SW_BOOT_BANK1) puts(": bank1\n"); else if ((in1 & SW_BOOT_MASK) == SW_BOOT_BANK2) puts(": bank2\n"); else puts("unknown\n"); #else puts("Board: LS1012A2G5RDB "); #endif return 0; } #ifdef CONFIG_TFABOOT int dram_init(void) { gd->ram_size = tfa_get_dram_size(); if (!gd->ram_size) gd->ram_size = CFG_SYS_SDRAM_SIZE; return 0; } #else int dram_init(void) { #ifndef CONFIG_TFABOOT static const struct fsl_mmdc_info mparam = { 0x05180000, /* mdctl */ 0x00030035, /* mdpdc */ 0x12554000, /* mdotc */ 0xbabf7954, /* mdcfg0 */ 0xdb328f64, /* mdcfg1 */ 0x01ff00db, /* mdcfg2 */ 0x00001680, /* mdmisc */ 0x0f3c8000, /* mdref */ 0x00002000, /* mdrwd */ 0x00bf1023, /* mdor */ 0x0000003f, /* mdasp */ 0x0000022a, /* mpodtctrl */ 0xa1390003, /* mpzqhwctrl */ }; mmdc_init(&mparam); #endif gd->ram_size = CFG_SYS_SDRAM_SIZE; #if !defined(CONFIG_SPL) || defined(CONFIG_XPL_BUILD) /* This will break-before-make MMU for DDR */ update_early_mmu_table(); #endif return 0; } #endif int board_early_init_f(void) { fsl_lsch2_early_init_f(); return 0; } int board_init(void) { struct ccsr_cci400 *cci = (struct ccsr_cci400 *)(CONFIG_SYS_IMMR + CONFIG_SYS_CCI400_OFFSET); /* * Set CCI-400 control override register to enable barrier * transaction */ if (current_el() == 3) out_le32(&cci->ctrl_ord, CCI400_CTRLORD_EN_BARRIER); #ifdef CONFIG_SYS_FSL_ERRATUM_A010315 erratum_a010315(); #endif return 0; } #ifdef CONFIG_FSL_PFE void board_quiesce_devices(void) { pfe_command_stop(0, NULL); } #endif #ifdef CONFIG_TARGET_LS1012ARDB int esdhc_status_fixup(void *blob, const char *compat) { char esdhc1_path[] = "/soc/esdhc@1580000"; bool sdhc2_en = false; u8 mux_sdhc2; u8 io = 0; int ret, bus_num = 0; #if CONFIG_IS_ENABLED(DM_I2C) struct udevice *dev; ret = i2c_get_chip_for_busnum(bus_num, I2C_MUX_IO_ADDR, 1, &dev); if (ret) { printf("%s: Cannot find udev for a bus %d\n", __func__, bus_num); return -ENXIO; } ret = dm_i2c_read(dev, I2C_MUX_IO_1, &io, 1); #else i2c_set_bus_num(bus_num); /* IO1[7:3] is the field of board revision info. */ ret = i2c_read(I2C_MUX_IO_ADDR, I2C_MUX_IO_1, 1, &io, 1); #endif if (ret < 0) { printf("Error reading i2c boot information!\n"); return 0; } /* hwconfig method is used for RevD and later versions. */ if ((io & SW_REV_MASK) <= SW_REV_D) { #ifdef CONFIG_HWCONFIG if (hwconfig("esdhc1")) sdhc2_en = true; #endif } else { /* * The I2C IO-expander for mux select is used to control * the muxing of various onboard interfaces. * * IO0[3:2] indicates SDHC2 interface demultiplexer * select lines. * 00 - SDIO wifi * 01 - GPIO (to Arduino) * 10 - eMMC Memory * 11 - SPI */ #if CONFIG_IS_ENABLED(DM_I2C) ret = dm_i2c_read(dev, I2C_MUX_IO_0, &io, 1); #else ret = i2c_read(I2C_MUX_IO_ADDR, I2C_MUX_IO_0, 1, &io, 1); #endif if (ret < 0) { printf("Error reading i2c boot information!\n"); return 0; } mux_sdhc2 = (io & 0x0c) >> 2; /* Enable SDHC2 only when use SDIO wifi and eMMC */ if (mux_sdhc2 == 2 || mux_sdhc2 == 0) sdhc2_en = true; } if (sdhc2_en) do_fixup_by_path(blob, esdhc1_path, "status", "okay", sizeof("okay"), 1); else do_fixup_by_path(blob, esdhc1_path, "status", "disabled", sizeof("disabled"), 1); return 0; } #endif int ft_board_setup(void *blob, struct bd_info *bd) { arch_fixup_fdt(blob); ft_cpu_setup(blob, bd); return 0; } static int switch_to_bank1(void) { u8 data = 0xf4, chip_addr = 0x24, offset_addr = 0x03; int ret, bus_num = 0; #if CONFIG_IS_ENABLED(DM_I2C) struct udevice *dev; ret = i2c_get_chip_for_busnum(bus_num, chip_addr, 1, &dev); if (ret) { printf("%s: Cannot find udev for a bus %d\n", __func__, bus_num); return -ENXIO; } /* * -------------------------------------------------------------------- * |bus |I2C address| Device | Notes | * -------------------------------------------------------------------- * |I2C1|0x24, 0x25,| IO expander (CFG,| Provides 16bits of General | * | |0x26 | RESET, and INT/ | Purpose parallel Input/Output| * | | | KW41GPIO) - NXP | (GPIO) expansion for the | * | | | PCAL9555AHF | I2C bus | * ----- -------------------------------------------------------------- * - mount three IO expander(PCAL9555AHF) on I2C1 * * PCAL9555A device address * slave address * -------------------------------------- * | 0 | 1 | 0 | 0 | A2 | A1 | A0 | R/W | * -------------------------------------- * | fixed | hardware selectable| * * Output port 1(Pinter register bits = 0x03) * * P1_[7~0] = 0xf4 * P1_0 <---> CFG_MUX_QSPI_S0 * P1_1 <---> CFG_MUX_QSPI_S1 * CFG_MUX_QSPI_S[1:0] = 0b00 * * QSPI chip-select demultiplexer select * --------------------------------------------------------------------- * CFG_MUX_QSPI_S1|CFG_MUX_QSPI_S0| Values * --------------------------------------------------------------------- * 0 | 0 |CS routed to SPI memory bank1(default) * --------------------------------------------------------------------- * 0 | 1 |CS routed to SPI memory bank2 * --------------------------------------------------------------------- * */ ret = dm_i2c_write(dev, offset_addr, &data, 1); #else /* Non DM I2C support - will be removed */ i2c_set_bus_num(bus_num); ret = i2c_write(chip_addr, offset_addr, 1, &data, 1); #endif if (ret) { printf("i2c write error to chip : %u, addr : %u, data : %u\n", chip_addr, offset_addr, data); } return ret; } static int switch_to_bank2(void) { u8 data[2] = {0xfc, 0xf5}, offset_addr[2] = {0x7, 0x3}; u8 chip_addr = 0x24; int ret, i, bus_num = 0; #if CONFIG_IS_ENABLED(DM_I2C) struct udevice *dev; ret = i2c_get_chip_for_busnum(bus_num, chip_addr, 1, &dev); if (ret) { printf("%s: Cannot find udev for a bus %d\n", __func__, bus_num); return -ENXIO; } #else /* Non DM I2C support - will be removed */ i2c_set_bus_num(bus_num); #endif /* * 1th step: config port 1 * - the port 1 pin is enabled as an output * 2th step: output port 1 * - P1_[7:0] output 0xf5, * then CFG_MUX_QSPI_S[1:0] equal to 0b01, * CS routed to SPI memory bank2 */ for (i = 0; i < sizeof(data); i++) { #if CONFIG_IS_ENABLED(DM_I2C) ret = dm_i2c_write(dev, offset_addr[i], &data[i], 1); #else /* Non DM I2C support - will be removed */ ret = i2c_write(chip_addr, offset_addr[i], 1, &data[i], 1); #endif if (ret) { printf("i2c write error to chip : %u, addr : %u, data : %u\n", chip_addr, offset_addr[i], data[i]); goto err; } } err: return ret; } static int convert_flash_bank(int bank) { int ret = 0; switch (bank) { case BOOT_FROM_UPPER_BANK: ret = switch_to_bank2(); break; case BOOT_FROM_LOWER_BANK: ret = switch_to_bank1(); break; default: ret = CMD_RET_USAGE; break; }; return ret; } static int flash_bank_cmd(struct cmd_tbl *cmdtp, int flag, int argc, char *const argv[]) { if (argc != 2) return CMD_RET_USAGE; if (strcmp(argv[1], "1") == 0) convert_flash_bank(BOOT_FROM_LOWER_BANK); else if (strcmp(argv[1], "2") == 0) convert_flash_bank(BOOT_FROM_UPPER_BANK); else return CMD_RET_USAGE; return 0; } U_BOOT_CMD( boot_bank, 2, 0, flash_bank_cmd, "Flash bank Selection Control", "bank[1-lower bank/2-upper bank] (e.g. boot_bank 1)" ); |