[1774] | 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 | *****************************************************************/ |
---|
[1766] | 7 | |
---|
[1774] | 8 | /** \file w3_iic_eeprom.c |
---|
[1766] | 9 | |
---|
[1774] | 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. |
---|
[1766] | 13 | |
---|
[1774] | 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 | |
---|
[1766] | 31 | #include "w3_iic_eeprom.h" |
---|
| 32 | #include "stdio.h" |
---|
| 33 | |
---|
[1774] | 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 | */ |
---|
[1766] | 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 | |
---|
[1774] | 81 | /** |
---|
| 82 | \brief Writes one bytes to the EEPROM |
---|
| 83 | \param ba Base memory address of w3_iic_eeprom pcore |
---|
[1849] | 84 | \param addrToWrite Byte address to write, in [0,16000] (addresses >16000 are reserved) |
---|
[1774] | 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) |
---|
[1766] | 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 | */ |
---|
[1850] | 109 | #if 1 //protect upper EEPROM bytes |
---|
[1863] | 110 | if(addrToWrite > 16000) { |
---|
| 111 | xil_printf("ERROR! High bytes read-only by default. Edit %s to override!\n", __FILE__); |
---|
[1849] | 112 | return -1; |
---|
[1863] | 113 | } |
---|
[1850] | 114 | #endif |
---|
| 115 | |
---|
[1766] | 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)); |
---|
[1774] | 118 | if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (1)!\r"); return -1;} |
---|
[1766] | 119 | |
---|
| 120 | Xil_Out32(ba+IIC_EEPROM_REG_TX, (addrToWrite>>8 & 0xFF)); |
---|
| 121 | Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_WRITE)); |
---|
[1774] | 122 | if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (2)!\r"); return -1;} |
---|
[1766] | 123 | |
---|
| 124 | Xil_Out32(ba+IIC_EEPROM_REG_TX, (addrToWrite & 0xFF)); |
---|
| 125 | Xil_Out32(ba+IIC_EEPROM_REG_CMD, (IIC_EEPROM_REGMASK_WRITE)); |
---|
[1774] | 126 | if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (3)!\r"); return -1;} |
---|
[1766] | 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)); |
---|
[1774] | 130 | if(iic_eeprom_waitForRxACK(ba)) {print("EEPROM: Error (4)!\r"); return -1;} |
---|
[1766] | 131 | |
---|
[1774] | 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 | */ |
---|
[1766] | 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 | |
---|
[1774] | 146 | return 0; |
---|
[1766] | 147 | } |
---|
| 148 | |
---|
[1774] | 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 | */ |
---|
[1766] | 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 | |
---|
[1774] | 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) |
---|
[1766] | 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 | |
---|
[1774] | 218 | /** |
---|
[1849] | 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 | |
---|
| 228 | addrOffset = addrSel ? 6 : 0; |
---|
| 229 | |
---|
| 230 | addrBuf[5] = iic_eeprom_readByte(ba, 16352+addrOffset); |
---|
| 231 | addrBuf[4] = iic_eeprom_readByte(ba, 16353+addrOffset); |
---|
| 232 | addrBuf[3] = iic_eeprom_readByte(ba, 16354+addrOffset); |
---|
| 233 | addrBuf[2] = iic_eeprom_readByte(ba, 16355+addrOffset); |
---|
| 234 | addrBuf[1] = iic_eeprom_readByte(ba, 16356+addrOffset); |
---|
| 235 | addrBuf[0] = iic_eeprom_readByte(ba, 16357+addrOffset); |
---|
| 236 | |
---|
| 237 | return; |
---|
| 238 | } |
---|
| 239 | |
---|
| 240 | /** |
---|
[1774] | 241 | \brief Reads part of the 56-bit Virtex-6 FPGA DNA value (copied to EEPROM during manufacturing) |
---|
| 242 | \param ba Base memory address of w3_iic_eeprom pcore |
---|
| 243 | \param lo_hi Selects between 32 LSB or 24 MSB of DNA value (0=LSB, 1=MSB) |
---|
| 244 | \return Returns selected portion of FPGA DNA value |
---|
| 245 | */ |
---|
| 246 | u32 w3_eeprom_read_fpga_dna(u32 ba, int lo_hi) |
---|
[1766] | 247 | { |
---|
| 248 | int x0,x1,x2,x3; |
---|
| 249 | if(lo_hi==0) |
---|
| 250 | { |
---|
| 251 | x0 = (int)iic_eeprom_readByte(ba, 16376); |
---|
| 252 | x1 = (int)iic_eeprom_readByte(ba, 16377); |
---|
| 253 | x2 = (int)iic_eeprom_readByte(ba, 16378); |
---|
| 254 | x3 = (int)iic_eeprom_readByte(ba, 16379); |
---|
| 255 | } |
---|
| 256 | else if(lo_hi==1) |
---|
| 257 | { |
---|
| 258 | x0 = (int)iic_eeprom_readByte(ba, 16380); |
---|
| 259 | x1 = (int)iic_eeprom_readByte(ba, 16381); |
---|
| 260 | x2 = (int)iic_eeprom_readByte(ba, 16382); |
---|
| 261 | x3 = (int)iic_eeprom_readByte(ba, 16383); |
---|
| 262 | } |
---|
| 263 | |
---|
| 264 | return (x3<<24 | x2<<16 | x1<<8 | x0); |
---|
| 265 | } |
---|
[1774] | 266 | /** @}*/ //END group user_functions |
---|
| 267 | |
---|
| 268 | /// @cond EXCLUDE_FROM_DOCS |
---|
| 269 | // User code never calls this, so exclude it from the API docs |
---|
| 270 | //Returns 0 if IIC bus ACK is detected |
---|
| 271 | inline int iic_eeprom_waitForRxACK(u32 ba) |
---|
| 272 | { |
---|
| 273 | // xil_printf("Status: 0x%08x CMD: 0x%08x\r", Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS), Xil_In32(ba+IIC_EEPROM_REG_CMD)); |
---|
| 274 | while(Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS) & IIC_EEPROM_REGMASK_TIP) {} |
---|
| 275 | |
---|
| 276 | return (0 != (Xil_In32(ba+IIC_EEPROM_REG_CONFIG_STATUS) & IIC_EEPROM_REGMASK_RXACK)); |
---|
| 277 | } |
---|
| 278 | /// @endcond |
---|