blob: 27200f728efedbb90d6bc148edb9c7a4ddadba5e [file] [log] [blame]
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +08001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright 2018 NXP
4 * Copyright 2020 Linaro
5 */
6
7#include <common.h>
8#include <env.h>
Ying-Chun Liu (PaulLiu)a96ed8d2021-11-05 17:13:25 +08009#include <extension_board.h>
Ying-Chun Liu (PaulLiu)20dc0ba2021-08-24 17:44:19 +080010#include <hang.h>
Ying-Chun Liu (PaulLiu)a96ed8d2021-11-05 17:13:25 +080011#include <i2c.h>
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +080012#include <init.h>
13#include <miiphy.h>
14#include <netdev.h>
Fabio Estevamf2acfc72022-04-12 13:05:37 -030015#include <i2c_eeprom.h>
16#include <i2c.h>
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +080017
18#include <asm/arch/clock.h>
Ying-Chun Liu (PaulLiu)a96ed8d2021-11-05 17:13:25 +080019#include <asm/arch/imx8mm_pins.h>
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +080020#include <asm/arch/sys_proto.h>
Ying-Chun Liu (PaulLiu)a96ed8d2021-11-05 17:13:25 +080021#include <asm/global_data.h>
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +080022#include <asm/io.h>
Ying-Chun Liu (PaulLiu)a96ed8d2021-11-05 17:13:25 +080023#include <asm/mach-imx/gpio.h>
24#include <asm/mach-imx/mxc_i2c.h>
25#include <asm/sections.h>
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +080026
Ying-Chun Liu (PaulLiu)20dc0ba2021-08-24 17:44:19 +080027#include "ddr/ddr.h"
28
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +080029DECLARE_GLOBAL_DATA_PTR;
30
Ying-Chun Liu (PaulLiu)20dc0ba2021-08-24 17:44:19 +080031int board_phys_sdram_size(phys_size_t *size)
32{
33 struct lpddr4_tcm_desc *lpddr4_tcm_desc =
34 (struct lpddr4_tcm_desc *)TCM_DATA_CFG;
35
36 switch (lpddr4_tcm_desc->size) {
37 case 4096:
38 case 2048:
39 case 1024:
40 *size = (1L << 20) * lpddr4_tcm_desc->size;
41 break;
42 default:
43 printf("%s: DRAM size %uM is not supported\n",
44 __func__,
45 lpddr4_tcm_desc->size);
46 hang();
47 break;
48 };
49
50 return 0;
51}
52
Ying-Chun Liu (PaulLiu)a96ed8d2021-11-05 17:13:25 +080053/* IOT_GATE-iMX8 extension boards ID */
54typedef enum {
55 IOT_GATE_EXT_EMPTY, /* No extension */
56 IOT_GATE_EXT_CAN, /* CAN bus */
57 IOT_GATE_EXT_IED, /* Bridge */
58 IOT_GATE_EXT_POE, /* POE */
59 IOT_GATE_EXT_POEV2, /* POEv2 */
60} iot_gate_imx8_ext;
61
62typedef enum {
63 IOT_GATE_IMX8_CARD_ID_EMPTY = 0, /* card id - uninhabited */
64 IOT_GATE_IMX8_CARD_ID_DI4O4 = 1, /* Card ID - IED-DI4O4 */
65 IOT_GATE_IMX8_CARD_ID_RS_485 = 2, /* Card ID - IED-RS485 */
66 IOT_GATE_IMX8_CARD_ID_TPM = 3, /* Card ID - IED-TPM */
67 IOT_GATE_IMX8_CARD_ID_CAN = 4, /* Card ID - IED-CAN */
68 IOT_GATE_IMX8_CARD_ID_CL420 = 5, /* Card ID - IED-CL420 */
69 IOT_GATE_IMX8_CARD_ID_RS_232 = 6, /* Card ID - IED-RS232 */
70} iot_gate_imx8_ied_ext;
71
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +080072static int setup_fec(void)
73{
74 if (IS_ENABLED(CONFIG_FEC_MXC)) {
75 struct iomuxc_gpr_base_regs *gpr =
76 (struct iomuxc_gpr_base_regs *)IOMUXC_GPR_BASE_ADDR;
77
78 /* Use 125M anatop REF_CLK1 for ENET1, not from external */
79 clrsetbits_le32(&gpr->gpr[1], 0x2000, 0);
80 }
81
82 return 0;
83}
84
85int board_phy_config(struct phy_device *phydev)
86{
87 if (IS_ENABLED(CONFIG_FEC_MXC)) {
88 /* enable rgmii rxc skew and phy mode select to RGMII copper */
89 phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x1f);
90 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x8);
91
92 phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x00);
93 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x82ee);
94 phy_write(phydev, MDIO_DEVAD_NONE, 0x1d, 0x05);
95 phy_write(phydev, MDIO_DEVAD_NONE, 0x1e, 0x100);
96
97 if (phydev->drv->config)
98 phydev->drv->config(phydev);
99 }
100 return 0;
101}
102
103int board_init(void)
104{
105 if (IS_ENABLED(CONFIG_FEC_MXC))
106 setup_fec();
107
108 return 0;
109}
110
111int board_mmc_get_env_dev(int devno)
112{
113 return devno;
114}
115
Ying-Chun Liu (PaulLiu)a96ed8d2021-11-05 17:13:25 +0800116#define IOT_GATE_IMX8_EXT_I2C 3 /* I2C ID of the extension board */
117#define IOT_GATE_IMX8_EXT_I2C_ADDR_EEPROM 0x54 /* I2C address of the EEPROM */
118
119/* I2C address of the EEPROM in the POE extension */
120#define IOT_GATE_IMX8_EXT_I2C_ADDR_EEPROM_POE 0x50
121#define IOT_GATE_IMX8_EXT_I2C_ADDR_EEPROM_POEV2 0x51
122#define IOT_GATE_IMX8_EXT_I2C_ADDR_GPIO 0x22 /* I2C address of the GPIO
123 extender */
124
125static int iot_gate_imx8_ext_id = IOT_GATE_EXT_EMPTY; /* Extension board ID */
126static int iot_gate_imx8_ext_ied_id [3] = {
127 IOT_GATE_IMX8_CARD_ID_EMPTY,
128 IOT_GATE_IMX8_CARD_ID_EMPTY,
129 IOT_GATE_IMX8_CARD_ID_EMPTY };
130
131/*
132 * iot_gate_imx8_detect_ext() - extended board detection
133 * The detection is done according to the detected I2C devices.
134 */
135static void iot_gate_imx8_detect_ext(void)
136{
137 int ret;
138 struct udevice *i2c_bus, *i2c_dev;
139
140 ret = uclass_get_device_by_seq(UCLASS_I2C, IOT_GATE_IMX8_EXT_I2C,
141 &i2c_bus);
142 if (ret) {
143 printf("%s: Failed getting i2c device\n", __func__);
144 return;
145 }
146
147 ret = dm_i2c_probe(i2c_bus, IOT_GATE_IMX8_EXT_I2C_ADDR_EEPROM_POE, 0,
148 &i2c_dev);
149 if (!ret) {
150 iot_gate_imx8_ext_id = IOT_GATE_EXT_POE;
151 return;
152 }
153
154 ret = dm_i2c_probe(i2c_bus, IOT_GATE_IMX8_EXT_I2C_ADDR_EEPROM_POEV2, 0,
155 &i2c_dev);
156 if (!ret) {
157 iot_gate_imx8_ext_id = IOT_GATE_EXT_POEV2;
158 return;
159 }
160
161 ret = dm_i2c_probe(i2c_bus, IOT_GATE_IMX8_EXT_I2C_ADDR_EEPROM, 0,
162 &i2c_dev);
163 if (ret){
164 iot_gate_imx8_ext_id = IOT_GATE_EXT_EMPTY;
165 return;
166 }
167 /* Only the bridge extension includes the GPIO extender */
168 ret = dm_i2c_probe(i2c_bus, IOT_GATE_IMX8_EXT_I2C_ADDR_GPIO, 0,
169 &i2c_dev);
170 if (ret) /* GPIO extender not detected */
171 iot_gate_imx8_ext_id = IOT_GATE_EXT_CAN;
172 else /* GPIO extender detected */
173 iot_gate_imx8_ext_id = IOT_GATE_EXT_IED;
174}
175
176static iomux_v3_cfg_t const iot_gate_imx8_ext_ied_pads[] = {
177 IMX8MM_PAD_NAND_ALE_GPIO3_IO0 | MUX_PAD_CTRL(PAD_CTL_PE),
178 IMX8MM_PAD_NAND_CE0_B_GPIO3_IO1 | MUX_PAD_CTRL(PAD_CTL_PE),
179 IMX8MM_PAD_NAND_DATA00_GPIO3_IO6 | MUX_PAD_CTRL(PAD_CTL_PE),
180 IMX8MM_PAD_NAND_DATA01_GPIO3_IO7 | MUX_PAD_CTRL(PAD_CTL_PE),
181 IMX8MM_PAD_NAND_DATA02_GPIO3_IO8 | MUX_PAD_CTRL(PAD_CTL_PE),
182 IMX8MM_PAD_NAND_DATA03_GPIO3_IO9 | MUX_PAD_CTRL(PAD_CTL_PE),
183};
184
185static iomux_v3_cfg_t const iot_gate_imx8_ext_poev2_pads[] = {
186 IMX8MM_PAD_SAI3_TXD_GPIO5_IO1 | MUX_PAD_CTRL(PAD_CTL_PE |
187 PAD_CTL_PUE),
188};
189
190/* Extension board bridge GPIOs */
191#define IOT_GATE_IMX8_GPIO_EXT_IED_I0 IMX_GPIO_NR(3, 0) /* IN 0 */
192#define IOT_GATE_IMX8_GPIO_EXT_IED_I1 IMX_GPIO_NR(3, 1) /* IN 1 */
193#define IOT_GATE_IMX8_GPIO_EXT_IED_I2 IMX_GPIO_NR(3, 6) /* IN 2 */
194#define IOT_GATE_IMX8_GPIO_EXT_IED_I3 IMX_GPIO_NR(3, 7) /* IN 3 */
195#define IOT_GATE_IMX8_GPIO_EXT_IED_O0 IMX_GPIO_NR(3, 8) /* OUT 0 */
196#define IOT_GATE_IMX8_GPIO_EXT_IED_O1 IMX_GPIO_NR(3, 9) /* OUT 1 */
197#define IOT_GATE_IMX8_GPIO_EXT_IED_O2 IMX_GPIO_NR(6, 9) /* OUT 2 */
198#define IOT_GATE_IMX8_GPIO_EXT_IED_O3 IMX_GPIO_NR(6, 10)/* OUT 3 */
199
200/* Extension board POE GPIOs */
201#define IOT_GATE_IMX8_GPIO_EXT_POE_MUX IMX_GPIO_NR(5, 1)/* USB_MUX */
202
203/*
204 * iot_gate_imx8_update_pinmux() - update the pinmux
205 * Update the pinmux according to the detected extended board.
206 */
207static void iot_gate_imx8_update_pinmux(void)
208{
209 if (iot_gate_imx8_ext_id == IOT_GATE_EXT_POEV2) {
210 imx_iomux_v3_setup_multiple_pads(iot_gate_imx8_ext_poev2_pads,
211 ARRAY_SIZE(iot_gate_imx8_ext_poev2_pads));
212 gpio_request(IOT_GATE_IMX8_GPIO_EXT_POE_MUX, "poev2_usb-mux");
213 /* Update USB MUX state */
214 gpio_direction_output(IOT_GATE_IMX8_GPIO_EXT_POE_MUX, 1);
215
216 return;
217 }
218 if (iot_gate_imx8_ext_id != IOT_GATE_EXT_IED)
219 return;
220
221 imx_iomux_v3_setup_multiple_pads(iot_gate_imx8_ext_ied_pads,
222 ARRAY_SIZE(iot_gate_imx8_ext_ied_pads));
223
224 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_I0, "ied-di4o4_i0");
225 gpio_direction_input(IOT_GATE_IMX8_GPIO_EXT_IED_I0);
226 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_I1, "ied-di4o4_i1");
227 gpio_direction_input(IOT_GATE_IMX8_GPIO_EXT_IED_I1);
228 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_I2, "ied-di4o4_i2");
229 gpio_direction_input(IOT_GATE_IMX8_GPIO_EXT_IED_I2);
230 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_I3, "ied-di4o4_i3");
231 gpio_direction_input(IOT_GATE_IMX8_GPIO_EXT_IED_I3);
232 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_O0, "ied-di4o4_o0");
233 gpio_direction_output(IOT_GATE_IMX8_GPIO_EXT_IED_O0, 0);
234 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_O1, "ied-di4o4_o1");
235 gpio_direction_output(IOT_GATE_IMX8_GPIO_EXT_IED_O1, 0);
236 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_O2, "ied-di4o4_o2");
237 gpio_direction_output(IOT_GATE_IMX8_GPIO_EXT_IED_O2, 0);
238 gpio_request(IOT_GATE_IMX8_GPIO_EXT_IED_O3, "ied-di4o4_o3");
239 gpio_direction_output(IOT_GATE_IMX8_GPIO_EXT_IED_O3, 0);
240}
241
242#define IOT_GATE_IMX8_GPIO_S0B0 IMX_GPIO_NR(6, 0) /* Slot ID slot 0 bit 0 */
243#define IOT_GATE_IMX8_GPIO_S0B1 IMX_GPIO_NR(6, 1) /* Slot ID slot 0 bit 1 */
244#define IOT_GATE_IMX8_GPIO_S0B2 IMX_GPIO_NR(6, 2) /* Slot ID slot 0 bit 2 */
245#define IOT_GATE_IMX8_GPIO_S1B0 IMX_GPIO_NR(6, 3) /* Slot ID slot 1 bit 0 */
246#define IOT_GATE_IMX8_GPIO_S1B1 IMX_GPIO_NR(6, 4) /* Slot ID slot 1 bit 1 */
247#define IOT_GATE_IMX8_GPIO_S1B2 IMX_GPIO_NR(6, 5) /* Slot ID slot 1 bit 2 */
248#define IOT_GATE_IMX8_GPIO_S2B0 IMX_GPIO_NR(6, 6) /* Slot ID slot 2 bit 0 */
249#define IOT_GATE_IMX8_GPIO_S2B1 IMX_GPIO_NR(6, 7) /* Slot ID slot 2 bit 1 */
250#define IOT_GATE_IMX8_GPIO_S2B2 IMX_GPIO_NR(6, 8) /* Slot ID slot 2 bit 2 */
251
252/*
253 * iot_gate_imx8_update_ext_ied()
254 * Update device tree of the extended board IED-BASE.
255 * The device tree is updated according to the detected sub modules.
256 *
257 * Return 0 for success, 1 for failure.
258 */
259static int iot_gate_imx8_update_ext_ied(void)
260{
261 int revision;
262
263 if (iot_gate_imx8_ext_id != IOT_GATE_EXT_IED)
264 return 0;
265
266 /* ID GPIO initializations */
267 if (gpio_request(IOT_GATE_IMX8_GPIO_S0B0, "id_s0b0") ||
268 gpio_request(IOT_GATE_IMX8_GPIO_S0B1, "id_s0b1") ||
269 gpio_request(IOT_GATE_IMX8_GPIO_S0B2, "id_s0b2") ||
270 gpio_request(IOT_GATE_IMX8_GPIO_S1B0, "id_s1b0") ||
271 gpio_request(IOT_GATE_IMX8_GPIO_S1B1, "id_s1b1") ||
272 gpio_request(IOT_GATE_IMX8_GPIO_S1B2, "id_s1b2") ||
273 gpio_request(IOT_GATE_IMX8_GPIO_S2B0, "id_s2b0") ||
274 gpio_request(IOT_GATE_IMX8_GPIO_S2B1, "id_s2b1") ||
275 gpio_request(IOT_GATE_IMX8_GPIO_S2B2, "id_s2b2")) {
276 printf("%s: ID GPIO request failure\n", __func__);
277 return 1;
278 }
279 gpio_direction_input(IOT_GATE_IMX8_GPIO_S0B0);
280 gpio_direction_input(IOT_GATE_IMX8_GPIO_S0B1);
281 gpio_direction_input(IOT_GATE_IMX8_GPIO_S0B2);
282 gpio_direction_input(IOT_GATE_IMX8_GPIO_S1B0);
283 gpio_direction_input(IOT_GATE_IMX8_GPIO_S1B1);
284 gpio_direction_input(IOT_GATE_IMX8_GPIO_S1B2);
285 gpio_direction_input(IOT_GATE_IMX8_GPIO_S2B0);
286 gpio_direction_input(IOT_GATE_IMX8_GPIO_S2B1);
287 gpio_direction_input(IOT_GATE_IMX8_GPIO_S2B2);
288
289 /* Get slot 0 card ID */
290 revision = gpio_get_value(IOT_GATE_IMX8_GPIO_S0B0) |
291 gpio_get_value(IOT_GATE_IMX8_GPIO_S0B1) << 1 |
292 gpio_get_value(IOT_GATE_IMX8_GPIO_S0B2) << 2;
293 iot_gate_imx8_ext_ied_id[0] = revision;
294
295 /* Get slot 1 card ID */
296 revision = gpio_get_value(IOT_GATE_IMX8_GPIO_S1B0) |
297 gpio_get_value(IOT_GATE_IMX8_GPIO_S1B1) << 1 |
298 gpio_get_value(IOT_GATE_IMX8_GPIO_S1B2) << 2;
299 iot_gate_imx8_ext_ied_id[1] = revision;
300
301 /* Get slot 2 card ID */
302 revision = gpio_get_value(IOT_GATE_IMX8_GPIO_S2B0) |
303 gpio_get_value(IOT_GATE_IMX8_GPIO_S2B1) << 1 |
304 gpio_get_value(IOT_GATE_IMX8_GPIO_S2B2) << 2;
305 iot_gate_imx8_ext_ied_id[2] = revision;
306
307 return 0;
308}
309
310int board_fix_fdt(void *rw_fdt_blob)
311{
312 return 0;
313}
314
315int extension_board_scan(struct list_head *extension_list)
316{
317 struct extension *extension = NULL;
318 int i;
319 int ret = 0;
320
321 iot_gate_imx8_detect_ext(); /* Extended board detection */
322
323 switch(iot_gate_imx8_ext_id) {
324 case IOT_GATE_EXT_EMPTY:
325 break;
326 case IOT_GATE_EXT_CAN:
327 extension = calloc(1, sizeof(struct extension));
328 snprintf(extension->name, sizeof(extension->name),
329 "IOT_GATE_EXT_CAN");
330 break;
331 case IOT_GATE_EXT_IED:
332 extension = calloc(1, sizeof(struct extension));
333 snprintf(extension->name, sizeof(extension->name),
334 "IOT_GATE_EXT_IED");
335 snprintf(extension->overlay, sizeof(extension->overlay),
336 "imx8mm-cl-iot-gate-ied.dtbo");
337 break;
338 case IOT_GATE_EXT_POE:
339 extension = calloc(1, sizeof(struct extension));
340 snprintf(extension->name, sizeof(extension->name),
341 "IOT_GATE_EXT_POE");
342 break;
343 case IOT_GATE_EXT_POEV2:
344 extension = calloc(1, sizeof(struct extension));
345 snprintf(extension->name, sizeof(extension->name),
346 "IOT_GATE_EXT_POEV2");
347 break;
348 default:
349 printf("IOT_GATE-iMX8 extension board: unknown\n");
350 break;
351 }
352
353 if (extension) {
354 snprintf(extension->owner, sizeof(extension->owner),
355 "Compulab");
356 list_add_tail(&extension->list, extension_list);
357 ret = 1;
358 } else
359 return ret;
360
361 iot_gate_imx8_update_pinmux();
362
363 iot_gate_imx8_update_ext_ied();
364 for (i=0; i<ARRAY_SIZE(iot_gate_imx8_ext_ied_id); i++) {
365 extension = NULL;
366 switch (iot_gate_imx8_ext_ied_id[i]) {
367 case IOT_GATE_IMX8_CARD_ID_EMPTY:
368 break;
369 case IOT_GATE_IMX8_CARD_ID_RS_485:
370 extension = calloc(1, sizeof(struct extension));
371 snprintf(extension->name, sizeof(extension->name),
372 "IOT_GATE_IMX8_CARD_ID_RS_485");
373 break;
374 case IOT_GATE_IMX8_CARD_ID_RS_232:
375 extension = calloc(1, sizeof(struct extension));
376 snprintf(extension->name, sizeof(extension->name),
377 "IOT_GATE_IMX8_CARD_ID_RS_232");
378 break;
379 case IOT_GATE_IMX8_CARD_ID_CAN:
380 extension = calloc(1, sizeof(struct extension));
381 snprintf(extension->name, sizeof(extension->name),
382 "IOT_GATE_IMX8_CARD_ID_CAN");
383 snprintf(extension->overlay, sizeof(extension->overlay),
384 "imx8mm-cl-iot-gate-ied-can%d.dtbo", i);
385 break;
386 case IOT_GATE_IMX8_CARD_ID_TPM:
387 extension = calloc(1, sizeof(struct extension));
388 snprintf(extension->name, sizeof(extension->name),
389 "IOT_GATE_IMX8_CARD_ID_TPM");
390 snprintf(extension->overlay, sizeof(extension->overlay),
391 "imx8mm-cl-iot-gate-ied-tpm%d.dtbo", i);
392 break;
393 case IOT_GATE_IMX8_CARD_ID_CL420:
394 extension = calloc(1, sizeof(struct extension));
395 snprintf(extension->name, sizeof(extension->name),
396 "IOT_GATE_IMX8_CARD_ID_CL420");
397 snprintf(extension->overlay, sizeof(extension->overlay),
398 "imx8mm-cl-iot-gate-ied-can%d.dtbo", i);
399 break;
400 case IOT_GATE_IMX8_CARD_ID_DI4O4:
401 extension = calloc(1, sizeof(struct extension));
402 snprintf(extension->name, sizeof(extension->name),
403 "IOT_GATE_IMX8_CARD_ID_DI4O4");
404 break;
405 default:
406 printf("%s: invalid slot %d card ID: %d\n",
407 __func__, i, iot_gate_imx8_ext_ied_id[i]);
408 break;
409 }
410 if (extension) {
411 snprintf(extension->owner, sizeof(extension->owner),
412 "Compulab");
413 snprintf(extension->other, sizeof(extension->other),
414 "On slot %d", i);
415 list_add_tail(&extension->list, extension_list);
416 ret = ret + 1;
417 }
418 }
419
420 return ret;
421}
422
Fabio Estevamf2acfc72022-04-12 13:05:37 -0300423static int setup_mac_address(void)
424{
425 unsigned char enetaddr[6];
426 struct udevice *dev;
427 int ret, off;
428
429 ret = eth_env_get_enetaddr("ethaddr", enetaddr);
430 if (ret)
431 return 0;
432
433 off = fdt_path_offset(gd->fdt_blob, "eeprom1");
434 if (off < 0) {
435 printf("No eeprom0 path offset found in DT\n");
436 return off;
437 }
438
439 ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev);
440 if (ret) {
441 printf("%s: Could not find EEPROM\n", __func__);
442 return ret;
443 }
444
445 ret = i2c_set_chip_offset_len(dev, 1);
446 if (ret)
447 return ret;
448
449 ret = i2c_eeprom_read(dev, 4, enetaddr, sizeof(enetaddr));
450 if (ret) {
451 printf("%s: Could not read EEPROM\n", __func__);
452 return ret;
453 }
454
455 ret = is_valid_ethaddr(enetaddr);
456 if (!ret)
457 return -EINVAL;
458
459 ret = eth_env_set_enetaddr("ethaddr", enetaddr);
460 if (ret)
461 return ret;
462
463 return 0;
464}
465
Fabio Estevam938f70f2022-04-12 13:05:38 -0300466static int read_serial_number(void)
467{
468 unsigned char serialnumber[6];
469 unsigned char reversed[6];
470 char serial_string[12];
471 struct udevice *dev;
472 int ret, off, i;
473
474 off = fdt_path_offset(gd->fdt_blob, "eeprom0");
475 if (off < 0) {
476 printf("No eeprom0 path offset found in DT\n");
477 return off;
478 }
479
480 ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev);
481 if (ret) {
482 printf("%s: Could not find EEPROM\n", __func__);
483 return ret;
484 }
485
486 ret = i2c_set_chip_offset_len(dev, 1);
487 if (ret)
488 return ret;
489
490 ret = i2c_eeprom_read(dev, 0x14, serialnumber, sizeof(serialnumber));
491 if (ret) {
492 printf("%s: Could not read EEPROM\n", __func__);
493 return ret;
494 }
495
496 for (i = sizeof(serialnumber) - 1; i >= 0; i--)
497 reversed[i] = serialnumber[sizeof(serialnumber) - 1 - i];
498
499 for (i = 0; i < sizeof(reversed); i++) {
500 serial_string[i * 2] = (reversed[i] >> 4) & 0xf;
501 serial_string[i * 2 + 1] = reversed[i] & 0xf;
502 }
503
504 for (i = 0; i < sizeof(serial_string); i++)
505 serial_string[i] += '0';
506
507 env_set("serial#", serial_string);
508
509 return 0;
510}
511
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +0800512int board_late_init(void)
513{
Fabio Estevamf2acfc72022-04-12 13:05:37 -0300514 int ret;
515
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +0800516 if (IS_ENABLED(CONFIG_ENV_VARS_UBOOT_RUNTIME_CONFIG)) {
517 env_set("board_name", "IOT-GATE-IMX8");
518 env_set("board_rev", "SBC-IOTMX8");
519 }
520
Fabio Estevamf2acfc72022-04-12 13:05:37 -0300521 ret = setup_mac_address();
522 if (ret < 0)
523 printf("Cannot set MAC address from EEPROM\n");
524
Fabio Estevam938f70f2022-04-12 13:05:38 -0300525 ret = read_serial_number();
526 if (ret < 0)
527 printf("Cannot read serial number from EEPROM\n");
528
Ying-Chun Liu (PaulLiu)a97107f2021-04-22 04:50:31 +0800529 return 0;
530}