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;
90 for (i
= 0; fact_get_char(i
) != end
; i
= nxt
) {
92 if (fact_get_char(i
) == '>') {
97 c
= strncmp((char *)&eeprom_buf
[i
+ 1], (char *)record
,
98 strlen((char *)record
));
101 pos
= i
+ strlen((char *)record
) + 2;
105 for (z
= pos
; fact_get_char(z
) != end
; z
++) {
106 if ((fact_get_char(z
) == '<') ||
107 (fact_get_char(z
) == '>')) {
116 /* end found -> call get_factory_val */
117 eeprom_buf
[endpos
] = end
;
118 ret
= get_factory_val(&eeprom_buf
[pos
],
119 size
- pos
, name
, buf
, len
);
121 eeprom_buf
[endpos
] = '<';
122 debug("%s: %s.%s = %s\n",
123 __func__
, record
, name
, buf
);
131 int factoryset_read_eeprom(int i2c_addr
)
133 int i
, pages
= 0, size
= 0;
134 unsigned char eeprom_buf
[0x3c00], hdr
[4], buf
[MAX_STRING_LENGTH
];
135 unsigned char *cp
, *cp1
;
137 #if defined(CONFIG_DFU_FUNCTION)
138 factory_dat
.usb_vendor_id
= CONFIG_G_DNL_VENDOR_NUM
;
139 factory_dat
.usb_product_id
= CONFIG_G_DNL_PRODUCT_NUM
;
141 if (i2c_probe(i2c_addr
))
144 if (i2c_read(i2c_addr
, EEPROM_FATORYSET_OFFSET
, 2, hdr
, sizeof(hdr
)))
147 if ((hdr
[0] != 0x99) || (hdr
[1] != 0x80)) {
148 printf("FactorySet is not right in eeprom.\n");
152 /* get FactorySet size */
153 size
= (hdr
[2] << 8) + hdr
[3] + sizeof(hdr
);
157 pages
= size
/ EEPR_PG_SZ
;
160 * read the eeprom using i2c
161 * I can not read entire eeprom in once, so separate into several
162 * times. Furthermore, fetch eeprom take longer time, so we fetch
163 * data after every time we got a record from eeprom
165 debug("Read eeprom page :\n");
166 for (i
= 0; i
< pages
; i
++)
167 if (i2c_read(i2c_addr
, (OFF_PG
+ i
) * EEPR_PG_SZ
, 2,
168 eeprom_buf
+ (i
* EEPR_PG_SZ
), EEPR_PG_SZ
))
171 if (size
% EEPR_PG_SZ
)
172 if (i2c_read(i2c_addr
, (OFF_PG
+ pages
) * EEPR_PG_SZ
, 2,
173 eeprom_buf
+ (pages
* EEPR_PG_SZ
),
174 (size
% EEPR_PG_SZ
)))
177 /* we do below just for eeprom align */
178 for (i
= 0; i
< size
; i
++)
179 if (eeprom_buf
[i
] == '\n')
184 cp
= (uchar
*)eeprom_buf
+ sizeof(hdr
);
186 /* get mac address */
187 get_factory_record_val(cp
, size
, (uchar
*)"ETH1", (uchar
*)"mac",
188 buf
, MAX_STRING_LENGTH
);
190 for (i
= 0; i
< 6; i
++) {
191 factory_dat
.mac
[i
] = simple_strtoul((char *)cp1
, NULL
, 16);
195 #if defined(CONFIG_DFU_FUNCTION)
196 /* read vid and pid for dfu mode */
197 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"USBD1",
199 MAX_STRING_LENGTH
)) {
200 factory_dat
.usb_vendor_id
= simple_strtoul((char *)buf
,
204 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"USBD1",
206 MAX_STRING_LENGTH
)) {
207 factory_dat
.usb_product_id
= simple_strtoul((char *)buf
,
210 printf("DFU USB: VID = 0x%4x, PID = 0x%4x\n", factory_dat
.usb_vendor_id
,
211 factory_dat
.usb_product_id
);
213 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DEV",
215 MAX_STRING_LENGTH
)) {
216 if (strncmp((const char *)buf
, "PXM50", 5) == 0)
217 factory_dat
.pxm50
= 1;
219 factory_dat
.pxm50
= 0;
221 debug("PXM50: %d\n", factory_dat
.pxm50
);
222 #if defined(CONFIG_VIDEO)
223 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DISP1",
224 (uchar
*)"name", factory_dat
.disp_name
,
225 MAX_STRING_LENGTH
)) {
226 debug("display name: %s\n", factory_dat
.disp_name
);
229 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DEV",
230 (uchar
*)"num", factory_dat
.serial
,
231 MAX_STRING_LENGTH
)) {
232 debug("serial number: %s\n", factory_dat
.serial
);
234 if (0 <= get_factory_record_val(cp
, size
, (uchar
*)"DEV",
236 MAX_STRING_LENGTH
)) {
237 factory_dat
.version
= simple_strtoul((char *)buf
,
239 debug("version number: %d\n", factory_dat
.version
);
245 printf("Could not read the EEPROM; something fundamentally wrong on the I2C bus.\n");
249 static struct ctrl_dev
*cdev
= (struct ctrl_dev
*)CTRL_DEVICE_BASE
;
251 static int factoryset_mac_setenv(void)
255 debug("FactorySet: Set mac address\n");
256 if (is_valid_ether_addr(factory_dat
.mac
)) {
257 memcpy(mac_addr
, factory_dat
.mac
, 6);
259 uint32_t mac_hi
, mac_lo
;
261 debug("Warning: FactorySet: <ethaddr> not set. Fallback to E-fuse\n");
262 mac_lo
= readl(&cdev
->macid0l
);
263 mac_hi
= readl(&cdev
->macid0h
);
265 mac_addr
[0] = mac_hi
& 0xFF;
266 mac_addr
[1] = (mac_hi
& 0xFF00) >> 8;
267 mac_addr
[2] = (mac_hi
& 0xFF0000) >> 16;
268 mac_addr
[3] = (mac_hi
& 0xFF000000) >> 24;
269 mac_addr
[4] = mac_lo
& 0xFF;
270 mac_addr
[5] = (mac_lo
& 0xFF00) >> 8;
271 if (!is_valid_ether_addr(mac_addr
)) {
272 printf("Warning: ethaddr not set by FactorySet or E-fuse. Set <ethaddr> variable to overcome this.\n");
277 eth_setenv_enetaddr("ethaddr", mac_addr
);
281 int factoryset_setenv(void)
285 if (factoryset_mac_setenv() < 0)
291 int g_dnl_bind_fixup(struct usb_device_descriptor
*dev
, const char *name
)
293 put_unaligned(factory_dat
.usb_vendor_id
, &dev
->idVendor
);
294 put_unaligned(factory_dat
.usb_product_id
, &dev
->idProduct
);
295 g_dnl_set_serialnumber((char *)factory_dat
.serial
);
300 int g_dnl_get_board_bcd_device_number(int gcnum
)
302 return factory_dat
.version
;
304 #endif /* defined(CONFIG_SPL_BUILD) */