1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2023 Variscite Ltd. 4 * 5 */ 6#include <command.h> 7#include <dm.h> 8#include <i2c.h> 9#include <asm/io.h> 10#include <cpu_func.h> 11#include <u-boot/crc.h> 12#include <asm/arch-imx9/ddr.h> 13 14#include "imx9_eeprom.h" 15 16static int var_eeprom_get_dev(struct udevice **devp) 17{ 18 int ret; 19 struct udevice *bus; 20 21 ret = uclass_get_device_by_name(UCLASS_I2C, VAR_SOM_EEPROM_I2C_NAME, &bus); 22 if (ret) { 23 printf("%s: No EEPROM I2C bus '%s'\n", __func__, 24 VAR_SOM_EEPROM_I2C_NAME); 25 return ret; 26 } 27 28 ret = dm_i2c_probe(bus, VAR_SOM_EEPROM_I2C_ADDR, 0, devp); 29 if (ret) { 30 printf("%s: I2C EEPROM probe failed\n", __func__); 31 return ret; 32 } 33 34 i2c_set_chip_offset_len(*devp, 1); 35 i2c_set_chip_addr_offset_mask(*devp, 1); 36 37 return 0; 38} 39 40int var_eeprom_read_header(struct var_eeprom *e) 41{ 42 int ret; 43 struct udevice *dev; 44 45 ret = var_eeprom_get_dev(&dev); 46 if (ret) { 47 printf("%s: Failed to detect I2C EEPROM\n", __func__); 48 return ret; 49 } 50 51 /* Read EEPROM header to memory */ 52 ret = dm_i2c_read(dev, 0, (void *)e, sizeof(*e)); 53 if (ret) { 54 printf("%s: EEPROM read failed, ret=%d\n", __func__, ret); 55 return ret; 56 } 57 58 return 0; 59} 60 61int var_eeprom_get_mac(struct var_eeprom *ep, u8 *mac) 62{ 63 flush_dcache_all(); 64 if (!var_eeprom_is_valid(ep)) 65 return -1; 66 67 memcpy(mac, ep->mac, sizeof(ep->mac)); 68 69 return 0; 70} 71 72int var_eeprom_get_dram_size(struct var_eeprom *ep, phys_size_t *size) 73{ 74 /* No data in EEPROM - return default DRAM size */ 75 if (!var_eeprom_is_valid(ep)) { 76 *size = DEFAULT_SDRAM_SIZE; 77 return 0; 78 } 79 80 *size = (ep->dramsize * 128UL) << 20; 81 return 0; 82} 83 84void var_eeprom_print_prod_info(struct var_eeprom *ep) 85{ 86 if (IS_ENABLED(CONFIG_SPL_BUILD)) 87 return; 88 89 flush_dcache_all(); 90 91 if (!var_eeprom_is_valid(ep)) 92 return; 93 94 if (IS_ENABLED(CONFIG_TARGET_IMX93_VAR_SOM)) 95 printf("\nPart number: VSM-MX93-%.*s\n", 96 (int)sizeof(ep->partnum), ep->partnum); 97 98 printf("Assembly: AS%.*s\n", (int)sizeof(ep->assembly), (char *)ep->assembly); 99 100 printf("Production date: %.*s %.*s %.*s\n", 101 4, /* YYYY */ 102 (char *)ep->date, 103 3, /* MMM */ 104 ((char *)ep->date) + 4, 105 2, /* DD */ 106 ((char *)ep->date) + 4 + 3); 107 108 printf("Serial Number: %02x:%02x:%02x:%02x:%02x:%02x\n", 109 ep->mac[0], ep->mac[1], ep->mac[2], ep->mac[3], ep->mac[4], ep->mac[5]); 110 111 debug("EEPROM version: 0x%x\n", ep->version); 112 debug("SOM features: 0x%x\n", ep->features); 113 printf("SOM revision: 0x%x\n", ep->somrev); 114 printf("DRAM PN: VIC-%04d\n", ep->ddr_vic); 115 debug("DRAM size: %d GiB\n\n", (ep->dramsize * 128) / 1024); 116} 117 118int var_carrier_eeprom_read(const char *bus_name, int addr, struct var_carrier_eeprom *ep) 119{ 120 int ret; 121 struct udevice *bus; 122 struct udevice *dev; 123 124 ret = uclass_get_device_by_name(UCLASS_I2C, bus_name, &bus); 125 if (ret) { 126 printf("%s: No bus '%s'\n", __func__, bus_name); 127 return ret; 128 } 129 130 ret = dm_i2c_probe(bus, addr, 0, &dev); 131 if (ret) { 132 printf("%s: Carrier EEPROM I2C probe failed\n", __func__); 133 return ret; 134 } 135 136 /* Read EEPROM to memory */ 137 ret = dm_i2c_read(dev, 0, (void *)ep, sizeof(*ep)); 138 if (ret) { 139 printf("%s: Carrier EEPROM read failed, ret=%d\n", __func__, ret); 140 return ret; 141 } 142 143 return 0; 144} 145 146int var_carrier_eeprom_is_valid(struct var_carrier_eeprom *ep) 147{ 148 u32 crc, crc_offset = offsetof(struct var_carrier_eeprom, crc); 149 150 if (htons(ep->magic) != VAR_CARRIER_EEPROM_MAGIC) { 151 printf("Invalid carrier EEPROM magic 0x%x, expected 0x%x\n", 152 htons(ep->magic), VAR_CARRIER_EEPROM_MAGIC); 153 return 0; 154 } 155 156 if (ep->struct_ver < 1) { 157 printf("Invalid carrier EEPROM version 0x%x\n", ep->struct_ver); 158 return 0; 159 } 160 161 if (ep->struct_ver == 1) 162 return 1; 163 164 /* Only EEPROM structure above version 1 has CRC field */ 165 crc = crc32(0, (void *)ep, crc_offset); 166 167 if (crc != ep->crc) { 168 printf("Carrier EEPROM CRC mismatch (%08x != %08x)\n", 169 crc, be32_to_cpu(ep->crc)); 170 return 0; 171 } 172 173 return 1; 174} 175 176/* 177 * Returns carrier board revision string via 'rev' argument. For legacy 178 * carrier board revisions the "legacy" string is returned. For new carrier 179 * board revisions the actual carrier revision is returned. Symphony-Board 180 * 1.4 and below are legacy, 1.4a and above are new. DT8MCustomBoard 1.4 and 181 * below are legacy, 2.0 and above are new. 182 * 183 */ 184void var_carrier_eeprom_get_revision(struct var_carrier_eeprom *ep, char *rev, size_t size) 185{ 186 if (var_carrier_eeprom_is_valid(ep)) 187 strlcpy(rev, (const char *)ep->carrier_rev, size); 188 else 189 strlcpy(rev, "legacy", size); 190} 191