📄 emac_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>#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 + -