xref: /rk3399_rockchip-uboot/board/ti/common/board_detect.c (revision 7774e97aa77c1fc18283a1ee1bfb9bdf7c6a14f2)
10bea813dSLokesh Vutla /*
20bea813dSLokesh Vutla  * Library to support early TI EVM EEPROM handling
30bea813dSLokesh Vutla  *
40bea813dSLokesh Vutla  * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
50bea813dSLokesh Vutla  *	Lokesh Vutla
60bea813dSLokesh Vutla  *	Steve Kipisz
70bea813dSLokesh Vutla  *
80bea813dSLokesh Vutla  * SPDX-License-Identifier:    GPL-2.0+
90bea813dSLokesh Vutla  */
100bea813dSLokesh Vutla 
110bea813dSLokesh Vutla #include <common.h>
120bea813dSLokesh Vutla #include <asm/omap_common.h>
130bea813dSLokesh Vutla #include <i2c.h>
140bea813dSLokesh Vutla 
150bea813dSLokesh Vutla #include "board_detect.h"
160bea813dSLokesh Vutla 
170bea813dSLokesh Vutla /**
180bea813dSLokesh Vutla  * ti_i2c_eeprom_init - Initialize an i2c bus and probe for a device
190bea813dSLokesh Vutla  * @i2c_bus: i2c bus number to initialize
200bea813dSLokesh Vutla  * @dev_addr: Device address to probe for
210bea813dSLokesh Vutla  *
220bea813dSLokesh Vutla  * Return: 0 on success or corresponding error on failure.
230bea813dSLokesh Vutla  */
240bea813dSLokesh Vutla static int __maybe_unused ti_i2c_eeprom_init(int i2c_bus, int dev_addr)
250bea813dSLokesh Vutla {
260bea813dSLokesh Vutla 	int rc;
270bea813dSLokesh Vutla 
280bea813dSLokesh Vutla 	if (i2c_bus >= 0) {
290bea813dSLokesh Vutla 		rc = i2c_set_bus_num(i2c_bus);
300bea813dSLokesh Vutla 		if (rc)
310bea813dSLokesh Vutla 			return rc;
320bea813dSLokesh Vutla 	}
330bea813dSLokesh Vutla 
340bea813dSLokesh Vutla 	return i2c_probe(dev_addr);
350bea813dSLokesh Vutla }
360bea813dSLokesh Vutla 
370bea813dSLokesh Vutla /**
380bea813dSLokesh Vutla  * ti_i2c_eeprom_read - Read data from an EEPROM
390bea813dSLokesh Vutla  * @dev_addr: The device address of the EEPROM
400bea813dSLokesh Vutla  * @offset: Offset to start reading in the EEPROM
410bea813dSLokesh Vutla  * @ep: Pointer to a buffer to read into
420bea813dSLokesh Vutla  * @epsize: Size of buffer
430bea813dSLokesh Vutla  *
440bea813dSLokesh Vutla  * Return: 0 on success or corresponding result of i2c_read
450bea813dSLokesh Vutla  */
460bea813dSLokesh Vutla static int __maybe_unused ti_i2c_eeprom_read(int dev_addr, int offset,
470bea813dSLokesh Vutla 					     uchar *ep, int epsize)
480bea813dSLokesh Vutla {
490bea813dSLokesh Vutla 	return i2c_read(dev_addr, offset, 2, ep, epsize);
500bea813dSLokesh Vutla }
510bea813dSLokesh Vutla 
520bea813dSLokesh Vutla /**
530bea813dSLokesh Vutla  * ti_eeprom_string_cleanup() - Handle eeprom programming errors
540bea813dSLokesh Vutla  * @s:	eeprom string (should be NULL terminated)
550bea813dSLokesh Vutla  *
560bea813dSLokesh Vutla  * Some Board manufacturers do not add a NULL termination at the
570bea813dSLokesh Vutla  * end of string, instead some binary information is kludged in, hence
580bea813dSLokesh Vutla  * convert the string to just printable characters of ASCII chart.
590bea813dSLokesh Vutla  */
600bea813dSLokesh Vutla static void __maybe_unused ti_eeprom_string_cleanup(char *s)
610bea813dSLokesh Vutla {
620bea813dSLokesh Vutla 	int i, l;
630bea813dSLokesh Vutla 
640bea813dSLokesh Vutla 	l = strlen(s);
650bea813dSLokesh Vutla 	for (i = 0; i < l; i++, s++)
660bea813dSLokesh Vutla 		if (*s < ' ' || *s > '~') {
670bea813dSLokesh Vutla 			*s = 0;
680bea813dSLokesh Vutla 			break;
690bea813dSLokesh Vutla 		}
700bea813dSLokesh Vutla }
710bea813dSLokesh Vutla 
720bea813dSLokesh Vutla __weak void gpi2c_init(void)
730bea813dSLokesh Vutla {
740bea813dSLokesh Vutla }
750bea813dSLokesh Vutla 
760bea813dSLokesh Vutla static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr,
770bea813dSLokesh Vutla 					    u32 header, u32 size, uint8_t *ep)
780bea813dSLokesh Vutla {
790bea813dSLokesh Vutla 	u32 byte, hdr_read;
800bea813dSLokesh Vutla 	int rc;
810bea813dSLokesh Vutla 
820bea813dSLokesh Vutla 	gpi2c_init();
830bea813dSLokesh Vutla 	rc = ti_i2c_eeprom_init(bus_addr, dev_addr);
840bea813dSLokesh Vutla 	if (rc)
850bea813dSLokesh Vutla 		return rc;
860bea813dSLokesh Vutla 
870bea813dSLokesh Vutla 	/*
880bea813dSLokesh Vutla 	 * Read the header first then only read the other contents.
890bea813dSLokesh Vutla 	 */
900bea813dSLokesh Vutla 	byte = 2;
910bea813dSLokesh Vutla 	rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
920bea813dSLokesh Vutla 	if (rc)
930bea813dSLokesh Vutla 		return rc;
940bea813dSLokesh Vutla 
950bea813dSLokesh Vutla 	/* Corrupted data??? */
960bea813dSLokesh Vutla 	if (hdr_read != header) {
970bea813dSLokesh Vutla 		rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
980bea813dSLokesh Vutla 		/*
990bea813dSLokesh Vutla 		 * read the eeprom header using i2c again, but use only a
1000bea813dSLokesh Vutla 		 * 1 byte address (some legacy boards need this..)
1010bea813dSLokesh Vutla 		 */
1020bea813dSLokesh Vutla 		byte = 1;
1030bea813dSLokesh Vutla 		if (rc)
1040bea813dSLokesh Vutla 			rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read,
1050bea813dSLokesh Vutla 				      4);
1060bea813dSLokesh Vutla 		if (rc)
1070bea813dSLokesh Vutla 			return rc;
1080bea813dSLokesh Vutla 	}
1090bea813dSLokesh Vutla 	if (hdr_read != header)
1100bea813dSLokesh Vutla 		return -1;
1110bea813dSLokesh Vutla 
1120bea813dSLokesh Vutla 	rc = i2c_read(dev_addr, 0x0, byte, ep, size);
1130bea813dSLokesh Vutla 	if (rc)
1140bea813dSLokesh Vutla 		return rc;
1150bea813dSLokesh Vutla 
1160bea813dSLokesh Vutla 	return 0;
1170bea813dSLokesh Vutla }
1180bea813dSLokesh Vutla 
1190bea813dSLokesh Vutla int __maybe_unused ti_i2c_eeprom_am_get(int bus_addr, int dev_addr)
1200bea813dSLokesh Vutla {
1210bea813dSLokesh Vutla 	int rc;
1220bea813dSLokesh Vutla 	struct ti_am_eeprom am_ep;
1230bea813dSLokesh Vutla 	struct ti_common_eeprom *ep;
1240bea813dSLokesh Vutla 
1250bea813dSLokesh Vutla 	ep = TI_EEPROM_DATA;
1260bea813dSLokesh Vutla 	if (ep->header == TI_EEPROM_HEADER_MAGIC)
1270bea813dSLokesh Vutla 		goto already_read;
1280bea813dSLokesh Vutla 
1290bea813dSLokesh Vutla 	/* Initialize with a known bad marker for i2c fails.. */
1300bea813dSLokesh Vutla 	ep->header = TI_DEAD_EEPROM_MAGIC;
1310bea813dSLokesh Vutla 	ep->name[0] = 0x0;
1320bea813dSLokesh Vutla 	ep->version[0] = 0x0;
1330bea813dSLokesh Vutla 	ep->serial[0] = 0x0;
1342a78c9e7SNishanth Menon 	ep->config[0] = 0x0;
1350bea813dSLokesh Vutla 
1360bea813dSLokesh Vutla 	rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
1370bea813dSLokesh Vutla 			       sizeof(am_ep), (uint8_t *)&am_ep);
1380bea813dSLokesh Vutla 	if (rc)
1390bea813dSLokesh Vutla 		return rc;
1400bea813dSLokesh Vutla 
1410bea813dSLokesh Vutla 	ep->header = am_ep.header;
1420bea813dSLokesh Vutla 	strlcpy(ep->name, am_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
1430bea813dSLokesh Vutla 	ti_eeprom_string_cleanup(ep->name);
1440bea813dSLokesh Vutla 
1450bea813dSLokesh Vutla 	/* BeagleBone Green '1' eeprom, board_rev: 0x1a 0x00 0x00 0x00 */
1460bea813dSLokesh Vutla 	if (am_ep.version[0] == 0x1a && am_ep.version[1] == 0x00 &&
1470bea813dSLokesh Vutla 	    am_ep.version[2] == 0x00 && am_ep.version[3] == 0x00)
1480bea813dSLokesh Vutla 		strlcpy(ep->version, "BBG1", TI_EEPROM_HDR_REV_LEN + 1);
1490bea813dSLokesh Vutla 	else
1500bea813dSLokesh Vutla 		strlcpy(ep->version, am_ep.version, TI_EEPROM_HDR_REV_LEN + 1);
1510bea813dSLokesh Vutla 	ti_eeprom_string_cleanup(ep->version);
1520bea813dSLokesh Vutla 	strlcpy(ep->serial, am_ep.serial, TI_EEPROM_HDR_SERIAL_LEN + 1);
1530bea813dSLokesh Vutla 	ti_eeprom_string_cleanup(ep->serial);
1540bea813dSLokesh Vutla 	strlcpy(ep->config, am_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
1550bea813dSLokesh Vutla 	ti_eeprom_string_cleanup(ep->config);
1560bea813dSLokesh Vutla 
1570bea813dSLokesh Vutla 	memcpy(ep->mac_addr, am_ep.mac_addr,
1580bea813dSLokesh Vutla 	       TI_EEPROM_HDR_NO_OF_MAC_ADDR * TI_EEPROM_HDR_ETH_ALEN);
1590bea813dSLokesh Vutla 
1600bea813dSLokesh Vutla already_read:
1610bea813dSLokesh Vutla 	return 0;
1620bea813dSLokesh Vutla }
1630bea813dSLokesh Vutla 
164d3b98a9eSLokesh Vutla int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr)
165d3b98a9eSLokesh Vutla {
166d3b98a9eSLokesh Vutla 	int rc, offset = 0;
167d3b98a9eSLokesh Vutla 	struct dra7_eeprom dra7_ep;
168d3b98a9eSLokesh Vutla 	struct ti_common_eeprom *ep;
169d3b98a9eSLokesh Vutla 
170d3b98a9eSLokesh Vutla 	ep = TI_EEPROM_DATA;
171d3b98a9eSLokesh Vutla 	if (ep->header == DRA7_EEPROM_HEADER_MAGIC)
172d3b98a9eSLokesh Vutla 		goto already_read;
173d3b98a9eSLokesh Vutla 
174d3b98a9eSLokesh Vutla 	/* Initialize with a known bad marker for i2c fails.. */
17528d624beSNishanth Menon 	ep->header = TI_DEAD_EEPROM_MAGIC;
176d3b98a9eSLokesh Vutla 	ep->name[0] = 0x0;
177d3b98a9eSLokesh Vutla 	ep->version[0] = 0x0;
178d3b98a9eSLokesh Vutla 	ep->serial[0] = 0x0;
1792a78c9e7SNishanth Menon 	ep->config[0] = 0x0;
180d3b98a9eSLokesh Vutla 	ep->emif1_size = 0;
181d3b98a9eSLokesh Vutla 	ep->emif2_size = 0;
182d3b98a9eSLokesh Vutla 
183d3b98a9eSLokesh Vutla 	rc = ti_i2c_eeprom_get(bus_addr, dev_addr, DRA7_EEPROM_HEADER_MAGIC,
184d3b98a9eSLokesh Vutla 			       sizeof(dra7_ep), (uint8_t *)&dra7_ep);
185d3b98a9eSLokesh Vutla 	if (rc)
186d3b98a9eSLokesh Vutla 		return rc;
187d3b98a9eSLokesh Vutla 
188d3b98a9eSLokesh Vutla 	ep->header = dra7_ep.header;
189d3b98a9eSLokesh Vutla 	strlcpy(ep->name, dra7_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
190d3b98a9eSLokesh Vutla 	ti_eeprom_string_cleanup(ep->name);
191d3b98a9eSLokesh Vutla 
192d3b98a9eSLokesh Vutla 	offset = dra7_ep.version_major - 1;
193d3b98a9eSLokesh Vutla 
194d3b98a9eSLokesh Vutla 	/* Rev F is skipped */
195d3b98a9eSLokesh Vutla 	if (offset >= 5)
196d3b98a9eSLokesh Vutla 		offset = offset + 1;
197d3b98a9eSLokesh Vutla 	snprintf(ep->version, TI_EEPROM_HDR_REV_LEN + 1, "%c.%d",
198d3b98a9eSLokesh Vutla 		 'A' + offset, dra7_ep.version_minor);
199d3b98a9eSLokesh Vutla 	ti_eeprom_string_cleanup(ep->version);
200d3b98a9eSLokesh Vutla 	ep->emif1_size = (u64)dra7_ep.emif1_size;
201d3b98a9eSLokesh Vutla 	ep->emif2_size = (u64)dra7_ep.emif2_size;
202d3b98a9eSLokesh Vutla 	strlcpy(ep->config, dra7_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
203d3b98a9eSLokesh Vutla 	ti_eeprom_string_cleanup(ep->config);
204d3b98a9eSLokesh Vutla 
205d3b98a9eSLokesh Vutla already_read:
206d3b98a9eSLokesh Vutla 	return 0;
207d3b98a9eSLokesh Vutla }
208d3b98a9eSLokesh Vutla 
2090bea813dSLokesh Vutla bool __maybe_unused board_ti_is(char *name_tag)
2100bea813dSLokesh Vutla {
2110bea813dSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
2120bea813dSLokesh Vutla 
2130bea813dSLokesh Vutla 	if (ep->header == TI_DEAD_EEPROM_MAGIC)
2140bea813dSLokesh Vutla 		return false;
2150bea813dSLokesh Vutla 	return !strncmp(ep->name, name_tag, TI_EEPROM_HDR_NAME_LEN);
2160bea813dSLokesh Vutla }
2170bea813dSLokesh Vutla 
2180bea813dSLokesh Vutla bool __maybe_unused board_ti_rev_is(char *rev_tag, int cmp_len)
2190bea813dSLokesh Vutla {
2200bea813dSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
2210bea813dSLokesh Vutla 	int l;
2220bea813dSLokesh Vutla 
2230bea813dSLokesh Vutla 	if (ep->header == TI_DEAD_EEPROM_MAGIC)
2240bea813dSLokesh Vutla 		return false;
2250bea813dSLokesh Vutla 
2260bea813dSLokesh Vutla 	l = cmp_len > TI_EEPROM_HDR_REV_LEN ? TI_EEPROM_HDR_REV_LEN : cmp_len;
2270bea813dSLokesh Vutla 	return !strncmp(ep->version, rev_tag, l);
2280bea813dSLokesh Vutla }
2290bea813dSLokesh Vutla 
2300bea813dSLokesh Vutla char * __maybe_unused board_ti_get_rev(void)
2310bea813dSLokesh Vutla {
2320bea813dSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
2330bea813dSLokesh Vutla 
234*7774e97aSNishanth Menon 	/* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
2350bea813dSLokesh Vutla 	return ep->version;
2360bea813dSLokesh Vutla }
2370bea813dSLokesh Vutla 
2380bea813dSLokesh Vutla char * __maybe_unused board_ti_get_config(void)
2390bea813dSLokesh Vutla {
2400bea813dSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
2410bea813dSLokesh Vutla 
242*7774e97aSNishanth Menon 	/* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
2430bea813dSLokesh Vutla 	return ep->config;
2440bea813dSLokesh Vutla }
2450bea813dSLokesh Vutla 
2460bea813dSLokesh Vutla char * __maybe_unused board_ti_get_name(void)
2470bea813dSLokesh Vutla {
2480bea813dSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
2490bea813dSLokesh Vutla 
250*7774e97aSNishanth Menon 	/* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
2510bea813dSLokesh Vutla 	return ep->name;
2520bea813dSLokesh Vutla }
2530bea813dSLokesh Vutla 
2540bea813dSLokesh Vutla void __maybe_unused
2550bea813dSLokesh Vutla board_ti_get_eth_mac_addr(int index,
2560bea813dSLokesh Vutla 			  u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
2570bea813dSLokesh Vutla {
2580bea813dSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
2590bea813dSLokesh Vutla 
2600bea813dSLokesh Vutla 	if (ep->header == TI_DEAD_EEPROM_MAGIC)
2610bea813dSLokesh Vutla 		goto fail;
2620bea813dSLokesh Vutla 
2630bea813dSLokesh Vutla 	if (index < 0 || index >= TI_EEPROM_HDR_NO_OF_MAC_ADDR)
2640bea813dSLokesh Vutla 		goto fail;
2650bea813dSLokesh Vutla 
2660bea813dSLokesh Vutla 	memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
2670bea813dSLokesh Vutla 	return;
2680bea813dSLokesh Vutla 
2690bea813dSLokesh Vutla fail:
2700bea813dSLokesh Vutla 	memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
2710bea813dSLokesh Vutla }
2720bea813dSLokesh Vutla 
273d3b98a9eSLokesh Vutla u64 __maybe_unused board_ti_get_emif1_size(void)
274d3b98a9eSLokesh Vutla {
275d3b98a9eSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
276d3b98a9eSLokesh Vutla 
277d3b98a9eSLokesh Vutla 	if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
278d3b98a9eSLokesh Vutla 		return 0;
279d3b98a9eSLokesh Vutla 
280d3b98a9eSLokesh Vutla 	return ep->emif1_size;
281d3b98a9eSLokesh Vutla }
282d3b98a9eSLokesh Vutla 
283d3b98a9eSLokesh Vutla u64 __maybe_unused board_ti_get_emif2_size(void)
284d3b98a9eSLokesh Vutla {
285d3b98a9eSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
286d3b98a9eSLokesh Vutla 
287d3b98a9eSLokesh Vutla 	if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
288d3b98a9eSLokesh Vutla 		return 0;
289d3b98a9eSLokesh Vutla 
290d3b98a9eSLokesh Vutla 	return ep->emif2_size;
291d3b98a9eSLokesh Vutla }
292d3b98a9eSLokesh Vutla 
2930bea813dSLokesh Vutla void __maybe_unused set_board_info_env(char *name)
2940bea813dSLokesh Vutla {
2950bea813dSLokesh Vutla 	char *unknown = "unknown";
2960bea813dSLokesh Vutla 	struct ti_common_eeprom *ep = TI_EEPROM_DATA;
2970bea813dSLokesh Vutla 
2980bea813dSLokesh Vutla 	if (name)
2990bea813dSLokesh Vutla 		setenv("board_name", name);
3000bea813dSLokesh Vutla 	else if (ep->name)
3010bea813dSLokesh Vutla 		setenv("board_name", ep->name);
3020bea813dSLokesh Vutla 	else
3030bea813dSLokesh Vutla 		setenv("board_name", unknown);
3040bea813dSLokesh Vutla 
3050bea813dSLokesh Vutla 	if (ep->version)
3060bea813dSLokesh Vutla 		setenv("board_rev", ep->version);
3070bea813dSLokesh Vutla 	else
3080bea813dSLokesh Vutla 		setenv("board_rev", unknown);
3090bea813dSLokesh Vutla 
3100bea813dSLokesh Vutla 	if (ep->serial)
3110bea813dSLokesh Vutla 		setenv("board_serial", ep->serial);
3120bea813dSLokesh Vutla 	else
3130bea813dSLokesh Vutla 		setenv("board_serial", unknown);
3140bea813dSLokesh Vutla }
315