📄 gmac_phy.c
字号:
/***************************************************************************** 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>#ifdef MIDWAY#ifndef LEPUS_FPGA #ifndef LEPUS_ASIC#include "gmac_sl2312.h"#define diag_printf 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 gmac_set_phy_status(void);void gmac_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 gmac_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 gmac_conf))/************************************************//* function body *//************************************************/#define gmac_read_reg(offset) REG32(GMAC_BASE_ADDR + offset)#define gmac_write_reg(offset, data, mask) REG32(GMAC_BASE_ADDR + offset) = \ (gmac_read_reg(offset) & (~mask)) | \ (data & mask)#define readl(addr) REG32(addr)#define writel(value, addr) REG32(addr) = value //module_init(gmac_init_module);//module_exit(gmac_cleanup_module);void gmac_set_phy_status(void){ unsigned int value; unsigned int i = 0; if (FLAG_SWITCH==1) { return; /* GMAC connects to a switch chip, not PHY */ } // mii_write(PHY_ADDR,0x04,0x61);#ifdef GEMINI_ASIC mii_write(PHY_ADDR,0x04,0x05e1); mii_write(PHY_ADDR,0x09,0x0300);#else mii_write(PHY_ADDR,0x04,0x05e1); /* advertisement 100M full duplex, pause capable on */ mii_write(PHY_ADDR,0x09,0x0000); /* advertisement no 1000M */#endif mii_write(PHY_ADDR,0x00,0x1200);// while (((value=mii_read(PHY_ADDR,0x01)) & 0x00000004)!=0x04)// {// i++;// if (i > 3000)// {// break ;// }// hal_delay_us(1000);// }// if (i<3000)// {// diag_printf("Link Up (%04x)\n",value);// }// else// { // diag_printf("Link Down \n");// } // value = mii_read(PHY_ADDR,0x05);// if ((value & 0x0040) == 0x0040)// {// full_duplex = 1;// }// else// {// full_duplex = 0;// } full_duplex = 1; } void gmac_get_phy_status(void){ GMAC_STATUS_T status, old_status; unsigned int reg_val; status.bits32 = old_status.bits32 = gmac_read_reg(GMAC_STATUS); #ifdef GEMINI_ASIC status.bits.phy_mode = 1;#else status.bits.phy_mode = 0;#endif /* 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,10); if ((reg_val & 0x0800) == 0x0800) { status.bits.mii_rmii = 3; status.bits.duplex = 1; status.bits.speed = 2; } else if ((reg_val & 0x0400) == 0x0400) { status.bits.mii_rmii = 3; status.bits.duplex = 0; status.bits.speed = 2; } else { reg_val = (mii_read(PHY_ADDR,0x05) & 0x05E0) >> 5; status.bits.mii_rmii = 2; if ((reg_val & 0x08)==0x08) /* 100M full duplex */ { status.bits.mii_rmii = 2; /* RGMII 10/100Mbps mode */ status.bits.duplex = 1; status.bits.speed = 1; } else if ((reg_val & 0x04)==0x04) /* 100M half duplex */ { status.bits.mii_rmii = 2; /* RGMII 10/100Mbps mode */ status.bits.duplex = 0; status.bits.speed = 1; } else if ((reg_val & 0x02)==0x02) /* 10M full duplex */ { status.bits.mii_rmii = 2; /* RGMII 10/100Mbps mode */ status.bits.duplex = 1; status.bits.speed = 0; } else if ((reg_val & 0x01)==0x01) /* 10M half duplex */ { status.bits.mii_rmii = 2; /* RGMII 10/100Mbps mode */ status.bits.duplex = 0; status.bits.speed = 0; } } status.bits.link = 1; /* link up */ } else { status.bits.link = 0; /* link down */ } if (status.bits32 != old_status.bits32) gmac_write_reg(GMAC_STATUS, status.bits32, 0x0000007f);} /******************************************************************************//* define GPIO module base address *//******************************************************************************/#define GPIO_BASE_ADDR SL2312_GPIO_BASE/* define GPIO pin for MDC/MDIO */#ifndef GEMINI_ASIC#define H_MDC_PIN 3#define H_MDIO_PIN 2#define G_MDC_PIN 0#define G_MDIO_PIN 1#else#define H_MDC_PIN 22#define H_MDIO_PIN 21#define G_MDC_PIN 22#define G_MDIO_PIN 21#endif//#define readl(addr) (*addr)//#define writel(val,addr) (*addr = val)// For PHY test definition!!#define LPC_EECK 0x02#define LPC_EDIO 0x04#define LPC_GPIO_SET 3#define LPC_BASE_ADDR SL2312_LPC_IO_BASE #define inb_gpio(x) inb(LPC_BASE_ADDR + IT8712_GPIO_BASE + x)#define outb_gpio(x, y) outb(y, LPC_BASE_ADDR + IT8712_GPIO_BASE + x)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};static unsigned int GPIO_MDC = 0;static unsigned int GPIO_MDIO = 0;static unsigned int GPIO_MDC_PIN = 0;static unsigned int GPIO_MDIO_PIN = 0;/***********************//* 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 0 //LPC_IT8712 //CONFIG_SL2312_LPC_IT8712 unsigned char iomode,status; iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET); iomode |= (LPC_EECK|LPC_EDIO) ; // Set EECK,EDIO,EECS output LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode); if(bit_MDO) { status = inb_gpio( LPC_GPIO_SET); status |= LPC_EDIO ; //EDIO high outb_gpio(LPC_GPIO_SET, status); } else { status = inb_gpio( LPC_GPIO_SET); status &= ~(LPC_EDIO) ; //EDIO low outb_gpio(LPC_GPIO_SET, status); } status |= LPC_EECK ; //EECK high outb_gpio(LPC_GPIO_SET, status); status &= ~(LPC_EECK) ; //EECK low outb_gpio(LPC_GPIO_SET, status); #else unsigned int *addr; unsigned int value; addr = (unsigned int *)(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 = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET); writel(GPIO_MDIO,addr); /* set MDIO to 1 */ addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET); writel(GPIO_MDC,addr); /* set MDC to 1 */ addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR); writel(GPIO_MDC,addr); /* set MDC to 0 */ } else { addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR); writel(GPIO_MDIO,addr); /* set MDIO to 0 */ addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET); writel(GPIO_MDC,addr); /* set MDC to 1 */ addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR); writel(GPIO_MDC,addr); /* set MDC to 0 */ } #endif }/*********************************************************************** read a bit from NWay register through CSR9_MDC,MDIO***********************************************************************/unsigned int mii_serial_read(void) // read data from mii PHY{#if 0 //LPC_IT8712 //CONFIG_SL2312_LPC_IT8712 unsigned char iomode,status; unsigned int value ; iomode = LPCGetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET); iomode &= ~(LPC_EDIO) ; // Set EDIO input iomode |= (LPC_EECK) ; // Set EECK,EECS output LPCSetConfig(LDN_GPIO, 0xc8 + LPC_GPIO_SET, iomode); status = inb_gpio( LPC_GPIO_SET); status |= LPC_EECK ; //EECK high outb_gpio(LPC_GPIO_SET, status); status &= ~(LPC_EECK) ; //EECK low outb_gpio(LPC_GPIO_SET, status); value = inb_gpio( LPC_GPIO_SET); value = value>>2 ; value &= 0x01; return value ; #else unsigned int *addr; unsigned int value; addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_PIN_DIR); value = readl(addr) & ~GPIO_MDIO; //0xffbfffff; /* set MDC to output and MDIO to input */ writel(value,addr); addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_SET); writel(GPIO_MDC,addr); /* set MDC to 1 */ addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_CLEAR); writel(GPIO_MDC,addr); /* set MDC to 0 */ addr = (unsigned int *)(GPIO_BASE_ADDR + GPIO_DATA_IN); value = readl(addr); value = (value & (1<<GPIO_MDIO_PIN)) >> GPIO_MDIO_PIN; 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; if (phyad == GPHY_ADDR) { GPIO_MDC_PIN = G_MDC_PIN; /* assigned MDC pin for giga PHY */ GPIO_MDIO_PIN = G_MDIO_PIN; /* assigned MDIO pin for giga PHY */ } else { GPIO_MDC_PIN = H_MDC_PIN; /* assigned MDC pin for 10/100 PHY */ GPIO_MDIO_PIN = H_MDIO_PIN; /* assigned MDIO pin for 10/100 PHY */ } GPIO_MDC = (1<<GPIO_MDC_PIN); GPIO_MDIO = (1<<GPIO_MDIO_PIN); mii_pre_st(); // PRE+ST mii_serial_write(1); // OP mii_serial_write(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -