// SPDX-License-Identifier: GPL-2.0+ /* * Copyright 2022 Marek Vasut */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include DECLARE_GLOBAL_DATA_PTR; #define WDOG_PAD_CTRL (PAD_CTL_DSE6 | PAD_CTL_ODE | PAD_CTL_PUE | PAD_CTL_PE) u8 dmo_get_memcfg(void) { struct gpio_desc gpio[4]; u8 memcfg = 0; ofnode node; int i, ret; node = ofnode_path("/config"); if (!ofnode_valid(node)) { printf("%s: no /config node?\n", __func__); return BIT(2) | BIT(0); } ret = gpio_request_list_by_name_nodev(node, "dmo,ram-coding-gpios", gpio, ARRAY_SIZE(gpio), GPIOD_IS_IN); for (i = 0; i < ret; i++) memcfg |= !!dm_gpio_get_value(&(gpio[i])) << i; gpio_free_list_nodev(gpio, ret); return memcfg; } int board_phys_sdram_size(phys_size_t *size) { u8 memcfg = dmo_get_memcfg(); *size = (4ULL >> ((memcfg >> 1) & 0x3)) * SZ_1G; return 0; } #ifdef CONFIG_SPL_BUILD static void data_modul_imx_edm_sbc_early_init_f(const iomux_v3_cfg_t wdog_pad) { struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR; imx_iomux_v3_setup_pad(wdog_pad | MUX_PAD_CTRL(WDOG_PAD_CTRL)); set_wdog_reset(wdog); } __weak int data_modul_imx_edm_sbc_board_power_init(void) { return 0; } static void spl_dram_init(struct dram_timing_info *dram_timing_info[8]) { u8 memcfg = dmo_get_memcfg(); int i; printf("DDR: %d GiB x%d [0x%x]\n", /* 0..4 GiB, 1..2 GiB, 0..1 GiB */ 4 >> ((memcfg >> 1) & 0x3), /* 0..x32, 1..x16 */ 32 >> (memcfg & BIT(0)), memcfg); if (!dram_timing_info[memcfg]) { printf("Unsupported DRAM strapping, trying lowest supported. MEMCFG=0x%x\n", memcfg); for (i = 7; i >= 0; i--) if (dram_timing_info[i]) /* Configuration found */ break; } ddr_init(dram_timing_info[memcfg]); } void dmo_board_init_f(const iomux_v3_cfg_t wdog_pad, struct dram_timing_info *dram_timing_info[8]) { struct udevice *dev; int ret; icache_enable(); arch_cpu_init(); init_uart_clk(2); data_modul_imx_edm_sbc_early_init_f(wdog_pad); /* Clear the BSS. */ memset(__bss_start, 0, __bss_end - __bss_start); ret = spl_early_init(); if (ret) { debug("spl_early_init() failed: %d\n", ret); hang(); } preloader_console_init(); ret = uclass_get_device_by_name(UCLASS_CLK, "clock-controller@30380000", &dev); if (ret < 0) { printf("Failed to find clock node. Check device tree\n"); hang(); } enable_tzc380(); data_modul_imx_edm_sbc_board_power_init(); /* DDR initialization */ spl_dram_init(dram_timing_info); board_init_r(NULL, 0); } #else void dmo_setup_boot_device(void) { int boot_device = get_boot_device(); char *devnum; devnum = env_get("devnum"); if (devnum) /* devnum is already set */ return; if (boot_device == MMC3_BOOT) /* eMMC */ env_set_ulong("devnum", 0); else env_set_ulong("devnum", 1); } void dmo_setup_mac_address(void) { unsigned char enetaddr[6]; struct udevice *dev; int off, ret; ret = eth_env_get_enetaddr("ethaddr", enetaddr); if (ret) /* ethaddr is already set */ return; off = fdt_path_offset(gd->fdt_blob, "eeprom0"); if (off < 0) { printf("%s: No eeprom0 path offset\n", __func__); return; } ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev); if (ret) { printf("Cannot find EEPROM!\n"); return; } ret = i2c_eeprom_read(dev, 0xb0, enetaddr, 0x6); if (ret) { printf("Error reading configuration EEPROM!\n"); return; } if (is_valid_ethaddr(enetaddr)) eth_env_set_enetaddr("ethaddr", enetaddr); } #endif