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

📄 smc_rv.c

📁 U-boot源码 ARM7启动代码
💻 C
📖 第 1 页 / 共 5 页
字号:
{	int env_size, rom_valid, env_present = 0, reg;	char *s = NULL, *e, *v_mac, es[] = "11:22:33:44:55:66";	char s_env_mac[64];	uchar v_env_mac[6], v_rom_mac[6];	env_size = getenv_r ("ethaddr", s_env_mac, sizeof (s_env_mac));	if ((env_size > 0) && (env_size < sizeof (es))) {	/* exit if env is bad */		printf ("\n*** ERROR: ethaddr is not set properly!!\n");		return (-1);	}	if (env_size > 0) {		env_present = 1;		s = s_env_mac;	}	for (reg = 0; reg < 6; ++reg) { /* turn string into mac value */		v_env_mac[reg] = s ? simple_strtoul (s, &e, 16) : 0;		if (s)			s = (*e) ? e + 1 : e;	}	rom_valid = get_rom_mac (v_rom_mac);	/* get ROM mac value if any */	if (!env_present) {	/* if NO env */		if (rom_valid) {	/* but ROM is valid */			v_mac = (char *)v_rom_mac;			sprintf (s_env_mac, "%02X:%02X:%02X:%02X:%02X:%02X",				 v_mac[0], v_mac[1], v_mac[2], v_mac[3],				 v_mac[4], v_mac[5]);			setenv ("ethaddr", s_env_mac);		} else {	/* no env, bad ROM */			printf ("\n*** ERROR: ethaddr is NOT set !!\n");			return (-1);		}	} else {		/* good env, don't care ROM */		v_mac = (char *)v_env_mac;	/* always use a good env over a ROM */	}	if (env_present && rom_valid) { /* if both env and ROM are good */		if (memcmp (v_env_mac, v_rom_mac, 6) != 0) {			printf ("\nWarning: MAC addresses don't match:\n");			printf ("\tHW MAC address:  "				"%02X:%02X:%02X:%02X:%02X:%02X\n",				v_rom_mac[0], v_rom_mac[1],				v_rom_mac[2], v_rom_mac[3],				v_rom_mac[4], v_rom_mac[5] );			printf ("\t\"ethaddr\" value: "				"%02X:%02X:%02X:%02X:%02X:%02X\n",				v_env_mac[0], v_env_mac[1],				v_env_mac[2], v_env_mac[3],				v_env_mac[4], v_env_mac[5]) ;			debug ("### Set MAC addr from environment\n");		}	}	memcpy (bd->bi_enetaddr, v_mac, 6);	/* update global address to match env (allows env changing) */	smc_set_mac_addr ((uchar *)v_mac);	/* use old function to update smc default */	PRINTK("Using MAC Address %02X:%02X:%02X:%02X:%02X:%02X\n", v_mac[0], v_mac[1],		v_mac[2], v_mac[3], v_mac[4], v_mac[5]);	return (0);}int get_rom_mac (uchar *v_rom_mac){#ifdef HARDCODE_MAC	/* used for testing or to supress run time warnings */	char hw_mac_addr[] = { 0x02, 0x80, 0xad, 0x20, 0x31, 0xb8 };	memcpy (v_rom_mac, hw_mac_addr, 6);	return (1);#else	int i;	int valid_mac = 0;	SMC_SELECT_BANK (1);	for (i=0; i<6; i++)	{		v_rom_mac[i] = SMC_inb ((ADDR0_REG + i));		valid_mac |= v_rom_mac[i];	}	return (valid_mac ? 1 : 0);#endif}// 91111 code end// 9118 code start#define SMC9118_DEV_NAME "SMC9118"#ifndef CONFIG_SMC_RV_BASE	include/configs/<board>.h must define the base address of the device registers#endif#define SMC9118_DBG 0#if SMC9118_DBG > 1static const char version[] =	"smc9118.c:v1.0 06/10/24 by Peter Pearse <peter.pearse@arm.com>\n";#endif#if (SMC9118_DBG > 2 )# define PRINTK3(args...) printf(args)#else# define PRINTK3(args...)#endif#if SMC9118_DBG > 1# define PRINTK2(args...) printf(args)#else# define PRINTK2(args...)#endif#ifdef SMC9118_DBG# define PRINTK(args...) printf(args)#else# define PRINTK(args...)#endif#if SMC9118_DBG > 0static void smsc9118_print_mac_registers(void){    unsigned int read;    int i;    i = 0;    read = 0;    for(i = 1; i <= 0xC; i++) {        smsc9118_mac_regread(i, &read);        debug("MAC Register %02d: 0x%08x\n",i,read);    }    debug("\n");    return;}static void smsc9118_print_registers(void){    volatile unsigned int *i;    for  (i = (volatile unsigned int *)CONFIG_SMC_RV_BASE; (int)i < (int)SMSC9118_RESERVED3; i++){        debug("Register @%p 0x%08x\n",i, *i);    }} static void smsc9118_print_phy_registers(void){    unsigned short read;    unsigned int i;    i = 0;    read = 0;    for(i = 0; i <= 6; i++) {        smsc9118_phy_regread(i, &read);        debug("PHY Register %02d: 0x%08x\n",i,read);    }    smsc9118_phy_regread(i = 17, &read);    debug("Phy Register %02d: 0x%08x\n", i, read);    smsc9118_phy_regread(i = 18, &read);    debug("Phy Register %02d: 0x%08x\n", i, read);    smsc9118_phy_regread(i = 27, &read);    debug("Phy Register %02d: 0x%08x\n", i, read);    smsc9118_phy_regread(i = 29, &read);    debug("Phy Register %02d: 0x%08x\n", i, read);    smsc9118_phy_regread(i = 30, &read);    debug("Phy Register %02d: 0x%08x\n", i, read);    smsc9118_phy_regread(i = 31, &read);    debug("Phy Register %02d: 0x%08x\n", i, read);    debug("\n");    return;}#endif /* SMC9118_DBG > 0 */#ifdef SHARED_RESOURCES/* * Resource swapper */void swap_to(int device_id);#endif/* * ---------------------------------------------------------- * * Chip register access routines * * ---------------------------------------------------------- */static int smsc9118_mac_regread(unsigned char regoffset, unsigned int *data){    unsigned int val, maccmd;    int timedout;    int error;    ulong start;    error = 0;    val = *SMSC9118_MAC_CSR_CMD;    if(!(val & ((unsigned int)1 << 31))) {    // Make sure there's no pending operation        maccmd = 0;        maccmd |= regoffset;        maccmd |= ((unsigned int)1 << 30);     // Indicates read        maccmd |= ((unsigned int)1 << 31);     // Start bit        *SMSC9118_MAC_CSR_CMD = maccmd; // Start operation	start = get_timer (0);        do {	    timedout = get_timer(start) > MS50 ? 1 : 0;            val = *SMSC9118_BYTE_TEST;  // A no-op read.        } while(!timedout && (*SMSC9118_MAC_CSR_CMD & ((unsigned int)1 << 31)));        if(timedout) {            printf("Error: SMSC9118 MAC CSR read operation timed out.\n");            error = 1;            return error;        }        *data = *SMSC9118_MAC_CSR_DATA;    } else {        printf("Warning: SMSC9118 MAC CSR is busy. No data read.\n");        *data = 0;    }    return 0;}static int smsc9118_mac_regwrite(unsigned char regoffset, unsigned int val){    unsigned int read, maccmd;    int timedout;    int error;    ulong start;    debug("MAC[%02d] write 0x%08x \n", regoffset, val);    error = 0;    read = *SMSC9118_MAC_CSR_CMD;    if(!(read & ((unsigned int)1 << 31))) { // Make sure there's no pending operation        *SMSC9118_MAC_CSR_DATA = val;       // Load data.        maccmd = 0;        maccmd |= regoffset;        maccmd &= ~((unsigned int)1 << 30); // Clear indicates write        maccmd |= ((unsigned int)1 << 31);  // Indicate start of operation        *SMSC9118_MAC_CSR_CMD = maccmd;	start = get_timer (0);        do {	    timedout = get_timer(start) > MS50 ? 1 : 0;            read = *SMSC9118_BYTE_TEST;     // A no-op read.        } while(!timedout && (*SMSC9118_MAC_CSR_CMD & ((unsigned int)1 << 31)));        if(timedout) {            printf("Error: SMSC9118 MAC CSR write operation timed out.\n");            error = 1;            return error;        }    } else {        printf("Warning: SMSC9118 MAC CSR is busy. No data written.\n");    }    return 0;}static int smsc9118_phy_regread(unsigned char regoffset, unsigned short *data){    unsigned int val, phycmd; int error;    int timedout;    ulong start;    error = 0;    smsc9118_mac_regread(SMSC9118_MAC_MII_ACC, &val);    if(!(val & 1)) {				// Not busy        phycmd = 0;        phycmd |= (1 << 11);			// 1 to [15:11]        phycmd |= ((regoffset & 0x1F) << 6);	// Put regoffset to [10:6]        phycmd &= ~(1 << 1);			// Clear [1] indicates read.        phycmd |= (1 << 0);			// Set [0] indicates operation start        smsc9118_mac_regwrite(SMSC9118_MAC_MII_ACC, phycmd);	        val = 0;        timedout = 0;	start = get_timer (0);        do {	    timedout = get_timer(start) > MS50 ? 1 : 0;            smsc9118_mac_regread(SMSC9118_MAC_MII_ACC,&val);        } while(!timedout && (val & ((unsigned int)1 << 0)));        if(timedout) {            printf("Error: SMSC9118 MAC MII read operation timed out.\n");            error = 1;            return error;        }        smsc9118_mac_regread(SMSC9118_MAC_MII_DATA, &val);    } else {        printf("Warning: SMSC9118 MAC MII is busy. No data read.\n");        val = 0;    }    *data = (unsigned short)(val & 0xFFFF);    return 0;}static int smsc9118_phy_regwrite(unsigned char regoffset, unsigned short data){    unsigned int val, phycmd, u32data; int error;    int timedout;    ulong start;    u32data = (unsigned int)data;    debug("PHY[%02d] write 0x%08x \n", regoffset, u32data);    smsc9118_mac_regread(SMSC9118_MAC_MII_ACC, &val);    if(!(val & 1)) {    // Not busy        smsc9118_mac_regwrite(SMSC9118_MAC_MII_DATA, u32data); // Load the data        phycmd = 0;        phycmd |= (1 << 11);                    // 1 to [15:11]        phycmd |= ((regoffset & 0x1F) << 6);     // Put regoffset to [10:6]        phycmd |= (1 << 1);                     // Set [1] indicates write.        phycmd |= (1 << 0);                     // Set [0] indicates operation start        smsc9118_mac_regwrite(SMSC9118_MAC_MII_ACC, phycmd);   // Start operation        phycmd = 0;        timedout = 0;	start = get_timer (0);        do {	    timedout = get_timer(start) > MS50 ? 1 : 0;            smsc9118_mac_regread(SMSC9118_MAC_MII_ACC, &phycmd);        } while(!timedout && (phycmd & (1 << 0)));        if(timedout) {            printf("Error: SMSC9118 MAC MII write operation timed out.\n");            error = 1;            return error;        }    } else {        printf("Warning: SMSC9118 MAC MII is busy. No data written.\n");    }    return 0;}/* ------------------------------------------------------------ . . Internal routines . ------------------------------------------------------------*//* * Functions left as in/outu16, even for ARM where ARM WORD == 32 bits == (2* Other Architecture Word) * until we decide we can't use the common functions..... */#ifdef CONFIG_SMC_USE_IOFUNCS/* * input and output functions * - the access macros defined in smc9118.h may not  *   work for other boards - they have only been tested on  *   ARM RealViewEB Revision D boards  * *   This code is copied from smc91111.c (functions & types renamed), *   however 16 bit access may be different for SMC9118  *   - see the datasheet & test well before use * */# if defined(CONFIG_SMC_USE_32_BIT)	32 bit access functions not yet provided# elsestatic inline u16 SMC9118_inu16(u32 offset);static inline void SMC9118_outu16(u16 value, u32 offset);static inline u8 SMC9118_inu8(u32 offset);static inline void SMC9118_outu8(u8 value, u32 offset);static inline void SMC9118_ins16(u32 offset, volatile uchar* buf, u32 len);static inline void SMC9118_outs16(u32 offset, uchar* buf, u32 len);#define barrier() __asm__ __volatile__("": : :"memory")#define SMC9118_BASE_ADDRESS CONFIG_SMC_RV_BASEstatic inline u16 SMC9118_inu16(u32 offset){	u16 v;	v = *((volatile u16*)(SMC9118_BASE_ADDRESS+offset));	barrier(); *(volatile u32*)(0xc0000000);	return v;}static inline void SMC9118_outu16(u16 value, u32 offset){	*((volatile u16*)(SMC9118_BASE_ADDRESS+offset)) = value;	barrier(); *(volatile u32*)(0xc0000000);}static inline u8 SMC9118_inu8(u32 offset){	u16  _w;	_w = SMC9118_inu16(offset & ~((u32)1));	return (offset & 1) ? (u8)(_w >> 8) : (u8)(_w);}static inline void SMC9118_outu8(u8 value, u32 offset){	u16  _w;	_w = SMC9118_inu16(offset & ~((u32)1));	if (offset & 1)			*((volatile u16*)(SMC9118_BASE_ADDRESS+(offset & ~((u32)1)))) = (value<<8) | (_w & 0x00ff);	else			*((volatile u16*)(SMC9118_BASE_ADDRESS+offset)) = value | (_w & 0xff00);}static inline void SMC9118_ins16(u32 offset, volatile uchar* buf, u32 len){	volatile u16 *p = (volatile u16 *)buf;	while (len-- > 0) {		*p++ = SMC9118_inu16(offset);		barrier();		*((volatile u32*)(0xc0000000));	}}static inline void SMC9118_outs16(u32 offset, uchar* buf, u32 len){	volatile u16 *p = (volatile u16 *)buf;	while (len-- > 0) {		SMC9118_outu16(*p++, offset);		barrier();		*(volatile u32*)(0xc0000000);	}}# endif#endif  /* CONFIG_SMC_USE_IOFUNCS */// Returns smsc9118 id.static unsigned int smsc9118_read_id(void){    return *SMSC9118_ID_REV;}static int smsc9118_check_id(void){    int error = 0;    unsigned int id;    id = smsc9118_read_id();    switch(((id >> 16) & 0xFFFF)) {        case 0x118:            // If bottom and top halves of the words are the same	    // then the bus mode is incorrect            if(((id >> 16) & 0xFFFF) == (id & 0xFFFF)) {                printf("Error: The SMSC9118 bus is in 16-bit mode. 32-bit mode was expected.\n");                error = 1;            }             break;        default:            printf("Error: SMSC9118 id reads: 0x%08x, either an unknown chip, or error.\n",id);            error = 1;            break;    }    if((id & 0xFFFF) == 0) {        printf("Error: This test is not intended for this chip revision.\n");        error = 1;    }    return error;}// Initiates a soft reset, returns failure or success.static __inline int smsc9118_soft_reset(void){    int timedout = 0;    ulong start;    // Soft reset    *SMSC9118_HW_CFG |= 1;    // Wait    start = get_timer(0);    while (!timedout && (*SMSC9118_HW_CFG & 1)){    	timedout = get_timer(start) < MS10 ? 0 : 1;    }    return timedout;}static __inline void smsc9118_set_txfifo(unsigned int val){    // 2kb minimum, 14kb maximum    if(val < 2 || val > 14)        return;    *SMSC9118_HW_CFG = val << 16;}

⌨️ 快捷键说明

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