netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Re: [PATCH 1/1]  PHY configuration for compatible issue
  2011-11-17 14:05 [PATCH 1/1] PHY configuration for compatible issue AriesLee
@ 2011-11-17  7:15 ` Guo-Fu Tseng
  2011-11-18  7:13   ` Aries Lee
  0 siblings, 1 reply; 11+ messages in thread
From: Guo-Fu Tseng @ 2011-11-17  7:15 UTC (permalink / raw)
  To: AriesLee, netdev; +Cc: AriesLee

On Thu, 17 Nov 2011 22:05:42 +0800, AriesLee wrote
> From: Aries Lee <AriesLee@jmicron.com>
> 
> To perform PHY calibration and set a different EA value by chip ID,
> Whenever the NIC chip power on, ie booting or resuming, we need to
> force HW to calibrate PHY parameter again, and also set a proper EA
> value which gathered from experiment.
> 
> That process resolve the compatible issues(NIC is unable to link
> up in some special case) in giga speed.
Thank you Aries.

Here is some suggestions after a quick review:

It would be better if you implement the read/write function
for extended-phy-register, instead of using JM_PHY_SPEC_ADDR_REG
and JM_PHY_SPEC_DATA_REG directly all the time.

There are jme_phy_on() and jme_phy_off() function in place.
Should you simply using it?

> 
> Signed-off-by: Aries Lee <AriesLee@jmicron.com>
> ---
>  drivers/net/ethernet/jme.c |  127 
> ++++++++++++++++++++++++++++++++++++++++++- drivers/net/ethernet/jme.h 
> |   19 +++++++ 2 files changed, 143 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
> index df3ab83..bd9633d 100644
> --- a/drivers/net/ethernet/jme.c
> +++ b/drivers/net/ethernet/jme.c
> @@ -1743,6 +1743,126 @@ jme_phy_off(struct jme_adapter *jme)
>  	if (new_phy_power_ctrl(jme->chip_main_rev))
>  		jme_new_phy_off(jme);
>  }
> +static int
> +jme_phy_calibration(struct jme_adapter *jme)
> +{
> +	u32 ctrl1000, bmcr, phy_addr, phy_data;
> +
> +	/*  Turn PHY off */
> +	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
> +	bmcr |= BMCR_PDOWN;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
> +	/*  Turn PHY on */
> +	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
> +	bmcr &= ~BMCR_PDOWN;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
> +	/*  Enabel PHY test mode 1 */
> +	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
> +	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
> +	ctrl1000 |= PHY_GAD_TEST_MODE_1;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
> +
> +
> +	phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
> +			phy_addr);
> +	phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id,
> +			JM_PHY_SPEC_DATA_REG);
> +
> +	phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0;
> +	phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH |
> +			JM_PHY_EXT_COMM_2_CALI_ENABLE;
> +
> +	phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
> +			phy_data);
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
> +			phy_addr);
> +
> +	msleep(20);
> +
> +	phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
> +			phy_addr);
> +	phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id,
> +			JM_PHY_SPEC_DATA_REG);
> +
> +	phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE |
> +			JM_PHY_EXT_COMM_2_CALI_MODE_0 |
> +			JM_PHY_EXT_COMM_2_CALI_LATCH);
> +
> +	phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
> +			phy_data);
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
> +			phy_addr);
> +
> +	/*  Disable PHY test mode */
> +	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
> +	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
> +	return 0;
> +}
> +
> +static int
> +jme_phy_setEA(struct jme_adapter *jme)
> +{
> +	u32 phy_addr, phy_comm0 = 0, phy_comm1 = 0;
> +	u8 nic_ctrl;
> +
> +	pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl);
> +	if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE)
> +		return 0;
> +
> +	switch (jme->pdev->device) {
> +	case PCI_DEVICE_ID_JMICRON_JMC250:
> +		if (((jme->chip_main_rev == 5) &&
> +			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
> +			(jme->chip_sub_rev == 3))) ||
> +			(jme->chip_main_rev >= 6)) {
> +			phy_comm0 = 0x008A;
> +			phy_comm1 = 0x4109;
> +		}
> +		if ((jme->chip_main_rev == 3) &&
> +			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
> +			phy_comm0 = 0xE088;
> +		break;
> +	case PCI_DEVICE_ID_JMICRON_JMC260:
> +		if (((jme->chip_main_rev == 5) &&
> +			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
> +			(jme->chip_sub_rev == 3))) ||
> +			(jme->chip_main_rev >= 6)) {
> +			phy_comm0 = 0x008A;
> +			phy_comm1 = 0x4109;
> +		}
> +		if ((jme->chip_main_rev == 3) &&
> +			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
> +			phy_comm0 = 0xE088;
> +		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0))
> +			phy_comm0 = 0x608A;
> +		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2))
> +			phy_comm0 = 0x408A;
> +		break;
> +	default:
> +		return -ENODEV;
> +	}
> +	if (phy_comm0) {
> +		phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_0_REG;
> +		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
> +				JM_PHY_SPEC_DATA_REG, phy_comm0);
> +		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
> +				JM_PHY_SPEC_ADDR_REG, phy_addr);
> +	}
> +	if (phy_comm1) {
> +		phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_1_REG;
> +		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
> +				JM_PHY_SPEC_DATA_REG, phy_comm1);
> +		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
> +				JM_PHY_SPEC_ADDR_REG, phy_addr);
> +	}
> +
> +	return 0;
> +}
> 
>  static int
>  jme_open(struct net_device *netdev)
> @@ -1769,7 +1889,8 @@ jme_open(struct net_device *netdev)
>  		jme_set_settings(netdev, &jme->old_ecmd);
>  	else
>  		jme_reset_phy_processor(jme);
> -
> +	jme_phy_calibration(jme);
> +	jme_phy_setEA(jme);
>  	jme_reset_link(jme);
> 
>  	return 0;
> @@ -3184,7 +3305,8 @@ jme_resume(struct device *dev)
>  		jme_set_settings(netdev, &jme->old_ecmd);
>  	else
>  		jme_reset_phy_processor(jme);
> -
> +	jme_phy_calibration(jme);
> +	jme_phy_setEA(jme);
>  	jme_start_irq(jme);
>  	netif_device_attach(netdev);
> 
> @@ -3239,4 +3361,3 @@ MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express 
> Ethernet driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); 
> MODULE_DEVICE_TABLE(pci, jme_pci_tbl);
> -
> diff --git a/drivers/net/ethernet/jme.h b/drivers/net/ethernet/jme.h
> index 02ea27c..47e47a9 100644
> --- a/drivers/net/ethernet/jme.h
> +++ b/drivers/net/ethernet/jme.h
> @@ -760,6 +760,25 @@ enum jme_rxmcs_bits {
>  				  RXMCS_CHECKSUM,
>  };
> 
> +/*	Extern PHY common register 2	*/
> +
> +#define PHY_GAD_TEST_MODE_1			0x00002000
> +#define PHY_GAD_TEST_MODE_MSK			0x0000E000
> +#define JM_PHY_SPEC_REG_READ			0x00004000
> +#define JM_PHY_SPEC_REG_WRITE			0x00008000
> +#define PHY_CALIBRATION_DELAY			20
> +#define JM_PHY_SPEC_ADDR_REG			0x1E
> +#define JM_PHY_SPEC_DATA_REG			0x1F
> +
> +#define JM_PHY_EXT_COMM_0_REG			0x30
> +#define JM_PHY_EXT_COMM_1_REG			0x31
> +#define JM_PHY_EXT_COMM_2_REG			0x32
> +#define JM_PHY_EXT_COMM_2_CALI_ENABLE		0x01
> +#define JM_PHY_EXT_COMM_2_CALI_MODE_0		0x02
> +#define JM_PHY_EXT_COMM_2_CALI_LATCH		0x10
> +#define PCI_PRIV_SHARE_NICCTRL			0xF5
> +#define JME_FLAG_PHYEA_ENABLE			0x2
> +
>  /*
>   * Wakeup Frame setup interface registers
>   */
> -- 
> 1.7.4.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html


