The 1st cell is reset pre-delay in micro seconds.
        The 2nd cell is reset pulse in micro seconds.
        The 3rd cell is reset post-delay in micro seconds.
+
+Optional properties:
+- resets: Should contain a phandle to the STMMAC reset signal, if any
+- reset-names: Should contain the reset signal name "stmmaceth", if a
+       reset phandle is given
+- max-frame-size: See ethernet.txt file in the same directory
+- clocks: If present, the first clock should be the GMAC main clock and
+  the second clock should be peripheral's register interface clock. Further
+  clocks may be specified in derived bindings.
+- clock-names: One name for each entry in the clocks property, the
+  first one should be "stmmaceth" and the second one should be "pclk".
+- clk_ptp_ref: this is the PTP reference clock; in case of the PTP is
+  available this clock is used for programming the Timestamp Addend Register.
+  If not passed then the system clock will be used and this is fine on some
+  platforms.
+- tx-fifo-depth: See ethernet.txt file in the same directory
+- rx-fifo-depth: See ethernet.txt file in the same directory
 - snps,pbl             Programmable Burst Length
+- snps,aal             Address-Aligned Beats
 - snps,fixed-burst     Program the DMA to use the fixed burst mode
 - snps,mixed-burst     Program the DMA to use the mixed burst mode
 - snps,force_thresh_dma_mode   Force DMA to use the threshold mode for
                                supported by this device instance
 - snps,perfect-filter-entries: Number of perfect filter entries supported
                                by this device instance
-
-Optional properties:
-- resets: Should contain a phandle to the STMMAC reset signal, if any
-- reset-names: Should contain the reset signal name "stmmaceth", if a
-       reset phandle is given
-- max-frame-size: See ethernet.txt file in the same directory
-- clocks: If present, the first clock should be the GMAC main clock
-  The optional second clock should be peripheral's register interface clock.
-  The third optional clock should be the ptp reference clock.
-  Further clocks may be specified in derived bindings.
-- clock-names: One name for each entry in the clocks property.
-  The first one should be "stmmaceth".
-  The optional second one should be "pclk".
-  The optional third one should be "clk_ptp_ref".
-- snps,burst_len: The AXI burst lenth value of the AXI BUS MODE register.
-- tx-fifo-depth: See ethernet.txt file in the same directory
-- rx-fifo-depth: See ethernet.txt file in the same directory
+- AXI BUS Mode parameters: below the list of all the parameters to program the
+                          AXI register inside the DMA module:
+       - snps,lpi_en: enable Low Power Interface
+       - snps,xit_frm: unlock on WoL
+       - snps,wr_osr_lmt: max write oustanding req. limit
+       - snps,rd_osr_lmt: max read oustanding req. limit
+       - snps,kbbe: do not cross 1KiB boundary.
+       - snps,axi_all: align address
+       - snps,blen: this is a vector of supported burst length.
+       - snps,fb: fixed-burst
+       - snps,mb: mixed-burst
+       - snps,rb: rebuild INCRx Burst
 - mdio: with compatible = "snps,dwmac-mdio", create and register mdio bus.
 
 Examples:
 
