source: PlatformSupport/CustomPeripherals/pcores/w3_iic_eeprom_axi_v1_01_a/src/w3_iic_eeprom.c

Last change on this file was 2480, checked in by welsh, 10 years ago

Updated Ethernet MAC address check.

File size: 11.2 KB
Line 
1/*****************************************************************
2* File: w3_iic_eeprom.c
3* Copyright (c) 2012 Mango Communications, all rights reseved
4* Released under the WARP License
5* See http://warp.rice.edu/license for details
6*****************************************************************/
7
8/** \file w3_iic_eeprom.c
9
10\mainpage
11This is the driver for the w3_iic_eeprom core, which implements an IIC master for accessing
12the EEPROM on the WARP v3 board.
13
14This driver implements functions for reading and writing individual bytes in the EEPROM. Functions
15are also provided for accessing EEPROM entries written during manufacturing (serial number, etc.).
16
17The full EEPROM is readable/writable from user-code. No addresses are write-protected.
18
19Refer to the <a href="http://warp.rice.edu/trac/wiki/HardwareUsersGuides/WARPv3/EEPROM">WARP v3 User Guide</a> for details
20on the data written to the EEPROM during manufacturing.
21
22@version 1.00.b
23@author Patrick Murphy
24@copyright (c) 2012 Mango Communications, Inc. All rights reserved.<br>
25Released under the WARP open source license (see http://warp.rice.edu/license)
26
27\brief Main source for EEPROM controller driver
28
29*/
30
31#include "w3_iic_eeprom.h"
32#include "stdio.h"
33
34/**
35\defgroup user_functions Functions
36\brief Functions to call from user code
37\addtogroup user_functions
38
39Example:
40\code{.c}
41//Assumes user code sets EEPROM_BASEADDR to base address of w3_iic_eeprom core, as set in xparameters.h
42
43int x;
44u32 board_sn;
45
46//Initialize the EEPROM controller at boot
47iic_eeprom_init(EEPROM_BASEADDR, 0x64);
48
49//Write a value to the EEPROM (set EEPROM byte address 2345 to 182)
50x = iic_eeprom_writeByte(EEPROM_BASEADDR, 2345, 182);
51if(x != 0) xil_printf("EEPROM Write Error!\n");
52
53//Read the value back from EEPROM
54x = iic_eeprom_readByte(EEPROM_BASEADDR, 2345);
55if(x != 182) xil_printf("EEPROM Read Error (read %d, should be 182)!\n", x);
56
57//Read the WARP v3 board serial number from the EEPROM
58board_sn = w3_eeprom_readSerialNum(EEPROM_BASEADDDR);
59xil_printf("Board s/n: W3-a-%05d\n", board_sn);
60
61\endcode
62
63@{
64*/
65
66/**
67\brief Initializes the EEPROM controller. This function must be called once at boot before any EEPROM read/write operations.
68\param ba Base memory address of w3_iic_eeprom pcore
69\param clkDiv Clock divider for IIC clock (set 0x64 for 160MHz bus)
70*/
71void iic_eeprom_init(u32 ba, u8 clkDiv)
72{
73    //Configure the IIC master core
74    Xil_Out32(ba+IIC_EEPROM_REG_CMD, 0);
75    Xil_Out32(ba+IIC_EEPROM_REG_CONFIG_STATUS, (IIC_EEPROM_REGMASK_CLKDIV & clkDiv));
76    Xil_Out32(ba+IIC_EEPROM_REG_CONFIG_STATUS, Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS) | IIC_EEPROM_REGMASK_COREEN);
77
78    return;
79}
80
81/**
82\brief Writes one bytes to the EEPROM
83\param ba Base memory address of w3_iic_eeprom pcore
84\param addrToWrite Byte address to write, in [0,16000] (addresses >16000 are reserved)
85\param byteToWrite Byte value to write
86\return Returns 0 if EEPROM write succeeds. Returns -1 if an error occurs.
87*/
88int iic_eeprom_writeByte(u32 ba, u16 addrToWrite, u8 byteToWrite)
89{
90    int writeDone;
91    /* Process to write 1 byte to random address in IIC EEPROM
92        - Write EEPROM control word to Tx register {1 0 1 0 0 0 0 RNW}, RNW=0
93            - Assert START and WRITE command bits
94            - Poll TIP bit, wait for TIP=0
95            - Read RXACK status bit, should be 0
96        - Write top 8 bits of target address to Tx register
97            - Assert WRITE command bit
98            - Poll TIP bit, wait for TIP=0
99            - Read RXACK status bit, should be 0
100        - Write bottom 8 bits of target address to Tx register
101            - Assert WRITE command bit
102            - Poll TIP bit, wait for TIP=0
103            - Read RXACK status bit, should be 0
104        - Write data byte to Tx register
105            - Assert STOP and WRITE command bits
106            - Poll TIP bit, wait for TIP=0
107            - Read RXACK status bit, should be 0
108    */
109    #if 0 //protect upper EEPROM bytes
110    if(addrToWrite > 16000) {
111        xil_printf("ERROR! High bytes read-only by default. Edit %s to override!\n", __FILE__);
112        return -1;
113    }
114    #endif
115
116    Xil_Out32(ba+IIC_EEPROM_REG_TX, IIC_EEPROM_CONTROL_WORD_WR);
117    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_START | IIC_EEPROM_REGMASK_WRITE));
118    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (1)!\r"); return -1;}
119
120    Xil_Out32(ba+IIC_EEPROM_REG_TX, (addrToWrite>>8 & 0xFF));
121    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_WRITE));
122    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (2)!\r"); return -1;}
123
124    Xil_Out32(ba+IIC_EEPROM_REG_TX, (addrToWrite & 0xFF));
125    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_WRITE));
126    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (3)!\r"); return -1;}
127
128    Xil_Out32(ba+IIC_EEPROM_REG_TX, (byteToWrite & 0xFF));
129    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_STOP | IIC_EEPROM_REGMASK_WRITE));
130    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (4)!\r"); return -1;}
131
132    /* Poll the EEPROM until its internal write cycle is complete
133       This is done by:
134        -Send START
135        -Write control word for write command
136        -Check for ACK; no ACK means internal write is still ongoing
137    */
138    writeDone = 0;
139    while(writeDone == 0)
140    {
141        Xil_Out32(ba+IIC_EEPROM_REG_TX, IIC_EEPROM_CONTROL_WORD_WR);
142        Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_START | IIC_EEPROM_REGMASK_WRITE));
143        if(iic_eeprom_waitForRxACK(ba) == 0) {writeDone = 1;}
144    }
145
146    return 0;
147}
148
149/**
150\brief Reads one bytes to the EEPROM
151\param ba Base memory address of w3_iic_eeprom pcore
152\param addrToRead Byte address to read (in [0,16383])
153\return If EEPROM read succeeds, the read byte is returned in the LSB. If an error occurs, returns -1.
154*/
155int iic_eeprom_readByte(u32 ba, u16 addrToRead)
156{
157    /* Process to read 1 byte from random address in IIC EEPROM
158        - Write EEPROM control word to Tx register {1 0 1 0 0 0 0 RNW}, RNW=0
159            - Assert START and WRITE command bits
160            - Poll TIP bit, wait for TIP=0
161            - Read RXACK status bit, should be 0
162        - Write top 8 bits of target address to Tx register
163            - Assert WRITE command bit
164            - Poll TIP bit, wait for TIP=0
165            - Read RXACK status bit, should be 0
166        - Write bottom 8 bits of target address to Tx register
167            - Assert WRITE command bit
168            - Poll TIP bit, wait for TIP=0
169            - Read RXACK status bit, should be 0
170        - Write EEPROM control word to Tx register {1 0 1 0 0 0 0 RNW}, RNW=1
171            - Assert START and WRITE command bits (causes repeat START event)
172            - Poll TIP bit, wait for TIP=0
173            - Read RXACK status bit, should be 0
174        - Assert STOP, READ and ACK command bits
175        - Read received byte from rx register
176    */
177
178
179    Xil_Out32(ba+IIC_EEPROM_REG_TX, IIC_EEPROM_CONTROL_WORD_WR);
180    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_START | IIC_EEPROM_REGMASK_WRITE));
181    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (1)!\r"); return -1;}
182
183    Xil_Out32(ba+IIC_EEPROM_REG_TX, (addrToRead>>8 & 0xFF));
184    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_WRITE));
185    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (2)!\r"); return -1;}
186
187    Xil_Out32(ba+IIC_EEPROM_REG_TX, (addrToRead & 0xFF));
188    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_WRITE));
189    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (3)!\r"); return -1;}
190
191    Xil_Out32(ba+IIC_EEPROM_REG_TX, IIC_EEPROM_CONTROL_WORD_RD);
192    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_START | IIC_EEPROM_REGMASK_WRITE));
193    if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (4)!\r"); return -1;}
194
195    Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_STOP | IIC_EEPROM_REGMASK_READ | IIC_EEPROM_REGMASK_ACK));
196    while(Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS) & IIC_EEPROM_REGMASK_TIP) {}
197
198    return (Xil_In32(ba+IIC_EEPROM_REG_RX) & 0xFF);
199
200}
201
202/**
203\brief Reads the WARP v3 board serial number (programmed during manufacturing)
204\param ba Base memory address of w3_iic_eeprom pcore
205\return Numeric part of board serial number (prefix "W3-a-" not stored in EEPROM)
206*/
207u32 w3_eeprom_readSerialNum(u32 ba)
208{
209    int x0,x1,x2;
210
211    x0 = (int)iic_eeprom_readByte(ba, 16372);
212    x1 = (int)iic_eeprom_readByte(ba, 16373);
213    x2 = (int)iic_eeprom_readByte(ba, 16374);
214
215    return (x2<<16 | x1<<8 | x0);
216}
217
218/**
219\brief Reads one of the WARP v3 board Ethernet MAC addresses (programmed during manufacturing)
220\param ba Base memory address of w3_iic_eeprom pcore
221\param addrSel Selection of Ethernet address to retrieve (0=ETH_A address, 1=ETH_B address)
222\param addrBuf Pointer to array of 6 bytes to store retrieved address. This function will overwrite 6 bytes starting at addrBuf.
223*/
224void w3_eeprom_readEthAddr(u32 ba, u8 addrSel, u8* addrBuf)
225{
226    u8 addrOffset;
227    u32 sn;
228
229    addrOffset = addrSel ? 6 : 0;
230   
231    addrBuf[5] = iic_eeprom_readByte(ba, 16352+addrOffset);
232    addrBuf[4] = iic_eeprom_readByte(ba, 16353+addrOffset);
233    addrBuf[3] = iic_eeprom_readByte(ba, 16354+addrOffset);
234    addrBuf[2] = iic_eeprom_readByte(ba, 16355+addrOffset);
235    addrBuf[1] = iic_eeprom_readByte(ba, 16356+addrOffset);
236    addrBuf[0] = iic_eeprom_readByte(ba, 16357+addrOffset);
237
238    if( ( (addrBuf[0] == 0x40) && (addrBuf[1] == 0xD8) && (addrBuf[2] == 0x55) ) == 0) {
239        //EEPROM contains invalid (or no) MAC address
240        // Use the node serial number to compute a valid address instead
241        // See http://warpproject.org/trac/wiki/HardwareUsersGuides/WARPv3/Ethernet#MACAddresses
242        sn = 2 * w3_eeprom_readSerialNum(ba);
243        addrBuf[0] = 0x40;
244        addrBuf[1] = 0xD8;
245        addrBuf[2] = 0x55;
246        addrBuf[3] = 0x04;
247        addrBuf[4] = 0x20 + ((sn>>8)&0xF);
248        addrBuf[5] = 0x00 + (sn&0xFF) + (addrSel & 0x1);
249    }
250   
251    // If the first three octets match, then the node has a serial number that does not follow the
252    // serial_number * 2 scheme.  However, we still need to check to make sure that octet [3] and [4]
253    // are correct.
254    if (addrBuf[3] != 0x04) {                         // addrBuf[3] must be 0x04
255        addrBuf[3] = 0x04; 
256    }   
257
258    if ((addrBuf[4] & 0xF0) != 0x20) {                // addrBuf[4] must be 0x2X, where X is in [0..F]
259        addrBuf[4] = 0x20 | (addrBuf[4] & 0x0F); 
260    }
261   
262    return;
263}
264
265/**
266\brief Reads part of the 56-bit Virtex-6 FPGA DNA value (copied to EEPROM during manufacturing)
267\param ba Base memory address of w3_iic_eeprom pcore
268\param lo_hi Selects between 32 LSB or 24 MSB of DNA value (0=LSB, 1=MSB)
269\return Returns selected portion of FPGA DNA value
270*/
271u32 w3_eeprom_read_fpga_dna(u32 ba, int lo_hi)
272{
273    int x0,x1,x2,x3;
274    if(lo_hi==0)
275    {
276        x0 = (int)iic_eeprom_readByte(ba, 16376);
277        x1 = (int)iic_eeprom_readByte(ba, 16377);
278        x2 = (int)iic_eeprom_readByte(ba, 16378);
279        x3 = (int)iic_eeprom_readByte(ba, 16379);
280    }
281    else if(lo_hi==1)
282    {
283        x0 = (int)iic_eeprom_readByte(ba, 16380);
284        x1 = (int)iic_eeprom_readByte(ba, 16381);
285        x2 = (int)iic_eeprom_readByte(ba, 16382);
286        x3 = (int)iic_eeprom_readByte(ba, 16383);
287    }
288
289    return (x3<<24 | x2<<16 | x1<<8 | x0);
290}
291/** @}*/ //END group user_functions
292
293/// @cond EXCLUDE_FROM_DOCS
294// User code never calls this, so exclude it from the API docs
295//Returns 0 if IIC bus ACK is detected
296inline int iic_eeprom_waitForRxACK(u32 ba)
297{
298//  xil_printf("Status: 0x%08x CMD: 0x%08x\r", Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS), Xil_In32(ba+IIC_EEPROM_REG_CMD));
299    while(Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS) & IIC_EEPROM_REGMASK_TIP) {}
300
301    return (0 != (Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS) & IIC_EEPROM_REGMASK_RXACK));
302}
303/// @endcond
Note: See TracBrowser for help on using the repository browser.