MIPS: qca956x: Enable AP151 target support

The following features are enabled ,
1) AP151 target specific configs are added ( mainly ethernet )
2) AP151 and AP152 share a common configuration file & Makefile
with minimal changes between them. Support for avoiding the conflict
between them is implemented.

Change-Id: Ia71b20199d43cd29ff214c1258e4b15fcd55cb6b
Signed-off-by: Prabhu Jayakumar <pjayak@codeaurora.org>
diff --git a/board/qca/mips32/common/ath_phy.h b/board/qca/mips32/common/ath_phy.h
index e8aa749..bbfda27 100644
--- a/board/qca/mips32/common/ath_phy.h
+++ b/board/qca/mips32/common/ath_phy.h
@@ -12,10 +12,8 @@
  *
  */
 
-#ifndef _PHY_H
-#define _PHY_H
-
-#include <config.h>
+#ifndef _ATH_PHY_H
+#define _ATH_PHY_H
 
 #define ath_gmac_unit2name(_unit) (_unit ?  "eth1" : "eth0")
 
diff --git a/board/qca/mips32/common/athr_s27_phy.c b/board/qca/mips32/common/athr_s27_phy.c
new file mode 100644
index 0000000..4053426
--- /dev/null
+++ b/board/qca/mips32/common/athr_s27_phy.c
@@ -0,0 +1,849 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+/*
+ * Manage the atheros ethernet PHY.
+ *
+ * All definitions in this file are operating system independent!
+ */
+
+#include <config.h>
+#include <linux/types.h>
+#include <common.h>
+#include <miiphy.h>
+#include <asm/addrspace.h>
+#include <atheros.h>
+#include "athr_s27_phy.h"
+#include "ath_phy.h"
+
+/* PHY selections and access functions */
+
+typedef enum {
+    PHY_SRCPORT_INFO,
+    PHY_PORTINFO_SIZE,
+} PHY_CAP_TYPE;
+
+typedef enum {
+    PHY_SRCPORT_NONE,
+    PHY_SRCPORT_VLANTAG,
+    PHY_SRCPORT_TRAILER,
+} PHY_SRCPORT_TYPE;
+
+
+#define _UNKNOWN_SPEED 0
+#define DRV_LOG(DBG_SW, X0, X1, X2, X3, X4, X5, X6)
+#define DRV_MSG(x,a,b,c,d,e,f)
+#define DRV_PRINT(DBG_SW,X)
+
+#define ATHR_LAN_PORT_VLAN          1
+#define ATHR_WAN_PORT_VLAN          2
+#define ENET_UNIT_LAN 1
+#define ENET_UNIT_WAN 0
+
+#define TRUE    1
+#define FALSE   0
+
+#define ATHR_PHY0_ADDR   0x0
+#define ATHR_PHY1_ADDR   0x1
+#define ATHR_PHY2_ADDR   0x2
+#define ATHR_PHY3_ADDR   0x3
+#define ATHR_PHY4_ADDR   0x4
+
+#define MODULE_NAME "ATHRS27"
+/*
+ * Track per-PHY port information.
+ */
+
+
+typedef struct {
+    BOOL   isEnetPort;       /* normal enet port */
+    BOOL   isPhyAlive;       /* last known state of link */
+    int    ethUnit;          /* MAC associated with this phy port */
+    uint32_t phyBase;
+    uint32_t phyAddr;          /* PHY registers associated with this phy port */
+    uint32_t VLANTableSetting; /* Value to be written to VLAN table */
+} athrPhyInfo_t;
+
+/*
+ * Per-PHY information, indexed by PHY unit number.
+ */
+static athrPhyInfo_t athrPhyInfo[] = {
+
+    {TRUE,   /* port 1 -- LAN port 1 */
+     FALSE,
+     ENET_UNIT_LAN,
+     0,
+     ATHR_PHY0_ADDR,
+     ATHR_LAN_PORT_VLAN
+    },
+
+    {TRUE,   /* port 2 -- LAN port 2 */
+     FALSE,
+     ENET_UNIT_LAN,
+     0,
+     ATHR_PHY1_ADDR,
+     ATHR_LAN_PORT_VLAN
+    },
+
+    {TRUE,   /* port 3 -- LAN port 3 */
+     FALSE,
+     ENET_UNIT_LAN,
+     0,
+     ATHR_PHY2_ADDR,
+     ATHR_LAN_PORT_VLAN
+    },
+
+
+   {TRUE,   /* port 4 --  LAN port 4 */
+     FALSE,
+     ENET_UNIT_LAN,
+     0,
+     ATHR_PHY3_ADDR,
+     ATHR_LAN_PORT_VLAN   /* Send to all ports */
+    },
+
+    {TRUE,  /* port 5 -- WAN Port 5 */
+     FALSE,
+     ENET_UNIT_WAN,
+     0,
+     ATHR_PHY4_ADDR,
+     ATHR_LAN_PORT_VLAN    /* Send to all ports */
+    },
+
+    {FALSE,   /* port 0 -- cpu port 0 */
+     TRUE,
+     ENET_UNIT_LAN,
+     0,
+     0x00,
+     ATHR_LAN_PORT_VLAN
+    },
+
+};
+
+
+#define ATHR_GLOBALREGBASE    0
+
+#define ATHR_PHY_MAX 5
+
+/* Range of valid PHY IDs is [MIN..MAX] */
+#define ATHR_ID_MIN 0
+#define ATHR_ID_MAX (ATHR_PHY_MAX-1)
+
+
+/* Convenience macros to access myPhyInfo */
+#define ATHR_IS_ENET_PORT(phyUnit) (athrPhyInfo[phyUnit].isEnetPort)
+#define ATHR_IS_PHY_ALIVE(phyUnit) (athrPhyInfo[phyUnit].isPhyAlive)
+#define ATHR_ETHUNIT(phyUnit) (athrPhyInfo[phyUnit].ethUnit)
+#define ATHR_PHYBASE(phyUnit) (athrPhyInfo[phyUnit].phyBase)
+#define ATHR_PHYADDR(phyUnit) (athrPhyInfo[phyUnit].phyAddr)
+#define ATHR_VLAN_TABLE_SETTING(phyUnit) (athrPhyInfo[phyUnit].VLANTableSetting)
+
+
+#define ATHR_IS_ETHUNIT(phyUnit, ethUnit) \
+            (ATHR_IS_ENET_PORT(phyUnit) &&        \
+            ATHR_ETHUNIT(phyUnit) == (ethUnit))
+
+#define ATHR_IS_WAN_PORT(phyUnit) (!(ATHR_ETHUNIT(phyUnit)==ENET_UNIT_LAN))
+
+/* Forward references */
+BOOL athrs27_phy_is_link_alive(int phyUnit);
+uint32_t athrs27_reg_read(uint32_t reg_addr);
+void athrs27_reg_write(uint32_t reg_addr, uint32_t reg_val);
+unsigned int s27_rd_phy(unsigned int phy_addr, unsigned int reg_addr);
+void s27_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data);
+
+
+void athrs27_powersave_off(int phy_addr)
+{
+    s27_wr_phy(phy_addr,ATHR_DEBUG_PORT_ADDRESS,0x29);
+    s27_wr_phy(phy_addr,ATHR_DEBUG_PORT_DATA,0x36c0);
+
+}
+void athrs27_sleep_off(int phy_addr)
+{
+    s27_wr_phy(phy_addr,ATHR_DEBUG_PORT_ADDRESS,0xb);
+    s27_wr_phy(phy_addr,ATHR_DEBUG_PORT_DATA,0x3c00);
+}
+
+void athrs27_force_100M(int phyAddr,int duplex)
+{
+   /*
+    *  Force MDI and MDX to alternate ports
+    *  Phy 0,2 and 4 -- MDI
+    *  Phy 1 and 3 -- MDX
+    */
+
+    if(phyAddr%2) {
+        s27_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x820);
+    }
+    else {
+        s27_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x800);
+    }
+
+    s27_wr_phy(phyAddr,0x1d,0x29);
+    s27_wr_phy(phyAddr,0x1e,0x0);
+    s27_wr_phy(phyAddr,0x10,0xc60);
+    s27_wr_phy(phyAddr,ATHR_PHY_CONTROL,(0xa000|(duplex << 8)));
+}
+
+void athrs27_force_10M(int phyAddr,int duplex)
+{
+
+    athrs27_powersave_off(phyAddr);
+    athrs27_sleep_off(phyAddr);
+
+    s27_wr_phy(phyAddr,ATHR_PHY_CONTROL,(0x8000 |(duplex << 8)));
+}
+
+int athrs27_reg_init(void)
+{
+#if S27_PHY_DEBUG
+    uint32_t rd_val;
+#endif
+
+    /* if using header for register configuration, we have to     */
+    /* configure s27 register after frame transmission is enabled */
+    athrs27_reg_rmw(0x8,(1<<28));  /* Set WAN port is connected to GE0 */
+
+#if defined(S27_FORCE_100M)
+    athrs27_force_100M(ATHR_PHY4_ADDR,1);
+#elif  defined(S27_FORCE_10M)
+    athrs27_force_10M(ATHR_PHY4_ADDR,1);
+#else
+    s27_wr_phy(ATHR_PHY4_ADDR,ATHR_PHY_CONTROL,0x9000);
+
+#endif
+#ifdef S27_PHY_DEBUG
+    printf(MODULE_NAME":OPERATIONAL_MODE_REG0:%x\n",athrs27_reg_read(OPERATIONAL_MODE_REG0));
+    printf(MODULE_NAME":REG 0x4-->:%x\n",athrs27_reg_read(0x4));
+    printf(MODULE_NAME":REG 0x2c-->:%x\n",athrs27_reg_read(0x2c));
+    printf(MODULE_NAME":REG 0x8-->:%x\n",athrs27_reg_read(0x8));
+#endif
+
+    return 0;
+}
+
+int athrs27_reg_init_lan(void)
+{
+    int i = 60;
+#if S26_PHY_DEBUG
+    uint32_t rd_val;
+#endif
+    int       phyUnit;
+    uint32_t  phyBase = 0;
+    BOOL      foundPhy = FALSE;
+    uint32_t  phyAddr = 0;
+
+
+    /* reset switch */
+    printf(MODULE_NAME ": resetting s27\n");
+    athrs27_reg_write(0x0, athrs27_reg_read(0x0)|0x80000000);
+
+    while(i--) {
+        sysMsDelay(100);
+        if(!(athrs27_reg_read(0x0)&0x80000000))
+            break;
+    }
+    printf(MODULE_NAME ": s27 reset done\n");
+    athrs27_reg_write(PORT_STATUS_REGISTER0,0x4e);
+
+    athrs27_reg_rmw(OPERATIONAL_MODE_REG0,(1<<6));  /* Set GMII mode */
+
+    if (is_emu() || is_wasp()) {
+       athrs27_reg_rmw(0x2c,((1<<26)| (1<<16) | 0x1)); /* FiX ME: EBU debug */
+    }
+
+    for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+
+        foundPhy = TRUE;
+        phyBase = ATHR_PHYBASE(phyUnit);
+        phyAddr = ATHR_PHYADDR(phyUnit);
+
+#if defined(S27_FORCE_100M)
+        athrs27_force_100M(phyAddr,1);
+#elif defined(S27_FORCE_10M)
+        athrs27_force_10M(phyAddr,1);
+#else
+        s27_wr_phy(phyAddr,ATHR_PHY_CONTROL,0x9000);
+#endif
+
+#if S27_PHY_DEBUG
+        rd_val = s27_rd_phy(phyAddr,ATHR_PHY_FUNC_CONTROL);
+        printf("S27 ATHR_PHY_FUNC_CONTROL (%d):%x\n",phyAddr,rd_val);
+        rd_val = s27_rd_phy(phyAddr,ATHR_PHY_ID1);
+        printf("S27 PHY ID  (%d) :%x\n",phyAddr, rd_val);
+        rd_val = s27_rd_phy(phyAddr,ATHR_PHY_SPEC_STATUS);
+        printf("S27 PHY CTRL  (%d) :%x\n",phyAddr, rd_val);
+        rd_val = s27_rd_phy(phyAddr,ATHR_PHY_STATUS);
+        printf("S27 ATHR PHY STATUS  (%d) :%x\n",phyAddr, rd_val);
+#endif
+    }
+
+    /*
+     * status[1:0]=2'h2;   - (0x10 - 1000 Mbps , 0x01 - 100Mbps, 0x0 - 10 Mbps)
+     * status[2]=1'h1;     - Tx Mac En
+     * status[3]=1'h1;     - Rx Mac En
+     * status[4]=1'h1;     - Tx Flow Ctrl En
+     * status[5]=1'h1;     - Rx Flow Ctrl En
+     * status[6]=1'h1;     - Duplex Mode
+     */
+    athrs27_reg_write(PORT_STATUS_REGISTER1, 0x200);  /* LAN - 1 */
+    athrs27_reg_write(PORT_STATUS_REGISTER2, 0x200);  /* LAN - 2 */
+    athrs27_reg_write(PORT_STATUS_REGISTER3, 0x200);  /* LAN - 3 */
+    athrs27_reg_write(PORT_STATUS_REGISTER4, 0x200);  /* LAN - 4 */
+
+    if (is_emu()) {
+        athrs27_reg_write(PORT_STATUS_REGISTER1, 0x4C);  /* LAN - 1 */
+        athrs27_reg_write(PORT_STATUS_REGISTER2, 0x4c);  /* LAN - 2 */
+        athrs27_reg_write(PORT_STATUS_REGISTER3, 0x4c);  /* LAN - 3 */
+        athrs27_reg_write(PORT_STATUS_REGISTER4, 0x4c);  /* LAN - 4 */
+    }
+
+    /* QM Control */
+    athrs27_reg_write(0x38, 0xc000050e);
+
+    /*
+     * status[11]=1'h0;    - CPU Disable
+     * status[7] = 1'b1;   - Learn One Lock
+     * status[14] = 1'b0;  - Learn Enable
+     */
+#ifdef ATHEROS_HEADER_EN
+    athrs27_reg_write(PORT_CONTROL_REGISTER0, 0x4804);
+#else
+   /* Atheros Header Disable */
+    athrs27_reg_write(PORT_CONTROL_REGISTER0, 0x4004);
+#endif
+
+    /* Tag Priority Mapping */
+    athrs27_reg_write(0x70, 0xfa50);
+
+    /* Enable ARP packets to CPU port */
+    athrs27_reg_write(S27_ARL_TBL_CTRL_REG,(athrs27_reg_read(S27_ARL_TBL_CTRL_REG) | 0x100000));
+
+   /* Enable Broadcast packets to CPU port */
+    athrs27_reg_write(S27_FLD_MASK_REG,(athrs27_reg_read(S27_FLD_MASK_REG) |
+                           S27_ENABLE_CPU_BROADCAST | S27_ENABLE_CPU_BCAST_FWD ));
+
+    return 0;
+}
+
+/******************************************************************************
+*
+* athrs27_phy_is_link_alive - test to see if the specified link is alive
+*
+* RETURNS:
+*    TRUE  --> link is alive
+*    FALSE --> link is down
+*/
+BOOL
+athrs27_phy_is_link_alive(int phyUnit)
+{
+    uint16_t phyHwStatus;
+    uint32_t phyBase;
+    uint32_t phyAddr;
+
+    phyBase = ATHR_PHYBASE(phyUnit);
+    phyAddr = ATHR_PHYADDR(phyUnit);
+    phyHwStatus = s27_rd_phy(phyAddr, ATHR_PHY_SPEC_STATUS);
+
+    if (phyHwStatus & ATHR_STATUS_LINK_PASS)
+        return TRUE;
+
+    return FALSE;
+}
+
+/******************************************************************************
+*
+* athrs27_phy_setup - reset and setup the PHY associated with
+* the specified MAC unit number.
+*
+* Resets the associated PHY port.
+*
+* RETURNS:
+*    TRUE  --> associated PHY is alive
+*    FALSE --> no LINKs on this ethernet unit
+*/
+BOOL
+athrs27_phy_setup(int ethUnit)
+{
+    int       phyUnit;
+    uint16_t  phyHwStatus;
+    uint16_t  timeout;
+    int       liveLinks = 0;
+    uint32_t  phyBase = 0;
+    BOOL      foundPhy = FALSE;
+    uint32_t  phyAddr = 0;
+//#if S27_PHY_DEBUG
+    uint32_t  rd_val = 0;
+//#endif
+    uint32_t  ar7240_revid;
+
+
+    /* See if there's any configuration data for this enet */
+    /* start auto negogiation on each phy */
+    for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+
+        foundPhy = TRUE;
+        phyBase = ATHR_PHYBASE(phyUnit);
+        phyAddr = ATHR_PHYADDR(phyUnit);
+
+        if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+        if (!is_emu()) {
+           s27_wr_phy(phyAddr, ATHR_AUTONEG_ADVERT,ATHR_ADVERTISE_ALL);
+
+           s27_wr_phy(phyAddr, ATHR_PHY_CONTROL,ATHR_CTRL_AUTONEGOTIATION_ENABLE
+                         | ATHR_CTRL_SOFTWARE_RESET);
+        }
+        else  {
+		printf("############ is emulation ############\n");
+
+           if(ATHR_ETHUNIT(phyUnit) == ENET_UNIT_WAN) {
+               s27_wr_phy(phyAddr, ATHR_AUTONEG_ADVERT,ATHR_ADVERTISE_ALL);
+               s27_wr_phy(phyAddr,0x9, 0x0); //donot advertise 1000Mbps mode
+               s27_wr_phy(phyAddr, ATHR_PHY_CONTROL,0x0);
+               s27_wr_phy(phyAddr, ATHR_PHY_CONTROL,ATHR_CTRL_AUTONEGOTIATION_ENABLE
+                         | ATHR_CTRL_SOFTWARE_RESET);
+           }
+           else {
+
+               s27_wr_phy(phyAddr, ATHR_AUTONEG_ADVERT,(ATHR_ADVERTISE_ASYM_PAUSE | ATHR_ADVERTISE_PAUSE |
+                            ATHR_ADVERTISE_10HALF | ATHR_ADVERTISE_10FULL));
+               s27_wr_phy(phyAddr,0x9, 0x0); //donot advertise 1000Mbps mode
+               s27_wr_phy(phyAddr, ATHR_PHY_CONTROL,0x0);
+               s27_wr_phy(phyAddr, ATHR_PHY_CONTROL,ATHR_CTRL_AUTONEGOTIATION_ENABLE
+                         | ATHR_CTRL_SOFTWARE_RESET);
+           }
+       }
+       rd_val = s27_rd_phy(phyAddr,ATHR_PHY_CONTROL);
+       printf("%s ATHR_PHY_CONTROL %d :%x\n",__func__,phyAddr,rd_val);
+       rd_val = s27_rd_phy(phyAddr,ATHR_PHY_SPEC_STATUS);
+       printf("%s ATHR_PHY_SPEC_STAUS %d :%x\n",__func__,phyAddr,rd_val);
+    }
+    if (!foundPhy) {
+        return FALSE; /* No PHY's configured for this ethUnit */
+    }
+
+    /*
+     * After the phy is reset, it takes a little while before
+     * it can respond properly.
+     */
+    if (ethUnit == ENET_UNIT_LAN)
+        sysMsDelay(1000);
+    else
+        sysMsDelay(3000);
+
+    /*
+     * Wait up to 3 seconds for ALL associated PHYs to finish
+     * autonegotiation.  The only way we get out of here sooner is
+     * if ALL PHYs are connected AND finish autonegotiation.
+     */
+    for (phyUnit=0; (phyUnit < ATHR_PHY_MAX) /*&& (timeout > 0) */; phyUnit++) {
+        if (ATHR_ETHUNIT(phyUnit) == ENET_UNIT_WAN)
+            continue;
+
+        timeout=20;
+        for (;;) {
+            phyHwStatus =  s27_rd_phy(phyAddr, ATHR_PHY_CONTROL);
+
+            if (ATHR_RESET_DONE(phyHwStatus)) {
+                DRV_PRINT(DRV_DEBUG_PHYSETUP,
+                          ("Port %d, Neg Success\n", phyUnit));
+                break;
+            }
+            if (timeout == 0) {
+                DRV_PRINT(DRV_DEBUG_PHYSETUP,
+                          ("Port %d, Negogiation timeout\n", phyUnit));
+                break;
+            }
+            if (--timeout == 0) {
+                DRV_PRINT(DRV_DEBUG_PHYSETUP,
+                          ("Port %d, Negogiation timeout\n", phyUnit));
+                break;
+            }
+
+            sysMsDelay(150);
+        }
+        /* extend the cable length */
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_ADDRESS, 0x14);
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_DATA, 0xf52);
+
+       /* Force Class A setting phys */
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_ADDRESS, 4);
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_DATA, 0xebbb);
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_ADDRESS, 5);
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_DATA, 0x2c47);
+
+        /* fine-tune PHYs */
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_ADDRESS, 0x3c);
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_DATA, 0x1c1);
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_ADDRESS, 0x37);
+        s27_wr_phy(phyUnit, ATHR_DEBUG_PORT_DATA, 0xd600);
+
+
+#ifdef S27_VER_1_0
+        /* turn off power saving */
+        s27_wr_phy(phyUnit, 29, 41);
+        s27_wr_phy(phyUnit, 30, 0);
+        printf("def_ S27_VER_1_0\n");
+#endif
+    }
+
+    /*
+     * All PHYs have had adequate time to autonegotiate.
+     * Now initialize software status.
+     *
+     * It's possible that some ports may take a bit longer
+     * to autonegotiate; but we can't wait forever.  They'll
+     * get noticed by mv_phyCheckStatusChange during regular
+     * polling activities.
+     */
+    for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+        if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        if (athrs27_phy_is_link_alive(phyUnit)) {
+            liveLinks++;
+            ATHR_IS_PHY_ALIVE(phyUnit) = TRUE;
+        } else {
+            ATHR_IS_PHY_ALIVE(phyUnit) = FALSE;
+        }
+        DRV_PRINT(DRV_DEBUG_PHYSETUP,
+            ("eth%d: Phy Specific Status=%4.4x\n",
+            ethUnit,
+            s27_rd_phy(ATHR_PHYADDR(phyUnit),ATHR_PHY_SPEC_STATUS)));
+    }
+
+    return (liveLinks > 0);
+}
+
+/******************************************************************************
+*
+* athrs27_phy_is_fdx - Determines whether the phy ports associated with the
+* specified device are FULL or HALF duplex.
+*
+* RETURNS:
+*    1 --> FULL
+*    0 --> HALF
+*/
+int
+athrs27_phy_is_fdx(int ethUnit,int phyUnit)
+{
+    uint32_t  phyBase;
+    uint32_t  phyAddr;
+    uint16_t  phyHwStatus;
+    int       ii = 200;
+
+    if (ethUnit == ENET_UNIT_LAN)
+        return TRUE;
+
+    for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+        if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        if (athrs27_phy_is_link_alive(phyUnit)) {
+
+            phyBase = ATHR_PHYBASE(phyUnit);
+            phyAddr = ATHR_PHYADDR(phyUnit);
+
+            do {
+                phyHwStatus = s27_rd_phy (phyAddr, ATHR_PHY_SPEC_STATUS);
+                        if(phyHwStatus & ATHR_STATUS_RESOVLED)
+                                break;
+                sysMsDelay(10);
+            } while(--ii);
+            if (phyHwStatus & ATHER_STATUS_FULL_DUPLEX) {
+                return TRUE;
+            }
+        }
+    }
+
+    return FALSE;
+}
+/******************************************************************************
+*
+* athrs27_phy_speed - Determines the speed of phy ports associated with the
+* specified device.
+*
+* RETURNS:
+*               ATHR_PHY_SPEED_10T, AG7240_PHY_SPEED_100T;
+*               ATHR_PHY_SPEED_1000T;
+*/
+
+int
+athrs27_phy_speed(int ethUnit,int phyUnit)
+{
+    uint16_t  phyHwStatus;
+    uint32_t  phyBase;
+    uint32_t  phyAddr;
+    int       ii = 200;
+    int       phySpeed = _UNKNOWN_SPEED;
+    for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+        if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+
+        phyBase = ATHR_PHYBASE(phyUnit);
+        phyAddr = ATHR_PHYADDR(phyUnit);
+        phySpeed = _10BASET;
+
+        if (athrs27_phy_is_link_alive(phyUnit)) {
+
+            do {
+                phyHwStatus = s27_rd_phy(phyAddr,
+                                              ATHR_PHY_SPEC_STATUS);
+                        if(phyHwStatus & ATHR_STATUS_RESOVLED)
+                                break;
+                sysMsDelay(10);
+            }while(--ii);
+
+            phyHwStatus = ((phyHwStatus & ATHER_STATUS_LINK_MASK) >>
+                           ATHER_STATUS_LINK_SHIFT);
+
+            switch(phyHwStatus) {
+            case 0:
+                phySpeed = _10BASET;
+		break;
+            case 1:
+                phySpeed = _100BASET;
+		break;
+            case 2:
+                phySpeed = _1000BASET;
+		break;
+            default:
+                printf("Unkown speed read!\n");
+            }
+        }
+
+        phy_reg_write(1,phyAddr, ATHR_DEBUG_PORT_ADDRESS, 0x18);
+
+        if(phySpeed == _100BASET) {
+            phy_reg_write(1,phyAddr, ATHR_DEBUG_PORT_DATA, 0xba8);
+        } else {
+            phy_reg_write(1,phyAddr, ATHR_DEBUG_PORT_DATA, 0x2ea);
+        }
+    }
+
+    if (ethUnit == ENET_UNIT_LAN)
+         phySpeed = _1000BASET;
+
+    return phySpeed;
+}
+
+/*****************************************************************************
+*
+* athr_phy_is_up -- checks for significant changes in PHY state.
+*
+* A "significant change" is:
+*     dropped link (e.g. ethernet cable unplugged) OR
+*     autonegotiation completed + link (e.g. ethernet cable plugged in)
+*
+* When a PHY is plugged in, phyLinkGained is called.
+* When a PHY is unplugged, phyLinkLost is called.
+*/
+
+int
+athrs27_phy_is_up(int ethUnit)
+{
+
+    uint16_t      phyHwStatus, phyHwControl;
+    athrPhyInfo_t *lastStatus;
+    int           linkCount   = 0;
+    int           lostLinks   = 0;
+    int           gainedLinks = 0;
+    uint32_t      phyBase;
+    uint32_t      phyAddr;
+    int           phyUnit;
+
+    for (phyUnit=0; phyUnit < ATHR_PHY_MAX; phyUnit++) {
+        if (!ATHR_IS_ETHUNIT(phyUnit, ethUnit)) {
+            continue;
+        }
+
+        phyBase = ATHR_PHYBASE(phyUnit);
+        phyAddr = ATHR_PHYADDR(phyUnit);
+
+        lastStatus = &athrPhyInfo[phyUnit];
+        if (lastStatus->isPhyAlive) { /* last known link status was ALIVE */
+            phyHwStatus = s27_rd_phy(phyAddr, ATHR_PHY_SPEC_STATUS);
+
+            /* See if we've lost link */
+            if (phyHwStatus & ATHR_STATUS_LINK_PASS) {
+                linkCount++;
+            } else {
+                lostLinks++;
+                DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d down\n",
+                                               ethUnit, phyUnit));
+                printf("enet%d port%d down\n",ethUnit, phyUnit);
+                lastStatus->isPhyAlive = FALSE;
+            }
+        } else { /* last known link status was DEAD */
+            /* Check for reset complete */
+            if(is_emu())
+            {
+                phyHwStatus = s27_rd_phy(phyAddr, ATHR_PHY_STATUS);
+                if(phyAddr%2) {
+                    s27_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x820);
+                }
+                else {
+                    s27_wr_phy(phyAddr,ATHR_PHY_FUNC_CONTROL,0x800);
+                }
+
+                if((phyHwStatus & 0x4)==0)
+                {
+                   s27_wr_phy(phyAddr,0x9,0x0);
+                   if(phyAddr !=0x4)
+                       s27_wr_phy(phyAddr,0x4,0x41);
+                   s27_wr_phy(phyAddr,0x0,0x9000);
+                }
+            }
+
+            phyHwStatus = s27_rd_phy(phyAddr, ATHR_PHY_CONTROL);
+            if (!ATHR_RESET_DONE(phyHwStatus))
+                continue;
+
+             phyHwControl = s27_rd_phy(phyAddr, ATHR_PHY_CONTROL);
+             phyHwStatus = s27_rd_phy(phyAddr, ATHR_PHY_STATUS);
+
+            /* Check for AutoNegotiation complete */
+            if ((!(phyHwControl & ATHR_CTRL_AUTONEGOTIATION_ENABLE))
+                 || ATHR_AUTONEG_DONE(phyHwStatus)) {
+                phyHwStatus = s27_rd_phy(phyAddr,
+                                           ATHR_PHY_SPEC_STATUS);
+
+                if (phyHwStatus & ATHR_STATUS_LINK_PASS) {
+                gainedLinks++;
+                linkCount++;
+                printf("enet%d port%d up\n",ethUnit, phyUnit);
+                DRV_PRINT(DRV_DEBUG_PHYCHANGE,("\nenet%d port%d up\n",
+                                               ethUnit, phyUnit));
+                lastStatus->isPhyAlive = TRUE;
+                }
+            }
+        }
+    }
+    return (linkCount);
+}
+
+unsigned int athrs27_reg_read(unsigned int s27_addr)
+{
+    unsigned int addr_temp;
+    unsigned int s27_rd_csr_low, s27_rd_csr_high, s27_rd_csr;
+    unsigned int data,unit = 0;
+    unsigned int phy_address, reg_address;
+
+    addr_temp = s27_addr >>2;
+    data = addr_temp >> 7;
+
+    phy_address = 0x1f;
+    reg_address = 0x10;
+
+    if (is_ar7240()) {
+        unit = 0;
+    }
+    else if(is_ar7241() || is_ar7242() || is_wasp() || is_qca953x() || is_qca956x()) {
+        unit = 1;
+    }
+
+    phy_reg_write(unit,phy_address, reg_address, data);
+
+    phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
+    reg_address = ((addr_temp << 1) & 0x1e);
+    s27_rd_csr_low = (uint32_t) phy_reg_read(unit,phy_address, reg_address);
+
+    reg_address = reg_address | 0x1;
+    s27_rd_csr_high = (uint32_t) phy_reg_read(unit,phy_address, reg_address);
+    s27_rd_csr = (s27_rd_csr_high << 16) | s27_rd_csr_low ;
+
+    return(s27_rd_csr);
+}
+
+void athrs27_reg_write(unsigned int s27_addr, unsigned int s27_write_data)
+{
+    unsigned int addr_temp;
+    unsigned int data;
+    unsigned int phy_address, reg_address,unit = 0;
+
+    addr_temp = (s27_addr ) >>2;
+    data = addr_temp >> 7;
+
+    phy_address = 0x1f;
+    reg_address = 0x10;
+
+    if (is_ar7240()) {
+        unit = 0;
+    }
+    else if(is_ar7241() || is_ar7242() || is_wasp() || is_qca953x() || is_qca956x()) {
+        unit = 1;
+    }
+    phy_reg_write(unit,phy_address, reg_address, data);
+
+    phy_address = (0x17 & ((addr_temp >> 4) | 0x10));
+
+    reg_address = (((addr_temp << 1) & 0x1e) | 0x1);
+    data = (s27_write_data >> 16) & 0xffff;
+    phy_reg_write(unit,phy_address, reg_address, data);
+
+    reg_address = ((addr_temp << 1) & 0x1e);
+    data = s27_write_data  & 0xffff;
+    phy_reg_write(unit,phy_address, reg_address, data);
+
+}
+
+void athrs27_reg_rmw(unsigned int s27_addr, unsigned int s27_write_data)
+{
+    int val = athrs27_reg_read(s27_addr);
+    athrs27_reg_write(s27_addr,(val | s27_write_data));
+}
+
+unsigned int s27_rd_phy(unsigned int phy_addr, unsigned int reg_addr)
+{
+  int unit, val = 0;
+
+  if (is_ar7240()) {
+    unit = 0;
+  } else if(is_ar7241() || is_ar7242() || is_wasp() || is_qca953x() || is_qca956x()) {
+    unit = 1;
+  }
+  val = (uint32_t) phy_reg_read(unit, phy_addr, reg_addr);
+  return val;
+}
+
+void s27_wr_phy(unsigned int phy_addr, unsigned int reg_addr, unsigned int write_data)
+{
+  int unit;
+
+  if (is_ar7240()) {
+    unit = 0;
+  } else if(is_ar7241() || is_ar7242() || is_wasp() || is_qca953x() || is_qca956x()) {
+    unit = 1;
+  }
+
+  phy_reg_write(unit, phy_addr, reg_addr, write_data);
+}
+int athrs27_mdc_check()
+{
+    int i;
+
+    for (i=0; i<4000; i++) {
+        if(athrs27_reg_read(0x10c) != 0x18007fff)
+            return -1;
+    }
+    return 0;
+}
+
diff --git a/board/qca/mips32/common/athr_s27_phy.h b/board/qca/mips32/common/athr_s27_phy.h
new file mode 100644
index 0000000..597a4d2
--- /dev/null
+++ b/board/qca/mips32/common/athr_s27_phy.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2016 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _ATHRS27_PHY_H
+#define _ATHRS27_PHY_H
+
+
+/*****************/
+/* PHY Registers */
+/*****************/
+#define ATHR_PHY_CONTROL                 0
+#define ATHR_PHY_STATUS                  1
+#define ATHR_PHY_ID1                     2
+#define ATHR_PHY_ID2                     3
+#define ATHR_AUTONEG_ADVERT              4
+#define ATHR_LINK_PARTNER_ABILITY        5
+#define ATHR_AUTONEG_EXPANSION           6
+#define ATHR_NEXT_PAGE_TRANSMIT          7
+#define ATHR_LINK_PARTNER_NEXT_PAGE      8
+#define ATHR_1000BASET_CONTROL           9
+#define ATHR_1000BASET_STATUS            10
+#define ATHR_PHY_FUNC_CONTROL            16
+#define ATHR_PHY_SPEC_STATUS             17
+#define ATHR_DEBUG_PORT_ADDRESS          29
+#define ATHR_DEBUG_PORT_DATA             30
+#define ATHR_PHY_INTR_ENABLE             0x12
+#define ATHR_PHY_INTR_STATUS             0x13
+
+/* ATHR_PHY_CONTROL fields */
+#define ATHR_CTRL_SOFTWARE_RESET                    0x8000
+#define ATHR_CTRL_SPEED_LSB                         0x2000
+#define ATHR_CTRL_AUTONEGOTIATION_ENABLE            0x1000
+#define ATHR_CTRL_RESTART_AUTONEGOTIATION           0x0200
+#define ATHR_CTRL_SPEED_FULL_DUPLEX                 0x0100
+#define ATHR_CTRL_SPEED_MSB                         0x0040
+
+#define ATHR_RESET_DONE(phy_control)                   \
+    (((phy_control) & (ATHR_CTRL_SOFTWARE_RESET)) == 0)
+
+/* Phy status fields */
+#define ATHR_STATUS_AUTO_NEG_DONE                   0x0020
+
+#define ATHR_AUTONEG_DONE(ip_phy_status)                   \
+    (((ip_phy_status) &                                  \
+        (ATHR_STATUS_AUTO_NEG_DONE)) ==                    \
+        (ATHR_STATUS_AUTO_NEG_DONE))
+
+/* Link Partner ability */
+#define ATHR_LINK_100BASETX_FULL_DUPLEX       0x0100
+#define ATHR_LINK_100BASETX                   0x0080
+#define ATHR_LINK_10BASETX_FULL_DUPLEX        0x0040
+#define ATHR_LINK_10BASETX                    0x0020
+
+/* Advertisement register. */
+#define ATHR_ADVERTISE_NEXT_PAGE              0x8000
+#define ATHR_ADVERTISE_ASYM_PAUSE             0x0800
+#define ATHR_ADVERTISE_PAUSE                  0x0400
+#define ATHR_ADVERTISE_100FULL                0x0100
+#define ATHR_ADVERTISE_100HALF                0x0080
+#define ATHR_ADVERTISE_10FULL                 0x0040
+#define ATHR_ADVERTISE_10HALF                 0x0020
+
+#define ATHR_ADVERTISE_ALL (ATHR_ADVERTISE_ASYM_PAUSE | ATHR_ADVERTISE_PAUSE | \
+                            ATHR_ADVERTISE_10HALF | ATHR_ADVERTISE_10FULL | \
+                            ATHR_ADVERTISE_100HALF | ATHR_ADVERTISE_100FULL)
+
+/* 1000BASET_CONTROL */
+#define ATHR_ADVERTISE_1000FULL               0x0200
+#define ATHR_ADVERTISE_1000HALF		      0x0100
+
+/* Phy Specific status fields */
+#define ATHER_STATUS_LINK_MASK                0xC000
+#define ATHER_STATUS_LINK_SHIFT               14
+#define ATHER_STATUS_FULL_DUPLEX              0x2000
+#define ATHR_STATUS_LINK_PASS                 0x0400
+#define ATHR_LATCH_LINK_PASS                  0x0004
+#define ATHR_STATUS_RESOVLED                  0x0800
+
+/*phy debug port  register */
+#define ATHER_DEBUG_SERDES_REG                5
+
+/* Serdes debug fields */
+#define ATHER_SERDES_BEACON                   0x0100
+
+#define OPERATIONAL_MODE_REG0                0x4
+
+/* S27 CSR Registers */
+
+#define PORT_STATUS_REGISTER0                0x0100
+#define PORT_STATUS_REGISTER1                0x0200
+#define PORT_STATUS_REGISTER2                0x0300
+#define PORT_STATUS_REGISTER3                0x0400
+#define PORT_STATUS_REGISTER4                0x0500
+#define PORT_STATUS_REGISTER5                0x0600
+
+#define RATE_LIMIT_REGISTER0                 0x010C
+#define RATE_LIMIT_REGISTER1                 0x020C
+#define RATE_LIMIT_REGISTER2                 0x030C
+#define RATE_LIMIT_REGISTER3                 0x040C
+#define RATE_LIMIT_REGISTER4                 0x050C
+#define RATE_LIMIT_REGISTER5                 0x060C
+
+#define PORT_CONTROL_REGISTER0               0x0104
+#define PORT_CONTROL_REGISTER1               0x0204
+#define PORT_CONTROL_REGISTER2               0x0304
+#define PORT_CONTROL_REGISTER3               0x0404
+#define PORT_CONTROL_REGISTER4               0x0504
+#define PORT_CONTROL_REGISTER5               0x0604
+
+#define CPU_PORT_REGISTER                    0x0078
+#define MDIO_CTRL_REGISTER                   0x0098
+
+#define S27_ARL_TBL_FUNC_REG0                0x0050
+#define S27_ARL_TBL_FUNC_REG1                0x0054
+#define S27_ARL_TBL_FUNC_REG2                0x0058
+#define S27_FLD_MASK_REG                     0x002c
+#define S27_ARL_TBL_CTRL_REG                 0x005c
+#define S27_GLOBAL_INTR_REG                  0x10
+#define S27_GLOBAL_INTR_MASK_REG             0x14
+
+
+#define S27_ENABLE_CPU_BROADCAST             (1 << 26)
+#define S27_ENABLE_CPU_BCAST_FWD             (1 << 25)
+
+#define PHY_LINK_CHANGE_REG 		     0x4
+#define PHY_LINK_UP 		             0x400
+#define PHY_LINK_DOWN 		             0x800
+#define PHY_LINK_DUPLEX_CHANGE 		     0x2000
+#define PHY_LINK_SPEED_CHANGE		     0x4000
+#define PHY_LINK_INTRS			     (PHY_LINK_UP | PHY_LINK_DOWN | PHY_LINK_DUPLEX_CHANGE | PHY_LINK_SPEED_CHANGE)
+
+/* SWITCH QOS REGISTERS */
+
+#define ATHR_QOS_PORT_0			0x110 /* CPU PORT */
+#define ATHR_QOS_PORT_1			0x210
+#define ATHR_QOS_PORT_2			0x310
+#define ATHR_QOS_PORT_3			0x410
+#define ATHR_QOS_PORT_4			0x510
+
+#define ATHR_ENABLE_TOS                 (1 << 16)
+
+#define ATHR_QOS_MODE_REGISTER          0x030
+#define ATHR_QOS_FIXED_PRIORITY        ((0 << 31) | (0 << 28))
+#define ATHR_QOS_WEIGHTED              ((1 << 31) | (0 << 28)) /* Fixed weight 8,4,2,1 */
+#define ATHR_QOS_MIXED                 ((1 << 31) | (1 << 28)) /* Q3 for managment; Q2,Q1,Q0 - 4,2,1 */
+
+#ifndef BOOL
+#define BOOL    int
+#endif
+
+#define sysMsDelay(_x) udelay((_x) * 1000)
+#define mdelay(_x)      sysMsDelay(_x)
+
+#undef S27_VER_1_0
+
+/*
+ *  Atheros header defines
+ */
+#ifndef _ATH_HEADER_CONF
+#define _ATH_HEADER_CONF
+
+typedef enum {
+    NORMAL_PACKET,
+    RESERVED0,
+    MIB_1ST,
+    RESERVED1,
+    RESERVED2,
+    READ_WRITE_REG,
+    READ_WRITE_REG_ACK,
+    RESERVED3
+} AT_HEADER_TYPE;
+
+typedef struct {
+    uint16_t    reserved0  :2;
+    uint16_t    priority   :2;
+    uint16_t    type       :4;
+    uint16_t    broadcast  :1;
+    uint16_t    from_cpu   :1;
+    uint16_t    reserved1  :2;
+    uint16_t    port_num   :4;
+}at_header_t;
+
+#define ATHR_HEADER_LEN 2
+
+#endif // _ATH_HEADER_CONF
+
+typedef enum {
+    PORT_EG_UNMODIFIED = 0,  /**<  egress transmit packets unmodified */
+    PORT_EG_UNTAGGED,        /**<  egress transmit packets without vlan tag */
+    PORT_EG_TAGGED,          /**<  egress transmit packets with vlan tag */
+} port_1q_egmode_t;
+
+extern void set_packet_inspection_flag(int flag);
+
+#endif
diff --git a/board/qca/mips32/common/956x.S b/board/qca/mips32/qca956x/956x.S
similarity index 100%
rename from board/qca/mips32/common/956x.S
rename to board/qca/mips32/qca956x/956x.S
diff --git a/board/qca/mips32/qca956x/Makefile b/board/qca/mips32/qca956x/Makefile
index 2f71f7d..67909ff 100644
--- a/board/qca/mips32/qca956x/Makefile
+++ b/board/qca/mips32/qca956x/Makefile
@@ -1,7 +1,42 @@
-obj-y	:= 	board956x.o extra.o ../common/init-956x.o		\
-		../common/956x.o ../common/tap-956x.o			\
-		../common/ath_serial.o ../common/qca-mach-common.o	\
-		flash.o ../common/ath_flash.o				\
-		../common/athrs17_phy.o					\
-		../common/qca-eth-956x.o				\
-		../common/ath_pci.o
+BOARD=board956x
+COMPRESSED_UBOOT=0
+
+ifdef CONFIG_AP151
+ETH_CONFIG=_s27
+else
+ETH_CONFIG=_s17
+endif
+
+OBJS=	\
+	$(BOARD).o		\
+	flash.o			\
+	extra.o			\
+	init-956x.o	\
+	qca-eth-956x.o	\
+	../common/qca-mach-common.o	\
+	../common/ath_serial.o	\
+	../common/ath_pci.o
+
+ifndef BOOT_FROM_NAND
+OBJS	+= ../common/ath_flash.o
+endif
+
+ifeq ($(ATH_RGMII_CAL),1)
+OBJS	+= ../common/rgmii-cal-956x.o
+OBJS	+= ../common/athrs17_lpbk.o
+endif
+
+ifeq ($(ETH_CONFIG), _s17)
+OBJS	+= ../common/athrs17_phy.o
+endif
+
+ifeq ($(ETH_CONFIG), _s27)
+OBJS	+= ../common/athr_s27_phy.o
+endif
+
+OBJS	+= 956x.o tap-956x.o
+
+$(OBJS): .depend
+
+.depend:
+obj-y	+= $(OBJS)
diff --git a/board/qca/mips32/qca956x/board956x.c b/board/qca/mips32/qca956x/board956x.c
index 8f77729..6096529 100644
--- a/board/qca/mips32/qca956x/board956x.c
+++ b/board/qca/mips32/qca956x/board956x.c
@@ -37,7 +37,7 @@
 #	define prmsg	printf
 #	define args		void
 #	define board_str(a)				\
