/* 
 | 
 * Misc utility routines for accessing chip-specific features 
 | 
 * of the BOOKER NCI (non coherent interconnect) based Broadcom chips. 
 | 
 * 
 | 
 * Broadcom Proprietary and Confidential. Copyright (C) 2020, 
 | 
 * All Rights Reserved. 
 | 
 * 
 | 
 * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Broadcom; 
 | 
 * the contents of this file may not be disclosed to third parties, 
 | 
 * copied or duplicated in any form, in whole or in part, without 
 | 
 * the prior written permission of Broadcom. 
 | 
 * 
 | 
 * 
 | 
 * <<Broadcom-WL-IPTag/Proprietary:>> 
 | 
 */ 
 | 
  
 | 
#include <typedefs.h> 
 | 
#include <hndsoc.h> 
 | 
#include <sbchipc.h> 
 | 
#include <pcicfg.h> 
 | 
#include <pcie_core.h> 
 | 
#include "siutils_priv.h" 
 | 
#include <nci.h> 
 | 
#include <bcmdevs.h> 
 | 
#include <hndoobr.h> 
 | 
  
 | 
#define NCI_BAD_REG            0xbbadd000u    /* Bad Register Address */ 
 | 
#define NCI_BAD_INDEX            -1        /* Bad Index */ 
 | 
  
 | 
#define OOBR_BASE_MASK            0x00001FFFu    /* Mask to get Base address of OOBR */ 
 | 
#define EROM1_BASE_MASK            0x00000FFFu    /* Mask to get Base address of EROM1 */ 
 | 
  
 | 
/* Core Info */ 
 | 
#define COREINFO_COREID_MASK        0x00000FFFu    /* Bit-11 to 0 */ 
 | 
#define COREINFO_REV_MASK        0x000FF000u    /* Core Rev Mask */ 
 | 
#define COREINFO_REV_SHIFT        12u        /* Bit-12 */ 
 | 
#define COREINFO_MFG_MASK        0x00F00000u    /* Core Mfg Mask */ 
 | 
#define COREINFO_MFG_SHIFT        20u        /* Bit-20 */ 
 | 
#define COREINFO_BPID_MASK        0x07000000u    /* 26-24 Gives Backplane ID */ 
 | 
#define COREINFO_BPID_SHIFT        24u        /* Bit:26-24 */ 
 | 
#define COREINFO_ISBP_MASK        0x08000000u    /* Is Backplane or Bridge */ 
 | 
#define COREINFO_ISBP_SHIFT        27u        /* Bit:27 */ 
 | 
  
 | 
/* Interface Config */ 
 | 
#define IC_IFACECNT_MASK        0x0000F000u    /* No of Interface Descriptor Mask */ 
 | 
#define IC_IFACECNT_SHIFT        12u        /* Bit-12 */ 
 | 
#define IC_IFACEOFFSET_MASK        0x00000FFFu    /* OFFSET for 1st Interface Descriptor */ 
 | 
  
 | 
/* DMP Reg Offset */ 
 | 
#define DMP_DMPCTRL_REG_OFFSET        8u 
 | 
  
 | 
/* Interface Descriptor Masks */ 
 | 
#define ID_NODEPTR_MASK            0xFFFFFFF8u    /* Master/Slave Network Interface Addr */ 
 | 
#define ID_NODETYPE_MASK        0x00000007u    /* 0:Booker 1:IDM 1-0xf:Reserved */ 
 | 
#define ID_WORDOFFSET_MASK        0xF0000000u    /* WordOffset to next Iface Desc in EROM2 */ 
 | 
#define ID_WORDOFFSET_SHIFT        28u        /* WordOffset bits 31-28 */ 
 | 
#define ID_CORETYPE_MASK        0x08000000u    /* CORE belongs to OOBR(0) or EROM(1) */ 
 | 
#define ID_CORETYPE_SHIFT        27u        /* Bit-27 */ 
 | 
#define ID_MI_MASK            0x04000000u    /* 0: Slave Interface, 1:Master Interface */ 
 | 
#define ID_MI_SHIFT            26u        /* Bit-26 */ 
 | 
#define ID_NADDR_MASK            0x03000000u    /* No of Slave Address Regions */ 
 | 
#define ID_NADDR_SHIFT            24u        /* Bit:25-24 */ 
 | 
#define ID_BPID_MASK            0x00F00000u    /* Give Backplane ID */ 
 | 
#define ID_BPID_SHIFT            20u        /* Bit:20-23 */ 
 | 
#define ID_COREINFOPTR_MASK        0x00001FFFu    /* OOBR or EROM Offset */ 
 | 
#define ID_ENDMARKER            0xFFFFFFFFu    /* End of EROM Part 2 */ 
 | 
  
 | 
/* Slave Port Address Descriptor Masks */ 
 | 
#define SLAVEPORT_BASE_ADDR_MASK    0xFFFFFF00u    /* Bits 31:8 is the base address */ 
 | 
#define SLAVEPORT_BOUND_ADDR_MASK    0x00000040u    /* Addr is not 2^n and with bound addr */ 
 | 
#define SLAVEPORT_BOUND_ADDR_SHIFT    6u        /* Bit-6 */ 
 | 
#define SLAVEPORT_64BIT_ADDR_MASK    0x00000020u    /* 64-bit base and bound fields */ 
 | 
#define SLAVEPORT_64BIT_ADDR_SHIFT    5u        /* Bit-5 */ 
 | 
#define SLAVEPORT_ADDR_SIZE_MASK    0x0000001Fu    /* Address Size mask */ 
 | 
#define SLAVEPORT_ADDR_TYPE_BOUND    0x1u        /* Bound Addr */ 
 | 
#define SLAVEPORT_ADDR_TYPE_64        0x2u        /* 64-Bit Addr */ 
 | 
#define SLAVEPORT_ADDR_MIN_SHIFT    0x8u 
 | 
/* Address space Size of the slave port */ 
 | 
#define SLAVEPORT_ADDR_SIZE(adesc)    (1u << ((adesc & SLAVEPORT_ADDR_SIZE_MASK) + \ 
 | 
            SLAVEPORT_ADDR_MIN_SHIFT)) 
 | 
  
 | 
#define GET_NEXT_EROM_ADDR(addr)    ((uint32*)((uintptr)(addr) + 4u)) 
 | 
  
 | 
#define NCI_DEFAULT_CORE_UNIT        (0u) 
 | 
  
 | 
/* Error Codes */ 
 | 
enum { 
 | 
    NCI_OK                = 0, 
 | 
    NCI_BACKPLANE_ID_MISMATCH    = -1, 
 | 
    NCI_INVALID_EROM2PTR        = -2, 
 | 
    NCI_WORDOFFSET_MISMATCH        = -3, 
 | 
    NCI_NOMEM            = -4, 
 | 
    NCI_MASTER_INVALID_ADDR        = -5 
 | 
}; 
 | 
  
 | 
#define GET_OOBR_BASE(erom2base)    ((erom2base) & ~OOBR_BASE_MASK) 
 | 
#define GET_EROM1_BASE(erom2base)    ((erom2base) & ~EROM1_BASE_MASK) 
 | 
#define CORE_ID(core_info)        ((core_info) & COREINFO_COREID_MASK) 
 | 
#define GET_INFACECNT(iface_cfg)    (((iface_cfg) & IC_IFACECNT_MASK) >> IC_IFACECNT_SHIFT) 
 | 
#define GET_NODEPTR(iface_desc_0)    ((iface_desc_0) & ID_NODEPTR_MASK) 
 | 
#define GET_NODETYPE(iface_desc_0)    ((iface_desc_0) & ID_NODETYPE_MASK) 
 | 
#define GET_WORDOFFSET(iface_desc_1)    (((iface_desc_1) & ID_WORDOFFSET_MASK) \ 
 | 
                    >> ID_WORDOFFSET_SHIFT) 
 | 
#define IS_MASTER(iface_desc_1)        (((iface_desc_1) & ID_MI_MASK) >> ID_MI_SHIFT) 
 | 
#define GET_CORETYPE(iface_desc_1)    (((iface_desc_1) & ID_CORETYPE_MASK) >> ID_CORETYPE_SHIFT) 
 | 
#define GET_NUM_ADDR_REG(iface_desc_1)    (((iface_desc_1) & ID_NADDR_MASK) >> ID_NADDR_SHIFT) 
 | 
#define GET_COREOFFSET(iface_desc_1)    ((iface_desc_1) & ID_COREINFOPTR_MASK) 
 | 
#define ADDR_SIZE(sz)            ((1u << ((sz) + 8u)) - 1u) 
 | 
  
 | 
#define CORE_REV(core_info)        ((core_info) & COREINFO_REV_MASK) >> COREINFO_REV_SHIFT 
 | 
#define CORE_MFG(core_info)        ((core_info) & COREINFO_MFG_MASK) >> COREINFO_MFG_SHIFT 
 | 
#define COREINFO_BPID(core_info)    (((core_info) & COREINFO_BPID_MASK) >> COREINFO_BPID_SHIFT) 
 | 
#define IS_BACKPLANE(core_info)        (((core_info) & COREINFO_ISBP_MASK) >> COREINFO_ISBP_SHIFT) 
 | 
#define ID_BPID(iface_desc_1)        (((iface_desc_1) & ID_BPID_MASK) >> ID_BPID_SHIFT) 
 | 
#define IS_BACKPLANE_ID_SAME(core_info, iface_desc_1) \ 
 | 
                    (COREINFO_BPID((core_info)) == ID_BPID((iface_desc_1))) 
 | 
  
 | 
#define NCI_WORD_SIZE            (4u) 
 | 
#define PCI_ACCESS_SIZE            (4u) 
 | 
  
 | 
#define NCI_ADDR2NUM(addr)        ((uintptr)(addr)) 
 | 
#define NCI_ADD_NUM(addr, size)        (NCI_ADDR2NUM(addr) + (size)) 
 | 
#ifdef DONGLEBUILD 
 | 
#define NCI_ADD_ADDR(addr, size)    ((uint32*)REG_MAP(NCI_ADD_NUM((addr), (size)), 0u)) 
 | 
#else /* !DONGLEBUILD */ 
 | 
#define NCI_ADD_ADDR(addr, size)    ((uint32*)(NCI_ADD_NUM((addr), (size)))) 
 | 
#endif /* DONGLEBUILD */ 
 | 
#define NCI_INC_ADDR(addr, size)    ((addr) = NCI_ADD_ADDR((addr), (size))) 
 | 
  
 | 
#define NODE_TYPE_BOOKER        0x0u 
 | 
#define NODE_TYPE_NIC400        0x1u 
 | 
  
 | 
#define BP_BOOKER            0x0u 
 | 
#define BP_NIC400            0x1u 
 | 
#define BP_APB1                0x2u 
 | 
#define BP_APB2                0x3u 
 | 
#define BP_CCI400            0x4u 
 | 
  
 | 
#define PCIE_WRITE_SIZE            4u 
 | 
  
 | 
static const char BACKPLANE_ID_NAME[][11] = { 
 | 
    "BOOKER", 
 | 
    "NIC400", 
 | 
    "APB1", 
 | 
    "APB2", 
 | 
    "CCI400", 
 | 
    "\0" 
 | 
}; 
 | 
  
 | 
#define APB_INF(ifd)    ((ID_BPID((ifd).iface_desc_1) == BP_APB1) || \ 
 | 
    (ID_BPID((ifd).iface_desc_1) == BP_APB2)) 
 | 
#define BOOKER_INF(ifd)    (ID_BPID((ifd).iface_desc_1) == BP_BOOKER) 
 | 
#define NIC_INF(ifd)    (ID_BPID((ifd).iface_desc_1) == BP_NIC400) 
 | 
  
 | 
/* BOOKER NCI LOG LEVEL */ 
 | 
#define NCI_LOG_LEVEL_ERROR        0x1u 
 | 
#define NCI_LOG_LEVEL_TRACE        0x2u 
 | 
#define NCI_LOG_LEVEL_INFO        0x4u 
 | 
#define NCI_LOG_LEVEL_PRINT        0x8u 
 | 
  
 | 
#ifndef NCI_DEFAULT_LOG_LEVEL 
 | 
#define NCI_DEFAULT_LOG_LEVEL    (NCI_LOG_LEVEL_ERROR) 
 | 
#endif /* NCI_DEFAULT_LOG_LEVEL */ 
 | 
  
 | 
uint32 nci_log_level = NCI_DEFAULT_LOG_LEVEL; 
 | 
  
 | 
#ifdef DONGLEBUILD 
 | 
#define NCI_ERROR(args) do { if (nci_log_level & NCI_LOG_LEVEL_ERROR) { printf args; } } while (0u) 
 | 
#define NCI_TRACE(args) do { if (nci_log_level & NCI_LOG_LEVEL_TRACE) { printf args; } } while (0u) 
 | 
#define NCI_INFO(args)  do { if (nci_log_level & NCI_LOG_LEVEL_INFO) { printf args; } } while (0u) 
 | 
#define NCI_PRINT(args) do { if (nci_log_level & NCI_LOG_LEVEL_PRINT) { printf args; } } while (0u) 
 | 
#else /* !DONGLEBUILD */ 
 | 
#define NCI_KERN_PRINT(...) printk(KERN_ERR __VA_ARGS__) 
 | 
#define NCI_ERROR(args) do { if (nci_log_level & NCI_LOG_LEVEL_ERROR) \ 
 | 
        { NCI_KERN_PRINT args; } } while (0u) 
 | 
#define NCI_TRACE(args) do { if (nci_log_level & NCI_LOG_LEVEL_TRACE) \ 
 | 
        { NCI_KERN_PRINT args; } } while (0u) 
 | 
#define NCI_INFO(args)  do { if (nci_log_level & NCI_LOG_LEVEL_INFO) \ 
 | 
        { NCI_KERN_PRINT args; } } while (0u) 
 | 
#define NCI_PRINT(args)  do { if (nci_log_level & NCI_LOG_LEVEL_PRINT) \ 
 | 
            { NCI_KERN_PRINT args; } } while (0u) 
 | 
#endif /* DONGLEBUILD */ 
 | 
  
 | 
#define NCI_EROM_WORD_SIZEOF        4u 
 | 
#define NCI_REGS_PER_CORE        2u 
 | 
  
 | 
#define NCI_EROM1_LEN(erom2base)    (erom2base - GET_EROM1_BASE(erom2base)) 
 | 
#define NCI_NONOOBR_CORES(erom2base)    NCI_EROM1_LEN(erom2base) \ 
 | 
                        /(NCI_REGS_PER_CORE * NCI_EROM_WORD_SIZEOF) 
 | 
  
 | 
/* AXI ID to CoreID + unit mappings */ 
 | 
typedef struct nci_axi_to_coreidx { 
 | 
    uint coreid; 
 | 
    uint coreunit; 
 | 
} nci_axi_to_coreidx_t; 
 | 
  
 | 
static const nci_axi_to_coreidx_t axi2coreidx_4397[] = { 
 | 
    {CC_CORE_ID, 0},     /* 00 Chipcommon */ 
 | 
    {PCIE2_CORE_ID, 0},    /* 01 PCIe */ 
 | 
    {D11_CORE_ID, 0},    /* 02 D11 Main */ 
 | 
    {ARMCR4_CORE_ID, 0},    /* 03 ARM */ 
 | 
    {BT_CORE_ID, 0},    /* 04 BT AHB */ 
 | 
    {D11_CORE_ID, 1},    /* 05 D11 Aux */ 
 | 
    {D11_CORE_ID, 0},    /* 06 D11 Main l1 */ 
 | 
    {D11_CORE_ID, 1},    /* 07 D11 Aux  l1 */ 
 | 
    {D11_CORE_ID, 0},    /* 08 D11 Main l2 */ 
 | 
    {D11_CORE_ID, 1},    /* 09 D11 Aux  l2 */ 
 | 
    {NODEV_CORE_ID, 0},    /* 10 M2M DMA */ 
 | 
    {NODEV_CORE_ID, 0},    /* 11 unused */ 
 | 
    {NODEV_CORE_ID, 0},    /* 12 unused */ 
 | 
    {NODEV_CORE_ID, 0},    /* 13 unused */ 
 | 
    {NODEV_CORE_ID, 0},    /* 14 unused */ 
 | 
    {NODEV_CORE_ID, 0}    /* 15 unused */ 
 | 
}; 
 | 
  
 | 
typedef struct slave_port { 
 | 
    uint32        adesc;        /**< Address Descriptor 0 */ 
 | 
    uint32        addrl;        /**< Lower Base */ 
 | 
    uint32        addrh;        /**< Upper Base */ 
 | 
    uint32        extaddrl;    /**< Lower Bound */ 
 | 
    uint32        extaddrh;    /**< Ubber Bound */ 
 | 
} slave_port_t; 
 | 
  
 | 
typedef struct interface_desc { 
 | 
    slave_port_t    *sp;        /**< Slave Port Addr 0-3 */ 
 | 
  
 | 
    uint32        iface_desc_0;    /**< Interface-0 Descriptor Word0 */ 
 | 
    /* If Node Type 0-Booker xMNI/xSNI address. If Node Type 1-DMP wrapper Address */ 
 | 
    uint32        node_ptr;    /**< Core's Node pointer */ 
 | 
  
 | 
    uint32        iface_desc_1;    /**< Interface Descriptor Word1 */ 
 | 
    uint8        num_addr_reg;    /**< Number of Slave Port Addr (Valid only if master=0) */ 
 | 
    uint8        coretype;    /**< Core Belongs to 0:OOBR 1:Without OOBR */ 
 | 
    uint8        master;        /**< 1:Master 0:Slave */ 
 | 
  
 | 
    uint8        node_type;    /**< 0:Booker , 1:IDM Wrapper, 2-0xf: Reserved */ 
 | 
} interface_desc_t; 
 | 
  
 | 
typedef struct nci_cores { 
 | 
    void        *regs; 
 | 
    /* 2:0-Node type (0-booker,1-IDM Wrapper) 31:3-Interconnect registyer space */ 
 | 
    interface_desc_t *desc;        /**< Interface & Address Descriptors */ 
 | 
    /* 
 | 
     * 11:0-CoreID, 19:12-RevID 23:20-MFG 26:24-Backplane ID if 
 | 
     * bit 27 is 1 (Core is Backplane or Bridge ) 
 | 
     */ 
 | 
    uint32        coreinfo;    /**< CoreInfo of each core */ 
 | 
    /* 
 | 
     * 11:0 - Offosewt of 1st Interface desc in EROM 15:12 - No. 
 | 
     * of interfaces attachedto this core 
 | 
     */ 
 | 
    uint32        iface_cfg;    /**< Interface config Reg */ 
 | 
    uint32        dmp_regs_off;    /**< DMP control & DMP status @ 0x48 from coreinfo */ 
 | 
    uint32        coreid;        /**< id of each core */ 
 | 
    uint8        coreunit;    /**< Unit differentiate same coreids */ 
 | 
    uint8        iface_cnt;    /**< no of Interface connected to each core */ 
 | 
    uint8        PAD[2u]; 
 | 
} nci_cores_t; 
 | 
  
 | 
