BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_customized/user_config/Makefile b/bcm68620_release/release/host_customized/user_config/Makefile
new file mode 100644
index 0000000..1db59e8
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/Makefile
@@ -0,0 +1,16 @@
+#
+# user_config
+#
+MOD_NAME = user_config
+MOD_DEPS = common_api fld ll_pcie
+
+ifeq ("$(OS_KERNEL)", "linux")
+    MOD_TYPE = linux_lib
+else
+    MOD_TYPE = lib
+endif
+
+ifneq ("$(BOARD)", "")
+    srcs = board/$(BOARD)/bcmolt_user_utils.c
+    MOD_DEPS += i2c_devs board_selector
+endif
diff --git a/bcm68620_release/release/host_customized/user_config/bcmolt_user_utils.h b/bcm68620_release/release/host_customized/user_config/bcmolt_user_utils.h
new file mode 100644
index 0000000..ff32e36
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/bcmolt_user_utils.h
@@ -0,0 +1,75 @@
+/*
+<: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.
+
+:>
+ */
+
+#ifndef _BCMOLT_USER_UTILS_H_
+#define _BCMOLT_USER_UTILS_H_
+
+#include <bcmolt_model_types.h>
+#include <bcmos_system.h>
+#include <bcmolt_msg.h>
+#include <bcmolt_fld.h>
+
+/* Validate that the given system mode is supported for the given device.
+ * This function returns BCM_ERR_OK if the system mode is valid or a different error code otherwise. */
+bcmos_errno bcmuser_system_mode_validate(bcmolt_devid device, bcmolt_system_mode system_mode);
+
+/* Read file from a file system into a buffer. */
+int bcmuser_image_read(
+    bcmolt_devid device,
+    bcmolt_device_image_type image_type,
+    uint32_t offset,
+    uint8_t *buf,
+    uint32_t buf_size);
+
+/* Turn off the processor of the embedded device. */
+bcmos_errno bcmuser_device_off(bcmolt_devid device);
+
+/* Turn on the processor of the embedded device. */
+bcmos_errno bcmuser_device_on(bcmolt_devid device);
+
+/* Check whether or not the embedded device processor is running. */
+bcmos_errno bcmuser_device_is_running(bcmolt_devid device, bcmos_bool *is_cpu_on);
+
+/* Prepare the PCIe bus for communication with the embedded devices */
+bcmos_errno bcmuser_pcie_prepare(void);
+
+/* Prepare the PCIe channel for communication with the embedded device.
+ * For example, this function may re-enumerate the PCI-E bus. */
+bcmos_errno bcmuser_pcie_channel_prepare(bcmolt_devid device);
+
+bcmos_errno bcmuser_pcie_channel_prepare_for_kt2(bcmolt_devid device);
+
+/* Remove the PCIe channel for communication with the embedded device.
+ * For example, this function may re-enumerate the PCI-E bus. */
+bcmos_errno bcmuser_pcie_channel_remove(bcmolt_devid device);
+
+/* Reset the host processor. */
+bcmos_errno bcmuser_host_reset(void);
+
+#endif
diff --git a/bcm68620_release/release/host_customized/user_config/board/wrx/bcmolt_user_utils.c b/bcm68620_release/release/host_customized/user_config/board/wrx/bcmolt_user_utils.c
new file mode 100644
index 0000000..94f58a9
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board/wrx/bcmolt_user_utils.c
@@ -0,0 +1,533 @@
+/*
+<: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 <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <bcmos_system.h>
+#include <bcm_config.h>
+#include <bcmolt_msg.h>
+#include <bcmolt_fld.h>
+#include <bcmolt_llpcie.h>
+#include <bcmolt_conv.h>
+#include <bcmolt_i2c_devs.h>
+#include <bcmolt_board_selector.h>
+#include "bcmolt_user_utils.h"
+
+#define BCM_I2C_DEV_ADDR_START typedef enum {
+#define BCM_I2C_DEV_ADDR(name, desc, val) name = val,
+#define BCM_I2C_DEV_ADDR_END } bcm_i2c_dev_addr;
+#include <bcmolt_i2c_devs_addr.h>
+
+#define BOOT_FILE                       "/opt/bcm68620/bcm68620_boot.bin"
+#define APPL_FILE                       "/opt/bcm68620/bcm68620_appl.bin"
+#define ONU_FW_FILE                     "/opt/bcm68620/dummy_onu_firmware.bin"
+
+#define FPGA_REG_FPGA_VERSION 0x0
+#define FPGA_REG_BOARD_CONF 0x1
+#define FPGA_REG_RESETS 0x2
+
+#define FPGA_RST_BIT_DEVICE 0x0
+#define FPGA_DEVICE_SWITCH  4
+
+#define FPGA_ENABLE_ALL_DEVICES 0x1f
+#define FPGA_ENABLE_SWITCH              (1 << FPGA_DEVICE_SWITCH)
+/* For now swap devices for consistency with PCI enumeration */
+#define FPGA_DEVICE_RESET_BIT(dev)      (1 << (FPGA_RST_BIT_DEVICE + dev))
+
+/* Minimum required FPGA version for reading default system mode via BOARD_CONF register. */
+#define FPGA_VER_FOR_SVK_CONFIG 6
+
+/* Lock that protects critical sections */
+static bcmos_mutex user_lock;
+static bcmos_bool user_lock_initialized;
+
+typedef enum
+{
+    SVK_BOARD_ID_1    = 0x7, /* SVK #1 - BCM968620S: all PON flavors supported, SFP+ */
+    SVK_BOARD_ID_2_XG = 0x6, /* SVK #2 - BCM968620XG: XGPON */
+    SVK_BOARD_ID_2_XE = 0x5, /* SVK #2 - BCM968620XE: 10G EPON */
+    SVK_BOARD_ID_3    = 0x4, /* SVK #3 - BCM968620K: all PON flavors supported, XFP */
+    DVT_BOARD_ID      = 0x3, /* DVT board */
+} svk_board_id;
+
+typedef enum
+{
+    SVK_MODE_GPON_16X     = 0xF, /* SVK #1/3: 16x GPON mode, SVK #2: only valid mode */
+    SVK_MODE_EPON_1G_16X  = 0xE, /* SVK #1/3: 16x 1G EPON mode */
+    SVK_MODE_XGPON        = 0xD, /* SVK #1/3: 8x XGPON mode */
+    SVK_MODE_EPON_10G_8X  = 0xC, /* SVK #1/3: 8x 10G EPON mode */
+    SVK_MODE_EPON_GPON_8X = 0xB, /* SVK #1/3: 8x 10G EPON + 8x GPON coexistence mode */
+} svk_mode;
+
+
+#define CHECK_RETURN_ERROR(cond,rc) \
+		do { \
+			if (cond) {\
+				bcmos_printf("%s#%d: failed with rc=%d\n", __FUNCTION__, __LINE__, rc);\
+				return rc;\
+			}\
+		} while (0)
+
+
+static void userlock_lock(void)
+{
+    if (!user_lock_initialized)
+    {
+        bcmos_mutex_create(&user_lock, 0, "reset_lock");
+        user_lock_initialized = BCMOS_TRUE;
+    }
+    bcmos_mutex_lock(&user_lock);
+}
+
+
+static void userlock_unlock(void)
+{
+    bcmos_mutex_unlock(&user_lock);
+}
+
+static struct file *file_open(const char *path, int flags)
+{
+    struct file *fd = NULL;
+    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+    fd = filp_open(path, flags, mode);
+    if(IS_ERR(fd))
+        return NULL;
+    return fd;
+}
+
+static void file_close(struct file *file)
+{
+    filp_close(file, NULL);
+}
+
+static int file_read(struct file *file, uint32_t offset, uint8_t *data, unsigned int size)
+{
+    unsigned long long o = offset;
+    mm_segment_t oldfs;
+    int bytes_read;
+
+    oldfs = get_fs();
+    set_fs(get_ds());
+    bytes_read = vfs_read(file, data, size, &o);
+    set_fs(oldfs);
+    if (bytes_read < 0)
+    {
+        BCMOS_TRACE_ERR("vfs_read returned error %d\n", bytes_read);
+        return (int)BCM_ERR_IO;
+    }
+    return bytes_read;
+}
+
+static int file_write(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size)
+{
+    mm_segment_t oldfs;
+    int ret;
+
+    oldfs = get_fs();
+    set_fs(get_ds());
+
+    ret = vfs_write(file, data, size, &offset);
+
+    set_fs(oldfs);
+    return ret;
+}
+
+static bcmos_errno file_write_1(const char *path)
+{
+    struct file *fd;
+    char to_write[] = { '1' };
+    loff_t pos = 0;
+    ssize_t bytes_written;
+
+    fd = file_open(path, O_WRONLY);
+    if ((fd == NULL) || (fd == (void *)-ENOENT)) /* -ENOENT; No such file or directory */
+    {
+        BCMOS_TRACE_ERR("Can't open file %s for writing. Error %s\n",
+            path, bcmos_strerror(fd == NULL ? BCM_ERR_NULL : BCM_ERR_NOENT));
+        return (fd == NULL ? BCM_ERR_NULL : BCM_ERR_NOENT);
+    }
+
+    bytes_written = file_write(fd, pos, to_write, sizeof(to_write));
+    if (bytes_written != sizeof(to_write))
+    {
+        BCMOS_TRACE_ERR("vfs_write returned incorrect number of characters written: %d\n", bytes_written);
+    }
+
+    file_close(fd);
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno i2c_fpga_read(uint32_t reg, uint32_t *val)
+{
+    return maple_i2c_read_fpga(maple_i2c_get_client(FPGA_I2C_ADDR), reg, val);
+}
+
+static bcmos_errno i2c_fpga_write(uint32_t reg, uint32_t val)
+{
+    return maple_i2c_write_fpga(maple_i2c_get_client(FPGA_I2C_ADDR), reg, val);
+}
+
+static bcmos_errno i2c_config_switch(void)
+{
+    uint8_t to_write = 1;
+    int ret;
+
+    ret = maple_i2c_write(maple_i2c_get_client(I2C_SW0_I2C_ADDR), &to_write, 1);
+    if (ret != 0)
+    {
+        BCMOS_TRACE_ERR("Failed to write switch: %d\n", ret);
+        return BCM_ERR_INTERNAL;
+    }
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno i2c_fpga_version_get(uint32_t *version)
+{
+    return i2c_fpga_read(FPGA_REG_FPGA_VERSION, version);
+}
+
+static bcmos_errno i2c_svk_config_get(svk_board_id *board_id, svk_mode *mode)
+{
+    uint32_t val;
+    bcmos_errno rc;
+
+    rc = i2c_fpga_read(FPGA_REG_BOARD_CONF, &val);
+    if (rc == BCM_ERR_OK)
+    {
+        *board_id = (svk_board_id)(val & 0x7);
+        *mode = (svk_mode)((val >> 4) & 0xF);
+    }
+
+    return rc;
+}
+
+static bcmos_errno i2c_device_cpu_state_set(bcmolt_devid device, bcmos_bool is_on)
+{
+    bcmos_errno rc;
+    uint32_t reset_values;
+
+    /* Prevent race condition when this function is called for 2 devices simultaneously */
+    userlock_lock();
+
+    do
+    {
+        rc = i2c_config_switch();
+        if (rc)
+            break;
+
+        /* Read-modify-write so we can set only the relevant bit */
+        rc = i2c_fpga_read(FPGA_REG_RESETS, &reset_values);
+        if (rc)
+            break;
+
+        if (is_on)
+            reset_values |= FPGA_DEVICE_RESET_BIT(device);
+        else
+            reset_values &= ~FPGA_DEVICE_RESET_BIT(device);
+
+        rc = i2c_fpga_write(FPGA_REG_RESETS, reset_values);
+
+    } while (0);
+
+    userlock_unlock();
+
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    bcmos_usleep(1000);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_bool bcmuser_system_mode_is_valid(bcmolt_system_mode system_mode, svk_board_id board_id, svk_mode svk_mode)
+{
+    switch (board_id)
+    {
+    case SVK_BOARD_ID_1:
+    case SVK_BOARD_ID_3:
+        switch (svk_mode)
+        {
+        case SVK_MODE_GPON_16X:
+            return (system_mode == BCMOLT_SYSTEM_MODE_GPON__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_GPON__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_GPON__16_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_GPON_8_XGPON_4_X_COEXISTENCE ||
+                    system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_NGPON2__8_X_2_P_5_G);
+        case SVK_MODE_EPON_1G_16X:
+            return (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__16_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__2_X_10_G ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_10_G ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_10_G);
+        case SVK_MODE_XGPON:
+            return (system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_NGPON2__8_X_2_P_5_G);
+        case SVK_MODE_EPON_10G_8X:
+            return
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__2_X_10_G) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_10_G) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_10_G);
+        default:
+            return BCMOS_FALSE;
+        }
+    case SVK_BOARD_ID_2_XG:
+        return (system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__8_X ||
+                system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__4_X ||
+                system_mode == BCMOLT_SYSTEM_MODE_NGPON2__8_X_2_P_5_G ||
+                system_mode == BCMOLT_SYSTEM_MODE_XGS__2_X_10_G ||
+                system_mode == BCMOLT_SYSTEM_MODE_NGPON2__2_X_10_G);
+    case SVK_BOARD_ID_2_XE:
+        return
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_AE_8_X) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__2_X_10_G) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_10_G) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_10_G);
+    case DVT_BOARD_ID:
+        return BCMOS_TRUE;
+    default:
+        return BCMOS_FALSE;
+    }
+}
+
+bcmos_errno bcmuser_system_mode_validate(bcmolt_devid device, bcmolt_system_mode system_mode)
+{
+    bcmos_errno rc;
+    uint32_t version;
+    svk_board_id board_id;
+    svk_mode svk_mode;
+
+    rc = i2c_config_switch();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    rc = i2c_fpga_version_get(&version);
+    if (rc != BCM_ERR_OK)
+    {
+        BCMOS_TRACE_INFO("Failed to read FPGA version\n");
+        return rc;
+    }
+
+    if (version < FPGA_VER_FOR_SVK_CONFIG)
+    {
+        /* this FPGA version don't support reading the SVK version, so we must assume it's OK */
+        return BCM_ERR_OK;
+    }
+
+    rc = i2c_svk_config_get(&board_id, &svk_mode);
+    if (rc != BCM_ERR_OK)
+    {
+        BCMOS_TRACE_INFO("Failed to read SVK config\n");
+        return rc;
+    }
+
+    if (bcmuser_system_mode_is_valid(system_mode, board_id, svk_mode))
+    {
+        return BCM_ERR_OK;
+    }
+    else
+    {
+        BCMOS_TRACE_INFO(
+            "System mode %s is not supported for board ID %d, SVK mode %d\n",
+            bcmolt_system_mode_name(system_mode),
+            board_id,
+            svk_mode);
+        return BCM_ERR_NOT_SUPPORTED;
+    }
+}
+
+int bcmuser_image_read(bcmolt_devid device, bcmolt_device_image_type image_type,
+    uint32_t offset, uint8_t *buf, uint32_t buf_size)
+{
+    struct file *fd;
+    int bytes_read;
+    bcmos_errno rc;
+    static int2str_t image_type2str[] =
+    {
+        {BCMOLT_DEVICE_IMAGE_TYPE_BOOTLOADER, BOOT_FILE},
+        {BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION, APPL_FILE},
+        {BCMOLT_DEVICE_IMAGE_TYPE_ITU_PON_ONU_FIRMWARE, ONU_FW_FILE},
+        {-1}
+    };
+    const char *filename;
+
+    filename = int2str(image_type2str, image_type);
+    fd = file_open(filename, O_RDONLY);
+    if ((fd == NULL) || (fd == (void *)-ENOENT)) /* -ENOENT; No such file or directory */
+    {
+        rc = (fd == NULL ? BCM_ERR_NULL : BCM_ERR_NOENT);
+        BCMOS_TRACE_ERR("filp_open returned error %s (%d)\n", bcmos_strerror(rc), rc);
+        return rc;
+    }
+    bytes_read = file_read(fd, offset, buf, buf_size);
+    file_close(fd);
+    if (bytes_read < 0)
+    {
+        return (int)BCM_ERR_IO;
+    }
+    return bytes_read;
+}
+
+bcmos_errno bcmuser_device_off(bcmolt_devid device)
+{
+    /* Ignore request for non-existing device */
+    if (device >= bcmolt_board_num_maple_devices())
+        return BCM_ERR_OK;
+    BCMOS_TRACE_INFO("device=%u\n", device);
+    return i2c_device_cpu_state_set(device, BCMOS_FALSE);
+}
+
+bcmos_errno bcmuser_device_on(bcmolt_devid device)
+{
+    bcmos_errno rc;
+
+    BCMOS_TRACE_INFO("device=%u\n", device);
+    if (device >= bcmolt_board_num_maple_devices())
+        return BCM_ERR_RANGE;
+
+    rc = i2c_device_cpu_state_set(device, BCMOS_TRUE);
+    /* Wait a moment to make sure the device is discoverable in case it just booted. */
+    bcmos_usleep(50 * 1000);
+
+    return rc;
+}
+
+bcmos_errno bcmuser_device_is_running(bcmolt_devid device, bcmos_bool *is_running)
+{
+    bcmos_errno rc;
+    uint32_t reset_values;
+    uint32_t version;
+
+    rc = i2c_config_switch();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    rc = i2c_fpga_version_get(&version);
+    if (rc != BCM_ERR_OK)
+    {
+        BCMOS_TRACE_INFO("Failed to read FPGA version\n");
+        return rc;
+    }
+    if (!bcmolt_board_supports_standalone(version))
+    {
+        /* For older FPGAs that don't support standalone mode, the device is taken out of reset at boot.  We need to lie
+           and tell device control that it's not running, so it will be programmed from scratch. */
+        BCMOS_TRACE_INFO("FPGA version %d doesn't support standalone mode\n", version);
+        *is_running = BCMOS_FALSE;
+        return BCM_ERR_OK;
+    }
+
+    rc = i2c_fpga_read(FPGA_REG_RESETS, &reset_values);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    *is_running = ((reset_values & FPGA_DEVICE_RESET_BIT(device)) != 0);
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcmuser_host_reset(void)
+{
+    bcm_ll_pcie_cleanup();
+    kernel_restart(NULL);
+    return BCM_ERR_OK; /* will never be reached */
+}
+
+bcmos_errno bcmuser_pcie_prepare(void)
+{
+    bcmos_errno rc;
+    uint32_t reset_values;
+    const char *pcie_rescan_file = bcmolt_board_pci_rescan_string_get();
+    int i;
+
+    /* - Take all devices out of reset
+     * - rescan bus
+     * - restore reset value
+     */
+
+    rc = i2c_config_switch();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    /* Read-modify-write so we can set only the relevant bit */
+    rc = i2c_fpga_read(FPGA_REG_RESETS, &reset_values);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    rc = i2c_fpga_write(FPGA_REG_RESETS, FPGA_ENABLE_ALL_DEVICES);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    bcmos_usleep(50000);
+
+    /* Now recan PCI bus */
+    /* Now re-enumerate the PCI bus by writing a 1 to the 'rescan' file. */
+    rc = file_write_1(pcie_rescan_file);
+    if (rc != BCM_ERR_OK)
+        BCMOS_TRACE_ERR("file write returned error %s (%d)\n", bcmos_strerror(rc), rc);
+    bcmos_usleep(100 * 1000);
+
+    /* Now initialize ll_pcie driver and map maple devices */
+    rc = bcm_ll_pcie_init();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    /* Now restore rest values. Keep switch out of reset */
+    for (i = 0; i < bcmolt_board_num_maple_devices(); i++)
+    {
+        if ((FPGA_DEVICE_RESET_BIT(i) & reset_values) == 0)
+            bcmuser_pcie_channel_remove(i);
+    }
+    rc = i2c_fpga_write(FPGA_REG_RESETS, reset_values | FPGA_ENABLE_SWITCH);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    return 0;
+}
+
+bcmos_errno bcmuser_pcie_channel_prepare(bcmolt_devid device)
+{
+    bcmos_errno rc;
+
+    rc = bcm_ll_pcie_dev_enable(device);
+    if (rc)
+        BCMOS_TRACE_ERR("Couldn't prepare device %d. Error %s\n", device, bcmos_strerror(rc));
+
+    return rc;
+}
+
+bcmos_errno bcmuser_pcie_channel_remove(bcmolt_devid device)
+{
+    bcm_ll_pcie_dev_disable(device);
+    return BCM_ERR_OK;
+}
diff --git a/bcm68620_release/release/host_customized/user_config/board_selector/Makefile b/bcm68620_release/release/host_customized/user_config/board_selector/Makefile
new file mode 100644
index 0000000..bfbfe46
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board_selector/Makefile
@@ -0,0 +1,15 @@
+#
+# board_selector
+#
+MOD_NAME = board_selector
+MOD_SUPPRESS_OS_DEP = y
+
+ifeq ("$(OS_KERNEL)", "linux")
+    MOD_TYPE = linux_lib
+else
+    MOD_TYPE = lib
+endif
+
+ifneq ("$(BOARD)", "")
+    srcs = $(BOARD)/bcmolt_board_selector.c
+endif
diff --git a/bcm68620_release/release/host_customized/user_config/board_selector/bcmolt_board_selector.h b/bcm68620_release/release/host_customized/user_config/board_selector/bcmolt_board_selector.h
new file mode 100644
index 0000000..74a8103
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board_selector/bcmolt_board_selector.h
@@ -0,0 +1,61 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmolt_board_selector.h
+ */
+
+#ifndef _BCMOLT_BOARD_SELECTOR_H_
+#define _BCMOLT_BOARD_SELECTOR_H_
+
+#include <bcmos_system.h>
+
+/* bus, devfn --> device mapping table */
+typedef struct
+{
+    int bus;
+    int devfn;
+    int device;
+} bus_devfn_devid;
+
+/* Get PCI rescan string. It is used in linux to rescan PCIe bus */
+const char *bcmolt_board_pci_rescan_string_get(void);
+
+/* Get bus, devfn --> dev_id mapping table.
+ * The table is terminated by row with bus=-1,devfn=-1
+ */
+const bus_devfn_devid *bcmolt_board_pci_map_table_get(void);
+
+/* Return TRUE if board supports Maple-standalone mode */
+bcmos_bool bcmolt_board_supports_standalone(uint32_t version);
+
+/* Returns number of maple devices on the board */
+uint8_t bcmolt_board_num_maple_devices(void);
+
+#endif /* _BCMOLT_BOARD_SELECTOR_H_ */
diff --git a/bcm68620_release/release/host_customized/user_config/board_selector/wrx/bcmolt_board_selector.c b/bcm68620_release/release/host_customized/user_config/board_selector/wrx/bcmolt_board_selector.c
new file mode 100644
index 0000000..c997a12
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board_selector/wrx/bcmolt_board_selector.c
@@ -0,0 +1,113 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmolt_board_selector.c
+ */
+
+#include <linux/fs.h>
+#include "bcmolt_board_selector.h"
+
+static bus_devfn_devid bus_devfn_devid_table_svk4[] = {
+    { 5, 0, 0},
+    { 3, 0, 1},
+    {-1,-1,-1},
+};
+
+static bus_devfn_devid bus_devfn_devid_table_svk1_3[] = {
+    { 3, 0, 0},
+    {-1,-1,-1},
+};
+
+#define SVK4_IDENT_FILE                 "/etc/svk4"
+
+#define PCIE_DEVICE_RESCAN_FILE_SVK4    "/sys/bus/pci/devices/0000:02:00.0/rescan"
+#define PCIE_DEVICE_RESCAN_FILE_SVK1_3  "/sys/bus/pci/devices/0000:02:01.0/rescan"
+
+/* Minimum required FPGA version for standalone mode (host / embedded processors running disconnected). */
+#define FPGA_VER_FOR_STANDALONE 7
+
+static struct file *file_open(const char *path, int flags)
+{
+    struct file *fd = NULL;
+    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+    fd = filp_open(path, flags, mode);
+    if(IS_ERR(fd))
+        return NULL;
+    return fd;
+}
+
+static void file_close(struct file *file)
+{
+    filp_close(file, NULL);
+}
+
+static bcmos_bool can_read_file(const char *path)
+{
+    struct file *fd = file_open(path, O_RDONLY);
+    if ((fd == NULL) || (fd == (void *)-ENOENT)) /* -ENOENT; No such file or directory */
+    {
+        return BCMOS_FALSE;
+    }
+
+    file_close(fd);
+    return BCMOS_TRUE;
+}
+
+static bcmos_bool board_is_svk4(void)
+{
+    return can_read_file(SVK4_IDENT_FILE);
+}
+
+/* Get PCI rescan string. It is used in linux to rescan PCIe bus */
+const char *bcmolt_board_pci_rescan_string_get(void)
+{
+    return board_is_svk4() ? PCIE_DEVICE_RESCAN_FILE_SVK4 : PCIE_DEVICE_RESCAN_FILE_SVK1_3;
+}
+
+/* Get bus, devfn --> dev_id mapping table.
+ * The table is terminated by row with bus=-1,devfn=-1
+ */
+const bus_devfn_devid *bcmolt_board_pci_map_table_get(void)
+{
+    return board_is_svk4() ? bus_devfn_devid_table_svk4 : bus_devfn_devid_table_svk1_3;
+}
+
+/* Return TRUE if board supports Maple-standalone mode */
+bcmos_bool bcmolt_board_supports_standalone(uint32_t version)
+{
+    return board_is_svk4() || version >= FPGA_VER_FOR_STANDALONE;
+}
+
+/* Returns number of maple devices on the board */
+uint8_t bcmolt_board_num_maple_devices(void)
+{
+    return board_is_svk4() ? 2 : 1;
+}