📄 adm_phy.c
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright © 2003 Atheros Communications, Inc., All Rights Reserved. *//* * Manage the ICPLUS ethernet PHY. * * All definitions in this file are operating system independent! *//*#include <linux/config.h>#include <linux/types.h>#include <linux/netdevice.h>#include <linux/etherdevice.h>#include <linux/delay.h>#include "ag7100_phy.h"*/#include <config.h>#include <linux/types.h>#include <common.h>#include <miiphy.h>#include "phy.h"#include "adm_phy.h"#define mdelay(_x) udelay((_x) * 1000)/* PHY selections and access functions */typedef enum { PHY_SRCPORT_INFO, PHY_PORTINFO_SIZE,} PHY_CAP_TYPE;typedef enum { PHY_SRCPORT_NONE, PHY_SRCPORT_VLANTAG, PHY_SRCPORT_TRAILER,} PHY_SRCPORT_TYPE;#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)#define DRV_MSG(x,a,b,c,d,e,f)#define DRV_PRINT(DBG_SW,X)#define ADM_LAN_PORT_VLAN 1#define ADM_WAN_PORT_VLAN 2#define ENET_UNIT_DEFAULT 0 /* MAC0 for LAN */#define TRUE 1#define FALSE 0/* * Track per-PHY port information. */typedef struct { BOOL isEnetPort; /* normal enet port */ BOOL isPhyAlive; /* last known state of link */ int ethUnit; /* MAC associated with this phy port */ uint32_t phyBase; uint32_t phyAddr; /* PHY registers associated with this phy port */ uint32_t VLANTableSetting; /* Value to be written to VLAN table */} ipPhyInfo_t;#define ADM_PHY0_ADDR 0x10#define ADM_PHY1_ADDR 0x11#define ADM_PHY2_ADDR 0x12#define ADM_PHY3_ADDR 0x13#define ADM_PHY4_ADDR 0x14#define P0_TXL 0xcc#define P5_TXL 0xdc#define P0_TXH 0xcd#define P5_TXH 0xdd#define P0_TXBL 0xde#define P5_TXBL 0xee#define P0_TXBH 0xdf#define P5_TXBH 0xef#define P0_RXL 0xac#define P5_RXL 0xb8#define P0_RXH 0xa9#define P5_RXH 0xb9#define P0_ERRL 0x102#define P5_ERRL 0x112#define P0_ERRH 0x103#define P5_ERRH 0x113/* * Per-PHY information, indexed by PHY unit number. */ipPhyInfo_t ipPhyInfo[] = { /* * On AP30/AR5312, all PHYs are associated with MAC0. * AP30/AR5312's MAC1 isn't used for anything. * CONFIG_VENETDEV==1 (router) configuration: * Ports 0,1,2, and 3 are "LAN ports" * Port 4 is a WAN port * Port 5 connects to MAC0 in the AR5312 * CONFIG_VENETDEV==0 (bridge) configuration: * Ports 0,1,2,3,4 are "LAN ports" * Port 5 connects to the MAC0 in the AR5312 */ {TRUE, /* phy port 0 -- WAN port */ FALSE, ENET_UNIT_DEFAULT, 0, ADM_PHY0_ADDR, ADM_LAN_PORT_VLAN }, {TRUE, /* phy port 1 -- LAN port 1 */ FALSE, ENET_UNIT_DEFAULT, 0, ADM_PHY1_ADDR, ADM_LAN_PORT_VLAN }, {TRUE, /* phy port 2 -- LAN port 2 */ FALSE, ENET_UNIT_DEFAULT, 0, ADM_PHY2_ADDR, ADM_LAN_PORT_VLAN }, {TRUE, /* phy port 3 -- LAN port 3 */ FALSE, ENET_UNIT_DEFAULT, 0, ADM_PHY3_ADDR, ADM_LAN_PORT_VLAN }, {TRUE, /* phy port 4 -- LAN port 4 */ FALSE, ENET_UNIT_DEFAULT, 0, ADM_PHY4_ADDR, ADM_LAN_PORT_VLAN /* Send to all ports */ }, {FALSE, /* phy port 5 -- CPU port (no RJ45 connector) */ TRUE, ENET_UNIT_DEFAULT, 0, 0x00, ADM_LAN_PORT_VLAN /* Send to all ports */ },};#define ADM_GLOBALREGBASE 0//#define ADM_PHY_MAX (sizeof(ipPhyInfo) / sizeof(ipPhyInfo[0]))#define ADM_PHY_MAX 5/* Range of valid PHY IDs is [MIN..MAX] */#define ADM_ID_MIN 0#define ADM_ID_MAX (ADM_PHY_MAX-1)/* Convenience macros to access myPhyInfo */#define ADM_IS_ENET_PORT(phyUnit) (ipPhyInfo[phyUnit].isEnetPort)#define ADM_IS_PHY_ALIVE(phyUnit) (ipPhyInfo[phyUnit].isPhyAlive)#define ADM_ETHUNIT(phyUnit) (ipPhyInfo[phyUnit].ethUnit)#define ADM_PHYBASE(phyUnit) (ipPhyInfo[phyUnit].phyBase)#define ADM_PHYADDR(phyUnit) (ipPhyInfo[phyUnit].phyAddr)#define ADM_VLAN_TABLE_SETTING(phyUnit) (ipPhyInfo[phyUnit].VLANTableSetting)#define ADM_IS_ETHUNIT(phyUnit, ethUnit) \ (ADM_IS_ENET_PORT(phyUnit) && \ ADM_ETHUNIT(phyUnit) == (ethUnit))/* Forward references */BOOL adm_phyIsLinkAlive(int phyUnit);void adm_get_counters(void);/******************************************************************************** adm_phyIsLinkAlive - test to see if the specified link is alive** RETURNS:* TRUE --> link is alive* FALSE --> link is down*/BOOLadm_phyIsLinkAlive(int phyUnit){ uint16_t phyHwStatus; uint32_t phyBase; uint32_t phyAddr; phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS, &phyHwStatus); if (phyHwStatus & ADM_STATUS_LINK_PASS) { return TRUE; } else { return FALSE; }}/******************************************************************************** adm_phySetup - reset and setup the PHY associated with* the specified MAC unit number.** Resets the associated PHY port.** RETURNS:* TRUE --> associated PHY is alive* FALSE --> no LINKs on this ethernet unit*/BOOLadm_phySetup(int ethUnit){ int phyUnit; uint16_t phyHwStatus; uint16_t timeout; int liveLinks = 0; uint32_t phyBase = 0; BOOL foundPhy = FALSE; uint32_t phyAddr; /* Reset PHYs*/ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL, ADM_CTRL_SOFTWARE_RESET); } /* * After the phy is reset, it takes a little while before * it can respond properly. */ mdelay(300); /* See if there's any configuration data for this enet */ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); foundPhy = TRUE; break; } if (!foundPhy) { return FALSE; /* No PHY's configured for this ethUnit */ } /* start auto negogiation on each phy */ for (phyUnit=0; phyUnit < ADM_PHY_MAX; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_write(phyBase, phyAddr, ADM_AUTONEG_ADVERT, ADM_ADVERTISE_ALL); phy_reg_write(phyBase, phyAddr, ADM_PHY_CONTROL, ADM_CTRL_AUTONEGOTIATION_ENABLE | ADM_CTRL_START_AUTONEGOTIATION); } /* * Wait up to .75 seconds for ALL associated PHYs to finish * autonegotiation. The only way we get out of here sooner is * if ALL PHYs are connected AND finish autonegotiation. */ timeout=5; for (phyUnit=0; (phyUnit < ADM_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) { if (!ADM_IS_ETHUNIT(phyUnit, ethUnit)) { continue; } for (;;) { phyBase = ADM_PHYBASE(phyUnit); phyAddr = ADM_PHYADDR(phyUnit); phy_reg_read(phyBase, phyAddr, ADM_PHY_STATUS, &phyHwStatus); if (ADM_AUTONEG_DONE(phyHwStatus)) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Neg Success\n", phyUnit)); break; } if (timeout == 0) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit)); break; } if (--timeout == 0) { DRV_PRINT(DRV_DEBUG_PHYSETUP, ("Port %d, Negogiation timeout\n", phyUnit)); break; } mdelay(150); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -