📄 smc_rv.c
字号:
{ 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 + -