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 |
---|
11 | This is the driver for the w3_iic_eeprom core, which implements an IIC master for accessing |
---|
12 | the EEPROM on the WARP v3 board. |
---|
13 | |
---|
14 | This driver implements functions for reading and writing individual bytes in the EEPROM. Functions |
---|
15 | are also provided for accessing EEPROM entries written during manufacturing (serial number, etc.). |
---|
16 | |
---|
17 | The full EEPROM is readable/writable from user-code. No addresses are write-protected. |
---|
18 | |
---|
19 | Refer to the <a href="http://warp.rice.edu/trac/wiki/HardwareUsersGuides/WARPv3/EEPROM">WARP v3 User Guide</a> for details |
---|
20 | on 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> |
---|
25 | Released 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 | |
---|
39 | Example: |
---|
40 | \code{.c} |
---|
41 | //Assumes user code sets EEPROM_BASEADDR to base address of w3_iic_eeprom core, as set in xparameters.h |
---|
42 | |
---|
43 | int x; |
---|
44 | u32 board_sn; |
---|
45 | |
---|
46 | //Initialize the EEPROM controller at boot |
---|
47 | iic_eeprom_init(EEPROM_BASEADDR, 0x64); |
---|
48 | |
---|
49 | //Write a value to the EEPROM (set EEPROM byte address 2345 to 182) |
---|
50 | x = iic_eeprom_writeByte(EEPROM_BASEADDR, 2345, 182); |
---|
51 | if(x != 0) xil_printf("EEPROM Write Error!\n"); |
---|
52 | |
---|
53 | //Read the value back from EEPROM |
---|
54 | x = iic_eeprom_readByte(EEPROM_BASEADDR, 2345); |
---|
55 | if(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 |
---|
58 | board_sn = w3_eeprom_readSerialNum(EEPROM_BASEADDDR); |
---|
59 | xil_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 | */ |
---|
71 | void 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 | */ |
---|
88 | int 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 | */ |
---|
155 | int 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 | */ |
---|
207 | u32 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 | */ |
---|
224 | void 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 | */ |
---|
271 | u32 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 |
---|
296 | inline 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 |
---|