eeprom.c revision 161193
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: head/sys/boot/arm/at91/libat91/eeprom.c 161193 2006-08-10 18:03:50Z imp $ 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 */ 52void 53InitEEPROM(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_PA25_TWD | AT91C_PA26_TWCK; 62 pPio->PIO_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK; 63 64 pPio->PIO_MDDR = ~AT91C_PA25_TWD; 65 pPio->PIO_MDER = AT91C_PA25_TWD; 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 */ 85void 86ReadEEPROM(unsigned ee_off, char *data_addr, unsigned size) 87{ 88 const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 89 unsigned int status; 90 91 status = twiPtr->TWI_SR; 92 status = twiPtr->TWI_RHR; 93 94 // Set the TWI Master Mode Register 95 twiPtr->TWI_MMR = (TWSI_EEPROM_ADDRESS << 16) | 96 AT91C_TWI_IADRSZ_2_BYTE | AT91C_TWI_MREAD; 97 98 // Set TWI Internal Address Register 99 twiPtr->TWI_IADR = ee_off; 100 101 // Start transfer 102 twiPtr->TWI_CR = AT91C_TWI_START; 103 104 status = twiPtr->TWI_SR; 105 106 while (size-- > 1){ 107 108 // Wait RHR Holding register is full 109 while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY)) 110 continue; 111 112 // Read byte 113 *(data_addr++) = twiPtr->TWI_RHR; 114 } 115 116 twiPtr->TWI_CR = AT91C_TWI_STOP; 117 118 status = twiPtr->TWI_SR; 119 120 // Wait transfer is finished 121 while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 122 continue; 123 124 // Read last byte 125 *data_addr = twiPtr->TWI_RHR; 126} 127 128 129/* 130 * .KB_C_FN_DEFINITION_START 131 * void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 132 * This global function writes data to the eeprom at ee_off using data 133 * from data_addr for size bytes. Assume the TWI has been initialized. 134 * This function does not utilize the page write mode as the write time is 135 * much greater than the time required to access the device for byte-write 136 * functionality. This allows the function to be much simpler. 137 * .KB_C_FN_DEFINITION_END 138 */ 139void 140WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 141{ 142 const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 143 unsigned status; 144 char test_data; 145 146 while (size--) { 147 if (!(ee_off & 0x3f)) 148 putchar('.'); 149 150 // Set the TWI Master Mode Register 151 twiPtr->TWI_MMR = ((TWSI_EEPROM_ADDRESS << 16) | 152 AT91C_TWI_IADRSZ_2_BYTE) & ~AT91C_TWI_MREAD; 153 154 // Set TWI Internal Address Register 155 twiPtr->TWI_IADR = ee_off++; 156 157 status = twiPtr->TWI_SR; 158 159 twiPtr->TWI_THR = *(data_addr++); 160 161 twiPtr->TWI_CR = AT91C_TWI_START; 162 163 // Wait transfer is finished 164 while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY)) 165 continue; 166 167 twiPtr->TWI_CR = AT91C_TWI_STOP; 168 169 status = twiPtr->TWI_SR; 170 171 // Wait transfer is finished 172 while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 173 continue; 174 175 // wait for write operation to complete 176 ReadEEPROM(ee_off, &test_data, 1); 177 } 178 179 putchar('\r'); 180 putchar('\n'); 181} 182