1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2017 PHYTEC Messtechnik GmbH
4  * Author: Wadim Egorov <w.egorov@phytec.de>
5  */
6 
7 #include <asm/io.h>
8 #include <common.h>
9 #include <dm.h>
10 #include <environment.h>
11 #include <i2c.h>
12 #include <i2c_eeprom.h>
13 #include <netdev.h>
14 #include "som.h"
15 
valid_rk3288_som(struct rk3288_som * som)16 static int valid_rk3288_som(struct rk3288_som *som)
17 {
18 	unsigned char *p = (unsigned char *)som;
19 	unsigned char *e = p + sizeof(struct rk3288_som) - 1;
20 	int hw = 0;
21 
22 	while (p < e) {
23 		hw += hweight8(*p);
24 		p++;
25 	}
26 
27 	return hw == som->bs;
28 }
29 
rk_board_late_init(void)30 int rk_board_late_init(void)
31 {
32 	int ret;
33 	struct udevice *dev;
34 	struct rk3288_som opt;
35 	int off;
36 
37 	/* Get the identificatioin page of M24C32-D EEPROM */
38 	off = fdt_path_offset(gd->fdt_blob, "eeprom0");
39 	if (off < 0) {
40 		printf("%s: No eeprom0 path offset\n", __func__);
41 		return off;
42 	}
43 
44 	ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev);
45 	if (ret) {
46 		printf("%s: Could not find EEPROM\n", __func__);
47 		return ret;
48 	}
49 
50 	ret = i2c_set_chip_offset_len(dev, 2);
51 	if (ret)
52 		return ret;
53 
54 	ret = i2c_eeprom_read(dev, 0, (uint8_t *)&opt,
55 				sizeof(struct rk3288_som));
56 	if (ret) {
57 		printf("%s: Could not read EEPROM\n", __func__);
58 		return ret;
59 	}
60 
61 	if (opt.api_version != 0 || !valid_rk3288_som(&opt)) {
62 		printf("Invalid data or wrong EEPROM layout version.\n");
63 		/* Proceed anyway, since there is no fallback option */
64 	}
65 
66 	if (is_valid_ethaddr(opt.mac))
67 		eth_env_set_enetaddr("ethaddr", opt.mac);
68 
69 	return 0;
70 }
71