+static inline int
+jme_pseudo_hotplug_enabled(struct jme_adapter *jme)
+{
+ u32 apmc;
+ apmc = jread32(jme, JME_APMC);
+ return apmc & JME_APMC_PSEUDO_HP_EN;
+}
+
+static void
+jme_start_shutdown_timer(struct jme_adapter *jme)
+{
+ u32 apmc;
+
+ apmc = jread32(jme, JME_APMC) | JME_APMC_PCIE_SD_EN;
+ apmc &= ~JME_APMC_EPIEN_CTRL;
+ if (!no_extplug) {
+ jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_EN);
+ wmb();
+ }
+ jwrite32f(jme, JME_APMC, apmc);
+
+ jwrite32f(jme, JME_TIMER2, 0);
+ set_bit(JME_FLAG_SHUTDOWN, &jme->flags);
+ jwrite32(jme, JME_TMCSR,
+ TMCSR_EN | ((0xFFFFFF - APMC_PHP_SHUTDOWN_DELAY) & TMCSR_CNT));
+}
+
+static void
+jme_stop_shutdown_timer(struct jme_adapter *jme)
+{
+ u32 apmc;
+
+ jwrite32f(jme, JME_TMCSR, 0);
+ jwrite32f(jme, JME_TIMER2, 0);
+ clear_bit(JME_FLAG_SHUTDOWN, &jme->flags);
+
+ apmc = jread32(jme, JME_APMC);
+ apmc &= ~(JME_APMC_PCIE_SD_EN | JME_APMC_EPIEN_CTRL);
+ jwrite32f(jme, JME_APMC, apmc | JME_APMC_EPIEN_CTRL_DIS);
+ wmb();
+ jwrite32f(jme, JME_APMC, apmc);
+}
+
+
+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;
+}
+