typedef struct nci_info { 
 | 
    void        *osh;        /**< osl os handle */ 
 | 
    nci_cores_t    *cores;        /**< Cores Parsed */ 
 | 
    void        *pci_bar_addr;    /**< PCI BAR0 Window */ 
 | 
    uint32        cc_erom2base;    /**< Base of EROM2 from ChipCommon */ 
 | 
    uint32        *erom1base;    /**< Base of EROM1 */ 
 | 
    uint32        *erom2base;    /**< Base of EROM2 */ 
 | 
    uint32        *oobr_base;    /**< Base of OOBR */ 
 | 
    uint16        bustype;    /**< SI_BUS, PCI_BUS */ 
 | 
    uint8        max_cores;    /**< # Max cores indicated by Register */ 
 | 
    uint8        num_cores;    /**< # discovered cores */ 
 | 
    uint8        refcnt;        /**< Allocation reference count  */ 
 | 
    uint8        scan_done;    /**< Set to TRUE when erom scan is done. */ 
 | 
    uint8        PAD[2]; 
 | 
} nci_info_t; 
 | 
  
 | 
#define NI_IDM_RESET_ENTRY 0x1 
 | 
#define NI_IDM_RESET_EXIT  0x0 
 | 
  
 | 
/* AXI Slave Network Interface registers */ 
 | 
typedef volatile struct asni_regs { 
 | 
    uint32 node_type;    /* 0x000 */ 
 | 
    uint32 node_info;    /* 0x004 */ 
 | 
    uint32 secr_acc;    /* 0x008 */ 
 | 
    uint32 pmusela;        /* 0x00c */ 
 | 
    uint32 pmuselb;        /* 0x010 */ 
 | 
    uint32 PAD[11]; 
 | 
    uint32 node_feat;    /* 0x040 */ 
 | 
    uint32 bursplt;        /* 0x044 */ 
 | 
    uint32 addr_remap;    /* 0x048 */ 
 | 
    uint32 PAD[13]; 
 | 
    uint32 sildbg;        /* 0x080 */ 
 | 
    uint32 qosctl;        /* 0x084 */ 
 | 
    uint32 wdatthrs;    /* 0x088 */ 
 | 
    uint32 arqosovr;    /* 0x08c */ 
 | 
    uint32 awqosovr;    /* 0x090 */ 
 | 
    uint32 atqosot;        /* 0x094 */ 
 | 
    uint32 arqosot;        /* 0x098 */ 
 | 
    uint32 awqosot;        /* 0x09c */ 
 | 
    uint32 axqosot;        /* 0x0a0 */ 
 | 
    uint32 qosrdpk;        /* 0x0a4 */ 
 | 
    uint32 qosrdbur;    /* 0x0a8 */ 
 | 
    uint32 qosrdavg;    /* 0x0ac */ 
 | 
    uint32 qoswrpk;        /* 0x0b0 */ 
 | 
    uint32 qoswrbur;    /* 0x0b4 */ 
 | 
    uint32 qoswravg;    /* 0x0b8 */ 
 | 
    uint32 qoscompk;    /* 0x0bc */ 
 | 
    uint32 qoscombur;    /* 0x0c0 */ 
 | 
    uint32 qoscomavg;    /* 0x0c4 */ 
 | 
    uint32 qosrbbqv;    /* 0x0c8 */ 
 | 
    uint32 qoswrbqv;    /* 0x0cc */ 
 | 
    uint32 qoscombqv;    /* 0x0d0 */ 
 | 
    uint32 PAD[11]; 
 | 
    uint32 idm_device_id;    /* 0x100 */ 
 | 
    uint32 PAD[15]; 
 | 
    uint32 idm_reset_ctrl;    /* 0x140 */ 
 | 
} asni_regs_t; 
 | 
  
 | 
/* AXI Master Network Interface registers */ 
 | 
typedef volatile struct amni_regs { 
 | 
    uint32 node_type;        /* 0x000 */ 
 | 
    uint32 node_info;        /* 0x004 */ 
 | 
    uint32 secr_acc;        /* 0x008 */ 
 | 
    uint32 pmusela;            /* 0x00c */ 
 | 
    uint32 pmuselb;            /* 0x010 */ 
 | 
    uint32 PAD[11]; 
 | 
    uint32 node_feat;        /* 0x040 */ 
 | 
    uint32 PAD[15]; 
 | 
    uint32 sildbg;            /* 0x080 */ 
 | 
    uint32 qosacc;            /* 0x084 */ 
 | 
    uint32 PAD[26]; 
 | 
    uint32 interrupt_status;    /* 0x0f0 */ 
 | 
    uint32 interrupt_mask;        /* 0x0f4 */ 
 | 
    uint32 interrupt_status_ns;    /* 0x0f8 */ 
 | 
    uint32 interrupt_mask_ns;    /* 0x0FC */ 
 | 
    uint32 idm_device_id;        /* 0x100 */ 
 | 
    uint32 PAD[15]; 
 | 
    uint32 idm_reset_ctrl;        /* 0x140 */ 
 | 
} amni_regs_t; 
 | 
  
 | 
#define NCI_SPINWAIT_TIMEOUT        (300u) 
 | 
  
 | 
/* DMP/io control and DMP/io status */ 
 | 
typedef struct dmp_regs { 
 | 
    uint32 dmpctrl; 
 | 
    uint32 dmpstatus; 
 | 
} dmp_regs_t; 
 | 
  
 | 
#ifdef _RTE_ 
 | 
static nci_info_t *knci_info = NULL; 
 | 
#endif /* _RTE_ */ 
 | 
  
 | 
static void nci_save_iface1_reg(interface_desc_t *desc, uint32 iface_desc_1); 
 | 
static uint32* nci_save_slaveport_addr(nci_info_t *nci, 
 | 
    interface_desc_t *desc, uint32 *erom2ptr); 
 | 
static int nci_get_coreunit(nci_cores_t *cores, uint32 numcores, uint cid, 
 | 
    uint32 iface_desc_1); 
 | 
static nci_cores_t* nci_initial_parse(nci_info_t *nci, uint32 *erom2ptr, uint32 *core_idx); 
 | 
static void _nci_setcoreidx_pcie_bus(si_t *sih, volatile void **regs, uint32 curmap, 
 | 
    uint32 curwrap); 
 | 
static volatile void *_nci_setcoreidx(si_t *sih, uint coreidx); 
 | 
static uint32 _nci_get_curwrap(nci_info_t *nci, uint coreidx, uint wrapper_idx); 
 | 
static uint32 nci_get_curwrap(nci_info_t *nci, uint coreidx); 
 | 
static uint32 _nci_get_curmap(nci_info_t *nci, uint coreidx, uint slave_port_idx, uint base_idx); 
 | 
static uint32 nci_get_curmap(nci_info_t *nci, uint coreidx); 
 | 
static void _nci_core_reset(const si_t *sih, uint32 bits, uint32 resetbits); 
 | 
#if defined (AXI_TIMEOUTS) || defined (AXI_TIMEOUTS_NIC) 
 | 
static void nci_reset_APB(const si_info_t *sii, aidmp_t *ai, int *ret, 
 | 
    uint32 errlog_status, uint32 errlog_id); 
 | 
static void nci_reset_axi_to(const si_info_t *sii, aidmp_t *ai); 
 | 
#endif /* (AXI_TIMEOUTS) ||  (AXI_TIMEOUTS_NIC) */ 
 | 
static uint32 nci_find_numcores(si_t *sih); 
 | 
#ifdef BOOKER_NIC400_INF 
 | 
static int32 nci_find_first_wrapper_idx(nci_info_t *nci, uint32 coreidx); 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
  
 | 
/* 
 | 
 * Description : This function will search for a CORE with matching 'core_id' and mismatching 
 | 
 * 'wordoffset', if found then increments 'coreunit' by 1. 
 | 
 */ 
 | 
/* TODO: Need to understand this. */ 
 | 
static int 
 | 
BCMATTACHFN(nci_get_coreunit)(nci_cores_t *cores, uint32 numcores, 
 | 
        uint core_id, uint32 iface_desc_1) 
 | 
{ 
 | 
    uint32 core_idx; 
 | 
    uint32 coreunit = NCI_DEFAULT_CORE_UNIT; 
 | 
  
 | 
    for (core_idx = 0u; core_idx < numcores; core_idx++) { 
 | 
        if ((cores[core_idx].coreid == core_id) && 
 | 
            (GET_COREOFFSET(cores[core_idx].desc->iface_desc_1) != 
 | 
                GET_COREOFFSET(iface_desc_1))) { 
 | 
            coreunit = cores[core_idx].coreunit + 1; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    return coreunit; 
 | 
} 
 | 
  
 | 
/* 
 | 
 * OOBR Region 
 | 
    +-------------------------------+ 
 | 
    +                + 
 | 
    +    OOBR with EROM Data    + 
 | 
    +                + 
 | 
    +-------------------------------+ 
 | 
    +                + 
 | 
    +    EROM1            + 
 | 
    +                + 
 | 
    +-------------------------------+  --> ChipCommon.EROMBASE 
 | 
    +                + 
 | 
    +    EROM2            + 
 | 
    +                + 
 | 
    +-------------------------------+ 
 | 
*/ 
 | 
  
 | 
/** 
 | 
 * Function : nci_init 
 | 
 * Description : Malloc's memory related to 'nci_info_t' and its internal elements. 
 | 
 * 
 | 
 * @paramter[in] 
 | 
 * @regs : This is a ChipCommon Regster 
 | 
 * @bustype : Bus Connect Type 
 | 
 * 
 | 
 * Return : On Succes 'nci_info_t' data structure is returned as void, 
 | 
 *    where all EROM parsed Cores are saved, 
 | 
 *    using this all EROM Cores are Freed. 
 | 
 *    On Failure 'NULL' is returned by printing ERROR messages 
 | 
 */ 
 | 
void* 
 | 
BCMATTACHFN(nci_init)(si_t *sih, chipcregs_t *cc, uint bustype) 
 | 
{ 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_cores_t *cores; 
 | 
    nci_info_t *nci = NULL; 
 | 
    uint8 err_at = 0u; 
 | 
  
 | 
#ifdef _RTE_ 
 | 
    if (knci_info) { 
 | 
        knci_info->refcnt++; 
 | 
        nci = knci_info; 
 | 
  
 | 
        goto end; 
 | 
    } 
 | 
#endif /* _RTE_ */ 
 | 
  
 | 
    /* It is used only when NCI_ERROR is used */ 
 | 
    BCM_REFERENCE(err_at); 
 | 
  
 | 
    if ((nci = MALLOCZ(sii->osh, sizeof(*nci))) == NULL) { 
 | 
        err_at = 1u; 
 | 
        goto end; 
 | 
    } 
 | 
    sii->nci_info = nci; 
 | 
  
 | 
    nci->osh = sii->osh; 
 | 
    nci->refcnt++; 
 | 
  
 | 
    nci->cc_erom2base = R_REG(nci->osh, &cc->eromptr); 
 | 
    nci->bustype = bustype; 
 | 
    switch (nci->bustype) { 
 | 
        case SI_BUS: 
 | 
            nci->erom2base = (uint32*)REG_MAP(nci->cc_erom2base, 0u); 
 | 
            nci->oobr_base = (uint32*)REG_MAP(GET_OOBR_BASE(nci->cc_erom2base), 0u); 
 | 
            nci->erom1base = (uint32*)REG_MAP(GET_EROM1_BASE(nci->cc_erom2base), 0u); 
 | 
  
 | 
            break; 
 | 
  
 | 
        case PCI_BUS: 
 | 
            /* Set wrappers address */ 
 | 
            sii->curwrap = (void *)((uintptr)cc + SI_CORE_SIZE); 
 | 
            /* Set access window to Erom Base(For NCI, EROM starts with OOBR) */ 
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
                GET_EROM1_BASE(nci->cc_erom2base)); 
 | 
            nci->erom1base = (uint32*)((uintptr)cc); 
 | 
            nci->erom2base = (uint32*)((uintptr)cc + NCI_EROM1_LEN(nci->cc_erom2base)); 
 | 
  
 | 
            break; 
 | 
  
 | 
        default: 
 | 
            err_at = 2u; 
 | 
            ASSERT(0u); 
 | 
            goto end; 
 | 
    } 
 | 
  
 | 
    nci->max_cores = nci_find_numcores(sih); 
 | 
    if (!nci->max_cores) { 
 | 
        err_at = 3u; 
 | 
        goto end; 
 | 
    } 
 | 
  
 | 
    if ((cores = MALLOCZ(nci->osh, sizeof(*cores) * nci->max_cores)) == NULL) { 
 | 
        err_at = 4u; 
 | 
        goto end; 
 | 
    } 
 | 
    nci->cores = cores; 
 | 
  
 | 
#ifdef _RTE_ 
 | 
    knci_info = nci; 
 | 
#endif /* _RTE_ */ 
 | 
  
 | 
end: 
 | 
    if (err_at) { 
 | 
        NCI_ERROR(("nci_init: Failed err_at=%#x\n", err_at)); 
 | 
        nci_uninit(nci); 
 | 
        nci = NULL; 
 | 
    } 
 | 
  
 | 
    return nci; 
 | 
} 
 | 
  
 | 
/** 
 | 
 * Function : nci_uninit 
 | 
 * Description : Free's memory related to 'nci_info_t' and its internal malloc'd elements. 
 | 
 * 
 | 
 * @paramter[in] 
 | 
 * @nci : This is 'nci_info_t' data structure, where all EROM parsed Cores are saved, using this 
 | 
 *    all EROM Cores are Freed. 
 | 
 * 
 | 
 * Return : void 
 | 
 */ 
 | 
void 
 | 
BCMATTACHFN(nci_uninit)(void *ctx) 
 | 
{ 
 | 
    nci_info_t *nci = (nci_info_t *)ctx; 
 | 
    uint8 core_idx, desc_idx; 
 | 
    interface_desc_t *desc; 
 | 
    nci_cores_t *cores; 
 | 
    slave_port_t *sp; 
 | 
  
 | 
    if (nci == NULL) { 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    nci->refcnt--; 
 | 
  
 | 
#ifdef _RTE_ 
 | 
    if (nci->refcnt != 0) { 
 | 
        return; 
 | 
    } 
 | 
#endif /* _RTE_ */ 
 | 
  
 | 
    cores = nci->cores; 
 | 
    if (cores == NULL) { 
 | 
        goto end; 
 | 
    } 
 | 
  
 | 
    for (core_idx = 0u; core_idx < nci->num_cores; core_idx++) { 
 | 
        desc = cores[core_idx].desc; 
 | 
        if (desc == NULL) { 
 | 
            break; 
 | 
        } 
 | 
  
 | 
        for (desc_idx = 0u; desc_idx < cores[core_idx].iface_cnt; desc_idx++) { 
 | 
            sp = desc[desc_idx].sp; 
 | 
            if (sp) { 
 | 
                MFREE(nci->osh, sp, (sizeof(*sp) * desc[desc_idx].num_addr_reg)); 
 | 
            } 
 | 
        } 
 | 
        MFREE(nci->osh, desc, (sizeof(*desc) * cores[core_idx].iface_cnt)); 
 | 
    } 
 | 
    MFREE(nci->osh, cores, sizeof(*cores) * nci->max_cores); 
 | 
  
 | 
end: 
 | 
  
 | 
#ifdef _RTE_ 
 | 
    knci_info = NULL; 
 | 
#endif /* _RTE_ */ 
 | 
  
 | 
    MFREE(nci->osh, nci, sizeof(*nci)); 
 | 
} 
 | 
  
 | 
/** 
 | 
 * Function : nci_save_iface1_reg 
 | 
 * Description : Interface1 Descriptor is obtained from the Reg and saved in 
 | 
 * Internal data structures 'nci->cores'. 
 | 
 * 
 | 
 * @paramter[in] 
 | 
 * @desc : Descriptor of Core which needs to be updated with obatained Interface1 Descritpor. 
 | 
 * @iface_desc_1 : Obatained Interface1 Descritpor. 
 | 
 * 
 | 
 * Return : void 
 | 
 */ 
 | 
static void 
 | 
BCMATTACHFN(nci_save_iface1_reg)(interface_desc_t *desc, uint32 iface_desc_1) 
 | 
{ 
 | 
    BCM_REFERENCE(BACKPLANE_ID_NAME); 
 | 
  
 | 
    desc->coretype = GET_CORETYPE(iface_desc_1); 
 | 
    desc->master = IS_MASTER(iface_desc_1); 
 | 
  
 | 
    desc->iface_desc_1 = iface_desc_1; 
 | 
    desc->num_addr_reg = GET_NUM_ADDR_REG(iface_desc_1); 
 | 
    if (desc->master) { 
 | 
        if (desc->num_addr_reg) { 
 | 
            NCI_ERROR(("nci_save_iface1_reg: Master NODEPTR Addresses is not zero " 
 | 
                "i.e. %d\n", GET_NUM_ADDR_REG(iface_desc_1))); 
 | 
            ASSERT(0u); 
 | 
        } 
 | 
    } else { 
 | 
        /* SLAVE 'NumAddressRegion' one less than actual slave ports, so increment by 1 */ 
 | 
        desc->num_addr_reg++; 
 | 
    } 
 | 
  
 | 
    NCI_INFO(("\tnci_save_iface1_reg: %s InterfaceDesc:%#x WordOffset=%#x " 
 | 
        "NoAddrReg=%#x %s_Offset=%#x BackplaneID=%s\n", 
 | 
        desc->master?"Master":"Slave", desc->iface_desc_1, 
 | 
        GET_WORDOFFSET(desc->iface_desc_1), 
 | 
        desc->num_addr_reg, desc->coretype?"EROM1":"OOBR", 
 | 
        GET_COREOFFSET(desc->iface_desc_1), 
 | 
        BACKPLANE_ID_NAME[ID_BPID(desc->iface_desc_1)])); 
 | 
} 
 | 
  
 | 
/** 
 | 
 * Function : nci_save_slaveport_addr 
 | 
 * Description : All Slave Port Addr of Interface Descriptor are saved. 
 | 
 * 
 | 
 * @paramter[in] 
 | 
 * @nci : This is 'nci_info_t' data structure, where all EROM parsed Cores are saved 
 | 
 * @desc : Current Interface Descriptor. 
 | 
 * @erom2ptr : Pointer to Address Descriptor0. 
 | 
 * 
 | 
 * Return : On Success, this function returns Erom2 Ptr to Next Interface Descriptor, 
 | 
 *    On Failure, NULL is returned. 
 | 
 */ 
 | 
static uint32* 
 | 
BCMATTACHFN(nci_save_slaveport_addr)(nci_info_t *nci, 
 | 
        interface_desc_t *desc, uint32 *erom2ptr) 
 | 
{ 
 | 
    slave_port_t *sp; 
 | 
    uint32 adesc; 
 | 
    uint32 sz; 
 | 
    uint32 addr_idx; 
 | 
  
 | 
    /* Allocate 'NumAddressRegion' of Slave Port */ 
 | 
    if ((desc->sp = (slave_port_t *)MALLOCZ( 
 | 
        nci->osh, (sizeof(*sp) * desc->num_addr_reg))) == NULL) { 
 | 
        NCI_ERROR(("\tnci_save_slaveport_addr: Memory Allocation failed for Slave Port\n")); 
 | 
        return NULL; 
 | 
    } 
 | 
  
 | 
    sp = desc->sp; 
 | 
    /* Slave Port Addrs Desc */ 
 | 
    for (addr_idx = 0u; addr_idx < desc->num_addr_reg; addr_idx++) { 
 | 
        adesc = R_REG(nci->osh, erom2ptr); 
 | 
        NCI_INC_ADDR(erom2ptr, NCI_WORD_SIZE); 
 | 
        sp[addr_idx].adesc = adesc; 
 | 
  
 | 
        sp[addr_idx].addrl = adesc & SLAVEPORT_BASE_ADDR_MASK; 
 | 
        if (adesc & SLAVEPORT_64BIT_ADDR_MASK) { 
 | 
            sp[addr_idx].addrh = R_REG(nci->osh, erom2ptr); 
 | 
            NCI_INC_ADDR(erom2ptr, NCI_WORD_SIZE); 
 | 
            sp[addr_idx].extaddrl = R_REG(nci->osh, erom2ptr); 
 | 
            NCI_INC_ADDR(erom2ptr, NCI_WORD_SIZE); 
 | 
            sp[addr_idx].extaddrh = R_REG(nci->osh, erom2ptr); 
 | 
            NCI_INC_ADDR(erom2ptr, NCI_WORD_SIZE); 
 | 
            NCI_INFO(("\tnci_save_slaveport_addr: SlavePortAddr[%#x]:0x%08x al=0x%08x " 
 | 
                "ah=0x%08x extal=0x%08x extah=0x%08x\n", addr_idx, adesc, 
 | 
                sp[addr_idx].addrl, sp[addr_idx].addrh, sp[addr_idx].extaddrl, 
 | 
                sp[addr_idx].extaddrh)); 
 | 
            } 
 | 
        else if (adesc & SLAVEPORT_BOUND_ADDR_MASK) { 
 | 
            sp[addr_idx].addrh = R_REG(nci->osh, erom2ptr); 
 | 
            NCI_INC_ADDR(erom2ptr, NCI_WORD_SIZE); 
 | 
            NCI_INFO(("\tnci_save_slaveport_addr: SlavePortAddr[%#x]:0x%08x al=0x%08x " 
 | 
                "ah=0x%08x\n", addr_idx, adesc, sp[addr_idx].addrl, 
 | 
                sp[addr_idx].addrh)); 
 | 
        } else { 
 | 
            sz = adesc & SLAVEPORT_ADDR_SIZE_MASK; 
 | 
            sp[addr_idx].addrh = sp[addr_idx].addrl + ADDR_SIZE(sz); 
 | 
            NCI_INFO(("\tnci_save_slaveport_addr: SlavePortAddr[%#x]:0x%08x al=0x%08x " 
 | 
                "ah=0x%08x sz=0x%08x\n", addr_idx, adesc, sp[addr_idx].addrl, 
 | 
                sp[addr_idx].addrh, sz)); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    return erom2ptr; 
 | 
} 
 | 
  
 | 
/** 
 | 
 * Function : nci_initial_parse 
 | 
 * Description : This function does 
 | 
 *    1. Obtains OOBR/EROM1 pointer based on CoreType 
 | 
 *    2. Analysis right CoreUnit for this 'core' 
 | 
 *    3. Saves CoreInfo & Interface Config in Coresponding 'core' 
 | 
 * 
 | 
 * @paramter[in] 
 | 
 * @nci : This is 'nci_info_t' data structure, where all EROM parsed Cores are saved. 
 | 
 * @erom2ptr : Pointer to Interface Descriptor0. 
 | 
 * @core_idx : New core index needs to be populated in this pointer. 
 | 
 * 
 | 
 * Return : On Success, this function returns 'core' where CoreInfo & Interface Config are saved. 
 | 
 */ 
 | 
static nci_cores_t* 
 | 
BCMATTACHFN(nci_initial_parse)(nci_info_t *nci, uint32 *erom2ptr, uint32 *core_idx) 
 | 
{ 
 | 
    uint32 iface_desc_1; 
 | 
    nci_cores_t *core; 
 | 
    uint32 dmp_regs_off = 0u; 
 | 
    uint32 iface_cfg = 0u; 
 | 
    uint32 core_info; 
 | 
    uint32 *ptr; 
 | 
    uint coreid; 
 | 
  
 | 
    iface_desc_1 = R_REG(nci->osh, erom2ptr); 
 | 
  
 | 
    /* Get EROM1/OOBR Pointer based on CoreType */ 
 | 
    if (!GET_CORETYPE(iface_desc_1)) { 
 | 
        if (nci->bustype == PCI_BUS) { 
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
                GET_OOBR_BASE(nci->cc_erom2base)); 
 | 
            nci->oobr_base = (uint32*)((uintptr)nci->erom1base); 
 | 
        } 
 | 
  
 | 
        ptr = NCI_ADD_ADDR(nci->oobr_base, GET_COREOFFSET(iface_desc_1)); 
 | 
    } else { 
 | 
        ptr = NCI_ADD_ADDR(nci->erom1base, GET_COREOFFSET(iface_desc_1)); 
 | 
    } 
 | 
    dmp_regs_off = GET_COREOFFSET(iface_desc_1) + DMP_DMPCTRL_REG_OFFSET; 
 | 
  
 | 
    core_info = R_REG(nci->osh, ptr); 
 | 
    NCI_INC_ADDR(ptr, NCI_WORD_SIZE); 
 | 
    iface_cfg = R_REG(nci->osh, ptr); 
 | 
  
 | 
    *core_idx = nci->num_cores; 
 | 
    core = &nci->cores[*core_idx]; 
 | 
  
 | 
    if (CORE_ID(core_info) < 0xFFu) { 
 | 
        coreid = CORE_ID(core_info) | 0x800u; 
 | 
    } else { 
 | 
        coreid = CORE_ID(core_info); 
 | 
    } 
 | 
  
 | 
    /* Get coreunit from previous cores i.e. num_cores */ 
 | 
    core->coreunit = nci_get_coreunit(nci->cores, nci->num_cores, 
 | 
        coreid, iface_desc_1); 
 | 
  
 | 
    core->coreid = coreid; 
 | 
  
 | 
    /* Increment the num_cores once proper coreunit is known */ 
 | 
    nci->num_cores++; 
 | 
  
 | 
    NCI_INFO(("\n\nnci_initial_parse: core_idx:%d %s=%p \n", 
 | 
        *core_idx, GET_CORETYPE(iface_desc_1)?"EROM1":"OOBR", ptr)); 
 | 
  
 | 
    /* Core Info Register */ 
 | 
    core->coreinfo = core_info; 
 | 
  
 | 
    /* Save DMP register base address. */ 
 | 
    core->dmp_regs_off = dmp_regs_off; 
 | 
  
 | 
    NCI_INFO(("\tnci_initial_parse: COREINFO:%#x CId:%#x CUnit=%#x CRev=%#x CMfg=%#x\n", 
 | 
        core->coreinfo, core->coreid, core->coreunit, CORE_REV(core->coreinfo), 
 | 
        CORE_MFG(core->coreinfo))); 
 | 
  
 | 
    /* Interface Config Register */ 
 | 
    core->iface_cfg = iface_cfg; 
 | 
    core->iface_cnt = GET_INFACECNT(iface_cfg); 
 | 
  
 | 
    NCI_INFO(("\tnci_initial_parse: INTERFACE_CFG:%#x IfaceCnt=%#x IfaceOffset=%#x \n", 
 | 
        iface_cfg, core->iface_cnt, iface_cfg & IC_IFACEOFFSET_MASK)); 
 | 
  
 | 
    /* For PCI_BUS case set back BAR0 Window to EROM1 Base */ 
 | 
    if (nci->bustype == PCI_BUS) { 
 | 
        OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
            GET_EROM1_BASE(nci->cc_erom2base)); 
 | 
    } 
 | 
  
 | 
    return core; 
 | 
} 
 | 
  
 | 
static uint32 
 | 
BCMATTACHFN(nci_find_numcores)(si_t *sih) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    volatile hndoobr_reg_t *oobr_reg = NULL; 
 | 
    uint32 orig_bar0_win1 = 0u; 
 | 
    uint32 num_oobr_cores = 0u; 
 | 
    uint32 num_nonoobr_cores = 0u; 
 | 
  
 | 
    /* No of Non-OOBR Cores */ 
 | 
    num_nonoobr_cores = NCI_NONOOBR_CORES(nci->cc_erom2base); 
 | 
    if (num_nonoobr_cores <= 0u) { 
 | 
        NCI_ERROR(("nci_find_numcores: Invalid Number of non-OOBR cores %d\n", 
 | 
            num_nonoobr_cores)); 
 | 
        goto fail; 
 | 
    } 
 | 
  
 | 
    /* No of OOBR Cores */ 
 | 
    switch (BUSTYPE(sih->bustype)) { 
 | 
    case SI_BUS: 
 | 
        oobr_reg = (volatile hndoobr_reg_t*)REG_MAP(GET_OOBR_BASE(nci->cc_erom2base), 
 | 
                SI_CORE_SIZE); 
 | 
        break; 
 | 
  
 | 
    case PCI_BUS: 
 | 
        /* Save Original Bar0 Win1 */ 
 | 
        orig_bar0_win1 = OSL_PCI_READ_CONFIG(nci->osh, PCI_BAR0_WIN, 
 | 
            PCI_ACCESS_SIZE); 
 | 
  
 | 
        OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
            GET_OOBR_BASE(nci->cc_erom2base)); 
 | 
        oobr_reg = (volatile hndoobr_reg_t*)sii->curmap; 
 | 
        break; 
 | 
  
 | 
    default: 
 | 
        NCI_ERROR(("nci_find_numcores: Invalid bustype %d\n", BUSTYPE(sih->bustype))); 
 | 
        ASSERT(0); 
 | 
        goto fail; 
 | 
    } 
 | 
  
 | 
    num_oobr_cores = R_REG(nci->osh, &oobr_reg->capability) & OOBR_CAP_CORECNT_MASK; 
 | 
    if (num_oobr_cores <= 0u) { 
 | 
        NCI_ERROR(("nci_find_numcores: Invalid Number of OOBR cores %d\n", num_oobr_cores)); 
 | 
        goto fail; 
 | 
    } 
 | 
  
 | 
    /* Point back to original base */ 
 | 
    if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
        OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, orig_bar0_win1); 
 | 
    } 
 | 
  
 | 
    NCI_PRINT(("nci_find_numcores: Total Cores found %d\n", 
 | 
        (num_oobr_cores + num_nonoobr_cores))); 
 | 
    /* Total No of Cores */ 
 | 
    return (num_oobr_cores + num_nonoobr_cores); 
 | 
  
 | 