-	printf(a " - Dragonfly 1.%d", ath_reg_rd		\
+	printf(a " - Dragonfly 1.%d\n", ath_reg_rd		\
 			(RST_REVISION_ID_ADDRESS) & 0xf)
 #endif
 
diff --git a/board/qca/mips32/qca956x/extra.c b/board/qca/mips32/qca956x/extra.c
index e295ebb..4ee9a10 100644
--- a/board/qca/mips32/qca956x/extra.c
+++ b/board/qca/mips32/qca956x/extra.c
@@ -124,3 +124,10 @@
 	printf("Setting " str(XTAL_ADDRESS) " to 0x%x\n", val);
 	return 0;
 }
+#ifdef CONFIG_LAST_STAGE_INIT
+int last_stage_init(void)
+{
+	ath_set_tuning_caps();
+	return 0;
+}
+#endif
diff --git a/board/qca/mips32/common/init-956x.c b/board/qca/mips32/qca956x/init-956x.c
similarity index 98%
rename from board/qca/mips32/common/init-956x.c
rename to board/qca/mips32/qca956x/init-956x.c
index e61e764..14b86a5 100644
--- a/board/qca/mips32/common/init-956x.c
+++ b/board/qca/mips32/qca956x/init-956x.c
@@ -251,11 +251,7 @@
 	uint32_t	bootstrap;
 
 	prmsg("\nsri\n");
