blob: cbd35f24342c68d43c7a901ccf46877cc56c6b63 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Lokesh Vutla35f7a972016-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 Vutla35f7a972016-02-24 12:30:54 -06008 */
9
10#include <common.h>
Simon Glasseba6b8d2019-11-14 12:57:50 -070011#include <eeprom.h>
Andreas Dannenbergf998a822019-06-04 18:08:24 -050012#include <asm/arch/hardware.h>
Lokesh Vutla35f7a972016-02-24 12:30:54 -060013#include <asm/omap_common.h>
Cooper Jr., Franklinf2598de2017-04-20 10:25:44 -050014#include <dm/uclass.h>
Simon Glass5e6201b2019-08-01 09:46:51 -060015#include <env.h>
Lokesh Vutla35f7a972016-02-24 12:30:54 -060016#include <i2c.h>
Caleb Robey0dfcc932020-01-02 08:17:25 -060017#include <mmc.h>
18#include <errno.h>
19#include <malloc.h>
Lokesh Vutla35f7a972016-02-24 12:30:54 -060020
21#include "board_detect.h"
22
Jean-Jacques Hiblot52a51512018-12-07 14:50:49 +010023#if !defined(CONFIG_DM_I2C)
Lokesh Vutla35f7a972016-02-24 12:30:54 -060024/**
25 * ti_i2c_eeprom_init - Initialize an i2c bus and probe for a device
26 * @i2c_bus: i2c bus number to initialize
27 * @dev_addr: Device address to probe for
28 *
29 * Return: 0 on success or corresponding error on failure.
30 */
31static int __maybe_unused ti_i2c_eeprom_init(int i2c_bus, int dev_addr)
32{
33 int rc;
34
35 if (i2c_bus >= 0) {
36 rc = i2c_set_bus_num(i2c_bus);
37 if (rc)
38 return rc;
39 }
40
41 return i2c_probe(dev_addr);
42}
43
44/**
45 * ti_i2c_eeprom_read - Read data from an EEPROM
46 * @dev_addr: The device address of the EEPROM
47 * @offset: Offset to start reading in the EEPROM
48 * @ep: Pointer to a buffer to read into
49 * @epsize: Size of buffer
50 *
51 * Return: 0 on success or corresponding result of i2c_read
52 */
53static int __maybe_unused ti_i2c_eeprom_read(int dev_addr, int offset,
54 uchar *ep, int epsize)
55{
Jean-Jacques Hiblot52a51512018-12-07 14:50:49 +010056 return i2c_read(dev_addr, offset, 2, ep, epsize);
Lokesh Vutla35f7a972016-02-24 12:30:54 -060057}
Andreas Dannenberge315a662018-12-07 14:50:47 +010058#endif
Lokesh Vutla35f7a972016-02-24 12:30:54 -060059
60/**
61 * ti_eeprom_string_cleanup() - Handle eeprom programming errors
62 * @s: eeprom string (should be NULL terminated)
63 *
64 * Some Board manufacturers do not add a NULL termination at the
65 * end of string, instead some binary information is kludged in, hence
66 * convert the string to just printable characters of ASCII chart.
67 */
68static void __maybe_unused ti_eeprom_string_cleanup(char *s)
69{
70 int i, l;
71
72 l = strlen(s);
73 for (i = 0; i < l; i++, s++)
74 if (*s < ' ' || *s > '~') {
75 *s = 0;
76 break;
77 }
78}
79
80__weak void gpi2c_init(void)
81{
82}
83
84static int __maybe_unused ti_i2c_eeprom_get(int bus_addr, int dev_addr,
85 u32 header, u32 size, uint8_t *ep)
86{
Andreas Dannenberge315a662018-12-07 14:50:47 +010087 u32 hdr_read;
Lokesh Vutla35f7a972016-02-24 12:30:54 -060088 int rc;
89
Jean-Jacques Hiblot52a51512018-12-07 14:50:49 +010090#if defined(CONFIG_DM_I2C)
Andreas Dannenberge315a662018-12-07 14:50:47 +010091 struct udevice *dev;
92 struct udevice *bus;
93
94 rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
95 if (rc)
96 return rc;
Andreas Dannenberg48034922020-01-07 13:15:53 +053097 rc = dm_i2c_probe(bus, dev_addr, 0, &dev);
Andreas Dannenberge315a662018-12-07 14:50:47 +010098 if (rc)
99 return rc;
100
101 /*
102 * Read the header first then only read the other contents.
103 */
104 rc = i2c_set_chip_offset_len(dev, 2);
105 if (rc)
106 return rc;
107
108 rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
109 if (rc)
110 return rc;
111
112 /* Corrupted data??? */
113 if (hdr_read != header) {
114 rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
115 /*
116 * read the eeprom header using i2c again, but use only a
117 * 1 byte address (some legacy boards need this..)
118 */
119 if (rc) {
120 rc = i2c_set_chip_offset_len(dev, 1);
121 if (rc)
122 return rc;
123
124 rc = dm_i2c_read(dev, 0, (uint8_t *)&hdr_read, 4);
125 }
126 if (rc)
127 return rc;
128 }
129 if (hdr_read != header)
130 return -1;
131
132 rc = dm_i2c_read(dev, 0, ep, size);
133 if (rc)
134 return rc;
135#else
136 u32 byte;
137
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600138 gpi2c_init();
139 rc = ti_i2c_eeprom_init(bus_addr, dev_addr);
140 if (rc)
141 return rc;
142
143 /*
144 * Read the header first then only read the other contents.
145 */
146 byte = 2;
Cooper Jr., Franklin5b89c972017-04-20 10:25:45 -0500147
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600148 rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
149 if (rc)
150 return rc;
151
152 /* Corrupted data??? */
153 if (hdr_read != header) {
154 rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read, 4);
155 /*
156 * read the eeprom header using i2c again, but use only a
157 * 1 byte address (some legacy boards need this..)
158 */
159 byte = 1;
Cooper Jr., Franklin5b89c972017-04-20 10:25:45 -0500160 if (rc) {
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600161 rc = i2c_read(dev_addr, 0x0, byte, (uint8_t *)&hdr_read,
162 4);
Cooper Jr., Franklin5b89c972017-04-20 10:25:45 -0500163 }
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600164 if (rc)
165 return rc;
166 }
167 if (hdr_read != header)
168 return -1;
169
170 rc = i2c_read(dev_addr, 0x0, byte, ep, size);
171 if (rc)
172 return rc;
Andreas Dannenberge315a662018-12-07 14:50:47 +0100173#endif
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600174 return 0;
175}
176
Caleb Robey0dfcc932020-01-02 08:17:25 -0600177int __maybe_unused ti_emmc_boardid_get(void)
178{
179 int rc;
180 struct udevice *dev;
181 struct mmc *mmc;
182 struct ti_common_eeprom *ep;
183 struct ti_am_eeprom brdid;
184 struct blk_desc *bdesc;
185 uchar *buffer;
186
187 ep = TI_EEPROM_DATA;
188 if (ep->header == TI_EEPROM_HEADER_MAGIC)
189 return 0; /* EEPROM has already been read */
190
191 /* Initialize with a known bad marker for emmc fails.. */
192 ep->header = TI_DEAD_EEPROM_MAGIC;
193 ep->name[0] = 0x0;
194 ep->version[0] = 0x0;
195 ep->serial[0] = 0x0;
196 ep->config[0] = 0x0;
197
198 /* uclass object initialization */
199 rc = mmc_initialize(NULL);
200 if (rc)
201 return rc;
202
203 /* Set device to /dev/mmcblk1 */
204 rc = uclass_get_device(UCLASS_MMC, 1, &dev);
205 if (rc)
206 return rc;
207
208 /* Grab the mmc device */
209 mmc = mmc_get_mmc_dev(dev);
210 if (!mmc)
211 return -ENODEV;
212
213 /* mmc hardware initialization routine */
214 mmc_init(mmc);
215
216 /* Set partition to /dev/mmcblk1boot1 */
217 rc = mmc_switch_part(mmc, 2);
218 if (rc)
219 return rc;
220
221 buffer = malloc(mmc->read_bl_len);
222 if (!buffer)
223 return -ENOMEM;
224
225 bdesc = mmc_get_blk_desc(mmc);
226
227 /* blk_dread returns the number of blocks read*/
228 if (blk_dread(bdesc, 0L, 1, buffer) != 1) {
229 rc = -EIO;
230 goto cleanup;
231 }
232
233 memcpy(&brdid, buffer, sizeof(brdid));
234
235 /* Write out the ep struct values */
236 ep->header = brdid.header;
237 strlcpy(ep->name, brdid.name, TI_EEPROM_HDR_NAME_LEN + 1);
238 ti_eeprom_string_cleanup(ep->name);
239 strlcpy(ep->version, brdid.version, TI_EEPROM_HDR_REV_LEN + 1);
240 ti_eeprom_string_cleanup(ep->version);
241 strlcpy(ep->serial, brdid.serial, TI_EEPROM_HDR_SERIAL_LEN + 1);
242 ti_eeprom_string_cleanup(ep->serial);
243
244cleanup:
245 free(buffer);
246
247 return rc;
248}
249
Nishanth Menon27856ff2017-06-16 17:25:04 -0500250int __maybe_unused ti_i2c_eeprom_am_set(const char *name, const char *rev)
251{
252 struct ti_common_eeprom *ep;
253
254 if (!name || !rev)
255 return -1;
256
257 ep = TI_EEPROM_DATA;
258 if (ep->header == TI_EEPROM_HEADER_MAGIC)
259 goto already_set;
260
261 /* Set to 0 all fields */
262 memset(ep, 0, sizeof(*ep));
263 strncpy(ep->name, name, TI_EEPROM_HDR_NAME_LEN);
264 strncpy(ep->version, rev, TI_EEPROM_HDR_REV_LEN);
265 /* Some dummy serial number to identify the platform */
266 strncpy(ep->serial, "0000", TI_EEPROM_HDR_SERIAL_LEN);
267 /* Mark it with a valid header */
268 ep->header = TI_EEPROM_HEADER_MAGIC;
269
270already_set:
271 return 0;
272}
273
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600274int __maybe_unused ti_i2c_eeprom_am_get(int bus_addr, int dev_addr)
275{
276 int rc;
277 struct ti_am_eeprom am_ep;
278 struct ti_common_eeprom *ep;
279
280 ep = TI_EEPROM_DATA;
Jean-Jacques Hiblota096a762016-12-01 10:37:03 +0100281#ifndef CONFIG_SPL_BUILD
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600282 if (ep->header == TI_EEPROM_HEADER_MAGIC)
Jean-Jacques Hiblota096a762016-12-01 10:37:03 +0100283 return 0; /* EEPROM has already been read */
284#endif
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600285
286 /* Initialize with a known bad marker for i2c fails.. */
287 ep->header = TI_DEAD_EEPROM_MAGIC;
288 ep->name[0] = 0x0;
289 ep->version[0] = 0x0;
290 ep->serial[0] = 0x0;
Nishanth Menone2b0a522016-10-11 12:39:04 -0500291 ep->config[0] = 0x0;
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600292
293 rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
294 sizeof(am_ep), (uint8_t *)&am_ep);
295 if (rc)
296 return rc;
297
298 ep->header = am_ep.header;
299 strlcpy(ep->name, am_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
300 ti_eeprom_string_cleanup(ep->name);
301
302 /* BeagleBone Green '1' eeprom, board_rev: 0x1a 0x00 0x00 0x00 */
303 if (am_ep.version[0] == 0x1a && am_ep.version[1] == 0x00 &&
304 am_ep.version[2] == 0x00 && am_ep.version[3] == 0x00)
305 strlcpy(ep->version, "BBG1", TI_EEPROM_HDR_REV_LEN + 1);
306 else
307 strlcpy(ep->version, am_ep.version, TI_EEPROM_HDR_REV_LEN + 1);
308 ti_eeprom_string_cleanup(ep->version);
309 strlcpy(ep->serial, am_ep.serial, TI_EEPROM_HDR_SERIAL_LEN + 1);
310 ti_eeprom_string_cleanup(ep->serial);
311 strlcpy(ep->config, am_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
312 ti_eeprom_string_cleanup(ep->config);
313
314 memcpy(ep->mac_addr, am_ep.mac_addr,
315 TI_EEPROM_HDR_NO_OF_MAC_ADDR * TI_EEPROM_HDR_ETH_ALEN);
316
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600317 return 0;
318}
319
Lokesh Vutla7c08a782016-03-08 09:18:04 +0530320int __maybe_unused ti_i2c_eeprom_dra7_get(int bus_addr, int dev_addr)
321{
322 int rc, offset = 0;
323 struct dra7_eeprom dra7_ep;
324 struct ti_common_eeprom *ep;
325
326 ep = TI_EEPROM_DATA;
Jean-Jacques Hiblota096a762016-12-01 10:37:03 +0100327#ifndef CONFIG_SPL_BUILD
Lokesh Vutla7c08a782016-03-08 09:18:04 +0530328 if (ep->header == DRA7_EEPROM_HEADER_MAGIC)
Jean-Jacques Hiblota096a762016-12-01 10:37:03 +0100329 return 0; /* EEPROM has already been read */
330#endif
Lokesh Vutla7c08a782016-03-08 09:18:04 +0530331
332 /* Initialize with a known bad marker for i2c fails.. */
Nishanth Menon21e54c02016-10-11 12:39:03 -0500333 ep->header = TI_DEAD_EEPROM_MAGIC;
Lokesh Vutla7c08a782016-03-08 09:18:04 +0530334 ep->name[0] = 0x0;
335 ep->version[0] = 0x0;
336 ep->serial[0] = 0x0;
Nishanth Menone2b0a522016-10-11 12:39:04 -0500337 ep->config[0] = 0x0;
Lokesh Vutla7c08a782016-03-08 09:18:04 +0530338 ep->emif1_size = 0;
339 ep->emif2_size = 0;
340
341 rc = ti_i2c_eeprom_get(bus_addr, dev_addr, DRA7_EEPROM_HEADER_MAGIC,
342 sizeof(dra7_ep), (uint8_t *)&dra7_ep);
343 if (rc)
344 return rc;
345
346 ep->header = dra7_ep.header;
347 strlcpy(ep->name, dra7_ep.name, TI_EEPROM_HDR_NAME_LEN + 1);
348 ti_eeprom_string_cleanup(ep->name);
349
350 offset = dra7_ep.version_major - 1;
351
352 /* Rev F is skipped */
353 if (offset >= 5)
354 offset = offset + 1;
355 snprintf(ep->version, TI_EEPROM_HDR_REV_LEN + 1, "%c.%d",
356 'A' + offset, dra7_ep.version_minor);
357 ti_eeprom_string_cleanup(ep->version);
358 ep->emif1_size = (u64)dra7_ep.emif1_size;
359 ep->emif2_size = (u64)dra7_ep.emif2_size;
360 strlcpy(ep->config, dra7_ep.config, TI_EEPROM_HDR_CONFIG_LEN + 1);
361 ti_eeprom_string_cleanup(ep->config);
362
Lokesh Vutla7c08a782016-03-08 09:18:04 +0530363 return 0;
364}
365
Andreas Dannenbergf998a822019-06-04 18:08:24 -0500366static int ti_i2c_eeprom_am6_parse_record(struct ti_am6_eeprom_record *record,
367 struct ti_am6_eeprom *ep,
368 char **mac_addr,
369 u8 mac_addr_max_cnt,
370 u8 *mac_addr_cnt)
371{
372 switch (record->header.id) {
373 case TI_AM6_EEPROM_RECORD_BOARD_INFO:
374 if (record->header.len != sizeof(record->data.board_info))
375 return -EINVAL;
376
377 if (!ep)
378 break;
379
380 /* Populate (and clean, if needed) the board name */
381 strlcpy(ep->name, record->data.board_info.name,
382 sizeof(ep->name));
383 ti_eeprom_string_cleanup(ep->name);
384
385 /* Populate selected other fields from the board info record */
386 strlcpy(ep->version, record->data.board_info.version,
387 sizeof(ep->version));
388 strlcpy(ep->software_revision,
389 record->data.board_info.software_revision,
390 sizeof(ep->software_revision));
391 strlcpy(ep->serial, record->data.board_info.serial,
392 sizeof(ep->serial));
393 break;
394 case TI_AM6_EEPROM_RECORD_MAC_INFO:
395 if (record->header.len != sizeof(record->data.mac_info))
396 return -EINVAL;
397
398 if (!mac_addr || !mac_addr_max_cnt)
399 break;
400
401 *mac_addr_cnt = ((record->data.mac_info.mac_control &
402 TI_AM6_EEPROM_MAC_ADDR_COUNT_MASK) >>
403 TI_AM6_EEPROM_MAC_ADDR_COUNT_SHIFT) + 1;
404
405 /*
406 * The EEPROM can (but may not) hold a very large amount
407 * of MAC addresses, by far exceeding what we want/can store
408 * in the common memory array, so only grab what we can fit.
409 * Note that a value of 0 means 1 MAC address, and so on.
410 */
411 *mac_addr_cnt = min(*mac_addr_cnt, mac_addr_max_cnt);
412
413 memcpy(mac_addr, record->data.mac_info.mac_addr,
414 *mac_addr_cnt * TI_EEPROM_HDR_ETH_ALEN);
415 break;
416 case 0x00:
417 /* Illegal value... Fall through... */
418 case 0xFF:
419 /* Illegal value... Something went horribly wrong... */
420 return -EINVAL;
421 default:
422 pr_warn("%s: Ignoring record id %u\n", __func__,
423 record->header.id);
424 }
425
426 return 0;
427}
428
429int __maybe_unused ti_i2c_eeprom_am6_get(int bus_addr, int dev_addr,
430 struct ti_am6_eeprom *ep,
431 char **mac_addr,
432 u8 mac_addr_max_cnt,
433 u8 *mac_addr_cnt)
434{
435 struct udevice *dev;
436 struct udevice *bus;
437 unsigned int eeprom_addr;
438 struct ti_am6_eeprom_record_board_id board_id;
439 struct ti_am6_eeprom_record record;
440 int rc;
441
442 /* Initialize with a known bad marker for i2c fails.. */
443 memset(ep, 0, sizeof(*ep));
444 ep->header = TI_DEAD_EEPROM_MAGIC;
445
446 /* Read the board ID record which is always the first EEPROM record */
447 rc = ti_i2c_eeprom_get(bus_addr, dev_addr, TI_EEPROM_HEADER_MAGIC,
448 sizeof(board_id), (uint8_t *)&board_id);
449 if (rc)
450 return rc;
451
452 if (board_id.header.id != TI_AM6_EEPROM_RECORD_BOARD_ID) {
453 pr_err("%s: Invalid board ID record!\n", __func__);
454 return -EINVAL;
455 }
456
457 /* Establish DM handle to board config EEPROM */
458 rc = uclass_get_device_by_seq(UCLASS_I2C, bus_addr, &bus);
459 if (rc)
460 return rc;
461 rc = i2c_get_chip(bus, dev_addr, 1, &dev);
462 if (rc)
463 return rc;
464
465 ep->header = TI_EEPROM_HEADER_MAGIC;
466
467 /* Ready to parse TLV structure. Initialize variables... */
468 *mac_addr_cnt = 0;
469
470 /*
471 * After the all-encompassing board ID record all other records follow
472 * a TLV-type scheme. Point to the first such record and then start
473 * parsing those one by one.
474 */
475 eeprom_addr = sizeof(board_id);
476
477 while (true) {
478 rc = dm_i2c_read(dev, eeprom_addr, (uint8_t *)&record.header,
479 sizeof(record.header));
480 if (rc)
481 return rc;
482
483 /*
484 * Check for end of list marker. If we reached it don't go
485 * any further and stop parsing right here.
486 */
487 if (record.header.id == TI_AM6_EEPROM_RECORD_END_LIST)
488 break;
489
490 eeprom_addr += sizeof(record.header);
491
492 debug("%s: dev_addr=0x%02x header.id=%u header.len=%u\n",
493 __func__, dev_addr, record.header.id,
494 record.header.len);
495
496 /* Read record into memory if it fits */
497 if (record.header.len <= sizeof(record.data)) {
498 rc = dm_i2c_read(dev, eeprom_addr,
499 (uint8_t *)&record.data,
500 record.header.len);
501 if (rc)
502 return rc;
503
504 /* Process record */
505 rc = ti_i2c_eeprom_am6_parse_record(&record, ep,
506 mac_addr,
507 mac_addr_max_cnt,
508 mac_addr_cnt);
509 if (rc) {
510 pr_err("%s: EEPROM parsing error!\n", __func__);
511 return rc;
512 }
513 } else {
514 /*
515 * We may get here in case of larger records which
516 * are not yet understood.
517 */
518 pr_err("%s: Ignoring record id %u\n", __func__,
519 record.header.id);
520 }
521
522 eeprom_addr += record.header.len;
523 }
524
525 return 0;
526}
527
528int __maybe_unused ti_i2c_eeprom_am6_get_base(int bus_addr, int dev_addr)
529{
530 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
531 int ret;
532
533 /*
534 * Always execute EEPROM read by not allowing to bypass it during the
535 * first invocation of SPL which happens on the R5 core.
536 */
537#if !(defined(CONFIG_SPL_BUILD) && defined(CONFIG_CPU_V7R))
538 if (ep->header == TI_EEPROM_HEADER_MAGIC) {
539 debug("%s: EEPROM has already been read\n", __func__);
540 return 0;
541 }
542#endif
543
544 ret = ti_i2c_eeprom_am6_get(bus_addr, dev_addr, ep,
545 (char **)ep->mac_addr,
546 AM6_EEPROM_HDR_NO_OF_MAC_ADDR,
547 &ep->mac_addr_cnt);
548 return ret;
549}
550
Andreas Dannenbergd036a212020-01-07 13:15:54 +0530551bool __maybe_unused board_ti_k3_is(char *name_tag)
552{
553 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
554
555 if (ep->header == TI_DEAD_EEPROM_MAGIC)
556 return false;
557 return !strncmp(ep->name, name_tag, AM6_EEPROM_HDR_NAME_LEN);
558}
559
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600560bool __maybe_unused board_ti_is(char *name_tag)
561{
562 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
563
564 if (ep->header == TI_DEAD_EEPROM_MAGIC)
565 return false;
566 return !strncmp(ep->name, name_tag, TI_EEPROM_HDR_NAME_LEN);
567}
568
569bool __maybe_unused board_ti_rev_is(char *rev_tag, int cmp_len)
570{
571 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
572 int l;
573
574 if (ep->header == TI_DEAD_EEPROM_MAGIC)
575 return false;
576
577 l = cmp_len > TI_EEPROM_HDR_REV_LEN ? TI_EEPROM_HDR_REV_LEN : cmp_len;
578 return !strncmp(ep->version, rev_tag, l);
579}
580
581char * __maybe_unused board_ti_get_rev(void)
582{
583 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
584
Nishanth Menon23afc8a2016-10-11 12:39:05 -0500585 /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600586 return ep->version;
587}
588
589char * __maybe_unused board_ti_get_config(void)
590{
591 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
592
Nishanth Menon23afc8a2016-10-11 12:39:05 -0500593 /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600594 return ep->config;
595}
596
597char * __maybe_unused board_ti_get_name(void)
598{
599 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
600
Nishanth Menon23afc8a2016-10-11 12:39:05 -0500601 /* if ep->header == TI_DEAD_EEPROM_MAGIC, this is empty already */
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600602 return ep->name;
603}
604
605void __maybe_unused
606board_ti_get_eth_mac_addr(int index,
607 u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
608{
609 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
610
611 if (ep->header == TI_DEAD_EEPROM_MAGIC)
612 goto fail;
613
614 if (index < 0 || index >= TI_EEPROM_HDR_NO_OF_MAC_ADDR)
615 goto fail;
616
617 memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
618 return;
619
620fail:
621 memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
622}
623
Andreas Dannenberg5a647112019-06-04 18:08:25 -0500624void __maybe_unused
625board_ti_am6_get_eth_mac_addr(int index,
626 u8 mac_addr[TI_EEPROM_HDR_ETH_ALEN])
627{
628 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
629
630 if (ep->header == TI_DEAD_EEPROM_MAGIC)
631 goto fail;
632
633 if (index < 0 || index >= ep->mac_addr_cnt)
634 goto fail;
635
636 memcpy(mac_addr, ep->mac_addr[index], TI_EEPROM_HDR_ETH_ALEN);
637 return;
638
639fail:
640 memset(mac_addr, 0, TI_EEPROM_HDR_ETH_ALEN);
641}
642
Lokesh Vutla7c08a782016-03-08 09:18:04 +0530643u64 __maybe_unused board_ti_get_emif1_size(void)
644{
645 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
646
647 if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
648 return 0;
649
650 return ep->emif1_size;
651}
652
653u64 __maybe_unused board_ti_get_emif2_size(void)
654{
655 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
656
657 if (ep->header != DRA7_EEPROM_HEADER_MAGIC)
658 return 0;
659
660 return ep->emif2_size;
661}
662
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600663void __maybe_unused set_board_info_env(char *name)
664{
665 char *unknown = "unknown";
666 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
667
668 if (name)
Simon Glass6a38e412017-08-03 12:22:09 -0600669 env_set("board_name", name);
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600670 else if (ep->name)
Simon Glass6a38e412017-08-03 12:22:09 -0600671 env_set("board_name", ep->name);
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600672 else
Simon Glass6a38e412017-08-03 12:22:09 -0600673 env_set("board_name", unknown);
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600674
675 if (ep->version)
Simon Glass6a38e412017-08-03 12:22:09 -0600676 env_set("board_rev", ep->version);
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600677 else
Simon Glass6a38e412017-08-03 12:22:09 -0600678 env_set("board_rev", unknown);
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600679
680 if (ep->serial)
Simon Glass6a38e412017-08-03 12:22:09 -0600681 env_set("board_serial", ep->serial);
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600682 else
Simon Glass6a38e412017-08-03 12:22:09 -0600683 env_set("board_serial", unknown);
Lokesh Vutla35f7a972016-02-24 12:30:54 -0600684}
Roger Quadros44c7d9a2017-03-14 15:04:19 +0200685
Andreas Dannenbergf998a822019-06-04 18:08:24 -0500686void __maybe_unused set_board_info_env_am6(char *name)
687{
688 char *unknown = "unknown";
689 struct ti_am6_eeprom *ep = TI_AM6_EEPROM_DATA;
690
691 if (name)
692 env_set("board_name", name);
693 else if (ep->name)
694 env_set("board_name", ep->name);
695 else
696 env_set("board_name", unknown);
697
698 if (ep->version)
699 env_set("board_rev", ep->version);
700 else
701 env_set("board_rev", unknown);
702
703 if (ep->software_revision)
704 env_set("board_software_revision", ep->software_revision);
705 else
706 env_set("board_software_revision", unknown);
707
708 if (ep->serial)
709 env_set("board_serial", ep->serial);
710 else
711 env_set("board_serial", unknown);
712}
713
Roger Quadros44c7d9a2017-03-14 15:04:19 +0200714static u64 mac_to_u64(u8 mac[6])
715{
716 int i;
717 u64 addr = 0;
718
719 for (i = 0; i < 6; i++) {
720 addr <<= 8;
721 addr |= mac[i];
722 }
723
724 return addr;
725}
726
727static void u64_to_mac(u64 addr, u8 mac[6])
728{
729 mac[5] = addr;
730 mac[4] = addr >> 8;
731 mac[3] = addr >> 16;
732 mac[2] = addr >> 24;
733 mac[1] = addr >> 32;
734 mac[0] = addr >> 40;
735}
736
737void board_ti_set_ethaddr(int index)
738{
739 uint8_t mac_addr[6];
740 int i;
741 u64 mac1, mac2;
742 u8 mac_addr1[6], mac_addr2[6];
743 int num_macs;
744 /*
745 * Export any Ethernet MAC addresses from EEPROM.
746 * The 2 MAC addresses in EEPROM define the address range.
747 */
748 board_ti_get_eth_mac_addr(0, mac_addr1);
749 board_ti_get_eth_mac_addr(1, mac_addr2);
750
751 if (is_valid_ethaddr(mac_addr1) && is_valid_ethaddr(mac_addr2)) {
752 mac1 = mac_to_u64(mac_addr1);
753 mac2 = mac_to_u64(mac_addr2);
754
755 /* must contain an address range */
756 num_macs = mac2 - mac1 + 1;
757 if (num_macs <= 0)
758 return;
759
760 if (num_macs > 50) {
761 printf("%s: Too many MAC addresses: %d. Limiting to 50\n",
762 __func__, num_macs);
763 num_macs = 50;
764 }
765
766 for (i = 0; i < num_macs; i++) {
767 u64_to_mac(mac1 + i, mac_addr);
768 if (is_valid_ethaddr(mac_addr)) {
Simon Glass8551d552017-08-03 12:22:11 -0600769 eth_env_set_enetaddr_by_index("eth", i + index,
770 mac_addr);
Roger Quadros44c7d9a2017-03-14 15:04:19 +0200771 }
772 }
773 }
774}
Cooper Jr., Frankline1328c72017-06-16 17:25:08 -0500775
Andreas Dannenberg5a647112019-06-04 18:08:25 -0500776void board_ti_am6_set_ethaddr(int index, int count)
777{
778 u8 mac_addr[6];
779 int i;
780
781 for (i = 0; i < count; i++) {
782 board_ti_am6_get_eth_mac_addr(i, mac_addr);
783 if (is_valid_ethaddr(mac_addr))
784 eth_env_set_enetaddr_by_index("eth", i + index,
785 mac_addr);
786 }
787}
788
Cooper Jr., Frankline1328c72017-06-16 17:25:08 -0500789bool __maybe_unused board_ti_was_eeprom_read(void)
790{
791 struct ti_common_eeprom *ep = TI_EEPROM_DATA;
792
793 if (ep->header == TI_EEPROM_HEADER_MAGIC)
794 return true;
795 else
796 return false;
797}