Guo-Fu Tseng

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/1]  PHY configuration for compatible issue
@ 2011-11-17 14:05 AriesLee
  2011-11-17  7:15 ` Guo-Fu Tseng
  0 siblings, 1 reply; 11+ messages in thread
From: AriesLee @ 2011-11-17 14:05 UTC (permalink / raw)
  To: Guo-Fu Tseng, netdev; +Cc: AriesLee, Aries Lee

From: Aries Lee <AriesLee@jmicron.com>

To perform PHY calibration and set a different EA value by chip ID,
Whenever the NIC chip power on, ie booting or resuming, we need to
force HW to calibrate PHY parameter again, and also set a proper EA
value which gathered from experiment.

That process resolve the compatible issues(NIC is unable to link
up in some special case) in giga speed.

Signed-off-by: Aries Lee <AriesLee@jmicron.com>
---
 drivers/net/ethernet/jme.c |  127 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/ethernet/jme.h |   19 +++++++
 2 files changed, 143 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index df3ab83..bd9633d 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1743,6 +1743,126 @@ jme_phy_off(struct jme_adapter *jme)
 	if (new_phy_power_ctrl(jme->chip_main_rev))
 		jme_new_phy_off(jme);
 }
+static int
+jme_phy_calibration(struct jme_adapter *jme)
+{
+	u32 ctrl1000, bmcr, phy_addr, phy_data;
+
+	/*  Turn PHY off */
+	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+	bmcr |= BMCR_PDOWN;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+	/*  Turn PHY on */
+	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+	bmcr &= ~BMCR_PDOWN;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+	/*  Enabel PHY test mode 1 */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	ctrl1000 |= PHY_GAD_TEST_MODE_1;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+
+
+	phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+	phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id,
+			JM_PHY_SPEC_DATA_REG);
+
+	phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0;
+	phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH |
+			JM_PHY_EXT_COMM_2_CALI_ENABLE;
+
+	phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
+			phy_data);
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+
+	msleep(20);
+
+	phy_addr = JM_PHY_SPEC_REG_READ | JM_PHY_EXT_COMM_2_REG;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+	phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id,
+			JM_PHY_SPEC_DATA_REG);
+
+	phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE |
+			JM_PHY_EXT_COMM_2_CALI_MODE_0 |
+			JM_PHY_EXT_COMM_2_CALI_LATCH);
+
+	phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_2_REG;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
+			phy_data);
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+
+	/*  Disable PHY test mode */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+	return 0;
+}
+
+static int
+jme_phy_setEA(struct jme_adapter *jme)
+{
+	u32 phy_addr, phy_comm0 = 0, phy_comm1 = 0;
+	u8 nic_ctrl;
+
+	pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl);
+	if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE)
+		return 0;
+
+	switch (jme->pdev->device) {
+	case PCI_DEVICE_ID_JMICRON_JMC250:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		break;
+	case PCI_DEVICE_ID_JMICRON_JMC260:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0))
+			phy_comm0 = 0x608A;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2))
+			phy_comm0 = 0x408A;
+		break;
+	default:
+		return -ENODEV;
+	}
+	if (phy_comm0) {
+		phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_0_REG;
+		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
+				JM_PHY_SPEC_DATA_REG, phy_comm0);
+		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
+				JM_PHY_SPEC_ADDR_REG, phy_addr);
+	}
+	if (phy_comm1) {
+		phy_addr = JM_PHY_SPEC_REG_WRITE | JM_PHY_EXT_COMM_1_REG;
+		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
+				JM_PHY_SPEC_DATA_REG, phy_comm1);
+		jme_mdio_write(jme->dev, jme->mii_if.phy_id,
+				JM_PHY_SPEC_ADDR_REG, phy_addr);
+	}
+
+	return 0;
+}
 
 static int
 jme_open(struct net_device *netdev)
@@ -1769,7 +1889,8 @@ jme_open(struct net_device *netdev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_reset_link(jme);
 
 	return 0;
@@ -3184,7 +3305,8 @@ jme_resume(struct device *dev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
 
@@ -3239,4 +3361,3 @@ MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, jme_pci_tbl);
-
diff --git a/drivers/net/ethernet/jme.h b/drivers/net/ethernet/jme.h
index 02ea27c..47e47a9 100644
--- a/drivers/net/ethernet/jme.h
+++ b/drivers/net/ethernet/jme.h
@@ -760,6 +760,25 @@ enum jme_rxmcs_bits {
 				  RXMCS_CHECKSUM,
 };
 
+/*	Extern PHY common register 2	*/
+
+#define PHY_GAD_TEST_MODE_1			0x00002000
+#define PHY_GAD_TEST_MODE_MSK			0x0000E000
+#define JM_PHY_SPEC_REG_READ			0x00004000
+#define JM_PHY_SPEC_REG_WRITE			0x00008000
+#define PHY_CALIBRATION_DELAY			20
+#define JM_PHY_SPEC_ADDR_REG			0x1E
+#define JM_PHY_SPEC_DATA_REG			0x1F
+
+#define JM_PHY_EXT_COMM_0_REG			0x30
+#define JM_PHY_EXT_COMM_1_REG			0x31
+#define JM_PHY_EXT_COMM_2_REG			0x32
+#define JM_PHY_EXT_COMM_2_CALI_ENABLE		0x01
+#define JM_PHY_EXT_COMM_2_CALI_MODE_0		0x02
+#define JM_PHY_EXT_COMM_2_CALI_LATCH		0x10
+#define PCI_PRIV_SHARE_NICCTRL			0xF5
+#define JME_FLAG_PHYEA_ENABLE			0x2
+
 /*
  * Wakeup Frame setup interface registers
  */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* RE: [PATCH 1/1]  PHY configuration for compatible issue
  2011-11-17  7:15 ` Guo-Fu Tseng
