1163598Simp/****************************************************************************** 2163598Simp * 3163598Simp * Filename: eeprom.c 4163598Simp * 5163598Simp * Instantiation of eeprom routines 6163598Simp * 7163598Simp * Revision information: 8163598Simp * 9163598Simp * 28AUG2004 kb_admin initial creation - adapted from Atmel sources 10163598Simp * 12JAN2005 kb_admin fixed clock generation, write polling, init 11163598Simp * 12163598Simp * BEGIN_KBDD_BLOCK 13163598Simp * No warranty, expressed or implied, is included with this software. It is 14163598Simp * provided "AS IS" and no warranty of any kind including statutory or aspects 15163598Simp * relating to merchantability or fitness for any purpose is provided. All 16163598Simp * intellectual property rights of others is maintained with the respective 17163598Simp * owners. This software is not copyrighted and is intended for reference 18163598Simp * only. 19163598Simp * END_BLOCK 20163598Simp * 21163598Simp * $FreeBSD: releng/10.2/sys/boot/arm/at91/bootspi/ee.c 238463 2012-07-15 05:35:14Z imp $ 22163598Simp *****************************************************************************/ 23163598Simp 24163598Simp#include "at91rm9200_lowlevel.h" 25163598Simp#include "at91rm9200.h" 26163598Simp#include "lib.h" 27163598Simp#include "ee.h" 28163598Simp 29163598Simp/******************************* GLOBALS *************************************/ 30163598Simp 31163598Simp 32163598Simp/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 33163598Simp 34163598Simp 35163598Simp/* Use a macro to calculate the TWI clock generator value to save code space. */ 36163598Simp#define AT91C_TWSI_CLOCK 100000 37163598Simp#define TWSI_EEPROM_ADDRESS 0x40 38163598Simp 39163598Simp#define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2) 40163598Simp#define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8)) 41163598Simp 42163598Simp 43163598Simp/*************************** GLOBAL FUNCTIONS ********************************/ 44163598Simp 45163598Simp 46163598Simp/* 47163598Simp * .KB_C_FN_DEFINITION_START 48163598Simp * void InitEEPROM(void) 49163598Simp * This global function initializes the EEPROM interface (TWI). Intended 50163598Simp * to be called a single time. 51163598Simp * .KB_C_FN_DEFINITION_END 52163598Simp */ 53163598Simpvoid 54163598SimpEEInit(void) 55163598Simp{ 56163598Simp 57163598Simp AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI; 58163598Simp 59163598Simp AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA; 60163598Simp AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC; 61163598Simp 62238463Simp pPio->PIO_ASR = AT91C_PIO_PA25 | AT91C_PIO_PA26; 63238463Simp pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26; 64163598Simp 65238463Simp pPio->PIO_MDDR = ~AT91C_PIO_PA25; 66238463Simp pPio->PIO_MDER = AT91C_PIO_PA25; 67163598Simp 68163598Simp pPMC->PMC_PCER = 1u << AT91C_ID_TWI; 69163598Simp 70163598Simp twiPtr->TWI_IDR = 0xffffffffu; 71163598Simp twiPtr->TWI_CR = AT91C_TWI_SWRST; 72163598Simp twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; 73163598Simp 74163598Simp twiPtr->TWI_CWGR = SET_TWI_CLOCK; 75163598Simp} 76163598Simp 77163598Simpstatic inline unsigned 78163598Simpiicaddr(unsigned ee_off) 79163598Simp{ 80163598Simp return (TWSI_EEPROM_ADDRESS | ((ee_off >> 8) & 0x7)); 81163598Simp} 82163598Simp 83163598Simp 84163598Simp/* 85163598Simp * .KB_C_FN_DEFINITION_START 86163598Simp * void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size) 87163598Simp * This global function reads data from the eeprom at ee_addr storing data 88163598Simp * to data_addr for size bytes. Assume the TWI has been initialized. 89163598Simp * This function does not utilize the page read mode to simplify the code. 90163598Simp * .KB_C_FN_DEFINITION_END 91163598Simp */ 92163598Simpvoid 93163598SimpEERead(unsigned ee_off, char *data_addr, unsigned size) 94163598Simp{ 95163598Simp const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 96163598Simp unsigned int status; 97163598Simp 98163598Simp if ((ee_off & ~0xff) != ((ee_off + size) & ~0xff)) { 99163598Simp printf("Crosses page boundary: 0x%x 0x%x\n", ee_off, size); 100163598Simp return; 101163598Simp } 102163598Simp 103163598Simp status = twiPtr->TWI_SR; 104163598Simp status = twiPtr->TWI_RHR; 105163598Simp twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) | AT91C_TWI_IADRSZ_1_BYTE | 106163598Simp AT91C_TWI_MREAD; 107163598Simp twiPtr->TWI_IADR = ee_off & 0xff; 108163598Simp twiPtr->TWI_CR = AT91C_TWI_START; 109163598Simp while (size-- > 1) { 110163598Simp while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY)) 111163598Simp continue; 112163598Simp *(data_addr++) = twiPtr->TWI_RHR; 113163598Simp } 114163598Simp twiPtr->TWI_CR = AT91C_TWI_STOP; 115163598Simp status = twiPtr->TWI_SR; 116163598Simp while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 117163598Simp continue; 118163598Simp *data_addr = twiPtr->TWI_RHR; 119163598Simp} 120163598Simp 121163598Simp 122163598Simp/* 123163598Simp * .KB_C_FN_DEFINITION_START 124163598Simp * void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 125163598Simp * This global function writes data to the eeprom at ee_off using data 126163598Simp * from data_addr for size bytes. Assume the TWI has been initialized. 127163598Simp * This function does not utilize the page write mode as the write time is 128163598Simp * much greater than the time required to access the device for byte-write 129163598Simp * functionality. This allows the function to be much simpler. 130163598Simp * .KB_C_FN_DEFINITION_END 131163598Simp */ 132163598Simpvoid 133163598SimpEEWrite(unsigned ee_off, const char *data_addr, unsigned size) 134163598Simp{ 135163598Simp const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 136163598Simp unsigned status; 137163598Simp char test_data; 138163598Simp 139163598Simp while (size--) { 140163598Simp // Set the TWI Master Mode Register 141163598Simp twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) | 142163598Simp AT91C_TWI_IADRSZ_1_BYTE; 143163598Simp twiPtr->TWI_IADR = ee_off++; 144163598Simp status = twiPtr->TWI_SR; 145163598Simp 146163598Simp // Load one data byte 147163598Simp twiPtr->TWI_THR = *(data_addr++); 148163598Simp twiPtr->TWI_CR = AT91C_TWI_START; 149163598Simp while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY)) 150163598Simp continue; 151163598Simp twiPtr->TWI_CR = AT91C_TWI_STOP; 152163598Simp status = twiPtr->TWI_SR; 153163598Simp while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 154163598Simp continue; 155163598Simp 156163598Simp // wait for write operation to complete, it is done once 157163598Simp // we can read it back... 158163598Simp EERead(ee_off, &test_data, 1); 159163598Simp } 160163598Simp} 161