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 <eeprom.h>
8#include <init.h>
9#include <log.h>
10#include <net.h>
11#include <asm/global_data.h>
12#include <asm/io.h>
13#include <common.h>
14#include <dm.h>
15#include <env.h>
16#include <env_internal.h>
17#include <i2c.h>
18#include <i2c_eeprom.h>
19#include <netdev.h>
20#include <linux/bitops.h>
21#include "som.h"
22
23static int valid_rk3288_som(struct rk3288_som *som)
24{
25	unsigned char *p = (unsigned char *)som;
26	unsigned char *e = p + sizeof(struct rk3288_som) - 1;
27	int hw = 0;
28
29	while (p < e) {
30		hw += hweight8(*p);
31		p++;
32	}
33
34	return hw == som->bs;
35}
36
37int rk3288_board_late_init(void)
38{
39	int ret;
40	struct udevice *dev;
41	struct rk3288_som opt;
42	int off;
43
44	/* Get the identificatioin page of M24C32-D EEPROM */
45	off = fdt_path_offset(gd->fdt_blob, "eeprom0");
46	if (off < 0) {
47		printf("%s: No eeprom0 path offset\n", __func__);
48		return off;
49	}
50
51	ret = uclass_get_device_by_of_offset(UCLASS_I2C_EEPROM, off, &dev);
52	if (ret) {
53		printf("%s: Could not find EEPROM\n", __func__);
54		return ret;
55	}
56
57	ret = i2c_set_chip_offset_len(dev, 2);
58	if (ret)
59		return ret;
60
61	ret = i2c_eeprom_read(dev, 0, (uint8_t *)&opt,
62				sizeof(struct rk3288_som));
63	if (ret) {
64		printf("%s: Could not read EEPROM\n", __func__);
65		return ret;
66	}
67
68	if (opt.api_version != 0 || !valid_rk3288_som(&opt)) {
69		printf("Invalid data or wrong EEPROM layout version.\n");
70		/* Proceed anyway, since there is no fallback option */
71	}
72
73	if (is_valid_ethaddr(opt.mac))
74		eth_env_set_enetaddr("ethaddr", opt.mac);
75
76	return 0;
77}
78