@ 2011-11-18  7:13   ` Aries Lee
  2011-11-19  4:19     ` Guo-Fu Tseng
  0 siblings, 1 reply; 11+ messages in thread
From: Aries Lee @ 2011-11-18  7:13 UTC (permalink / raw)
  To: 'Guo-Fu Tseng', netdev; +Cc: 'AriesLee'

Hi Guo-Fu and All

	Because jme_phy_on() and jme_phy_off() just turn on/off the PHY, the
value of extern register is still the power on default value, not the most
robust value which we collect in the LAB.
It still need to config those registers to the proper value when the chip
lost the power and power on again.

B.R
Aries
-----Original Message-----
From: Guo-Fu Tseng [mailto:cooldavid@cooldavid.org] 
Sent: Thursday, November 17, 2011 3:15 PM
To: AriesLee; netdev@vger.kernel.org
Cc: AriesLee
Subject: Re: [PATCH 1/1] PHY configuration for compatible issue

On Thu, 17 Nov 2011 22:05:42 +0800, AriesLee wrote
> From: Aries Lee <AriesLee@jmicron.com>
> 
> To perform PHY calibration and set a different EA value by chip ID,
> Whenever the NIC chip power on, ie booting or resuming, we need to
> force HW to calibrate PHY parameter again, and also set a proper EA
> value which gathered from experiment.
> 
> That process resolve the compatible issues(NIC is unable to link
> up in some special case) in giga speed.
Thank you Aries.

