/* ALE Registers */
 #define ALE_IDVER              0x00
+#define ALE_STATUS             0x04
 #define ALE_CONTROL            0x08
 #define ALE_PRESCALE           0x10
 #define ALE_UNKNOWNVLAN                0x18
 #define ALE_UCAST_OUI                  2
 #define ALE_UCAST_TOUCHED              3
 
+#define ALE_TABLE_SIZE_MULTIPLIER      1024
+#define ALE_STATUS_SIZE_MASK           0x1f
+#define ALE_TABLE_SIZE_DEFAULT         64
+
 static inline int cpsw_ale_get_field(u32 *ale_entry, u32 start, u32 bits)
 {
        int idx;
 
 void cpsw_ale_start(struct cpsw_ale *ale)
 {
-       u32 rev;
+       u32 rev, ale_entries;
 
        rev = __raw_readl(ale->params.ale_regs + ALE_IDVER);
        if (!ale->params.major_ver_mask)
                 ALE_VERSION_MAJOR(rev, ale->params.major_ver_mask),
                 ALE_VERSION_MINOR(rev));
 
+       if (!ale->params.ale_entries) {
+               ale_entries =
+                       __raw_readl(ale->params.ale_regs + ALE_STATUS) &
+                                   ALE_STATUS_SIZE_MASK;
+               /* ALE available on newer NetCP switches has introduced
+                * a register, ALE_STATUS, to indicate the size of ALE
+                * table which shows the size as a multiple of 1024 entries.
+                * For these, params.ale_entries will be set to zero. So
+                * read the register and update the value of ale_entries.
+                * ALE table on NetCP lite, is much smaller and is indicated
+                * by a value of zero in ALE_STATUS. So use a default value
+                * of ALE_TABLE_SIZE_DEFAULT for this. Caller is expected
+                * to set the value of ale_entries for all other versions
+                * of ALE.
+                */
+               if (!ale_entries)
+                       ale_entries = ALE_TABLE_SIZE_DEFAULT;
+               else
+                       ale_entries *= ALE_TABLE_SIZE_MULTIPLIER;
+               ale->params.ale_entries = ale_entries;
+       }
+       dev_info(ale->params.dev,
+                "ALE Table size %ld\n", ale->params.ale_entries);
+
        if (ale->params.nu_switch_ale) {
                /* Separate registers for unknown vlan configuration.
                 * Also there are N bits, where N is number of ale
 
 #define GBENU_CPTS_OFFSET              0x1d000
 #define GBENU_ALE_OFFSET               0x1e000
 #define GBENU_HOST_PORT_NUM            0
-#define GBENU_NUM_ALE_ENTRIES          1024
 #define GBENU_SGMII_MODULE_SIZE                0x100
 
 /* 10G Ethernet SS defines */
 #define XGBE10_ALE_OFFSET              0x700
 #define XGBE10_HW_STATS_OFFSET         0x800
 #define XGBE10_HOST_PORT_NUM           0
-#define XGBE10_NUM_ALE_ENTRIES         1024
+#define XGBE10_NUM_ALE_ENTRIES         2048
 
 #define        GBE_TIMER_INTERVAL                      (HZ / 2)
 
        gbe_dev->ale_reg = gbe_dev->switch_regs + GBENU_ALE_OFFSET;
        gbe_dev->ale_ports = gbe_dev->max_num_ports;
        gbe_dev->host_port = GBENU_HOST_PORT_NUM;
-       gbe_dev->ale_entries = GBE13_NUM_ALE_ENTRIES;
        gbe_dev->stats_en_mask = (1 << (gbe_dev->max_num_ports)) - 1;
 
        /* Subsystem registers */