-#ifdef CONFIG_MACH_955x
-	prmsg("Scorpion 1.%d\n", ath_reg_rd(RST_REVISION_ID_ADDRESS) & 0xf);
-#elif defined (CONFIG_MACH_956x)
-	prmsg("Dragonfly 1.%d\n", ath_reg_rd(RST_REVISION_ID_ADDRESS) & 0xf);
-#endif
+
 	bootstrap = ath_reg_rd(RST_BOOTSTRAP_ADDRESS);
 
 	switch(type = ath_ram_type(bootstrap)) {
diff --git a/board/qca/mips32/common/qca-eth-956x.c b/board/qca/mips32/qca956x/qca-eth-956x.c
similarity index 99%
rename from board/qca/mips32/common/qca-eth-956x.c
rename to board/qca/mips32/qca956x/qca-eth-956x.c
index c4fbf1d..f955d31 100644
--- a/board/qca/mips32/common/qca-eth-956x.c
+++ b/board/qca/mips32/qca956x/qca-eth-956x.c
@@ -438,7 +438,7 @@
 
 	if(!mac->link) {
 		printf("%s link down\n",mac->dev->name);
-		return 0;
+		return 1;
 	}
 
 	switch (speed)
@@ -489,7 +489,7 @@
 
 	ath_gmac_set_mac_duplex(mac,duplex);
 
-	return 1;
+	return 0;
 }
 
 /*
@@ -502,8 +502,9 @@
 	ath_gmac_desc_t *fr;
 	ath_gmac_mac_t *mac = (ath_gmac_mac_t*)dev->priv;
 
-	if (!ath_gmac_check_link(mac))
-		return 0;
+	if (ath_gmac_check_link(mac)) {
+		return -1;
+	}
 
 	mac->next_rx = 0;
 
@@ -520,7 +521,7 @@
 	ath_gmac_reg_wr(mac, ATH_DMA_RX_CTRL, ATH_RXE);	/* rx start */
 	udelay(1000 * 1000);
 
-	return 1;
+	return 0;
 
 }
 
diff --git a/board/qca/mips32/common/qca-eth-956x.h b/board/qca/mips32/qca956x/qca-eth-956x.h
similarity index 100%
rename from board/qca/mips32/common/qca-eth-956x.h
rename to board/qca/mips32/qca956x/qca-eth-956x.h
diff --git a/board/qca/mips32/common/qca-eth-956x_phy.h b/board/qca/mips32/qca956x/qca-eth-956x_phy.h
similarity index 100%
rename from board/qca/mips32/common/qca-eth-956x_phy.h
rename to board/qca/mips32/qca956x/qca-eth-956x_phy.h
diff --git a/board/qca/mips32/common/tap-956x.S b/board/qca/mips32/qca956x/tap-956x.S
similarity index 100%
rename from board/qca/mips32/common/tap-956x.S
rename to board/qca/mips32/qca956x/tap-956x.S
diff --git a/common/board_r.c b/common/board_r.c
index b3f0af1..75ee43e 100644
--- a/common/board_r.c
+++ b/common/board_r.c
@@ -64,11 +64,6 @@
 #ifdef CONFIG_AVR32
 #include <asm/arch/mmu.h>
 #endif
-#if defined(CONFIG_MIPS) && defined(CONFIG_MACH_QCA956x)
-int ath_set_tuning_caps(void);
-#else
-#define ath_set_tuning_caps()   /* nothing */
-#endif
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -955,9 +950,6 @@
 #if defined(CONFIG_SPARC)
 	prom_init,
 #endif
-#if defined(CONFIG_MIPS) && defined(CONFIG_MACH_QCA956x)
-	ath_set_tuning_caps,
-#endif
 	run_main_loop,
 };
 
diff --git a/configs/qca956x_defconfig b/configs/qca956x_defconfig
index 8be45c8..d5cf9ac 100644
--- a/configs/qca956x_defconfig
+++ b/configs/qca956x_defconfig
@@ -1,14 +1,15 @@
 CONFIG_MIPS=y
 CONFIG_TARGET_QCA956X=y
 CONFIG_SYS_EXTRA_OPTIONS="QCA956X"
-CONFIG_SYS_PROMPT="QCA9563# "
+CONFIG_SYS_PROMPT="QCA956X# "
 # CONFIG_CMD_BDI is not set
 # CONFIG_CMD_ELF is not set
-# CONFIG_CMD_RUN is not set
-# CONFIG_CMD_SAVEENV is not set
+CONFIG_CMD_RUN=y
+CONFIG_CMD_SAVEENV=y
+CONFIG_CMD_PING=y
 # CONFIG_CMD_LOADB is not set
 # CONFIG_CMD_LOADS is not set
-# CONFIG_CMD_FLASH is not set
+CONFIG_CMD_FLASH=y
 # CONFIG_CMD_FPGA is not set
 # CONFIG_CMD_SETEXPR is not set
 CONFIG_USE_PRIVATE_LIBGCC=y
