1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2022 Marek Vasut <marex@denx.de>
4 */
5
6#include <common.h>
7#include <asm-generic/gpio.h>
8#include <asm-generic/sections.h>
9#include <asm/arch/clock.h>
10#include <asm/arch/ddr.h>
11#include <asm/arch/sys_proto.h>
12#include <asm/io.h>
13#include <asm/mach-imx/boot_mode.h>
14#include <asm/mach-imx/iomux-v3.h>
15#include <dm/uclass.h>
16#include <hang.h>
17#include <i2c_eeprom.h>
18#include <image.h>
19#include <init.h>
20#include <net.h>
21#include <spl.h>
22
23#include <dm/uclass.h>
24#include <dm/device.h>
25#include <dm/uclass-internal.h>
26#include <dm/device-internal.h>
27
28DECLARE_GLOBAL_DATA_PTR;
29
30#define WDOG_PAD_CTRL	(PAD_CTL_DSE6 | PAD_CTL_ODE | PAD_CTL_PUE | PAD_CTL_PE)
31
32#define DDRC_ECCCFG0_ECC_MODE_MASK	0x7
33
34u8 dmo_get_memcfg(void)
35{
36	struct gpio_desc gpio[4];
37	u8 memcfg = 0;
38	ofnode node;
39	int i, ret;
40
41	node = ofnode_path("/config");
42	if (!ofnode_valid(node)) {
43		printf("%s: no /config node?\n", __func__);
44		return BIT(2) | BIT(0);
45	}
46
47	ret = gpio_request_list_by_name_nodev(node,
48					      "dmo,ram-coding-gpios",
49					      gpio, ARRAY_SIZE(gpio),
50					      GPIOD_IS_IN);
51	for (i = 0; i < ret; i++)
52		memcfg |= !!dm_gpio_get_value(&(gpio[i])) << i;
53
54	gpio_free_list_nodev(gpio, ret);
55
56	return memcfg;
57}
58
59int board_phys_sdram_size(phys_size_t *size)
60{
61	u8 memcfg = dmo_get_memcfg();
62	u8 ecc = 0;
63
64	*size = 4ULL >> ((memcfg >> 1) & 0x3);
65
66	if (IS_ENABLED(CONFIG_IMX8M_DRAM_INLINE_ECC)) {
67		/* 896 MiB, i.e. 1 GiB without 12.5% reserved for in-band ECC */
68		ecc = readl(DDRC_ECCCFG0(0)) & DDRC_ECCCFG0_ECC_MODE_MASK;
69	}
70
71	*size *= SZ_1G - (ecc ? (SZ_1G / 8) : 0);
72
73	return 0;
74}
75
76#ifdef CONFIG_SPL_BUILD
77static void data_modul_imx_edm_sbc_early_init_f(const iomux_v3_cfg_t wdog_pad)
78{
79	struct wdog_regs *wdog = (struct wdog_regs *)WDOG1_BASE_ADDR;
80
81	imx_iomux_v3_setup_pad(wdog_pad | MUX_PAD_CTRL(WDOG_PAD_CTRL));
82
83	set_wdog_reset(wdog);
84}
85
86__weak int data_modul_imx_edm_sbc_board_power_init(void)
87{
88	return 0;
89}
90
91static void spl_dram_init(struct dram_timing_info *dram_timing_info[8])
92{
93	u8 memcfg = dmo_get_memcfg();
94	int i;
95
96	printf("DDR:   %d GiB x%d [0x%x]\n",
97	       /* 0..4 GiB, 1..2 GiB, 0..1 GiB */
98	       4 >> ((memcfg >> 1) & 0x3),
99	       /* 0..x32, 1..x16 */
100	       32 >> (memcfg & BIT(0)),
101	       memcfg);
102
103	if (!dram_timing_info[memcfg]) {
104		printf("Unsupported DRAM strapping, trying lowest supported. MEMCFG=0x%x\n",
105		       memcfg);
106		for (i = 7; i >= 0; i--)
107			if (dram_timing_info[i])	/* Configuration found */
108				break;
109	}
110
111	ddr_init(dram_timing_info[memcfg]);
112
113	if (IS_ENABLED(CONFIG_IMX8M_DRAM_INLINE_ECC)) {
114		printf("DDR:   Inline ECC %sabled\n",
115		       (readl(DDRC_ECCCFG0(0)) & DDRC_ECCCFG0_ECC_MODE_MASK) ?
116		       "en" : "dis");
117	}
118}
119
120void dmo_board_init_f(const iomux_v3_cfg_t wdog_pad,
121		      struct dram_timing_info *dram_timing_info[8])
122{
123	struct udevice *dev;
124	int ret;
125
126	icache_enable();
127
128	arch_cpu_init();
129
130	init_uart_clk(2);
131
132	data_modul_imx_edm_sbc_early_init_f(wdog_pad);
133
134	/* Clear the BSS. */
135	memset(__bss_start, 0, __bss_end - __bss_start);
136
137	ret = spl_early_init();
138	if (ret) {
139		debug("spl_early_init() failed: %d\n", ret);
140		hang();
141	}
142
143	preloader_console_init();
144
145	ret = uclass_get_device_by_name(UCLASS_CLK,
146					"clock-controller@30380000",
147					&dev);
148	if (ret < 0) {
149		printf("Failed to find clock node. Check device tree\n");
150		hang();
151	}
152
153	enable_tzc380();
154
155	data_modul_imx_edm_sbc_board_power_init();
156
157	/* DDR initialization */
158	spl_dram_init(dram_timing_info);
159
160	board_init_r(NULL, 0);
161}
162#else
163void dmo_setup_boot_device(void)
164{
165	int boot_device = get_boot_device();
166	char *devnum;
167
168	devnum = env_get("devnum");
169	if (devnum)	/* devnum is already set */
170		return;
171
172	if (boot_device == MMC3_BOOT)	/* eMMC */
173		env_set_ulong("devnum", 0);
174	else
175		env_set_ulong("devnum", 1);
176}
177
178void dmo_setup_mac_address(void)
179{
180	unsigned char enetaddr[6];
181	struct udevice *dev;
182	int off, ret;
183
184	ret = eth_env_get_enetaddr("ethaddr", enetaddr);
185	if (ret)	/* ethaddr is already set */
186		return;
187
188	off = fdt_path_offset(gd->fdt_blob, "eeprom0");
189	if (off < 0) {
190		printf("%s: No eeprom0 path offset\n", __func__);
191		return;
192	}
193
194	ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev);
195	if (ret) {
196		printf("Cannot find EEPROM!\n");
197		return;
198	}
199
200	ret = i2c_eeprom_read(dev, 0xb0, enetaddr, 0x6);
201	if (ret) {
202		printf("Error reading configuration EEPROM!\n");
203		return;
204	}
205
206	if (is_valid_ethaddr(enetaddr))
207		eth_env_set_enetaddr("ethaddr", enetaddr);
208}
209#endif
210