+       stmmac_axi_setup: stmmac-axi-config {
+               snps,wr_osr_lmt = <0xf>;
+               snps,rd_osr_lmt = <0xf>;
+               snps,blen = <256 128 64 32 0 0 0>;
+       };
+
        gmac0: ethernet@e0800000 {
                compatible = "st,spear600-gmac";
                reg = <0xe0800000 0x8000>;
                tx-fifo-depth = <16384>;
                clocks = <&clock>;
                clock-names = "stmmaceth";
+               snps,axi-config = <&stmmac_axi_setup>;
                mdio0 {
                        #address-cells = <1>;
                        #size-cells = <0>;
 
 
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
+#include <linux/stmmac.h>
 #include <linux/phy.h>
 #include <linux/module.h>
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
        /* DMA core initialization */
        int (*reset)(void __iomem *ioaddr);
        void (*init)(void __iomem *ioaddr, int pbl, int fb, int mb,
-                    int burst_len, u32 dma_tx, u32 dma_rx, int atds);
+                    int aal, u32 dma_tx, u32 dma_rx, int atds);
+       /* Configure the AXI Bus Mode Register */
+       void (*axi)(void __iomem *ioaddr, struct stmmac_axi *axi);
        /* Dump DMA registers */
        void (*dump_regs) (void __iomem *ioaddr);
        /* Set tx/rx threshold in the csr6 register
 
 #define DMA_BUS_MODE_RPBL_MASK 0x003e0000      /* Rx-Programmable Burst Len */
 #define DMA_BUS_MODE_RPBL_SHIFT        17
 #define DMA_BUS_MODE_USP       0x00800000
-#define DMA_BUS_MODE_PBL       0x01000000
+#define DMA_BUS_MODE_MAXPBL    0x01000000
 #define DMA_BUS_MODE_AAL       0x02000000
 
 /* DMA CRS Control and Status Register Mapping */
 
 #include "dwmac1000.h"
 #include "dwmac_dma.h"
 
+static void dwmac1000_dma_axi(void __iomem *ioaddr, struct stmmac_axi *axi)
+{
+       u32 value = readl(ioaddr + DMA_AXI_BUS_MODE);
+       int i;
+
+       pr_info("dwmac1000: Master AXI performs %s burst length\n",
+               !(value & DMA_AXI_UNDEF) ? "fixed" : "any");
+
+       if (axi->axi_lpi_en)
+               value |= DMA_AXI_EN_LPI;
+       if (axi->axi_xit_frm)
+               value |= DMA_AXI_LPI_XIT_FRM;
+
+       value |= (axi->axi_wr_osr_lmt & DMA_AXI_WR_OSR_LMT_MASK) <<
+                DMA_AXI_WR_OSR_LMT_SHIFT;
+
+       value |= (axi->axi_rd_osr_lmt & DMA_AXI_RD_OSR_LMT_MASK) <<
+                DMA_AXI_RD_OSR_LMT_SHIFT;
+
+       /* Depending on the UNDEF bit the Master AXI will perform any burst
+        * length according to the BLEN programmed (by default all BLEN are
+        * set).
+        */
+       for (i = 0; i < AXI_BLEN; i++) {
+               switch (axi->axi_blen[i]) {
+               case 256:
+                       value |= DMA_AXI_BLEN256;
+                       break;
+               case 128:
+                       value |= DMA_AXI_BLEN128;
+                       break;
+               case 64:
+                       value |= DMA_AXI_BLEN64;
+                       break;
+               case 32:
+                       value |= DMA_AXI_BLEN32;
+                       break;
+               case 16:
+                       value |= DMA_AXI_BLEN16;
+                       break;
+               case 8:
+                       value |= DMA_AXI_BLEN8;
+                       break;
+               case 4:
+                       value |= DMA_AXI_BLEN4;
+                       break;
+               }
+       }
+
+       writel(value, ioaddr + DMA_AXI_BUS_MODE);
+}
+
 static void dwmac1000_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
-                              int burst_len, u32 dma_tx, u32 dma_rx, int atds)
+                              int aal, u32 dma_tx, u32 dma_rx, int atds)
 {
-       u32 value;
+       u32 value = readl(ioaddr + DMA_BUS_MODE);
 
        /*
-        * Set the DMA PBL (Programmable Burst Length) mode
-        * Before stmmac core 3.50 this mode bit was 4xPBL, and
+        * Set the DMA PBL (Programmable Burst Length) mode.
+        *
+        * Note: before stmmac core 3.50 this mode bit was 4xPBL, and
         * post 3.5 mode bit acts as 8*PBL.
-        * For core rev < 3.5, when the core is set for 4xPBL mode, the
-        * DMA transfers the data in 4, 8, 16, 32, 64 & 128 beats
-        * depending on pbl value.
-        * For core rev > 3.5, when the core is set for 8xPBL mode, the
-        * DMA transfers the data in 8, 16, 32, 64, 128 & 256 beats
-        * depending on pbl value.
+        *
+        * This configuration doesn't take care about the Separate PBL
+        * so only the bits: 13-8 are programmed with the PBL passed from the
+        * platform.
         */
-       value = DMA_BUS_MODE_PBL | ((pbl << DMA_BUS_MODE_PBL_SHIFT) |
-                                   (pbl << DMA_BUS_MODE_RPBL_SHIFT));
+       value |= DMA_BUS_MODE_MAXPBL;
+       value &= ~DMA_BUS_MODE_PBL_MASK;
+       value |= (pbl << DMA_BUS_MODE_PBL_SHIFT);
 
        /* Set the Fixed burst mode */
        if (fb)
        if (atds)
                value |= DMA_BUS_MODE_ATDS;
 
-       writel(value, ioaddr + DMA_BUS_MODE);
+       if (aal)
+               value |= DMA_BUS_MODE_AAL;
 
-       /* In case of GMAC AXI configuration, program the DMA_AXI_BUS_MODE
-        * for supported bursts.
-        *
-        * Note: This is applicable only for revision GMACv3.61a. For
-        * older version this register is reserved and shall have no
-        * effect.
-        *
-        * Note:
-        *  For Fixed Burst Mode: if we directly write 0xFF to this
-        *  register using the configurations pass from platform code,
-        *  this would ensure that all bursts supported by core are set
-        *  and those which are not supported would remain ineffective.
-        *
-        *  For Non Fixed Burst Mode: provide the maximum value of the
-        *  burst length. Any burst equal or below the provided burst
-        *  length would be allowed to perform.
-        */
-       writel(burst_len, ioaddr + DMA_AXI_BUS_MODE);
+       writel(value, ioaddr + DMA_BUS_MODE);
 
        /* Mask interrupts by writing to CSR7 */
        writel(DMA_INTR_DEFAULT_MASK, ioaddr + DMA_INTR_ENA);
 const struct stmmac_dma_ops dwmac1000_dma_ops = {
        .reset = dwmac_dma_reset,
        .init = dwmac1000_dma_init,
+       .axi = dwmac1000_dma_axi,
        .dump_regs = dwmac1000_dump_dma_regs,
        .dma_mode = dwmac1000_dma_operation_mode,
        .enable_dma_transmission = dwmac_enable_dma_transmission,
 
 #include "dwmac_dma.h"
 
 static void dwmac100_dma_init(void __iomem *ioaddr, int pbl, int fb, int mb,
-                             int burst_len, u32 dma_tx, u32 dma_rx, int atds)
+                             int aal, u32 dma_tx, u32 dma_rx, int atds)
 {
        /* Enable Application Access by writing to DMA CSR0 */
        writel(DMA_BUS_MODE_DEFAULT | (pbl << DMA_BUS_MODE_PBL_SHIFT),
 
 
 /* Rx watchdog register */
 #define DMA_RX_WATCHDOG                0x00001024
-/* AXI Bus Mode */
+
+/* AXI Master Bus Mode */
 #define DMA_AXI_BUS_MODE       0x00001028
+
+#define DMA_AXI_EN_LPI         BIT(31)
+#define DMA_AXI_LPI_XIT_FRM    BIT(30)
+#define DMA_AXI_WR_OSR_LMT     GENMASK(23, 20)
+#define DMA_AXI_WR_OSR_LMT_SHIFT       20
+#define DMA_AXI_WR_OSR_LMT_MASK        0xf
+#define DMA_AXI_RD_OSR_LMT     GENMASK(19, 16)
+#define DMA_AXI_RD_OSR_LMT_SHIFT       16
+#define DMA_AXI_RD_OSR_LMT_MASK        0xf
+
+#define DMA_AXI_OSR_MAX                0xf
+#define DMA_AXI_MAX_OSR_LIMIT ((DMA_AXI_OSR_MAX << DMA_AXI_WR_OSR_LMT_SHIFT) | \
+                              (DMA_AXI_OSR_MAX << DMA_AXI_RD_OSR_LMT_SHIFT))
+#define        DMA_AXI_1KBBE           BIT(13)
+#define DMA_AXI_AAL            BIT(12)
+#define DMA_AXI_BLEN256                BIT(7)
+#define DMA_AXI_BLEN128                BIT(6)
+#define DMA_AXI_BLEN64         BIT(5)
+#define DMA_AXI_BLEN32         BIT(4)
+#define DMA_AXI_BLEN16         BIT(3)
+#define DMA_AXI_BLEN8          BIT(2)
+#define DMA_AXI_BLEN4          BIT(1)
+#define DMA_BURST_LEN_DEFAULT  (DMA_AXI_BLEN256 | DMA_AXI_BLEN128 | \
+                                DMA_AXI_BLEN64 | DMA_AXI_BLEN32 | \
+                                DMA_AXI_BLEN16 | DMA_AXI_BLEN8 | \
+                                DMA_AXI_BLEN4)
+
+#define DMA_AXI_UNDEF          BIT(0)
+
+#define DMA_AXI_BURST_LEN_MASK 0x000000FE
+
 #define DMA_CUR_TX_BUF_ADDR    0x00001050      /* Current Host Tx Buffer */
 #define DMA_CUR_RX_BUF_ADDR    0x00001054      /* Current Host Rx Buffer */
 #define DMA_HW_FEATURE         0x00001058      /* HW Feature Register */
 
  */
 static int stmmac_init_dma_engine(struct stmmac_priv *priv)
 {
-       int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, burst_len = 0;
+       int pbl = DEFAULT_DMA_PBL, fixed_burst = 0, aal = 0;
        int mixed_burst = 0;
        int atds = 0;
        int ret = 0;
                pbl = priv->plat->dma_cfg->pbl;
                fixed_burst = priv->plat->dma_cfg->fixed_burst;
                mixed_burst = priv->plat->dma_cfg->mixed_burst;
-               burst_len = priv->plat->dma_cfg->burst_len;
+               aal = priv->plat->dma_cfg->aal;
        }
 
        if (priv->extend_desc && (priv->mode == STMMAC_RING_MODE))
        }
 
        priv->hw->dma->init(priv->ioaddr, pbl, fixed_burst, mixed_burst,
-                           burst_len, priv->dma_tx_phy,
-                           priv->dma_rx_phy, atds);
+                           aal, priv->dma_tx_phy, priv->dma_rx_phy, atds);
+
+       if ((priv->synopsys_id >= DWMAC_CORE_3_50) &&
+           (priv->plat->axi && priv->hw->dma->axi))
+               priv->hw->dma->axi(priv->ioaddr, priv->plat->axi);
+
        return ret;
 }
 
 
        plat->mdio_bus_data->phy_mask = 0;
 
        plat->dma_cfg->pbl = 32;