diff --git a/include/956x.h b/include/956x.h
index a17e165..81ec23b 100644
--- a/include/956x.h
+++ b/include/956x.h
@@ -3362,7 +3362,6 @@
 #define CFG_MAXARGS     16      /* max number of command args*/
 
 /*#define CFG_MALLOC_LEN      (128*1024) CONFIG_SYS_MALLOC_LEN */ /* Moved to QCA956x board config */
-#define CONFIG_SYS_BOOTPARAMS_LEN  (128*1024)
 #define CONFIG_SYS_SDRAM_BASE	0x80000000    /* Cached addr */
 /* #define CONFIG_SYS_LOAD_ADDR	0x81000000 */ /* default load address  */ /* Moved to QCA956x board config */
 
diff --git a/include/configs/qca956x.h b/include/configs/qca956x.h
index ba56b26..1f14919 100644
--- a/include/configs/qca956x.h
+++ b/include/configs/qca956x.h
@@ -21,6 +21,9 @@
 #define CONFIG_COMMANDS 1
 
 #define CFG_DDR2_DRAGONFLY_CAS_LATENCY 5
+
+
+#if CONFIG_AP152
 #define CFG_ATH_GMAC_NMACS      1
 #define CFG_ATH_GE1_IS_CONNECTED 1
 #define CONFIG_ATHRS_GMAC_SGMII  1
