+// SPDX-License-Identifier: GPL-2.0+
/*
* (C) Copyright 2011
* Holger Brunck, Keymile GmbH Hannover, holger.brunck@keymile.com
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
-#include <hush.h>
+#include <cli_hush.h>
+#include <env.h>
#include <i2c.h>
#include "common.h"
+#define MAC_STR_SZ 20
+
static int ivm_calc_crc(unsigned char *buf, int len)
{
const unsigned short crc_tab[16] = {
{
char tempbuf[256];
- if (value != NULL) {
+ if (value) {
sprintf(tempbuf, "%s=%s", name, value);
return set_local_var(tempbuf, 0);
- } else {
- unset_local_var(name);
}
+ unset_local_var(name);
return 0;
}
static int ivm_get_value(unsigned char *buf, int len, char *name, int off,
- int check)
+ int check)
{
unsigned short val;
unsigned char valbuf[30];
- if ((buf[off + 0] != buf[off + 2]) &&
- (buf[off + 2] != buf[off + 4])) {
+ if (buf[off + 0] != buf[off + 2] &&
+ buf[off + 2] != buf[off + 4]) {
printf("%s Error corrupted %s\n", __func__, name);
val = -1;
} else {
val = buf[off + 0] + (buf[off + 1] << 8);
- if ((val == 0) && (check == 1))
+ if (val == 0 && check == 1)
val = -1;
}
sprintf((char *)valbuf, "%x", val);
}
static int ivm_findinventorystring(int type,
- unsigned char *const string,
- unsigned long maxlen,
- unsigned char *buf)
+ unsigned char *const string,
+ unsigned long maxlen,
+ unsigned char *buf)
{
int xcode = 0;
unsigned long cr = 0;
/* Look for the requested number of CR. */
while ((cr != nr) && (addr < INVENTORYDATASIZE)) {
- if ((buf[addr] == '\r'))
+ if (buf[addr] == '\r')
cr++;
addr++;
}
*/
if (addr < INVENTORYDATASIZE) {
/* Copy the IVM string in the corresponding string */
- for (; (buf[addr] != '\r') &&
- ((buf[addr] != ';') || (!stop)) &&
- (size < (maxlen - 1) &&
- (addr < INVENTORYDATASIZE)); addr++) {
+ for (; (buf[addr] != '\r') &&
+ ((buf[addr] != ';') || (!stop)) &&
+ (size < (maxlen - 1) &&
+ (addr < INVENTORYDATASIZE)); addr++) {
size += sprintf((char *)string + size, "%c",
- convert_char (buf[addr]));
+ convert_char (buf[addr]));
}
/*
unsigned long crceeprom;
crc = ivm_calc_crc(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2);
- crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] + \
+ crceeprom = (buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 1] +
buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN - 2] * 256);
if (crc != crceeprom) {
if (block == 0)
- printf("Error CRC Block: %d EEprom: calculated: \
- %lx EEprom: %lx\n", block, crc, crceeprom);
+ printf("Error CRC Block: %d EEprom: calculated: %lx EEprom: %lx\n",
+ block, crc, crceeprom);
return -1;
}
return 0;
}
-static int calculate_mac_offset(unsigned char *valbuf, unsigned char *buf,
- int offset)
+/* take care of the possible MAC address offset and the IVM content offset */
+static int process_mac(unsigned char *valbuf, unsigned char *buf,
+ int offset, bool unique)
{
+ unsigned char mac[6];
unsigned long val = (buf[4] << 16) + (buf[5] << 8) + buf[6];
- if (offset == 0)
- return 0;
+ /* use an intermediate buffer, to not change IVM content
+ * MAC address is at offset 1
+ */
+ memcpy(mac, buf + 1, 6);
- val += offset;
- buf[4] = (val >> 16) & 0xff;
- buf[5] = (val >> 8) & 0xff;
- buf[6] = val & 0xff;
- sprintf((char *)valbuf, "%pM", buf + 1);
+ /* MAC address can be set to locally administred, this is only allowed
+ * for interfaces which have now connection to the outside. For these
+ * addresses we need to set the second bit in the first byte.
+ */
+ if (!unique)
+ mac[0] |= 0x2;
+
+ if (offset) {
+ val += offset;
+ mac[3] = (val >> 16) & 0xff;
+ mac[4] = (val >> 8) & 0xff;
+ mac[5] = val & 0xff;
+ }
+
+ sprintf((char *)valbuf, "%pM", mac);
return 0;
}
static int ivm_analyze_block2(unsigned char *buf, int len)
{
- unsigned char valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
+ unsigned char valbuf[MAC_STR_SZ];
unsigned long count;
- /* IVM_MAC Adress begins at offset 1 */
+ /* IVM_MAC Address begins at offset 1 */
sprintf((char *)valbuf, "%pM", buf + 1);
ivm_set_value("IVM_MacAddress", (char *)valbuf);
- /* if an offset is defined, add it */
- calculate_mac_offset(buf, valbuf, CONFIG_PIGGY_MAC_ADRESS_OFFSET);
-#ifdef MACH_TYPE_KM_KIRKWOOD
- setenv((char *)"ethaddr", (char *)valbuf);
-#else
- if (getenv("ethaddr") == NULL)
- setenv((char *)"ethaddr", (char *)valbuf);
-#endif
-#ifdef CONFIG_KMVECT1
-/* KMVECT1 has two ethernet interfaces */
- if (getenv("eth1addr") == NULL) {
- calculate_mac_offset(buf, valbuf, 1);
- setenv((char *)"eth1addr", (char *)valbuf);
- }
-#endif
/* IVM_MacCount */
count = (buf[10] << 24) +
(buf[11] << 16) +
return 0;
}
-static int ivm_analyze_eeprom(unsigned char *buf, int len)
+int ivm_analyze_eeprom(unsigned char *buf, int len)
{
unsigned short val;
unsigned char valbuf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN];
return -1;
ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
- "IVM_BoardId", 0, 1);
+ "IVM_BoardId", 0, 1);
val = ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
- "IVM_HWKey", 6, 1);
+ "IVM_HWKey", 6, 1);
if (val != 0xffff) {
sprintf((char *)valbuf, "%x", ((val / 100) % 10));
ivm_set_value("IVM_HWVariant", (char *)valbuf);
ivm_set_value("IVM_HWVersion", (char *)valbuf);
}
ivm_get_value(buf, CONFIG_SYS_IVM_EEPROM_PAGE_LEN,
- "IVM_Functions", 12, 0);
+ "IVM_Functions", 12, 0);
GET_STRING("IVM_Symbol", IVM_POS_SYMBOL_ONLY, 8)
GET_STRING("IVM_DeviceName", IVM_POS_SHORT_TEXT, 64)
- tmp = (unsigned char *) getenv("IVM_DeviceName");
+ tmp = (unsigned char *)env_get("IVM_DeviceName");
if (tmp) {
int len = strlen((char *)tmp);
int i = 0;
while (i < len) {
if (tmp[i] == ';') {
ivm_set_value("IVM_ShortText",
- (char *)&tmp[i + 1]);
+ (char *)&tmp[i + 1]);
break;
}
i++;
if (ivm_check_crc(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2], 2) != 0)
return 0;
ivm_analyze_block2(&buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2],
- CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
+ CONFIG_SYS_IVM_EEPROM_PAGE_LEN);
+
+ return 0;
+}
+
+static int ivm_populate_env(unsigned char *buf, int len, int mac_address_offset)
+{
+ unsigned char *page2;
+ unsigned char valbuf[MAC_STR_SZ];
+
+ /* do we have the page 2 filled ? if not return */
+ if (ivm_check_crc(buf, 2))
+ return 0;
+ page2 = &buf[CONFIG_SYS_IVM_EEPROM_PAGE_LEN * 2];
+
+ if (IS_ENABLED(CONFIG_KMTEGR1)) {
+ /* KMTEGR1 has a special setup. eth0 has no connection to the
+ * outside and gets an locally administred MAC address, eth1 is
+ * the debug interface and gets the official MAC address from
+ * the IVM
+ */
+ process_mac(valbuf, page2, mac_address_offset, false);
+ env_set((char *)"ethaddr", (char *)valbuf);
+ process_mac(valbuf, page2, mac_address_offset, true);
+ env_set((char *)"eth1addr", (char *)valbuf);
+ } else if (IS_ENABLED(CONFIG_ARCH_LS1021A)) {
+ /* LS102xA has 1xRGMII for debug connection and
+ * 2xSGMII for back-plane mgmt connection
+ */
+ process_mac(valbuf, page2, 1, true);
+ env_set((char *)"ethaddr", (char *)valbuf);
+ process_mac(valbuf, page2, 2, true);
+ env_set((char *)"eth1addr", (char *)valbuf);
+ process_mac(valbuf, page2, mac_address_offset, true);
+ env_set((char *)"eth2addr", (char *)valbuf);
+ } else {
+ process_mac(valbuf, page2, mac_address_offset, true);
+ env_set((char *)"ethaddr", (char *)valbuf);
+ }
+ if (IS_ENABLED(CONFIG_TARGET_KMCENT2)) {
+ /* 3rd ethernet interface */
+ process_mac(valbuf, page2, 2, true);
+ env_set((char *)"eth4addr", (char *)valbuf);
+ }
return 0;
}
-int ivm_read_eeprom(void)
+int ivm_read_eeprom(unsigned char *buf, int len, int mac_address_offset)
{
- uchar i2c_buffer[CONFIG_SYS_IVM_EEPROM_MAX_LEN];
int ret;
+#if CONFIG_IS_ENABLED(DM_I2C)
+ struct udevice *eedev = NULL;
+
+ ret = i2c_get_chip_for_busnum(CONFIG_KM_IVM_BUS,
+ CONFIG_SYS_I2C_EEPROM_ADDR, 1, &eedev);
+ if (ret) {
+ printf("failed to get device for EEPROM at address 0x%02x\n",
+ CONFIG_SYS_I2C_EEPROM_ADDR);
+ return 1;
+ }
+ ret = dm_i2c_read(eedev, 0, buf, len);
+ if (ret != 0) {
+ printf("Error: Unable to read from I2C EEPROM at address %02X:%02X\n",
+ CONFIG_SYS_I2C_EEPROM_ADDR, 0);
+ return 1;
+ }
+#else
i2c_set_bus_num(CONFIG_KM_IVM_BUS);
/* add deblocking here */
i2c_make_abort();
- ret = i2c_read(CONFIG_SYS_IVM_EEPROM_ADR, 0, 1, i2c_buffer,
- CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+ ret = i2c_read(CONFIG_SYS_IVM_EEPROM_ADR, 0, 1, buf, len);
if (ret != 0) {
printf("Error reading EEprom\n");
return -2;
}
-
- return ivm_analyze_eeprom(i2c_buffer, CONFIG_SYS_IVM_EEPROM_MAX_LEN);
+#endif
+ return ivm_populate_env(buf, len, mac_address_offset);
}