xref: /rk3399_rockchip-uboot/board/corscience/tricorder/tricorder-eeprom.c (revision 63a7578e4e7dc906e75b0bec5a2f3fe41c3720f4)
1459f1da8SAndreas Bießmann /*
2459f1da8SAndreas Bießmann  * (C) Copyright 2013
3459f1da8SAndreas Bießmann  * Corscience GmbH & Co. KG, <www.corscience.de>
4459f1da8SAndreas Bießmann  * Andreas Bießmann <andreas.biessmann@corscience.de>
5459f1da8SAndreas Bießmann  *
6459f1da8SAndreas Bießmann  * SPDX-License-Identifier:	GPL-2.0+
7459f1da8SAndreas Bießmann  */
8459f1da8SAndreas Bießmann #include <common.h>
9459f1da8SAndreas Bießmann #include <i2c.h>
10459f1da8SAndreas Bießmann 
11459f1da8SAndreas Bießmann #include "tricorder-eeprom.h"
12459f1da8SAndreas Bießmann 
warn_wrong_value(const char * msg,unsigned int a,unsigned int b)13459f1da8SAndreas Bießmann static inline void warn_wrong_value(const char *msg, unsigned int a,
14459f1da8SAndreas Bießmann 		unsigned int b)
15459f1da8SAndreas Bießmann {
16459f1da8SAndreas Bießmann 	printf("Expected EEPROM %s %08x, got %08x\n", msg, a, b);
17459f1da8SAndreas Bießmann }
18459f1da8SAndreas Bießmann 
handle_eeprom_v0(struct tricorder_eeprom * eeprom)19459f1da8SAndreas Bießmann static int handle_eeprom_v0(struct tricorder_eeprom *eeprom)
20459f1da8SAndreas Bießmann {
21459f1da8SAndreas Bießmann 	struct tricorder_eeprom_v0 {
22459f1da8SAndreas Bießmann 		uint32_t magic;
23459f1da8SAndreas Bießmann 		uint16_t length;
24459f1da8SAndreas Bießmann 		uint16_t version;
25459f1da8SAndreas Bießmann 		char board_name[TRICORDER_BOARD_NAME_LENGTH];
26459f1da8SAndreas Bießmann 		char board_version[TRICORDER_BOARD_VERSION_LENGTH];
27459f1da8SAndreas Bießmann 		char board_serial[TRICORDER_BOARD_SERIAL_LENGTH];
28459f1da8SAndreas Bießmann 		uint32_t crc32;
29459f1da8SAndreas Bießmann 	} __packed eepromv0;
30459f1da8SAndreas Bießmann 	uint32_t crc;
31459f1da8SAndreas Bießmann 
32459f1da8SAndreas Bießmann 	printf("Old EEPROM (v0), consider rewrite!\n");
33459f1da8SAndreas Bießmann 
34459f1da8SAndreas Bießmann 	if (be16_to_cpu(eeprom->length) != sizeof(eepromv0)) {
35459f1da8SAndreas Bießmann 		warn_wrong_value("length", sizeof(eepromv0),
36459f1da8SAndreas Bießmann 				 be16_to_cpu(eeprom->length));
37459f1da8SAndreas Bießmann 		return 1;
38459f1da8SAndreas Bießmann 	}
39459f1da8SAndreas Bießmann 
40459f1da8SAndreas Bießmann 	memcpy(&eepromv0, eeprom, sizeof(eepromv0));
41459f1da8SAndreas Bießmann 
42459f1da8SAndreas Bießmann 	crc = crc32(0L, (unsigned char *)&eepromv0,
43459f1da8SAndreas Bießmann 		    sizeof(eepromv0) - sizeof(eepromv0.crc32));
44459f1da8SAndreas Bießmann 	if (be32_to_cpu(eepromv0.crc32) != crc) {
45459f1da8SAndreas Bießmann 		warn_wrong_value("CRC", be32_to_cpu(eepromv0.crc32),
46459f1da8SAndreas Bießmann 				 crc);
47459f1da8SAndreas Bießmann 		return 1;
48459f1da8SAndreas Bießmann 	}
49459f1da8SAndreas Bießmann 
50459f1da8SAndreas Bießmann 	/* Ok the content is correct, do the conversion */
51459f1da8SAndreas Bießmann 	memset(eeprom->interface_version, 0x0,
52459f1da8SAndreas Bießmann 	       TRICORDER_INTERFACE_VERSION_LENGTH);
53459f1da8SAndreas Bießmann 	crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
54459f1da8SAndreas Bießmann 	eeprom->crc32 = cpu_to_be32(crc);
55459f1da8SAndreas Bießmann 
56459f1da8SAndreas Bießmann 	return 0;
57459f1da8SAndreas Bießmann }
58459f1da8SAndreas Bießmann 
handle_eeprom_v1(struct tricorder_eeprom * eeprom)59459f1da8SAndreas Bießmann static int handle_eeprom_v1(struct tricorder_eeprom *eeprom)
60459f1da8SAndreas Bießmann {
61459f1da8SAndreas Bießmann 	uint32_t crc;
62459f1da8SAndreas Bießmann 
63459f1da8SAndreas Bießmann 	if (be16_to_cpu(eeprom->length) != TRICORDER_EEPROM_SIZE) {
64459f1da8SAndreas Bießmann 		warn_wrong_value("length", TRICORDER_EEPROM_SIZE,
65459f1da8SAndreas Bießmann 				 be16_to_cpu(eeprom->length));
66459f1da8SAndreas Bießmann 		return 1;
67459f1da8SAndreas Bießmann 	}
68459f1da8SAndreas Bießmann 
69459f1da8SAndreas Bießmann 	crc = crc32(0L, (unsigned char *)eeprom, TRICORDER_EEPROM_CRC_SIZE);
70459f1da8SAndreas Bießmann 	if (be32_to_cpu(eeprom->crc32) != crc) {
71459f1da8SAndreas Bießmann 		warn_wrong_value("CRC", be32_to_cpu(eeprom->crc32), crc);
72459f1da8SAndreas Bießmann 		return 1;
73459f1da8SAndreas Bießmann 	}
74459f1da8SAndreas Bießmann 
75459f1da8SAndreas Bießmann 	return 0;
76459f1da8SAndreas Bießmann }
77459f1da8SAndreas Bießmann 
tricorder_get_eeprom(int addr,struct tricorder_eeprom * eeprom)78459f1da8SAndreas Bießmann int tricorder_get_eeprom(int addr, struct tricorder_eeprom *eeprom)
79459f1da8SAndreas Bießmann {
80459f1da8SAndreas Bießmann 	unsigned int bus = i2c_get_bus_num();
81459f1da8SAndreas Bießmann 	i2c_set_bus_num(CONFIG_SYS_EEPROM_BUS_NUM);
82459f1da8SAndreas Bießmann 
83459f1da8SAndreas Bießmann 	memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
84459f1da8SAndreas Bießmann 
85459f1da8SAndreas Bießmann 	i2c_read(addr, 0, 2, (unsigned char *)eeprom, TRICORDER_EEPROM_SIZE);
86459f1da8SAndreas Bießmann 	i2c_set_bus_num(bus);
87459f1da8SAndreas Bießmann 
88459f1da8SAndreas Bießmann 	if (be32_to_cpu(eeprom->magic) != TRICORDER_EEPROM_MAGIC) {
89459f1da8SAndreas Bießmann 		warn_wrong_value("magic", TRICORDER_EEPROM_MAGIC,
90459f1da8SAndreas Bießmann 				 be32_to_cpu(eeprom->magic));
91459f1da8SAndreas Bießmann 		return 1;
92459f1da8SAndreas Bießmann 	}
93459f1da8SAndreas Bießmann 
94459f1da8SAndreas Bießmann 	switch (be16_to_cpu(eeprom->version)) {
95459f1da8SAndreas Bießmann 	case 0:
96459f1da8SAndreas Bießmann 		return handle_eeprom_v0(eeprom);
97459f1da8SAndreas Bießmann 	case 1:
98459f1da8SAndreas Bießmann 		return handle_eeprom_v1(eeprom);
99459f1da8SAndreas Bießmann 	default:
100459f1da8SAndreas Bießmann 		warn_wrong_value("version", TRICORDER_EEPROM_VERSION,
101459f1da8SAndreas Bießmann 				 be16_to_cpu(eeprom->version));
102459f1da8SAndreas Bießmann 		return 1;
103459f1da8SAndreas Bießmann 	}
104459f1da8SAndreas Bießmann }
105459f1da8SAndreas Bießmann 
106459f1da8SAndreas Bießmann #if !defined(CONFIG_SPL)
tricorder_eeprom_read(unsigned devaddr)107459f1da8SAndreas Bießmann int tricorder_eeprom_read(unsigned devaddr)
108459f1da8SAndreas Bießmann {
109459f1da8SAndreas Bießmann 	struct tricorder_eeprom eeprom;
110459f1da8SAndreas Bießmann 	int ret = tricorder_get_eeprom(devaddr, &eeprom);
111459f1da8SAndreas Bießmann 
112459f1da8SAndreas Bießmann 	if (ret)
113459f1da8SAndreas Bießmann 		return ret;
114459f1da8SAndreas Bießmann 
115459f1da8SAndreas Bießmann 	printf("Board type:               %.*s\n",
116459f1da8SAndreas Bießmann 	       sizeof(eeprom.board_name), eeprom.board_name);
117459f1da8SAndreas Bießmann 	printf("Board version:            %.*s\n",
118459f1da8SAndreas Bießmann 	       sizeof(eeprom.board_version), eeprom.board_version);
119459f1da8SAndreas Bießmann 	printf("Board serial:             %.*s\n",
120459f1da8SAndreas Bießmann 	       sizeof(eeprom.board_serial), eeprom.board_serial);
121459f1da8SAndreas Bießmann 	printf("Board interface version:  %.*s\n",
122459f1da8SAndreas Bießmann 	       sizeof(eeprom.interface_version),
123459f1da8SAndreas Bießmann 	       eeprom.interface_version);
124459f1da8SAndreas Bießmann 
125459f1da8SAndreas Bießmann 	return ret;
126459f1da8SAndreas Bießmann }
127459f1da8SAndreas Bießmann 
tricorder_eeprom_write(unsigned devaddr,const char * name,const char * version,const char * serial,const char * interface)128459f1da8SAndreas Bießmann int tricorder_eeprom_write(unsigned devaddr, const char *name,
129459f1da8SAndreas Bießmann 		const char *version, const char *serial, const char *interface)
130459f1da8SAndreas Bießmann {
131459f1da8SAndreas Bießmann 	struct tricorder_eeprom eeprom, eeprom_verify;
132459f1da8SAndreas Bießmann 	size_t length;
133459f1da8SAndreas Bießmann 	uint32_t crc;
134459f1da8SAndreas Bießmann 	int ret;
135459f1da8SAndreas Bießmann 	unsigned char *p;
136459f1da8SAndreas Bießmann 	int i;
137459f1da8SAndreas Bießmann 
138459f1da8SAndreas Bießmann 	memset(eeprom, 0, TRICORDER_EEPROM_SIZE);
139459f1da8SAndreas Bießmann 	memset(eeprom_verify, 0, TRICORDER_EEPROM_SIZE);
140459f1da8SAndreas Bießmann 
141459f1da8SAndreas Bießmann 	eeprom.magic = cpu_to_be32(TRICORDER_EEPROM_MAGIC);
142459f1da8SAndreas Bießmann 	eeprom.length = cpu_to_be16(TRICORDER_EEPROM_SIZE);
143459f1da8SAndreas Bießmann 	eeprom.version = cpu_to_be16(TRICORDER_EEPROM_VERSION);
144459f1da8SAndreas Bießmann 
145459f1da8SAndreas Bießmann 	length = min(sizeof(eeprom.board_name), strlen(name));
146459f1da8SAndreas Bießmann 	strncpy(eeprom.board_name, name, length);
147459f1da8SAndreas Bießmann 
148459f1da8SAndreas Bießmann 	length = min(sizeof(eeprom.board_version), strlen(version));
149459f1da8SAndreas Bießmann 	strncpy(eeprom.board_version, version, length);
150459f1da8SAndreas Bießmann 
151459f1da8SAndreas Bießmann 	length = min(sizeof(eeprom.board_serial), strlen(serial));
152459f1da8SAndreas Bießmann 	strncpy(eeprom.board_serial, serial, length);
153459f1da8SAndreas Bießmann 
154459f1da8SAndreas Bießmann 	if (interface) {
155459f1da8SAndreas Bießmann 		length = min(sizeof(eeprom.interface_version),
156459f1da8SAndreas Bießmann 				strlen(interface));
157459f1da8SAndreas Bießmann 		strncpy(eeprom.interface_version, interface, length);
158459f1da8SAndreas Bießmann 	}
159459f1da8SAndreas Bießmann 
160459f1da8SAndreas Bießmann 	crc = crc32(0L, (unsigned char *)&eeprom, TRICORDER_EEPROM_CRC_SIZE);
161459f1da8SAndreas Bießmann 	eeprom.crc32 = cpu_to_be32(crc);
162459f1da8SAndreas Bießmann 
163459f1da8SAndreas Bießmann #if defined(DEBUG)
164459f1da8SAndreas Bießmann 	puts("Tricorder EEPROM content:\n");
165459f1da8SAndreas Bießmann 	print_buffer(0, &eeprom, 1, sizeof(eeprom), 16);
166459f1da8SAndreas Bießmann #endif
167459f1da8SAndreas Bießmann 
1688961dac9SAndreas Bießmann 	eeprom_init(CONFIG_SYS_EEPROM_BUS_NUM);
169459f1da8SAndreas Bießmann 
1708961dac9SAndreas Bießmann 	ret = eeprom_write(devaddr, 0, (unsigned char *)&eeprom,
171459f1da8SAndreas Bießmann 			TRICORDER_EEPROM_SIZE);
1728961dac9SAndreas Bießmann 	if (ret)
1738961dac9SAndreas Bießmann 		printf("Tricorder: Could not write EEPROM content!\n");
1748961dac9SAndreas Bießmann 
1758961dac9SAndreas Bießmann 	ret = eeprom_read(devaddr, 0, (unsigned char *)&eeprom_verify,
1768961dac9SAndreas Bießmann 			TRICORDER_EEPROM_SIZE);
1778961dac9SAndreas Bießmann 	if (ret)
1788961dac9SAndreas Bießmann 		printf("Tricorder: Could not read EEPROM content!\n");
179459f1da8SAndreas Bießmann 
180459f1da8SAndreas Bießmann 	if (memcmp(&eeprom, &eeprom_verify, sizeof(eeprom)) != 0) {
181459f1da8SAndreas Bießmann 		printf("Tricorder: Could not verify EEPROM content!\n");
182459f1da8SAndreas Bießmann 		ret = 1;
183459f1da8SAndreas Bießmann 	}
184459f1da8SAndreas Bießmann 
185459f1da8SAndreas Bießmann 	return ret;
186459f1da8SAndreas Bießmann }
187459f1da8SAndreas Bießmann 
do_tricorder_eeprom(cmd_tbl_t * cmdtp,int flag,int argc,char * argv[])188459f1da8SAndreas Bießmann int do_tricorder_eeprom(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
189459f1da8SAndreas Bießmann {
190459f1da8SAndreas Bießmann 	if (argc == 3) {
191459f1da8SAndreas Bießmann 		ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
1928961dac9SAndreas Bießmann 
193*63a7578eSMasahiro Yamada 		if (strcmp(argv[1], "read") == 0)
194*63a7578eSMasahiro Yamada 			return tricorder_eeprom_read(dev_addr);
195459f1da8SAndreas Bießmann 	} else if (argc == 6 || argc == 7) {
196459f1da8SAndreas Bießmann 		ulong dev_addr = simple_strtoul(argv[2], NULL, 16);
197459f1da8SAndreas Bießmann 		char *name = argv[3];
198459f1da8SAndreas Bießmann 		char *version = argv[4];
199459f1da8SAndreas Bießmann 		char *serial = argv[5];
200459f1da8SAndreas Bießmann 		char *interface = NULL;
201459f1da8SAndreas Bießmann 
202459f1da8SAndreas Bießmann 		if (argc == 7)
203459f1da8SAndreas Bießmann 			interface = argv[6];
204459f1da8SAndreas Bießmann 
205*63a7578eSMasahiro Yamada 		if (strcmp(argv[1], "write") == 0)
206*63a7578eSMasahiro Yamada 			return tricorder_eeprom_write(dev_addr, name, version,
207459f1da8SAndreas Bießmann 						      serial, interface);
208459f1da8SAndreas Bießmann 	}
209459f1da8SAndreas Bießmann 
210459f1da8SAndreas Bießmann 	return CMD_RET_USAGE;
211459f1da8SAndreas Bießmann }
212459f1da8SAndreas Bießmann 
213459f1da8SAndreas Bießmann U_BOOT_CMD(
214459f1da8SAndreas Bießmann 	tricordereeprom,	7,	1,	do_tricorder_eeprom,
215459f1da8SAndreas Bießmann 	"Tricorder EEPROM",
216459f1da8SAndreas Bießmann 	"read  devaddr\n"
217459f1da8SAndreas Bießmann 	"       - read Tricorder EEPROM at devaddr and print content\n"
218459f1da8SAndreas Bießmann 	"tricordereeprom write devaddr name version serial [interface]\n"
219459f1da8SAndreas Bießmann 	"       - write Tricorder EEPROM at devaddr with 'name', 'version'"
220459f1da8SAndreas Bießmann 	"and 'serial'\n"
221459f1da8SAndreas Bießmann 	"         optional add an HW interface parameter"
222459f1da8SAndreas Bießmann );
223459f1da8SAndreas Bießmann #endif /* CONFIG_SPL */
224