@@ -28,6 +31,24 @@
 #define CONFIG_ATHRS_GMAC_SGMII 1
 #define CONFIG_ATHRS17_PHY      1
 #define ATH_SGMII_FORCED_MODE    1
+#define UART_RX18_TX22  1
+#define __CONFIG_BOARD_NAME ap152
+#define CONFIG_BOARD_NAME "ap152"
+#endif
+
+#if CONFIG_AP151
+#define CFG_ATH_GMAC_NMACS	2
+#define CFG_ATH_GE1_IS_CONNECTED 1
+#define CFG_ATHRS27_PHY	1
+#define UART_RX18_TX20	1
+#define __CONFIG_BOARD_NAME ap151
+#define CONFIG_BOARD_NAME "ap151"
+#endif
+
+#define CONFIG_DISPLAY_BOARDINFO 1
+#define CONFIG_CUSTOM_BOARDINFO 1
+
+#define BOARDCAL 0x9fff0000
 #define CONFIG_SYS_RX_ETH_BUFFER 8
 #define CONFIG_TFTP_BLOCKSIZE 512
 
@@ -45,14 +66,14 @@
 #define CFG_INIT_SRAM_SP_OFFSET 0xbd001800
 
 #define CONFIG_SYS_MAXARGS 16
-#define CONFIG_SYS_FLASH_BASE           0x9f000000
+#define CONFIG_SYS_FLASH_BASE 0x9f000000
 #define CONFIG_SYS_MAX_FLASH_BANKS      1
 #define CONFIG_SYS_MAX_FLASH_SECT       256
 
 #define CONFIG_BAUDRATE 115200
 #define CONFIG_SYS_BAUDRATE_TABLE  {115200}
-
-#define UART_RX18_TX22  1
+#define CONFIG_LAST_STAGE_INIT
+#define CONFIG_SYS_TEXT_BASE 0x9f000000
 
 /* Console I/O Buffer Size */
 #define CONFIG_SYS_CBSIZE               512
@@ -73,7 +94,7 @@
 #define CONFIG_SYS_MONITOR_BASE 0x9f000000
 #define CONFIG_SYS_MONITOR_LEN  (192 << 10)
 #define CONFIG_SYS_MALLOC_LEN (128*1024)
-
+#define CONFIG_SYS_BOOTPARAMS_LEN (64*1024)
 
 #ifndef FLASH_SIZE
 #define FLASH_SIZE 16
@@ -160,9 +181,6 @@
 #define CFG_DDR_REFRESH_VAL	0x4186
 #define CFG_DDR2_REFRESH_VAL	0x40c3
 
-#define __CONFIG_BOARD_NAME ap152
-#define CONFIG_BOARD_NAME "ap152"
-
 #define CONFIG_PCI_CONFIG_DATA_IN_OTP
 
 #if defined(CONFIG_CUS249) || defined(CONFIG_TB753)