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

📄 emac_phy.c

📁 某个ARM9板子的实际bootloader 对裁剪
💻 C
📖 第 1 页 / 共 2 页
字号:
/***************************************************************************** Copyright  Storlink Corp 2005.  All rights reserved.                *--------------------------------------------------------------------------* Name			: emac_phy.c* Description	: *		Handle Ethernet PHY and MII interface** History**	Date		Writer		Description*	-----------	-----------	-------------------------------------------------*	04/25/2005	Gary Chen	Create and implement from Jason's Redboot code*****************************************************************************/#include <define.h>#include <board_config.h>#include <sl2312.h>#ifndef MIDWAY#include "emac_sl2312.h"#define diag_printf			printf#define printk				printf/************************************************//*                 function declare             *//************************************************/unsigned int mii_read(unsigned char phyad,unsigned char regad);void mii_write(unsigned char phyad,unsigned char regad,unsigned int value);void emac_set_phy_status(void);void emac_get_phy_status(void);void outb(unsigned int addr, unsigned int value);unsigned char inb(unsigned int addr);/****************************************//*	SPI Function Declare		*//****************************************/void SPI_write(unsigned char addr,unsigned int value);unsigned int SPI_read(unsigned char table,unsigned char addr);void SPI_write_bit(char bit_EEDO);unsigned int SPI_read_bit(void);void SPI_default(int vlan_enabled);void SPI_reset(unsigned char rstype,unsigned char port_cnt);void SPI_pre_st(void);void SPI_CS_enable(unsigned char enable);void SPI_Set_VLAN(unsigned char LAN,unsigned int port_mask);void SPI_Set_tag(unsigned int port,unsigned tag);void SPI_Set_PVID(unsigned int PVID,unsigned int port_mask);unsigned int SPI_Get_PVID(unsigned int port);void SPI_mac_lock(unsigned int port, unsigned char lock);void SPI_get_port_state(unsigned int port);void SPI_port_enable(unsigned int port,unsigned char enable);unsigned int SPI_get_identifier(void);void SPI_get_status(unsigned int port);/****************************************//*	VLAN Function Declare		        *//****************************************/extern unsigned int FLAG_SWITCH;	/* if 1-->switch chip presented. if 0-->switch chip unpresented */extern unsigned int full_duplex;extern unsigned int chip_id;struct emac_conf VLAN_conf[] = { #ifdef CONFIG_ADM_6999		{ (struct net_device *)0,0x7F,1 }, 	{ (struct net_device *)0,0x80,2 } #endif#ifdef CONFIG_ADM_6996	{ (struct net_device *)0,0x0F,1 }, 	{ (struct net_device *)0,0x10,2 } #endif};#define NUM_VLAN_IF	(sizeof(VLAN_conf)/sizeof(struct emac_conf))/************************************************//*                 function body                *//************************************************/#define emac_read_reg(offset)					REG32(EMAC_BASE_ADDR + offset)#define emac_write_reg(offset, data, mask)		REG32(EMAC_BASE_ADDR + offset) = 	\												(emac_read_reg(offset) & (~mask)) | \												(data & mask)#define readl(addr)								REG32(addr)#define writel(value, addr)						REG32(addr) = value        			//module_init(emac_init_module);//module_exit(emac_cleanup_module);void emac_set_phy_status(void){    unsigned int value;    unsigned int i = 0;    if (FLAG_SWITCH==1)    {        return; /* EMAC connects to a switch chip, not PHY */    }		return;#ifndef LPC_IT8712	// Disable GPIO pins switch to LPC PAD    REG32(SL2312_GLOBAL_BASE + GLOBAL_MISC_CTRL) &=  ~0x00000018;#endif	#define CONFIG_SL2312_ASIC            #ifdef CONFIG_SL2312_ASIC        mii_write(PHY_ADDR,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */#else    mii_write(PHY_ADDR,0x04,0x0461); /* advertisement 10M full duplex, pause capable on */#endif        mii_write(PHY_ADDR,0x00,0x1200);	hal_delay_us(100000);    while (((value=mii_read(PHY_ADDR,0x01)) & 0x00000004)!=0x04)    {    	hal_delay_us(1000);        i++;        if (i > 50)        {            break ;        }    }	if (i > 50)		diag_printf("Link Down\n");	else    	diag_printf("Link Up (%04x)\n",value);        value = (mii_read(PHY_ADDR,0x05) & 0x05E0) >> 5;    printk("PHY Status = %x \n", value);    if ((value & 0x08)==0x08) /* 100M full duplex */    {                     full_duplex = 1;            printk(" 100M/Full \n");     }    else if ((value & 0x04)==0x04) /* 100M half duplex */    {                           full_duplex = 0;            printk(" 100M/Half \n");     }    else if ((value & 0x02)==0x02) /* 10M full duplex */    {                    full_duplex = 1;            printk(" 10M/Full \n");     }    else if ((value & 0x01)==0x01) /* 10M half duplex */    {            full_duplex = 0;            printk(" 10M/Half \n");     }    if ((value & 0x20)==0x20)    {        // flow_control_enable = 1;        printk("Flow Control Enable. \n");    }    else    {        // flow_control_enable = 0;        printk("Flow Control Disable. \n");    }    }    void emac_get_phy_status(void){    EMAC_STATUS_T   status;    unsigned int    reg_val;        status.bits32 = 0;    status.bits.phy_mode = 0;    status.bits.mii_rmii = 0;    /* read PHY status register */    reg_val = mii_read(PHY_ADDR,0x01);    if ((reg_val & 0x0024) == 0x0024) /* link is established and auto_negotiate process completed */    {        /* read PHY Auto-Negotiation Link Partner Ability Register */        reg_val = (mii_read(PHY_ADDR,0x05) & 0x01E0) >> 5;        switch (reg_val)        {            case 8: /* 100M full duplex */                status.bits.duplex = 1;                status.bits.speed = 1;                break;                            case 4: /* 100M half duplex */                status.bits.duplex = 0;                status.bits.speed = 1;                break;                            case 2: /* 10M full duplex */                status.bits.duplex = 1;                status.bits.speed = 0;                break;                            case 1: /* 10M half duplex */                status.bits.duplex = 0;                status.bits.speed = 0;                break;        }        status.bits.link = 1; /* link up */    }    else    {        status.bits.link = 0; /* link down */    }    status.bits.speed = 1; /* force EMAC to 100M */    emac_write_reg(EMAC_STATUS,status.bits32,0x0000001f);}    /***************************************//* define GPIO module base address     *//***************************************/#define GPIO_BASE_ADDR      (0x21000000)#define GPIO_MDC			(1 << BOARD_MDC_GPIO_PIN)	// 0x80000000#define GPIO_MDIO			(1 << BOARD_MDIO_GPIO_PIN)	// 0x00400000    enum GPIO_REG{    GPIO_DATA_OUT   = 0x00,    GPIO_DATA_IN    = 0x04,    GPIO_PIN_DIR    = 0x08,    GPIO_BY_PASS    = 0x0c,    GPIO_DATA_SET   = 0x10,    GPIO_DATA_CLEAR = 0x14,};/***********************//*    MDC : GPIO[31]   *//*    MDIO: GPIO[22]   *//***********************/      /**************************************************** All the commands should have the frame structure:*<PRE><ST><OP><PHYAD><REGAD><TA><DATA><IDLE>****************************************************//****************************************************************** Inject a bit to NWay register through CSR9_MDC,MDIO*******************************************************************/void mii_serial_write(char bit_MDO) // write data into mii PHY{#if 1    unsigned int addr;    unsigned int value;    addr = GPIO_BASE_ADDR + GPIO_PIN_DIR;    value = readl(addr) | GPIO_MDC | GPIO_MDIO; /* set MDC/MDIO Pin to output */    writel(value,addr);    if(bit_MDO)    {        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);        writel(GPIO_MDIO,addr); /* set MDIO to 1 */        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);        writel(GPIO_MDC,addr); /* set MDC to 1 */        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);        writel(GPIO_MDC,addr); /* set MDC to 0 */                        }    else    {        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);        writel(GPIO_MDIO,addr); /* set MDIO to 0 */        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);        writel(GPIO_MDC,addr); /* set MDC to 1 */        addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);        writel(GPIO_MDC,addr); /* set MDC to 0 */                        }   #else        unsigned int *addr;    unsigned int value;    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_PIN_DIR);    value = (*addr) | 0x80400000;   /* set MDC/MDIO Pin to output */    *addr = value;    if(bit_MDO){        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);        *addr = 0x00400000; /* set MDIO to 1 */        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);        *addr = 0x80000000; /* set MDC to 1 */        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);        *addr = 0x80000000; /* set MDC to 0 */                        }    else{        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);        *addr = 0x00400000; /* set MDIO to 0 */        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);        *addr = 0x80000000; /* set MDC to 1 */        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);        *addr = 0x80000000; /* set MDC to 0 */                        }       return ;#endif    }/*********************************************************************** read a bit from NWay register through CSR9_MDC,MDIO***********************************************************************/unsigned int mii_serial_read(void) // read data from mii PHY{#if 1    unsigned int addr;    unsigned int value;        addr = (GPIO_BASE_ADDR + GPIO_PIN_DIR);    value = readl(addr) | GPIO_MDC & (~GPIO_MDIO); //0xffbfffff;   /* set MDC to output and MDIO to input */    writel(value,addr);        addr = (GPIO_BASE_ADDR + GPIO_DATA_SET);    writel(GPIO_MDC,addr); /* set MDC to 1 */    addr = (GPIO_BASE_ADDR + GPIO_DATA_CLEAR);    writel(GPIO_MDC,addr); /* set MDC to 0 */                        addr = (GPIO_BASE_ADDR + GPIO_DATA_IN);    value = readl(addr);    value = (value & GPIO_MDIO) >> BOARD_MDIO_GPIO_PIN;    return(value);#else        unsigned int *addr;    unsigned int value;        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_PIN_DIR);    value = (*addr) & 0xffbfffff;   /* set MDC to output and MDIO to input */    *addr = value;        addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET);    *addr = 0x80000000; /* set MDC to 1 */    addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR);    *addr = 0x80000000; /* set MDC to 0 */                        value = *(unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_IN);    value = (value & 0x00400000) >> 22;    return(value);#endif    }/**************************************** preamble + ST***************************************/void mii_pre_st(void){    unsigned char i;    for(i=0;i<32;i++) // PREAMBLE        mii_serial_write(1);    mii_serial_write(0); // ST    mii_serial_write(1);}/******************************************* Read MII register* phyad -> physical address* regad -> register address***************************************** */unsigned int mii_read(unsigned char phyad,unsigned char regad){    unsigned int i,value;    unsigned int bit;        mii_pre_st(); // PRE+ST    mii_serial_write(1); // OP    mii_serial_write(0);    for (i=0;i<5;i++) { // PHYAD        bit= ((phyad>>(4-i)) & 0x01) ? 1 :0 ;        mii_serial_write(bit);    }        for (i=0;i<5;i++) { // REGAD        bit= ((regad>>(4-i)) & 0x01) ? 1 :0 ;        mii_serial_write(bit);    }        mii_serial_read(); // TA_Z//    if((bit=mii_serial_read()) !=0 ) // TA_0//    {//        return(0);        //    }    value=0;    for (i=0;i<16;i++) { // READ DATA        bit=mii_serial_read();        value += (bit<<(15-i)) ;    }    

⌨️ 快捷键说明

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