fail: 
 | 
    return 0u; 
 | 
} 
 | 
  
 | 
/** 
 | 
 * Function : nci_scan 
 | 
 * Description : Function parses EROM in BOOKER NCI Architecture and saves all inforamtion about 
 | 
 *    Cores in 'nci_info_t' data structure. 
 | 
 * 
 | 
 * @paramter[in] 
 | 
 * @nci : This is 'nci_info_t' data structure, where all EROM parsed Cores are saved. 
 | 
 * 
 | 
 * Return : On Success No of parsed Cores in EROM is returned, 
 | 
 *    On Failure '0' is returned by printing ERROR messages 
 | 
 *    in Console(If NCI_LOG_LEVEL is enabled). 
 | 
 */ 
 | 
uint32 
 | 
BCMATTACHFN(nci_scan)(si_t *sih) 
 | 
{ 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = (nci_info_t *)sii->nci_info; 
 | 
    axi_wrapper_t * axi_wrapper = sii->axi_wrapper; 
 | 
    uint32 *cur_iface_desc_1_ptr; 
 | 
    nci_cores_t *core; 
 | 
    interface_desc_t *desc; 
 | 
    uint32 wordoffset = 0u; 
 | 
    uint32 iface_desc_0; 
 | 
    uint32 iface_desc_1; 
 | 
    uint32 *erom2ptr; 
 | 
    uint8 iface_idx; 
 | 
    uint32 core_idx; 
 | 
    int err = 0; 
 | 
  
 | 
    /* If scan was finished already */ 
 | 
    if (nci->scan_done) { 
 | 
        goto end; 
 | 
    } 
 | 
  
 | 
    erom2ptr = nci->erom2base; 
 | 
    sii->axi_num_wrappers = 0; 
 | 
  
 | 
    while (TRUE) { 
 | 
        iface_desc_0 = R_REG(nci->osh, erom2ptr); 
 | 
        if (iface_desc_0 == ID_ENDMARKER) { 
 | 
            NCI_INFO(("\nnci_scan: Reached end of EROM2 with total cores=%d \n", 
 | 
                nci->num_cores)); 
 | 
            break; 
 | 
        } 
 | 
  
 | 
        /* Save current Iface1 Addr for comparision */ 
 | 
        cur_iface_desc_1_ptr = GET_NEXT_EROM_ADDR(erom2ptr); 
 | 
  
 | 
        /* Get CoreInfo, InterfaceCfg, CoreIdx */ 
 | 
        core = nci_initial_parse(nci, cur_iface_desc_1_ptr, &core_idx); 
 | 
  
 | 
        core->desc = (interface_desc_t *)MALLOCZ( 
 | 
            nci->osh, (sizeof(*(core->desc)) * core->iface_cnt)); 
 | 
        if (core->desc == NULL) { 
 | 
            NCI_ERROR(("nci_scan: Mem Alloc failed for Iface and Addr " 
 | 
                "Descriptor\n")); 
 | 
            err = NCI_NOMEM; 
 | 
            break; 
 | 
        } 
 | 
  
 | 
        for (iface_idx = 0u; iface_idx < core->iface_cnt; iface_idx++) { 
 | 
            desc = &core->desc[iface_idx]; 
 | 
  
 | 
            iface_desc_0 = R_REG(nci->osh, erom2ptr); 
 | 
            NCI_INC_ADDR(erom2ptr, NCI_WORD_SIZE); 
 | 
            iface_desc_1 = R_REG(nci->osh, erom2ptr); 
 | 
            NCI_INC_ADDR(erom2ptr, NCI_WORD_SIZE); 
 | 
  
 | 
            /* Interface Descriptor Register */ 
 | 
            nci_save_iface1_reg(desc, iface_desc_1); 
 | 
            if (desc->master && desc->num_addr_reg) { 
 | 
                err = NCI_MASTER_INVALID_ADDR; 
 | 
                goto end; 
 | 
            } 
 | 
  
 | 
            wordoffset = GET_WORDOFFSET(iface_desc_1); 
 | 
  
 | 
            /* NodePointer Register */ 
 | 
            desc->iface_desc_0 = iface_desc_0; 
 | 
            desc->node_ptr = GET_NODEPTR(iface_desc_0); 
 | 
            desc->node_type = GET_NODETYPE(iface_desc_0); 
 | 
  
 | 
            if (axi_wrapper && (sii->axi_num_wrappers < SI_MAX_AXI_WRAPPERS)) { 
 | 
                axi_wrapper[sii->axi_num_wrappers].mfg = CORE_MFG(core->coreinfo); 
 | 
                axi_wrapper[sii->axi_num_wrappers].cid = CORE_ID(core->coreinfo); 
 | 
                axi_wrapper[sii->axi_num_wrappers].rev = CORE_REV(core->coreinfo); 
 | 
                axi_wrapper[sii->axi_num_wrappers].wrapper_type = desc->master; 
 | 
                axi_wrapper[sii->axi_num_wrappers].wrapper_addr = desc->node_ptr; 
 | 
                sii->axi_num_wrappers++; 
 | 
            } 
 | 
  
 | 
            NCI_INFO(("nci_scan: %s NodePointer:%#x Type=%s NODEPTR=%#x \n", 
 | 
                desc->master?"Master":"Slave", desc->iface_desc_0, 
 | 
                desc->node_type?"NIC-400":"BOOKER", desc->node_ptr)); 
 | 
  
 | 
            /* Slave Port Addresses */ 
 | 
            if (!desc->master) { 
 | 
                erom2ptr = nci_save_slaveport_addr(nci, desc, erom2ptr); 
 | 
                if (erom2ptr == NULL) { 
 | 
                    NCI_ERROR(("nci_scan: Invalid EROM2PTR\n")); 
 | 
                    err = NCI_INVALID_EROM2PTR; 
 | 
                    goto end; 
 | 
                } 
 | 
            } 
 | 
  
 | 
            /* Current loop ends with next iface_desc_0 */ 
 | 
        } 
 | 
  
 | 
        if (wordoffset == 0u) { 
 | 
            NCI_INFO(("\nnci_scan: EROM PARSING found END 'wordoffset=%#x' " 
 | 
                "with total cores=%d \n", wordoffset, nci->num_cores)); 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
    nci->scan_done = TRUE; 
 | 
  
 | 
end: 
 | 
    if (err) { 
 | 
        NCI_ERROR(("nci_scan: Failed with Code %d\n", err)); 
 | 
        nci->num_cores = 0; 
 | 
        ASSERT(0u); 
 | 
    } 
 | 
  
 | 
    return nci->num_cores; 
 | 
} 
 | 
  
 | 
/** 
 | 
 * Function : nci_dump_erom 
 | 
 * Description : Function dumps EROM from inforamtion cores in 'nci_info_t' data structure. 
 | 
 * 
 | 
 * @paramter[in] 
 | 
 * @nci : This is 'nci_info_t' data structure, where all EROM parsed Cores are saved. 
 | 
 * 
 | 
 * Return : void 
 | 
 */ 
 | 
void 
 | 
BCMATTACHFN(nci_dump_erom)(void *ctx) 
 | 
{ 
 | 
    nci_info_t *nci = (nci_info_t *)ctx; 
 | 
    nci_cores_t *core; 
 | 
    interface_desc_t *desc; 
 | 
    slave_port_t *sp; 
 | 
    uint32 core_idx, addr_idx, iface_idx; 
 | 
    uint32 core_info; 
 | 
  
 | 
    BCM_REFERENCE(core_info); 
 | 
  
 | 
    NCI_INFO(("\nnci_dump_erom: -- EROM Dump --\n")); 
 | 
    for (core_idx = 0u; core_idx < nci->num_cores; core_idx++) { 
 | 
        core = &nci->cores[core_idx]; 
 | 
  
 | 
        /* Core Info Register */ 
 | 
        core_info = core->coreinfo; 
 | 
        NCI_INFO(("\nnci_dump_erom: core_idx=%d COREINFO:%#x CId:%#x CUnit:%#x CRev=%#x " 
 | 
            "CMfg=%#x\n", core_idx, core_info, CORE_ID(core_info), core->coreunit, 
 | 
            CORE_REV(core_info), CORE_MFG(core_info))); 
 | 
  
 | 
        /* Interface Config Register */ 
 | 
        NCI_INFO(("nci_dump_erom: IfaceCfg=%#x IfaceCnt=%#x \n", 
 | 
            core->iface_cfg, core->iface_cnt)); 
 | 
  
 | 
        for (iface_idx = 0u; iface_idx < core->iface_cnt; iface_idx++) { 
 | 
            desc = &core->desc[iface_idx]; 
 | 
            /* NodePointer Register */ 
 | 
            NCI_INFO(("nci_dump_erom: %s iface_desc_0 Master=%#x MASTER_WRAP=%#x " 
 | 
                "Type=%s \n", desc->master?"Master":"Slave", desc->iface_desc_0, 
 | 
                desc->node_ptr, 
 | 
                (desc->node_type)?"NIC-400":"BOOKER")); 
 | 
  
 | 
            /* Interface Descriptor Register */ 
 | 
            NCI_INFO(("nci_dump_erom: %s InterfaceDesc:%#x WOffset=%#x NoAddrReg=%#x " 
 | 
                "%s_Offset=%#x\n", desc->master?"Master":"Slave", 
 | 
                desc->iface_desc_1, GET_WORDOFFSET(desc->iface_desc_1), 
 | 
                desc->num_addr_reg, 
 | 
                desc->coretype?"EROM1":"OOBR", GET_COREOFFSET(desc->iface_desc_1))); 
 | 
  
 | 
            /* Slave Port Addresses */ 
 | 
            sp = desc->sp; 
 | 
            if (!sp) { 
 | 
                continue; 
 | 
            } 
 | 
            for (addr_idx = 0u; addr_idx < desc->num_addr_reg; addr_idx++) { 
 | 
                if (sp[addr_idx].extaddrl) { 
 | 
                    NCI_INFO(("nci_dump_erom: SlavePortAddr[%#x]: AddrDesc=%#x" 
 | 
                        " al=%#x ah=%#x  extal=%#x extah=%#x\n", addr_idx, 
 | 
                        sp[addr_idx].adesc, sp[addr_idx].addrl, 
 | 
                        sp[addr_idx].addrh, sp[addr_idx].extaddrl, 
 | 
                        sp[addr_idx].extaddrh)); 
 | 
                } else { 
 | 
                    NCI_INFO(("nci_dump_erom: SlavePortAddr[%#x]: AddrDesc=%#x" 
 | 
                        " al=%#x ah=%#x\n", addr_idx, sp[addr_idx].adesc, 
 | 
                        sp[addr_idx].addrl, sp[addr_idx].addrh)); 
 | 
                } 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    return; 
 | 
} 
 | 
  
 | 
/* 
 | 
 * Switch to 'coreidx', issue a single arbitrary 32bit register mask & set operation, 
 | 
 * switch back to the original core, and return the new value. 
 | 
 */ 
 | 
uint 
 | 
BCMPOSTTRAPFN(nci_corereg)(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) 
 | 
{ 
 | 
    uint origidx = 0; 
 | 
    volatile uint32 *r = NULL; 
 | 
    uint w; 
 | 
    bcm_int_bitmask_t intr_val; 
 | 
    bool fast = FALSE; 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *cores_info = &nci->cores[coreidx]; 
 | 
  
 | 
    NCI_TRACE(("nci_corereg coreidx %u regoff %u mask %u val %u\n", 
 | 
        coreidx, regoff, mask, val)); 
 | 
    ASSERT(GOODIDX(coreidx, nci->num_cores)); 
 | 
    ASSERT(regoff < SI_CORE_SIZE); 
 | 
    ASSERT((val & ~mask) == 0); 
 | 
  
 | 
    if (coreidx >= SI_MAXCORES) { 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    if (BUSTYPE(sih->bustype) == SI_BUS) { 
 | 
        /* If internal bus, we can always get at everything */ 
 | 
        uint32 curmap = nci_get_curmap(nci, coreidx); 
 | 
        BCM_REFERENCE(curmap); 
 | 
  
 | 
        fast = TRUE; 
 | 
        /* map if does not exist */ 
 | 
        if (!cores_info->regs) { 
 | 
            cores_info->regs = REG_MAP(curmap, SI_CORE_SIZE); 
 | 
            ASSERT(GOODREGS(cores_info->regs)); 
 | 
        } 
 | 
        r = (volatile uint32 *)((volatile uchar *)cores_info->regs + regoff); 
 | 
    } else if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
        /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ 
 | 
  
 | 
        if ((cores_info->coreid == CC_CORE_ID) && SI_FAST(sii)) { 
 | 
            /* Chipc registers are mapped at 12KB */ 
 | 
  
 | 
            fast = TRUE; 
 | 
            r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                PCI_16KB0_CCREGS_OFFSET + regoff); 
 | 
        } else if (sii->pub.buscoreidx == coreidx) { 
 | 
            /* pci registers are at either in the last 2KB of an 8KB window 
 | 
             * or, in pcie and pci rev 13 at 8KB 
 | 
             */ 
 | 
            fast = TRUE; 
 | 
            if (SI_FAST(sii)) { 
 | 
                r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                    PCI_16KB0_PCIREGS_OFFSET + regoff); 
 | 
            } else { 
 | 
                r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                    ((regoff >= SBCONFIGOFF) ? 
 | 
                    PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + regoff); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    if (!fast) { 
 | 
        INTR_OFF(sii, &intr_val); 
 | 
  
 | 
        /* save current core index */ 
 | 
        origidx = si_coreidx(&sii->pub); 
 | 
  
 | 
        /* switch core */ 
 | 
        r = (volatile uint32*)((volatile uchar*)nci_setcoreidx(&sii->pub, coreidx) + 
 | 
            regoff); 
 | 
    } 
 | 
    ASSERT(r != NULL); 
 | 
  
 | 
    /* mask and set */ 
 | 
    if (mask || val) { 
 | 
        w = (R_REG(sii->osh, r) & ~mask) | val; 
 | 
        W_REG(sii->osh, r, w); 
 | 
    } 
 | 
  
 | 
    /* readback */ 
 | 
    w = R_REG(sii->osh, r); 
 | 
  
 | 
    if (!fast) { 
 | 
        /* restore core index */ 
 | 
        if (origidx != coreidx) { 
 | 
            nci_setcoreidx(&sii->pub, origidx); 
 | 
        } 
 | 
        INTR_RESTORE(sii, &intr_val); 
 | 
    } 
 | 
  
 | 
    return (w); 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_corereg_writeonly(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) 
 | 
{ 
 | 
    uint origidx = 0; 
 | 
    volatile uint32 *r = NULL; 
 | 
    uint w = 0; 
 | 
    bcm_int_bitmask_t intr_val; 
 | 
    bool fast = FALSE; 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *cores_info = &nci->cores[coreidx]; 
 | 
  
 | 
    NCI_TRACE(("nci_corereg_writeonly() coreidx %u regoff %u mask %u val %u\n", 
 | 
        coreidx, regoff, mask, val)); 
 | 
  
 | 
    ASSERT(GOODIDX(coreidx, nci->num_cores)); 
 | 
    ASSERT(regoff < SI_CORE_SIZE); 
 | 
    ASSERT((val & ~mask) == 0); 
 | 
  
 | 
    if (coreidx >= SI_MAXCORES) { 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    if (BUSTYPE(sih->bustype) == SI_BUS) { 
 | 
        /* If internal bus, we can always get at everything */ 
 | 
        uint32 curmap = nci_get_curmap(nci, coreidx); 
 | 
        BCM_REFERENCE(curmap); 
 | 
        fast = TRUE; 
 | 
        /* map if does not exist */ 
 | 
        if (!cores_info->regs) { 
 | 
            cores_info->regs = REG_MAP(curmap, SI_CORE_SIZE); 
 | 
            ASSERT(GOODREGS(cores_info->regs)); 
 | 
        } 
 | 
        r = (volatile uint32 *)((volatile uchar *)cores_info->regs + regoff); 
 | 
    } else if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
        /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ 
 | 
  
 | 
        if ((cores_info->coreid == CC_CORE_ID) && SI_FAST(sii)) { 
 | 
            /* Chipc registers are mapped at 12KB */ 
 | 
  
 | 
            fast = TRUE; 
 | 
            r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                PCI_16KB0_CCREGS_OFFSET + regoff); 
 | 
        } else if (sii->pub.buscoreidx == coreidx) { 
 | 
            /* pci registers are at either in the last 2KB of an 8KB window 
 | 
             * or, in pcie and pci rev 13 at 8KB 
 | 
             */ 
 | 
            fast = TRUE; 
 | 
            if (SI_FAST(sii)) { 
 | 
                r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                    PCI_16KB0_PCIREGS_OFFSET + regoff); 
 | 
            } else { 
 | 
                r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                    ((regoff >= SBCONFIGOFF) ? 
 | 
                    PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + regoff); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    if (!fast) { 
 | 
        INTR_OFF(sii, &intr_val); 
 | 
  
 | 
        /* save current core index */ 
 | 
        origidx = si_coreidx(&sii->pub); 
 | 
  
 | 
        /* switch core */ 
 | 
        r = (volatile uint32*) ((volatile uchar*) nci_setcoreidx(&sii->pub, coreidx) + 
 | 
            regoff); 
 | 
    } 
 | 
    ASSERT(r != NULL); 
 | 
  
 | 
    /* mask and set */ 
 | 
    if (mask || val) { 
 | 
        w = (R_REG(sii->osh, r) & ~mask) | val; 
 | 
        W_REG(sii->osh, r, w); 
 | 
    } 
 | 
  
 | 
    if (!fast) { 
 | 
        /* restore core index */ 
 | 
        if (origidx != coreidx) { 
 | 
            nci_setcoreidx(&sii->pub, origidx); 
 | 
        } 
 | 
  
 | 
        INTR_RESTORE(sii, &intr_val); 
 | 
    } 
 | 
  
 | 
    return (w); 
 | 
} 
 | 
  
 | 
/* 
 | 
 * If there is no need for fiddling with interrupts or core switches (typically silicon 
 | 
 * back plane registers, pci registers and chipcommon registers), this function 
 | 
 * returns the register offset on this core to a mapped address. This address can 
 | 
 * be used for W_REG/R_REG directly. 
 | 
 * 
 | 
 * For accessing registers that would need a core switch, this function will return 
 | 
 * NULL. 
 | 
 */ 
 | 
volatile uint32 * 
 | 
nci_corereg_addr(si_t *sih, uint coreidx, uint regoff) 
 | 
{ 
 | 
    volatile uint32 *r = NULL; 
 | 
    bool fast = FALSE; 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *cores_info = &nci->cores[coreidx]; 
 | 
  
 | 
    NCI_TRACE(("nci_corereg_addr() coreidx %u regoff %u\n", coreidx, regoff)); 
 | 
  
 | 
    ASSERT(GOODIDX(coreidx, nci->num_cores)); 
 | 
    ASSERT(regoff < SI_CORE_SIZE); 
 | 
  
 | 
    if (coreidx >= SI_MAXCORES) { 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    if (BUSTYPE(sih->bustype) == SI_BUS) { 
 | 
        uint32 curmap = nci_get_curmap(nci, coreidx); 
 | 
        BCM_REFERENCE(curmap); 
 | 
  
 | 
        /* If internal bus, we can always get at everything */ 
 | 
        fast = TRUE; 
 | 
        /* map if does not exist */ 
 | 
        if (!cores_info->regs) { 
 | 
            cores_info->regs = REG_MAP(curmap, SI_CORE_SIZE); 
 | 
            ASSERT(GOODREGS(cores_info->regs)); 
 | 
        } 
 | 
        r = (volatile uint32 *)((volatile uchar *)cores_info->regs + regoff); 
 | 
  
 | 
    } else if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
        /* If pci/pcie, we can get at pci/pcie regs and on newer cores to chipc */ 
 | 
  
 | 
        if ((cores_info->coreid == CC_CORE_ID) && SI_FAST(sii)) { 
 | 
            /* Chipc registers are mapped at 12KB */ 
 | 
  
 | 
            fast = TRUE; 
 | 
            r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                PCI_16KB0_CCREGS_OFFSET + regoff); 
 | 
        } else if (sii->pub.buscoreidx == coreidx) { 
 | 
            /* pci registers are at either in the last 2KB of an 8KB window 
 | 
             * or, in pcie and pci rev 13 at 8KB 
 | 
             */ 
 | 
            fast = TRUE; 
 | 
            if (SI_FAST(sii)) { 
 | 
                r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                    PCI_16KB0_PCIREGS_OFFSET + regoff); 
 | 
            } else { 
 | 
                r = (volatile uint32 *)((volatile char *)sii->curmap + 
 | 
                    ((regoff >= SBCONFIGOFF) ? 
 | 
                    PCI_BAR0_PCISBR_OFFSET : PCI_BAR0_PCIREGS_OFFSET) + regoff); 
 | 
            } 
 | 
        } 
 | 
    } 
 | 
  
 | 
    if (!fast) { 
 | 
        ASSERT(sii->curidx == coreidx); 
 | 
        r = (volatile uint32*) ((volatile uchar*)sii->curmap + regoff); 
 | 
    } 
 | 
  
 | 
    return (r); 
 | 
} 
 | 
  
 | 
uint 
 | 
BCMPOSTTRAPFN(nci_findcoreidx)(const si_t *sih, uint coreid, uint coreunit) 
 | 
{ 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    uint core_idx; 
 | 
  
 | 
    NCI_TRACE(("nci_findcoreidx() coreid %u coreunit %u\n", coreid, coreunit)); 
 | 
  
 | 
    for (core_idx = 0; core_idx < nci->num_cores; core_idx++) { 
 | 
        if ((nci->cores[core_idx].coreid == coreid) && 
 | 
            (nci->cores[core_idx].coreunit == coreunit)) { 
 | 
            return core_idx; 
 | 
        } 
 | 
    } 
 | 
    return BADIDX; 
 | 
} 
 | 
  
 | 
static uint32 
 | 
_nci_get_slave_addr_size(nci_info_t *nci, uint coreidx, uint32 slave_port_idx, uint base_idx) 
 | 
{ 
 | 
    uint32 size; 
 | 
    uint32 add_desc; 
 | 
  
 | 
    NCI_TRACE(("_nci_get_slave_addr_size() coreidx %u slave_port_idx %u base_idx %u\n", 
 | 
        coreidx, slave_port_idx, base_idx)); 
 | 
  
 | 
    add_desc = nci->cores[coreidx].desc[slave_port_idx].sp[base_idx].adesc; 
 | 
  
 | 
    size = add_desc & SLAVEPORT_ADDR_SIZE_MASK; 
 | 
    return ADDR_SIZE(size); 
 | 
} 
 | 
  
 | 
static uint32 
 | 
BCMPOSTTRAPFN(_nci_get_curmap)(nci_info_t *nci, uint coreidx, uint slave_port_idx, uint base_idx) 
 | 
{ 
 | 
    /* TODO: Is handling of 64 bit addressing required */ 
 | 
    NCI_TRACE(("_nci_get_curmap coreidx %u slave_port_idx %u base_idx %u\n", 
 | 
        coreidx, slave_port_idx, base_idx)); 
 | 
    return nci->cores[coreidx].desc[slave_port_idx].sp[base_idx].addrl; 
 | 
} 
 | 
  
 | 
/* Get the interface descriptor which is connected to APB and return its address */ 
 | 
static uint32 
 | 
BCMPOSTTRAPFN(nci_get_curmap)(nci_info_t *nci, uint coreidx) 
 | 
{ 
 | 
    nci_cores_t *core_info = &nci->cores[coreidx]; 
 | 
    uint32 iface_idx; 
 | 
  
 | 
    NCI_TRACE(("nci_get_curmap coreidx %u\n", coreidx)); 
 | 
    for (iface_idx = 0; iface_idx < core_info->iface_cnt; iface_idx++) { 
 | 
        NCI_TRACE(("nci_get_curmap iface_idx %u BP_ID %u master %u\n", 
 | 
            iface_idx, ID_BPID(core_info->desc[iface_idx].iface_desc_1), 
 | 
            IS_MASTER(core_info->desc[iface_idx].iface_desc_1))); 
 | 
  
 | 
        /* If core is a Backplane or Bridge, then its slave port 
 | 
         * will give the pointer to access registers. 
 | 
         */ 
 | 
        if (!IS_MASTER(core_info->desc[iface_idx].iface_desc_1) && 
 | 
            (IS_BACKPLANE(core_info->coreinfo) || 
 | 
            APB_INF(core_info->desc[iface_idx]))) { 
 | 
            return _nci_get_curmap(nci, coreidx, iface_idx, 0); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* no valid slave port address is found */ 
 | 
    return NCI_BAD_REG; 
 | 
} 
 | 
  
 | 
static uint32 
 | 
BCMPOSTTRAPFN(_nci_get_curwrap)(nci_info_t *nci, uint coreidx, uint wrapper_idx) 
 | 
{ 
 | 
    return nci->cores[coreidx].desc[wrapper_idx].node_ptr; 
 | 
} 
 | 
  
 | 
static uint32 
 | 
BCMPOSTTRAPFN(nci_get_curwrap)(nci_info_t *nci, uint coreidx) 
 | 
{ 
 | 
    nci_cores_t *core_info = &nci->cores[coreidx]; 
 | 
    uint32 iface_idx; 
 | 
    NCI_TRACE(("nci_get_curwrap coreidx %u\n", coreidx)); 
 | 
    for (iface_idx = 0; iface_idx < core_info->iface_cnt; iface_idx++) { 
 | 
        NCI_TRACE(("nci_get_curwrap iface_idx %u BP_ID %u master %u\n", 
 | 
            iface_idx, ID_BPID(core_info->desc[iface_idx].iface_desc_1), 
 | 
        IS_MASTER(core_info->desc[iface_idx].iface_desc_1))); 
 | 
        if ((ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_BOOKER) || 
 | 
            (ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_NIC400)) { 
 | 
            return _nci_get_curwrap(nci, coreidx, iface_idx); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* no valid master wrapper found */ 
 | 
    return NCI_BAD_REG; 
 | 
} 
 | 
  
 | 
static void 
 | 
_nci_setcoreidx_pcie_bus(si_t *sih, volatile void **regs, uint32 curmap, 
 | 
        uint32 curwrap) 
 | 
{ 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
  
 | 
    *regs = sii->curmap; 
 | 
    switch (sii->slice) { 
 | 
    case 0: /* main/first slice */ 
 | 
        /* point bar0 window */ 
 | 
        OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN, PCIE_WRITE_SIZE, curmap); 
 | 
        // TODO: why curwrap is zero i.e no master wrapper 
 | 
        if (curwrap != 0) { 
 | 
            if (PCIE_GEN2(sii)) { 
 | 
                OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_WIN2, 
 | 
                    PCIE_WRITE_SIZE, curwrap); 
 | 
            } else { 
 | 
                OSL_PCI_WRITE_CONFIG(sii->osh, PCI_BAR0_WIN2, 
 | 
                    PCIE_WRITE_SIZE, curwrap); 
 | 
            } 
 | 
        } 
 | 
        break; 
 | 
    case 1: /* aux/second slice */ 
 | 
        /* PCIE GEN2 only for other slices */ 
 | 
        if (!PCIE_GEN2(sii)) { 
 | 
            /* other slices not supported */ 
 | 
            NCI_ERROR(("pci gen not supported for slice 1\n")); 
 | 
            ASSERT(0); 
 | 
            break; 
 | 
        } 
 | 
  
 | 
        /* 0x4000 - 0x4fff: enum space 0x5000 - 0x5fff: wrapper space */ 
 | 
  
 | 
        *regs = (volatile uint8 *)*regs + PCI_SEC_BAR0_WIN_OFFSET; 
 | 
        sii->curwrap = (void *)((uintptr)*regs + SI_CORE_SIZE); 
 | 
  
 | 
        /* point bar0 window */ 
 | 
        OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_CORE2_WIN, PCIE_WRITE_SIZE,    curmap); 
 | 
        OSL_PCI_WRITE_CONFIG(sii->osh, PCIE2_BAR0_CORE2_WIN2, PCIE_WRITE_SIZE, curwrap); 
 | 
        break; 
 | 
  
 | 
    case 2: /* scan/third slice */ 
 | 
        /* PCIE GEN2 only for other slices */ 
 | 
        if (!PCIE_GEN2(sii)) { 
 | 
            /* other slices not supported */ 
 | 
            NCI_ERROR(("pci gen not supported for slice 1\n")); 
 | 
            ASSERT(0); 
 | 
            break; 
 | 
        } 
 | 
        /* 0x9000 - 0x9fff: enum space 0xa000 - 0xafff: wrapper space */ 
 | 
        *regs = (volatile uint8 *)*regs + PCI_SEC_BAR0_WIN_OFFSET; 
 | 
        sii->curwrap = (void *)((uintptr)*regs + SI_CORE_SIZE); 
 | 
  
 | 
        /* point bar0 window */ 
 | 
        nci_corereg(sih, sih->buscoreidx, PCIE_TER_BAR0_WIN, ~0, curmap); 
 | 
        nci_corereg(sih, sih->buscoreidx, PCIE_TER_BAR0_WRAPPER, ~0, curwrap); 
 | 
        break; 
 | 
    default: 
 | 
        ASSERT(0); 
 | 
        break; 
 | 
    } 
 | 
} 
 | 
  
 | 
static volatile void * 
 | 
BCMPOSTTRAPFN(_nci_setcoreidx)(si_t *sih, uint coreidx) 
 | 
{ 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *cores_info = &nci->cores[coreidx]; 
 | 
    uint32 curmap, curwrap; 
 | 
    volatile void *regs = NULL; 
 | 
  
 | 
    NCI_TRACE(("_nci_setcoreidx coreidx %u\n", coreidx)); 
 | 
    if (!GOODIDX(coreidx, nci->num_cores)) { 
 | 
        return (NULL); 
 | 
    } 
 | 
    /* 
 | 
     * If the user has provided an interrupt mask enabled function, 
 | 
     * then assert interrupts are disabled before switching the core. 
 | 
     */ 
 | 
    ASSERT((sii->intrsenabled_fn == NULL) || 
 | 
        !(*(sii)->intrsenabled_fn)((sii)->intr_arg)); 
 | 
  
 | 
    curmap = nci_get_curmap(nci, coreidx); 
 | 
    curwrap = nci_get_curwrap(nci, coreidx); 
 | 
  
 | 
    switch (BUSTYPE(sih->bustype)) { 
 | 
    case SI_BUS: 
 | 
        /* map if does not exist */ 
 | 
        if (!cores_info->regs) { 
 | 
            cores_info->regs = REG_MAP(curmap, SI_CORE_SIZE); 
 | 
            ASSERT(GOODREGS(cores_info->regs)); 
 | 
        } 
 | 
        sii->curmap = regs = cores_info->regs; 
 | 
        sii->curwrap = REG_MAP(curwrap, SI_CORE_SIZE); 
 | 
        break; 
 | 
  
 | 
    case PCI_BUS: 
 | 
        _nci_setcoreidx_pcie_bus(sih, ®s, curmap, curwrap); 
 | 
        break; 
 | 
  
 | 
    default: 
 | 
        NCI_ERROR(("_nci_stcoreidx Invalid bustype %d\n", BUSTYPE(sih->bustype))); 
 | 
        break; 
 | 
    } 
 | 
    sii->curidx = coreidx; 
 | 
    return regs; 
 | 
} 
 | 
  
 | 
volatile void * 
 | 
BCMPOSTTRAPFN(nci_setcoreidx)(si_t *sih, uint coreidx) 
 | 
{ 
 | 
    return _nci_setcoreidx(sih, coreidx); 
 | 
} 
 | 
  
 | 
volatile void * 
 | 
BCMPOSTTRAPFN(nci_setcore)(si_t *sih, uint coreid, uint coreunit) 
 | 
{ 
 | 
    si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    uint core_idx; 
 | 
  
 | 
    NCI_TRACE(("nci_setcore coreidx %u coreunit %u\n", coreid, coreunit)); 
 | 
    core_idx = nci_findcoreidx(sih, coreid, coreunit); 
 | 
  
 | 
    if (!GOODIDX(core_idx, nci->num_cores)) { 
 | 
        return (NULL); 
 | 
    } 
 | 
    return nci_setcoreidx(sih, core_idx); 
 | 
} 
 | 
  
 | 
/* Get the value of the register at offset "offset" of currently configured core */ 
 | 
uint 
 | 
BCMPOSTTRAPFN(nci_get_wrap_reg)(const si_t *sih, uint32 offset, uint32 mask, uint32 val) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    uint32 *addr = (uint32 *) ((uchar *)(sii->curwrap) + offset); 
 | 
    NCI_TRACE(("nci_wrap_reg offset %u mask %u val %u\n", offset, mask, val)); 
 | 
  
 | 
    if (mask || val) { 
 | 
        uint32 w = R_REG(sii->osh, addr); 
 | 
        w &= ~mask; 
 | 
        w |= val; 
 | 
        W_REG(sii->osh, addr, w); 
 | 
    } 
 | 
    return (R_REG(sii->osh, addr)); 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_corevendor(const si_t *sih) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
  
 | 
    NCI_TRACE(("nci_corevendor coreidx %u\n", sii->curidx)); 
 | 
    return (nci->cores[sii->curidx].coreinfo & COREINFO_MFG_MASK) >> COREINFO_MFG_SHIFT; 
 | 
} 
 | 
  
 | 
uint 
 | 
BCMPOSTTRAPFN(nci_corerev)(const si_t *sih) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    uint coreidx = sii->curidx; 
 | 
  
 | 
    NCI_TRACE(("nci_corerev coreidx %u\n", coreidx)); 
 | 
  
 | 
    return (nci->cores[coreidx].coreinfo & COREINFO_REV_MASK) >> COREINFO_REV_SHIFT; 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_corerev_minor(const si_t *sih) 
 | 
{ 
 | 
    return (nci_core_sflags(sih, 0, 0) >> SISF_MINORREV_D11_SHIFT) & 
 | 
            SISF_MINORREV_D11_MASK; 
 | 
} 
 | 
  
 | 
uint 
 | 
BCMPOSTTRAPFN(nci_coreid)(const si_t *sih, uint coreidx) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
  
 | 
    NCI_TRACE(("nci_coreid coreidx %u\n", coreidx)); 
 | 
    return nci->cores[coreidx].coreid; 
 | 
} 
 | 
  
 | 
/** return total coreunit of coreid or zero if not found */ 
 | 
uint 
 | 
BCMPOSTTRAPFN(nci_numcoreunits)(const si_t *sih, uint coreid) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    uint found = 0; 
 | 
    uint i; 
 | 
  
 | 
    NCI_TRACE(("nci_numcoreunits coreidx %u\n", coreid)); 
 | 
  
 | 
    for (i = 0; i < nci->num_cores; i++) { 
 | 
        if (nci->cores[i].coreid == coreid) { 
 | 
            found++; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    return found; 
 | 
} 
 | 
  
 | 
/* Return the address of the nth address space in the current core 
 | 
 * Arguments: 
 | 
 * sih : Pointer to struct si_t 
 | 
 * spidx : slave port index 
 | 
 * baidx : base address index 
 | 
 */ 
 | 
uint32 
 | 
nci_addr_space(const si_t *sih, uint spidx, uint baidx) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    uint cidx; 
 | 
  
 | 
    NCI_TRACE(("nci_addr_space spidx %u baidx %u\n", spidx, baidx)); 
 | 
    cidx = sii->curidx; 
 | 
    return _nci_get_curmap(sii->nci_info, cidx, spidx, baidx); 
 | 
} 
 | 
  
 | 
/* Return the size of the nth address space in the current core 
 | 
* Arguments: 
 | 
* sih : Pointer to struct si_t 
 | 
* spidx : slave port index 
 | 
* baidx : base address index 
 | 
*/ 
 | 
uint32 
 | 
nci_addr_space_size(const si_t *sih, uint spidx, uint baidx) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    uint cidx; 
 | 
  
 | 
    NCI_TRACE(("nci_addr_space_size spidx %u baidx %u\n", spidx, baidx)); 
 | 
  
 | 
    cidx = sii->curidx; 
 | 
    return _nci_get_slave_addr_size(sii->nci_info, cidx, spidx, baidx); 
 | 
} 
 | 
  
 | 
/* 
 | 
 * Performs soft reset of attached device. 
 | 
 * Writes have the following effect: 
 | 
 * 0b1 Request attached device to enter reset. 
 | 
 * Write is ignored if it occurs before soft reset exit has occurred. 
 | 
 * 
 | 
 * 0b0 Request attached device to exit reset. 
 | 
 * Write is ignored if it occurs before soft reset entry has occurred. 
 | 
 * 
 | 
 * Software can poll this register to determine whether soft reset entry or exit has occurred, 
 | 
 * using the following values: 
 | 
 * 0b1 Indicates that the device is in reset. 
 | 
 * 0b0 Indicates that the device is not in reset. 
 | 
 * 
 | 
 * 
 | 
 * Note 
 | 
 * The register value updates to reflect a request for reset entry or reset exit, 
 | 
 * but the update can only occur after required internal conditions are met. 
 | 
 * Until these conditions are met, a read to the register returns the old value. 
 | 
 * For example, outstanding transactions currently being handled must complete before 
 | 
 * the register value updates. 
 | 
 * 
 | 
 * To ensure reset propagation within the device, 
 | 
 * it is the responsibility of software to allow enough cycles after 
 | 
 * soft reset assertion is reflected in the reset control register 
 | 
 * before exiting soft reset by triggering a write of 0b0. 
 | 
 * If this responsibility is not met, the behavior is undefined or unpredictable. 
 | 
 * 
 | 
 * When the register value is 0b1, 
 | 
 * the external soft reset pin that connects to the attached AXI master or slave 
 | 
 * device is asserted, using the correct polarity of the reset pin. 
 | 
 * When the register value is 0b0, the external softreset 
 | 
 * pin that connects to the attached AXI master or slave device is deasserted, 
 | 
 * using the correct polarity of the reset pin. 
 | 
 */ 
 | 
static void 
 | 
BCMPOSTTRAPFN(_nci_core_reset)(const si_t *sih, uint32 bits, uint32 resetbits) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    amni_regs_t *amni = (amni_regs_t *)(uintptr)sii->curwrap; 
 | 
    volatile dmp_regs_t *io; 
 | 
    volatile uint32* erom_base = 0u; 
 | 
    uint32 orig_bar0_win1 = 0u; 
 | 
    volatile uint32 dummy; 
 | 
    volatile uint32 reg_read; 
 | 
    uint32 dmp_write_value; 
 | 
  
 | 
    /* Point to OOBR base */ 
 | 
    switch (BUSTYPE(sih->bustype)) { 
 | 
    case SI_BUS: 
 | 
        erom_base = (volatile uint32*)REG_MAP(GET_OOBR_BASE(nci->cc_erom2base), 
 | 
            SI_CORE_SIZE); 
 | 
        break; 
 | 
  
 | 
    case PCI_BUS: 
 | 
        /* 
 | 
         * Save Original Bar0 Win1. In nci, the io registers dmpctrl & dmpstatus 
 | 
         * registers are implemented in the EROM section. REF - 
 | 
         * https://docs.google.com/document/d/1HE7hAmvdoNFSnMI7MKQV1qVrFBZVsgLdNcILNOA2C8c 
 | 
         * This requires addition BAR0 windows mapping to erom section in chipcommon. 
 | 
         */ 
 | 
        orig_bar0_win1 = OSL_PCI_READ_CONFIG(nci->osh, PCI_BAR0_WIN, 
 | 
            PCI_ACCESS_SIZE); 
 | 
  
 | 
        OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
            GET_OOBR_BASE(nci->cc_erom2base)); 
 | 
        erom_base = (volatile uint32*)sii->curmap; 
 | 
        break; 
 | 
  
 | 
    default: 
 | 
        NCI_ERROR(("_nci_core_reset Invalid bustype %d\n", BUSTYPE(sih->bustype))); 
 | 
        break; 
 | 
    } 
 | 
  
 | 
    /* Point to DMP Control */ 
 | 
    io = (dmp_regs_t*)(NCI_ADD_ADDR(erom_base, nci->cores[sii->curidx].dmp_regs_off)); 
 | 
  
 | 
    NCI_TRACE(("_nci_core_reset reg 0x%p io %p\n", amni, io)); 
 | 
  
 | 
    /* Put core into reset */ 
 | 
    W_REG(nci->osh, &amni->idm_reset_ctrl, NI_IDM_RESET_ENTRY); 
 | 
  
 | 
    /* poll for the reset to happen */ 
 | 
    while (TRUE) { 
 | 
        /* Wait until reset is effective */ 
 | 
        SPINWAIT(((reg_read = R_REG(nci->osh, &amni->idm_reset_ctrl)) != 
 | 
            NI_IDM_RESET_ENTRY), NCI_SPINWAIT_TIMEOUT); 
 | 
  
 | 
        if (reg_read == NI_IDM_RESET_ENTRY) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    dmp_write_value = (bits | resetbits | SICF_FGC | SICF_CLOCK_EN); 
 | 
  
 | 
    W_REG(nci->osh, &io->dmpctrl, dmp_write_value); 
 | 
  
 | 
    /* poll for the dmp_reg write to happen */ 
 | 
    while (TRUE) { 
 | 
        /* Wait until reset is effective */ 
 | 
        SPINWAIT(((reg_read = R_REG(nci->osh, &io->dmpctrl)) != 
 | 
            dmp_write_value), NCI_SPINWAIT_TIMEOUT); 
 | 
        if (reg_read == dmp_write_value) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* take core out of reset */ 
 | 
    W_REG(nci->osh, &amni->idm_reset_ctrl, 0u); 
 | 
  
 | 
    /* poll for the core to come out of reset */ 
 | 
    while (TRUE) { 
 | 
        /* Wait until reset is effected */ 
 | 
        SPINWAIT(((reg_read = R_REG(nci->osh, &amni->idm_reset_ctrl)) != 
 | 
            NI_IDM_RESET_EXIT), NCI_SPINWAIT_TIMEOUT); 
 | 
        if (reg_read == NI_IDM_RESET_EXIT) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    dmp_write_value = (bits | SICF_CLOCK_EN); 
 | 
    W_REG(nci->osh, &io->dmpctrl, (bits | SICF_CLOCK_EN)); 
 | 
    /* poll for the core to come out of reset */ 
 | 
    while (TRUE) { 
 | 
        SPINWAIT(((reg_read = R_REG(nci->osh, &io->dmpctrl)) != 
 | 
            dmp_write_value), NCI_SPINWAIT_TIMEOUT); 
 | 
        if (reg_read == dmp_write_value) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    dummy = R_REG(nci->osh, &io->dmpctrl); 
 | 
    BCM_REFERENCE(dummy); 
 | 
  
 | 
    /* Point back to original base */ 
 | 
    if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
        OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, orig_bar0_win1); 
 | 
    } 
 | 
} 
 | 
  
 | 
/* reset and re-enable a core 
 | 
 */ 
 | 
void 
 | 
BCMPOSTTRAPFN(nci_core_reset)(const si_t *sih, uint32 bits, uint32 resetbits) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    int32 iface_idx = 0u; 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *core = &nci->cores[sii->curidx]; 
 | 
  
 | 
    /* If Wrapper is of NIC400, then call AI functionality */ 
 | 
    for (iface_idx = core->iface_cnt-1; iface_idx >= 0; iface_idx--) { 
 | 
        if (!(BOOKER_INF(core->desc[iface_idx]) || NIC_INF(core->desc[iface_idx]))) { 
 | 
            continue; 
 | 
        } 
 | 
#ifdef BOOKER_NIC400_INF 
 | 
        if (core->desc[iface_idx].node_type == NODE_TYPE_NIC400) { 
 | 
            ai_core_reset_ext(sih, bits, resetbits); 
 | 
        } else 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
        { 
 | 
            _nci_core_reset(sih, bits, resetbits); 
 | 
        } 
 | 
    } 
 | 
} 
 | 
  
 | 
#ifdef BOOKER_NIC400_INF 
 | 
static int32 
 | 
BCMPOSTTRAPFN(nci_find_first_wrapper_idx)(nci_info_t *nci, uint32 coreidx) 
 | 
{ 
 | 
    nci_cores_t *core_info = &nci->cores[coreidx]; 
 | 
    uint32 iface_idx; 
 | 
  
 | 
    NCI_TRACE(("nci_find_first_wrapper_idx %u\n", coreidx)); 
 | 
  
 | 
    for (iface_idx = 0; iface_idx < core_info->iface_cnt; iface_idx++) { 
 | 
        NCI_INFO(("nci_find_first_wrapper_idx: %u BP_ID %u master %u\n", 
 | 
            iface_idx, ID_BPID(core_info->desc[iface_idx].iface_desc_1), 
 | 
            IS_MASTER(core_info->desc[iface_idx].iface_desc_1))); 
 | 
  
 | 
        if ((ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_BOOKER) || 
 | 
            (ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_NIC400)) { 
 | 
            return iface_idx; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* no valid master wrapper found */ 
 | 
    return NCI_BAD_INDEX; 
 | 
} 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
  
 | 
void 
 | 
nci_core_disable(const si_t *sih, uint32 bits) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    uint32 reg_read; 
 | 
    volatile dmp_regs_t *io = NULL; 
 | 
    uint32 orig_bar0_win1 = 0u; 
 | 
    uint32 dmp_write_value; 
 | 
    amni_regs_t *amni = (amni_regs_t *)(uintptr)sii->curwrap; 
 | 
    nci_cores_t *core = &nci->cores[sii->curidx]; 
 | 
    int32 iface_idx; 
 | 
  
 | 
    NCI_TRACE(("nci_core_disable\n")); 
 | 
  
 | 
    BCM_REFERENCE(core); 
 | 
    BCM_REFERENCE(iface_idx); 
 | 
  
 | 
#ifdef BOOKER_NIC400_INF 
 | 
    iface_idx = nci_find_first_wrapper_idx(nci, sii->curidx); 
 | 
  
 | 
    if (iface_idx < 0) { 
 | 
        NCI_ERROR(("nci_core_disable: First Wrapper is not found\n")); 
 | 
        ASSERT(0u); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    /* If Wrapper is of NIC400, then call AI functionality */ 
 | 
    if (core->desc[iface_idx].master && (core->desc[iface_idx].node_type == NODE_TYPE_NIC400)) { 
 | 
        return ai_core_disable(sih, bits); 
 | 
    } 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
  
 | 
    ASSERT(GOODREGS(sii->curwrap)); 
 | 
    reg_read = R_REG(nci->osh, &amni->idm_reset_ctrl); 
 | 
  
 | 
    /* if core is already in reset, just return */ 
 | 
    if (reg_read == NI_IDM_RESET_ENTRY) { 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    /* Put core into reset */ 
 | 
    W_REG(nci->osh, &amni->idm_reset_ctrl, NI_IDM_RESET_ENTRY); 
 | 
    while (TRUE) { 
 | 
        /* Wait until reset is effected */ 
 | 
        SPINWAIT(((reg_read = R_REG(nci->osh, &amni->idm_reset_ctrl)) != 
 | 
        NI_IDM_RESET_ENTRY), NCI_SPINWAIT_TIMEOUT); 
 | 
        if (reg_read == NI_IDM_RESET_ENTRY) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* Point to OOBR base */ 
 | 
    switch (BUSTYPE(sih->bustype)) { 
 | 
    case SI_BUS: 
 | 
        io = (volatile dmp_regs_t*) 
 | 
            REG_MAP(GET_OOBR_BASE(nci->cc_erom2base), SI_CORE_SIZE); 
 | 
        break; 
 | 
  
 | 
    case PCI_BUS: 
 | 
        /* Save Original Bar0 Win1 */ 
 | 
        orig_bar0_win1 = 
 | 
            OSL_PCI_READ_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE); 
 | 
  
 | 
        OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
            GET_OOBR_BASE(nci->cc_erom2base)); 
 | 
        io = (volatile dmp_regs_t*)sii->curmap; 
 | 
        break; 
 | 
  
 | 
    default: 
 | 
        NCI_ERROR(("nci_core_disable Invalid bustype %d\n", BUSTYPE(sih->bustype))); 
 | 
        break; 
 | 
  
 | 
    } 
 | 
  
 | 
    /* Point to DMP Control */ 
 | 
    io = (dmp_regs_t*)(NCI_ADD_ADDR(io, nci->cores[sii->curidx].dmp_regs_off)); 
 | 
  
 | 
    dmp_write_value = (bits | SICF_FGC | SICF_CLOCK_EN); 
 | 
    W_REG(nci->osh, &io->dmpctrl, dmp_write_value); 
 | 
  
 | 
    /* poll for the dmp_reg write to happen */ 
 | 
    while (TRUE) { 
 | 
        /* Wait until reset is effected */ 
 | 
        SPINWAIT(((reg_read = R_REG(nci->osh, &io->dmpctrl)) != dmp_write_value), 
 | 
        NCI_SPINWAIT_TIMEOUT); 
 | 
        if (reg_read == dmp_write_value) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    /* Point back to original base */ 
 | 
    if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
        OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, orig_bar0_win1); 
 | 
    } 
 | 
} 
 | 
  
 | 
bool 
 | 
BCMPOSTTRAPFN(nci_iscoreup)(const si_t *sih) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    amni_regs_t *ni = (amni_regs_t *)(uintptr)sii->curwrap; 
 | 
    uint32 reset_ctrl; 
 | 
  
 | 
#ifdef BOOKER_NIC400_INF 
 | 
    nci_cores_t *core = &nci->cores[sii->curidx]; 
 | 
    int32 iface_idx = nci_find_first_wrapper_idx(nci, sii->curidx); 
 | 
  
 | 
    if (iface_idx < 0) { 
 | 
        NCI_ERROR(("nci_iscoreup: First Wrapper is not found\n")); 
 | 
        ASSERT(0u); 
 | 
        return FALSE; 
 | 
    } 
 | 
  
 | 
    /* If Wrapper is of NIC400, then call AI functionality */ 
 | 
    if (core->desc[iface_idx].master && (core->desc[iface_idx].node_type == NODE_TYPE_NIC400)) { 
 | 
        return ai_iscoreup(sih); 
 | 
    } 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
  
 | 
    NCI_TRACE(("nci_iscoreup\n")); 
 | 
    reset_ctrl = R_REG(nci->osh, &ni->idm_reset_ctrl); 
 | 
  
 | 
    return (reset_ctrl == NI_IDM_RESET_ENTRY) ? FALSE : TRUE; 
 | 
} 
 | 
  
 | 
/* TODO: OOB Router core is not available. Can be removed. */ 
 | 
uint 
 | 
nci_intflag(si_t *sih) 
 | 
{ 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_flag(si_t *sih) 
 | 
{ 
 | 
    /* TODO: will be implemented if required for NCI */ 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_flag_alt(const si_t *sih) 
 | 
{ 
 | 
    /* TODO: will be implemented if required for NCI */ 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
void 
 | 
BCMATTACHFN(nci_setint)(const si_t *sih, int siflag) 
 | 
{ 
 | 
    BCM_REFERENCE(sih); 
 | 
    BCM_REFERENCE(siflag); 
 | 
  
 | 
    /* TODO: Figure out how to set interrupt mask in nci */ 
 | 
} 
 | 
  
 | 
/* TODO: OOB Router core is not available. Can we remove or need an alternate implementation. */ 
 | 
uint32 
 | 
nci_oobr_baseaddr(const si_t *sih, bool second) 
 | 
{ 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_coreunit(const si_t *sih) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *cores = nci->cores; 
 | 
    uint idx; 
 | 
    uint coreid; 
 | 
    uint coreunit; 
 | 
    uint i; 
 | 
  
 | 
    coreunit = 0; 
 | 
  
 | 
    idx = sii->curidx; 
 | 
  
 | 
    ASSERT(GOODREGS(sii->curmap)); 
 | 
    coreid = nci_coreid(sih, sii->curidx); 
 | 
  
 | 
    /* count the cores of our type */ 
 | 
    for (i = 0; i < idx; i++) { 
 | 
        if (cores[i].coreid == coreid) { 
 | 
            coreunit++; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    return (coreunit); 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_corelist(const si_t *sih, uint coreid[]) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *cores = nci->cores; 
 | 
    uint32 i; 
 | 
  
 | 
    for (i = 0; i < sii->numcores; i++) { 
 | 
        coreid[i] = cores[i].coreid; 
 | 
    } 
 | 
  
 | 
    return (sii->numcores); 
 | 
} 
 | 
  
 | 
/* Return the number of address spaces in current core */ 
 | 
int 
 | 
BCMATTACHFN(nci_numaddrspaces)(const si_t *sih) 
 | 
{ 
 | 
    /* TODO: Either save it or parse the EROM on demand, currently hardcode 2 */ 
 | 
    BCM_REFERENCE(sih); 
 | 
  
 | 
    return 2; 
 | 
} 
 | 
  
 | 
/* The value of wrap_pos should be greater than 0 */ 
 | 
/* wrapba, wrapba2 and wrapba3 */ 
 | 
uint32 
 | 
nci_get_nth_wrapper(const si_t *sih, int32 wrap_pos) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    const nci_cores_t *core_info = &nci->cores[sii->curidx]; 
 | 
    uint32 iface_idx; 
 | 
    uint32 addr = 0; 
 | 
  
 | 
    ASSERT(wrap_pos >= 0); 
 | 
    if (wrap_pos < 0) { 
 | 
        return addr; 
 | 
    } 
 | 
  
 | 
    NCI_TRACE(("nci_get_curmap coreidx %u\n", sii->curidx)); 
 | 
    for (iface_idx = 0; iface_idx < core_info->iface_cnt; iface_idx++) { 
 | 
    NCI_TRACE(("nci_get_curmap iface_idx %u BP_ID %u master %u\n", 
 | 
        iface_idx, ID_BPID(core_info->desc[iface_idx].iface_desc_1), 
 | 
        IS_MASTER(core_info->desc[iface_idx].iface_desc_1))); 
 | 
        /* hack for core idx 8, coreidx without APB Backplane ID */ 
 | 
        if (!IS_MASTER(core_info->desc[iface_idx].iface_desc_1)) { 
 | 
            continue; 
 | 
        } 
 | 
        /* TODO: Should the interface be only BOOKER or NIC is also fine. */ 
 | 
        if (GET_NODETYPE(core_info->desc[iface_idx].iface_desc_0) != NODE_TYPE_BOOKER) { 
 | 
            continue; 
 | 
        } 
 | 
        /* Iterate till we do not get a wrapper at nth (wrap_pos) position */ 
 | 
        if (wrap_pos == 0) { 
 | 
            break; 
 | 
        } 
 | 
        wrap_pos--; 
 | 
    } 
 | 
    if (iface_idx < core_info->iface_cnt) { 
 | 
        addr = GET_NODEPTR(core_info->desc[iface_idx].iface_desc_0); 
 | 
    } 
 | 
    return addr; 
 | 
} 
 | 
  
 | 
/* Get slave port address of the 0th slave (csp2ba) */ 
 | 
uint32 
 | 
nci_get_axi_addr(const si_t *sih, uint32 *size) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    const nci_cores_t *core_info = (const nci_cores_t *)&nci->cores[sii->curidx]; 
 | 
    uint32 iface_idx; 
 | 
    uint32 addr = 0; 
 | 
  
 | 
    NCI_TRACE(("nci_get_curmap coreidx %u\n", sii->curidx)); 
 | 
    for (iface_idx = 0; iface_idx < core_info->iface_cnt; iface_idx++) { 
 | 
    NCI_TRACE(("nci_get_curmap iface_idx %u BP_ID %u master %u\n", 
 | 
        iface_idx, ID_BPID(core_info->desc[iface_idx].iface_desc_1), 
 | 
        IS_MASTER(core_info->desc[iface_idx].iface_desc_1))); 
 | 
        if (IS_MASTER(core_info->desc[iface_idx].iface_desc_1)) { 
 | 
            continue; 
 | 
        } 
 | 
        if ((ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_BOOKER) || 
 | 
            (ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_NIC400)) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
    if (iface_idx < core_info->iface_cnt) { 
 | 
        /* 
 | 
         * TODO: Is there any case where we need to return the slave port address 
 | 
         * corresponding to index other than 0. 
 | 
         */ 
 | 
        if (&core_info->desc[iface_idx].sp[0] != NULL) { 
 | 
            addr = core_info->desc[iface_idx].sp[0].addrl; 
 | 
            if (size) { 
 | 
                uint32 adesc = core_info->desc[iface_idx].sp[0].adesc; 
 | 
                *size = SLAVEPORT_ADDR_SIZE(adesc); 
 | 
            } 
 | 
         } 
 | 
    } 
 | 
    return addr; 
 | 
} 
 | 
  
 | 
/* spidx shouldbe the index of the slave port which we are expecting. 
 | 
 * The value will vary from 0 to num_addr_reg. 
 | 
 */ 
 | 
/* coresba and coresba2 */ 
 | 
uint32 
 | 
nci_get_core_baaddr(const si_t *sih, uint32 *size, int32 baidx) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    const nci_cores_t *core_info = (const nci_cores_t *)&nci->cores[sii->curidx]; 
 | 
    uint32 iface_idx; 
 | 
    uint32 addr = 0; 
 | 
  
 | 
    NCI_TRACE(("nci_get_curmap coreidx %u\n", sii->curidx)); 
 | 
    for (iface_idx = 0; iface_idx < core_info->iface_cnt; iface_idx++) { 
 | 
    NCI_TRACE(("nci_get_curmap iface_idx %u BP_ID %u master %u\n", 
 | 
        iface_idx, ID_BPID(core_info->desc[iface_idx].iface_desc_1), 
 | 
        IS_MASTER(core_info->desc[iface_idx].iface_desc_1))); 
 | 
        /* hack for core idx 8, coreidx without APB Backplane ID */ 
 | 
        if (IS_MASTER(core_info->desc[iface_idx].iface_desc_1)) { 
 | 
            continue; 
 | 
        } 
 | 
        if ((ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_APB1) || 
 | 
            (ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_APB2)) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
    if (iface_idx < core_info->iface_cnt) { 
 | 
        /* 
 | 
         * TODO: Is there any case where we need to return the slave port address 
 | 
         * corresponding to index other than 0. 
 | 
         */ 
 | 
        if ((core_info->desc[iface_idx].num_addr_reg > baidx) && 
 | 
            (&core_info->desc[iface_idx].sp[baidx] != NULL)) { 
 | 
            addr = core_info->desc[iface_idx].sp[baidx].addrl; 
 | 
            if (size) { 
 | 
                uint32 adesc = core_info->desc[iface_idx].sp[0].adesc; 
 | 
                *size = SLAVEPORT_ADDR_SIZE(adesc); 
 | 
            } 
 | 
         } 
 | 
    } 
 | 
    return addr; 
 | 
} 
 | 
  
 | 
uint32 
 | 
nci_addrspace(const si_t *sih, uint spidx, uint baidx) 
 | 
{ 
 | 
    if (spidx == CORE_SLAVE_PORT_0) { 
 | 
        if (baidx == CORE_BASE_ADDR_0) { 
 | 
            return nci_get_core_baaddr(sih, NULL, CORE_BASE_ADDR_0); 
 | 
        } else if (baidx == CORE_BASE_ADDR_1) { 
 | 
            return nci_get_core_baaddr(sih, NULL, CORE_BASE_ADDR_1); 
 | 
        } 
 | 
    } else if (spidx == CORE_SLAVE_PORT_1) { 
 | 
        if (baidx == CORE_BASE_ADDR_0) { 
 | 
            return nci_get_axi_addr(sih, NULL); 
 | 
        } 
 | 
    } 
 | 
  
 | 
    SI_ERROR(("nci_addrspace: Need to parse the erom again to find %d base addr" 
 | 
        " in %d slave port\n", baidx, spidx)); 
 | 
  
 | 
    return 0; 
 | 
} 
 | 
  
 | 
uint32 
 | 
BCMATTACHFN(nci_addrspacesize)(const si_t *sih, uint spidx, uint baidx) 
 | 
{ 
 | 
    uint32 size = 0; 
 | 
  
 | 
    if (spidx == CORE_SLAVE_PORT_0) { 
 | 
        if (baidx == CORE_BASE_ADDR_0) { 
 | 
            nci_get_core_baaddr(sih, &size, CORE_BASE_ADDR_0); 
 | 
            goto done; 
 | 
        } else if (baidx == CORE_BASE_ADDR_1) { 
 | 
            nci_get_core_baaddr(sih, &size, CORE_BASE_ADDR_1); 
 | 
            goto done; 
 | 
        } 
 | 
    } else if (spidx == CORE_SLAVE_PORT_1) { 
 | 
        if (baidx == CORE_BASE_ADDR_0) { 
 | 
            nci_get_axi_addr(sih, &size); 
 | 
            goto done; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    SI_ERROR(("nci_addrspacesize: Need to parse the erom again to find %d" 
 | 
        " base addr in %d slave port\n", baidx, spidx)); 
 | 
done: 
 | 
    return size; 
 | 
} 
 | 
  
 | 
uint32 
 | 
BCMPOSTTRAPFN(nci_core_cflags)(const si_t *sih, uint32 mask, uint32 val) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *core = &nci->cores[sii->curidx]; 
 | 
    uint32 orig_bar0_win1 = 0; 
 | 
    int32 iface_idx; 
 | 
    uint32 w; 
 | 
  
 | 
    BCM_REFERENCE(iface_idx); 
 | 
  
 | 
    if ((core[sii->curidx].coreid) == PMU_CORE_ID) { 
 | 
        NCI_ERROR(("nci_core_cflags: Accessing PMU DMP register (ioctrl)\n")); 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    ASSERT(GOODREGS(sii->curwrap)); 
 | 
    ASSERT((val & ~mask) == 0); 
 | 
  
 | 
#ifdef BOOKER_NIC400_INF 
 | 
    iface_idx = nci_find_first_wrapper_idx(nci, sii->curidx); 
 | 
    if (iface_idx < 0) { 
 | 
        NCI_ERROR(("nci_core_cflags: First Wrapper is not found\n")); 
 | 
        ASSERT(0u); 
 | 
        return 0u; 
 | 
    } 
 | 
  
 | 
    /* If Wrapper is of NIC400, then call AI functionality */ 
 | 
    if (core->desc[iface_idx].master && (core->desc[iface_idx].node_type == NODE_TYPE_NIC400)) { 
 | 
        aidmp_t *ai = sii->curwrap; 
 | 
  
 | 
        if (mask || val) { 
 | 
             w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); 
 | 
            W_REG(sii->osh, &ai->ioctrl, w); 
 | 
        } 
 | 
        return R_REG(sii->osh, &ai->ioctrl); 
 | 
    } else 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
    { 
 | 
        volatile dmp_regs_t *io = sii->curwrap; 
 | 
        volatile uint32 reg_read; 
 | 
  
 | 
        /* BOOKER */ 
 | 
        /* Point to OOBR base */ 
 | 
        switch (BUSTYPE(sih->bustype)) { 
 | 
        case SI_BUS: 
 | 
            io = (volatile dmp_regs_t*) 
 | 
                REG_MAP(GET_OOBR_BASE(nci->cc_erom2base), SI_CORE_SIZE); 
 | 
            break; 
 | 
  
 | 
        case PCI_BUS: 
 | 
            /* Save Original Bar0 Win1 */ 
 | 
            orig_bar0_win1 = 
 | 
                OSL_PCI_READ_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE); 
 | 
  
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
                GET_OOBR_BASE(nci->cc_erom2base)); 
 | 
            io = (volatile dmp_regs_t*)sii->curmap; 
 | 
            break; 
 | 
  
 | 
        default: 
 | 
            NCI_ERROR(("nci_core_cflags Invalid bustype %d\n", BUSTYPE(sih->bustype))); 
 | 
            break; 
 | 
  
 | 
        } 
 | 
  
 | 
        /* Point to DMP Control */ 
 | 
        io = (dmp_regs_t*)(NCI_ADD_ADDR(io, nci->cores[sii->curidx].dmp_regs_off)); 
 | 
  
 | 
        if (mask || val) { 
 | 
            w = ((R_REG(sii->osh, &io->dmpctrl) & ~mask) | val); 
 | 
            W_REG(sii->osh, &io->dmpctrl, w); 
 | 
        } 
 | 
  
 | 
        reg_read = R_REG(sii->osh, &io->dmpctrl); 
 | 
  
 | 
        /* Point back to original base */ 
 | 
        if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, 
 | 
                PCI_ACCESS_SIZE, orig_bar0_win1); 
 | 
        } 
 | 
  
 | 
        return reg_read; 
 | 
    } 
 | 
} 
 | 
  
 | 
void 
 | 
BCMPOSTTRAPFN(nci_core_cflags_wo)(const si_t *sih, uint32 mask, uint32 val) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *core = &nci->cores[sii->curidx]; 
 | 
    volatile dmp_regs_t *io = sii->curwrap; 
 | 
    uint32 orig_bar0_win1 = 0; 
 | 
    int32 iface_idx; 
 | 
    uint32 w; 
 | 
  
 | 
    BCM_REFERENCE(iface_idx); 
 | 
  
 | 
    if ((core[sii->curidx].coreid) == PMU_CORE_ID) { 
 | 
        NCI_ERROR(("nci_core_cflags: Accessing PMU DMP register (ioctrl)\n")); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    ASSERT(GOODREGS(sii->curwrap)); 
 | 
    ASSERT((val & ~mask) == 0); 
 | 
  
 | 
#ifdef BOOKER_NIC400_INF 
 | 
    iface_idx = nci_find_first_wrapper_idx(nci, sii->curidx); 
 | 
    if (iface_idx < 0) { 
 | 
        NCI_ERROR(("nci_core_cflags_wo: First Wrapper is not found\n")); 
 | 
        ASSERT(0u); 
 | 
        return; 
 | 
    } 
 | 
  
 | 
    /* If Wrapper is of NIC400, then call AI functionality */ 
 | 
    if (core->desc[iface_idx].master && (core->desc[iface_idx].node_type == NODE_TYPE_NIC400)) { 
 | 
        aidmp_t *ai = sii->curwrap; 
 | 
        if (mask || val) { 
 | 
            w = ((R_REG(sii->osh, &ai->ioctrl) & ~mask) | val); 
 | 
            W_REG(sii->osh, &ai->ioctrl, w); 
 | 
        } 
 | 
    } else 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
    { 
 | 
        /* BOOKER */ 
 | 
        /* Point to OOBR base */ 
 | 
        switch (BUSTYPE(sih->bustype)) { 
 | 
        case SI_BUS: 
 | 
            io = (volatile dmp_regs_t*) 
 | 
                REG_MAP(GET_OOBR_BASE(nci->cc_erom2base), SI_CORE_SIZE); 
 | 
            break; 
 | 
  
 | 
        case PCI_BUS: 
 | 
            /* Save Original Bar0 Win1 */ 
 | 
            orig_bar0_win1 = 
 | 
                OSL_PCI_READ_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE); 
 | 
  
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
                GET_OOBR_BASE(nci->cc_erom2base)); 
 | 
            io = (volatile dmp_regs_t*)sii->curmap; 
 | 
            break; 
 | 
  
 | 
        default: 
 | 
            NCI_ERROR(("nci_core_cflags_wo Invalid bustype %d\n", 
 | 
                BUSTYPE(sih->bustype))); 
 | 
            break; 
 | 
        } 
 | 
  
 | 
        /* Point to DMP Control */ 
 | 
        io = (dmp_regs_t*)(NCI_ADD_ADDR(io, nci->cores[sii->curidx].dmp_regs_off)); 
 | 
  
 | 
        if (mask || val) { 
 | 
            w = ((R_REG(sii->osh, &io->dmpctrl) & ~mask) | val); 
 | 
            W_REG(sii->osh, &io->dmpctrl, w); 
 | 
        } 
 | 
  
 | 
        /* Point back to original base */ 
 | 
        if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, 
 | 
                PCI_ACCESS_SIZE, orig_bar0_win1); 
 | 
        } 
 | 
    } 
 | 
} 
 | 
  
 | 