Here is some suggestions after a quick review:

It would be better if you implement the read/write function
for extended-phy-register, instead of using JM_PHY_SPEC_ADDR_REG
and JM_PHY_SPEC_DATA_REG directly all the time.

There are jme_phy_on() and jme_phy_off() function in place.
Should you simply using it?

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/1]  PHY configuration for compatible issue
@ 2011-11-18 14:54 AriesLee
  0 siblings, 0 replies; 11+ messages in thread
From: AriesLee @ 2011-11-18 14:54 UTC (permalink / raw)
  To: Aries Lee, Guo-Fu Tseng, netdev; +Cc: AriesLee

To perform PHY calibration and set a different EA value by chip ID,
Whenever the NIC chip power on, ie booting or resuming, we need to
force HW to calibrate PHY parameter again, and also set a proper EA
value which gather from experiment.

Those procedures help to reduce compatible issues(NIC is unable to link
up in some special case) in giga speed.

Signed-off-by: AriesLee <AriesLee@jmicron.com>
---
 drivers/net/ethernet/jme.c |  119 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/ethernet/jme.h |   19 +++++++
 2 files changed, 135 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index df3ab83..46c68a4 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1744,6 +1744,118 @@ jme_phy_off(struct jme_adapter *jme)
 		jme_new_phy_off(jme);
 }
 
