blob: 9a53884c98e071cfad77bc53636d639134b2c6c7 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Lokesh Vutla0bea8132016-02-24 12:30:54 -06002/*
3 * Library to support early TI EVM EEPROM handling
4 *
5 * Copyright (C) 2015-2016 Texas Instruments Incorporated - http://www.ti.com/
6 * Lokesh Vutla
7 * Steve Kipisz
Lokesh Vutla0bea8132016-02-24 12:30:54 -06008 */
9
10#include <common.h>
Simon Glasscb3ef682019-11-14 12:57:50 -070011#include <eeprom.h>
Simon Glassf7ae49f2020-05-10 11:40:05 -060012#include <log.h>
Simon Glass90526e92020-05-10 11:39:56 -060013#include <net.h>
Andreas Dannenberg361a5332019-06-04 18:08:24 -050014#include <asm/arch/hardware.h>
Lokesh Vutla0bea8132016-02-24 12:30:54 -060015#include <asm/omap_common.h>
Cooper Jr., Franklinc6b80b12017-04-20 10:25:44 -050016#include <dm/uclass.h>
Simon Glass9fb625c2019-08-01 09:46:51 -060017#include <env.h>
Lokesh Vutla0bea8132016-02-24 12:30:54 -060018#include <i2c.h>
Caleb Robeyd6eaaae2020-01-02 08:17:25 -060019#include <mmc.h>
20#include <errno.h>
21#include <malloc.h>
Lokesh Vutla0bea8132016-02-24 12:30:54 -060022
23#include "board_detect.h"
24
Igor Opaniuk2147a162021-02-09 13:52:45 +020025#if !CONFIG_IS_ENABLED(DM_I2C)
Lokesh Vutla0bea8132016-02-24 12:30:54 -060026/**
27 * ti_i2c_eeprom_init - Initialize an i2c bus and probe for a device
28 * @i2c_bus: i2c bus number to initialize
29 * @dev_addr: Device address to probe for
30 *
31 * Return: 0 on success or corresponding error on failure.
32 */
33static int __maybe_unused ti_i2c_eeprom_init(int i2c_bus, int dev_addr)
34{
35 int rc;
36
37 if (i2c_bus >= 0) {
38 rc = i2c_set_bus_num(i2c_bus);
39 if (rc)
40 return rc;
41 }
42
43 return i2c_probe(dev_addr);
44}
45
46/**
47 * ti_i2c_eeprom_read - Read data from an EEPROM
48 * @dev_addr: The device address of the EEPROM
49 * @offset: Offset to start reading in the EEPROM
50 * @ep: Pointer to a buffer to read into
51 * @epsize: Size of buffer
52 *
53 * Return: 0 on success or corresponding result of i2c_read
54 */
55static int __maybe_unused ti_i2c_eeprom_read(int dev_addr, int offset,
56 uchar *ep, int epsize)
57{
Jean-Jacques Hiblot15142442018-12-07 14:50:49 +010058 return i2c_read(dev_addr, offset, 2, ep, epsize);
Lokesh Vutla0bea8132016-02-24 12:30:54 -060059}
Andreas Dannenberg2463f672018-12-07 14:50:47 +010060#endif
Lokesh Vutla0bea8132016-02-24 12:30:54 -060061
62/**
63 * ti_eeprom_string_cleanup() - Handle eeprom programming errors
64 * @s: eeprom string (should be NULL terminated)
65 *
66 * Some Board manufacturers do not add a NULL termination at the
67 * end of string, instead some binary information is kludged in, hence
68 * convert the string to just printable characters of ASCII chart.
69 */
70static void __maybe_unused ti_eeprom_string_cleanup(char *s)
71{
72 int i, l;
73
74 l = strlen(s);
75 for (i = 0; i < l; i++, s++)
76 if (*s < ' ' || *s > '~') {
77 *s = 0;
78 break;
79 }
80}
81
82__weak void gpi2c_init(void)
83{
84}
85
86static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr,
87 u32 header, u32 size, uint8_t *ep)
88{
Lokesh Vutla0bea8132016-02-24 12:30:54 -060089 int rc;
Neha Malcom Francis9f393a22022-12-13 11:57:34 +053090 uint8_t offset_test;
91 bool one_byte_addressing = true;
Lokesh Vutla0bea8132016-02-24 12:30:54 -060092
Igor Opaniuk2147a162021-02-09 13:52:45 +020093#if CONFIG_IS_ENABLED(DM_I2C)
Andreas Dannenberg2463f672018-12-07 14:50:47 +010094 struct udevice *dev;
95 struct udevice *bus;
96
97 rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
98 if (rc)
99 return rc;
Andreas Dannenberg499681e2020-01-07 13:15:53 +0530100 rc = dm_i2c_probe(bus, dev_addr, 0, &dev);
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100101 if (rc)
102 return rc;
103
104 /*
105 * Read the header first then only read the other contents.
106 */
Nishanth Menona58147c2022-06-17 13:26:12 -0500107 rc = i2c_set_chip_offset_len(dev, 1);
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100108 if (rc)
109 return rc;
110
Nishanth Menonbc1de482022-06-17 13:26:11 -0500111 /*
112 * Skip checking result here since this could be a valid i2c read fail
Nishanth Menona58147c2022-06-17 13:26:12 -0500113 * on some boards that use 2 byte addressing.
114 * We must allow for fall through to check the data if 2 byte
Nishanth Menonbc1de482022-06-17 13:26:11 -0500115 * addressing works
116 */
Matwey V. Kornilovbf637662022-08-23 19:05:34 +0300117 (void)dm_i2c_read(dev, 0, ep, size);
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100118
Neha Malcom Francis9f393a22022-12-13 11:57:34 +0530119 if (*((u32 *)ep) != header)
120 one_byte_addressing = false;
121
122 /*
123 * Handle case of bad 2 byte eeproms that responds to 1 byte addressing
124 * but gets stuck in const addressing when read requests are performed
125 * on offsets. We perform an offset test to make sure it is not a 2 byte
126 * eeprom that works with 1 byte addressing but just without an offset
127 */
128
129 rc = dm_i2c_read(dev, 0x1, &offset_test, sizeof(offset_test));
130
131 if (*((u32 *)ep) != (header & 0xFF))
132 one_byte_addressing = false;
133
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100134 /* Corrupted data??? */
Neha Malcom Francis9f393a22022-12-13 11:57:34 +0530135 if (!one_byte_addressing) {
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100136 /*
137 * read the eeprom header using i2c again, but use only a
Nishanth Menona58147c2022-06-17 13:26:12 -0500138 * 2 byte address (some newer boards need this..)
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100139 */
Nishanth Menona58147c2022-06-17 13:26:12 -0500140 rc = i2c_set_chip_offset_len(dev, 2);
Michal Simekb892b6d2020-08-27 15:43:48 +0200141 if (rc)
142 return rc;
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100143
Matwey V. Kornilovbf637662022-08-23 19:05:34 +0300144 rc = dm_i2c_read(dev, 0, ep, size);
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100145 if (rc)
146 return rc;
147 }
Matwey V. Kornilovbf637662022-08-23 19:05:34 +0300148 if (*((u32 *)ep) != header)
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100149 return -1;
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100150#else
151 u32 byte;
152
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600153 gpi2c_init();
154 rc = ti_i2c_eeprom_init(bus_addr, dev_addr);
155 if (rc)
156 return rc;
157
158 /*
159 * Read the header first then only read the other contents.
160 */
Nishanth Menona58147c2022-06-17 13:26:12 -0500161 byte = 1;
Cooper Jr., Frankline25ae322017-04-20 10:25:45 -0500162
Nishanth Menonbc1de482022-06-17 13:26:11 -0500163 /*
164 * Skip checking result here since this could be a valid i2c read fail
Nishanth Menona58147c2022-06-17 13:26:12 -0500165 * on some boards that use 2 byte addressing.
166 * We must allow for fall through to check the data if 2 byte
Nishanth Menonbc1de482022-06-17 13:26:11 -0500167 * addressing works
168 */
Matwey V. Kornilovbf637662022-08-23 19:05:34 +0300169 (void)i2c_read(dev_addr, 0x0, byte, ep, size);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600170
Neha Malcom Francis9f393a22022-12-13 11:57:34 +0530171 if (*((u32 *)ep) != header)
172 one_byte_addressing = false;
173
174 /*
175 * Handle case of bad 2 byte eeproms that responds to 1 byte addressing
176 * but gets stuck in const addressing when read requests are performed
177 * on offsets. We perform an offset test to make sure it is not a 2 byte
178 * eeprom that works with 1 byte addressing but just without an offset
179 */
180
181 rc = i2c_read(dev_addr, 0x1, byte, &offset_test, sizeof(offset_test));
182
183 if (*((u32 *)ep) != (header & 0xFF))
184 one_byte_addressing = false;
185
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600186 /* Corrupted data??? */
Neha Malcom Francis9f393a22022-12-13 11:57:34 +0530187 if (!one_byte_addressing) {
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600188 /*
189 * read the eeprom header using i2c again, but use only a
Nishanth Menona58147c2022-06-17 13:26:12 -0500190 * 2 byte address (some newer boards need this..)
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600191 */
Nishanth Menona58147c2022-06-17 13:26:12 -0500192 byte = 2;
Matwey V. Kornilovbf637662022-08-23 19:05:34 +0300193 rc = i2c_read(dev_addr, 0x0, byte, ep, size);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600194 if (rc)
195 return rc;
196 }
Matwey V. Kornilovbf637662022-08-23 19:05:34 +0300197 if (*((u32 *)ep) != header)
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600198 return -1;
Andreas Dannenberg2463f672018-12-07 14:50:47 +0100199#endif
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600200 return 0;
201}
202
Caleb Robeyd6eaaae2020-01-02 08:17:25 -0600203int __maybe_unused ti_emmc_boardid_get(void)
204{
205 int rc;
206 struct udevice *dev;
207 struct mmc *mmc;
208 struct ti_common_eeprom *ep;
209 struct ti_am_eeprom brdid;
210 struct blk_desc *bdesc;
211 uchar *buffer;
212
213 ep = TI_EEPROM_DATA;
214 if (ep->header == TI_EEPROM_HEADER_MAGIC)
215 return 0; /* EEPROM has already been read */
216
217 /* Initialize with a known bad marker for emmc fails.. */
218 ep->header = TI_DEAD_EEPROM_MAGIC;
219 ep->name[0] = 0x0;
220 ep->version[0] = 0x0;
221 ep->serial[0] = 0x0;
222 ep->config[0] = 0x0;
223
224 /* uclass object initialization */
225 rc = mmc_initialize(NULL);
226 if (rc)
227 return rc;
228
229 /* Set device to /dev/mmcblk1 */
230 rc = uclass_get_device(UCLASS_MMC, 1, &dev);
231 if (rc)
232 return rc;
233
234 /* Grab the mmc device */
235 mmc = mmc_get_mmc_dev(dev);
236 if (!mmc)
237 return -ENODEV;
238
239 /* mmc hardware initialization routine */
240 mmc_init(mmc);
241
242 /* Set partition to /dev/mmcblk1boot1 */
243 rc = mmc_switch_part(mmc, 2);
244 if (rc)
245 return rc;
246
247 buffer = malloc(mmc->read_bl_len);
248 if (!buffer)
249 return -ENOMEM;
250
251 bdesc = mmc_get_blk_desc(mmc);
252
253 /* blk_dread returns the number of blocks read*/
254 if (blk_dread(bdesc, 0L, 1, buffer) != 1) {
255 rc = -EIO;
256 goto cleanup;
257 }
258
259 memcpy(&brdid, buffer, sizeof(brdid));
260
261 /* Write out the ep struct values */
262 ep->header = brdid.header;
263 strlcpy(ep->name, brdid.name, TI_EEPROM_HDR_NAME_LEN + 1);
264 ti_eeprom_string_cleanup(ep->name);
265 strlcpy(ep->version, brdid.version, TI_EEPROM_HDR_REV_LEN + 1);
266 ti_eeprom_string_cleanup(ep->version);
267 strlcpy(ep->serial, brdid.serial, TI_EEPROM_HDR_SERIAL_LEN + 1);
268 ti_eeprom_string_cleanup(ep->serial);
269
270cleanup:
271 free(buffer);
272
273 return rc;
274}
275
Nishanth Menone936f992017-06-16 17:25:04 -0500276int __maybe_unused ti_i2c_eeprom_am_set(const char *name, const char *rev)
277{
278 struct ti_common_eeprom *ep;
279
280 if (!name || !rev)
281 return -1;
282
283 ep = TI_EEPROM_DATA;
284 if (ep->header == TI_EEPROM_HEADER_MAGIC)
285 goto already_set;
286
287 /* Set to 0 all fields */
288 memset(ep, 0, sizeof(*ep));
289 strncpy(ep->name, name, TI_EEPROM_HDR_NAME_LEN);
290 strncpy(ep->version, rev, TI_EEPROM_HDR_REV_LEN);
291 /* Some dummy serial number to identify the platform */
292 strncpy(ep->serial, "0000", TI_EEPROM_HDR_SERIAL_LEN);
293 /* Mark it with a valid header */
294 ep->header = TI_EEPROM_HEADER_MAGIC;
295
296already_set:
297 return 0;
298}
299
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600300int __maybe_unused ti_i2c_eeprom_am_get(int bus_addr, int dev_addr)
301{
302 int rc;
303 struct ti_am_eeprom am_ep;
304 struct ti_common_eeprom *ep;
305
306 ep = TI_EEPROM_DATA;
Jean-Jacques Hiblota3a23c92016-12-01 10:37:03 +0100307#ifndef CONFIG_SPL_BUILD
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600308 if (ep->header == TI_EEPROM_HEADER_MAGIC)
Jean-Jacques Hiblota3a23c92016-12-01 10:37:03 +0100309 return 0; /* EEPROM has already been read */
310#endif
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600311
312 /* Initialize with a known bad marker for i2c fails.. */
313 ep->header = TI_DEAD_EEPROM_MAGIC;
314 ep->name[0] = 0x0;
315 ep->version[0] = 0x0;
316 ep->serial[0] = 0x0;
Nishanth Menon2a78c9e2016-10-11 12:39:04 -0500317 ep->config[0] = 0x0;
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600318
319 rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
320 sizeof(am_ep), (uint8_t *)&am_ep);
321 if (rc)
322 return rc;
323
324 ep->header = am_ep.header;
325 strlcpy(ep->name, am_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
326 ti_eeprom_string_cleanup(ep->name);
327
328 /* BeagleBone Green '1' eeprom, board_rev: 0x1a 0x00 0x00 0x00 */
329 if (am_ep.version[0] == 0x1a && am_ep.version[1] == 0x00 &&
330 am_ep.version[2] == 0x00 && am_ep.version[3] == 0x00)
331 strlcpy(ep->version, "BBG1", TI_EEPROM_HDR_REV_LEN + 1);
332 else
333 strlcpy(ep->version, am_ep.version, TI_EEPROM_HDR_REV_LEN + 1);
334 ti_eeprom_string_cleanup(ep->version);
335 strlcpy(ep->serial, am_ep.serial, TI_EEPROM_HDR_SERIAL_LEN + 1);
336 ti_eeprom_string_cleanup(ep->serial);
337 strlcpy(ep->config, am_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
338 ti_eeprom_string_cleanup(ep->config);
339
340 memcpy(ep->mac_addr, am_ep.mac_addr,
341 TI_EEPROM_HDR_NO_OF_MAC_ADDR * TI_EEPROM_HDR_ETH_ALEN);
342
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600343 return 0;
344}
345
Lokesh Vutlad3b98a92016-03-08 09:18:04 +0530346int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr)
347{
348 int rc, offset = 0;
349 struct dra7_eeprom dra7_ep;
350 struct ti_common_eeprom *ep;
351
352 ep = TI_EEPROM_DATA;
Jean-Jacques Hiblota3a23c92016-12-01 10:37:03 +0100353#ifndef CONFIG_SPL_BUILD
Lokesh Vutlad3b98a92016-03-08 09:18:04 +0530354 if (ep->header == DRA7_EEPROM_HEADER_MAGIC)
Jean-Jacques Hiblota3a23c92016-12-01 10:37:03 +0100355 return 0; /* EEPROM has already been read */
356#endif
Lokesh Vutlad3b98a92016-03-08 09:18:04 +0530357
358 /* Initialize with a known bad marker for i2c fails.. */
Nishanth Menon28d624b2016-10-11 12:39:03 -0500359 ep->header = TI_DEAD_EEPROM_MAGIC;
Lokesh Vutlad3b98a92016-03-08 09:18:04 +0530360 ep->name[0] = 0x0;
361 ep->version[0] = 0x0;
362 ep->serial[0] = 0x0;
Nishanth Menon2a78c9e2016-10-11 12:39:04 -0500363 ep->config[0] = 0x0;
Lokesh Vutlad3b98a92016-03-08 09:18:04 +0530364 ep->emif1_size = 0;
365 ep->emif2_size = 0;
366
367 rc = ti_i2c_eeprom_get(bus_addr, dev_addr, DRA7_EEPROM_HEADER_MAGIC,
368 sizeof(dra7_ep), (uint8_t *)&dra7_ep);
369 if (rc)
370 return rc;
371
372 ep->header = dra7_ep.header;
373 strlcpy(ep->name, dra7_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
374 ti_eeprom_string_cleanup(ep->name);
375
376 offset = dra7_ep.version_major - 1;
377
378 /* Rev F is skipped */
379 if (offset >= 5)
380 offset = offset + 1;
381 snprintf(ep->version, TI_EEPROM_HDR_REV_LEN + 1, "%c.%d",
382 'A' + offset, dra7_ep.version_minor);
383 ti_eeprom_string_cleanup(ep->version);
384 ep->emif1_size = (u64)dra7_ep.emif1_size;
385 ep->emif2_size = (u64)dra7_ep.emif2_size;
386 strlcpy(ep->config, dra7_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
387 ti_eeprom_string_cleanup(ep->config);
388
Lokesh Vutlad3b98a92016-03-08 09:18:04 +0530389 return 0;
390}
391
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500392static int ti_i2c_eeprom_am6_parse_record(struct ti_am6_eeprom_record *record,
393 struct ti_am6_eeprom *ep,
394 char **mac_addr,
395 u8 mac_addr_max_cnt,
396 u8 *mac_addr_cnt)
397{
398 switch (record->header.id) {
399 case TI_AM6_EEPROM_RECORD_BOARD_INFO:
400 if (record->header.len != sizeof(record->data.board_info))
401 return -EINVAL;
402
403 if (!ep)
404 break;
405
406 /* Populate (and clean, if needed) the board name */
407 strlcpy(ep->name, record->data.board_info.name,
408 sizeof(ep->name));
409 ti_eeprom_string_cleanup(ep->name);
410
411 /* Populate selected other fields from the board info record */
412 strlcpy(ep->version, record->data.board_info.version,
413 sizeof(ep->version));
414 strlcpy(ep->software_revision,
415 record->data.board_info.software_revision,
416 sizeof(ep->software_revision));
417 strlcpy(ep->serial, record->data.board_info.serial,
418 sizeof(ep->serial));
419 break;
420 case TI_AM6_EEPROM_RECORD_MAC_INFO:
421 if (record->header.len != sizeof(record->data.mac_info))
422 return -EINVAL;
423
424 if (!mac_addr || !mac_addr_max_cnt)
425 break;
426
427 *mac_addr_cnt = ((record->data.mac_info.mac_control &
428 TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK) >>
429 TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT) + 1;
430
431 /*
432 * The EEPROM can (but may not) hold a very large amount
433 * of MAC addresses, by far exceeding what we want/can store
434 * in the common memory array, so only grab what we can fit.
435 * Note that a value of 0 means 1 MAC address, and so on.
436 */
437 *mac_addr_cnt = min(*mac_addr_cnt, mac_addr_max_cnt);
438
439 memcpy(mac_addr, record->data.mac_info.mac_addr,
440 *mac_addr_cnt * TI_EEPROM_HDR_ETH_ALEN);
441 break;
442 case 0x00:
443 /* Illegal value... Fall through... */
444 case 0xFF:
445 /* Illegal value... Something went horribly wrong... */
446 return -EINVAL;
447 default:
448 pr_warn("%s: Ignoring record id %u\n", __func__,
449 record->header.id);
450 }
451
452 return 0;
453}
454
455int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr,
456 struct ti_am6_eeprom *ep,
457 char **mac_addr,
458 u8 mac_addr_max_cnt,
459 u8 *mac_addr_cnt)
460{
461 struct udevice *dev;
462 struct udevice *bus;
463 unsigned int eeprom_addr;
464 struct ti_am6_eeprom_record_board_id board_id;
465 struct ti_am6_eeprom_record record;
466 int rc;
Nishanth Menon8b5218e2022-06-17 13:26:10 -0500467 int consecutive_bad_records = 0;
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500468
469 /* Initialize with a known bad marker for i2c fails.. */
470 memset(ep, 0, sizeof(*ep));
471 ep->header = TI_DEAD_EEPROM_MAGIC;
472
473 /* Read the board ID record which is always the first EEPROM record */
474 rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
475 sizeof(board_id), (uint8_t *)&board_id);
476 if (rc)
477 return rc;
478
479 if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) {
480 pr_err("%s: Invalid board ID record!\n", __func__);
481 return -EINVAL;
482 }
483
484 /* Establish DM handle to board config EEPROM */
485 rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
486 if (rc)
487 return rc;
488 rc = i2c_get_chip(bus, dev_addr, 1, &dev);
489 if (rc)
490 return rc;
491
492 ep->header = TI_EEPROM_HEADER_MAGIC;
493
494 /* Ready to parse TLV structure. Initialize variables... */
495 *mac_addr_cnt = 0;
496
497 /*
498 * After the all-encompassing board ID record all other records follow
499 * a TLV-type scheme. Point to the first such record and then start
500 * parsing those one by one.
501 */
502 eeprom_addr = sizeof(board_id);
503
Nishanth Menon8b5218e2022-06-17 13:26:10 -0500504 while (consecutive_bad_records < 10) {
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500505 rc = dm_i2c_read(dev, eeprom_addr, (uint8_t *)&record.header,
506 sizeof(record.header));
507 if (rc)
508 return rc;
509
510 /*
511 * Check for end of list marker. If we reached it don't go
512 * any further and stop parsing right here.
513 */
514 if (record.header.id == TI_AM6_EEPROM_RECORD_END_LIST)
515 break;
516
517 eeprom_addr += sizeof(record.header);
518
519 debug("%s: dev_addr=0x%02x header.id=%u header.len=%u\n",
520 __func__, dev_addr, record.header.id,
521 record.header.len);
522
523 /* Read record into memory if it fits */
524 if (record.header.len <= sizeof(record.data)) {
525 rc = dm_i2c_read(dev, eeprom_addr,
526 (uint8_t *)&record.data,
527 record.header.len);
528 if (rc)
529 return rc;
530
531 /* Process record */
532 rc = ti_i2c_eeprom_am6_parse_record(&record, ep,
533 mac_addr,
534 mac_addr_max_cnt,
535 mac_addr_cnt);
536 if (rc) {
537 pr_err("%s: EEPROM parsing error!\n", __func__);
538 return rc;
539 }
Nishanth Menon8b5218e2022-06-17 13:26:10 -0500540 consecutive_bad_records = 0;
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500541 } else {
542 /*
543 * We may get here in case of larger records which
544 * are not yet understood.
545 */
546 pr_err("%s: Ignoring record id %u\n", __func__,
547 record.header.id);
Nishanth Menon8b5218e2022-06-17 13:26:10 -0500548 consecutive_bad_records++;
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500549 }
550
551 eeprom_addr += record.header.len;
552 }
553
554 return 0;
555}
556
557int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr)
558{
559 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
560 int ret;
561
562 /*
563 * Always execute EEPROM read by not allowing to bypass it during the
564 * first invocation of SPL which happens on the R5 core.
565 */
566#if !(defined(CONFIG_SPL_BUILD) && defined(CONFIG_CPU_V7R))
567 if (ep->header == TI_EEPROM_HEADER_MAGIC) {
568 debug("%s: EEPROM has already been read\n", __func__);
569 return 0;
570 }
571#endif
572
573 ret = ti_i2c_eeprom_am6_get(bus_addr, dev_addr, ep,
574 (char **)ep->mac_addr,
575 AM6_EEPROM_HDR_NO_OF_MAC_ADDR,
576 &ep->mac_addr_cnt);
577 return ret;
578}
579
Andreas Dannenberg643eb6e2020-01-07 13:15:54 +0530580bool __maybe_unused board_ti_k3_is(char *name_tag)
581{
582 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
583
584 if (ep->header == TI_DEAD_EEPROM_MAGIC)
585 return false;
586 return !strncmp(ep->name, name_tag, AM6_EEPROM_HDR_NAME_LEN);
587}
588
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600589bool __maybe_unused board_ti_is(char *name_tag)
590{
591 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
592
593 if (ep->header == TI_DEAD_EEPROM_MAGIC)
594 return false;
595 return !strncmp(ep->name, name_tag, TI_EEPROM_HDR_NAME_LEN);
596}
597
598bool __maybe_unused board_ti_rev_is(char *rev_tag, int cmp_len)
599{
600 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
601 int l;
602
603 if (ep->header == TI_DEAD_EEPROM_MAGIC)
604 return false;
605
606 l = cmp_len > TI_EEPROM_HDR_REV_LEN ? TI_EEPROM_HDR_REV_LEN : cmp_len;
607 return !strncmp(ep->version, rev_tag, l);
608}
609
610char * __maybe_unused board_ti_get_rev(void)
611{
612 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
613
Nishanth Menon7774e972016-10-11 12:39:05 -0500614 /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600615 return ep->version;
616}
617
618char * __maybe_unused board_ti_get_config(void)
619{
620 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
621
Nishanth Menon7774e972016-10-11 12:39:05 -0500622 /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600623 return ep->config;
624}
625
626char * __maybe_unused board_ti_get_name(void)
627{
628 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
629
Nishanth Menon7774e972016-10-11 12:39:05 -0500630 /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600631 return ep->name;
632}
633
634void __maybe_unused
635board_ti_get_eth_mac_addr(int index,
636 u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
637{
638 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
639
640 if (ep->header == TI_DEAD_EEPROM_MAGIC)
641 goto fail;
642
643 if (index < 0 || index >= TI_EEPROM_HDR_NO_OF_MAC_ADDR)
644 goto fail;
645
646 memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
647 return;
648
649fail:
650 memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
651}
652
Andreas Dannenberg183fa082019-06-04 18:08:25 -0500653void __maybe_unused
654board_ti_am6_get_eth_mac_addr(int index,
655 u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
656{
657 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
658
659 if (ep->header == TI_DEAD_EEPROM_MAGIC)
660 goto fail;
661
662 if (index < 0 || index >= ep->mac_addr_cnt)
663 goto fail;
664
665 memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
666 return;
667
668fail:
669 memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
670}
671
Lokesh Vutlad3b98a92016-03-08 09:18:04 +0530672u64 __maybe_unused board_ti_get_emif1_size(void)
673{
674 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
675
676 if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
677 return 0;
678
679 return ep->emif1_size;
680}
681
682u64 __maybe_unused board_ti_get_emif2_size(void)
683{
684 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
685
686 if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
687 return 0;
688
689 return ep->emif2_size;
690}
691
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600692void __maybe_unused set_board_info_env(char *name)
693{
694 char *unknown = "unknown";
695 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
696
697 if (name)
Simon Glass382bee52017-08-03 12:22:09 -0600698 env_set("board_name", name);
Tom Rinie76e85c2020-06-04 15:45:08 -0400699 else if (strlen(ep->name) != 0)
Simon Glass382bee52017-08-03 12:22:09 -0600700 env_set("board_name", ep->name);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600701 else
Simon Glass382bee52017-08-03 12:22:09 -0600702 env_set("board_name", unknown);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600703
Tom Rinie76e85c2020-06-04 15:45:08 -0400704 if (strlen(ep->version) != 0)
Simon Glass382bee52017-08-03 12:22:09 -0600705 env_set("board_rev", ep->version);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600706 else
Simon Glass382bee52017-08-03 12:22:09 -0600707 env_set("board_rev", unknown);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600708
Tom Rinie76e85c2020-06-04 15:45:08 -0400709 if (strlen(ep->serial) != 0)
Simon Glass382bee52017-08-03 12:22:09 -0600710 env_set("board_serial", ep->serial);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600711 else
Simon Glass382bee52017-08-03 12:22:09 -0600712 env_set("board_serial", unknown);
Lokesh Vutla0bea8132016-02-24 12:30:54 -0600713}
Roger Quadros38f719e2017-03-14 15:04:19 +0200714
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500715void __maybe_unused set_board_info_env_am6(char *name)
716{
717 char *unknown = "unknown";
718 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
719
720 if (name)
721 env_set("board_name", name);
Tom Rinie76e85c2020-06-04 15:45:08 -0400722 else if (strlen(ep->name) != 0)
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500723 env_set("board_name", ep->name);
724 else
725 env_set("board_name", unknown);
726
Tom Rinie76e85c2020-06-04 15:45:08 -0400727 if (strlen(ep->version) != 0)
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500728 env_set("board_rev", ep->version);
729 else
730 env_set("board_rev", unknown);
731
Tom Rinie76e85c2020-06-04 15:45:08 -0400732 if (strlen(ep->software_revision) != 0)
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500733 env_set("board_software_revision", ep->software_revision);
734 else
735 env_set("board_software_revision", unknown);
736
Tom Rinie76e85c2020-06-04 15:45:08 -0400737 if (strlen(ep->serial) != 0)
Andreas Dannenberg361a5332019-06-04 18:08:24 -0500738 env_set("board_serial", ep->serial);
739 else
740 env_set("board_serial", unknown);
741}
742
Roger Quadros38f719e2017-03-14 15:04:19 +0200743static u64 mac_to_u64(u8 mac[6])
744{
745 int i;
746 u64 addr = 0;
747
748 for (i = 0; i < 6; i++) {
749 addr <<= 8;
750 addr |= mac[i];
751 }
752
753 return addr;
754}
755
756static void u64_to_mac(u64 addr, u8 mac[6])
757{
758 mac[5] = addr;
759 mac[4] = addr >> 8;
760 mac[3] = addr >> 16;
761 mac[2] = addr >> 24;
762 mac[1] = addr >> 32;
763 mac[0] = addr >> 40;
764}
765
766void board_ti_set_ethaddr(int index)
767{
768 uint8_t mac_addr[6];
769 int i;
770 u64 mac1, mac2;
771 u8 mac_addr1[6], mac_addr2[6];
772 int num_macs;
773 /*
774 * Export any Ethernet MAC addresses from EEPROM.
775 * The 2 MAC addresses in EEPROM define the address range.
776 */
777 board_ti_get_eth_mac_addr(0, mac_addr1);
778 board_ti_get_eth_mac_addr(1, mac_addr2);
779
780 if (is_valid_ethaddr(mac_addr1) && is_valid_ethaddr(mac_addr2)) {
781 mac1 = mac_to_u64(mac_addr1);
782 mac2 = mac_to_u64(mac_addr2);
783
784 /* must contain an address range */
785 num_macs = mac2 - mac1 + 1;
786 if (num_macs <= 0)
787 return;
788
789 if (num_macs > 50) {
790 printf("%s: Too many MAC addresses: %d. Limiting to 50\n",
791 __func__, num_macs);
792 num_macs = 50;
793 }
794
795 for (i = 0; i < num_macs; i++) {
796 u64_to_mac(mac1 + i, mac_addr);
797 if (is_valid_ethaddr(mac_addr)) {
Simon Glassfd1e9592017-08-03 12:22:11 -0600798 eth_env_set_enetaddr_by_index("eth", i + index,
799 mac_addr);
Roger Quadros38f719e2017-03-14 15:04:19 +0200800 }
801 }
802 }
803}
Cooper Jr., Franklin69e8d4b2017-06-16 17:25:08 -0500804
Andreas Dannenberg183fa082019-06-04 18:08:25 -0500805void board_ti_am6_set_ethaddr(int index, int count)
806{
807 u8 mac_addr[6];
808 int i;
809
810 for (i = 0; i < count; i++) {
811 board_ti_am6_get_eth_mac_addr(i, mac_addr);
812 if (is_valid_ethaddr(mac_addr))
813 eth_env_set_enetaddr_by_index("eth", i + index,
814 mac_addr);
815 }
816}
817
Cooper Jr., Franklin69e8d4b2017-06-16 17:25:08 -0500818bool __maybe_unused board_ti_was_eeprom_read(void)
819{
820 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
821
822 if (ep->header == TI_EEPROM_HEADER_MAGIC)
823 return true;
824 else
825 return false;
826}