uint32 
 | 
nci_core_sflags(const si_t *sih, uint32 mask, uint32 val) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    nci_cores_t *core = &nci->cores[sii->curidx]; 
 | 
    uint32 orig_bar0_win1 = 0; 
 | 
    int32 iface_idx; 
 | 
    uint32 w; 
 | 
  
 | 
    BCM_REFERENCE(iface_idx); 
 | 
  
 | 
    if ((core[sii->curidx].coreid) == PMU_CORE_ID) { 
 | 
        NCI_ERROR(("nci_core_sflags: Accessing PMU DMP register (ioctrl)\n")); 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    ASSERT(GOODREGS(sii->curwrap)); 
 | 
  
 | 
    ASSERT((val & ~mask) == 0); 
 | 
    ASSERT((mask & ~SISF_CORE_BITS) == 0); 
 | 
  
 | 
#ifdef BOOKER_NIC400_INF 
 | 
    iface_idx = nci_find_first_wrapper_idx(nci, sii->curidx); 
 | 
    if (iface_idx < 0) { 
 | 
        NCI_ERROR(("nci_core_sflags: First Wrapper is not found\n")); 
 | 
        ASSERT(0u); 
 | 
        return 0u; 
 | 
    } 
 | 
  
 | 
    /* If Wrapper is of NIC400, then call AI functionality */ 
 | 
    if (core->desc[iface_idx].master && (core->desc[iface_idx].node_type == NODE_TYPE_NIC400)) { 
 | 
        aidmp_t *ai = sii->curwrap; 
 | 
        if (mask || val) { 
 | 
            w = ((R_REG(sii->osh, &ai->iostatus) & ~mask) | val); 
 | 
            W_REG(sii->osh, &ai->iostatus, w); 
 | 
        } 
 | 
  
 | 
        return R_REG(sii->osh, &ai->iostatus); 
 | 
    } else 
 | 
#endif /* BOOKER_NIC400_INF */ 
 | 
    { 
 | 
        volatile dmp_regs_t *io = sii->curwrap; 
 | 
        volatile uint32 reg_read; 
 | 
  
 | 
        /* BOOKER */ 
 | 
        /* Point to OOBR base */ 
 | 
        switch (BUSTYPE(sih->bustype)) { 
 | 
        case SI_BUS: 
 | 
            io = (volatile dmp_regs_t*) 
 | 
                REG_MAP(GET_OOBR_BASE(nci->cc_erom2base), SI_CORE_SIZE); 
 | 
            break; 
 | 
  
 | 
        case PCI_BUS: 
 | 
            /* Save Original Bar0 Win1 */ 
 | 
            orig_bar0_win1 = 
 | 
                OSL_PCI_READ_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE); 
 | 
  
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, PCI_ACCESS_SIZE, 
 | 
            GET_OOBR_BASE(nci->cc_erom2base)); 
 | 
            io = (volatile dmp_regs_t*)sii->curmap; 
 | 
            break; 
 | 
  
 | 
        default: 
 | 
            NCI_ERROR(("nci_core_sflags Invalid bustype %d\n", BUSTYPE(sih->bustype))); 
 | 
            return 0u; 
 | 
        } 
 | 
  
 | 
        /* Point to DMP Control */ 
 | 
        io = (dmp_regs_t*)(NCI_ADD_ADDR(io, nci->cores[sii->curidx].dmp_regs_off)); 
 | 
  
 | 
        if (mask || val) { 
 | 
            w = ((R_REG(sii->osh, &io->dmpstatus) & ~mask) | val); 
 | 
            W_REG(sii->osh, &io->dmpstatus, w); 
 | 
        } 
 | 
  
 | 
        reg_read = R_REG(sii->osh, &io->dmpstatus); 
 | 
  
 | 
        /* Point back to original base */ 
 | 
        if (BUSTYPE(sih->bustype) == PCI_BUS) { 
 | 
            OSL_PCI_WRITE_CONFIG(nci->osh, PCI_BAR0_WIN, 
 | 
                PCI_ACCESS_SIZE, orig_bar0_win1); 
 | 
        } 
 | 
  
 | 
        return reg_read; 
 | 
    } 
 | 
} 
 | 
  
 | 
