1157873Simp/****************************************************************************** 2157873Simp * 3157873Simp * Filename: eeprom.c 4157873Simp * 5157873Simp * Instantiation of eeprom routines 6157873Simp * 7157873Simp * Revision information: 8157873Simp * 9157873Simp * 28AUG2004 kb_admin initial creation - adapted from Atmel sources 10157873Simp * 12JAN2005 kb_admin fixed clock generation, write polling, init 11157873Simp * 12157873Simp * BEGIN_KBDD_BLOCK 13157873Simp * No warranty, expressed or implied, is included with this software. It is 14157873Simp * provided "AS IS" and no warranty of any kind including statutory or aspects 15157873Simp * relating to merchantability or fitness for any purpose is provided. All 16157873Simp * intellectual property rights of others is maintained with the respective 17157873Simp * owners. This software is not copyrighted and is intended for reference 18157873Simp * only. 19157873Simp * END_BLOCK 20157873Simp * 21157873Simp * $FreeBSD$ 22157873Simp *****************************************************************************/ 23157873Simp 24157873Simp#include "at91rm9200_lowlevel.h" 25157873Simp#include "at91rm9200.h" 26157873Simp#include "lib.h" 27157873Simp 28157873Simp/******************************* GLOBALS *************************************/ 29157873Simp 30157873Simp 31157873Simp/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 32157873Simp 33157873Simp 34157873Simp/* Use a macro to calculate the TWI clock generator value to save code space. */ 35157873Simp#define AT91C_TWSI_CLOCK 100000 36157873Simp#define TWSI_EEPROM_ADDRESS 0x50 37157873Simp 38157873Simp#define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2) 39157873Simp#define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8)) 40157873Simp 41157873Simp 42157873Simp/*************************** GLOBAL FUNCTIONS ********************************/ 43157873Simp 44157873Simp 45157873Simp/* 46157873Simp * .KB_C_FN_DEFINITION_START 47157873Simp * void InitEEPROM(void) 48157873Simp * This global function initializes the EEPROM interface (TWI). Intended 49157873Simp * to be called a single time. 50157873Simp * .KB_C_FN_DEFINITION_END 51157873Simp */ 52157873Simpvoid 53157873SimpInitEEPROM(void) 54157873Simp{ 55157873Simp 56157873Simp AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI; 57157873Simp 58157873Simp AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA; 59157873Simp AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC; 60157873Simp 61238463Simp pPio->PIO_ASR = AT91C_PIO_PA25 | AT91C_PIO_PA26; 62238463Simp pPio->PIO_PDR = AT91C_PIO_PA25 | AT91C_PIO_PA26; 63157873Simp 64238463Simp pPio->PIO_MDDR = ~AT91C_PIO_PA25; 65238463Simp pPio->PIO_MDER = AT91C_PIO_PA25; 66157873Simp 67157873Simp pPMC->PMC_PCER = 1u << AT91C_ID_TWI; 68157873Simp 69157873Simp twiPtr->TWI_IDR = 0xffffffffu; 70157873Simp twiPtr->TWI_CR = AT91C_TWI_SWRST; 71157873Simp twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; 72157873Simp 73157873Simp twiPtr->TWI_CWGR = SET_TWI_CLOCK; 74157873Simp} 75157873Simp 76157873Simp 77157873Simp/* 78157873Simp * .KB_C_FN_DEFINITION_START 79157873Simp * void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size) 80157873Simp * This global function reads data from the eeprom at ee_addr storing data 81157873Simp * to data_addr for size bytes. Assume the TWI has been initialized. 82157873Simp * This function does not utilize the page read mode to simplify the code. 83157873Simp * .KB_C_FN_DEFINITION_END 84157873Simp */ 85165399Simpint 86172991ScognetReadEEPROM(unsigned ee_off, unsigned char *data_addr, unsigned size) 87157873Simp{ 88157873Simp const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 89157873Simp unsigned int status; 90165399Simp unsigned int count; 91157873Simp 92157873Simp status = twiPtr->TWI_SR; 93157873Simp status = twiPtr->TWI_RHR; 94157873Simp 95157873Simp // Set the TWI Master Mode Register 96157873Simp twiPtr->TWI_MMR = (TWSI_EEPROM_ADDRESS << 16) | 97157873Simp AT91C_TWI_IADRSZ_2_BYTE | AT91C_TWI_MREAD; 98157873Simp 99157873Simp // Set TWI Internal Address Register 100161193Simp twiPtr->TWI_IADR = ee_off; 101157873Simp 102157873Simp // Start transfer 103157873Simp twiPtr->TWI_CR = AT91C_TWI_START; 104157873Simp 105157873Simp status = twiPtr->TWI_SR; 106157873Simp 107157873Simp while (size-- > 1){ 108157873Simp // Wait RHR Holding register is full 109165399Simp count = 1000000; 110165399Simp while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY) && --count > 0) 111157873Simp continue; 112165399Simp if (count <= 0) 113165399Simp return -1; 114157873Simp 115157873Simp // Read byte 116157873Simp *(data_addr++) = twiPtr->TWI_RHR; 117157873Simp } 118157873Simp 119157873Simp twiPtr->TWI_CR = AT91C_TWI_STOP; 120157873Simp 121157873Simp status = twiPtr->TWI_SR; 122157873Simp 123157873Simp // Wait transfer is finished 124157873Simp while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 125157873Simp continue; 126157873Simp 127157873Simp // Read last byte 128157873Simp *data_addr = twiPtr->TWI_RHR; 129165399Simp return 0; 130157873Simp} 131157873Simp 132157873Simp 133157873Simp/* 134157873Simp * .KB_C_FN_DEFINITION_START 135161193Simp * void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 136161193Simp * This global function writes data to the eeprom at ee_off using data 137157873Simp * from data_addr for size bytes. Assume the TWI has been initialized. 138157873Simp * This function does not utilize the page write mode as the write time is 139157873Simp * much greater than the time required to access the device for byte-write 140157873Simp * functionality. This allows the function to be much simpler. 141157873Simp * .KB_C_FN_DEFINITION_END 142157873Simp */ 143157873Simpvoid 144161193SimpWriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 145157873Simp{ 146157873Simp const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 147157873Simp unsigned status; 148172991Scognet unsigned char test_data; 149157873Simp 150157873Simp while (size--) { 151161193Simp if (!(ee_off & 0x3f)) 152157873Simp putchar('.'); 153157873Simp 154157873Simp // Set the TWI Master Mode Register 155157873Simp twiPtr->TWI_MMR = ((TWSI_EEPROM_ADDRESS << 16) | 156157873Simp AT91C_TWI_IADRSZ_2_BYTE) & ~AT91C_TWI_MREAD; 157157873Simp 158157873Simp // Set TWI Internal Address Register 159161193Simp twiPtr->TWI_IADR = ee_off++; 160157873Simp 161157873Simp status = twiPtr->TWI_SR; 162157873Simp 163157873Simp twiPtr->TWI_THR = *(data_addr++); 164157873Simp 165157873Simp twiPtr->TWI_CR = AT91C_TWI_START; 166157873Simp 167157873Simp // Wait transfer is finished 168157873Simp while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY)) 169157873Simp continue; 170157873Simp 171157873Simp twiPtr->TWI_CR = AT91C_TWI_STOP; 172157873Simp 173157873Simp status = twiPtr->TWI_SR; 174157873Simp 175157873Simp // Wait transfer is finished 176157873Simp while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 177157873Simp continue; 178157873Simp 179157873Simp // wait for write operation to complete 180161193Simp ReadEEPROM(ee_off, &test_data, 1); 181157873Simp } 182157873Simp 183157873Simp putchar('\r'); 184157873Simp putchar('\n'); 185157873Simp} 186