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

📄 smc9118.c

📁 U-boot源码 ARM7启动代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------ . smc9118.c . This is a driver for SMSC's LAN9118 single-chip Ethernet device. . . (C) Copyright 2006 ARM Ltd. <www.arm.com> . . 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. . . This program is distributed in the hope that it will be useful, . but WITHOUT ANY WARRANTY; without even the implied warranty of . MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the . GNU General Public License for more details. . . 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307	 USA . . Device information contained in this file was obtained from the LAN9118 . manual from SMC <www.smsc.com>. . . author: .	Peter Pearse				( peter.pearse@arm.com) . . Sources: .    o	  SMSC LAN9118 databook (www.smsc.com) .    o	  drivers/smc91111.c . . History: .	2006.10.24	Peter Pearse	Initial version based on drivers/smc91111.c	 .                                      - Dropped board specific code .                                      - Dropped #if 0 code,  .                                        it's in smc91111.c if you want it  .                                      - Made all but interface functions static .                                      - Add in ARM smc9118 code ----------------------------------------------------------------------------*/#include <common.h>#include <command.h>#include <config.h>#include "smc9118.h"#include <net.h>#ifdef CONFIG_DRIVER_SMC9118#define SMC9118_DEV_NAME "SMC9118"#ifndef CONFIG_SMC9118_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_SMC9118_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 *//*----------------------------------------------------------------- . .  The driver can be entered at any of the following entry points. . .------------------------------------------------------------------  */int  eth_init(bd_t *bd);void eth_halt(void);int  eth_rx(void);int  eth_send(volatile void *packet, int length);#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_SMC9118_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;    unsigned int id;    error = 0;    id = smsc9118_read_id();    switch(((id >> 16) & 0xFFFF)) {        case 0x118:            // If bottom and top halves of the words are the same            if(((id >> 16) & 0xFFFF) == (id & 0xFFFF)) {                printf("Error: The SMSC9118 bus is in 16-bit mode. 32-bit mode was expected.\n");                error = 1;                return error;            } else {                printf("SMSC9118 is identified successfully.\n");                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;}static int smsc9118_wait_eeprom(void){    int timedout = 0;    // Wait    ulong start = get_timer(0);    while (!timedout && (*SMSC9118_E2P_CMD & ((unsigned int) 1 << 31))){    	timedout = get_timer(start) < MS50 ? 0 : 1;    }    return timedout;}static 

⌨️ 快捷键说明

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