/* TODO: Used only by host */ 
 | 
int 
 | 
nci_backplane_access(si_t *sih, uint addr, uint size, uint *val, bool read) 
 | 
{ 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
int 
 | 
nci_backplane_access_64(si_t *sih, uint addr, uint size, uint64 *val, bool read) 
 | 
{ 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
uint 
 | 
nci_num_slaveports(const si_t *sih, uint coreidx) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    const nci_cores_t *core_info = (const nci_cores_t *)&nci->cores[coreidx]; 
 | 
    uint32 iface_idx; 
 | 
    uint32 numports = 0; 
 | 
  
 | 
    NCI_TRACE(("nci_get_curmap coreidx %u\n", coreidx)); 
 | 
    for (iface_idx = 0; iface_idx < core_info->iface_cnt; iface_idx++) { 
 | 
    NCI_TRACE(("nci_get_curmap iface_idx %u BP_ID %u master %u\n", 
 | 
        iface_idx, ID_BPID(core_info->desc[iface_idx].iface_desc_1), 
 | 
        IS_MASTER(core_info->desc[iface_idx].iface_desc_1))); 
 | 
        /* hack for core idx 8, coreidx without APB Backplane ID */ 
 | 
        if (IS_MASTER(core_info->desc[iface_idx].iface_desc_1)) { 
 | 
            continue; 
 | 
        } 
 | 
        if ((ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_APB1) || 
 | 
            (ID_BPID(core_info->desc[iface_idx].iface_desc_1) == BP_APB2)) { 
 | 
            break; 
 | 
        } 
 | 
    } 
 | 
    if (iface_idx < core_info->iface_cnt) { 
 | 
        numports = core_info->desc[iface_idx].num_addr_reg; 
 | 
    } 
 | 
    return numports; 
 | 
} 
 | 
  
 | 
#if defined(BCMDBG) || defined(BCMDBG_DUMP) || defined(BCMDBG_PHYDUMP) 
 | 
void 
 | 
nci_dumpregs(const si_t *sih, struct bcmstrbuf *b) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
  
 | 
    bcm_bprintf(b, "ChipNum:%x, ChipRev;%x, BusType:%x, BoardType:%x, BoardVendor:%x\n\n", 
 | 
            sih->chip, sih->chiprev, sih->bustype, sih->boardtype, sih->boardvendor); 
 | 
    BCM_REFERENCE(sii); 
 | 
    /* TODO: Implement dump regs for nci. */ 
 | 
} 
 | 
