BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_customized/ll_pcie/Makefile b/bcm68620_release/release/host_customized/ll_pcie/Makefile
new file mode 100755
index 0000000..db7aa7d
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/Makefile
@@ -0,0 +1,36 @@
+MOD_NAME = ll_pcie
+MOD_SUPPRESS_OS_DEP = y
+MOD_DEPS = board_selector
+
+ifeq ("$(RELEASE_BUILD)", "y")
+	EXTRA_CFLAGS += -I$(SRC_DIR) -I$(TOP_DIR)/host_customized/os_abstraction 
+	EXTRA_CFLAGS += -I$(TOP_DIR)/host_customized/os_abstraction/linux -I$(TOP_DIR)/host_driver/config
+else
+	EXTRA_CFLAGS += -I$(SRC_DIR) -I$(TOP_DIR)/common/os_abstraction -I$(TOP_DIR)/host/config
+	EXTRA_CFLAGS += -I$(TOP_DIR)/common/os_abstraction/linux -I$(TOP_DIR)/host/os_abstraction/$(PLATFORM)
+endif
+
+ifeq ("$(ENABLE_TRACE)", "y")
+	MOD_DEFS += -DTX_ENABLE_EVENT_TRACE
+	EXTRA_CFLAGS += -I$(TOP_DIR)/common/drivers/maple/fld
+    ifeq ("$(DEBUG_TRACE_INIT)", "y")
+       MOD_DEFS += -DDEBUG_TRACE_INIT
+    endif
+endif
+
+ifeq ("$(OS_KERNEL)", "linux")
+    MOD_TYPE = linux_module
+    srcs = bcmolt_llpcie.c 
+else
+    MOD_TYPE = lib
+endif
+
+# If called by linux kernel builder - add include paths manually.
+# It is not elegant, but we'll not have many linux modules
+ifneq ("$(KBUILD_SRC)", "")
+	-include $(OUT_DIR_BASE)/Makefile.config.$(MOD_NAME)
+endif
+
+USE_LINT = yes
+
+
diff --git a/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.c b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.c
new file mode 100755
index 0000000..4bb1507
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.c
@@ -0,0 +1,1010 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+/*
+    might use readl or ioread32
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#ifdef TX_ENABLE_EVENT_TRACE
+#include <linux/ctype.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include "bcm_fld_common.h"
+#endif
+#include <bcmolt_board_selector.h>
+#include "bcmolt_llpcie.h"
+
+#define DRV_NAME	"maple"
+#define DRV_VERSION	"1.0.3"
+
+#define BAR_REGS                        0
+#define BAR_DDR                         2
+#define BAR_SRAM                        4
+/*
+bar 1 = 8  Mbyte register space
+bar 2 = 16 Mbyte DDR space
+bar 3 = 64 Kbyte SRAM space
+*/
+#define MAPLE_REGS_LENGTH                   0x00800000
+#define MAPLE_DDR_LENGTH                    0x01000000
+#define MAPLE_SRAM_LENGTH                   0x00010000
+
+#ifdef TX_ENABLE_EVENT_TRACE
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO			0x064014U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI			0x064018U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT	0x064074U
+#endif
+#define PCIE_REVISION_REGISTER_OFFSET       0x6406CU /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_REVISION    */
+#define PCIE_STATUS_REGISTER_OFFSET         0x64068U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
+#define PCIE_HARD_DEBUG_REGISTER_OFFSET     0x64204U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_HARD_DEBUG  */
+#define PCIE_INT_STATUS_REGISTER_OFFSET     0x69400U /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_STATUS        */
+#define PCIE_INT_CLEAR_MASK_OFFSET          0x6940CU /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_MASK_CLEAR    */
+#define PCIE_INTR1_STATUS_REGISTER_OFFSET   0x69300U /* Interrupt Status Register */
+
+#define PCIE_MAPLE_VENDOR_ID                0x14E4 /* PCIE_CFG_TYPE0_EP_SUBSYSTEM_ID_VENDOR_ID      */
+#define PCIE_MAPLE_DEVICE_ID                0x6862
+#define PCIE_MAPLE_6863_SKU_DEVICE_ID       0x6863
+#define PCIE_MAPLE_EPON_DEVICE_ID           0x5554
+
+#define MAPLE_DRIVER_NAME   DRV_NAME " BCM68620 (Maple) PCI driver " DRV_VERSION
+
+struct proc_dir_entry *bcmolt_dir = NULL;
+static DEFINE_PCI_DEVICE_TABLE(maple_pci_tbl) =
+{ /* vendor_id,                  device_id,       any,       any */
+    {PCI_DEVICE(PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_DEVICE_ID)},
+    {PCI_DEVICE(PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_6863_SKU_DEVICE_ID)},
+    {PCI_DEVICE(PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_EPON_DEVICE_ID)},
+    {0}
+};
+MODULE_DEVICE_TABLE (pci, maple_pci_tbl);
+
+typedef struct
+{
+    bcm_ll_dev_info  device;
+    spinlock_t       lock;
+    int              err_status;
+    int              phylink;
+    int              prev_datalink;
+    int              datalink;
+    uint32_t         deviceid;
+    unsigned int    *traceaddr;
+    struct pci_dev  *pdev;
+    int              enabled;
+} maple_device_info;
+
+static int crt_device = 0;
+static bcm_ll_pcie_status_change callback;
+static bcmos_bool is_initialized = BCMOS_FALSE;
+
+static maple_device_info devices[MAPLE_MAX_DEVICES];
+//static irqreturn_t maple_interrupt (int irq, void *dev_instance);
+static maple_device_info *get_maple_pci_info(int crt);
+
+static int maple_write(struct file *file,const char *buffer,size_t count, void *data);
+static int maple_read(char *page, char **start, off_t off, int count, int *eof, void *data);
+
+/* Map bus/device to device_id */
+static int _pcie_bus_devfv_to_devid(int bus, int devfn)
+{
+    const bus_devfn_devid *map;
+    for (map = bcmolt_board_pci_map_table_get(); map && map->bus > 0; map++)
+    {
+        if (map->bus == bus && map->devfn == devfn)
+        {
+            return map->device;
+        }
+    }
+    /* Not found - use incremental mapping */
+    return crt_device;
+}
+
+/* procedure used by OS to connect Maple PCI to allocated memory */
+
+static int __devinit maple_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+    int rc;
+    volatile unsigned int readval;
+    maple_device_info *device_info = NULL;
+    int dev_id;
+    u32 val;
+
+    if (!pdev)
+        return 1;
+
+    dev_info(&pdev->dev,
+        "Bus = %d Slot = %d Vendor:device = 0x%04x:0x%04x revision = 0x%02x\n",
+        pdev->bus->number, pdev->devfn,
+        pdev->vendor, pdev->device, pdev->revision);
+
+    if (crt_device == MAPLE_MAX_DEVICES)
+    {
+        printk(" Maximum Maple devices already defined (%d)\n", MAPLE_MAX_DEVICES);
+        return -ENODEV;
+    }
+
+    dev_id = _pcie_bus_devfv_to_devid(pdev->bus->number, pdev->devfn);
+    ++crt_device;
+    device_info = &devices[dev_id];
+    memset(device_info, 0, sizeof(maple_device_info));
+
+    spin_lock_init(&device_info->lock);
+    device_info->deviceid = dev_id;
+    device_info->pdev = pdev;
+
+    /* Enable maple device on PCIe bus and fixup BARs.
+     * Without fixup, module unload/reload crashes with WRX host
+     * because PCI hotplug doesn't work and after unload/re-load
+     * linux believes that BARs are already set.
+     */
+    rc = bcm_ll_pcie_dev_enable(dev_id);
+    if (rc)
+    {
+        printk("Error pci_enable_device_mem = %d\n",rc);
+        goto err_out;
+    }
+
+    rc = pci_request_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM), DRV_NAME);
+    if (rc)
+        goto err_out;
+
+    pci_set_master(pdev);
+    pci_save_state(pdev);
+
+    device_info->device.soc_regs_base = (unsigned long)pci_ioremap_bar(pdev, BAR_REGS);
+    device_info->device.soc_sram_base = (unsigned long)pci_ioremap_bar(pdev, BAR_SRAM);
+    device_info->device.soc_ddr_base = (unsigned long)pci_ioremap_bar(pdev, BAR_DDR);
+    device_info->device.soc_ddr_length = (uint32_t)pci_resource_len(pdev, BAR_DDR);
+    device_info->device.irq = pdev->irq;
+    pci_set_drvdata(pdev, device_info);
+
+    //rc = request_irq(device_info->device.irq, maple_interrupt, IRQF_SHARED, "maple-pcie", device_info);
+    if (!rc && device_info->device.soc_sram_base)
+    {
+        device_info->device.irq_connected = 1;
+        readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
+        printk("Card %d version major=%02x minor=%02x\n",device_info->deviceid,
+               ((readval & 0x0000ff00) >> 8),(readval & 0x000000ff));
+        printk("regs_start = 0x%lx\nddr_start  = 0x%lx\nsram_start = 0x%lx\nddr_length  = %d\n",
+                 device_info->device.soc_regs_base,device_info->device.soc_ddr_base,
+                 device_info->device.soc_sram_base, (int)device_info->device.soc_ddr_length);
+        pci_read_config_dword(pdev,PCI_BASE_ADDRESS_0,&val);
+        printk("BAR REGS = 0x%x\n",(unsigned int)val);
+        pci_read_config_dword(pdev,PCI_BASE_ADDRESS_2,&val);
+        printk("BAR DDR = 0x%x\n",(unsigned int)val);
+        pci_read_config_dword(pdev,PCI_BASE_ADDRESS_4,&val);
+        printk("BAR SRAM = 0x%x\n",(unsigned int)val);
+        readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+        device_info->err_status = readval & 0x0000000f;
+        device_info->phylink    = (readval >> 4) & 0x1;
+        device_info->datalink   = (readval >> 5) & 0x1;
+        device_info->prev_datalink  = device_info->datalink;
+    }
+    else
+        goto err_out;
+
+    return rc;
+
+err_out:
+    pci_disable_device (pdev);
+    memset(device_info, 0, sizeof(*device_info));
+    --crt_device;
+
+    return rc;
+}
+
+static void __devexit maple_pci_remove(struct pci_dev *pdev)
+{
+    int i;
+    maple_device_info *dev = pci_get_drvdata(pdev);
+
+    if (!dev)
+        return;
+
+    if (dev->device.irq_connected)
+    {
+        //free_irq(dev->device.irq, dev);
+        dev->device.irq_connected = 0;
+    }
+    if (callback)
+    {
+        for (i = 0; i < crt_device; i++)
+        {
+            if (devices[i].pdev == pdev)
+            {
+                callback(i, BCM_LL_PCIE_LINK_DOWN);
+                break;
+            }
+        }
+    }
+    pci_disable_device(pdev);
+    pci_release_regions(pdev);
+    pci_set_drvdata(pdev, NULL);
+    dev->device.soc_sram_base = 0;
+    dev->device.soc_regs_base = 0;
+    dev->pdev = NULL;
+}
+
+static struct pci_driver maple_pci_driver = {
+    .name       = DRV_NAME,
+    .id_table   = maple_pci_tbl,
+    .probe      = maple_pci_probe,
+    .remove     = __devexit_p(maple_pci_remove),
+};
+
+static maple_device_info *get_maple_pci_info(int crt)
+{
+    unsigned int readval=0;
+    maple_device_info *device;
+
+    if (crt >= BCMTR_MAX_OLTS)
+        return NULL;
+
+    device = &devices[crt];
+    if (device->device.soc_regs_base)
+    {
+        if (device->enabled)
+        {
+            readval = bcm_pci_read32((uint32_t *)(device->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+            device->err_status = readval & 0x0000000f;
+            device->phylink    = (readval >> 4) & 0x1;
+            device->datalink   = (readval >> 5) & 0x1;
+        }
+        else
+        {
+            device->err_status = 0;
+            device->phylink    = 0;
+            device->datalink   = 0;
+        }
+    }
+    else
+        device = NULL;
+
+    return device;
+}
+
+#if 0
+static irqreturn_t maple_interrupt (int irq, void *dev_instance)
+{
+    volatile unsigned int value;
+    maple_device_info *device_info;
+    unsigned long flags;
+    int handled = IRQ_NONE;
+    uint32_t device;
+
+    spin_lock_irqsave(&device_info->lock, flags);
+    value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
+    if (value)
+    {
+        if (device_info->datalink != device_info->prev_datalink)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
+                printk("Device=%d : Link is up !!!\n", device);
+            else
+            {
+                printk("Device=%d : Link is down !!!\n", device);
+                printk("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
+            }
+            device_info->prev_datalink = device_info->datalink;
+            if (callback)
+                callback(device, device_info->datalink);
+        }
+        value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
+        if (!value)
+            handled = IRQ_HANDLED;
+    }
+    spin_unlock_irqrestore(&device_info->lock, flags);
+
+    return IRQ_RETVAL(handled);
+}
+#endif
+
+/* Returns BAR register address */
+static int _pci_bar_reg_addr(int res)
+{
+    return 0x10 + res*4;
+}
+
+static void _pci_update_resource(struct pci_dev *dev, int resno)
+{
+        struct pci_bus_region region;
+        u16 cmd;
+        u32 new, check, mask;
+        int reg;
+        struct resource *res = dev->resource + resno;
+
+        /*
+         * Ignore resources for unimplemented BARs and unused resource slots
+         * for 64 bit BARs.
+         */
+        if (!res->flags)
+                return;
+
+        /*
+         * Ignore non-moveable resources.  This might be legacy resources for
+         * which no functional BAR register exists or another important
+         * system resource we shouldn't move around.
+         */
+        if (res->flags & IORESOURCE_PCI_FIXED)
+                return;
+
+        pcibios_resource_to_bus(dev, &region, res);
+
+        new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
+        if (res->flags & IORESOURCE_IO)
+                mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
+        else
+                mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
+
+        reg = _pci_bar_reg_addr(resno);
+
+        pci_write_config_dword(dev, reg, new);
+        pci_read_config_dword(dev, reg, &check);
+
+        if ((new ^ check) & mask) {
+                dev_err(&dev->dev, "BAR %d: error updating (%#08x != %#08x)\n",
+                        resno, new, check);
+        }
+
+        if (res->flags & IORESOURCE_MEM_64) {
+                new = region.start >> 16 >> 16;
+                pci_write_config_dword(dev, reg + 4, new);
+                pci_read_config_dword(dev, reg + 4, &check);
+                if (check != new) {
+                        dev_err(&dev->dev, "BAR %d: error updating "
+                               "(high %#08x != %#08x)\n", resno, new, check);
+                }
+        }
+
+        pci_read_config_word(dev, PCI_COMMAND, &cmd);
+        pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+        res->flags &= ~IORESOURCE_UNSET;
+        dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
+                resno, res, (unsigned long long)region.start,
+                (unsigned long long)region.end);
+}
+
+/* Enable PCI access to device */
+bcmos_errno bcm_ll_pcie_dev_enable(int dev_id)
+{
+    maple_device_info *device;
+    int rc;
+
+    if (dev_id >= MAPLE_MAX_DEVICES)
+        return BCM_ERR_PARM;
+
+    device = &devices[dev_id];
+    if (!device->pdev)
+        return BCM_ERR_IO;
+
+    rc = pci_enable_device_mem(device->pdev);
+    if (rc)
+    {
+        printk("Error pci_enable_device_mem for device %d = %d\n", dev_id, rc);\
+        goto out;
+    }
+
+    /* Refresh devices's PCIe header */
+    _pci_update_resource(device->pdev, BAR_REGS);
+    _pci_update_resource(device->pdev, BAR_SRAM);
+    _pci_update_resource(device->pdev, BAR_DDR);
+    device->enabled = 1;
+
+out:
+    return rc ? BCM_ERR_IO : BCM_ERR_OK;
+}
+
+/* Disable PCI access to device */
+bcmos_errno bcm_ll_pcie_dev_disable(int dev_id)
+{
+    maple_device_info *device;
+
+    printk("%s: device %d\n", __FUNCTION__, dev_id);
+
+    if (dev_id >= MAPLE_MAX_DEVICES)
+        return BCM_ERR_PARM;
+
+    device = &devices[dev_id];
+    if (!device->pdev || !device->enabled)
+        return BCM_ERR_OK;
+    pci_disable_device(device->pdev);
+    device->enabled = 0;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_ll_pcie_init(void)
+{
+    int rc;
+    if (is_initialized)
+        return BCM_ERR_OK;
+    is_initialized = BCMOS_TRUE;
+    rc = pci_register_driver(&maple_pci_driver);
+    printk(KERN_INFO "Maple PCI driver registered with PCI subsystem. rc=%d\n", rc);
+    return rc ? BCM_ERR_INTERNAL : BCM_ERR_OK;
+}
+
+void bcm_ll_pcie_cleanup(void)
+{
+    if (!is_initialized)
+        return;
+    is_initialized = BCMOS_FALSE;
+
+    pci_unregister_driver(&maple_pci_driver);
+    crt_device = 0;
+    memset(devices, 0, sizeof(devices));
+}
+
+/*******************************************/
+/* procedures executed on insmod and rmmod */
+/*******************************************/
+static int __init bcm_ll_init_module(void)
+{
+    struct proc_dir_entry *bcmolt_file = NULL;
+
+    if ((bcmolt_dir = create_proc_entry("bcmolt", S_IFDIR, NULL)) == NULL)
+    {
+        printk("Unable to create /proc/bcmolt entry\n");
+        return -1;
+    }
+    if ((bcmolt_file = create_proc_entry("card", S_IFREG | S_IWUSR | S_IRUGO, bcmolt_dir)) == NULL)
+    {
+        printk("Unable to create /proc/bcmolt/card entry\n");
+        remove_proc_entry("bcmolt", bcmolt_dir);
+        return -1;
+    }
+    bcmolt_file->write_proc = (write_proc_t *)maple_write;
+    bcmolt_file->read_proc = (read_proc_t *)maple_read;
+
+    return 0;
+}
+
+static void __exit bcm_ll_cleanup_module(void)
+{
+    bcm_ll_pcie_cleanup();
+    remove_proc_entry("card", bcmolt_dir);
+    remove_proc_entry("bcmolt", NULL);
+    printk("Unregister done\n");
+}
+
+/*****************************/
+/* APIs used by Host drivers */
+/*****************************/
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
+{
+    int i;
+    maple_device_info *device_info;
+
+    callback = cb;
+    if(callback)
+    {
+        for (i = 0; i < crt_device; i++)
+        {
+            device_info = get_maple_pci_info(i);
+            if (device_info)
+                callback(i, device_info->datalink);
+            else
+                callback(i, BCM_LL_PCIE_LINK_DOWN);
+        }
+    }
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_ll_pcie_status_change_unregister(void)
+{
+    callback = NULL;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
+{
+    maple_device_info *device_info;
+
+    if (!info)
+        return BCM_ERR_PARM;
+
+    if (dev_id < MAPLE_MAX_DEVICES)
+    {
+        device_info = get_maple_pci_info(dev_id);
+        if (device_info && device_info->pdev)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_DOWN)
+                return BCM_ERR_IO;
+            *info = device_info->device;
+            return BCM_ERR_OK;
+        }
+        return BCM_ERR_IO;
+    }
+    return BCM_ERR_RANGE;
+}
+
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
+{
+    maple_device_info *device_info;
+
+    if (dev_id < crt_device)
+    {
+        device_info = get_maple_pci_info(dev_id);
+        return (device_info ? device_info->pdev : NULL);
+    }
+
+    return NULL;
+}
+
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
+{
+    uint32_t val;
+
+    val = enabled ? 0 : 1;
+    bcm_pci_write32((uint32_t *)(devices[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET), val);
+
+    return BCM_ERR_OK;
+}
+
+#ifdef TX_ENABLE_EVENT_TRACE
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id)
+{
+    maple_device_info *device_info;
+    uint32_t val,lim,base,size;
+    uint32_t reglo,reghi,baselim;
+    unsigned long addr;
+
+    if (dev_id < crt_device)
+    {
+        device_info = &devices[dev_id];
+        if (!device_info)
+            return BCM_ERR_IO;
+        size = EVENT_BUFFER_SIZE;
+        device_info->traceaddr = (unsigned int *)bcmos_alloc_not_cache(size);
+        memset(device_info->traceaddr,0,size);
+        addr = bcmos_virt_to_phys(device_info->traceaddr); /* | 0x02 = reverse byte order = swap */
+        printk("trace window : alloc=0x%lx size=0x%x\n",(unsigned long)device_info->traceaddr, (unsigned int)size);
+        reglo = PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO;
+        reghi = PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI;
+        baselim = PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT;
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_regs_base + reglo),addr & 0xffffffff);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_regs_base + reghi)),((addr >> 32) & 0xffffffff);
+        /* base */
+        base = CPU_2_PCIE_MEM_WIN1_BASE;
+        /* limit */
+        lim = base + size;
+        val = lim  | (base >> 16);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_regs_base + baselim),val);
+        //bcm_fld_set_event_trace(dev_id);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_sram_base + BCM_FLD_EVENT_TRACE_OFFSET),0x1);
+
+        return BCM_ERR_OK;
+    }
+    return BCM_ERR_RANGE;
+}
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id)
+{
+    maple_device_info *device_info;
+
+    if (dev_id < crt_device)
+    {
+        device_info = &devices[dev_id];
+        if (!device_info)
+            return BCM_ERR_IO;
+        //bcm_fld_clear_event_trace(dev_id);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_sram_base + BCM_FLD_EVENT_TRACE_OFFSET),0x0);
+        return BCM_ERR_OK;
+    }
+    return BCM_ERR_RANGE;
+}
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename)
+{
+    maple_device_info *device_info;
+    struct file         *fp;
+    unsigned long seg   = 0;
+    mm_segment_t memseg;
+
+    if (!tracefilename)
+        return BCM_ERR_PARM;
+
+    printk("device=%d from=%d, Go to write to file %s\n",dev_id , crt_device, tracefilename);
+
+    if (dev_id < crt_device)
+    {
+        device_info = &devices[dev_id];
+        if (!device_info)
+        {
+            printk("Error: device_info is null\n");
+            goto exit;
+        }
+        fp = filp_open(tracefilename, O_WRONLY | O_CREAT, 0666);
+        if ((fp == NULL) || (fp == (void *)-ENOENT))
+        {
+            printk("Error: Can't open file %s\n",tracefilename);
+            goto exit;
+        }
+        // Get current segment descriptor
+        seg = get_fs().seg;
+
+        // Set segment descriptor associated to kernel space
+        set_fs(get_ds());
+        fp->f_op->write(fp, (char *)device_info->traceaddr,EVENT_BUFFER_SIZE, &fp->f_pos);
+
+        memseg.seg = seg;
+        set_fs(memseg);
+        filp_close(fp, NULL);
+        printk("Wrote file %s\n",tracefilename);
+exit:
+        bcmos_free_not_cache(device_info->traceaddr);
+
+        return BCM_ERR_OK;
+    }
+    return BCM_ERR_RANGE;
+}
+#endif
+
+/*************************************************************/
+/* User interface functions : implement echo/cat to proc file*/
+/*************************************************************/
+
+typedef struct
+{
+    char *name;
+	void (*callback)(int cmdid, char *cmd);
+    char *description;
+} maple_card_command;
+
+static char *find_command(char *cmd);
+static void command_reg(int cmdid, char *line);
+static void command_mem(int cmdid, char *line);
+static void command_cfg(int cmdid, char *line);
+#ifdef TX_ENABLE_EVENT_TRACE
+static void command_trace(int cmdid, char *line);
+#endif
+
+#define READCMD     0
+#define WRITECMD    1
+
+static maple_card_command commands[] =
+{
+    {"readreg",     command_reg, "read register <index> <register offset - hex>"},
+    {"writereg",    command_reg, "write register <index> <register offset - hex> <value - hex>"},
+    {"read",        command_mem, "read <address - hex> <number of words - dec>"},
+    {"write",       command_mem, "write <address - hex> <value - hex>"},
+    {"rcfg",        command_cfg, "read dev <address - hex> <number of words - dec>"},
+    {"wcfg",        command_cfg, "write dev <address - hex> <value - hex>"},
+#ifdef TX_ENABLE_EVENT_TRACE
+    {"trace",       command_trace, "trace <index> on/off/save tx trace"},
+#endif
+    {NULL, NULL, NULL}
+};
+
+static char *find_command(char *cmd)
+{
+    char *rest;
+    int i = 0;
+    maple_card_command *cmdptr = &commands[0];
+
+    cmd = skip_spaces(cmd);
+    if (!strncmp(cmd,"help",strlen("help")))
+    {
+        while (cmdptr->name)
+        {
+            printk("%s\t: %s\n",cmdptr->name, cmdptr->description);
+            cmdptr = &commands[++i];
+        }
+        return NULL;
+    }
+    while (cmdptr->name)
+    {
+        if (!strncmp(cmdptr->name, cmd, strlen(cmdptr->name)))
+        {
+            rest = cmd + strlen(cmdptr->name);
+            rest = skip_spaces(rest);
+            cmdptr->callback(i%2, rest);
+            return NULL;
+        }
+        cmdptr = &commands[++i];
+    }
+
+    return "Wrong command name";
+}
+/**********************************************************************
+  answers to cat /proc/bcmolt command
+**********************************************************************/
+static int maple_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+    int i;
+    int len;
+    maple_device_info *dev = NULL;
+
+    len = sprintf(page, "Maple Device Info\n\n");
+    for (i = 0; i < MAPLE_MAX_DEVICES; i++)
+    {
+        dev = get_maple_pci_info(i);
+        if (dev)
+        {
+            len += sprintf(page + len, "id=%d regs_start=0x%lx ddr_start=0x%lx sram_start=0x%lx ddr_length=%d\n",
+                dev->deviceid,
+                dev->device.soc_regs_base,dev->device.soc_ddr_base,
+                dev->device.soc_sram_base, (int)dev->device.soc_ddr_length);
+            len += sprintf(page + len, "Phy Link is %s Data Link is %s Error status = %d\n\n",
+                dev->phylink == 1 ? "UP" : "DOWN", dev->datalink == 1 ? "UP" : "DOWN", (int)dev->err_status);
+        }
+    }
+
+    return len;
+}
+#ifdef TX_ENABLE_EVENT_TRACE
+static void command_trace(int cmdid, char *line)
+{
+    char token[5];
+    int  index;
+
+    if (sscanf(line, "%d %s", &index, token) != 2)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+    printk("TRACE commands : %s\n",token);
+    if (!strncmp(token,"on",2))
+    {
+        //on
+        bcm_ll_pcie_setrace(index);
+        return;
+    }
+    if (!strncmp(token,"off",3))
+    {
+        // off
+        bcm_ll_pcie_cleartrace(index);
+        return;
+    }
+    if (!strncmp(token,"save",4))
+    {
+        //get
+        char filename[20];
+        sprintf(filename,"./tt_trace_%d.trx",index);
+        bcm_ll_pcie_savetrace(index,filename);
+        return;
+    }
+    printk("Wrong command\n");
+}
+#endif
+
+
+static void command_reg(int cmdindex, char *line)
+{
+    char *rest;
+    char *token;
+    int  index;
+    unsigned long address;
+    unsigned int reg;
+
+    if (sscanf(line, "%d %lx", &index, &address) != 2)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+    address += (unsigned long)devices[index].device.soc_regs_base;
+    switch (cmdindex)
+    {
+    case READCMD:
+        reg = bcm_pci_read32((uint32_t *)address);
+        printk("0x%lx : %08x\n", address, reg);
+        break;
+    case WRITECMD:
+        rest = line;
+        token = strsep(&rest, " "); /* skip index */
+        token = strsep(&rest, " "); /* skip address */
+        token = strsep(&rest, " ");
+        if (!token)
+        {
+            printk("Wrong parameter\n");
+            return;
+        }
+        sscanf(token, "%x", &reg);
+        printk("write 0x%x to 0x%lx\n", reg, address);
+        bcm_pci_write32((uint32_t *)address,reg);
+        break;
+    }
+}
+
+static void command_mem(int cmdindex, char *line)
+{
+    char *token;
+    char *rest;
+    unsigned long address;
+    unsigned int reg;
+    int i, number_of_words;
+    int in_line=0, max_in_line;
+
+    if (sscanf(line, "%lx", &address) != 1)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+    rest = line;
+    token = strsep(&rest, " "); /* skip address */
+    switch (cmdindex)
+    {
+    case READCMD:
+        token = strsep(&rest, " ");
+        if (!token)
+            number_of_words = 1;
+        else
+            sscanf(token, "%d", &number_of_words);
+
+        max_in_line = 4;
+        for (i = 0; i < number_of_words; i++, address += 4)
+        {
+            if (!in_line)
+                printk("%08lx: ", address);
+            reg = bcm_pci_read32((uint32_t *)address);
+            printk("%08x", reg);
+            if (++in_line < max_in_line)
+                printk(" ");
+            else
+            {
+                printk("\n");
+                in_line = 0;
+            }
+        }
+        if (in_line)
+            printk("\n");
+        break;
+    case WRITECMD:
+        token = strsep(&rest, " ");
+        if (!token)
+        {
+            printk("Wrong parameter\n");
+            return;
+        }
+        sscanf(token, "%x", &reg);
+        bcm_pci_write32((uint32_t *)address,reg);
+        break;
+    }
+}
+
+static void command_cfg(int cmdindex, char *line)
+{
+    unsigned long address;
+    unsigned int reg;
+    unsigned int val_or_num;
+    int crt;
+    int i;
+    int in_line=0, max_in_line;
+    maple_device_info *device;
+
+    if (sscanf(line, "%d %lx %x", &crt, &address, &val_or_num) != 3)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+
+    if (crt >= crt_device || !devices[crt].pdev)
+    {
+        printk("Invalid device %d\n", crt);
+        return;
+    }
+
+    device = &devices[crt];
+
+    switch (cmdindex)
+    {
+    case READCMD:
+        max_in_line = 4;
+        for (i = 0; i < val_or_num; i++, address += 4)
+        {
+            if (!in_line)
+                printk("%08lx: ", address);
+            pci_read_config_dword(device->pdev, address, &reg);
+            printk("%08x", reg);
+            if (++in_line < max_in_line)
+                printk(" ");
+            else
+            {
+                printk("\n");
+                in_line = 0;
+            }
+        }
+        if (in_line)
+            printk("\n");
+        break;
+
+    case WRITECMD:
+        pci_write_config_dword(device->pdev, address, val_or_num);
+        break;
+    }
+}
+
+/**********************************************************************
+  answers to echo [...] > /proc/bcmolt command
+**********************************************************************/
+static int maple_write(struct file *file,const char *buffer,size_t count, void *data)
+{
+    char *internal;
+
+    if (buffer == NULL)
+        return -EFAULT;
+
+    internal = kmalloc(count, GFP_KERNEL);
+    if (!internal)
+    {
+        printk("Not enough memmory\n");
+        return count;
+    }
+
+    memset(internal, 0, count);
+    if (copy_from_user(internal, buffer, count))
+    {
+        printk("Not enough memmory\n");
+        goto error;
+    }
+    find_command(internal);
+
+error:
+    kfree(internal);
+
+    return count;
+}
+
+EXPORT_SYMBOL(bcmolt_dir);
+EXPORT_SYMBOL(bcm_ll_pcie_init);
+EXPORT_SYMBOL(bcm_ll_pcie_cleanup);
+EXPORT_SYMBOL(bcm_ll_pcie_status_change_register);
+EXPORT_SYMBOL(bcm_ll_pcie_status_change_unregister);
+EXPORT_SYMBOL(bcm_ll_pcie_query);
+EXPORT_SYMBOL(bcm_ll_pcie_dev_get);
+EXPORT_SYMBOL(bcm_ll_pcie_dev_enable);
+EXPORT_SYMBOL(bcm_ll_pcie_dev_disable);
+EXPORT_SYMBOL(bcm_ll_pcie_host_reset_enable);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+EXPORT_SYMBOL(bcm_ll_pcie_setrace);
+EXPORT_SYMBOL(bcm_ll_pcie_cleartrace);
+EXPORT_SYMBOL(bcm_ll_pcie_savetrace);
+#endif
+module_init(bcm_ll_init_module);
+module_exit(bcm_ll_cleanup_module);
+
+MODULE_DESCRIPTION("maple line card");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.h b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.h
new file mode 100755
index 0000000..bd1a60e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.h
@@ -0,0 +1,134 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+/*
+ * bcm_llpcie.h - Low-level PCIe driver interface
+ */
+
+#ifndef BCMOLT_LLPCIE_H_
+#define BCMOLT_LLPCIE_H_
+
+#include "bcmos_system.h"
+#define MAPLE_MAX_DEVICES               BCMTR_MAX_OLTS
+
+/** Low-level device info */
+typedef struct bcmolt_ll_dev_info
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+    uint32_t        soc_ddr_length;     /**< Device DDR window size */
+    uint32_t        irq;                /**< Device irq number */
+    int             irq_connected;      /**< Device irq number connected */
+} bcm_ll_dev_info;
+
+/** Device PCIe link status change notification callback */
+typedef enum
+{
+    BCM_LL_PCIE_LINK_DOWN,             /**< PCIe link is down */
+    BCM_LL_PCIE_LINK_UP,               /**< PCIe link is up */
+} bcm_ll_pcie_link_status;
+
+/** Low-level device handle */
+typedef void *bcm_ll_pcie_dev;
+
+/** Status change indication */
+typedef void (*bcm_ll_pcie_status_change)(uint8_t dev_id, bcm_ll_pcie_link_status status);
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb);
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void);
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info);
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id);
+
+/* Initialize low-level PCIe driver
+ * \return
+ *   - 0=OK
+ *   - BCM_ERR_INTERNAL - failed to register with PCI subsystem
+ */
+bcmos_errno bcm_ll_pcie_init(void);
+
+/* Cleanup low-level PCIe driver */
+void bcm_ll_pcie_cleanup(void);
+
+/** Enable PCI access to device
+ * \param[in]   dev_id  Device id
+ * \return
+ *   - 0=OK
+ *   - BCM_ERR_PARM-dev_id is invalid
+ *   - BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_dev_enable(int dev_id);
+
+/** Disable PCI access to device
+ * \param[in]   dev_id  Device id
+ * \return
+ *   - 0=OK
+ *   - BCM_ERR_PARM-dev_id is invalid
+ */
+bcmos_errno bcm_ll_pcie_dev_disable(int dev_id);
+
+/** Enable/disable host reset for all PCIe interfaces (automatic
+ *  device reset when host is reset)
+ * \param[in]   enabled Whether or not hot reset should be enabled
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+/** Handle low-level trace on target
+ * \param[in]   dev_id  Device id
+ * \param[in]  lfile name for trace
+ * \return device handle or NULL if link is down
+ */
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename);
+#endif
+
+#endif
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.c b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.c
new file mode 100644
index 0000000..df6d3c0
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.c
@@ -0,0 +1,410 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+*/ 
+
+#include <vxWorks.h>
+#include <drv/pci/pciConfigLib.h>
+#include "bcmolt_llpcie.h"
+
+/* Define PCIE device BAR registers */
+#define BAR_REGS                        0
+#define BAR_DDR                         2
+#define BAR_SRAM                        4
+
+/* 
+Define PCIE device BAR space length:
+    bar 1 = 8  Mbyte register space 
+    bar 2 = 16 Mbyte DDR space 
+    bar 3 = 64 Kbyte SRAM space
+*/
+#define MAPLE_REGS_LENGTH                   0x00800000
+#define MAPLE_DDR_LENGTH                    0x01000000
+#define MAPLE_SRAM_LENGTH                   0x00010000
+
+/* Define special registers address */
+#ifdef TX_ENABLE_EVENT_TRACE
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO			0x064014U	
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI			0x064018U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT	0x064074U	
+#endif
+#define PCIE_REVISION_REGISTER_OFFSET       0x6406C /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_REVISION    */
+#define PCIE_STATUS_REGISTER_OFFSET         0x64068 /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
+#define PCIE_HARD_DEBUG_REGISTER_OFFSET     0x64204U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_HARD_DEBUG  */
+#define PCIE_INT_STATUS_REGISTER_OFFSET     0x69400 /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_STATUS        */
+#define PCIE_INT_CLEAR_MASK_OFFSET          0x6940C /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_MASK_CLEAR    */
+#define PCIE_INTR1_STATUS_REGISTER_OFFSET   0x69300 /* Interrupt Status Register */       	
+
+/* Maple device ID */
+#define PCIE_MAPLE_VENDOR_ID                0x14E4 /* PCIE_CFG_TYPE0_EP_SUBSYSTEM_ID_VENDOR_ID      */
+#define PCIE_MAPLE_DEVICE_ID                0x6862 
+#define PCIE_MAPLE_6863_SKU_DEVICE_ID       0x6863
+#define PCIE_MAPLE_EPON_DEVICE_ID           0x5554
+
+/* Define interrupt vector number according BCM53003 BSP */
+#define PCIE1_IV_0 86
+#define PCIE1_IV_1 87
+#define PCIE1_INT_LINE 4
+
+/* Maple device object struct */
+typedef struct  
+{
+    bcm_ll_dev_info  device;
+    bcmos_fastlock   lock;
+    int              err_status;
+    int              phylink;
+    int              prev_datalink;
+    int              datalink;
+    uint32_t         deviceid;  // start from 0
+    unsigned int    *traceaddr;
+    void  *pdev;
+    int pciBusNo;       /* PCI bus number */
+    int pciDevNo;       /* PCI device number */
+    int pciFuncNo;      /* PCI function number */
+    uint32_t dev_status_irq;
+} maple_device_info;
+
+/* Maple device objects */
+static maple_device_info devices[MAPLE_MAX_DEVICES];
+int crt_device = 0;
+
+/* Device PCIE interface status change callback */
+static bcm_ll_pcie_status_change callback;
+
+/** Device status change ISR
+ * \irq          IRQ number
+ * \dev_instance device object 
+ */
+int dev_status_interrupt (int irq, void *dev_instance)
+{
+    bcmos_errno err = BCM_ERR_OK;
+    uint32_t reg_value = 0;
+    maple_device_info *device_info = NULL;   
+    long flags = 0;
+    int handled = 0;
+    uint32_t dev_id = 0;
+    
+    device_info = (maple_device_info *)dev_instance;
+    dev_id = device_info->deviceid;
+    
+    flags = bcmos_fastlock_lock(&device_info->lock);
+
+    reg_value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
+    {
+        if (device_info->datalink != device_info->prev_datalink)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
+                printf("Device=%d : Link is up !!!\n", dev_id);
+            else
+            {
+                printf("Device=%d : Link is down !!!\n", dev_id);
+                printf("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
+            }
+            device_info->prev_datalink = device_info->datalink;
+            if (callback)
+            {
+                callback(dev_id, device_info->datalink); 
+            }
+        }
+        reg_value = bcm_pci_read32(
+                        (uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
+        {
+            handled = 1;
+        }
+    }
+    
+    bcmos_fastlock_unlock(&device_info->lock, flags);
+    
+    return handled;
+}
+
+/** Maple device detection and initialization
+ */
+bcmos_errno bcm_ll_pcie_interface_init()
+{
+    STATUS ret_status;
+    maple_device_info *dev_info = NULL; 
+    uint32_t readval = 0;
+    uint8_t readvalb = 0;
+    bcmos_errno err = BCM_ERR_OK;
+    uint8_t irq = 0;
+    uint16_t device_id;
+
+    printf("%s()\r\n", __FUNCTION__);
+
+    // check maple device number
+    if (crt_device == MAPLE_MAX_DEVICES)
+    {
+        printf(" Maximum Maple devices already defined (%d)\n", MAPLE_MAX_DEVICES);
+        return BCM_ERR_ALREADY;
+    } 
+    // Init device object struct
+    dev_info = &devices[crt_device++];
+    memset(dev_info, 0, sizeof(maple_device_info));
+    
+    // find maple 6862 device
+    ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+        PCIE_MAPLE_DEVICE_ID,
+        0,
+        &dev_info->pciBusNo,
+        &dev_info->pciDevNo,
+        &dev_info->pciFuncNo);
+
+    if (OK == ret_status)
+    {
+        device_id = PCIE_MAPLE_DEVICE_ID;
+        goto found_device_id;
+    }
+
+    // find maple 6863 device
+    ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+        PCIE_MAPLE_6863_SKU_DEVICE_ID,
+        0,
+        &dev_info->pciBusNo,
+        &dev_info->pciDevNo,
+        &dev_info->pciFuncNo);
+
+    if (OK == ret_status)
+    {
+        device_id = PCIE_MAPLE_6863_SKU_DEVICE_ID;
+        goto found_device_id;
+    }
+
+    // find maple epon device
+    ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+        PCIE_MAPLE_EPON_DEVICE_ID,
+        0,
+        &dev_info->pciBusNo,
+        &dev_info->pciDevNo,
+        &dev_info->pciFuncNo);
+
+    if (OK == ret_status)
+    {
+        device_id = PCIE_MAPLE_EPON_DEVICE_ID;
+        goto found_device_id;
+    }
+
+    printf("Can't find any device[%d]\n", PCIE_MAPLE_VENDOR_ID);
+    return BCM_ERR_NODEV;
+
+found_device_id:
+    printf("Found maple device[%x - %x]\n", PCIE_MAPLE_VENDOR_ID, device_id);
+
+    // init    
+    dev_info->deviceid = (crt_device - 1);
+    dev_info->pdev = NULL;
+
+
+    // Enable PCI address map
+    pciConfigInByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_COMMAND,
+                    (UINT8 *)&readvalb);
+    printf("CMD reg = 0x%x\n", readvalb);
+
+    readvalb |= 0x6;
+    pciConfigOutByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_COMMAND,
+                    (UINT8)readvalb);
+
+    pciConfigInByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_COMMAND,
+                    (UINT8 *)&readvalb);
+    printf("Adjusted CMD reg = 0x%x\n", readvalb);
+
+    // Init base addresses
+    dev_info->device.soc_regs_base = 0xe0000000;
+    dev_info->device.soc_sram_base = 0xe2000000;
+    dev_info->device.soc_ddr_base  = 0xe1000000;
+    dev_info->device.soc_ddr_length = 0x1000000; // 16M
+
+    // init interrupt line
+    readvalb = PCIE1_INT_LINE;
+    pciConfigOutByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_DEV_INT_LINE,
+                    (UINT8)readvalb);
+    pciConfigInByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_DEV_INT_LINE,
+                    (UINT8 *)&readvalb);
+    printf("Adjusted INT Line reg = 0x%x\n", readvalb);
+
+    // init interrupt
+    dev_info->device.irq = PCIE1_IV_0;
+    dev_info->dev_status_irq = PCIE1_IV_1;
+
+    // read revision register
+    readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
+    printf("readval = 0x%x\n", readval);
+    printf("Card %d version major=%02x minor=%02x\n",
+                dev_info->deviceid, 
+                ((readval & 0x0000ff00) >> 8),
+                (readval & 0x000000ff)); 
+    
+    // read status register
+    readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+    printf("readval = 0x%x\n", readval);
+    dev_info->err_status = (readval & 0x0000000f);
+    dev_info->phylink    = ((readval >> 4) & 0x1);
+    dev_info->datalink   = ((readval >> 5) & 0x1);
+    dev_info->prev_datalink  = dev_info->datalink;
+
+    // connect INT for device status
+    bcmos_fastlock_init(&dev_info->lock, 0);
+    bcmos_int_connect((int)dev_info->dev_status_irq, 
+                        0, 
+                        BCMOS_IRQ_SHARED, 
+                        dev_status_interrupt, 
+                        "status_isr", 
+                        dev_info);
+
+    return BCM_ERR_OK;
+}
+
+/** Get Maple device object struct
+ * \crt devie index,start from 0
+ */
+static maple_device_info *get_maple_pci_info(int crt)
+{
+    bcmos_errno err = BCM_ERR_OK;
+    uint32_t readval = 0;
+    maple_device_info *device_info = NULL;
+
+    /* check input parameter */
+    if (MAPLE_MAX_DEVICES <= crt)
+    {
+        return NULL;
+    }
+    device_info = &devices[crt];
+
+    /* read status register */
+    readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+    device_info->err_status = (readval & 0x0000000f);
+    device_info->phylink    = ((readval >> 4) & 0x1);
+    device_info->datalink   = ((readval >> 5) & 0x1);
+
+    /* return device */
+    return device_info;
+}
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0 
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
+{
+    int i;
+    maple_device_info *dev_info; 
+    
+    callback = cb;
+    for (i = 0; i < crt_device; i++)
+    {
+        dev_info = get_maple_pci_info(i);
+        callback(i, dev_info->datalink);
+    }
+    
+    return BCM_ERR_OK;
+}
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void)
+{
+    callback = NULL;
+    
+    return BCM_ERR_OK;
+}
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
+{
+    maple_device_info *dev_info; 
+    
+    if (NULL == info)
+    {
+        return BCM_ERR_PARM;
+    }
+    
+    if (dev_id < crt_device)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        if (dev_info->datalink == BCM_LL_PCIE_LINK_DOWN)
+        {
+            return BCM_ERR_IO;
+        }
+
+        *info = dev_info->device;
+        return BCM_ERR_OK;
+    }
+    
+    return BCM_ERR_RANGE;   
+}
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
+{
+    maple_device_info *dev_info; 
+    
+    if (dev_id < MAPLE_MAX_DEVICES)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        return dev_info->pdev;
+    } 
+    
+    return NULL;
+}
+
+/** Host reset enable 
+ * \enabled 
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
+{
+    uint32_t val;
+
+    val = enabled ? 0 : 1;
+    bcm_pci_write32((uint32_t *)(devices[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET) , val);
+
+    return BCM_ERR_OK;
+}
+
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.h b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.h
new file mode 100644
index 0000000..d484976
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.h
@@ -0,0 +1,105 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+/*
+ * bcm_llpcie.h - Low-level PCIe driver interface
+ */
+
+#ifndef BCMOLT_LLPCIE_H_
+#define BCMOLT_LLPCIE_H_
+
+#include "bcmos_system.h"
+#define MAPLE_MAX_DEVICES               1 /* 5 */
+
+/** Low-level device info */
+typedef struct bcmolt_ll_dev_info
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+    uint32_t        soc_ddr_length;     /**< Device DDR window size */
+    uint32_t        irq;                /**< Device irq number */
+} bcm_ll_dev_info;
+
+/** Device PCIe link status change notification callback */
+typedef enum
+{
+    BCM_LL_PCIE_LINK_DOWN,             /**< PCIe link is down */
+    BCM_LL_PCIE_LINK_UP,               /**< PCIe link is up */
+} bcm_ll_pcie_link_status;
+
+/** Low-level device handle */
+typedef void *bcm_ll_pcie_dev;
+
+/** Status change indication */
+typedef void (*bcm_ll_pcie_status_change)(uint8_t dev_id, bcm_ll_pcie_link_status status);
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb);
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void);
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info);
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id);
+
+/** Enable/disable host reset for all PCIe interfaces (automatic
+ *  device reset when host is reset)
+ * \param[in]   enabled Whether or not hot reset should be enabled
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+/** Handle low-level trace on target
+ * \param[in]   dev_id  Device id
+ * \param[in]  lfile name for trace
+ * \return device handle or NULL if link is down
+ */
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename);
+#endif
+#endif
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.c b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.c
new file mode 100755
index 0000000..1de7475
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.c
@@ -0,0 +1,505 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+*/ 
+
+#include <vxWorks.h>
+#include <drv/pci/pciConfigLib.h>
+#include "bcmolt_llpcie.h"
+
+/* Define PCIE device BAR registers */
+#define BAR_REGS                        0
+#define BAR_DDR                         2
+#define BAR_SRAM                        4
+
+/* 
+Define PCIE device BAR space length:
+    bar 0 = 8  Mbyte register space 
+    bar 2 = 16 Mbyte DDR space 
+    bar 4 = 64 Kbyte SRAM space
+*/
+#define MAPLE_REGS_LENGTH                   0x00800000
+#define MAPLE_DDR_LENGTH                    0x01000000
+#define MAPLE_SRAM_LENGTH                   0x00010000
+
+/* Define special registers address */
+#ifdef TX_ENABLE_EVENT_TRACE
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO			0x064014U	
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI			0x064018U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT	0x064074U	
+#endif
+#define PCIE_REVISION_REGISTER_OFFSET       0x6406C /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_REVISION    */
+#define PCIE_STATUS_REGISTER_OFFSET         0x64068 /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
+#define PCIE_HARD_DEBUG_REGISTER_OFFSET     0x64204U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_HARD_DEBUG  */
+#define PCIE_INT_STATUS_REGISTER_OFFSET     0x69400 /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_STATUS        */
+#define PCIE_INT_CLEAR_MASK_OFFSET          0x6940C /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_MASK_CLEAR    */
+#define PCIE_INTR1_STATUS_REGISTER_OFFSET   0x69300 /* Interrupt Status Register */       	
+
+/* Maple device ID */
+#define PCIE_MAPLE_VENDOR_ID                0x14E4 /* PCIE_CFG_TYPE0_EP_SUBSYSTEM_ID_VENDOR_ID      */
+#define PCIE_MAPLE_DEVICE_ID                0x6862 
+#define PCIE_MAPLE_6863_SKU_DEVICE_ID       0x6863
+#define PCIE_MAPLE_EPON_DEVICE_ID           0x5554
+
+/* Define interrupt vector number for MPC8308 */
+#define DRV_PCIE_INT_IRQ_BASE 96
+#define PCIE_DEV0_IV_0   (DRV_PCIE_INT_IRQ_BASE + 24)
+#define PCIE_DEV0_IV_1   (DRV_PCIE_INT_IRQ_BASE + 25)
+#define PCIE_DEV1_IV_0   (DRV_PCIE_INT_IRQ_BASE + 0)
+#define PCIE_DEV1_IV_1   (DRV_PCIE_INT_IRQ_BASE + 1)
+
+/* Maple device object struct */
+typedef struct  
+{
+    uint32_t llpcie_irq;
+    uint32_t llpcie_status_irq;
+} maple_llpcie_device_irqs;
+
+maple_llpcie_device_irqs llpcie_device_irqs[BCMOLT_MAX_MAPLE_DEVICES] =
+{
+    {PCIE_DEV0_IV_0,PCIE_DEV0_IV_1},
+    {PCIE_DEV1_IV_0,PCIE_DEV1_IV_1}
+};
+
+
+#ifdef LLPCIE_SET_BASE_ADDRESSES_MANUALLY 
+
+typedef struct 
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+
+} maple_llpcie_base_addresses;
+
+maple_llpcie_base_addresses llpcie_base_addresses[BCMOLT_MAX_MAPLE_DEVICES] =
+{
+     {.soc_regs_base = 0xe0000000, .soc_sram_base = 0xe2000000, .soc_ddr_base  = 0xe1000000},
+     /* in this example there is only one device*/
+     {.soc_regs_base = 0x00000000, .soc_sram_base = 0x00000000, .soc_ddr_base  = 0x00000000}
+};
+#endif
+
+/* Maple device object struct */
+typedef struct  
+{
+    bcm_ll_dev_info  device;
+    bcmos_fastlock   lock;
+    int              err_status;
+    int              phylink;
+    int              prev_datalink;
+    int              datalink;
+    uint32_t         deviceid;  // start from 0
+    unsigned int    *traceaddr;
+    void  *pdev;
+    int pciBusNo;       /* PCI bus number */
+    int pciDevNo;       /* PCI device number */
+    int pciFuncNo;      /* PCI function number */
+    uint32_t dev_status_irq;
+} maple_device_info;
+
+/* Maple device objects */
+maple_device_info g_maple_devs_info[BCMOLT_MAX_MAPLE_DEVICES];
+
+int g_maple_dev_num = 0;
+
+/* Device PCIE interface status change callback */
+bcm_ll_pcie_status_change g_dev_status_change_cb;
+
+/** Device status change ISR
+ * \irq          IRQ number
+ * \dev_instance device object 
+ */
+int dev_status_interrupt (int irq, void *dev_instance)
+{
+    uint32_t reg_value = 0;
+    maple_device_info *device_info = NULL;   
+    long flags = 0;
+    int handled = 0;
+    uint32_t dev_id = 0;
+    
+    device_info = (maple_device_info *)dev_instance;
+    dev_id = device_info->deviceid;
+    
+    flags = bcmos_fastlock_lock(&device_info->lock);
+
+    reg_value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
+    {
+        if (device_info->datalink != device_info->prev_datalink)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
+                printf("Device=%d : Link is up !!!\n", dev_id);
+            else
+            {
+                printf("Device=%d : Link is down !!!\n", dev_id);
+                printf("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
+            }
+            device_info->prev_datalink = device_info->datalink;
+            if (g_dev_status_change_cb)
+            {
+                g_dev_status_change_cb(dev_id, device_info->datalink); 
+            }
+        }
+        reg_value = bcm_pci_read32(
+                        (uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
+        {
+            handled = 1;
+        }
+    }
+    
+    bcmos_fastlock_unlock(&device_info->lock, flags);
+    
+    return handled;
+}
+
+/** Maple device detection and initialization
+ */
+bcmos_errno bcm_ll_pcie_interface_init()
+{
+    STATUS ret_status;
+    maple_device_info *dev_info = NULL; 
+    uint32_t readval = 0;
+    uint8_t readvalb = 0;
+    uint32_t pci_dev_idx = 0;
+
+    printf("%s()\r\n", __FUNCTION__);
+
+    // check maple device number
+    if (g_maple_dev_num >= BCMOLT_MAX_MAPLE_DEVICES)
+    {
+        printf("Maximum Maple devices already defined (%d)\n", BCMOLT_MAX_MAPLE_DEVICES);
+        return BCM_ERR_ALREADY;
+    } 
+
+    // Support multiple Maple devices
+    for (pci_dev_idx = 0; pci_dev_idx < BCMOLT_MAX_MAPLE_DEVICES; pci_dev_idx++)
+    {
+        uint16_t device_id;
+
+        // Init device object struct
+        dev_info = &g_maple_devs_info[pci_dev_idx];
+        memset(dev_info, 0, sizeof(maple_device_info));
+        
+        // Try to find maple device
+        ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+            PCIE_MAPLE_DEVICE_ID,
+            pci_dev_idx,
+            &dev_info->pciBusNo,
+            &dev_info->pciDevNo,
+            &dev_info->pciFuncNo);
+
+        if (ret_status == OK)
+        {
+            device_id = PCIE_MAPLE_DEVICE_ID;
+            goto found_device_id;
+        }
+
+        ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+            PCIE_MAPLE_6863_SKU_DEVICE_ID,
+            pci_dev_idx,
+            &dev_info->pciBusNo,
+            &dev_info->pciDevNo,
+            &dev_info->pciFuncNo);
+
+        if (ret_status == OK)
+        {
+            device_id = PCIE_MAPLE_6863_SKU_DEVICE_ID;
+            goto found_device_id;
+        }
+
+        ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+            PCIE_MAPLE_EPON_DEVICE_ID,
+            pci_dev_idx,
+            &dev_info->pciBusNo,
+            &dev_info->pciDevNo,
+            &dev_info->pciFuncNo);
+
+        if (ret_status == OK)
+        {
+            device_id = PCIE_MAPLE_EPON_DEVICE_ID;
+            goto found_device_id;
+        }
+
+        printf("No more devices, Found %d maple device(s)\n", g_maple_dev_num);
+        break;
+
+found_device_id:
+        // Found new Maple device
+        printf("Found maple device[%x - %x][%d] @ Bus %d, Dev %d, Func %d\n", 
+            PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_DEVICE_ID, pci_dev_idx,
+            dev_info->pciBusNo, dev_info->pciDevNo, dev_info->pciFuncNo);
+        g_maple_dev_num += 1;
+        
+        // init    
+        dev_info->deviceid = pci_dev_idx;
+        dev_info->pdev = NULL;        
+    
+
+        // Enable PCI address map
+        pciConfigInByte(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_COMMAND,
+                        (UINT8 *)&readvalb);
+        printf("CMD reg = 0x%x\n", readvalb);
+
+        readvalb |= 0x6;
+        pciConfigOutByte(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_COMMAND,
+                        (UINT8)readvalb);
+
+        pciConfigInByte(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_COMMAND,
+                        (UINT8 *)&readvalb);
+        printf("Adjusted CMD reg = 0x%x\n", readvalb);
+
+        // Init base addresses
+
+#ifdef LLPCIE_SET_BASE_ADDRESSES_MANUALLY 
+       dev_info->device.soc_regs_base = llpcie_base_addresses.soc_regs_base;
+       dev_info->device.soc_sram_base = llpcie_base_addresses.soc_sram_base;
+       dev_info->device.soc_ddr_base  = llpcie_base_addresses.soc_ddr_base;
+       dev_info->device.soc_ddr_length = MAPLE_DDR_LENGTH; // 16M */
+#else
+        pciConfigInLong(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_BASE_ADDRESS_0,
+                        (UINT32 *)&readval);
+        printf("BAR0 = 0x%x\n", readval);
+        dev_info->device.soc_regs_base = (readval & PCI_MEMBASE_MASK);
+
+        pciConfigInLong(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_BASE_ADDRESS_2,
+                        (UINT32 *)&readval);
+        printf("BAR2 = 0x%x\n", readval);
+        dev_info->device.soc_ddr_base = (readval & PCI_MEMBASE_MASK);
+        dev_info->device.soc_ddr_length = MAPLE_DDR_LENGTH;         // 16M           
+
+        pciConfigInLong(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_BASE_ADDRESS_4,
+                        (UINT32 *)&readval);
+        printf("BAR4 = 0x%x\n", readval);
+        dev_info->device.soc_sram_base = (readval & PCI_MEMBASE_MASK);   
+#endif             
+
+        printf("Regs Base = 0x%lx, DDR Base = 0x%lx, DDR Length = 0x%x, SRAM Base = 0x%lx\n",
+            dev_info->device.soc_regs_base,
+            dev_info->device.soc_ddr_base,
+            dev_info->device.soc_ddr_length,
+            dev_info->device.soc_sram_base);
+
+        // init interrupt
+        dev_info->device.irq = llpcie_device_irqs[pci_dev_idx].llpcie_irq;
+        dev_info->dev_status_irq = llpcie_device_irqs[pci_dev_idx].llpcie_status_irq;
+        printf("DMA IRQ = %d, Device status IRQ = %d\n", 
+            dev_info->device.irq, dev_info->dev_status_irq);
+                
+        // read revision register
+        readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
+        printf("readval = 0x%x\n", readval);
+        printf("Card %d version major=%02x minor=%02x\n",
+                    dev_info->deviceid, 
+                    ((readval & 0x0000ff00) >> 8),
+                    (readval & 0x000000ff)); 
+        
+        // read status register
+        readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+        printf("readval = 0x%x\n", readval);
+        dev_info->err_status = (readval & 0x0000000f);
+        dev_info->phylink    = ((readval >> 4) & 0x1);
+        dev_info->datalink   = ((readval >> 5) & 0x1);
+        dev_info->prev_datalink  = dev_info->datalink;
+
+        // connect INT for device status
+        bcmos_fastlock_init(&dev_info->lock, 0);
+        bcmos_int_connect((int)dev_info->dev_status_irq, 
+                            0, 
+                            BCMOS_IRQ_SHARED, 
+                            dev_status_interrupt, 
+                            "status_isr", 
+                            dev_info);
+    }
+
+    // Return status
+    if (0 >=g_maple_dev_num)
+    {
+        return BCM_ERR_NODEV;
+    }
+    else
+    {
+        return BCM_ERR_OK;
+    }
+}
+
+/** Get Maple device object struct
+ * \crt devie index,start from 0
+ */
+static maple_device_info *get_maple_pci_info(int crt)
+{
+    bcmos_errno err = BCM_ERR_OK;
+    uint32_t readval = 0;
+    maple_device_info *device_info = NULL;
+
+    /* check input parameter */
+    /* don't access invalid device regs base address */
+    if (crt >= g_maple_dev_num)
+    {
+        return NULL;
+    }
+    device_info = &g_maple_devs_info[crt];
+
+    /* read status register */
+    readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+    device_info->err_status = (readval & 0x0000000f);
+    device_info->phylink    = ((readval >> 4) & 0x1);
+    device_info->datalink   = ((readval >> 5) & 0x1);
+
+    /* return device */
+    return device_info;
+}
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0 
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
+{
+    int i;
+    maple_device_info *dev_info; 
+    
+    g_dev_status_change_cb = cb;
+    for (i = 0; i < g_maple_dev_num; i++)
+    {
+        dev_info = get_maple_pci_info(i);
+        g_dev_status_change_cb(i, dev_info->datalink);
+    }
+    
+    return BCM_ERR_OK;
+}
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void)
+{
+    g_dev_status_change_cb = NULL;
+    
+    return BCM_ERR_OK;
+}
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
+{
+    maple_device_info *dev_info = NULL; 
+
+    /* check input parameter */    
+    if (NULL == info)
+    {
+        return BCM_ERR_PARM;
+    }
+
+    /* don't access invalid device regs base address */
+    if (dev_id < g_maple_dev_num)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        if (NULL == dev_info)
+        {
+            return BCM_ERR_NOENT;
+        }
+        if (dev_info->datalink == BCM_LL_PCIE_LINK_DOWN)
+        {
+            return BCM_ERR_IO;
+        }
+
+        *info = dev_info->device;
+        return BCM_ERR_OK;
+    }
+    
+    return BCM_ERR_RANGE;   
+}
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
+{
+    maple_device_info *dev_info = NULL; 
+
+    /* check input parameter */
+    /* don't access invalid device regs base address */
+    if (dev_id < g_maple_dev_num)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        if (NULL == dev_info)
+        {
+            return NULL;
+        }
+        else
+        {
+            return dev_info->pdev;
+        }
+    } 
+    
+    return NULL;
+}
+
+/** Host reset enable 
+ * \enabled 
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
+{
+    uint32_t val;
+
+    /* check input parameter */
+    /* don't access invalid device regs base address */
+    if (dev_id >= g_maple_dev_num)
+    {
+        return BCM_ERR_OVERFLOW;
+    }
+    
+    val = enabled ? 0 : 1;
+    bcm_pci_write32((uint32_t *)(g_maple_devs_info[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET), 
+            val);
+
+    return BCM_ERR_OK;
+}
+
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.h b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.h
new file mode 100755
index 0000000..040d565
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.h
@@ -0,0 +1,105 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+   Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+   All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+   As a special exception, the copyright holders of this software give
+   you permission to link this software with independent modules, and
+   to copy and distribute the resulting executable under terms of your
+   choice, provided that you also meet, for each linked independent
+   module, the terms and conditions of the license of that module.
+   An independent module is a module which is not derived from this
+   software.  The special exception does not apply to any modifications
+   of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+/*
+ * bcm_llpcie.h - Low-level PCIe driver interface
+ */
+
+#ifndef BCMOLT_LLPCIE_H_
+#define BCMOLT_LLPCIE_H_
+
+#include "bcmos_system.h"
+#define BCMOLT_MAX_MAPLE_DEVICES               2 /* 5 */
+
+/** Low-level device info */
+typedef struct bcmolt_ll_dev_info
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+    uint32_t        soc_ddr_length;     /**< Device DDR window size */
+    uint32_t        irq;                /**< Device irq number */
+} bcm_ll_dev_info;
+
+/** Device PCIe link status change notification callback */
+typedef enum
+{
+    BCM_LL_PCIE_LINK_DOWN,             /**< PCIe link is down */
+    BCM_LL_PCIE_LINK_UP,               /**< PCIe link is up */
+} bcm_ll_pcie_link_status;
+
+/** Low-level device handle */
+typedef void *bcm_ll_pcie_dev;
+
+/** Status change indication */
+typedef void (*bcm_ll_pcie_status_change)(uint8_t dev_id, bcm_ll_pcie_link_status status);
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb);
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void);
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info);
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id);
+
+/** Enable/disable host reset for all PCIe interfaces (automatic
+ *  device reset when host is reset)
+ * \param[in]   enabled Whether or not hot reset should be enabled
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+/** Handle low-level trace on target
+ * \param[in]   dev_id  Device id
+ * \param[in]  lfile name for trace
+ * \return device handle or NULL if link is down
+ */
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename);
+#endif
+#endif