text: #include <linux/module.h>
  #include <linux/version.h>
  #include <linux/netdevice.h>
  
  #include <linux/kernel.h>
  #include <linux/sched.h>
  #if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0)
  #include <asm/rt2880/rt_mmap.h>
  #endif
  
  #include "ra2882ethreg.h"
  #include "raether.h"
  
  
  #if defined (CONFIG_RALINK_RT3052) 
  #define PHY_CONTROL_0 		0xC0   
  #define PHY_CONTROL_1 		0xC4   
  #define MDIO_PHY_CONTROL_0  (RALINK_ETH_SW_BASE + PHY_CONTROL_0)
  #define MDIO_PHY_CONTROL_1 	(RALINK_ETH_SW_BASE + PHY_CONTROL_1)
  
  #define GPIO_MDIO_BIT		(1<<7)
  #define GPIO_PURPOSE_SELECT	0x60
  #define GPIO_PRUPOSE		(RALINK_SYSCTL_BASE + GPIO_PURPOSE_SELECT)
  
  #else 
  #define PHY_CONTROL_0       	0x00
  #define PHY_CONTROL_1       	0x04
  #define MDIO_PHY_CONTROL_0	(RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_0)
  #define MDIO_PHY_CONTROL_1	(RALINK_FRAME_ENGINE_BASE + PHY_CONTROL_1)
  #define enable_mdio(x)
  #endif
  
  #if defined (CONFIG_RALINK_RT3052)
  void enable_mdio(int enable)
  {
  #if !defined (CONFIG_P5_MAC_TO_PHY_MODE)
  	u32 data = sysRegRead(GPIO_PRUPOSE);
  	if (enable)
  		data &= ~GPIO_MDIO_BIT;
  	else
  		data |= GPIO_MDIO_BIT;
  	sysRegWrite(GPIO_PRUPOSE, data);
  #endif
  }
  #endif
  
  u32 mii_mgr_read(u32 phy_addr, u32 phy_register, u32 *read_data)
  {
  	u32 volatile status = 0;
  	u32 rc = 0;
  	unsigned long volatile t_start = jiffies;
  
  	/* We enable mdio gpio purpose register, and disable it when exit. */
  	enable_mdio(1);
  
  	// make sure previous read operation is complete
  	while (1) {
  #if defined (CONFIG_RALINK_RT3052) 
  		// rd_rdy: read operation is complete
  		if(!( sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1))) 
  #else
  			// 0 : Read/write operation complet
  		if(!( sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
  #endif
  		{
  			break;
  		}
  		else if (time_after(jiffies, t_start + 5*HZ)) {
  			enable_mdio(0);
  			printk("\n MDIO Read operation is ongoing !!\n");
  			return rc;
  		}
  	}
  
  #if defined (CONFIG_RALINK_RT3052) 
  	sysRegWrite(MDIO_PHY_CONTROL_0 , (1<<14) | (phy_register << 8) | (phy_addr));
  #else
  	u32 volatile data = 0;
  	data  = (phy_addr << 24) | (phy_register << 16);
  	sysRegWrite(MDIO_PHY_CONTROL_0, data);
  	data |= (1<<31);
  	sysRegWrite(MDIO_PHY_CONTROL_0, data);
  #endif
  	//printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
  
  
  	// make sure read operation is complete
  	t_start = jiffies;
  	while (1) {
  #if defined (CONFIG_RALINK_RT3052) 
  		if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 1)) {
  			status = sysRegRead(MDIO_PHY_CONTROL_1);
  			*read_data = (u32)(status >>16);
  
  			enable_mdio(0);
  			return 1;
  		}
  #else
  		if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) {
  			status = sysRegRead(MDIO_PHY_CONTROL_0);
  			*read_data = (u32)(status & 0x0000FFFF);
  
  			enable_mdio(0);
  			return 1;
  		}
  #endif
  		else if (time_after(jiffies, t_start+5*HZ)) {
  			enable_mdio(0);
  			printk("\n MDIO Read operation is ongoing and Time Out!!\n");
  			return 0;
  		}
  	}
  }
  
  u32 mii_mgr_write(u32 phy_addr, u32 phy_register, u32 write_data)
  {
  	unsigned long volatile t_start=jiffies;
  	u32 volatile data;
  
  	enable_mdio(1);
  
  	// make sure previous write operation is complete
  	while(1) {
  #if defined (CONFIG_RALINK_RT3052) 
  		if (!(sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0)))
  #else
  		if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) 
  #endif
  		{
  			break;
  		}
  		else if (time_after(jiffies, t_start + 5 * HZ)) {
  			enable_mdio(0);
  			printk("\n MDIO Write operation ongoing\n");
  			return 0;
  		}
  	}
  
  #if defined (CONFIG_RALINK_RT3052) 
  	data = ((write_data & 0xFFFF) << 16);
  	data |= (phy_register << 8) | (phy_addr);
  	data |= (1<<13);
  	sysRegWrite(MDIO_PHY_CONTROL_0, data);
  #else
  	data = (1<<30) | (phy_addr << 24) | (phy_register << 16) | write_data;
  	sysRegWrite(MDIO_PHY_CONTROL_0, data);
  	data |= (1<<31);
  	sysRegWrite(MDIO_PHY_CONTROL_0, data); //start operation
  #endif
  	//printk("\n Set Command [0x%08X] to PHY !!\n",MDIO_PHY_CONTROL_0);
  
  	t_start = jiffies;
  
  	// make sure write operation is complete
  	while (1) {
  #if defined (CONFIG_RALINK_RT3052) 
  		if (sysRegRead(MDIO_PHY_CONTROL_1) & (0x1 << 0)) //wt_done ?= 1
  #else
  		if (!(sysRegRead(MDIO_PHY_CONTROL_0) & (0x1 << 31))) //0 : Read/write operation complete
  #endif
  		{
  			enable_mdio(0);
  			return 1;
  		}
  		else if (time_after(jiffies, t_start + 5 * HZ)) {
  			enable_mdio(0);
  			printk("\n MDIO Write operation Time Out\n");
  			return 0;
  		}
  	}
  }
  
  EXPORT_SYMBOL(mii_mgr_write);
  EXPORT_SYMBOL(mii_mgr_read);
  