1 /****************************************************************************** 2 * 3 * Filename: eeprom.c 4 * 5 * Instantiation of eeprom routines 6 * 7 * Revision information: 8 * 9 * 28AUG2004 kb_admin initial creation - adapted from Atmel sources 10 * 12JAN2005 kb_admin fixed clock generation, write polling, init 11 * 12 * BEGIN_KBDD_BLOCK 13 * No warranty, expressed or implied, is included with this software. It is 14 * provided "AS IS" and no warranty of any kind including statutory or aspects 15 * relating to merchantability or fitness for any purpose is provided. All 16 * intellectual property rights of others is maintained with the respective 17 * owners. This software is not copyrighted and is intended for reference 18 * only. 19 * END_BLOCK 20 * 21 * $FreeBSD$ 22 *****************************************************************************/ 23 24 #include "at91rm9200_lowlevel.h" 25 #include "at91rm9200.h" 26 #include "lib.h" 27 28 /******************************* GLOBALS *************************************/ 29 30 31 /*********************** PRIVATE FUNCTIONS/DATA ******************************/ 32 33 34 /* Use a macro to calculate the TWI clock generator value to save code space. */ 35 #define AT91C_TWSI_CLOCK 100000 36 #define TWSI_EEPROM_ADDRESS 0x50 37 38 #define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2) 39 #define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8)) 40 41 42 /*************************** GLOBAL FUNCTIONS ********************************/ 43 44 45 /* 46 * .KB_C_FN_DEFINITION_START 47 * void InitEEPROM(void) 48 * This global function initializes the EEPROM interface (TWI). Intended 49 * to be called a single time. 50 * .KB_C_FN_DEFINITION_END 51 */ 52 void 53 InitEEPROM(void) 54 { 55 56 AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI; 57 58 AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA; 59 AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC; 60 61 pPio->PIO_ASR = AT91C_PIO_PA25 | AT91C_PIO_PA26; 62 pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26; 63 64 pPio->PIO_MDDR = ~AT91C_PIO_PA25; 65 pPio->PIO_MDER = AT91C_PIO_PA25; 66 67 pPMC->PMC_PCER = 1u << AT91C_ID_TWI; 68 69 twiPtr->TWI_IDR = 0xffffffffu; 70 twiPtr->TWI_CR = AT91C_TWI_SWRST; 71 twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; 72 73 twiPtr->TWI_CWGR = SET_TWI_CLOCK; 74 } 75 76 77 /* 78 * .KB_C_FN_DEFINITION_START 79 * void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size) 80 * This global function reads data from the eeprom at ee_addr storing data 81 * to data_addr for size bytes. Assume the TWI has been initialized. 82 * This function does not utilize the page read mode to simplify the code. 83 * .KB_C_FN_DEFINITION_END 84 */ 85 int 86 ReadEEPROM(unsigned ee_off, unsigned char *data_addr, unsigned size) 87 { 88 const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 89 unsigned int status; 90 unsigned int count; 91 92 status = twiPtr->TWI_SR; 93 status = twiPtr->TWI_RHR; 94 95 // Set the TWI Master Mode Register 96 twiPtr->TWI_MMR = (TWSI_EEPROM_ADDRESS << 16) | 97 AT91C_TWI_IADRSZ_2_BYTE | AT91C_TWI_MREAD; 98 99 // Set TWI Internal Address Register 100 twiPtr->TWI_IADR = ee_off; 101 102 // Start transfer 103 twiPtr->TWI_CR = AT91C_TWI_START; 104 105 status = twiPtr->TWI_SR; 106 107 while (size-- > 1){ 108 // Wait RHR Holding register is full 109 count = 1000000; 110 while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY) && --count > 0) 111 continue; 112 if (count <= 0) 113 return -1; 114 115 // Read byte 116 *(data_addr++) = twiPtr->TWI_RHR; 117 } 118 119 twiPtr->TWI_CR = AT91C_TWI_STOP; 120 121 status = twiPtr->TWI_SR; 122 123 // Wait transfer is finished 124 while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 125 continue; 126 127 // Read last byte 128 *data_addr = twiPtr->TWI_RHR; 129 return 0; 130 } 131 132 133 /* 134 * .KB_C_FN_DEFINITION_START 135 * void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 136 * This global function writes data to the eeprom at ee_off using data 137 * from data_addr for size bytes. Assume the TWI has been initialized. 138 * This function does not utilize the page write mode as the write time is 139 * much greater than the time required to access the device for byte-write 140 * functionality. This allows the function to be much simpler. 141 * .KB_C_FN_DEFINITION_END 142 */ 143 void 144 WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 145 { 146 const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 147 unsigned status; 148 unsigned char test_data; 149 150 while (size--) { 151 if (!(ee_off & 0x3f)) 152 putchar('.'); 153 154 // Set the TWI Master Mode Register 155 twiPtr->TWI_MMR = ((TWSI_EEPROM_ADDRESS << 16) | 156 AT91C_TWI_IADRSZ_2_BYTE) & ~AT91C_TWI_MREAD; 157 158 // Set TWI Internal Address Register 159 twiPtr->TWI_IADR = ee_off++; 160 161 status = twiPtr->TWI_SR; 162 163 twiPtr->TWI_THR = *(data_addr++); 164 165 twiPtr->TWI_CR = AT91C_TWI_START; 166 167 // Wait transfer is finished 168 while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY)) 169 continue; 170 171 twiPtr->TWI_CR = AT91C_TWI_STOP; 172 173 status = twiPtr->TWI_SR; 174 175 // Wait transfer is finished 176 while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 177 continue; 178 179 // wait for write operation to complete 180 ReadEEPROM(ee_off, &test_data, 1); 181 } 182 183 putchar('\r'); 184 putchar('\n'); 185 } 186