|
@@ -129,10 +129,35 @@ static struct device_node *emac_boot_list[EMAC_BOOT_LIST_SIZE];
|
|
|
static inline void emac_report_timeout_error(struct emac_instance *dev,
|
|
|
const char *error)
|
|
|
{
|
|
|
- if (net_ratelimit())
|
|
|
+ if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX |
|
|
|
+ EMAC_FTR_440EP_PHY_CLK_FIX))
|
|
|
+ DBG(dev, "%s" NL, error);
|
|
|
+ else if (net_ratelimit())
|
|
|
printk(KERN_ERR "%s: %s\n", dev->ndev->name, error);
|
|
|
}
|
|
|
|
|
|
+/* EMAC PHY clock workaround:
|
|
|
+ * 440EP/440GR has more sane SDR0_MFR register implementation than 440GX,
|
|
|
+ * which allows controlling each EMAC clock
|
|
|
+ */
|
|
|
+static inline void emac_rx_clk_tx(struct emac_instance *dev)
|
|
|
+{
|
|
|
+#ifdef CONFIG_PPC_DCR_NATIVE
|
|
|
+ if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
|
|
|
+ dcri_clrset(SDR0, SDR0_MFR,
|
|
|
+ 0, SDR0_MFR_ECS >> dev->cell_index);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
+static inline void emac_rx_clk_default(struct emac_instance *dev)
|
|
|
+{
|
|
|
+#ifdef CONFIG_PPC_DCR_NATIVE
|
|
|
+ if (emac_has_feature(dev, EMAC_FTR_440EP_PHY_CLK_FIX))
|
|
|
+ dcri_clrset(SDR0, SDR0_MFR,
|
|
|
+ SDR0_MFR_ECS >> dev->cell_index, 0);
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
/* PHY polling intervals */
|
|
|
#define PHY_POLL_LINK_ON HZ
|
|
|
#define PHY_POLL_LINK_OFF (HZ / 5)
|
|
@@ -1099,9 +1124,11 @@ static int emac_open(struct net_device *ndev)
|
|
|
int link_poll_interval;
|
|
|
if (dev->phy.def->ops->poll_link(&dev->phy)) {
|
|
|
dev->phy.def->ops->read_link(&dev->phy);
|
|
|
+ emac_rx_clk_default(dev);
|
|
|
netif_carrier_on(dev->ndev);
|
|
|
link_poll_interval = PHY_POLL_LINK_ON;
|
|
|
} else {
|
|
|
+ emac_rx_clk_tx(dev);
|
|
|
netif_carrier_off(dev->ndev);
|
|
|
link_poll_interval = PHY_POLL_LINK_OFF;
|
|
|
}
|
|
@@ -1179,6 +1206,7 @@ static void emac_link_timer(struct work_struct *work)
|
|
|
|
|
|
if (dev->phy.def->ops->poll_link(&dev->phy)) {
|
|
|
if (!netif_carrier_ok(dev->ndev)) {
|
|
|
+ emac_rx_clk_default(dev);
|
|
|
/* Get new link parameters */
|
|
|
dev->phy.def->ops->read_link(&dev->phy);
|
|
|
|
|
@@ -1191,6 +1219,7 @@ static void emac_link_timer(struct work_struct *work)
|
|
|
link_poll_interval = PHY_POLL_LINK_ON;
|
|
|
} else {
|
|
|
if (netif_carrier_ok(dev->ndev)) {
|
|
|
+ emac_rx_clk_tx(dev);
|
|
|
netif_carrier_off(dev->ndev);
|
|
|
netif_tx_disable(dev->ndev);
|
|
|
emac_reinitialize(dev);
|
|
@@ -2339,6 +2368,14 @@ static int __devinit emac_init_phy(struct emac_instance *dev)
|
|
|
#ifdef CONFIG_PPC_DCR_NATIVE
|
|
|
if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
|
|
|
dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
|
|
|
+#endif
|
|
|
+ /* PHY clock workaround */
|
|
|
+ emac_rx_clk_tx(dev);
|
|
|
+
|
|
|
+ /* Enable internal clock source on 440GX*/
|
|
|
+#ifdef CONFIG_PPC_DCR_NATIVE
|
|
|
+ if (emac_has_feature(dev, EMAC_FTR_440GX_PHY_CLK_FIX))
|
|
|
+ dcri_clrset(SDR0, SDR0_MFR, 0, SDR0_MFR_ECS);
|
|
|
#endif
|
|
|
/* Configure EMAC with defaults so we can at least use MDIO
|
|
|
* This is needed mostly for 440GX
|
|
@@ -2507,6 +2544,10 @@ static int __devinit emac_init_config(struct emac_instance *dev)
|
|
|
dev->features |= EMAC_FTR_EMAC4;
|
|
|
if (of_device_is_compatible(np, "ibm,emac-440gx"))
|
|
|
dev->features |= EMAC_FTR_440GX_PHY_CLK_FIX;
|
|
|
+ } else {
|
|
|
+ if (of_device_is_compatible(np, "ibm,emac-440ep") ||
|
|
|
+ of_device_is_compatible(np, "ibm,emac-440gr"))
|
|
|
+ dev->features |= EMAC_FTR_440EP_PHY_CLK_FIX;
|
|
|
}
|
|
|
|
|
|
/* Fixup some feature bits based on the device tree */
|