config root man

Current Path : /usr/src/sys/boot/arm/at91/bootspi/

FreeBSD hs32.drive.ne.jp 9.1-RELEASE FreeBSD 9.1-RELEASE #1: Wed Jan 14 12:18:08 JST 2015 root@hs32.drive.ne.jp:/sys/amd64/compile/hs32 amd64
Upload File :
Current File : //usr/src/sys/boot/arm/at91/bootspi/ee.c

/******************************************************************************
 *
 * Filename: eeprom.c
 *
 * Instantiation of eeprom routines
 *
 * Revision information:
 *
 * 28AUG2004	kb_admin	initial creation - adapted from Atmel sources
 * 12JAN2005	kb_admin	fixed clock generation, write polling, init
 *
 * BEGIN_KBDD_BLOCK
 * No warranty, expressed or implied, is included with this software.  It is
 * provided "AS IS" and no warranty of any kind including statutory or aspects
 * relating to merchantability or fitness for any purpose is provided.  All
 * intellectual property rights of others is maintained with the respective
 * owners.  This software is not copyrighted and is intended for reference
 * only.
 * END_BLOCK
 *
 * $FreeBSD: release/9.1.0/sys/boot/arm/at91/bootspi/ee.c 163598 2006-10-21 22:51:21Z imp $
 *****************************************************************************/

#include "at91rm9200_lowlevel.h"
#include "at91rm9200.h"
#include "lib.h"
#include "ee.h"

/******************************* GLOBALS *************************************/


/*********************** PRIVATE FUNCTIONS/DATA ******************************/


/* Use a macro to calculate the TWI clock generator value to save code space. */
#define AT91C_TWSI_CLOCK	100000
#define TWSI_EEPROM_ADDRESS	0x40

#define TWI_CLK_BASE_DIV	((AT91C_MASTER_CLOCK/(4*AT91C_TWSI_CLOCK)) - 2)
#define SET_TWI_CLOCK	((0x00010000) | (TWI_CLK_BASE_DIV) | (TWI_CLK_BASE_DIV << 8))


/*************************** GLOBAL FUNCTIONS ********************************/


/*
 * .KB_C_FN_DEFINITION_START
 * void InitEEPROM(void)
 *  This global function initializes the EEPROM interface (TWI).  Intended
 * to be called a single time.
 * .KB_C_FN_DEFINITION_END
 */
void
EEInit(void)
{

	AT91PS_TWI twiPtr = (AT91PS_TWI)AT91C_BASE_TWI;

	AT91PS_PIO pPio = (AT91PS_PIO)AT91C_BASE_PIOA;
	AT91PS_PMC pPMC = (AT91PS_PMC)AT91C_BASE_PMC;

	pPio->PIO_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
	pPio->PIO_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK;

	pPio->PIO_MDDR = ~AT91C_PA25_TWD;
	pPio->PIO_MDER = AT91C_PA25_TWD;

	pPMC->PMC_PCER = 1u << AT91C_ID_TWI;

	twiPtr->TWI_IDR = 0xffffffffu;
	twiPtr->TWI_CR = AT91C_TWI_SWRST;
	twiPtr->TWI_CR = AT91C_TWI_MSEN | AT91C_TWI_SVDIS;

	twiPtr->TWI_CWGR = SET_TWI_CLOCK;
}

static inline unsigned
iicaddr(unsigned ee_off)
{
    return (TWSI_EEPROM_ADDRESS | ((ee_off >> 8) & 0x7));
}


/*
 * .KB_C_FN_DEFINITION_START
 * void ReadEEPROM(unsigned ee_addr, char *data_addr, unsigned size)
 *  This global function reads data from the eeprom at ee_addr storing data
 * to data_addr for size bytes.  Assume the TWI has been initialized.
 * This function does not utilize the page read mode to simplify the code.
 * .KB_C_FN_DEFINITION_END
 */
void
EERead(unsigned ee_off, char *data_addr, unsigned size)
{
	const AT91PS_TWI 	twiPtr = AT91C_BASE_TWI;
	unsigned int status;

	if ((ee_off & ~0xff) != ((ee_off + size) & ~0xff)) {
		printf("Crosses page boundary: 0x%x 0x%x\n", ee_off, size);
		return;
	}

	status = twiPtr->TWI_SR;
	status = twiPtr->TWI_RHR;
	twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) | AT91C_TWI_IADRSZ_1_BYTE |
	    AT91C_TWI_MREAD;
	twiPtr->TWI_IADR = ee_off & 0xff;
	twiPtr->TWI_CR = AT91C_TWI_START;
	while (size-- > 1) {
		while (!(twiPtr->TWI_SR & AT91C_TWI_RXRDY))
			continue;
		*(data_addr++) = twiPtr->TWI_RHR;
	}
	twiPtr->TWI_CR = AT91C_TWI_STOP;
	status = twiPtr->TWI_SR;
	while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
		continue;
	*data_addr = twiPtr->TWI_RHR;
}


/*
 * .KB_C_FN_DEFINITION_START
 * void WriteEEPROM(unsigned ee_off, char *data_addr, unsigned size)
 *  This global function writes data to the eeprom at ee_off using data
 * from data_addr for size bytes.  Assume the TWI has been initialized.
 * This function does not utilize the page write mode as the write time is
 * much greater than the time required to access the device for byte-write
 * functionality.  This allows the function to be much simpler.
 * .KB_C_FN_DEFINITION_END
 */
void
EEWrite(unsigned ee_off, const char *data_addr, unsigned size)
{
	const AT91PS_TWI 	twiPtr = AT91C_BASE_TWI;
	unsigned		status;
	char			test_data;

	while (size--) {
		// Set the TWI Master Mode Register
		twiPtr->TWI_MMR = (iicaddr(ee_off) << 16) |
		    AT91C_TWI_IADRSZ_1_BYTE;
		twiPtr->TWI_IADR = ee_off++;
		status = twiPtr->TWI_SR;

		// Load one data byte
		twiPtr->TWI_THR = *(data_addr++);
		twiPtr->TWI_CR = AT91C_TWI_START;
		while (!(twiPtr->TWI_SR & AT91C_TWI_TXRDY))
			continue;
		twiPtr->TWI_CR = AT91C_TWI_STOP;
		status = twiPtr->TWI_SR;
		while (!(twiPtr->TWI_SR & AT91C_TWI_TXCOMP))
			continue;

		// wait for write operation to complete, it is done once
		// we can read it back...
		EERead(ee_off, &test_data, 1);
	}
}

Man Man