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, ®ion, 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", ®);
+ 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", ®);
+ 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, ®);
+ 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