blob: 32551af5b4074481362bff11cb0757d3a4802254 [file] [log] [blame]
Mathieu Othacehe2415f1d2023-12-29 11:55:23 +01001// 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}