3 * Read FactorySet information from EEPROM into global structure.
4 * (C) Copyright 2013 Siemens Schweiz AG
6 * SPDX-License-Identifier: GPL-2.0+
9 #if !defined(CONFIG_SPL_BUILD)
14 #include <asm/arch/cpu.h>
15 #include <asm/arch/sys_proto.h>
16 #include <asm/unaligned.h>
20 #include "factoryset.h"
22 #define EEPR_PG_SZ 0x80
23 #define EEPROM_FATORYSET_OFFSET 0x400
24 #define OFF_PG EEPROM_FATORYSET_OFFSET/EEPR_PG_SZ
26 /* Global variable that contains necessary information from FactorySet */
27 struct factorysetcontainer factory_dat
;
29 #define fact_get_char(i) *((char *)&eeprom_buf[i])
31 static int fact_match(unsigned char *eeprom_buf
, uchar
*s1
, int i2
)
36 while (*s1
== fact_get_char(i2
++))
40 if (*s1
== '\0' && fact_get_char(i2
-1) == '=')
46 static int get_factory_val(unsigned char *eeprom_buf
, int size
, uchar
*name
,
51 for (i
= 0; fact_get_char(i
) != '\0'; i
= nxt
+ 1) {
54 for (nxt
= i
; fact_get_char(nxt
) != '\0'; ++nxt
) {
59 val
= fact_match(eeprom_buf
, (uchar
*)name
, i
);
64 for (n
= 0; n
< len
; ++n
, ++buf
) {
65 *buf
= fact_get_char(val
++);
73 printf("env_buf [%d bytes] too small for value of \"%s\"\n",
82 int get_factory_record_val(unsigned char *eeprom_buf
, int size
, uchar
*record
,
83 uchar
*name
, uchar
*buf
, int len
)
88 unsigned char end
= 0xff;
91 for (i
= 0; fact_get_char(i
) != end
; i
= nxt
) {
93 if (fact_get_char(i
) == '>') {
99 c
= strncmp((char *)&eeprom_buf
[i
+ 1], (char *)record
,
100 strlen((char *)record
));
103 pos
= i
+ strlen((char *)record
) + 2;
107 for (z
= pos
; fact_get_char(z
) != end
; z
++) {
108 if (fact_get_char(z
) == '<') {
118 if (fact_get_char(z
) == '>')
125 /* end found -> call get_factory_val */
126 tmp
= eeprom_buf
[endpos
];
127 eeprom_buf
[endpos
] = end
;
128 ret
= get_factory_val(&eeprom_buf
[pos
],
129 endpos
- pos
, name
, buf
, len
);
131 eeprom_buf
[endpos
] = tmp
;
132 debug("%s: %s.%s = %s\n",
133 __func__
, record
, name
, buf
);
141 int factoryset_read_eeprom(int i2c_addr
)
143 int i
, pages
= 0, size
= 0;
144 unsigned char eeprom_buf
[0x3c00], hdr
[4], buf
[MAX_STRING_LENGTH
];
145 unsigned char *cp
, *cp1
;
147 #if defined(CONFIG_USB_FUNCTION_DFU)
148 factory_dat
.usb_vendor_id
= CONFIG_USB_GADGET_VENDOR_NUM
;
149 factory_dat
.usb_product_id
= CONFIG_USB_GADGET_PRODUCT_NUM
;
151 if (i2c_probe(i2c_addr
))
154 if (i2c_read(i2c_addr
, EEPROM_FATORYSET_OFFSET
, 2, hdr
, sizeof(hdr
)))
157 if ((hdr
[0] != 0x99) || (hdr
[1] != 0x80)) {
158 printf("FactorySet is not right in eeprom.\n");
162 /* get FactorySet size */
163 size
= (hdr
[2] << 8) + hdr
[3] + sizeof(hdr
);
167 pages
= size
/ EEPR_PG_SZ
;
170 * read the eeprom using i2c
171 * I can not read entire eeprom in once, so separate into several
172 * times. Furthermore, fetch eeprom take longer time, so we fetch
173 * data after every time we got a record from eeprom
175 debug("Read eeprom page :\n");
176 for (i
= 0; i
< pages
; i
++)
177 if (i2c_read(i2c_addr
, (OFF_PG
+ i
) * EEPR_PG_SZ
, 2,
178 eeprom_buf
+ (i
* EEPR_PG_SZ
), EEPR_PG_SZ
))
181 if (size
% EEPR_PG_SZ
)
182 if (i2c_read(i2c_addr
, (OFF_PG
+ pages
) * EEPR_PG_SZ
, 2,
183 eeprom_buf
+ (pages
* EEPR_PG_SZ
),
184 (size
% EEPR_PG_SZ
)))
187 /* we do below just for eeprom align */
188 for (i
= 0; i
< size
; i
++)
189 if (eeprom_buf
[i
] == '\n')
194 cp
= (uchar
*)eeprom_buf
+ sizeof(hdr
);
196 /* get mac address */
197 get_factory_record_val(cp
, size
, (uchar
*)"ETH1", (uchar
*)"mac",
198 buf
, MAX_STRING_LENGTH
);
200 for (i
= 0; i
< 6; i
++) {
201 factory_dat
.mac
[i
] = simple_strtoul((char *)cp1
, NULL
, 16);
205 #if defined(CONFIG_USB_FUNCTION_DFU)
206 /* read vid and pid for dfu mode */
207 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"USBD1",
209 MAX_STRING_LENGTH
)) {
210 factory_dat
.usb_vendor_id
= simple_strtoul((char *)buf
,
214 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"USBD1",
216 MAX_STRING_LENGTH
)) {
217 factory_dat
.usb_product_id
= simple_strtoul((char *)buf
,
220 printf("DFU USB: VID = 0x%4x, PID = 0x%4x\n", factory_dat
.usb_vendor_id
,
221 factory_dat
.usb_product_id
);
223 #if defined(CONFIG_VIDEO)
224 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DISP1",
225 (uchar
*)"name", factory_dat
.disp_name
,
226 MAX_STRING_LENGTH
)) {
227 debug("display name: %s\n", factory_dat
.disp_name
);
230 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DEV",
231 (uchar
*)"num", factory_dat
.serial
,
232 MAX_STRING_LENGTH
)) {
233 debug("serial number: %s\n", factory_dat
.serial
);
235 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DEV",
237 MAX_STRING_LENGTH
)) {
238 factory_dat
.version
= simple_strtoul((char *)buf
,
240 debug("version number: %d\n", factory_dat
.version
);
242 /* Get ASN from factory set if available */
243 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DEV",
244 (uchar
*)"id", factory_dat
.asn
,
245 MAX_STRING_LENGTH
)) {
246 debug("factoryset asn: %s\n", factory_dat
.asn
);
248 factory_dat
.asn
[0] = 0;
250 /* Get COMP/ver from factory set if available */
251 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"COMP",
253 factory_dat
.comp_version
,
254 MAX_STRING_LENGTH
)) {
255 debug("factoryset COMP/ver: %s\n", factory_dat
.comp_version
);
257 strcpy((char *)factory_dat
.comp_version
, "1.0");
263 printf("Could not read the EEPROM; something fundamentally wrong on the I2C bus.\n");
267 static struct ctrl_dev
*cdev
= (struct ctrl_dev
*)CTRL_DEVICE_BASE
;
269 static int factoryset_mac_env_set(void)
273 debug("FactorySet: Set mac address\n");
274 if (is_valid_ethaddr(factory_dat
.mac
)) {
275 memcpy(mac_addr
, factory_dat
.mac
, 6);
277 uint32_t mac_hi
, mac_lo
;
279 debug("Warning: FactorySet: <ethaddr> not set. Fallback to E-fuse\n");
280 mac_lo
= readl(&cdev
->macid0l
);
281 mac_hi
= readl(&cdev
->macid0h
);
283 mac_addr
[0] = mac_hi
& 0xFF;
284 mac_addr
[1] = (mac_hi
& 0xFF00) >> 8;
285 mac_addr
[2] = (mac_hi
& 0xFF0000) >> 16;
286 mac_addr
[3] = (mac_hi
& 0xFF000000) >> 24;
287 mac_addr
[4] = mac_lo
& 0xFF;
288 mac_addr
[5] = (mac_lo
& 0xFF00) >> 8;
289 if (!is_valid_ethaddr(mac_addr
)) {
290 printf("Warning: ethaddr not set by FactorySet or E-fuse. Set <ethaddr> variable to overcome this.\n");
295 eth_env_set_enetaddr("ethaddr", mac_addr
);
299 int factoryset_env_set(void)
303 if (factoryset_mac_env_set() < 0)
309 int g_dnl_bind_fixup(struct usb_device_descriptor
*dev
, const char *name
)
311 put_unaligned(factory_dat
.usb_vendor_id
, &dev
->idVendor
);
312 put_unaligned(factory_dat
.usb_product_id
, &dev
->idProduct
);
313 g_dnl_set_serialnumber((char *)factory_dat
.serial
);
318 int g_dnl_get_board_bcd_device_number(int gcnum
)
320 return factory_dat
.version
;
322 #endif /* defined(CONFIG_SPL_BUILD) */