ee.c revision 163598
194936Smux/****************************************************************************** 294936Smux * 394936Smux * Filename: eeprom.c 494936Smux * 594936Smux * Instantiation of eeprom routines 694936Smux * 794936Smux * Revision information: 894936Smux * 994936Smux * 28AUG2004 kb_admin initial creation - adapted from Atmel sources 1094936Smux * 12JAN2005 kb_admin fixed clock generation, write polling, init 1194936Smux * 1294936Smux * BEGIN_KBDD_BLOCK 1394936Smux * No warranty, expressed or implied, is included with this software. It is 1494936Smux * provided "AS IS" and no warranty of any kind including statutory or aspects 1594936Smux * relating to merchantability or fitness for any purpose is provided. All 1694936Smux * intellectual property rights of others is maintained with the respective 1794936Smux * owners. This software is not copyrighted and is intended for reference 1894936Smux * only. 1994936Smux * END_BLOCK 2094936Smux * 2194936Smux * $FreeBSD: head/sys/boot/arm/at91/bootspi/ee.c 163598 2006-10-21 22:51:21Z imp $ 2294936Smux *****************************************************************************/ 2394936Smux 2494936Smux#include "at91rm9200_lowlevel.h" 2594936Smux#include "at91rm9200.h" 2694936Smux#include "lib.h" 2794936Smux#include "ee.h" 2894936Smux 2994936Smux/******************************* GLOBALS *************************************/ 3094936Smux 3194936Smux 3294936Smux/*********************** PRIVATE FUNCTIONS/DATA ******************************/ 3394936Smux 3494936Smux 3594936Smux/* Use a macro to calculate the TWI clock generator value to save code space. */ 3694936Smux#define AT91C_TWSI_CLOCK 100000 3794936Smux#define TWSI_EEPROM_ADDRESS 0x40 3894936Smux 3994936Smux#define TWI_CLK_BASE_DIV ((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2) 40#define SET_TWI_CLOCK ((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8)) 41 42 43/*************************** GLOBAL FUNCTIONS ********************************/ 44 45 46/* 47 * .KB_C_FN_DEFINITION_START 48 * void InitEEPROM(void) 49 * This global function initializes the EEPROM interface (TWI). Intended 50 * to be called a single time. 51 * .KB_C_FN_DEFINITION_END 52 */ 53void 54EEInit(void) 55{ 56 57 AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI; 58 59 AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA; 60 AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC; 61 62 pPio->PIO_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK; 63 pPio->PIO_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK; 64 65 pPio->PIO_MDDR = ~AT91C_PA25_TWD; 66 pPio->PIO_MDER = AT91C_PA25_TWD; 67 68 pPMC->PMC_PCER = 1u << AT91C_ID_TWI; 69 70 twiPtr->TWI_IDR = 0xffffffffu; 71 twiPtr->TWI_CR = AT91C_TWI_SWRST; 72 twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS; 73 74 twiPtr->TWI_CWGR = SET_TWI_CLOCK; 75} 76 77static inline unsigned 78iicaddr(unsigned ee_off) 79{ 80 return (TWSI_EEPROM_ADDRESS | ((ee_off >> 8) & 0x7)); 81} 82 83 84/* 85 * .KB_C_FN_DEFINITION_START 86 * void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size) 87 * This global function reads data from the eeprom at ee_addr storing data 88 * to data_addr for size bytes. Assume the TWI has been initialized. 89 * This function does not utilize the page read mode to simplify the code. 90 * .KB_C_FN_DEFINITION_END 91 */ 92void 93EERead(unsigned ee_off, char *data_addr, unsigned size) 94{ 95 const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 96 unsigned int status; 97 98 if ((ee_off & ~0xff) != ((ee_off + size) & ~0xff)) { 99 printf("Crosses page boundary: 0x%x 0x%x\n", ee_off, size); 100 return; 101 } 102 103 status = twiPtr->TWI_SR; 104 status = twiPtr->TWI_RHR; 105 twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) | AT91C_TWI_IADRSZ_1_BYTE | 106 AT91C_TWI_MREAD; 107 twiPtr->TWI_IADR = ee_off & 0xff; 108 twiPtr->TWI_CR = AT91C_TWI_START; 109 while (size-- > 1) { 110 while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY)) 111 continue; 112 *(data_addr++) = twiPtr->TWI_RHR; 113 } 114 twiPtr->TWI_CR = AT91C_TWI_STOP; 115 status = twiPtr->TWI_SR; 116 while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 117 continue; 118 *data_addr = twiPtr->TWI_RHR; 119} 120 121 122/* 123 * .KB_C_FN_DEFINITION_START 124 * void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size) 125 * This global function writes data to the eeprom at ee_off using data 126 * from data_addr for size bytes. Assume the TWI has been initialized. 127 * This function does not utilize the page write mode as the write time is 128 * much greater than the time required to access the device for byte-write 129 * functionality. This allows the function to be much simpler. 130 * .KB_C_FN_DEFINITION_END 131 */ 132void 133EEWrite(unsigned ee_off, const char *data_addr, unsigned size) 134{ 135 const AT91PS_TWI twiPtr = AT91C_BASE_TWI; 136 unsigned status; 137 char test_data; 138 139 while (size--) { 140 // Set the TWI Master Mode Register 141 twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) | 142 AT91C_TWI_IADRSZ_1_BYTE; 143 twiPtr->TWI_IADR = ee_off++; 144 status = twiPtr->TWI_SR; 145 146 // Load one data byte 147 twiPtr->TWI_THR = *(data_addr++); 148 twiPtr->TWI_CR = AT91C_TWI_START; 149 while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY)) 150 continue; 151 twiPtr->TWI_CR = AT91C_TWI_STOP; 152 status = twiPtr->TWI_SR; 153 while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP)) 154 continue; 155 156 // wait for write operation to complete, it is done once 157 // we can read it back... 158 EERead(ee_off, &test_data, 1); 159 } 160} 161