#endif  /* BCMDBG || BCMDBG_DUMP || BCMDBG_PHYDUMP */ 
 | 
  
 | 
#ifdef BCMDBG 
 | 
static void 
 | 
_nci_view(osl_t *osh, aidmp_t *ai, uint32 cid, uint32 addr, bool verbose) 
 | 
{ 
 | 
    /* TODO: This is WIP and will be developed once the 
 | 
     * implementation is done based on the NCI. 
 | 
     */ 
 | 
} 
 | 
  
 | 
void 
 | 
nci_view(si_t *sih, bool verbose) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    const nci_cores_t *core_info = (const nci_cores_t *)nci->cores; 
 | 
    osl_t *osh; 
 | 
    /* TODO: We need to do the structure mapping correctly based on the BOOKER/NIC type */ 
 | 
    aidmp_t *ai; 
 | 
    uint32 cid, addr; 
 | 
  
 | 
    ai = sii->curwrap; 
 | 
    osh = sii->osh; 
 | 
  
 | 
    if ((core_info[sii->curidx].coreid) == PMU_CORE_ID) { 
 | 
        SI_ERROR(("Cannot access pmu DMP\n")); 
 | 
        return; 
 | 
    } 
 | 
    cid = core_info[sii->curidx].coreid; 
 | 
    addr = nci_get_nth_wrapper(sih, 0u); 
 | 
    _nci_view(osh, ai, cid, addr, verbose); 
 | 
} 
 | 
  
 | 
