⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 iic_adapter.c

📁 Uboot源码,非常通用的bootloader.适用于各种平台的Linux系统引导.
💻 C
字号:
/********************************************************************************     Author: Xilinx, Inc.***     This program is free software; you can redistribute it and/or modify it*     under the terms of the GNU General Public License as published by the*     Free Software Foundation; either version 2 of the License, or (at your*     option) any later version.***     XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A*     COURTESY TO YOU. BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS*     ONE POSSIBLE IMPLEMENTATION OF THIS FEATURE, APPLICATION OR STANDARD,*     XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION IS FREE*     FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE FOR OBTAINING*     ANY THIRD PARTY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.*     XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO*     THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO ANY*     WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE FROM*     CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY AND*     FITNESS FOR A PARTICULAR PURPOSE.***     Xilinx hardware products are not intended for use in life support*     appliances, devices, or systems. Use in such applications is*     expressly prohibited.***     (c) Copyright 2002-2004 Xilinx Inc.*     All rights reserved.***     You should have received a copy of the GNU General Public License along*     with this program; if not, write to the Free Software Foundation, Inc.,*     675 Mass Ave, Cambridge, MA 02139, USA.*******************************************************************************/#include <common.h>#include <environment.h>#include <net.h>#include "xparameters.h"#ifdef CFG_ENV_IS_IN_EEPROM#include <i2c.h>#include "xiic_l.h"#define IIC_DELAY     5000static u8 envStep = 0;		/* 0 means crc has not been read */const u8 hex[] = "0123456789ABCDEF"; /* lookup table for ML300 CRC *//************************************************************************ * Use Xilinx provided driver to send data to EEPROM using iic bus. */static voidsend(u32 adr, u8 * data, u32 len){	u8 sendBuf[34];		/* first 2-bit is address and others are data */	u32 pos, wlen;	u32 ret;	wlen = 32;	for (pos = 0; pos < len; pos += 32) {		if ((len - pos) < 32)			wlen = len - pos;		/* Put address and data bits together */		sendBuf[0] = (u8) ((adr + pos) >> 8);		sendBuf[1] = (u8) (adr + pos);		memcpy(&sendBuf[2], &data[pos], wlen);		/* Send to EEPROM through iic bus */		ret = XIic_Send(XPAR_IIC_0_BASEADDR, CFG_I2C_EEPROM_ADDR >> 1,				sendBuf, wlen + 2);		udelay(IIC_DELAY);	}}/************************************************************************ * Use Xilinx provided driver to read data from EEPROM using the iic bus. */static voidreceive(u32 adr, u8 * data, u32 len){	u8 address[2];	u32 ret;	address[0] = (u8) (adr >> 8);	address[1] = (u8) adr;	/* Provide EEPROM address */	ret =	    XIic_Send(XPAR_IIC_0_BASEADDR, CFG_I2C_EEPROM_ADDR >> 1, address,		      2);	/* Receive data from EEPROM */	ret =	    XIic_Recv(XPAR_IIC_0_BASEADDR, CFG_I2C_EEPROM_ADDR >> 1, data, len);}/************************************************************************ * Convert a hexadecimal string to its equivalent integer value. */static u8axtoi(u8 * hexStg){	u8 n;			/* position in string */	u8 m;			/* position in digit[] to shift */	u8 count;		/* loop index */	u8 intValue;		/* integer value of hex string */	u8 digit[2];		/* hold values to convert */	for (n = 0; n < 2; n++) {		if (hexStg[n] == '\0')			break;		if (hexStg[n] > 0x29 && hexStg[n] < 0x40)			digit[n] = hexStg[n] & 0x0f;		else if (hexStg[n] >= 'a' && hexStg[n] <= 'f')			digit[n] = (hexStg[n] & 0x0f) + 9;		else if (hexStg[n] >= 'A' && hexStg[n] <= 'F')			digit[n] = (hexStg[n] & 0x0f) + 9;		else			break;	}	intValue = 0;	count = n;	m = n - 1;	n = 0;	while (n < count) {		intValue = intValue | (digit[n] << (m << 2));		m--;		/* adjust the position to set */		n++;		/* next digit to process */	}	return (intValue);}/************************************************************************ * Convert an integer string to its equivalent value. */static u8atoi(uchar * string){	u8 res = 0;	while (*string >= '0' && *string <= '9') {		res *= 10;		res += *string - '0';		string++;	}	return res;}/************************************************************************ * Key-value pairs are separated by "=" sign. */static voidfindKey(uchar * buffer, int *loc, u8 len){	u32 i;	for (i = 0; i < len; i++)		if (buffer[i] == '=') {			*loc = i;			return;		}	/* return -1 is no "=" sign found */	*loc = -1;}/************************************************************************ * Compute a new ML300 CRC when user calls the saveenv command. * Also update EEPROM with new CRC value. */static u8update_crc(u32 len, uchar * data){	uchar temp[6] = { 'C', '=', 0x00, 0x00, 0x00, 0x00 };	u32 crc;		/* new crc value */	u32 i;	crc = 0;	/* calculate new CRC */	for (i = 0; i < len; i++)		crc += data[i];	/* CRC includes key for check sum */	crc += 'C' + '=';	/* compose new CRC to be updated */	temp[2] = hex[(crc >> 4) & 0xf];	temp[3] = hex[crc & 0xf];	/* check to see if env size exceeded */	if (len + 6 > ENV_SIZE) {		printf("ERROR: not enough space to store CRC on EEPROM");		return 1;	}	memcpy(data + len, temp, 6);	return 0;}/************************************************************************ * Read out ML300 CRC and compare it with a runtime calculated ML300 CRC. * If equal, then pass back a u-boot CRC value, otherwise pass back * junk to indicate CRC error.*/static voidread_crc(uchar * buffer, int len){	u32 addr, n;	u32 crc;		/* runtime crc */	u8 old[2] = { 0xff, 0xff };	/* current CRC in EEPROM */	u8 stop;		/* indication of end of env data */	u8 pre;			/* previous EEPROM data bit */	int i, loc;	addr = CFG_ENV_OFFSET;	/* start from first env address */	n = 0;	pre = 1;	stop = 1;	crc = 0;	/* calculate runtime CRC according to ML300 and read back	   old CRC stored in the EEPROM */	while (n < CFG_ENV_SIZE) {		receive(addr, buffer, len);		/* found two null chars, end of env */		if ((pre || buffer[0]) == 0)			break;		findKey(buffer, &loc, len);		/* found old check sum, read and store old CRC */		if ((loc == 0 && pre == 'C')		    || (loc > 0 && buffer[loc - 1] == 'C'))			receive(addr + loc + 1, old, 2);		pre = buffer[len - 1];		/* calculate runtime ML300 CRC */		crc += buffer[0];		i = 1;		do {			crc += buffer[i];			stop = buffer[i] || buffer[i - 1];			i++;		} while (stop && (i < len));		if (stop == 0)			break;		n += len;		addr += len;	}	/* exclude old CRC from runtime calculation */	crc -= (old[0] + old[1]);	/* match CRC values, send back u-boot CRC */	if ((old[0] == hex[(crc >> 4) & 0xf])	    && (old[1] == hex[crc & 0xf])) {		crc = 0;		n = 0;		addr =		    CFG_ENV_OFFSET - offsetof(env_t, crc) + offsetof(env_t,								     data);		/* calculate u-boot crc */		while (n < ENV_SIZE) {			receive(addr, buffer, len);			crc = crc32(crc, buffer, len);			n += len;			addr += len;		}		memcpy(buffer, &crc, 4);	}}/************************************************************************ * Convert IP address to hexadecimals. */static voidip_ml300(uchar * s, uchar * res){	char temp[2];	u8 i;	res[0] = 0x00;	for (i = 0; i < 4; i++) {		sprintf(temp, "%02x", atoi(s));		s = (uchar *)strchr((char *)s, '.') + 1;		strcat((char *)res, temp);	}}/************************************************************************ * Change 0xff (255), a dummy null char to 0x00. */static voidchange_null(uchar * s){	if (s != NULL) {		change_null((uchar *)strchr((char *)s + 1, 255));		*(strchr((char *)s, 255)) = '\0';	}}/************************************************************************ * Update environment variable name and values to u-boot standard. */voidconvert_env(void){	char *s;		/* pointer to env value */	char temp[20];		/* temp storage for addresses */	/* E -> ethaddr */	s = getenv("E");	if (s != NULL) {		sprintf(temp, "%c%c.%c%c.%c%c.%c%c.%c%c.%c%c",			s[0], s[1],  s[ 2], s[ 3],			s[4], s[5],  s[ 6], s[ 7],			s[8], s[9],  s[10], s[11] );		setenv("ethaddr", temp);		setenv("E", NULL);	}	/* L -> serial# */	s = getenv("L");	if (s != NULL) {		setenv("serial#", s);		setenv("L", NULL);	}	/* I -> ipaddr */	s = getenv("I");	if (s != NULL) {		sprintf(temp, "%d.%d.%d.%d", axtoi((u8 *)s), axtoi((u8 *)(s + 2)),			axtoi((u8 *)(s + 4)), axtoi((u8 *)(s + 6)));		setenv("ipaddr", temp);		setenv("I", NULL);	}	/* S -> serverip */	s = getenv("S");	if (s != NULL) {		sprintf(temp, "%d.%d.%d.%d", axtoi((u8 *)s), axtoi((u8 *)(s + 2)),			axtoi((u8 *)(s + 4)), axtoi((u8 *)(s + 6)));		setenv("serverip", temp);		setenv("S", NULL);	}	/* A -> bootargs */	s = getenv("A");	if (s != NULL) {		setenv("bootargs", s);		setenv("A", NULL);	}	/* F -> bootfile */	s = getenv("F");	if (s != NULL) {		setenv("bootfile", s);		setenv("F", NULL);	}	/* M -> bootcmd */	s = getenv("M");	if (s != NULL) {		setenv("bootcmd", s);		setenv("M", NULL);	}	/* Don't include C (CRC) */	setenv("C", NULL);}/************************************************************************ * Save user modified environment values back to EEPROM. */static voidsave_env(void){	char eprom[ENV_SIZE];	/* buffer to be written back to EEPROM */	char *s, temp[20];	char ff[] = { 0xff, 0x00 };	/* dummy null value */	u32 len;		/* length of env to be written to EEPROM */	eprom[0] = 0x00;	/* ethaddr -> E */	s = getenv("ethaddr");	if (s != NULL) {		strcat(eprom, "E=");		sprintf(temp, "%c%c%c%c%c%c%c%c%c%c%c%c",			*s, *(s + 1), *(s + 3), *(s + 4), *(s + 6), *(s + 7),			*(s + 9), *(s + 10), *(s + 12), *(s + 13), *(s + 15),			*(s + 16));		strcat(eprom, temp);		strcat(eprom, ff);	}	/* serial# -> L */	s = getenv("serial#");	if (s != NULL) {		strcat(eprom, "L=");		strcat(eprom, s);		strcat(eprom, ff);	}	/* ipaddr -> I */	s = getenv("ipaddr");	if (s != NULL) {		strcat(eprom, "I=");		ip_ml300((uchar *)s, (uchar *)temp);		strcat(eprom, temp);		strcat(eprom, ff);	}	/* serverip -> S */	s = getenv("serverip");	if (s != NULL) {		strcat(eprom, "S=");		ip_ml300((uchar *)s, (uchar *)temp);		strcat(eprom, temp);		strcat(eprom, ff);	}	/* bootargs -> A */	s = getenv("bootargs");	if (s != NULL) {		strcat(eprom, "A=");		strcat(eprom, s);		strcat(eprom, ff);	}	/* bootfile -> F */	s = getenv("bootfile");	if (s != NULL) {		strcat(eprom, "F=");		strcat(eprom, s);		strcat(eprom, ff);	}	/* bootcmd -> M */	s = getenv("bootcmd");	if (s != NULL) {		strcat(eprom, "M=");		strcat(eprom, s);		strcat(eprom, ff);	}	len = strlen(eprom);	/* find env length without crc */	change_null((uchar *)eprom);	/* change 0xff to 0x00 */	/* update EEPROM env values if there is enough space */	if (update_crc(len, (uchar *)eprom) == 0)		send(CFG_ENV_OFFSET, (uchar *)eprom, len + 6);}/************************************************************************ * U-boot call for EEPROM read associated activities. */inti2c_read(uchar chip, uint addr, int alen, uchar * buffer, int len){	if (envStep == 0) {		/* first read call is for crc */		read_crc(buffer, len);		++envStep;		return 0;	} else if (envStep == 1) {		/* then read out EEPROM content for runtime u-boot CRC calculation */		receive(addr, buffer, len);		if (addr + len - CFG_ENV_OFFSET == CFG_ENV_SIZE)			/* end of runtime crc read */			++envStep;		return 0;	}	if (len < 2) {		/* when call getenv_r */		receive(addr, buffer, len);	} else if (addr + len < CFG_ENV_OFFSET + CFG_ENV_SIZE) {		/* calling env_relocate(), but don't read out		   crc value from EEPROM */		receive(addr, buffer + 4, len);	} else {		receive(addr, buffer + 4, len - 4);	}	return 0;}/************************************************************************ * U-boot call for EEPROM write acativities. */inti2c_write(uchar chip, uint addr, int alen, uchar * buffer, int len){	/* save env on last page write called by u-boot */	if (addr + len >= CFG_ENV_OFFSET + CFG_ENV_SIZE)		save_env();	return 0;}/************************************************************************ * Dummy function. */inti2c_probe(uchar chip){	return 1;}#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -