Merge remote-tracking branch 'gfiber-internal/master' into work2
diff --git a/3.3/bmoca.c b/3.3/bmoca.c
index 075520c..5f0a5c6 100644
--- a/3.3/bmoca.c
+++ b/3.3/bmoca.c
@@ -1457,6 +1457,8 @@
 	u32 mask = 0;
 	int ret, stopped = 0;
 
+	mutex_lock(&priv->dev_mutex);
+
 	if (priv->enabled) {
 		mask = moca_irq_status(priv, FLUSH_IRQ);
 		if (mask & M2H_DMA) {
@@ -1476,6 +1478,7 @@
 		}
 
 		if (mask == 0) {
+			mutex_unlock(&priv->dev_mutex);
 			moca_enable_irq(priv);
 			return;
 		}
@@ -1484,14 +1487,13 @@
 			M2H_REQ_CPU0 | M2H_RESP_CPU0)) {
 			if (moca_get_mbx_offset(priv)) {
 				/* mbx interrupt but mbx_offset is bogus?? */
+				mutex_unlock(&priv->dev_mutex);
 				moca_enable_irq(priv);
 				return;
 			}
 		}
 	}
 
-	mutex_lock(&priv->dev_mutex);
-
 	if (!priv->running) {
 		stopped = 1;
 	} else {
@@ -1737,6 +1739,10 @@
 {
 	u32 data;
 
+	/* some platforms connect the i2c directly to the MoCA core */
+	if (!priv->i2c_base)
+		return;
+
 	mutex_lock(&priv->moca_i2c_mutex);
 
 	if (action == MOCA_ENABLE) {
diff --git a/3.8/bmoca.c b/3.8/bmoca.c
index 79e0dc0..6702fde 100644
--- a/3.8/bmoca.c
+++ b/3.8/bmoca.c
@@ -1332,6 +1332,8 @@
 	u32 mask = 0;
 	int ret, stopped = 0;
 
+	mutex_lock(&priv->dev_mutex);
+
 	if (priv->enabled) {
 		mask = moca_irq_status(priv, FLUSH_IRQ);
 		if (mask & M2H_DMA) {
@@ -1350,6 +1352,7 @@
 		}
 
 		if (mask == 0) {
+			mutex_unlock(&priv->dev_mutex);
 			moca_enable_irq(priv);
 			return;
 		}
@@ -1358,14 +1361,13 @@
 			M2H_REQ_CPU0 | M2H_RESP_CPU0)) {
 			if (moca_get_mbx_offset(priv)) {
 				/* mbx interrupt but mbx_offset is bogus?? */
+				mutex_unlock(&priv->dev_mutex);
 				moca_enable_irq(priv);
 				return;
 			}
 		}
 	}
 
-	mutex_lock(&priv->dev_mutex);
-
 	if (!priv->running) {
 		stopped = 1;
 	} else {
diff --git a/bmoca-6802.c b/bmoca-6802.c
index 0df7bd6..8335d67 100644
--- a/bmoca-6802.c
+++ b/bmoca-6802.c
@@ -436,8 +436,6 @@
 	if (action == MOCA_ENABLE && !priv->enabled) {
 		clk_enable(priv->clk);
 
-		MOCA_WR(0x10404318, 0xfffffffd); // SUN_TOP_CTRL_SW_INIT_0_SET
-		udelay(20);
 		MOCA_WR(0x1040431c, ~(1 << 26)); // SUN_TOP_CTRL_SW_INIT_0_CLEAR --> Do this at start of sequence, don't touch gphy_sw_init
 		udelay(20);
 		moca_gphy_init(priv);
@@ -452,14 +450,6 @@
 	moca_hw_reset(priv);
 	udelay(1);
 
-	MOCA_WR(0x10800000, 0x03);       // EMUX_CNTRL
-	MOCA_WR(0x1080000c, 0x11);       // RGMII_0_CNTRL
-	MOCA_WR(0x10800014, 0xc0);       // RGMII_0_RX_CLK_DELAY_CNTRL
-
-	MOCA_WR(0x104040a4, 0x01);       // GENERAL_CTRL_NO_SCAN_0
-	MOCA_WR(0x10404100, 0x11110011); // PIN_MUX_CTRL_0
-	MOCA_WR(0x10404104, 0x11111111); // PIN_MUX_CTRL_1
-
 	if (action == MOCA_ENABLE) {
 
 		/* Power up all zones */
@@ -915,6 +905,7 @@
 {
 #ifdef DSL_MOCA
 	struct moca_platform_data *pMocaData;
+	u32 port_mode;
 
 	pMocaData = (struct moca_platform_data *)priv->pdev->dev.platform_data;
 
@@ -926,6 +917,29 @@
 		return -EFAULT;
 	}
 
+	MOCA_WR(0x1040431c, 0x0FFFFFFF); // SUN_TOP_CTRL_SW_INIT_0_CLEAR
+	MOCA_WR(0x104040a4, 0x01);       // GENERAL_CTRL_NO_SCAN_0
+	/* Power down GPHY LDO regulator to save power */
+	MOCA_WR(0x104040a8, 0x03);       // GENERAL_CTRL_NO_SCAN_1
+	MOCA_WR(0x10404100, 0x11110011); // PIN_MUX_CTRL_0
+	MOCA_WR(0x10404104, 0x11111111); // PIN_MUX_CTRL_1
+
+	/* The definition of PORT_MODE has changed from chip revision B0 to C0
+	 * */
+	if ((pMocaData->chip_id & 0xFFFEFFF0) == 0x680200C0)
+		port_mode = 2; /* RGMII_1 <-> GPHY, RGMII_0 <-> MoCA */
+	else
+		port_mode = 3; /* RGMII_0 <-> MoCA */
+
+	MOCA_WR(0x10800000, port_mode);  // EMUX_CNTRL
+	MOCA_WR(0x1080000c, 0x11);       // RGMII_0_CNTRL
+	MOCA_WR(0x10800014, 0xc0);       // RGMII_0_RX_CLK_DELAY_CNTRL
+
+	/* Shutdown GPHY to save power */
+	MOCA_WR(0x10800004, MOCA_RD(0x10800004) | 0xF); // EPORT_REG_GPHY_CNTRL
+	/* Disable UARTs to save power */
+	MOCA_WR(0x10406180, 0x4000); // PM_CONFIG
+
 	if (((pMocaData->chip_id & 0xFFFFFFF0) == 0x680200C0) || ((pMocaData->chip_id & 0xFFFFFFF0) == 0x680300C0))
 	{
 		priv->i2c_base = NULL; 
@@ -946,6 +960,11 @@
 	MOCA_WR(0x101000fc, 0x6); // CLKGEN_LEAP_TOP_INST_SHARED  
 	MOCA_WR(0x10100164, 0x3); // CLKGEN_SYS_CTRL_INST_POWER_SWITCH_MEMORY 
 
+	/* Disable clkobsv output pin to save power */
+	MOCA_WR(0x1010013C, 0x1); // CLKGEN_PAD_CLOCK_DISABLE
+	/* Disable LEAP clocks to save power */
+	MOCA_WR(0x101000D4, 0x7); // CLKGEN_LEAP_TOP_INST_CLOCK_DISABLE
+
 //	bcmenet_register_moca_fc_bits_cb(
 //		moca_get_fc_bits, pMocaData->use_spi ? 1 : 0, (void *)priv);
 #endif