+static void
+jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg, u32 *phy_data)
+{
+	u32 phy_addr;
+
+	phy_addr = JM_PHY_SPEC_REG_READ | specreg;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+	*phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id,
+			JM_PHY_SPEC_DATA_REG);
+}
+
+static void
+jme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data)
+{
+	u32 phy_addr;
+
+	phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
+			phy_data);
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+}
+
+static int
+jme_phy_calibration(struct jme_adapter *jme)
+{
+	u32 ctrl1000, bmcr, phy_addr, phy_data;
+
+	/*  Turn PHY off */
+	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+	bmcr |= BMCR_PDOWN;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+	/*  Turn PHY on */
+	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+	bmcr &= ~BMCR_PDOWN;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+	/*  Enabel PHY test mode 1 */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	ctrl1000 |= PHY_GAD_TEST_MODE_1;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+
+	jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG, &phy_data);
+	phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0;
+	phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH |
+			JM_PHY_EXT_COMM_2_CALI_ENABLE;
+	jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+	msleep(20);
+	jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG, &phy_data);
+	phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE |
+			JM_PHY_EXT_COMM_2_CALI_MODE_0 |
+			JM_PHY_EXT_COMM_2_CALI_LATCH);
+	jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+
+	/*  Disable PHY test mode */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+	return 0;
+}
+
+static int
+jme_phy_setEA(struct jme_adapter *jme)
+{
+	u32 phy_addr, phy_comm0 = 0, phy_comm1 = 0;
+	u8 nic_ctrl;
+
+	pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl);
+	if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE)
+		return 0;
+
+	switch (jme->pdev->device) {
+	case PCI_DEVICE_ID_JMICRON_JMC250:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		break;
+	case PCI_DEVICE_ID_JMICRON_JMC260:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0))
+			phy_comm0 = 0x608A;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2))
+			phy_comm0 = 0x408A;
+		break;
+	default:
+		return -ENODEV;
+	}
+	if (phy_comm0)
+		jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0);
+	if (phy_comm1)
+		jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1);
+
+	return 0;
+}
+
 static int
 jme_open(struct net_device *netdev)
 {
@@ -1769,7 +1881,8 @@ jme_open(struct net_device *netdev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_reset_link(jme);
 
 	return 0;
@@ -3184,7 +3297,8 @@ jme_resume(struct device *dev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
 
@@ -3239,4 +3353,3 @@ MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, jme_pci_tbl);
-
diff --git a/drivers/net/ethernet/jme.h b/drivers/net/ethernet/jme.h
index 02ea27c..4304072 100644
--- a/drivers/net/ethernet/jme.h
+++ b/drivers/net/ethernet/jme.h
@@ -760,6 +760,25 @@ enum jme_rxmcs_bits {
 				  RXMCS_CHECKSUM,
 };
 
+/*	Extern PHY common register 2	*/
+
+#define PHY_GAD_TEST_MODE_1			0x00002000
+#define PHY_GAD_TEST_MODE_MSK			0x0000E000
+#define JM_PHY_SPEC_REG_READ			0x00004000
+#define JM_PHY_SPEC_REG_WRITE			0x00008000
+#define PHY_CALIBRATION_DELAY			20
+#define JM_PHY_SPEC_ADDR_REG			0x1E
+#define JM_PHY_SPEC_DATA_REG			0x1F
+
+#define JM_PHY_EXT_COMM_0_REG			0x30
+#define JM_PHY_EXT_COMM_1_REG			0x31
+#define JM_PHY_EXT_COMM_2_REG			0x32
+#define JM_PHY_EXT_COMM_2_CALI_ENABLE		0x01
+#define JM_PHY_EXT_COMM_2_CALI_MODE_0		0x02
+#define JM_PHY_EXT_COMM_2_CALI_LATCH		0x10
+#define PCI_PRIV_SHARE_NICCTRL			0xF5
+#define JME_FLAG_PHYEA_ENABLE			0x2
+
 /*
  * Wakeup Frame setup interface registers
  */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* RE: [PATCH 1/1]  PHY configuration for compatible issue
  2011-11-18  7:13   ` Aries Lee
@ 2011-11-19  4:19     ` Guo-Fu Tseng
  2011-11-21  2:13       ` Aries Lee
  0 siblings, 1 reply; 11+ messages in thread
From: Guo-Fu Tseng @ 2011-11-19  4:19 UTC (permalink / raw)
  To: Aries Lee, netdev; +Cc: 'AriesLee'

On Fri, 18 Nov 2011 15:13:37 +0800, Aries Lee wrote
> Hi Guo-Fu and All
> 
> 	Because jme_phy_on() and jme_phy_off() just turn on/off the PHY, the
> value of extern register is still the power on default value, not the most
> robust value which we collect in the LAB.
Sure, I got it. That's the point of this patch isn't it? :p
+     /*  Turn PHY off */ 
+     bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 
+     bmcr |= BMCR_PDOWN; 
+     jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); 
+     /*  Turn PHY on */ 
+     bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 
+     bmcr &= ~BMCR_PDOWN; 
+     jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); 
But what I mean is this part of the code.

Guo-Fu Tseng

^ permalink raw reply	[flat|nested] 11+ messages in thread

* RE: [PATCH 1/1]  PHY configuration for compatible issue
  2011-11-19  4:19     ` Guo-Fu Tseng
@ 2011-11-21  2:13       ` Aries Lee
  0 siblings, 0 replies; 11+ messages in thread
From: Aries Lee @ 2011-11-21  2:13 UTC (permalink / raw)
  To: 'Guo-Fu Tseng', netdev; +Cc: 'AriesLee'


Yes ~~ that's indeed a good suggestion

-----Original Message-----
From: Guo-Fu Tseng [mailto:cooldavid@cooldavid.org] 
Sent: Saturday, November 19, 2011 12:20 PM
To: Aries Lee; netdev@vger.kernel.org
Cc: 'AriesLee'
Subject: RE: [PATCH 1/1] PHY configuration for compatible issue

On Fri, 18 Nov 2011 15:13:37 +0800, Aries Lee wrote
> Hi Guo-Fu and All
> 
> 	Because jme_phy_on() and jme_phy_off() just turn on/off the PHY, the
> value of extern register is still the power on default value, not the most
> robust value which we collect in the LAB.
Sure, I got it. That's the point of this patch isn't it? :p
+     /*  Turn PHY off */ 
+     bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 
+     bmcr |= BMCR_PDOWN; 
+     jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); 
+     /*  Turn PHY on */ 
+     bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR); 
+     bmcr &= ~BMCR_PDOWN; 
+     jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr); 
But what I mean is this part of the code.

Guo-Fu Tseng

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/1]  PHY configuration for compatible issue
  2011-11-21 10:08 AriesLee
@ 2011-11-21  5:35 ` Guo-Fu Tseng
  0 siblings, 0 replies; 11+ messages in thread
From: Guo-Fu Tseng @ 2011-11-21  5:35 UTC (permalink / raw)
  To: AriesLee, Aries Lee, netdev

On Mon, 21 Nov 2011 18:08:47 +0800, AriesLee wrote
> To perform PHY calibration and set a different EA value by chip ID,
> Whenever the NIC chip power on, ie booting or resuming, we need to
> force HW to calibrate PHY parameter again, and also set a proper EA
> value which gather from experiment.
> 
> Those procedures help to reduce compatible issues(NIC is unable to link
> up in some special case) in giga speed.
> 
> Signed-off-by: AriesLee <AriesLee@jmicron.com>
> ---
>  drivers/net/ethernet/jme.c |  113 
> ++++++++++++++++++++++++++++++++++++++++++- drivers/net/ethernet/jme.h 
> |   19 +++++++ 2 files changed, 129 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
> index df3ab83..4d217b8 100644
> --- a/drivers/net/ethernet/jme.c
> +++ b/drivers/net/ethernet/jme.c
> @@ -1744,6 +1744,112 @@ jme_phy_off(struct jme_adapter *jme)
>  		jme_new_phy_off(jme);
>  }
> 
> +static void
> +jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg, u32 *phy_data) 
> +{
> +	u32 phy_addr;
> +
> +	phy_addr = JM_PHY_SPEC_REG_READ | specreg;
> +	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
> +			phy_addr);
> +	*phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id,
> +			JM_PHY_SPEC_DATA_REG);
> +}
Is there any particular reason that you pass the address of reading data.
Instead of just returning the value? (phy_data)
It would be more consistent if you return the value in this kind of
read function.

Otherwise this path all seems to be OK to me. :)

Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>

Guo-Fu Tseng

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH 1/1]  PHY configuration for compatible issue
@ 2011-11-21 10:08 AriesLee
  2011-11-21  5:35 ` Guo-Fu Tseng
  0 siblings, 1 reply; 11+ messages in thread
From: AriesLee @ 2011-11-21 10:08 UTC (permalink / raw)
  To: Aries Lee, Guo-Fu Tseng, netdev; +Cc: AriesLee

To perform PHY calibration and set a different EA value by chip ID,
Whenever the NIC chip power on, ie booting or resuming, we need to
force HW to calibrate PHY parameter again, and also set a proper EA
value which gather from experiment.

Those procedures help to reduce compatible issues(NIC is unable to link
up in some special case) in giga speed.

Signed-off-by: AriesLee <AriesLee@jmicron.com>
---
 drivers/net/ethernet/jme.c |  113 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/ethernet/jme.h |   19 +++++++
 2 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index df3ab83..4d217b8 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1744,6 +1744,112 @@ jme_phy_off(struct jme_adapter *jme)
 		jme_new_phy_off(jme);
 }
 
+static void
+jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg, u32 *phy_data)
+{
+	u32 phy_addr;
+
+	phy_addr = JM_PHY_SPEC_REG_READ | specreg;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+	*phy_data = jme_mdio_read(jme->dev, jme->mii_if.phy_id,
+			JM_PHY_SPEC_DATA_REG);
+}
+
+static void
+jme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data)
+{
+	u32 phy_addr;
+
+	phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
+			phy_data);
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+}
+
+static int
+jme_phy_calibration(struct jme_adapter *jme)
+{
+	u32 ctrl1000, phy_data;
+
+	jme_phy_off(jme);
+	jme_phy_on(jme);
+	/*  Enabel PHY test mode 1 */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	ctrl1000 |= PHY_GAD_TEST_MODE_1;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+
+	jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG, &phy_data);
+	phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0;
+	phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH |
+			JM_PHY_EXT_COMM_2_CALI_ENABLE;
+	jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+	msleep(20);
+	jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG, &phy_data);
+	phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE |
+			JM_PHY_EXT_COMM_2_CALI_MODE_0 |
+			JM_PHY_EXT_COMM_2_CALI_LATCH);
+	jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+
+	/*  Disable PHY test mode */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+	return 0;
+}
+
+static int
+jme_phy_setEA(struct jme_adapter *jme)
+{
+	u32 phy_comm0 = 0, phy_comm1 = 0;
+	u8 nic_ctrl;
+
+	pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl);
+	if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE)
+		return 0;
+
+	switch (jme->pdev->device) {
+	case PCI_DEVICE_ID_JMICRON_JMC250:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		break;
+	case PCI_DEVICE_ID_JMICRON_JMC260:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0))
+			phy_comm0 = 0x608A;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2))
+			phy_comm0 = 0x408A;
+		break;
+	default:
+		return -ENODEV;
+	}
+	if (phy_comm0)
+		jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0);
+	if (phy_comm1)
+		jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1);
+
+	return 0;
+}
+
 static int
 jme_open(struct net_device *netdev)
 {
@@ -1769,7 +1875,8 @@ jme_open(struct net_device *netdev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_reset_link(jme);
 
 	return 0;
@@ -3184,7 +3291,8 @@ jme_resume(struct device *dev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
 
@@ -3239,4 +3347,3 @@ MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, jme_pci_tbl);
-
diff --git a/drivers/net/ethernet/jme.h b/drivers/net/ethernet/jme.h
index 02ea27c..4304072 100644
--- a/drivers/net/ethernet/jme.h
+++ b/drivers/net/ethernet/jme.h
@@ -760,6 +760,25 @@ enum jme_rxmcs_bits {
 				  RXMCS_CHECKSUM,
 };
 
+/*	Extern PHY common register 2	*/
+
+#define PHY_GAD_TEST_MODE_1			0x00002000
+#define PHY_GAD_TEST_MODE_MSK			0x0000E000
+#define JM_PHY_SPEC_REG_READ			0x00004000
+#define JM_PHY_SPEC_REG_WRITE			0x00008000
+#define PHY_CALIBRATION_DELAY			20
+#define JM_PHY_SPEC_ADDR_REG			0x1E
+#define JM_PHY_SPEC_DATA_REG			0x1F
+
+#define JM_PHY_EXT_COMM_0_REG			0x30
+#define JM_PHY_EXT_COMM_1_REG			0x31
+#define JM_PHY_EXT_COMM_2_REG			0x32
+#define JM_PHY_EXT_COMM_2_CALI_ENABLE		0x01
+#define JM_PHY_EXT_COMM_2_CALI_MODE_0		0x02
+#define JM_PHY_EXT_COMM_2_CALI_LATCH		0x10
+#define PCI_PRIV_SHARE_NICCTRL			0xF5
+#define JME_FLAG_PHYEA_ENABLE			0x2
+
 /*
  * Wakeup Frame setup interface registers
  */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 1/1]   PHY configuration for compatible issue
@ 2011-11-21 20:20 AriesLee
  2011-11-22 16:19 ` Guo-Fu Tseng
  2011-11-28  0:22 ` David Miller
  0 siblings, 2 replies; 11+ messages in thread
From: AriesLee @ 2011-11-21 20:20 UTC (permalink / raw)
  To: Aries Lee, Guo-Fu Tseng, netdev; +Cc: AriesLee

To perform PHY calibration and set a different EA value by chip ID,
Whenever the NIC chip power on, ie booting or resuming, we need to
force HW to calibrate PHY parameter again, and also set a proper EA
value which gather from experiment.

Those procedures help to reduce compatible issues(NIC is unable to link
up in some special case) in giga speed.

Signed-off-by: AriesLee <AriesLee@jmicron.com>
---
 drivers/net/ethernet/jme.c |  113 ++++++++++++++++++++++++++++++++++++++++++-
 drivers/net/ethernet/jme.h |   19 +++++++
 2 files changed, 129 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/jme.c b/drivers/net/ethernet/jme.c
index df3ab83..8ebbb33 100644
--- a/drivers/net/ethernet/jme.c
+++ b/drivers/net/ethernet/jme.c
@@ -1745,6 +1745,112 @@ jme_phy_off(struct jme_adapter *jme)
 }
 
 static int
+jme_phy_specreg_read(struct jme_adapter *jme, u32 specreg)
+{
+	u32 phy_addr;
+
+	phy_addr = JM_PHY_SPEC_REG_READ | specreg;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+	return jme_mdio_read(jme->dev, jme->mii_if.phy_id,
+			JM_PHY_SPEC_DATA_REG);
+}
+
+static void
+jme_phy_specreg_write(struct jme_adapter *jme, u32 ext_reg, u32 phy_data)
+{
+	u32 phy_addr;
+
+	phy_addr = JM_PHY_SPEC_REG_WRITE | ext_reg;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_DATA_REG,
+			phy_data);
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, JM_PHY_SPEC_ADDR_REG,
+			phy_addr);
+}
+
+static int
+jme_phy_calibration(struct jme_adapter *jme)
+{
+	u32 ctrl1000, phy_data;
+
+	jme_phy_off(jme);
+	jme_phy_on(jme);
+	/*  Enabel PHY test mode 1 */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	ctrl1000 |= PHY_GAD_TEST_MODE_1;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+
+	phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG);
+	phy_data &= ~JM_PHY_EXT_COMM_2_CALI_MODE_0;
+	phy_data |= JM_PHY_EXT_COMM_2_CALI_LATCH |
+			JM_PHY_EXT_COMM_2_CALI_ENABLE;
+	jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+	msleep(20);
+	phy_data = jme_phy_specreg_read(jme, JM_PHY_EXT_COMM_2_REG);
+	phy_data &= ~(JM_PHY_EXT_COMM_2_CALI_ENABLE |
+			JM_PHY_EXT_COMM_2_CALI_MODE_0 |
+			JM_PHY_EXT_COMM_2_CALI_LATCH);
+	jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_2_REG, phy_data);
+
+	/*  Disable PHY test mode */
+	ctrl1000 = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_CTRL1000);
+	ctrl1000 &= ~PHY_GAD_TEST_MODE_MSK;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_CTRL1000, ctrl1000);
+	return 0;
+}
+
+static int
+jme_phy_setEA(struct jme_adapter *jme)
+{
+	u32 phy_comm0 = 0, phy_comm1 = 0;
+	u8 nic_ctrl;
+
+	pci_read_config_byte(jme->pdev, PCI_PRIV_SHARE_NICCTRL, &nic_ctrl);
+	if ((nic_ctrl & 0x3) == JME_FLAG_PHYEA_ENABLE)
+		return 0;
+
+	switch (jme->pdev->device) {
+	case PCI_DEVICE_ID_JMICRON_JMC250:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		break;
+	case PCI_DEVICE_ID_JMICRON_JMC260:
+		if (((jme->chip_main_rev == 5) &&
+			((jme->chip_sub_rev == 0) || (jme->chip_sub_rev == 1) ||
+			(jme->chip_sub_rev == 3))) ||
+			(jme->chip_main_rev >= 6)) {
+			phy_comm0 = 0x008A;
+			phy_comm1 = 0x4109;
+		}
+		if ((jme->chip_main_rev == 3) &&
+			((jme->chip_sub_rev == 1) || (jme->chip_sub_rev == 2)))
+			phy_comm0 = 0xE088;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 0))
+			phy_comm0 = 0x608A;
+		if ((jme->chip_main_rev == 2) && (jme->chip_sub_rev == 2))
+			phy_comm0 = 0x408A;
+		break;
+	default:
+		return -ENODEV;
+	}
+	if (phy_comm0)
+		jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_0_REG, phy_comm0);
+	if (phy_comm1)
+		jme_phy_specreg_write(jme, JM_PHY_EXT_COMM_1_REG, phy_comm1);
+
+	return 0;
+}
+
+static int
 jme_open(struct net_device *netdev)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
@@ -1769,7 +1875,8 @@ jme_open(struct net_device *netdev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_reset_link(jme);
 
 	return 0;
@@ -3184,7 +3291,8 @@ jme_resume(struct device *dev)
 		jme_set_settings(netdev, &jme->old_ecmd);
 	else
 		jme_reset_phy_processor(jme);
-
+	jme_phy_calibration(jme);
+	jme_phy_setEA(jme);
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
 
@@ -3239,4 +3347,3 @@ MODULE_DESCRIPTION("JMicron JMC2x0 PCI Express Ethernet driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_VERSION);
 MODULE_DEVICE_TABLE(pci, jme_pci_tbl);
-
diff --git a/drivers/net/ethernet/jme.h b/drivers/net/ethernet/jme.h
index 02ea27c..4304072 100644
--- a/drivers/net/ethernet/jme.h
+++ b/drivers/net/ethernet/jme.h
@@ -760,6 +760,25 @@ enum jme_rxmcs_bits {
 				  RXMCS_CHECKSUM,
 };
 
+/*	Extern PHY common register 2	*/
+
+#define PHY_GAD_TEST_MODE_1			0x00002000
+#define PHY_GAD_TEST_MODE_MSK			0x0000E000
+#define JM_PHY_SPEC_REG_READ			0x00004000
+#define JM_PHY_SPEC_REG_WRITE			0x00008000
+#define PHY_CALIBRATION_DELAY			20
+#define JM_PHY_SPEC_ADDR_REG			0x1E
+#define JM_PHY_SPEC_DATA_REG			0x1F
+
+#define JM_PHY_EXT_COMM_0_REG			0x30
+#define JM_PHY_EXT_COMM_1_REG			0x31
+#define JM_PHY_EXT_COMM_2_REG			0x32
+#define JM_PHY_EXT_COMM_2_CALI_ENABLE		0x01
+#define JM_PHY_EXT_COMM_2_CALI_MODE_0		0x02
+#define JM_PHY_EXT_COMM_2_CALI_LATCH		0x10
+#define PCI_PRIV_SHARE_NICCTRL			0xF5
+#define JME_FLAG_PHYEA_ENABLE			0x2
+
 /*
  * Wakeup Frame setup interface registers
  */
-- 
1.7.4.4

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/1]   PHY configuration for compatible issue
  2011-11-21 20:20 AriesLee
@ 2011-11-22 16:19 ` Guo-Fu Tseng
  2011-11-28  0:22 ` David Miller
  1 sibling, 0 replies; 11+ messages in thread
From: Guo-Fu Tseng @ 2011-11-22 16:19 UTC (permalink / raw)
  To: AriesLee, Aries Lee, netdev

On Tue, 22 Nov 2011 04:20:42 +0800, AriesLee wrote
> To perform PHY calibration and set a different EA value by chip ID,
> Whenever the NIC chip power on, ie booting or resuming, we need to
> force HW to calibrate PHY parameter again, and also set a proper EA
> value which gather from experiment.
> 
> Those procedures help to reduce compatible issues(NIC is unable to link
> up in some special case) in giga speed.
> 
> Signed-off-by: AriesLee <AriesLee@jmicron.com>
Signed-off-by: Guo-Fu Tseng <cooldavid@cooldavid.org>

Guo-Fu Tseng

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/1] PHY configuration for compatible issue
  2011-11-21 20:20 AriesLee
  2011-11-22 16:19 ` Guo-Fu Tseng
@ 2011-11-28  0:22 ` David Miller
  1 sibling, 0 replies; 11+ messages in thread
From: David Miller @ 2011-11-28  0:22 UTC (permalink / raw)
  To: AriesLee; +Cc: ariesleeILan, cooldavid, netdev

From: AriesLee <AriesLee@jmicron.com>
Date: Tue, 22 Nov 2011 04:20:42 +0800

> To perform PHY calibration and set a different EA value by chip ID,
> Whenever the NIC chip power on, ie booting or resuming, we need to
> force HW to calibrate PHY parameter again, and also set a proper EA
> value which gather from experiment.
> 
> Those procedures help to reduce compatible issues(NIC is unable to link
> up in some special case) in giga speed.
> 
> Signed-off-by: AriesLee <AriesLee@jmicron.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2011-11-28  0:23 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-11-17 14:05 [PATCH 1/1] PHY configuration for compatible issue AriesLee
2011-11-17  7:15 ` Guo-Fu Tseng
2011-11-18  7:13   ` Aries Lee
2011-11-19  4:19     ` Guo-Fu Tseng
2011-11-21  2:13       ` Aries Lee
  -- strict thread matches above, loose matches on Subject: below --
2011-11-18 14:54 AriesLee
2011-11-21 10:08 AriesLee
2011-11-21  5:35 ` Guo-Fu Tseng
2011-11-21 20:20 AriesLee
2011-11-22 16:19 ` Guo-Fu Tseng
2011-11-28  0:22 ` David Miller

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).