void 
 | 
nci_viewall(si_t *sih, bool verbose) 
 | 
{ 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    nci_info_t *nci = sii->nci_info; 
 | 
    const nci_cores_t *core_info = (const nci_cores_t *)nci->cores; 
 | 
    osl_t *osh; 
 | 
    aidmp_t *ai; 
 | 
    uint32 cid, addr; 
 | 
    uint i; 
 | 
  
 | 
    osh = sii->osh; 
 | 
    for (i = 0; i < sii->numcores; i++) { 
 | 
        nci_setcoreidx(sih, i); 
 | 
  
 | 
        if ((core_info[i].coreid) == PMU_CORE_ID) { 
 | 
            SI_ERROR(("Skipping pmu DMP\n")); 
 | 
            continue; 
 | 
        } 
 | 
        ai = sii->curwrap; 
 | 
        cid = core_info[i].coreid; 
 | 
        addr = nci_get_nth_wrapper(sih, 0u); 
 | 
        _nci_view(osh, ai, cid, addr, verbose); 
 | 
    } 
 | 
} 
 | 
#endif /* BCMDBG */ 
 | 
  
 | 
uint32 
 | 
nci_clear_backplane_to(si_t *sih) 
 | 
{ 
 | 
    /* TODO: This is WIP and will be developed once the 
 | 
     * implementation is done based on the NCI. 
 | 
     */ 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
#if defined (AXI_TIMEOUTS) || defined (AXI_TIMEOUTS_NIC) 
 | 
static bool g_disable_backplane_logs = FALSE; 
 | 
  
 | 
static uint32 last_axi_error = AXI_WRAP_STS_NONE; 
 | 
static uint32 last_axi_error_log_status = 0; 
 | 
static uint32 last_axi_error_core = 0; 
 | 
static uint32 last_axi_error_wrap = 0; 
 | 
static uint32 last_axi_errlog_lo = 0; 
 | 
static uint32 last_axi_errlog_hi = 0; 
 | 
static uint32 last_axi_errlog_id = 0; 
 | 
  
 | 
/* slave error is ignored, so account for those cases */ 
 | 
static uint32 si_ignore_errlog_cnt = 0; 
 | 
  
 | 
static void 
 | 
nci_reset_APB(const si_info_t *sii, aidmp_t *ai, int *ret, 
 | 
        uint32 errlog_status, uint32 errlog_id) 
 | 
{ 
 | 
    /* only reset APB Bridge on timeout (not slave error, or dec error) */ 
 | 
    switch (errlog_status & AIELS_ERROR_MASK) { 
 | 
    case AIELS_SLAVE_ERR: 
 | 
        NCI_PRINT(("AXI slave error\n")); 
 | 
        *ret |= AXI_WRAP_STS_SLAVE_ERR; 
 | 
        break; 
 | 
  
 | 
    case AIELS_TIMEOUT: 
 | 
        nci_reset_axi_to(sii, ai); 
 | 
        *ret |= AXI_WRAP_STS_TIMEOUT; 
 | 
        break; 
 | 
  
 | 
    case AIELS_DECODE: 
 | 
        NCI_PRINT(("AXI decode error\n")); 
 | 
#ifdef USE_HOSTMEM 
 | 
        /* Ignore known cases of CR4 prefetch abort bugs */ 
 | 
        if ((errlog_id & (BCM_AXI_ID_MASK | BCM_AXI_ACCESS_TYPE_MASK)) != 
 | 
                (BCM43xx_AXI_ACCESS_TYPE_PREFETCH | BCM43xx_CR4_AXI_ID)) 
 | 
#endif /* USE_HOSTMEM */ 
 | 
        { 
 | 
            *ret |= AXI_WRAP_STS_DECODE_ERR; 
 | 
        } 
 | 
        break; 
 | 
    default: 
 | 
        ASSERT(0);    /* should be impossible */ 
 | 
    } 
 | 
    if (errlog_status & AIELS_MULTIPLE_ERRORS) { 
 | 
        NCI_PRINT(("Multiple AXI Errors\n")); 
 | 
        /* Set multiple errors bit only if actual error is not ignored */ 
 | 
        if (*ret) { 
 | 
            *ret |= AXI_WRAP_STS_MULTIPLE_ERRORS; 
 | 
        } 
 | 
    } 
 | 
    return; 
 | 
} 
 | 
/* 
 | 
 * API to clear the back plane timeout per core. 
 | 
 * Caller may passs optional wrapper address. If present this will be used as 
 | 
 * the wrapper base address. If wrapper base address is provided then caller 
 | 
 * must provide the coreid also. 
 | 
 * If both coreid and wrapper is zero, then err status of current bridge 
 | 
 * will be verified. 
 | 
 */ 
 | 
  
 | 
uint32 
 | 
nci_clear_backplane_to_per_core(si_t *sih, uint coreid, uint coreunit, void *wrap) 
 | 
{ 
 | 
    int ret = AXI_WRAP_STS_NONE; 
 | 
    aidmp_t *ai = NULL; 
 | 
    uint32 errlog_status = 0; 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
    uint32 errlog_lo = 0, errlog_hi = 0, errlog_id = 0, errlog_flags = 0; 
 | 
    uint32 current_coreidx = si_coreidx(sih); 
 | 
    uint32 target_coreidx = nci_findcoreidx(sih, coreid, coreunit); 
 | 
  
 | 
#if defined(AXI_TIMEOUTS_NIC) 
 | 
    si_axi_error_t * axi_error = sih->err_info ? 
 | 
        &sih->err_info->axi_error[sih->err_info->count] : NULL; 
 | 
#endif /* AXI_TIMEOUTS_NIC */ 
 | 
    bool restore_core = FALSE; 
 | 
  
 | 
    if ((sii->axi_num_wrappers == 0) || 
 | 
#ifdef AXI_TIMEOUTS_NIC 
 | 
        (!PCIE(sii)) || 
 | 
#endif /* AXI_TIMEOUTS_NIC */ 
 | 
        FALSE) { 
 | 
        SI_VMSG(("nci_clear_backplane_to_per_core, axi_num_wrappers:%d, Is_PCIE:%d," 
 | 
            " BUS_TYPE:%d, ID:%x\n", 
 | 
            sii->axi_num_wrappers, PCIE(sii), 
 | 
            BUSTYPE(sii->pub.bustype), sii->pub.buscoretype)); 
 | 
        return AXI_WRAP_STS_NONE; 
 | 
    } 
 | 
  
 | 
    if (wrap != NULL) { 
 | 
        ai = (aidmp_t *)wrap; 
 | 
    } else if (coreid && (target_coreidx != current_coreidx)) { 
 | 
        if (nci_setcoreidx(sih, target_coreidx) == NULL) { 
 | 
            /* Unable to set the core */ 
 | 
            NCI_PRINT(("Set Code Failed: coreid:%x, unit:%d, target_coreidx:%d\n", 
 | 
                coreid, coreunit, target_coreidx)); 
 | 
            errlog_lo = target_coreidx; 
 | 
            ret = AXI_WRAP_STS_SET_CORE_FAIL; 
 | 
            goto end; 
 | 
        } 
 | 
        restore_core = TRUE; 
 | 
        ai = (aidmp_t *)si_wrapperregs(sih); 
 | 
    } else { 
 | 
        /* Read error status of current wrapper */ 
 | 
        ai = (aidmp_t *)si_wrapperregs(sih); 
 | 
  
 | 
        /* Update CoreID to current Code ID */ 
 | 
        coreid = nci_coreid(sih, sii->curidx); 
 | 
    } 
 | 
  
 | 
    /* read error log status */ 
 | 
    errlog_status = R_REG(sii->osh, &ai->errlogstatus); 
 | 
  
 | 
    if (errlog_status == ID32_INVALID) { 
 | 
        /* Do not try to peek further */ 
 | 
        NCI_PRINT(("nci_clear_backplane_to_per_core, errlogstatus:%x - " 
 | 
                "Slave Wrapper:%x\n", errlog_status, coreid)); 
 | 
        ret = AXI_WRAP_STS_WRAP_RD_ERR; 
 | 
        errlog_lo = (uint32)(uintptr)&ai->errlogstatus; 
 | 
        goto end; 
 | 
    } 
 | 
  
 | 
    if ((errlog_status & AIELS_ERROR_MASK) != 0) { 
 | 
        uint32 tmp; 
 | 
        uint32 count = 0; 
 | 
        /* set ErrDone to clear the condition */ 
 | 
        W_REG(sii->osh, &ai->errlogdone, AIELD_ERRDONE_MASK); 
 | 
  
 | 
        /* SPINWAIT on errlogstatus timeout status bits */ 
 | 
        while ((tmp = R_REG(sii->osh, &ai->errlogstatus)) & AIELS_ERROR_MASK) { 
 | 
  
 | 
            if (tmp == ID32_INVALID) { 
 | 
                NCI_PRINT(("nci_clear_backplane_to_per_core: prev errlogstatus:%x," 
 | 
                            " errlogstatus:%x\n", 
 | 
                            errlog_status, tmp)); 
 | 
                ret = AXI_WRAP_STS_WRAP_RD_ERR; 
 | 
  
 | 
                errlog_lo = (uint32)(uintptr)&ai->errlogstatus; 
 | 
                goto end; 
 | 
            } 
 | 
            /* 
 | 
             * Clear again, to avoid getting stuck in the loop, if a new error 
 | 
             * is logged after we cleared the first timeout 
 | 
             */ 
 | 
            W_REG(sii->osh, &ai->errlogdone, AIELD_ERRDONE_MASK); 
 | 
  
 | 
            count++; 
 | 
            OSL_DELAY(10); 
 | 
            if ((10 * count) > AI_REG_READ_TIMEOUT) { 
 | 
                errlog_status = tmp; 
 | 
                break; 
 | 
            } 
 | 
        } 
 | 
  
 | 
        errlog_lo = R_REG(sii->osh, &ai->errlogaddrlo); 
 | 
        errlog_hi = R_REG(sii->osh, &ai->errlogaddrhi); 
 | 
        errlog_id = R_REG(sii->osh, &ai->errlogid); 
 | 
        errlog_flags = R_REG(sii->osh, &ai->errlogflags); 
 | 
  
 | 
        /* we are already in the error path, so OK to check for the  slave error */ 
 | 
        if (nci_ignore_errlog(sii, ai, errlog_lo, errlog_hi, errlog_id,    errlog_status)) { 
 | 
            si_ignore_errlog_cnt++; 
 | 
            goto end; 
 | 
        } 
 | 
  
 | 
        nci_reset_APB(sii, ai, &ret, errlog_status, errlog_id); 
 | 
  
 | 
        NCI_PRINT(("\tCoreID: %x\n", coreid)); 
 | 
        NCI_PRINT(("\t errlog: lo 0x%08x, hi 0x%08x, id 0x%08x, flags 0x%08x" 
 | 
                    ", status 0x%08x\n", 
 | 
                    errlog_lo, errlog_hi, errlog_id, errlog_flags, 
 | 
                    errlog_status)); 
 | 
    } 
 | 
  
 | 
end: 
 | 
    if (ret != AXI_WRAP_STS_NONE) { 
 | 
        last_axi_error = ret; 
 | 
        last_axi_error_log_status = errlog_status; 
 | 
        last_axi_error_core = coreid; 
 | 
        last_axi_error_wrap = (uint32)ai; 
 | 
        last_axi_errlog_lo = errlog_lo; 
 | 
        last_axi_errlog_hi = errlog_hi; 
 | 
        last_axi_errlog_id = errlog_id; 
 | 
    } 
 | 
  
 | 
#if defined(AXI_TIMEOUTS_NIC) 
 | 
    if (axi_error && (ret != AXI_WRAP_STS_NONE)) { 
 | 
        axi_error->error = ret; 
 | 
        axi_error->coreid = coreid; 
 | 
        axi_error->errlog_lo = errlog_lo; 
 | 
        axi_error->errlog_hi = errlog_hi; 
 | 
        axi_error->errlog_id = errlog_id; 
 | 
        axi_error->errlog_flags = errlog_flags; 
 | 
        axi_error->errlog_status = errlog_status; 
 | 
        sih->err_info->count++; 
 | 
  
 | 
        if (sih->err_info->count == SI_MAX_ERRLOG_SIZE) { 
 | 
            sih->err_info->count = SI_MAX_ERRLOG_SIZE - 1; 
 | 
            NCI_PRINT(("AXI Error log overflow\n")); 
 | 
        } 
 | 
    } 
 | 
#endif /* AXI_TIMEOUTS_NIC */ 
 | 
  
 | 
    if (restore_core) { 
 | 
        if (nci_setcoreidx(sih, current_coreidx) == NULL) { 
 | 
            /* Unable to set the core */ 
 | 
            return ID32_INVALID; 
 | 
        } 
 | 
    } 
 | 
    return ret; 
 | 
} 
 | 
  
 | 
/* TODO: It needs to be handled based on BOOKER/NCI DMP. */ 
 | 
/* reset AXI timeout */ 
 | 
static void 
 | 
nci_reset_axi_to(const si_info_t *sii, aidmp_t *ai) 
 | 
{ 
 | 
    /* reset APB Bridge */ 
 | 
    OR_REG(sii->osh, &ai->resetctrl, AIRC_RESET); 
 | 
    /* sync write */ 
 | 
    (void)R_REG(sii->osh, &ai->resetctrl); 
 | 
    /* clear Reset bit */ 
 | 
    AND_REG(sii->osh, &ai->resetctrl, ~(AIRC_RESET)); 
 | 
    /* sync write */ 
 | 
    (void)R_REG(sii->osh, &ai->resetctrl); 
 | 
    NCI_PRINT(("AXI timeout\n")); 
 | 
    if (R_REG(sii->osh, &ai->resetctrl) & AIRC_RESET) { 
 | 
        NCI_PRINT(("reset failed on wrapper %p\n", ai)); 
 | 
        g_disable_backplane_logs = TRUE; 
 | 
    } 
 | 
} 
 | 
  
 | 
void 
 | 
nci_wrapper_get_last_error(const si_t *sih, uint32 *error_status, uint32 *core, uint32 *lo, 
 | 
    uint32 *hi, uint32 *id) 
 | 
{ 
 | 
    *error_status = last_axi_error_log_status; 
 | 
    *core = last_axi_error_core; 
 | 
    *lo = last_axi_errlog_lo; 
 | 
    *hi = last_axi_errlog_hi; 
 | 
    *id = last_axi_errlog_id; 
 | 
} 
 | 
  
 | 
uint32 
 | 
nci_get_axi_timeout_reg(void) 
 | 
{ 
 | 
    return (GOODREGS(last_axi_errlog_lo) ? last_axi_errlog_lo : 0); 
 | 
} 
 | 
#endif /* AXI_TIMEOUTS || AXI_TIMEOUTS_NIC */ 
 | 
  
 | 
/* TODO: This function should be able to handle NIC as well as BOOKER */ 
 | 
bool 
 | 
nci_ignore_errlog(const si_info_t *sii, const aidmp_t *ai, 
 | 
    uint32 lo_addr, uint32 hi_addr, uint32 err_axi_id, uint32 errsts) 
 | 
{ 
 | 
    uint32 ignore_errsts = AIELS_SLAVE_ERR; 
 | 
    uint32 ignore_errsts_2 = 0; 
 | 
    uint32 ignore_hi = BT_CC_SPROM_BADREG_HI; 
 | 
    uint32 ignore_lo = BT_CC_SPROM_BADREG_LO; 
 | 
    uint32 ignore_size = BT_CC_SPROM_BADREG_SIZE; 
 | 
    bool address_check = TRUE; 
 | 
    uint32 axi_id = 0; 
 | 
    uint32 axi_id2 = 0; 
 | 
    bool extd_axi_id_mask = FALSE; 
 | 
    uint32 axi_id_mask; 
 | 
  
 | 
    NCI_PRINT(("err check: core %p, error %d, axi id 0x%04x, addr(0x%08x:%08x)\n", 
 | 
        ai, errsts, err_axi_id, hi_addr, lo_addr)); 
 | 
  
 | 
    /* ignore the BT slave errors if the errlog is to chipcommon addr 0x190 */ 
 | 
    switch (CHIPID(sii->pub.chip)) { 
 | 
        case BCM4397_CHIP_GRPID:    /* TODO: Are these IDs same for 4397 as well? */ 
 | 
#ifdef BTOVERPCIE 
 | 
            axi_id = BCM4378_BT_AXI_ID; 
 | 
            /* For BT over PCIE, ignore any slave error from BT. */ 
 | 
            /* No need to check any address range */ 
 | 
            address_check = FALSE; 
 | 
#endif /* BTOVERPCIE */ 
 | 
            axi_id2 = BCM4378_ARM_PREFETCH_AXI_ID; 
 | 
            extd_axi_id_mask = TRUE; 
 | 
            ignore_errsts_2 = AIELS_DECODE; 
 | 
            break; 
 | 
        default: 
 | 
            return FALSE; 
 | 
    } 
 | 
  
 | 
    axi_id_mask = extd_axi_id_mask ? AI_ERRLOGID_AXI_ID_MASK_EXTD : AI_ERRLOGID_AXI_ID_MASK; 
 | 
  
 | 
    /* AXI ID check */ 
 | 
    err_axi_id &= axi_id_mask; 
 | 
    errsts &=  AIELS_ERROR_MASK; 
 | 
  
 | 
    /* check the ignore error cases. 2 checks */ 
 | 
    if (!(((err_axi_id == axi_id) && (errsts == ignore_errsts)) || 
 | 
        ((err_axi_id == axi_id2) && (errsts == ignore_errsts_2)))) { 
 | 
        /* not the error ignore cases */ 
 | 
        return FALSE; 
 | 
  
 | 
    } 
 | 
  
 | 
    /* check the specific address checks now, if specified */ 
 | 
    if (address_check) { 
 | 
        /* address range check */ 
 | 
        if ((hi_addr != ignore_hi) || 
 | 
            (lo_addr < ignore_lo) || (lo_addr >= (ignore_lo + ignore_size))) { 
 | 
            return FALSE; 
 | 
        } 
 | 
    } 
 | 
  
 | 
    NCI_PRINT(("err check: ignored\n")); 
 | 
    return TRUE; 
 | 
} 
 | 
  
 | 
/* TODO: Check the CORE to AXI ID mapping for 4397 */ 
 | 
uint32 
 | 
nci_findcoreidx_by_axiid(const si_t *sih, uint32 axiid) 
 | 
{ 
 | 
    uint coreid = 0; 
 | 
    uint coreunit = 0; 
 | 
    const nci_axi_to_coreidx_t *axi2coreidx = NULL; 
 | 
    switch (CHIPID(sih->chip)) { 
 | 
    case BCM4397_CHIP_GRPID: 
 | 
        axi2coreidx = axi2coreidx_4397; 
 | 
        break; 
 | 
    default: 
 | 
        NCI_PRINT(("Chipid mapping not found\n")); 
 | 
        break; 
 | 
    } 
 | 
  
 | 
    if (!axi2coreidx) { 
 | 
        return (BADIDX); 
 | 
    } 
 | 
  
 | 
    coreid = axi2coreidx[axiid].coreid; 
 | 
    coreunit = axi2coreidx[axiid].coreunit; 
 | 
  
 | 
    return nci_findcoreidx(sih, coreid, coreunit); 
 | 
} 
 | 
  
 | 
void nci_coreaddrspaceX(const si_t *sih, uint asidx, uint32 *addr, uint32 *size) 
 | 
{ 
 | 
    /* Adding just a wrapper. Will implement when required. */ 
 | 
} 
 | 
  
 | 
/* 
 | 
 * this is not declared as static const, although that is the right thing to do 
 | 
 * reason being if declared as static const, compile/link process would that in 
 | 
 * read only section... 
 | 
 * currently this code/array is used to identify the registers which are dumped 
 | 
 * during trap processing 
 | 
 * and usually for the trap buffer, .rodata buffer is reused,  so for now just static 
 | 
*/ 
 | 
/* TODO: Should we do another mapping for BOOKER and used correct one based on type of DMP. */ 
 | 
#ifdef DONGLEBUILD 
 | 
static uint32 BCMPOST_TRAP_RODATA(wrapper_offsets_to_dump)[] = { 
 | 
    OFFSETOF(aidmp_t, ioctrl), 
 | 
    OFFSETOF(aidmp_t, iostatus), 
 | 
    OFFSETOF(aidmp_t, resetctrl), 
 | 
    OFFSETOF(aidmp_t, resetstatus), 
 | 
    OFFSETOF(aidmp_t, resetreadid), 
 | 
    OFFSETOF(aidmp_t, resetwriteid), 
 | 
    OFFSETOF(aidmp_t, errlogctrl), 
 | 
    OFFSETOF(aidmp_t, errlogdone), 
 | 
    OFFSETOF(aidmp_t, errlogstatus), 
 | 
    OFFSETOF(aidmp_t, errlogaddrlo), 
 | 
    OFFSETOF(aidmp_t, errlogaddrhi), 
 | 
    OFFSETOF(aidmp_t, errlogid), 
 | 
    OFFSETOF(aidmp_t, errloguser), 
 | 
    OFFSETOF(aidmp_t, errlogflags), 
 | 
    OFFSETOF(aidmp_t, itipoobaout), 
 | 
    OFFSETOF(aidmp_t, itipoobbout), 
 | 
    OFFSETOF(aidmp_t, itipoobcout), 
 | 
    OFFSETOF(aidmp_t, itipoobdout) 
 | 
}; 
 | 
  
 | 
static uint32 
 | 
BCMRAMFN(nci_get_sizeof_wrapper_offsets_to_dump)(void) 
 | 
{ 
 | 
    return (sizeof(wrapper_offsets_to_dump)); 
 | 
} 
 | 
  
 | 
static uint32 
 | 
BCMRAMFN(nci_get_wrapper_base_addr)(uint32 **offset) 
 | 
{ 
 | 
    uint32 arr_size = ARRAYSIZE(wrapper_offsets_to_dump); 
 | 
  
 | 
    *offset = &wrapper_offsets_to_dump[0]; 
 | 
    return arr_size; 
 | 
} 
 | 
  
 | 
#ifdef UART_TRAP_DBG 
 | 
/* TODO: Is br_wrapba populated for 4397 NCI? */ 
 | 
void 
 | 
nci_dump_APB_Bridge_registers(const si_t *sih) 
 | 
{ 
 | 
    aidmp_t *ai; 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
  
 | 
    ai = (aidmp_t *)sii->br_wrapba[0]; 
 | 
    printf("APB Bridge 0\n"); 
 | 
    printf("lo 0x%08x, hi 0x%08x, id 0x%08x, flags 0x%08x", 
 | 
        R_REG(sii->osh, &ai->errlogaddrlo), 
 | 
        R_REG(sii->osh, &ai->errlogaddrhi), 
 | 
        R_REG(sii->osh, &ai->errlogid), 
 | 
        R_REG(sii->osh, &ai->errlogflags)); 
 | 
    printf("\n status 0x%08x\n", R_REG(sii->osh, &ai->errlogstatus)); 
 | 
} 
 | 
#endif /* UART_TRAP_DBG */ 
 | 
  
 | 
uint32 
 | 
BCMATTACHFN(nci_wrapper_dump_buf_size)(const si_t *sih) 
 | 
{ 
 | 
    uint32 buf_size = 0; 
 | 
    uint32 wrapper_count = 0; 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
  
 | 
    wrapper_count = sii->axi_num_wrappers; 
 | 
    if (wrapper_count == 0) { 
 | 
        return 0; 
 | 
    } 
 | 
  
 | 
    /* cnt indicates how many registers, tag_id 0 will say these are address/value */ 
 | 
    /* address/value pairs */ 
 | 
    buf_size += 2 * (nci_get_sizeof_wrapper_offsets_to_dump() * wrapper_count); 
 | 
  
 | 
    return buf_size; 
 | 
} 
 | 
  
 | 
uint32* 
 | 
nci_wrapper_dump_binary_one(const si_info_t *sii, uint32 *p32, uint32 wrap_ba) 
 | 
{ 
 | 
    uint i; 
 | 
    uint32 *addr; 
 | 
    uint32 arr_size; 
 | 
    uint32 *offset_base; 
 | 
  
 | 
    arr_size = nci_get_wrapper_base_addr(&offset_base); 
 | 
  
 | 
    for (i = 0; i < arr_size; i++) { 
 | 
        addr = (uint32 *)(wrap_ba + *(offset_base + i)); 
 | 
        *p32++ = (uint32)addr; 
 | 
        *p32++ = R_REG(sii->osh, addr); 
 | 
    } 
 | 
    return p32; 
 | 
} 
 | 
  
 | 
uint32 
 | 
nci_wrapper_dump_binary(const si_t *sih, uchar *p) 
 | 
{ 
 | 
    uint32 *p32 = (uint32 *)p; 
 | 
    uint32 i; 
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
  
 | 
    for (i = 0; i < sii->axi_num_wrappers; i++) { 
 | 
        p32 = nci_wrapper_dump_binary_one(sii, p32, sii->axi_wrapper[i].wrapper_addr); 
 | 
    } 
 | 
    return 0; 
 | 
} 
 | 
  
 | 
#if defined(ETD) 
 | 
uint32 
 | 
nci_wrapper_dump_last_timeout(const si_t *sih, uint32 *error, uint32 *core, uint32 *ba, uchar *p) 
 | 
{ 
 | 
#if defined (AXI_TIMEOUTS) || defined (AXI_TIMEOUTS_NIC) 
 | 
    uint32 *p32; 
 | 
    uint32 wrap_ba = last_axi_error_wrap; 
 | 
    uint i; 
 | 
    uint32 *addr; 
 | 
  
 | 
    const si_info_t *sii = SI_INFO(sih); 
 | 
  
 | 
    if (last_axi_error != AXI_WRAP_STS_NONE) { 
 | 
        if (wrap_ba) { 
 | 
            p32 = (uint32 *)p; 
 | 
            uint32 arr_size; 
 | 
            uint32 *offset_base; 
 | 
  
 | 
            arr_size = nci_get_wrapper_base_addr(&offset_base); 
 | 
            for (i = 0; i < arr_size; i++) { 
 | 
                addr = (uint32 *)(wrap_ba + *(offset_base + i)); 
 | 
                *p32++ = R_REG(sii->osh, addr); 
 | 
            } 
 | 
        } 
 | 
        *error = last_axi_error; 
 | 
        *core = last_axi_error_core; 
 | 
        *ba = wrap_ba; 
 | 
    } 
 | 
#else 
 | 
    *error = 0; 
 | 
    *core = 0; 
 | 
    *ba = 0; 
 | 
#endif /* AXI_TIMEOUTS || AXI_TIMEOUTS_NIC */ 
 | 
    return 0; 
 | 
} 
 | 
#endif /* ETD */ 
 | 
  
 | 
bool 
 | 
nci_check_enable_backplane_log(const si_t *sih) 
 | 
{ 
 | 
#if defined (AXI_TIMEOUTS) || defined (AXI_TIMEOUTS_NIC) 
 | 
    if (g_disable_backplane_logs) { 
 | 
        return FALSE; 
 | 
    } 
 | 
    else { 
 | 
        return TRUE; 
 | 
    } 
 | 
#else /*  (AXI_TIMEOUTS) || defined (AXI_TIMEOUTS_NIC) */ 
 | 
    return FALSE; 
 | 
#endif /*  (AXI_TIMEOUTS) || defined (AXI_TIMEOUTS_NIC) */ 
 | 
} 
 | 
#endif /* DONGLEBUILD */ 
 |