Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include "types.h"
#include "i2c.h"
#include "eeprom.h"
#include "board.h"
#include "syscon.h"
/*
* The SFP section is placed somewhere inside FMC EEPROM and it really does not
* matter where (can be a binary data inside the Board Info section but can be
* placed also outside the FMC standardized EEPROM structure. The only requirement
* is that it starts with 0xdeadbeef pattern. The structure of SFP section is:
*
* --------------------------------
* | 0xdeadbeef (4B) | count (4B) |
* -------------------------------------------------------------------------------
* | SFP(1) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) |
* -------------------------------------------------------------------------------
* | SFP(2) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) |
* -------------------------------------------------------------------------------
* | (....) | (....) | (....) | (....) |
* -------------------------------------------------------------------------------
* | SFP(count) part number (16B) | alpha (4B) | deltaTx (4B) | deltaRx (4B) |
* -------------------------------------------------------------------------------
* | checksum (1B) |
* -----------------
*
* Fields description:
* count - how many SFPs are described in the list (binary)
* SFP(n) part number - SFP PN as read from SFP's EEPROM (e.g. AXGE-1254-0531)
* (16 ascii chars)
* checksum - low order 8 bits of the sum of all bytes starting from
* _count_ (without 0xdeadbeef)
*
*/
int eeprom_read(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
{
int i;
unsigned char c;
mi2c_start(i2cif);
if(mi2c_put_byte(i2cif, i2c_addr << 1) < 0)
{
mi2c_stop(i2cif);
return -1;
}
mi2c_put_byte(i2cif, (offset>>8) & 0xff);
mi2c_put_byte(i2cif, offset & 0xff);
mi2c_repeat_start(i2cif);
mi2c_put_byte(i2cif, (i2c_addr << 1) | 1);
for(i=0; i<size-1; ++i)
{
mi2c_get_byte(i2cif, &c, 0);
*buf++ = c;
}
mi2c_get_byte(i2cif, &c, 1);
*buf++ = c;
mi2c_stop(i2cif);
return size;
}
//int eeprom_write(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, uint8_t *buf, size_t size)
//{
// int i, busy;
//
// for(i=0;i<size;i++)
// {
// mi2c_start(i2cif);
//
// if(mi2c_put_byte(i2cif, i2c_addr << 1) < 0)
// {
// mi2c_stop(i2cif);
// return -1;
// }
// mi2c_put_byte(i2cif, (offset >> 8) & 0xff);
// mi2c_put_byte(i2cif, offset & 0xff);
// mi2c_put_byte(i2cif, *buf++);
// offset++;
// mi2c_stop(i2cif);
//
// do /* wait until the chip becomes ready */
// {
// mi2c_start(i2cif);
// busy = mi2c_put_byte(i2cif, i2c_addr << 1);
// mi2c_stop(i2cif);
// } while(busy);
//
// }
// return size;
//}
int32_t eeprom_sfp_section(uint8_t i2cif, uint8_t i2c_addr, size_t size, uint16_t *section_sz)
{
uint8_t c, match;
uint16_t i;
uint32_t sfp_pattern = SFP_SECTION_PATTERN;
match = 0x00;
*section_sz = 0x0000;
mi2c_start(i2cif);
if(mi2c_put_byte(i2cif, i2c_addr << 1) != 0)
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
{
mi2c_stop(i2cif);
return -1;
}
mi2c_put_byte(i2cif, 0x00);
mi2c_put_byte(i2cif, 0x00);
mi2c_repeat_start(i2cif);
mi2c_put_byte(i2cif, (i2c_addr << 1) | 1);
for(i=0; i<size-1; ++i)
{
mi2c_get_byte(i2cif, &c, 0);
if(match==0x0f)
{
*section_sz = ((uint16_t)c ) << 8;
match |= 0x10;
}
else if(match==0x1f)
{
*section_sz |= ((uint16_t)c ) & 0xff;
match |= 0x20;
}
else if( c== (uint8_t)(sfp_pattern>>24) )
match = 0x01;
else if( c== (uint8_t)((sfp_pattern>>16)&0xff) )
match |= 0x02;
else if( c== (uint8_t)((sfp_pattern>>8)&0xff) )
match |= 0x04;
else if( c== (uint8_t)(sfp_pattern&0xff) )
match |= 0x08;
else
match = 0x00;
if(match == 0x3f)
{
mi2c_get_byte(i2cif, &c, 1);
mi2c_stop(i2cif);
return i+1; //first address of first SFP in the list
}
}
mi2c_get_byte(i2cif, &c, 1);
mi2c_stop(i2cif);
return 0;
}
int8_t eeprom_get_sfpinfo(uint8_t i2cif, uint8_t i2c_addr, uint32_t offset, struct s_sfpinfo *sfpinfo, uint16_t section_sz)
{
uint8_t *buf;
uint32_t i;
uint8_t checksum, sum;
buf = (uint8_t *)sfpinfo;
eeprom_read(i2cif, i2c_addr, offset, buf, section_sz * sizeof(struct s_sfpinfo));
//read checksum
eeprom_read(i2cif, i2c_addr, offset+section_sz*sizeof(struct s_sfpinfo), &checksum, 1);
//count checksum
sum = (uint8_t) (section_sz>>8 & 0xff);
sum = (uint8_t) ((uint16_t) sum + (section_sz & 0xff)) & 0xff;
for(i=0; i<section_sz*sizeof(struct s_sfpinfo); ++i)
sum = (uint8_t) ((uint16_t)sum + *(buf+i)) & 0xff;
if(sum == checksum)
{
mprintf("%s: checksum match\n", __FUNCTION__);
return 0;
}
else
{
mprintf("%s: checksum error, %x | %x\n", __FUNCTION__, sum, checksum);
return -1;
}
}
int8_t access_eeprom(char *sfp_pn, int32_t *alpha, int32_t *deltaTx, int32_t *deltaRx)
{
uint16_t i;
uint8_t j;
uint16_t sfp_sz;
int32_t sfp_adr;
struct s_sfpinfo sfpinfo[SFPINFO_MAX];
mi2c_init(WRPC_FMC_I2C);
sfp_adr = eeprom_sfp_section(WRPC_FMC_I2C, FMC_EEPROM_ADR, 64*1024, &sfp_sz);
{
mprintf("FMC EEPROM not found\n");
return -1;
}
else if(sfp_sz > SFPINFO_MAX)
{
//Ooops, there are too many of them, print warning
mprintf("! Warning ! too many SFP entries (%d)\n", sfp_sz);
sfp_sz = SFPINFO_MAX;
}
mprintf("EEPROM: found SFP section at %d size %d\n", (uint32_t)sfp_adr, (uint32_t)sfp_sz);
if( eeprom_get_sfpinfo(WRPC_FMC_I2C, FMC_EEPROM_ADR, sfp_adr, sfpinfo, sfp_sz))
{
return -1;
}
for(i=0; i<sfp_sz; ++i)
{
for(j=0; j<16; ++j)
{
if(sfp_pn[j] != sfpinfo[i].pn[j])
break;
}
if( j==16 ) //which means sfp_pn = sfpinfo[i].pn
{
mprintf("match SFP%d: pn=", i+1);
for(j=0; j<16; ++j)
mprintf("%c", sfpinfo[i].pn[j]);
//mprintf(" alpha=%x deltaTx=%x deltaRx=%x\n", sfpinfo[i].alpha, sfpinfo[i].deltaTx, sfpinfo[i].deltaRx);