+
+static void
+jme_set_physpeed_capability(struct jme_adapter *jme,u16 speed)
+{
+ u32 advert, advert2;
+
+ spin_lock_bh(&jme->phy_lock);
+ if (speed == SPEED_1000){
+ advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+ advert2 = (advert2|ADVERTISE_1000HALF|ADVERTISE_1000FULL);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2);
+ advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE);
+ advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert);
+ }else if (speed == SPEED_100){
+ advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+ advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2);
+ advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE);
+ advert = (advert|ADVERTISE_100HALF|ADVERTISE_100FULL);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert);
+ }else{
+ advert2 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+ advert2 = advert2 & ~(ADVERTISE_1000HALF|ADVERTISE_1000FULL);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, advert2);
+ advert = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE);
+ advert = advert & ~(ADVERTISE_100HALF|ADVERTISE_100FULL);
+ jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_ADVERTISE, advert);
+ }
+ spin_unlock_bh(&jme->phy_lock);
+ return;
+}
+
+/* PHY reg: MII_FCSCOUNTER is read and clear, we have to continuing read until RJ45 is attached, then cache this result. */
+static int
+jme_check_ANcomplete(struct jme_adapter *jme)
+{
+ u32 val;
+
+ val = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_FCSCOUNTER);
+ return ((val&(PHY_SPEC_STATUS_AN_FAIL|PHY_SPEC_STATUS_AN_COMPLETE))==PHY_SPEC_STATUS_AN_COMPLETE) ? true : false;
+}
+
+static int
+jme_media_connected(struct jme_adapter *jme)
+{
+ if (jme->flag_media_connected == true)
+ return true;
+
+ jme->flag_media_connected = jme_check_ANcomplete(jme);
+
+ return jme->flag_media_connected;
+}
+
+static void
+asd_polling_func(unsigned long data)
+{
+ struct jme_adapter *jme = (struct jme_adapter *)data;
+
+ /*
+ check condition term by term.
+ 1. link is up() ==> reset all thing, exit the process.
+ 2. there is no RJ45 cable attached. ==> do nothing but polling.
+ 3. RJ45 cable attached. but link is down ==> downspeed if the timeing is over 3.5 second.
+ */
+ if (jme->flag_run_asd == true){
+ printk("%s: run polling \n", __FUNCTION__ );
+ if (jme_media_connected(jme)){
+ jme->mc_count++;
+ printk("%s: pos1 mc_count=%d flag_media_connected=%d \n", \
+ __FUNCTION__, jme->mc_count , jme->flag_media_connected);
+ if (jme->mc_count == (delay_time*3-5)){
+ /* RJ45 is attached but unable to link anyway, it CANT
+ be resolved by speed, restore the capability */
+ jme_set_physpeed_capability(jme,SPEED_1000);
+ jme->flag_media_connected = false;
+ jme->mc_count = 0;
+ }else if (jme->mc_count == (delay_time*2-5)){
+ if (jme_check_ANcomplete(jme))
+ jme_set_physpeed_capability(jme,SPEED_10);
+ else{
+ jme->flag_media_connected = false;
+ jme->mc_count = 0;
+ }
+ }else if (jme->mc_count == delay_time-5){
+ if (jme_check_ANcomplete(jme))
+ jme_set_physpeed_capability(jme,SPEED_100);
+ else{
+ jme->flag_media_connected = false;
+ jme->mc_count = 0;
+ }
+ }
+ }
+ mod_timer(&jme->asd_timer, jiffies+HZ);
+ return ;
+ }
+
+//out:
+ printk("%s stop polling \n", __FUNCTION__);
+ jme->flag_media_connected = false;
+ jme->mc_count = 0;
+ return;
+}
+
+static int jme_check_linkup(struct jme_adapter *jme)
+{
+ u32 phylink;
+
+ if (jme->fpgaver)
+ phylink = jme_linkstat_from_phy(jme);
+ else
+ phylink = jread32(jme, JME_PHY_LINK);
+
+ return (phylink & PHY_LINK_UP)? true : false;
+}
+