-       plat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
+       /* TODO: AXI */
 
        /* Set default value for multicast hash bins */
        plat->multicast_filter_bins = HASH_TABLE_SIZE;
        plat->mdio_bus_data->phy_mask = 0;
 
        plat->dma_cfg->pbl = 16;
-       plat->dma_cfg->burst_len = DMA_AXI_BLEN_256;
        plat->dma_cfg->fixed_burst = 1;
+       /* AXI (TODO) */
 
        /* Set default value for multicast hash bins */
        plat->multicast_filter_bins = HASH_TABLE_SIZE;
 
        return x;
 }
 
+/**
+ * stmmac_axi_setup - parse DT parameters for programming the AXI register
+ * @pdev: platform device
+ * @priv: driver private struct.
+ * Description:
+ * if required, from device-tree the AXI internal register can be tuned
+ * by using platform parameters.
+ */
+static struct stmmac_axi *stmmac_axi_setup(struct platform_device *pdev)
+{
+       struct device_node *np;
+       struct stmmac_axi *axi;
+
+       np = of_parse_phandle(pdev->dev.of_node, "snps,axi-config", 0);
+       if (!np)
+               return NULL;
+
+       axi = kzalloc(sizeof(axi), GFP_KERNEL);
+       if (!axi)
+               return ERR_PTR(-ENOMEM);
+
+       axi->axi_lpi_en = of_property_read_bool(np, "snps,lpi_en");
+       axi->axi_xit_frm = of_property_read_bool(np, "snps,xit_frm");
+       axi->axi_kbbe = of_property_read_bool(np, "snps,axi_kbbe");
+       axi->axi_axi_all = of_property_read_bool(np, "snps,axi_all");
+       axi->axi_fb = of_property_read_bool(np, "snps,axi_fb");
+       axi->axi_mb = of_property_read_bool(np, "snps,axi_mb");
+       axi->axi_rb =  of_property_read_bool(np, "snps,axi_rb");
+
+       of_property_read_u32(np, "snps,wr_osr_lmt", &axi->axi_wr_osr_lmt);
+       of_property_read_u32(np, "snps,rd_osr_lmt", &axi->axi_rd_osr_lmt);
+       of_property_read_u32_array(np, "snps,blen", axi->axi_blen, AXI_BLEN);
+
+       return axi;
+}
+
 /**
  * stmmac_probe_config_dt - parse device-tree driver parameters
  * @pdev: platform_device structure
                }
                plat->dma_cfg = dma_cfg;
                of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl);
+               dma_cfg->aal = of_property_read_bool(np, "snps,aal");
                dma_cfg->fixed_burst =
                        of_property_read_bool(np, "snps,fixed-burst");
                dma_cfg->mixed_burst =
                        of_property_read_bool(np, "snps,mixed-burst");
-               of_property_read_u32(np, "snps,burst_len", &dma_cfg->burst_len);
-               if (dma_cfg->burst_len < 0 || dma_cfg->burst_len > 256)
-                       dma_cfg->burst_len = 0;
        }
        plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode");
        if (plat->force_thresh_dma_mode) {
                pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set.");
        }
 
+       plat->axi = stmmac_axi_setup(pdev);
+
        return plat;
 }
 #else
 
        int pbl;
        int fixed_burst;
        int mixed_burst;
-       int burst_len;
+       bool aal;
+};
+
+#define AXI_BLEN       7
+struct stmmac_axi {
+       bool axi_lpi_en;
+       bool axi_xit_frm;
+       u32 axi_wr_osr_lmt;
+       u32 axi_rd_osr_lmt;
+       bool axi_kbbe;
+       bool axi_axi_all;
+       u32 axi_blen[AXI_BLEN];
+       bool axi_fb;
+       bool axi_mb;
+       bool axi_rb;
 };
 
 struct plat_stmmacenet_data {
        int (*init)(struct platform_device *pdev, void *priv);
        void (*exit)(struct platform_device *pdev, void *priv);
        void *bsp_priv;
+       struct stmmac_axi *axi;
 };
 #endif