soc/cavium: import raw BDK sources

This imports common BDK sources that will be used in subsequent
patches.
The BDK is licensed under BSD and will be reduced in size and optimized to
compile under coreboot.

Change-Id: Icb32ee670d9fa9e5c10f9abb298cebf616fa67ad
Signed-off-by: David Hendricks <dhendricks@fb.com>
Reviewed-on: https://review.coreboot.org/25524
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: David Hendricks <david.hendricks@gmail.com>
This commit is contained in:
David Hendricks
2018-03-09 13:58:27 -08:00
committed by Patrick Georgi
parent 71cbd71eb5
commit 2004b93aed
139 changed files with 148528 additions and 0 deletions

View File

@ -0,0 +1,376 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include <stdio.h>
#include "libbdk-arch/bdk-csrs-pccpf.h"
#include "libbdk-arch/bdk-csrs-pem.h"
#ifndef BDK_BUILD_HOST
/**
* Read a slow CSR, not RSL or NCB.
*
* @param type Bus type the CSR is on
* @param busnum Bus number the CSR is on
* @param size Width of the CSR in bytes
* @param address The address of the CSR
*
* @return The value of the CSR
*/
uint64_t __bdk_csr_read_slow(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address)
{
switch (type)
{
case BDK_CSR_TYPE_DAB:
case BDK_CSR_TYPE_DAB32b:
case BDK_CSR_TYPE_NCB:
case BDK_CSR_TYPE_NCB32b:
case BDK_CSR_TYPE_PEXP_NCB:
case BDK_CSR_TYPE_RSL:
case BDK_CSR_TYPE_RSL32b:
case BDK_CSR_TYPE_RVU_PF_BAR0:
case BDK_CSR_TYPE_RVU_PF_BAR2:
case BDK_CSR_TYPE_RVU_PFVF_BAR2:
case BDK_CSR_TYPE_RVU_VF_BAR2:
/* Handled by inline code, we should never get here */
bdk_error("%s: Passed type that should be handled inline\n", __FUNCTION__);
break;
case BDK_CSR_TYPE_PCCBR:
case BDK_CSR_TYPE_PCCPF:
case BDK_CSR_TYPE_PCCVF:
case BDK_CSR_TYPE_PEXP:
case BDK_CSR_TYPE_MDSB:
case BDK_CSR_TYPE_PCICONFIGEP_SHADOW:
case BDK_CSR_TYPE_PCICONFIGEPVF:
bdk_error("%s: Register not supported\n", __FUNCTION__);
break;
case BDK_CSR_TYPE_SYSREG:
return bdk_sysreg_read(node, bdk_get_core_num(), address);
case BDK_CSR_TYPE_PCICONFIGRC:
{
/* Don't allow PCIe register access if PCIe wasn't linked in */
if (!bdk_pcie_config_read32)
bdk_fatal("PCIe CSR access not supported when PCIe not linked in\n");
union bdk_pcc_dev_con_s dev_con;
switch (busnum)
{
case 0:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC0_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC0_CN83XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC0_CN81XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 1:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC1_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC1_CN83XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC1_CN81XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 2:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC2_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC2_CN83XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC2_CN81XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 3:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC3_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC3_CN83XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 4:
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC4;
break;
case 5:
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC5;
break;
default:
bdk_error("%s: Illegal PCIe bus number\n", __FUNCTION__);
return -1;
}
return bdk_pcie_config_read32(node, 100 + dev_con.cn8.ecam, dev_con.s.bus, dev_con.s.func >> 3, dev_con.s.func & 7, address);
}
case BDK_CSR_TYPE_PCICONFIGEP:
{
BDK_CSR_DEFINE(cfg_rd, BDK_PEMX_CFG_RD(busnum));
cfg_rd.u = 0;
cfg_rd.s.addr = address;
BDK_CSR_WRITE(node, BDK_PEMX_CFG_RD(busnum), cfg_rd.u);
cfg_rd.u = BDK_CSR_READ(node, BDK_PEMX_CFG_RD(busnum));
return cfg_rd.s.data;
}
}
return -1; /* Return -1 as this looks invalid in register dumps. Zero is too common as a good value */
}
/**
* Write a value to a slow CSR, not RSL or NCB.
*
* @param type Bus type the CSR is on
* @param busnum Bus number the CSR is on
* @param size Width of the CSR in bytes
* @param address The address of the CSR
* @param value Value to write to the CSR
*/
void __bdk_csr_write_slow(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value)
{
switch (type)
{
case BDK_CSR_TYPE_DAB:
case BDK_CSR_TYPE_DAB32b:
case BDK_CSR_TYPE_NCB:
case BDK_CSR_TYPE_NCB32b:
case BDK_CSR_TYPE_PEXP_NCB:
case BDK_CSR_TYPE_RSL:
case BDK_CSR_TYPE_RSL32b:
case BDK_CSR_TYPE_RVU_PF_BAR0:
case BDK_CSR_TYPE_RVU_PF_BAR2:
case BDK_CSR_TYPE_RVU_PFVF_BAR2:
case BDK_CSR_TYPE_RVU_VF_BAR2:
/* Handled by inline code, we should never get here */
bdk_error("%s: Passed type that should be handled inline\n", __FUNCTION__);
break;
case BDK_CSR_TYPE_PCCBR:
case BDK_CSR_TYPE_PCCPF:
case BDK_CSR_TYPE_PCCVF:
case BDK_CSR_TYPE_PEXP:
case BDK_CSR_TYPE_MDSB:
case BDK_CSR_TYPE_PCICONFIGEP_SHADOW:
case BDK_CSR_TYPE_PCICONFIGEPVF:
bdk_error("%s: Register not supported\n", __FUNCTION__);
break;
case BDK_CSR_TYPE_SYSREG:
bdk_sysreg_write(node, bdk_get_core_num(), address, value);
break;
case BDK_CSR_TYPE_PCICONFIGRC:
{
/* Don't allow PCIe register access if PCIe wasn't linked in */
if (!bdk_pcie_config_write32)
bdk_fatal("PCIe CSR access not supported when PCIe not linked in\n");
union bdk_pcc_dev_con_s dev_con;
switch (busnum)
{
case 0:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC0_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC0_CN83XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC0_CN81XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 1:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC1_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC1_CN83XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC1_CN81XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 2:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC2_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC2_CN83XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC2_CN81XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 3:
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC3_CN88XX;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC3_CN83XX;
else
bdk_fatal("Update PCICONFIG in %s\n", __FUNCTION__);
break;
case 4:
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC4;
break;
case 5:
dev_con.u = BDK_PCC_DEV_CON_E_PCIERC5;
break;
default:
bdk_error("%s: Illegal PCIe bus number\n", __FUNCTION__);
return;
}
bdk_pcie_config_write32(node, 100 + dev_con.cn8.ecam, dev_con.s.bus, dev_con.s.func >> 3, dev_con.s.func & 7, address, value);
break;
}
case BDK_CSR_TYPE_PCICONFIGEP:
{
BDK_CSR_DEFINE(cfg_wr, BDK_PEMX_CFG_WR(busnum));
cfg_wr.u = 0;
cfg_wr.s.addr = address;
cfg_wr.s.data = value;
BDK_CSR_WRITE(node, BDK_PEMX_CFG_WR(busnum), cfg_wr.u);
break;
}
}
}
#endif
void __bdk_csr_fatal(const char *name, int num_args, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4)
{
switch (num_args)
{
case 0:
bdk_fatal("%s is invalid on this chip\n", name);
case 1:
bdk_fatal("%s(%lu) is invalid on this chip\n", name, arg1);
case 2:
bdk_fatal("%s(%lu,%lu) is invalid on this chip\n", name, arg1, arg2);
case 3:
bdk_fatal("%s(%lu,%lu,%lu) is invalid on this chip\n", name, arg1, arg2, arg3);
default:
bdk_fatal("%s(%lu,%lu,%lu,%lu) is invalid on this chip\n", name, arg1, arg2, arg3, arg4);
}
}
/**
* Read a core system register from a different node or core
*
* @param node Node to read from
* @param core Core to read
* @param regnum Register to read in MRS encoding
*
* @return Register value
*/
uint64_t bdk_sysreg_read(int node, int core, uint64_t regnum)
{
BDK_CSR_INIT(pp_reset, node, BDK_RST_PP_RESET);
if (pp_reset.u & (1ull<<core))
{
bdk_error("Attempt to read system register for core in reset\n");
return -1;
}
/* Addresses indicate selects as follows:
select 3,4,14,2,3
== 0x03040e020300
| | | | |^--- 1 if is E2H duplicated register
| | | |^^-- fifth select
| | |^^-- fourth select
| |^^-- third select
|^^-- second select
^^-- first select */
uint64_t first = (regnum >> 40) & 0xff;
uint64_t second = (regnum >> 32) & 0xff;
uint64_t third = (regnum >> 24) & 0xff;
uint64_t fourth = (regnum >> 16) & 0xff;
uint64_t fifth = (regnum >> 8) & 0xff;
uint64_t regid = ((first & 3) << 14) | (second << 11) | (third << 7) | (fourth << 3) | fifth;
/* Note this requires DAP_IMP_DAR[caben] = 1 */
uint64_t address = 1ull<<47;
address |= 0x7Bull << 36;
address |= core << 19;
address |= regid << 3;
address = bdk_numa_get_address(node, address);
return bdk_read64_uint64(address);
}
/**
* Write a system register for a different node or core
*
* @param node Node to write too
* @param core Core to write
* @param regnum Register to write in MSR encoding
* @param value Value to write
*/
void bdk_sysreg_write(int node, int core, uint64_t regnum, uint64_t value)
{
BDK_CSR_INIT(pp_reset, node, BDK_RST_PP_RESET);
if (pp_reset.u & (1ull<<core))
{
bdk_error("Attempt to write system register for core in reset\n");
return;
}
/* Addresses indicate selects as follows:
select 3,4,14,2,3
== 0x03040e020300
| | | | |^--- 1 if is E2H duplicated register
| | | |^^-- fifth select
| | |^^-- fourth select
| |^^-- third select
|^^-- second select
^^-- first select */
uint64_t first = (regnum >> 40) & 0xff;
uint64_t second = (regnum >> 32) & 0xff;
uint64_t third = (regnum >> 24) & 0xff;
uint64_t fourth = (regnum >> 16) & 0xff;
uint64_t fifth = (regnum >> 8) & 0xff;
uint64_t regid = ((first & 3) << 14) | (second << 11) | (third << 7) | (fourth << 3) | fifth;
/* Note this requires DAP_IMP_DAR[caben] = 1 */
uint64_t address = 1ull<<47;
address |= 0x7Bull << 36;
address |= core << 19;
address |= regid << 3;
address = bdk_numa_get_address(node, address);
bdk_write64_uint64(address, value);
}

View File

@ -0,0 +1,927 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-ap.h"
#include "libbdk-arch/bdk-csrs-mio_fus.h"
#include "libbdk-arch/bdk-csrs-fus.h"
#include "libbdk-arch/bdk-csrs-fusf.h"
/*
Format of a SKU
CN8890-2000BG2601-AAP-G
CN8890-2000BG2601-AAP-PR-Y-G
CN XX XX X - XXX BG XXX - XX (- XX) (- X) - G
| | | | | | | | | | ^ RoHS Option, G=RoHS 6/6
| | | | | | | | | ^ Product Revision, blank for pass 1, Y=pass 2, W=pass 3, V=pass 4
| | | | | | | | ^ Product Phase, blank=production, PR=Prototype, ES=Engineering Sample
| | | | | | | ^ Marketing Segment Option (SC, SNT, etc)
| | | | | | ^ Number of balls on the package
| | | | | ^ Ball Grid Array
| | | | ^ Frequency in Mhz, 3 or 4 digits (300 - 2000)
| | | ^ Optional Customer Code, blank or A-Z
| | ^ Number of cores, see table below
| ^ Processor family, plus or minus for L2 sizes and such (88, 86, 83, 81, 80)
^ Cavium Prefix, sometimes changed for customer specific parts
Table of Core to Model encoding
>= 48 shows xx90
>= 44 shows xx88
>= 42 shows xx85
>= 32 shows xx80
>= 24 shows xx70
>= 20 shows xx65
>= 16 shows xx60
= 15 shows xx58
= 14 shows xx55
= 13 shows xx52
= 12 shows xx50
= 11 shows xx48
= 10 shows xx45
= 9 shows xx42
= 8 shows xx40
= 7 shows xx38
= 6 shows xx34
= 5 shows xx32
= 4 shows xx30
= 3 shows xx25
= 2 shows xx20
= 1 shows xx10
*/
/* Definition of each SKU table entry for the different dies */
typedef struct
{
uint8_t fuse_index; /* Index programmed into PNAME fuses to match this entry. Must never change once fused parts ship */
const char prefix[4]; /* Prefix before model number, usually "CN". Third letter is customer code shown after the model */
uint8_t model_base; /* First two digits of the model number */
uint16_t num_balls; /* Number of balls on package, included in SKU */
const char segment[4]; /* Market segment SKU is for, 2-3 character string */
uint16_t fuses[12]; /* List of fuses required for operation of this SKU */
} model_sku_info_t;
/* In the model_sku_info_t.fuses[] array, we use a special value
FUSES_CHECK_FUSF to represent that we need to check FUSF_CTL bit
6, checking for trusted boot */
#define FUSES_CHECK_FUSF 0xffff
/***************************************************/
/* SKU table for t88 */
/* From "Thunder Part Number fuse overview Rev 16.xlsx" */
/***************************************************/
static const model_sku_info_t t88_sku_info[] =
{
/* Index zero reserved for no fuses programmed */
{ 0x01, "CN", 88, 2601, "AAP", /* 48, 32 cores */
{ /* List of fuses for this SKU */
0 /* End of fuse list marker */
}
},
{ 0x02, "CN", 88, 2601, "AAS", /* 24 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_OCX_DIS, /* Disable CCPI */
0 /* End of fuse list marker */
}
},
{ 0x03, "CN", 88, 2601, "ST", /* 48, 32 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_TNS_CRIPPLE, /* Disable TNS */
BDK_MIO_FUS_FUSE_NUM_E_PEM_DISX(0), /* Disable PEM0-1 */
BDK_MIO_FUS_FUSE_NUM_E_PEM_DISX(2), /* Disable PEM4-5 */
0 /* End of fuse list marker */
}
},
{ 0x04, "CN", 88, 2601, "STT", /* 48 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_PEM_DISX(0), /* Disable PEM0-1 */
BDK_MIO_FUS_FUSE_NUM_E_PEM_DISX(2), /* Disable PEM4-5 */
0 /* End of fuse list marker */
}
},
{ 0x05, "CN", 88, 2601, "STS", /* 24 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_LMC_DIS, /* Disable LMC2-3 */
BDK_MIO_FUS_FUSE_NUM_E_OCX_DIS, /* Disable CCPI */
BDK_MIO_FUS_FUSE_NUM_E_TNS_CRIPPLE, /* Disable TNS */
BDK_MIO_FUS_FUSE_NUM_E_PEM_DISX(0), /* Disable PEM0-1 */
BDK_MIO_FUS_FUSE_NUM_E_PEM_DISX(2), /* Disable PEM4-5 */
BDK_MIO_FUS_FUSE_NUM_E_BGX_DISX(1), /* Disable BGX1 */
0 /* End of fuse list marker */
}
},
{ 0x06, "CN", 88, 2601, "STP", /* 48, 32 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_TNS_CRIPPLE, /* Disable TNS */
0 /* End of fuse list marker */
}
},
{ 0x07, "CN", 88, 2601, "NT", /* 48, 32 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(0),/* Disable SATA0-3 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(2),/* Disable SATA8-11 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(3),/* Disable SATA12-15 */
0 /* End of fuse list marker */
}
},
{ 0x08, "CN", 88, 2601, "NTS", /* 24 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_LMC_DIS, /* Disable LMC2-3 */
BDK_MIO_FUS_FUSE_NUM_E_OCX_DIS, /* Disable CCPI */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(0),/* Disable SATA0-3 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(2),/* Disable SATA8-11 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(3),/* Disable SATA12-15 */
BDK_MIO_FUS_FUSE_NUM_E_BGX_DISX(1), /* Disable BGX1 */
0 /* End of fuse list marker */
}
},
{ 0x09, "CN", 88, 2601, "NTP", /* 48, 32 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(0),/* Disable SATA0-3 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(1),/* Disable SATA4-7 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(2),/* Disable SATA8-11 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(3),/* Disable SATA12-15 */
0 /* End of fuse list marker */
}
},
{ 0x0a, "CN", 88, 2601, "CP", /* 48,32 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_NODFA_CP2, /* Disable HFA */
BDK_MIO_FUS_FUSE_NUM_E_RSVD134X(0), /* Disable HNA */
BDK_MIO_FUS_FUSE_NUM_E_NOZIP, /* Disable Compression */
BDK_MIO_FUS_FUSE_NUM_E_TNS_CRIPPLE, /* Disable TNS */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(0),/* Disable SATA0-3 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(2),/* Disable SATA8-11 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(3),/* Disable SATA12-15 */
0 /* End of fuse list marker */
}
},
{ 0x0b, "CN", 88, 2601, "CPS", /* 24 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_NODFA_CP2, /* Disable HFA */
BDK_MIO_FUS_FUSE_NUM_E_RSVD134X(0), /* Disable HNA */
BDK_MIO_FUS_FUSE_NUM_E_NOZIP, /* Disable Compression */
BDK_MIO_FUS_FUSE_NUM_E_LMC_DIS, /* Disable LMC2-3 */
BDK_MIO_FUS_FUSE_NUM_E_OCX_DIS, /* Disable CCPI */
BDK_MIO_FUS_FUSE_NUM_E_TNS_CRIPPLE, /* Disable TNS */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(0),/* Disable SATA0-3 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(2),/* Disable SATA8-11 */
BDK_MIO_FUS_FUSE_NUM_E_SATA_DISX(3),/* Disable SATA12-15 */
BDK_MIO_FUS_FUSE_NUM_E_BGX_DISX(1), /* Disable BGX1 */
0 /* End of fuse list marker */
}
},
{ 0x0c, "CN", 88, 2601, "SNT", /* 48,32 cores, Nitrox connects to PEM2x8, QLM4-5 */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_RSVD231X(0), /* Nitrox 3 is present */
0 /* End of fuse list marker */
}
},
{ 0x0d, "CN", 88, 2601, "SC", /* 48,32 cores, Nitrox connects to PEM2x8, QLM4-5 */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_RSVD231X(0), /* Nitrox 3 is present */
BDK_MIO_FUS_FUSE_NUM_E_NODFA_CP2, /* Disable HFA */
BDK_MIO_FUS_FUSE_NUM_E_RSVD134X(0), /* Disable HNA */
BDK_MIO_FUS_FUSE_NUM_E_NOZIP, /* Disable Compression */
BDK_MIO_FUS_FUSE_NUM_E_TNS_CRIPPLE, /* Disable TNS */
0 /* End of fuse list marker */
}
},
/* Index gap for adding more CN88 variants */
{ 0x20, "CN", 86, 1676, "AAP", /* No part, match unfused CN86XX */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_CHIP_IDX(6), /* Alternate package fuse */
0 /* End of fuse list marker */
}
},
{ 0x21, "CN", 86, 1676, "SCP", /* 8 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_CHIP_IDX(6), /* Alternate package fuse */
BDK_MIO_FUS_FUSE_NUM_E_L2C_CRIPX(1),/* L2C is half size */
BDK_MIO_FUS_FUSE_NUM_E_NODFA_CP2, /* Disable HFA */
BDK_MIO_FUS_FUSE_NUM_E_RSVD134X(0), /* Disable HNA */
BDK_MIO_FUS_FUSE_NUM_E_NOZIP, /* Disable Compression */
BDK_MIO_FUS_FUSE_NUM_E_LMC_DIS, /* Disable LMC2-3 */
BDK_MIO_FUS_FUSE_NUM_E_OCX_DIS, /* Disable CCPI */
BDK_MIO_FUS_FUSE_NUM_E_TNS_CRIPPLE, /* Disable TNS */
0 /* End of fuse list marker */
}
},
{} /* End of SKU list marker */
};
/***************************************************/
/* SKU table for t83 */
/* From "Thunder Part Number fuse overview Rev 16.xlsx" */
/***************************************************/
static const model_sku_info_t t83_sku_info[] =
{
/* Index zero reserved for no fuses programmed */
{ 0x01, "CN", 83, 1676, "SCP", /* 24, 20, 16, 12, 8 cores */
{ /* List of fuses for this SKU */
0 /* End of fuse list marker */
}
},
{ 0x02, "CN", 83, 1676, "CP", /* 24, 20, 16, 12, 8 cores */
{ /* List of fuses for this SKU */
/* Disable all Nitrox cores, CPT0 and CPT1 */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(0), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(16), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(17), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(18), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(19), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(20), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(21), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(22), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(23), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(24), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(25), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(26), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(27), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(28), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(29), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(30), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(31), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(32), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(33), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(34), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(35), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(36), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(37), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(38), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(39), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(40), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(41), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(42), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(43), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(44), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(45), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(46), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(47), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(0), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(16), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(17), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(18), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(19), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(20), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(21), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(22), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(23), /* Nitrox */
0 /* End of fuse list marker */
}
},
{ 0x03, "CN", 83, 1676, "AUS", /* 24, 20, 16, 12, 8 cores */
{ /* List of fuses for this SKU */
FUSES_CHECK_FUSF, /* Trusted boot */
0 /* End of fuse list marker */
}
},
{ 0x04, "CN", 82, 1676, "SCP", /* 12, 8 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_L2C_CRIPX(1),/* L2C is half size */
BDK_MIO_FUS_FUSE_NUM_E_LMC_DIS, /* Disable upper LMC */
/* Disable Nitrox cores CPT0[24-47] and CPT1[12-23] */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(24), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(25), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(26), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(27), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(28), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(29), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(30), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(31), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(32), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(33), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(34), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(35), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(36), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(37), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(38), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(39), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(40), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(41), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(42), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(43), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(44), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(45), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(46), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(47), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(16), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(17), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(18), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(19), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(20), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(21), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(22), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(23), /* Nitrox */
0 /* End of fuse list marker */
}
},
{ 0x05, "CN", 82, 1676, "CP", /* 12, 8 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_L2C_CRIPX(1),/* L2C is half size */
BDK_MIO_FUS_FUSE_NUM_E_LMC_DIS, /* Disable upper LMC */
/* Disable all Nitrox cores, CPT0 and CPT1 */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(0), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(16), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(17), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(18), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(19), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(20), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(21), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(22), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(23), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(24), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(25), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(26), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(27), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(28), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(29), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(30), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(31), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(32), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(33), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(34), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(35), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(36), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(37), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(38), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(39), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(40), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(41), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(42), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(43), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(44), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(45), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(46), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT0_ENG_DISX(47), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(0), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(16), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(17), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(18), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(19), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(20), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(21), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(22), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT1_ENG_DISX(23), /* Nitrox */
0 /* End of fuse list marker */
}
},
{} /* End of SKU list marker */
};
/***************************************************/
/* SKU table for t81 */
/* From "Thunder Part Number fuse overview Rev 16.xlsx" */
/***************************************************/
static const model_sku_info_t t81_sku_info[] =
{
/* Index zero reserved for no fuses programmed */
{ 0x01, "CN", 81, 676, "SCP", /* 4, 2 cores */
{ /* List of fuses for this SKU */
/* No fuses */
0 /* End of fuse list marker */
}
},
{ 0x02, "CN", 81, 676, "CP", /* 4, 2 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(16), /* Nitrox */
0 /* End of fuse list marker */
}
},
{ 0x07, "CN", 81, 676, "AUS", /* 4, 2 cores */
{ /* List of fuses for this SKU */
FUSES_CHECK_FUSF, /* Trusted boot */
0 /* End of fuse list marker */
}
},
{ 0x08, "CN", 81, 676, "AUC", /* 4, 2 cores */
{ /* List of fuses for this SKU */
FUSES_CHECK_FUSF, /* Trusted boot */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(16), /* Nitrox */
0 /* End of fuse list marker */
}
},
{ 0x03, "CN", 80, 676, "SCP", /* 4, 2 cores */
{ /* List of fuses for this SKU */
/* Note that CHIP_ID(7) is suppose to be blown, but a few chips
have incorrect fuses. We allow CN80XX SKUs with or without
CHIP_ID(7) */
//BDK_MIO_FUS_FUSE_NUM_E_CHIP_IDX(7), /* Alternate package fuse 2? */
BDK_MIO_FUS_FUSE_NUM_E_L2C_CRIPX(1), /* L2C is half size */
BDK_MIO_FUS_FUSE_NUM_E_LMC_HALF, /* LMC is half width */
0 /* End of fuse list marker */
}
},
{ 0x04, "CN", 80, 676, "CP", /* 4, 2 cores */
{ /* List of fuses for this SKU */
/* Note that CHIP_ID(7) is suppose to be blown, but a few chips
have incorrect fuses. We allow CN80XX SKUs with or without
CHIP_ID(7) */
//BDK_MIO_FUS_FUSE_NUM_E_CHIP_IDX(7), /* Alternate package fuse 2? */
BDK_MIO_FUS_FUSE_NUM_E_L2C_CRIPX(1), /* L2C is half size */
BDK_MIO_FUS_FUSE_NUM_E_LMC_HALF, /* LMC is half width */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(16), /* Nitrox */
0 /* End of fuse list marker */
}
},
{ 0x05, "CN", 80, 555, "SCP", /* 4, 2 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_CHIP_IDX(6), /* Alternate package fuse */
BDK_MIO_FUS_FUSE_NUM_E_L2C_CRIPX(1), /* L2C is half size */
BDK_MIO_FUS_FUSE_NUM_E_LMC_HALF, /* LMC is half width */
0 /* End of fuse list marker */
}
},
{ 0x06, "CN", 80, 555, "CP", /* 4, 2 cores */
{ /* List of fuses for this SKU */
BDK_MIO_FUS_FUSE_NUM_E_CHIP_IDX(6), /* Alternate package fuse */
BDK_MIO_FUS_FUSE_NUM_E_L2C_CRIPX(1), /* L2C is half size */
BDK_MIO_FUS_FUSE_NUM_E_LMC_HALF, /* LMC is half width */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(1), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(2), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(3), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(4), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(5), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(6), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(7), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(8), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(9), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(10), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(11), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(12), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(13), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(14), /* Nitrox */
//BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(15), /* Nitrox */
BDK_MIO_FUS_FUSE_NUM_E_CPT_ENG_DISX(16), /* Nitrox */
0 /* End of fuse list marker */
}
},
{} /* End of SKU list marker */
};
/***************************************************/
/* SKU table for t93 */
/***************************************************/
static const model_sku_info_t t93_sku_info[] =
{
/* Index zero reserved for no fuses programmed */
{ 0x01, "CN", 93, 1676, "SCP", /* 24, 20, 16, 12, 8 cores */
{ /* List of fuses for this SKU */
/* No fuses */
0 /* End of fuse list marker */
}
},
{} /* End of SKU list marker */
};
/**
* Given a core count, return the last two digits of a model number
*
* @param cores Number of cores
*
* @return Two digit model number
*/
static int model_digits_for_cores(int cores)
{
/* If the number of cores is between two model levels, use the lower
level. This assumes that a model guarantees a minimum number of
cores. This should never happen, but you never know */
switch (cores)
{
case 1: return 10; /* CNxx10 = 1 core */
case 2: return 20; /* CNxx20 = 2 cores */
case 3: return 25; /* CNxx25 = 3 cores */
case 4: return 30; /* CNxx30 = 4 cores */
case 5: return 32; /* CNxx32 = 5 cores */
case 6: return 34; /* CNxx34 = 6 cores */
case 7: return 38; /* CNxx38 = 7 cores */
case 8: return 40; /* CNxx40 = 8 cores */
case 9: return 42; /* CNxx42 = 9 cores */
case 10: return 45; /* CNxx45 = 10 cores */
case 11: return 48; /* CNxx48 = 11 cores */
case 12: return 50; /* CNxx50 = 12 cores */
case 13: return 52; /* CNxx52 = 13 cores */
case 14: return 55; /* CNxx55 = 14 cores */
case 15: return 58; /* CNxx58 = 15 cores */
case 16 ... 19: return 60; /* CNxx60 = 16 cores */
case 20 ... 23: return 65; /* CNxx65 = 20 cores */
case 24 ... 31: return 70; /* CNxx70 = 24 cores */
case 32 ... 39: return 80; /* CNxx80 = 32 cores */
case 40 ... 43: return 85; /* CNxx85 = 40 cores */
case 44 ... 47: return 88; /* CNxx88 = 44 cores */
default: return 90; /* CNxx90 = 48 cores */
}
}
/**
* Return non-zero if the die is in an alternate package. The
* normal is_model() checks will treat alternate package parts
* as all the same, where this function can be used to detect
* them. The return value is the upper two bits of
* MIO_FUS_DAT2[chip_id]. Most alternate packages use bit 6,
* which will return 1 here. Parts with a second alternative
* will use bit 7, which will return 2.
*
* @param arg_model One of the CAVIUM_* constants for chip models and passes
*
* @return Non-zero if an alternate package
* 0 = Normal package
* 1 = Alternate package 1 (CN86XX, CN80XX with 555 balls)
* 2 = Alternate package 2 (CN80XX with 676 balls)
* 3 = Alternate package 3 (Currently unused)
*/
int cavium_is_altpkg(uint32_t arg_model)
{
if (CAVIUM_IS_MODEL(arg_model))
{
BDK_CSR_INIT(mio_fus_dat2, bdk_numa_local(), BDK_MIO_FUS_DAT2);
/* Bits 7:6 are used for alternate packages. Return the exact
number so multiple alternate packages can be detected
(CN80XX is an example) */
int altpkg = mio_fus_dat2.s.chip_id >> 6;
if (altpkg)
return altpkg;
/* Due to a documentation mixup, some CN80XX parts do not have chip_id
bit 7 set. As a backup, use lmc_mode32 to find these parts. Both
bits are suppose to be fused, but some parts only have lmc_mode32 */
if (CAVIUM_IS_MODEL(CAVIUM_CN81XX) && mio_fus_dat2.s.lmc_mode32)
return 2;
return 0;
}
else
return 0;
}
/**
* Return the SKU string for a chip
*
* @param node Node to get SKU for
*
* @return Chip's SKU
*/
const char* bdk_model_get_sku(int node)
{
/* Storage for SKU is per node. Static variable stores the value
so we don't decode on every call */
static char chip_sku[BDK_NUMA_MAX_NODES][32] = { { 0, }, };
/* Return the cached string if we've already filled it in */
if (chip_sku[node][0])
return chip_sku[node];
/* Figure out which SKU list to use */
const model_sku_info_t *sku_info;
uint64_t result;
asm ("mrs %[rd],MIDR_EL1" : [rd] "=r" (result));
result = bdk_extract(result, 4, 12);
switch (result)
{
case 0xa1:
sku_info = t88_sku_info;
break;
case 0xa2:
sku_info = t81_sku_info;
break;
case 0xa3:
sku_info = t83_sku_info;
break;
case 0xb2:
sku_info = t93_sku_info;
break;
default:
bdk_fatal("SKU detect: Unknown die\n");
}
/* Read the SKU index from the PNAME fuses */
int match_index = -1;
// FIXME: Implement PNAME reads
/* Search the SKU list for the best match, where all the fuses match.
Only needed if the PNAME fuses don't specify the index */
if (match_index == -1)
{
match_index = 0;
int match_score = -1;
int index = 0;
while (sku_info[index].fuse_index)
{
int score = 0;
int fuse_index = 0;
/* Count the number of fuses that match. A mismatch forces the worst
score (-1) */
while (sku_info[index].fuses[fuse_index])
{
int fuse;
/* FUSES_CHECK_FUSF is special for trusted parts */
if (sku_info[index].fuses[fuse_index] == FUSES_CHECK_FUSF)
{
BDK_CSR_INIT(fusf_ctl, node, BDK_FUSF_CTL);
fuse = (fusf_ctl.u >> 6) & 1;
}
else
{
fuse = bdk_fuse_read(node, sku_info[index].fuses[fuse_index]);
}
if (fuse)
{
/* Match, improve the score */
score++;
}
else
{
/* Mismatch, force score bad */
score = -1;
break;
}
fuse_index++;
}
/* If this score is better than the last match, use this index as the
match */
if (score > match_score)
{
match_score = score;
match_index = index;
}
index++;
}
}
/* Use the SKU table to determine the defaults for the SKU parts */
const char *prefix = sku_info[match_index].prefix;
int model = 100 * sku_info[match_index].model_base;
int cores = bdk_get_num_cores(node);
const char *customer_code = "";
int rclk_limit = bdk_clock_get_rate(node, BDK_CLOCK_RCLK) / 1000000;
const char *bg_str = "BG"; /* Default Ball Grid array */
int balls = sku_info[match_index].num_balls; /* Num package balls */
const char *segment = sku_info[match_index].segment; /* Market segment */
char prod_phase[4]; /* Blank = production, PR = Prototype, ES = Engineering sample */
char prod_rev[5]; /* Product revision */
const char *rohs_option = "G"; /* RoHS is always G for current parts */
/* Update the model number with the number of cores */
model = (model / 100) * 100 + model_digits_for_cores(cores);
/* Update the RCLK setting based on MIO_FUS_DAT3[core_pll_mul] */
uint64_t core_pll_mul;
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
{
BDK_CSR_INIT(mio_fus_dat3, node, BDK_MIO_FUS_DAT3);
core_pll_mul = mio_fus_dat3.s.core_pll_mul;
}
else
core_pll_mul = bdk_fuse_read_range(bdk_numa_local(), BDK_FUS_FUSE_NUM_E_CORE_MAX_MULX(0), 7);
if (core_pll_mul)
{
/* CORE_PLL_MUL covers bits 5:1, so we need to multiple by 2. The
documentation doen't mention this clearly: There is a 300Mhz
addition to the base multiplier */
rclk_limit = core_pll_mul * 2 * 50 + 300;
}
/* FIXME: Hardcode production as there is no way to tell */
prod_phase[0] = 0;
/* Read the Pass information from fuses. Note that pass info in
MIO_FUS_DAT2[CHIP_ID] is encoded as
bit[7] = Unused, zero
bit[6] = Alternate package
bit[5..3] = Major pass
bit[2..0] = Minor pass */
int major_pass;
int minor_pass;
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
{
BDK_CSR_INIT(mio_fus_dat2, node, BDK_MIO_FUS_DAT2);
major_pass = ((mio_fus_dat2.s.chip_id >> 3) & 7) + 1;
minor_pass = mio_fus_dat2.s.chip_id & 7;
}
else
{
/* FIXME: We don't support getting the pass for other node on CN9XXX */
bdk_ap_midr_el1_t midr_el1;
BDK_MRS(MIDR_EL1, midr_el1.u);
major_pass = (midr_el1.s.variant & 7) + 1;
minor_pass = midr_el1.s.revision;
}
if (major_pass == 1)
{
/* Pass 1.x is special in that we don't show the implied 'X' */
if (minor_pass == 0)
{
/* Completely blank for 1.0 */
prod_rev[0] = 0;
}
else
{
/* If we are production and not pass 1.0, the product phase
changes from blank to "-P". The product revision then
follows the product phase without a '-' */
if (prod_phase[0] == 0)
{
/* Change product phase to "-P" */
prod_phase[0] = '-';
prod_phase[1] = 'P';
prod_phase[2] = 0;
}
/* No separator between phase and revision */
prod_rev[0] = '1';
prod_rev[1] = '0' + minor_pass;
prod_rev[2] = 0;
}
}
else
{
/* Pass 2.0 and above 12345678 */
const char pass_letter[8] = "XYWVUTSR";
prod_rev[0] = '-';
prod_rev[1] = pass_letter[major_pass-1];
if (minor_pass == 0)
{
/* Nothing after the letter code */
prod_rev[2] = 0;
}
else
{
/* Add major and minor after the letter code */
prod_rev[2] = '0' + major_pass;
prod_rev[3] = '0' + minor_pass;
prod_rev[4] = 0;
}
}
/* Special check for CN88XX pass 2.0 and 2.1. Documentation mistakenly
specified 2.0 as -PR and 2.1 as -Y. Rather than fix the docs, OPs has
decided to special case this SKU */
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX) && (major_pass == 2))
{
if (minor_pass == 0)
{
prod_phase[0] = '-'; /* SKU ends with -PR-Y-G */
prod_phase[1] = 'P';
prod_phase[2] = 'R';
prod_phase[3] = 0;
}
else if (minor_pass == 1)
{
prod_rev[0] = '-'; /* SKU ends with -Y-G */
prod_rev[1] = 'Y';
prod_rev[2] = 0;
}
}
/* Read PNAME fuses, looking for SKU overrides */
// FIXME: Implement PNAME reads
/* Build the SKU string */
snprintf(chip_sku[node], sizeof(chip_sku[node]), "%s%d%s-%d%s%d-%s%s%s-%s",
prefix, model, customer_code, rclk_limit, bg_str, balls, segment,
prod_phase, prod_rev, rohs_option);
return chip_sku[node];
}

View File

@ -0,0 +1,91 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include <stdio.h>
int __bdk_numa_master_node = -1; /* Which node is the master */
static int __bdk_numa_exists_mask = 0; /* Bitmask of nodes that exist */
static bdk_spinlock_t __bdk_numa_lock;
/**
* Get a bitmask of the nodes that exist
*
* @return bitmask
*/
uint64_t bdk_numa_get_exists_mask(void)
{
return __bdk_numa_exists_mask;
}
/**
* Add a node to the exists mask
*
* @param node Node to add
*/
void bdk_numa_set_exists(bdk_node_t node)
{
bdk_spinlock_lock(&__bdk_numa_lock);
__bdk_numa_exists_mask |= 1 << node;
if (__bdk_numa_master_node == -1)
__bdk_numa_master_node = node;
bdk_spinlock_unlock(&__bdk_numa_lock);
}
/**
* Return true if a node exists
*
* @param node Node to check
*
* @return Non zero if the node exists
*/
int bdk_numa_exists(bdk_node_t node)
{
return __bdk_numa_exists_mask & (1 << node);
}
/**
* Return true if there is only one node
*
* @return
*/
extern int bdk_numa_is_only_one()
{
return __bdk_numa_exists_mask == 1;
}

View File

@ -0,0 +1,59 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-ocla.h"
bdk_platform_t __bdk_platform;
void __bdk_platform_init()
{
BDK_CSR_INIT(c, bdk_numa_master(), BDK_OCLAX_CONST(0));
if (c.u == 0)
{
__bdk_platform = BDK_PLATFORM_ASIM;
}
else
{
int plat2 = bdk_fuse_read(bdk_numa_master(), 197);
int plat1 = bdk_fuse_read(bdk_numa_master(), 196);
int plat0 = bdk_fuse_read(bdk_numa_master(), 195);
__bdk_platform = (plat2 << 2) | (plat1 << 1) | plat0;
}
}

View File

@ -0,0 +1,81 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-mio_tws.h"
/**
* Report boot status to the BMC or whomever might care. This function
* will return quickly except for a status of "power cycle". In the power cycle
* case it is assumed the board is in a bad state and should not continue until
* a power cycle restarts us.
*
* @param status Status to report. Enumerated in bdk_boot_status_t
*/
void bdk_boot_status(bdk_boot_status_t status)
{
bdk_node_t node = bdk_numa_master();
int twsi = bdk_config_get_int(BDK_CONFIG_BMC_TWSI);
/* Update status */
if (twsi != -1)
{
BDK_CSR_DEFINE(sw_twsi, BDK_MIO_TWSX_SW_TWSI(twsi));
sw_twsi.u = 0;
sw_twsi.s.v = 1; /* Valid data */
sw_twsi.s.slonly = 1; /* Slave only */
sw_twsi.s.data = status;
BDK_CSR_WRITE(node, BDK_MIO_TWSX_SW_TWSI(twsi), sw_twsi.u);
}
/* As a special case, power cycle will display a message and try a
soft reset if we can't power cycle in 5 seconds */
if (status == BDK_BOOT_STATUS_REQUEST_POWER_CYCLE)
{
if (twsi != -1)
{
printf("Requested power cycle\n");
bdk_wait_usec(5000000); /* 5 sec */
printf("Power cycle failed, trying soft reset\n");
}
else
printf("Performing soft reset\n");
bdk_reset_chip(node);
}
}

View File

@ -0,0 +1,108 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-gti.h"
/**
* Setup the watchdog to expire in timeout_ms milliseconds. When the watchdog
* expires, the chip three things happen:
* 1) Expire 1: interrupt that is ignored by the BDK
* 2) Expire 2: DEL3T interrupt, which is disabled and ignored
* 3) Expire 3: Soft reset of the chip
*
* Since we want a soft reset, we actually program the watchdog to expire at
* the timeout / 3.
*
* @param timeout_ms Timeout in milliseconds. If this is zero, the timeout is taken from the
* global configuration option BDK_BRD_CFG_WATCHDOG_TIMEOUT
*/
void bdk_watchdog_set(unsigned int timeout_ms)
{
if (timeout_ms == 0)
timeout_ms = bdk_config_get_int(BDK_CONFIG_WATCHDOG_TIMEOUT);
if (timeout_ms > 0)
{
uint64_t sclk = bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_SCLK);
uint64_t timeout_sclk = sclk * timeout_ms / 1000;
/* Per comment above, we want the watchdog to expire at 3x the rate specified */
timeout_sclk /= 3;
/* Watchdog counts in 1024 cycle steps */
uint64_t timeout_wdog = timeout_sclk >> 10;
/* We can only specify the upper 16 bits of a 24 bit value. Round up */
timeout_wdog = (timeout_wdog + 0xff) >> 8;
/* If the timeout overflows the hardware limit, set max */
if (timeout_wdog >= 0x10000)
timeout_wdog = 0xffff;
BDK_TRACE(INIT, "Watchdog: Set to expire %lu SCLK cycles\n", timeout_wdog << 18);
BDK_CSR_MODIFY(c, bdk_numa_local(), BDK_GTI_CWD_WDOGX(bdk_get_core_num()),
c.s.len = timeout_wdog;
c.s.mode = 3);
}
}
/**
* Signal the watchdog that we are still running
*/
void bdk_watchdog_poke(void)
{
BDK_CSR_WRITE(bdk_numa_local(), BDK_GTI_CWD_POKEX(bdk_get_core_num()), 0);
}
/**
* Disable the hardware watchdog
*/
void bdk_watchdog_disable(void)
{
BDK_CSR_WRITE(bdk_numa_local(), BDK_GTI_CWD_WDOGX(bdk_get_core_num()), 0);
BDK_TRACE(INIT, "Watchdog: Disabled\n");
}
/**
* Return true if the watchdog is configured and running
*
* @return Non-zero if watchdog is running
*/
int bdk_watchdog_is_running(void)
{
BDK_CSR_INIT(wdog, bdk_numa_local(), BDK_GTI_CWD_WDOGX(bdk_get_core_num()));
return wdog.s.mode != 0;
}

View File

@ -0,0 +1,183 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-l2c.h"
#define EXTRACT(v, lsb, width) (((v) >> (lsb)) & ((1ull << (width)) - 1))
#define INSERT(a, v, lsb, width) a|=(((v) & ((1ull << (width)) - 1)) << (lsb))
/**
* Given a physical DRAM address, extract information about the node, LMC, DIMM,
* prank, lrank, bank, row, and column that was accessed.
*
* @param address Physical address to decode
* @param node Node the address was for
* @param lmc LMC controller the address was for
* @param dimm DIMM the address was for
* @param prank Physical RANK on the DIMM
* @param lrank Logical RANK on the DIMM
* @param bank BANK on the DIMM
* @param row Row on the DIMM
* @param col Column on the DIMM
*/
void
bdk_dram_address_extract_info(uint64_t address, int *node, int *lmc, int *dimm,
int *prank, int *lrank, int *bank, int *row, int *col)
{
int bitno = CAVIUM_IS_MODEL(CAVIUM_CN83XX) ? 19 : 20;
*node = EXTRACT(address, 40, 2); /* Address bits [41:40] */
/* Determine the LMC controller */
BDK_CSR_INIT(l2c_ctl, *node, BDK_L2C_CTL);
int bank_lsb, xbits;
/* xbits depends on number of LMCs */
xbits = __bdk_dram_get_num_lmc(*node) >> 1; // 4->2; 2->1; 1->0
bank_lsb = 7 + xbits;
/* LMC number is probably aliased */
if (l2c_ctl.s.disidxalias)
*lmc = EXTRACT(address, 7, xbits);
else
*lmc = EXTRACT(address, 7, xbits) ^ EXTRACT(address, bitno, xbits) ^ EXTRACT(address, 12, xbits);
/* Figure out the bank field width */
BDK_CSR_INIT(lmcx_config, *node, BDK_LMCX_CONFIG(*lmc));
int bank_width = __bdk_dram_get_num_bank_bits(*node, *lmc);
/* Extract additional info from the LMC_CONFIG CSR */
BDK_CSR_INIT(ext_config, *node, BDK_LMCX_EXT_CONFIG(*lmc));
int dimm_lsb = 28 + lmcx_config.s.pbank_lsb + xbits;
int dimm_width = 40 - dimm_lsb;
int prank_lsb = dimm_lsb - lmcx_config.s.rank_ena;
int prank_width = dimm_lsb - prank_lsb;
int lrank_lsb = prank_lsb - ext_config.s.dimm0_cid;
int lrank_width = prank_lsb - lrank_lsb;
int row_lsb = 14 + lmcx_config.s.row_lsb + xbits;
int row_width = lrank_lsb - row_lsb;
int col_hi_lsb = bank_lsb + bank_width;
int col_hi_width= row_lsb - col_hi_lsb;
/* Extract the parts of the address */
*dimm = EXTRACT(address, dimm_lsb, dimm_width);
*prank = EXTRACT(address, prank_lsb, prank_width);
*lrank = EXTRACT(address, lrank_lsb, lrank_width);
*row = EXTRACT(address, row_lsb, row_width);
/* bank calculation may be aliased... */
BDK_CSR_INIT(lmcx_control, *node, BDK_LMCX_CONTROL(*lmc));
if (lmcx_control.s.xor_bank)
*bank = EXTRACT(address, bank_lsb, bank_width) ^ EXTRACT(address, 12 + xbits, bank_width);
else
*bank = EXTRACT(address, bank_lsb, bank_width);
/* LMC number already extracted */
int col_hi = EXTRACT(address, col_hi_lsb, col_hi_width);
*col = EXTRACT(address, 3, 4) | (col_hi << 4);
/* Bus byte is address bits [2:0]. Unused here */
}
/**
* Construct a physical address given the node, LMC, DIMM, prank, lrank, bank, row, and column.
*
* @param node Node the address was for
* @param lmc LMC controller the address was for
* @param dimm DIMM the address was for
* @param prank Physical RANK on the DIMM
* @param lrank Logical RANK on the DIMM
* @param bank BANK on the DIMM
* @param row Row on the DIMM
* @param col Column on the DIMM
*/
uint64_t
bdk_dram_address_construct_info(bdk_node_t node, int lmc, int dimm,
int prank, int lrank, int bank, int row, int col)
{
uint64_t address = 0;
int bitno = CAVIUM_IS_MODEL(CAVIUM_CN83XX) ? 19 : 20;
// insert node bits
INSERT(address, node, 40, 2); /* Address bits [41:40] */
/* xbits depends on number of LMCs */
int xbits = __bdk_dram_get_num_lmc(node) >> 1; // 4->2; 2->1; 1->0
int bank_lsb = 7 + xbits;
/* Figure out the bank field width */
int bank_width = __bdk_dram_get_num_bank_bits(node, lmc);
/* Extract additional info from the LMC_CONFIG CSR */
BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc));
BDK_CSR_INIT(ext_config, node, BDK_LMCX_EXT_CONFIG(lmc));
int dimm_lsb = 28 + lmcx_config.s.pbank_lsb + xbits;
int dimm_width = 40 - dimm_lsb;
int prank_lsb = dimm_lsb - lmcx_config.s.rank_ena;
int prank_width = dimm_lsb - prank_lsb;
int lrank_lsb = prank_lsb - ext_config.s.dimm0_cid;
int lrank_width = prank_lsb - lrank_lsb;
int row_lsb = 14 + lmcx_config.s.row_lsb + xbits;
int row_width = lrank_lsb - row_lsb;
int col_hi_lsb = bank_lsb + bank_width;
int col_hi_width = row_lsb - col_hi_lsb;
/* Insert some other parts of the address */
INSERT(address, dimm, dimm_lsb, dimm_width);
INSERT(address, prank, prank_lsb, prank_width);
INSERT(address, lrank, lrank_lsb, lrank_width);
INSERT(address, row, row_lsb, row_width);
INSERT(address, col >> 4, col_hi_lsb, col_hi_width);
INSERT(address, col, 3, 4);
/* bank calculation may be aliased... */
BDK_CSR_INIT(lmcx_control, node, BDK_LMCX_CONTROL(lmc));
int new_bank = bank;
if (lmcx_control.s.xor_bank)
new_bank ^= EXTRACT(address, 12 + xbits, bank_width);
INSERT(address, new_bank, bank_lsb, bank_width);
/* Determine the actual C bits from the input LMC controller arg */
/* The input LMC number was probably aliased with other fields */
BDK_CSR_INIT(l2c_ctl, node, BDK_L2C_CTL);
int new_lmc = lmc;
if (!l2c_ctl.s.disidxalias)
new_lmc ^= EXTRACT(address, bitno, xbits) ^ EXTRACT(address, 12, xbits);
INSERT(address, new_lmc, 7, xbits);
return address;
}

View File

@ -0,0 +1,163 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include <unistd.h>
BDK_REQUIRE_DEFINE(DRAM_CONFIG);
/**
* Lookup a DRAM configuration by name and initialize DRAM using it
*
* @param node Node to configure
* @param ddr_clock_override
* If non zero, override the DRAM frequency specified
* in the config with this value
*
* @return Amount of DRAM in MB, or negative on failure
*/
int bdk_dram_config(int node, int ddr_clock_override)
{
const dram_config_t *config = libdram_config_load(node);
if (!config)
{
printf("N%d: No DRAM config specified, skipping DRAM init\n", node);
return 0;
}
BDK_TRACE(DRAM, "N%d: Starting DRAM init (config=%p, ddr_clock_override=%d)\n", node, config, ddr_clock_override);
int mbytes = libdram_config(node, config, ddr_clock_override);
BDK_TRACE(DRAM, "N%d: DRAM init returned %d\n", node, mbytes);
if (mbytes <= 0)
{
printf("ERROR: DDR initialization failed\n");
return -1;
}
return mbytes;
}
/**
* Do DRAM configuration tuning
*
* @param node Node to tune
*
* @return Success or Fail
*/
int bdk_dram_tune(int node)
{
int ret;
BDK_TRACE(DRAM, "N%d: Starting DRAM tuning\n", node);
ret = libdram_tune(node);
BDK_TRACE(DRAM, "N%d: DRAM tuning returned %d\n", node, ret);
return ret;
}
/**
* Do all the DRAM Margin tests
*
* @param node Node to test
*
* @return Success or Fail
*/
void bdk_dram_margin(int node)
{
BDK_TRACE(DRAM, "N%d: Starting DRAM margining\n", node);
libdram_margin(node);
BDK_TRACE(DRAM, "N%d: Finished DRAM margining.\n", node);
return;
}
/**
* Return the string of the DRAM configuration info at the specified node.
* If the node is not configured, NULL is returned.
*
* @param node node to retrieve
*
* @return string or NULL
*/
const char* bdk_dram_get_info_string(int node)
{
#define INFO_STRING_LEN 40
static char info_string[INFO_STRING_LEN];
static const char *info_ptr = info_string;
snprintf(info_string, INFO_STRING_LEN,
" %ld MB, %ld MT/s, %s %s",
bdk_dram_get_size_mbytes(node),
bdk_config_get_int(BDK_CONFIG_DDR_SPEED, node),
(__bdk_dram_is_ddr4(node, 0)) ? "DDR4" : "DDR3",
(__bdk_dram_is_rdimm(node, 0)) ? "RDIMM" : "UDIMM");
return info_ptr;
}
/**
* Return the highest address currently used by the BDK. This address will
* be about 4MB above the top of the BDK to make sure small growths between the
* call and its use don't cause corruption. Any call to memory allocation can
* change this value.
*
* @return Size of the BDK in bytes
*/
uint64_t bdk_dram_get_top_of_bdk(void)
{
/* Make sure the start address is higher that the BDK's active range.
*
* As sbrk() returns a node address, mask off the node portion of
* the address to make it a physical offset. Doing this simplifies the
* address checks and calculations which only work with physical offsets.
*/
uint64_t top_of_bdk = (bdk_ptr_to_phys(sbrk(0)) & bdk_build_mask(40));
uint64_t l2_size = bdk_l2c_get_cache_size_bytes(bdk_numa_master());
if (top_of_bdk <= l2_size)
{
/* Early BDK code takes care of the first L2 sized area of memory */
top_of_bdk = l2_size;
}
else
{
/* Give 4MB of extra so the BDK has room to grow */
top_of_bdk += 4 << 20;
/* Align it on a 64KB boundary */
top_of_bdk >>= 16;
top_of_bdk <<= 16;
}
return top_of_bdk;
}

View File

@ -0,0 +1,213 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
/**
* Return the number of LMC controllers in use
*
* @param node Node to probe
*
* @return 2 or 4 depending on the mode
*/
int __bdk_dram_get_num_lmc(bdk_node_t node)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
{
BDK_CSR_INIT(lmcx_dll_ctl2, node, BDK_LMCX_DLL_CTL2(2)); // sample LMC2
return (lmcx_dll_ctl2.s.intf_en) ? 4 : 2;
}
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
{
BDK_CSR_INIT(lmcx_dll_ctl1, node, BDK_LMCX_DLL_CTL2(1)); // sample LMC1
return (lmcx_dll_ctl1.s.intf_en) ? 2 : 1;
}
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
{
return 1;
}
else if (CAVIUM_IS_MODEL(CAVIUM_CN93XX))
{
BDK_CSR_INIT(lmcx_dll_ctl1, node, BDK_LMCX_DLL_CTL2(2));
if (lmcx_dll_ctl1.s.intf_en)
return 3;
lmcx_dll_ctl1.u = BDK_CSR_READ(node, BDK_LMCX_DLL_CTL2(1));
return (lmcx_dll_ctl1.s.intf_en) ? 2 : 1;
}
bdk_error("__bdk_dram_get_num_lmc() needs update for this chip\n");
return 1;
}
/**
* Return whether the node/LMC is in DRESET
*
* @param node Node to probe
* @param node LMC to probe
*
* @return 1 or 0
*/
static int __bdk_dram_is_lmc_in_dreset(bdk_node_t node, int lmc)
{
BDK_CSR_INIT(lmcx_dll_ctl2, node, BDK_LMCX_DLL_CTL2(lmc)); // can always read this
return (lmcx_dll_ctl2.s.dreset != 0) ? 1 : 0;
}
/**
* Return a mask of the number of row bits in use
*
* @param node Node to probe
*
*/
uint32_t __bdk_dram_get_row_mask(bdk_node_t node, int lmc)
{
// PROTECT!!!
if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
return 0;
BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
int numbits = 14 + lmcx_config.s.pbank_lsb - lmcx_config.s.row_lsb - lmcx_config.s.rank_ena;
return ((1ul << numbits) - 1);
}
/**
* Return a mask of the number of column bits in use
*
* @param node Node to probe
*
*/
uint32_t __bdk_dram_get_col_mask(bdk_node_t node, int lmc)
{
// PROTECT!!!
if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
return 0;
BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
int numbits = 11 + lmcx_config.s.row_lsb - __bdk_dram_get_num_bank_bits(node, lmc);
return ((1ul << numbits) - 1);
}
/**
* Return the number of bank bits in use
*
* @param node Node to probe
*
*/
// all DDR3, and DDR4 x16 today, use only 3 bank bits; DDR4 x4 and x8 always have 4 bank bits
// NOTE: this will change in the future, when DDR4 x16 devices can come with 16 banks!! FIXME!!
int __bdk_dram_get_num_bank_bits(bdk_node_t node, int lmc)
{
// PROTECT!!!
if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
return 0;
BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc)); // sample LMCn
int bank_width = (__bdk_dram_is_ddr4(node, lmc) && (lmcx_config.s.bg2_enable)) ? 4 : 3;
return bank_width;
}
/**
* Return whether the node has DDR3 or DDR4 DRAM
*
* @param node Node to probe
*
* @return 0 (DDR3) or 1 (DDR4)
*/
int __bdk_dram_is_ddr4(bdk_node_t node, int lmc)
{
// PROTECT!!!
if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
return 0;
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 1;
BDK_CSR_INIT(lmcx_ddr_pll_ctl, node, BDK_LMCX_DDR_PLL_CTL(lmc)); // sample LMCn
return (lmcx_ddr_pll_ctl.cn83xx.ddr4_mode != 0);
}
/**
* Return whether the node has Registered DIMMs or Unbuffered DIMMs
*
* @param node Node to probe
*
* @return 0 (Unbuffered) or 1 (Registered)
*/
int __bdk_dram_is_rdimm(bdk_node_t node, int lmc)
{
// PROTECT!!!
if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
return 0;
BDK_CSR_INIT(lmcx_control, node, BDK_LMCX_CONTROL(lmc)); // sample LMCn
return (lmcx_control.s.rdimm_ena != 0);
}
/**
* Get the amount of DRAM configured for a node. This is read from the LMC
* controller after DRAM is setup.
*
* @param node Node to query
*
* @return Size in megabytes
*/
uint64_t bdk_dram_get_size_mbytes(int node)
{
if (bdk_is_platform(BDK_PLATFORM_EMULATOR))
return 2 << 10; /* 2GB is available on t88 and t81
** some t83 models have 8gb, but it is too long to init */
/* Return zero if dram isn't enabled */
if (!__bdk_is_dram_enabled(node))
return 0;
uint64_t memsize = 0;
const int num_dram_controllers = __bdk_dram_get_num_lmc(node);
for (int lmc = 0; lmc < num_dram_controllers; lmc++)
{
if (bdk_is_platform(BDK_PLATFORM_ASIM))
{
/* Asim doesn't simulate the rank detection, fake 4GB per controller */
memsize += 4ull << 30;
}
else
{
// PROTECT!!!
if (__bdk_dram_is_lmc_in_dreset(node, lmc)) // check LMCn
return 0;
BDK_CSR_INIT(lmcx_config, node, BDK_LMCX_CONFIG(lmc));
int num_ranks = bdk_pop(lmcx_config.s.init_status);
uint64_t rank_size = 1ull << (28 + lmcx_config.s.pbank_lsb - lmcx_config.s.rank_ena);
memsize += rank_size * num_ranks;
}
}
return memsize >> 20;
}

View File

@ -0,0 +1,115 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include "bdk.h"
/* Used for all memory reads/writes related to the test */
#define READ64(address) __bdk_dram_read64(address)
#define WRITE64(address, data) __bdk_dram_write64(address, data)
/**
* Address bus test. This test writes a single value to each power of two in the
* area, looking for false aliases that would be created by address lines being
* shorted or tied together.
*
* @param area
* @param max_address
* @param bursts
*
* @return
*/
int __bdk_dram_test_mem_address_bus(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
/* Clear our work area. Checking for aliases later could get false
positives if it matched stale data */
void *ptr = (area) ? bdk_phys_to_ptr(area) : NULL;
bdk_zero_memory(ptr, max_address - area);
__bdk_dram_flush_to_mem_range(area, max_address);
/* Each time we write, we'll write this pattern xored the address it is
written too */
uint64_t pattern = 0x0fedcba987654321;
/* Walk through the region incrementing our offset by a power of two. The
first few writes will be to the same cache line (offset 0x8, 0x10, 0x20,
and 0x40. Offset 0x80 and beyond will be to different cache lines */
uint64_t offset = 0x8;
while (area + offset < max_address)
{
uint64_t address = area + offset;
/* Write one location with pattern xor address */
uint64_t p = pattern ^ address;
WRITE64(address, p);
__bdk_dram_flush_to_mem(address);
offset <<= 1;
}
/* Read all of the area to make sure no other locations were written */
uint64_t a = area;
offset = 0x8;
uint64_t next_write = area + offset;
while (a < max_address)
{
if (a + 256 < max_address)
BDK_PREFETCH(a + 256, 0);
for (int i=0; i<16; i++)
{
uint64_t data = READ64(a);
uint64_t correct;
if (a == next_write)
{
correct = pattern ^ next_write;
offset <<= 1;
next_write = area + offset;
}
else
correct = 0;
if (bdk_unlikely(data != correct))
{
failures++;
__bdk_dram_report_error(a, data, correct, 0, -1);
}
a += 8;
}
}
return failures;
}

View File

@ -0,0 +1,252 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include "bdk.h"
/* Used for all memory reads/writes related to the test */
#define READ64(address) __bdk_dram_read64(address)
#define WRITE64(address, data) __bdk_dram_write64(address, data)
/* Build a 64bit mask out of a single hex digit */
#define REPEAT2(v) ((((uint64_t)v) << 4) | ((uint64_t)v))
#define REPEAT4(v) ((REPEAT2(v) << 8) | REPEAT2(v))
#define REPEAT8(v) ((REPEAT4(v) << 16) | REPEAT4(v))
#define REPEAT16(v) ((REPEAT8(v) << 32) | REPEAT8(v))
/**
* Read memory and check that the data bus pattern is present. The pattern is a
* sequence if 16 dwords created from the 16 hex digits repeated in each word.
*
* @param address Physical address to read. This must be cache line aligned.
* @param bursts Number of time to repeat the read test to verify stability
*
* @return Number of errors, zero means success
*/
static int read_data_bus_burst(uint64_t address, int bursts)
{
int failures = 0;
/* Loop over the burst so people using a scope have time to capture
traces */
for (int burst = 0; burst < bursts; burst++)
{
/* Invalidate all caches so we must read from DRAM */
__bdk_dram_flush_to_mem(address);
BDK_DCACHE_INVALIDATE;
for (uint64_t digit = 0; digit < 16; digit++)
{
uint64_t a = address + digit * 8;
uint64_t data = READ64(a);
uint64_t correct = REPEAT16(digit);
if (data != correct)
{
failures++;
__bdk_dram_report_error(a, data, correct, burst, -1);
}
}
}
return failures;
}
/**
* Write memory with a data bus pattern and check that it can be read correctly.
* The pattern is a sequence if 16 dwords created from the 16 hex digits repeated
* in each word.
*
* @param address Physical address to write. This must be cache line aligned. 128 bytes will be
* written starting at this address.
* @param bursts Number of time to repeat the write+read test to verify stability
*
* @return Number of errors, zero means success
*/
static int write_data_bus_burst(uint64_t address, int bursts)
{
BDK_TRACE(DRAM_TEST, "[0x%016lx:0x%016lx] Writing incrementing digits\n",
address, address + 127);
/* Loop over the burst so people using a scope have time to capture
traces */
for (int burst = 0; burst < bursts; burst++)
{
/* Fill a cache line with an incrementing pattern. Each nibble
in the 64bit word increments from 0 to 0xf */
for (uint64_t digit = 0; digit < 16; digit++)
WRITE64(address + digit * 8, REPEAT16(digit));
/* Force the cache line out to memory */
__bdk_dram_flush_to_mem(address);
}
return read_data_bus_burst(address, bursts);
}
/**
* Read back the pattern written by write_data_bus_walk() nad
* make sure it was stored properly.
*
* @param address Physical address to read. This must be cache line aligned.
* @param bursts Number of time to repeat the read test to verify stability
* @param pattern Pattern basis for writes. See
* write_data_bus_walk()
*
* @return Number of errors, zero means success
*/
static int read_data_bus_walk(uint64_t address, int burst, uint64_t pattern)
{
int failures = 0;
/* Invalidate all caches so we must readfrom DRAM */
__bdk_dram_flush_to_mem(address);
BDK_DCACHE_INVALIDATE;
uint64_t correct = pattern;
for (uint64_t word = 0; word < 16; word++)
{
uint64_t a = address + word * 8;
uint64_t data = READ64(a);
if (data != correct)
{
failures++;
__bdk_dram_report_error(a, data, correct, burst, -1);
}
uint64_t tmp = correct >> 63; /* Save top bit */
correct <<= 1; /* Shift left one bit */
correct |= tmp; /* Restore the top bit as bit 0 */
}
return failures;
}
/**
* Write a pattern to a cache line, rotating it one bit for each DWORD. Read back
* the pattern and make sure it was stored properly. The input pattern is rotated
* left by one bit for each DWORD written.
*
* @param address Physical address to write. This must be cache line aligned. 128 bytes will be
* written starting at this address.
* @param bursts Number of time to repeat the write+read test to verify stability
* @param pattern Pattern basis
*
* @return Number of errors, zero means success
*/
static void write_data_bus_walk(uint64_t address, int burst, uint64_t pattern)
{
BDK_TRACE(DRAM_TEST, "[0x%016lx:0x%016lx] Writing walking pattern 0x%016lx\n",
address, address + 127, pattern);
uint64_t a = address;
uint64_t d = pattern;
/* Fill a cache line with pattern. Each 64bit work will have the
pattern rotated left one bit */
for (uint64_t word = 0; word < 16; word++)
{
WRITE64(a, d);
a += 8;
uint64_t tmp = d >> 63; /* Save top bit */
d <<= 1; /* Shift left one bit */
d |= tmp; /* Restore the top bit as bit 0 */
}
/* Force the cache line out to memory */
__bdk_dram_flush_to_mem(address);
}
/**
* The goal of these tests are to toggle every DDR data pin, one at a time or in
* related groups, to isolate any short circuits between the data pins or open
* circuits where the pin is not connected to the DDR memory. A board which fails
* one of these tests has severe problems and will not be able to run any of the
* later test patterns.
*
* @param start_address
* Physical address of a cache line to
* use for the test. Only this cache line is
* written.
* @param end_address
* Top end of the address range. Currently unused
* @param bursts Number of time to repeats writes+reads to insure stability
*
* @return Number of errors, zero means success
*/
int __bdk_dram_test_mem_data_bus(uint64_t start_address, uint64_t end_address, int bursts)
{
int failures = 0;
/* Incrementing pattern: 0x0 - 0xf in each nibble */
failures += write_data_bus_burst(start_address, bursts);
/* Walking ones. Run with 1, 2, and 3 bits walking */
for (int bits = 1; bits <= 3; bits++)
{
for (int burst = 0; burst < bursts; burst++)
{
/* Each write_data_bus_walk() call write 16 dword, so step by 16 */
for (int i = 0; i < 64; i += 16)
{
uint64_t pattern = bdk_build_mask(bits) << i;
write_data_bus_walk(start_address + i*8, burst, pattern);
}
/* Each read_data_bus_walk() call write 16 dword, so step by 16 */
for (int i = 0; i < 64; i += 16)
{
uint64_t pattern = bdk_build_mask(bits) << i;
failures += read_data_bus_walk(start_address + i*8, burst, pattern);
}
}
}
/* Walking zeros. Run with 1, 2, and 3 bits walking */
for (int bits = 1; bits <= 3; bits++)
{
for (int burst = 0; burst < bursts; burst++)
{
/* Each write_data_bus_walk() call write 16 dword, so step by 16 */
for (int i = 0; i < 64; i += 16)
{
uint64_t pattern = ~(bdk_build_mask(bits) << i);
write_data_bus_walk(start_address + i*8, burst, pattern);
}
/* Each read_data_bus_walk() call write 16 dword, so step by 16 */
for (int i = 0; i < 64; i += 16)
{
uint64_t pattern = ~(bdk_build_mask(bits) << i);
failures += read_data_bus_walk(start_address + i*8, burst, pattern);
}
}
}
return failures;
}

View File

@ -0,0 +1,103 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include "bdk.h"
/* Used for all memory reads/writes related to the test */
#define READ64(address) __bdk_dram_read64(address)
#define WRITE64(address, data) __bdk_dram_write64(address, data)
/**
* Fast scan test. This test is meant to find gross errors caused by read/write
* level failing on a single rank or dimm. The idea is to scan through all of
* memory in large steps. The large steps hit each rank multiple times, but not
* every byte. If the whole rank has errors, his should find it quickly. This test
* is suitable for an alive test during early boot.
*
* @param area Starting physical address
* @param max_address
* Ending physical address, exclusive
* @param bursts Burst to run
*
* @return Number of errors
*/
int __bdk_dram_test_fast_scan(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
const uint64_t step = 0x10008; /* The 8 is so we walk through cache lines too */
const uint64_t pattern1 = 0xaaaaaaaaaaaaaaaa;
const uint64_t pattern2 = 0x5555555555555555;
/* Walk through the region incrementing our offset by STEP */
uint64_t a = area;
while (a + 16 <= max_address)
{
WRITE64(a, pattern1);
WRITE64(a+8, pattern2);
__bdk_dram_flush_to_mem_range(a, a + 16);
a += step;
}
/* Read back, checking the writes */
a = area;
while (a + 16 <= max_address)
{
/* Prefetch 3 ahead for better performance */
uint64_t pre = a + step * 2;
if (pre + 16 < max_address)
BDK_PREFETCH(pre, 0);
/* Check pattern 1 */
uint64_t data1 = READ64(a);
if (bdk_unlikely(data1 != pattern1))
{
failures++;
__bdk_dram_report_error(a, data1, pattern1, 0, -1);
}
/* Check pattern 2 */
uint64_t data2 = READ64(a+8);
if (bdk_unlikely(data2 != pattern2))
{
failures++;
__bdk_dram_report_error(a+8, data2, pattern2, 0, -1);
}
a += step;
}
return failures;
}

View File

@ -0,0 +1,829 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include "bdk.h"
// choose prediction-based algorithms for mem_xor and mem_rows tests
#define USE_PREDICTION_CODE_VERSIONS 1 // change to 0 to go back to the original versions
/* Used for all memory reads/writes related to the test */
#define READ64(address) __bdk_dram_read64(address)
#define WRITE64(address, data) __bdk_dram_write64(address, data)
/**
* Fill an memory area with the address of each 64-bit word in the area.
* Reread to confirm the pattern.
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area (exclusive)
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_self_addr(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
{
/* Write the pattern to memory. Each location receives the address
* of the location.
*/
for (uint64_t address = area; address < max_address; address+=8)
WRITE64(address, address);
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Read by ascending address the written memory and confirm that it
* has the expected data pattern.
*/
for (uint64_t address = area; address < max_address; )
{
if (address + 256 < max_address)
BDK_PREFETCH(address + 256, 0);
for (int i=0; i<16; i++)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != address))
failures += __bdk_dram_retry_failure(burst, address, data, address);
address += 8;
}
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Read by descending address the written memory and confirm that it
* has the expected data pattern.
*/
uint64_t end = max_address - sizeof(uint64_t);
for (uint64_t address = end; address >= area; )
{
if (address - 256 >= area)
BDK_PREFETCH(address - 256, 0);
for (int i=0; i<16; i++)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != address))
failures += __bdk_dram_retry_failure(burst, address, data, address);
address -= 8;
}
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Read from random addresses within the memory area.
*/
uint64_t probes = (max_address - area) / 128;
uint64_t address_ahead1 = area;
uint64_t address_ahead2 = area;
for (uint64_t i = 0; i < probes; i++)
{
/* Create a pipeline of prefetches:
address = address read this loop
address_ahead1 = prefetch started last loop
address_ahead2 = prefetch started this loop */
uint64_t address = address_ahead1;
address_ahead1 = address_ahead2;
address_ahead2 = bdk_rng_get_random64() % (max_address - area);
address_ahead2 += area;
address_ahead2 &= -8;
BDK_PREFETCH(address_ahead2, 0);
uint64_t data = READ64(address);
if (bdk_unlikely(data != address))
failures += __bdk_dram_retry_failure(burst, address, data, address);
}
}
return failures;
}
/**
* Write "pattern" and its compliment to memory and verify it was written
* properly. Memory will be filled with DWORDs pattern, ~pattern, pattern,
* ~pattern, ...
*
* @param area Start physical address of memory
* @param max_address
* End of physical memory region
* @param pattern Pattern to write
* @param passes Number of time to repeat the test
*
* @return Number of errors, zero on success
*/
static uint32_t test_mem_pattern(uint64_t area, uint64_t max_address, uint64_t pattern,
int passes)
{
int failures = 0;
for (int pass = 0; pass < passes; pass++)
{
if (pass & 0x1)
pattern = ~pattern;
for (uint64_t address = area; address < max_address; address += 8)
WRITE64(address, pattern);
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Read the written memory and confirm that it has the expected
* data pattern.
*/
uint64_t address = area;
while (address < max_address)
{
if (address + 256 < max_address)
BDK_PREFETCH(address + 256, 0);
for (int i=0; i<16; i++)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != pattern))
failures += __bdk_dram_retry_failure(pass, address, data, pattern);
address += 8;
}
}
}
return failures;
}
/**
* Walking zero written to memory, left shift
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_leftwalk0(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
{
for (uint64_t pattern = 1; pattern != 0; pattern = pattern << 1)
failures += test_mem_pattern(area, max_address, ~pattern, 1);
}
return failures;
}
/**
* Walking one written to memory, left shift
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_leftwalk1(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
{
for (uint64_t pattern = 1; pattern != 0; pattern = pattern << 1)
failures += test_mem_pattern(area, max_address, pattern, 1);
}
return failures;
}
/**
* Walking zero written to memory, right shift
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_rightwalk0(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
{
for (uint64_t pattern = 1ull << 63; pattern != 0; pattern = pattern >> 1)
failures += test_mem_pattern(area, max_address, ~pattern, 1);
}
return failures;
}
/**
* Walking one written to memory, right shift
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_rightwalk1(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
{
for (uint64_t pattern = 1ull<<63; pattern != 0; pattern = pattern >> 1)
failures += test_mem_pattern(area, max_address, pattern, 1);
}
return failures;
}
/**
* Apply the March C- testing algorithm to the given memory area.
* 1) Write "pattern" to memory.
* 2) Verify "pattern" and write "~pattern".
* 3) Verify "~pattern" and write "pattern".
* 4) Verify "pattern" and write "~pattern".
* 5) Verify "~pattern" and write "pattern".
* 6) Verify "pattern".
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param pattern
*
* @return Number of errors, zero on success
*/
static int test_mem_march_c(uint64_t area, uint64_t max_address, uint64_t pattern)
{
int failures = 0;
/* Pass 1 ascending addresses, fill memory with pattern. */
BDK_TRACE(DRAM_TEST, " [0x%016lx:0x%016lx] Phase1, address incrementing, pattern 0x%016lx\n", area, max_address-1, pattern);
for (uint64_t address = area; address < max_address; address += 8)
WRITE64(address, pattern);
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Pass 2: ascending addresses, read pattern and write ~pattern */
BDK_TRACE(DRAM_TEST, " [0x%016lx:0x%016lx] Phase2, address incrementing, pattern 0x%016lx\n", area, max_address-1, ~pattern);
for (uint64_t address = area; address < max_address; address += 8)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != pattern))
failures += __bdk_dram_retry_failure(1, address, data, pattern);
WRITE64(address, ~pattern);
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Pass 3: ascending addresses, read ~pattern and write pattern. */
BDK_TRACE(DRAM_TEST, " [0x%016lx:0x%016lx] Phase3, address incrementing, pattern 0x%016lx\n", area, max_address-1, pattern);
for (uint64_t address = area; address < max_address; address += 8)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != ~pattern))
failures += __bdk_dram_retry_failure(1, address, data, ~pattern);
WRITE64(address, pattern);
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Pass 4: descending addresses, read pattern and write ~pattern. */
BDK_TRACE(DRAM_TEST, " [0x%016lx:0x%016lx] Phase4, address decrementing, pattern 0x%016lx\n", area, max_address-1, ~pattern);
uint64_t end = max_address - sizeof(uint64_t);
for (uint64_t address = end; address >= area; address -= 8)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != pattern))
failures += __bdk_dram_retry_failure(1, address, data, pattern);
WRITE64(address, ~pattern);
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Pass 5: descending addresses, read ~pattern and write pattern. */
BDK_TRACE(DRAM_TEST, " [0x%016lx:0x%016lx] Phase5, address decrementing, pattern 0x%016lx\n", area, max_address-1, pattern);
for (uint64_t address = end; address >= area; address -= 8)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != ~pattern))
failures += __bdk_dram_retry_failure(1, address, data, ~pattern);
WRITE64(address, pattern);
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Pass 6: ascending addresses, read pattern. */
BDK_TRACE(DRAM_TEST, " [0x%016lx:0x%016lx] Phase6, address incrementing\n", area, max_address-1);
for (uint64_t address = area; address < max_address; address += 8)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != pattern))
failures += __bdk_dram_retry_failure(1, address, data, pattern);
}
return failures;
}
/**
* Use test_mem_march_c() with a all ones pattern
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_solid(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
failures += test_mem_march_c(area, max_address, -1);
return failures;
}
/**
* Use test_mem_march_c() with a 0x55 pattern
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_checkerboard(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
failures += test_mem_march_c(area, max_address, 0x5555555555555555L);
return failures;
}
/**
* Write a pseudo random pattern to memory and verify it
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_random(uint64_t area, uint64_t max_address, int bursts)
{
/* This constant is used to increment the pattern after every DWORD. This
makes only the first DWORD truly random, but saves us processing
power generating the random values */
const uint64_t INC = 0x1010101010101010ULL;
int failures = 0;
for (int burst = 0; burst < bursts; burst++)
{
const uint64_t init_pattern = bdk_rng_get_random64();
uint64_t pattern = init_pattern;
/* Write the pattern to memory. Each location receives the address
* of the location. A second write pass is needed to force all of
* the cached memory out to the DDR.
*/
for (uint64_t address = area; address < max_address; address += 8)
{
WRITE64(address, pattern);
pattern += INC;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Read the written memory and confirm that it has the expected
* data pattern.
*/
pattern = init_pattern;
for (uint64_t address = area; address < max_address; address += 8)
{
uint64_t data = READ64(address);
if (bdk_unlikely(data != pattern))
failures += __bdk_dram_retry_failure(burst, address, data, pattern);
pattern += INC;
}
}
return failures;
}
#if !USE_PREDICTION_CODE_VERSIONS
/**
* test_mem_xor
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of time to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_xor(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
uint64_t extent = max_address - area;
uint64_t count = (extent / sizeof(uint64_t)) / 2;
/* Fill both halves of the memory area with identical randomized data.
*/
uint64_t address1 = area;
uint64_t address2 = area + count * sizeof(uint64_t);
uint64_t pattern = bdk_rng_get_random64();
for (uint64_t j = 0; j < count; j++)
{
uint64_t p = pattern * address1;
WRITE64(address1, p);
WRITE64(address2, p);
address1 += 8;
address2 += 8;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Make a series of passes over the memory areas. */
for (int burst = 0; burst < bursts; burst++)
{
/* XOR the data with a random value, applying the change to both
* memory areas.
*/
address1 = area;
address2 = area + count * sizeof(uint64_t);
pattern = bdk_rng_get_random64();
for (uint64_t j = 0; j < count; j++)
{
if ((address1 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1, BDK_CACHE_LINE_SIZE);
if ((address2 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address2, BDK_CACHE_LINE_SIZE);
WRITE64(address1, READ64(address1) ^ pattern);
WRITE64(address2, READ64(address2) ^ pattern);
address1 += 8;
address2 += 8;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Look for differences in the areas. If there is a mismatch, reset
* both memory locations with the same pattern. Failing to do so
* means that on all subsequent passes the pair of locations remain
* out of sync giving spurious errors.
*/
address1 = area;
address2 = area + count * sizeof(uint64_t);
for (uint64_t j = 0; j < count; j++)
{
if ((address1 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1, BDK_CACHE_LINE_SIZE);
if ((address2 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address2, BDK_CACHE_LINE_SIZE);
uint64_t d1 = READ64(address1);
uint64_t d2 = READ64(address2);
if (bdk_unlikely(d1 != d2))
{
failures += __bdk_dram_retry_failure2(burst, address1, d1, address2, d2);
// Synchronize the two areas, adjusting for the error.
WRITE64(address1, d2);
WRITE64(address2, d2);
}
address1 += 8;
address2 += 8;
}
}
return failures;
}
/**
* test_mem_rows
*
* Write a pattern of alternating 64-bit words of all one bits and then all 0
* bits. This pattern generates the maximum amount of simultaneous switching
* activity on the memory channels. Each pass flips the pattern with words
* going from all ones to all zeros and vice versa.
*
* @param area Start of the physical memory area
* @param max_address
* End of the physical memory area
* @param bursts Number of times to repeat the test over the entire area
*
* @return Number of errors, zero on success
*/
int __bdk_dram_test_mem_rows(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
uint64_t pattern = 0x0;
uint64_t extent = (max_address - area);
uint64_t count = (extent / 2) / sizeof(uint64_t); // in terms of 64bit words
/* Fill both halves of the memory area with identical data pattern. Odd
* address 64-bit words get the pattern, while even address words get the
* inverted pattern.
*/
uint64_t address1 = area;
uint64_t address2 = area + count * sizeof(uint64_t);
for (uint64_t j = 0; j < (count / 2); j++)
{
WRITE64(address1, pattern);
WRITE64(address2, pattern);
address1 += 8;
address2 += 8;
WRITE64(address1, ~pattern);
WRITE64(address2, ~pattern);
address1 += 8;
address2 += 8;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Make a series of passes over the memory areas. */
for (int burst = 0; burst < bursts; burst++)
{
/* Invert the data, applying the change to both memory areas. Thus on
* alternate passes, the data flips from 0 to 1 and vice versa.
*/
address1 = area;
address2 = area + count * sizeof(uint64_t);
for (uint64_t j = 0; j < count; j++)
{
WRITE64(address1, ~READ64(address1));
WRITE64(address2, ~READ64(address2));
address1 += 8;
address2 += 8;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Look for differences in the areas. If there is a mismatch, reset
* both memory locations with the same pattern. Failing to do so
* means that on all subsequent passes the pair of locations remain
* out of sync giving spurious errors.
*/
address1 = area;
address2 = area + count * sizeof(uint64_t);
for (uint64_t j = 0; j < count; j++)
{
uint64_t d1 = READ64(address1);
uint64_t d2 = READ64(address2);
if (bdk_unlikely(d1 != d2))
{
failures += __bdk_dram_retry_failure2(burst, address1, d1, address2, d2);
// Synchronize the two areas, adjusting for the error.
WRITE64(address1, d2);
WRITE64(address2, d2);
}
address1 += 8;
address2 += 8;
}
}
return failures;
}
#endif /* !USE_PREDICTION_CODE_VERSIONS */
#if USE_PREDICTION_CODE_VERSIONS
//////////////////////////// this is the new code...
int __bdk_dram_test_mem_xor(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
int burst;
uint64_t extent = max_address - area;
uint64_t count = (extent / sizeof(uint64_t)) / 2;
uint64_t offset = count * sizeof(uint64_t);
uint64_t area2 = area + offset;
/* Fill both halves of the memory area with identical randomized data.
*/
uint64_t address1 = area;
uint64_t pattern1 = bdk_rng_get_random64();
uint64_t pattern2 = 0;
uint64_t this_pattern;
uint64_t p;
uint64_t d1, d2;
// move the multiplies outside the loop
uint64_t pbase = address1 * pattern1;
uint64_t pincr = 8 * pattern1;
uint64_t ppred;
p = pbase;
while (address1 < area2)
{
WRITE64(address1 , p);
WRITE64(address1 + offset, p);
address1 += 8;
p += pincr;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Make a series of passes over the memory areas. */
for (burst = 0; burst < bursts; burst++)
{
/* XOR the data with a random value, applying the change to both
* memory areas.
*/
address1 = area;
this_pattern = bdk_rng_get_random64();
pattern2 ^= this_pattern;
while (address1 < area2)
{
#if 1
if ((address1 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1, BDK_CACHE_LINE_SIZE);
if (((address1 + offset) & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1 + offset, BDK_CACHE_LINE_SIZE);
#endif
WRITE64(address1 , READ64(address1 ) ^ this_pattern);
WRITE64(address1 + offset, READ64(address1 + offset) ^ this_pattern);
address1 += 8;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Look for differences from the expected pattern in both areas.
* If there is a mismatch, reset the appropriate memory location
* with the correct pattern. Failing to do so
* means that on all subsequent passes the erroring locations
* will be out of sync, giving spurious errors.
*/
address1 = area;
ppred = pbase;
while (address1 < area2)
{
#if 1
if ((address1 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1, BDK_CACHE_LINE_SIZE);
if (((address1 + offset) & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1 + offset, BDK_CACHE_LINE_SIZE);
#endif
d1 = READ64(address1 );
d2 = READ64(address1 + offset);
p = ppred ^ pattern2;
if (bdk_unlikely(d1 != p)) {
failures += __bdk_dram_retry_failure(burst, address1, d1, p);
// Synchronize the area, adjusting for the error.
//WRITE64(address1, p); // retries should do this
}
if (bdk_unlikely(d2 != p)) {
failures += __bdk_dram_retry_failure(burst, address1 + offset, d2, p);
// Synchronize the area, adjusting for the error.
//WRITE64(address1 + offset, p); // retries should do this
}
address1 += 8;
ppred += pincr;
} /* while (address1 < area2) */
} /* for (int burst = 0; burst < bursts; burst++) */
return failures;
}
//////////////// this is the new code...
int __bdk_dram_test_mem_rows(uint64_t area, uint64_t max_address, int bursts)
{
int failures = 0;
uint64_t pattern1 = 0x0;
uint64_t extent = (max_address - area);
uint64_t count = (extent / 2) / sizeof(uint64_t); // in terms of 64bit words
uint64_t offset = count * sizeof(uint64_t);
uint64_t area2 = area + offset;
uint64_t pattern2;
uint64_t d1, d2;
int burst;
/* Fill both halves of the memory area with identical data pattern. Odd
* address 64-bit words get the pattern, while even address words get the
* inverted pattern.
*/
uint64_t address1 = area;
pattern2 = pattern1; // start with original pattern
while (address1 < area2)
{
WRITE64(address1 , pattern2);
WRITE64(address1 + offset, pattern2);
address1 += 8;
pattern2 = ~pattern2; // flip for next slots
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Make a series of passes over the memory areas. */
for (burst = 0; burst < bursts; burst++)
{
/* Invert the data, applying the change to both memory areas. Thus on
* alternate passes, the data flips from 0 to 1 and vice versa.
*/
address1 = area;
while (address1 < area2)
{
if ((address1 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1 , BDK_CACHE_LINE_SIZE);
if (((address1 + offset) & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1 + offset, BDK_CACHE_LINE_SIZE);
WRITE64(address1 , ~READ64(address1 ));
WRITE64(address1 + offset, ~READ64(address1 + offset));
address1 += 8;
}
__bdk_dram_flush_to_mem_range(area, max_address);
BDK_DCACHE_INVALIDATE;
/* Look for differences in the areas. If there is a mismatch, reset
* both memory locations with the same pattern. Failing to do so
* means that on all subsequent passes the pair of locations remain
* out of sync giving spurious errors.
*/
address1 = area;
pattern1 = ~pattern1; // flip the starting pattern to match above loop
pattern2 = pattern1; // slots have been flipped by the above loop
while (address1 < area2)
{
if ((address1 & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1 , BDK_CACHE_LINE_SIZE);
if (((address1 + offset) & BDK_CACHE_LINE_MASK) == 0)
BDK_PREFETCH(address1 + offset, BDK_CACHE_LINE_SIZE);
d1 = READ64(address1 );
d2 = READ64(address1 + offset);
if (bdk_unlikely(d1 != pattern2)) {
failures += __bdk_dram_retry_failure(burst, address1, d1, pattern2);
// Synchronize the area, adjusting for the error.
//WRITE64(address1, pattern2); // retries should do this
}
if (bdk_unlikely(d2 != pattern2)) {
failures += __bdk_dram_retry_failure(burst, address1 + offset, d2, pattern2);
// Synchronize the two areas, adjusting for the error.
//WRITE64(address1 + offset, pattern2); // retries should do this
}
address1 += 8;
pattern2 = ~pattern2; // flip for next pair of slots
}
}
return failures;
}
#endif /* USE_PREDICTION_CODE_VERSIONS */

View File

@ -0,0 +1,860 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-gti.h"
#include "libbdk-arch/bdk-csrs-ocx.h"
/* This code is an optional part of the BDK. It is only linked in
if BDK_REQUIRE() needs it */
BDK_REQUIRE_DEFINE(DRAM_TEST);
#define MAX_ERRORS_TO_REPORT 50
#define RETRY_LIMIT 1000
typedef struct
{
const char * name; /* Friendly name for the test */
__bdk_dram_test_t test_func; /* Function to call */
int bursts; /* Bursts parameter to pass to the test */
int max_cores; /* Maximum number of cores the test should be run on in parallel. Zero means all */
} dram_test_info_t;
static const dram_test_info_t TEST_INFO[] = {
/* Name, Test function, Bursts, Max Cores */
{ "Data Bus", __bdk_dram_test_mem_data_bus, 8, 1},
{ "Address Bus", __bdk_dram_test_mem_address_bus, 0, 1},
{ "Marching Rows", __bdk_dram_test_mem_rows, 16, 0},
{ "Random Data", __bdk_dram_test_mem_random, 32, 0},
{ "Random XOR (32 Burst)", __bdk_dram_test_mem_xor, 32, 0},
{ "Self Address", __bdk_dram_test_mem_self_addr, 1, 0},
{ "March C- Solid Bits", __bdk_dram_test_mem_solid, 1, 0},
{ "March C- Checkerboard", __bdk_dram_test_mem_checkerboard, 1, 0},
{ "Walking Ones Left", __bdk_dram_test_mem_leftwalk1, 1, 0},
{ "Walking Ones Right", __bdk_dram_test_mem_rightwalk1, 1, 0},
{ "Walking Zeros Left", __bdk_dram_test_mem_leftwalk0, 1, 0},
{ "Walking Zeros Right", __bdk_dram_test_mem_rightwalk0, 1, 0},
{ "Random XOR (224 Burst)", __bdk_dram_test_mem_xor, 224, 0},
{ "Fast Scan", __bdk_dram_test_fast_scan, 0, 0},
{ NULL, NULL, 0, 0}
};
/* These variables count the number of ECC errors. They should only be accessed atomically */
int64_t __bdk_dram_ecc_single_bit_errors[BDK_MAX_MEM_CHANS];
int64_t __bdk_dram_ecc_double_bit_errors[BDK_MAX_MEM_CHANS];
static int64_t dram_test_thread_done;
static int64_t dram_test_thread_errors;
static uint64_t dram_test_thread_start;
static uint64_t dram_test_thread_end;
static uint64_t dram_test_thread_size;
/**
* Force the memory at the pointer location to be written to memory and evicted
* from L2. L1 will be unaffected.
*
* @param address Physical memory location
*/
void __bdk_dram_flush_to_mem(uint64_t address)
{
BDK_MB;
/* The DRAM code doesn't use the normal bdk_phys_to_ptr() because of the
NULL check in it. This greatly slows down the memory tests */
char *ptr = (void*)address;
BDK_CACHE_WBI_L2(ptr);
}
/**
* Force a memory region to be written to DRAM and evicted from L2
*
* @param area Start of the region
* @param max_address
* End of the region (exclusive)
*/
void __bdk_dram_flush_to_mem_range(uint64_t area, uint64_t max_address)
{
/* The DRAM code doesn't use the normal bdk_phys_to_ptr() because of the
NULL check in it. This greatly slows down the memory tests */
char *ptr = (void*)area;
char *end = (void*)max_address;
BDK_MB;
while (ptr < end)
{
BDK_CACHE_WBI_L2(ptr);
ptr += 128;
}
}
/**
* Convert a test enumeration into a string
*
* @param test Test to convert
*
* @return String for display
*/
const char *bdk_dram_get_test_name(int test)
{
if (test < (int)(sizeof(TEST_INFO) / sizeof(TEST_INFO[0])))
return TEST_INFO[test].name;
else
return NULL;
}
static bdk_dram_test_flags_t dram_test_flags; // FIXME: Don't use global
/**
* This function is run as a thread to perform memory tests over multiple cores.
* Each thread gets a section of memory to work on, which is controlled by global
* variables at the beginning of this file.
*
* @param arg Number of the region we should check
* @param arg1 Pointer the the test_info structure
*/
static void dram_test_thread(int arg, void *arg1)
{
const dram_test_info_t *test_info = arg1;
const int bursts = test_info->bursts;
const int range_number = arg;
/* Figure out our work memory range.
*
* Note start_address and end_address just provide the physical offset
* portion of the address and do not have the node bits set. This is
* to simplify address checks and calculations. Later, when about to run
* the memory test, the routines adds in the node bits to form the final
* addresses.
*/
uint64_t start_address = dram_test_thread_start + dram_test_thread_size * range_number;
uint64_t end_address = start_address + dram_test_thread_size;
if (end_address > dram_test_thread_end)
end_address = dram_test_thread_end;
bdk_node_t test_node = bdk_numa_local();
if (dram_test_flags & BDK_DRAM_TEST_USE_CCPI)
test_node ^= 1;
/* Insert the node part of the address */
start_address = bdk_numa_get_address(test_node, start_address);
end_address = bdk_numa_get_address(test_node, end_address);
/* Test the region */
BDK_TRACE(DRAM_TEST, " Node %d, core %d, Testing [0x%011lx:0x%011lx]\n",
bdk_numa_local(), bdk_get_core_num() & 127, start_address, end_address - 1);
test_info->test_func(start_address, end_address, bursts);
/* Report that we're done */
BDK_TRACE(DRAM_TEST, "Thread %d on node %d done with memory test\n", range_number, bdk_numa_local());
bdk_atomic_add64_nosync(&dram_test_thread_done, 1);
}
/**
* Run the memory test.
*
* @param test_info
* @param start_address
* Physical address to start at
* @param length Length of memory block
* @param flags Flags to control memory test options. Zero defaults to testing all
* node with statistics and progress output.
*
* @return Number of errors found. Zero is success. Negative means the test
* did not run due to some other failure.
*/
static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start_address,
uint64_t length, bdk_dram_test_flags_t flags)
{
/* Figure out the addess of the byte one off the top of memory */
uint64_t max_address = bdk_dram_get_size_mbytes(bdk_numa_local());
BDK_TRACE(DRAM_TEST, "DRAM available per node: %lu MB\n", max_address);
max_address <<= 20;
/* Make sure we have enough */
if (max_address < (16<<20))
{
bdk_error("DRAM size is too small\n");
return -1;
}
/* Make sure the amount is sane */
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
{
if (max_address > (1ull << 40)) /* 40 bits in CN8XXX */
max_address = 1ull << 40;
}
else
{
if (max_address > (1ull << 43)) /* 43 bits in CN9XXX */
max_address = 1ull << 43;
}
BDK_TRACE(DRAM_TEST, "DRAM max address: 0x%011lx\n", max_address-1);
/* Make sure the start address is lower than the top of memory */
if (start_address >= max_address)
{
bdk_error("Start address is larger than the amount of memory: 0x%011lx versus 0x%011lx\n",
start_address, max_address);
return -1;
}
if (length == (uint64_t)-1)
length = max_address - start_address;
/* Final range checks */
uint64_t end_address = start_address + length;
if (end_address > max_address)
{
end_address = max_address;
length = end_address - start_address;
}
if (length == 0)
return 0;
/* Ready to run the test. Figure out how many cores we need */
int max_cores = test_info->max_cores;
int total_cores_all_nodes = max_cores;
/* Figure out the number of cores available in the system */
if (max_cores == 0)
{
max_cores += bdk_get_num_running_cores(bdk_numa_local());
/* Calculate the total number of cores being used. The per node number
is confusing to people */
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
if (flags & (1 << node))
{
if (flags & BDK_DRAM_TEST_USE_CCPI)
total_cores_all_nodes += bdk_get_num_running_cores(node ^ 1);
else
total_cores_all_nodes += bdk_get_num_running_cores(node);
}
}
if (!(flags & BDK_DRAM_TEST_NO_BANNERS))
printf("Starting Test \"%s\" for [0x%011lx:0x%011lx] using %d core(s)\n",
test_info->name, start_address, end_address - 1, total_cores_all_nodes);
/* Remember the LMC perf counters for stats after the test */
uint64_t start_dram_dclk[BDK_NUMA_MAX_NODES][4];
uint64_t start_dram_ops[BDK_NUMA_MAX_NODES][4];
uint64_t stop_dram_dclk[BDK_NUMA_MAX_NODES][4];
uint64_t stop_dram_ops[BDK_NUMA_MAX_NODES][4];
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1 << node))
{
const int num_dram_controllers = __bdk_dram_get_num_lmc(node);
for (int i = 0; i < num_dram_controllers; i++)
{
start_dram_dclk[node][i] = BDK_CSR_READ(node, BDK_LMCX_DCLK_CNT(i));
start_dram_ops[node][i] = BDK_CSR_READ(node, BDK_LMCX_OPS_CNT(i));
}
}
}
/* Remember the CCPI link counters for stats after the test */
uint64_t start_ccpi_data[BDK_NUMA_MAX_NODES][3];
uint64_t start_ccpi_idle[BDK_NUMA_MAX_NODES][3];
uint64_t start_ccpi_err[BDK_NUMA_MAX_NODES][3];
uint64_t stop_ccpi_data[BDK_NUMA_MAX_NODES][3];
uint64_t stop_ccpi_idle[BDK_NUMA_MAX_NODES][3];
uint64_t stop_ccpi_err[BDK_NUMA_MAX_NODES][3];
if (!bdk_numa_is_only_one())
{
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1 << node))
{
for (int link = 0; link < 3; link++)
{
start_ccpi_data[node][link] = BDK_CSR_READ(node, BDK_OCX_TLKX_STAT_DATA_CNT(link));
start_ccpi_idle[node][link] = BDK_CSR_READ(node, BDK_OCX_TLKX_STAT_IDLE_CNT(link));
start_ccpi_err[node][link] = BDK_CSR_READ(node, BDK_OCX_TLKX_STAT_ERR_CNT(link));
}
}
}
}
/* WARNING: This code assumes the same memory range is being tested on
all nodes. The same number of cores are used on each node to test
its local memory */
uint64_t work_address = start_address;
dram_test_flags = flags;
bdk_atomic_set64(&dram_test_thread_errors, 0);
while ((work_address < end_address) && ((dram_test_thread_errors == 0) || (flags & BDK_DRAM_TEST_NO_STOP_ERROR)))
{
/* Check at most MAX_CHUNK_SIZE across each iteration. We only report
progress between chunks, so keep them reasonably small */
const uint64_t MAX_CHUNK_SIZE = 1ull << 28; /* 256MB */
uint64_t size = end_address - work_address;
if (size > MAX_CHUNK_SIZE)
size = MAX_CHUNK_SIZE;
/* Divide memory evenly between the cores. Round the size up so that
all memory is covered. The last core may have slightly less memory to
test */
uint64_t thread_size = (size + (max_cores - 1)) / max_cores;
thread_size += 127;
thread_size &= -128;
dram_test_thread_start = work_address;
dram_test_thread_end = work_address + size;
dram_test_thread_size = thread_size;
BDK_WMB;
/* Poke the watchdog */
BDK_CSR_WRITE(bdk_numa_local(), BDK_GTI_CWD_POKEX(0), 0);
/* disable progress output when batch mode is ON */
if (!(flags & BDK_DRAM_TEST_NO_PROGRESS)) {
/* Report progress percentage */
int percent_x10 = (work_address - start_address) * 1000 / (end_address - start_address);
printf(" %3d.%d%% complete, testing [0x%011lx:0x%011lx]\r",
percent_x10 / 10, percent_x10 % 10, work_address, work_address + size - 1);
fflush(stdout);
}
work_address += size;
/* Start threads for all the cores */
int total_count = 0;
bdk_atomic_set64(&dram_test_thread_done, 0);
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1 << node))
{
const int num_cores = bdk_get_num_cores(node);
int per_node = 0;
for (int core = 0; core < num_cores; core++)
{
if (per_node >= max_cores)
break;
int run_node = (flags & BDK_DRAM_TEST_USE_CCPI) ? node ^ 1 : node;
BDK_TRACE(DRAM_TEST, "Starting thread %d on node %d for memory test\n", per_node, node);
if (bdk_thread_create(run_node, 0, dram_test_thread, per_node, (void *)test_info, 0))
{
bdk_error("Failed to create thread %d for memory test on node %d\n", per_node, node);
}
else
{
per_node++;
total_count++;
}
}
}
}
#if 0
/* Wait for threads to finish */
while (bdk_atomic_get64(&dram_test_thread_done) < total_count)
bdk_thread_yield();
#else
#define TIMEOUT_SECS 30 // FIXME: long enough so multicore RXOR 224 should not print out
/* Wait for threads to finish, with progress */
int cur_count;
uint64_t cur_time;
uint64_t period = bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) * TIMEOUT_SECS; // FIXME?
uint64_t timeout = bdk_clock_get_count(BDK_CLOCK_TIME) + period;
do {
bdk_thread_yield();
cur_count = bdk_atomic_get64(&dram_test_thread_done);
cur_time = bdk_clock_get_count(BDK_CLOCK_TIME);
if (cur_time >= timeout) {
BDK_TRACE(DRAM_TEST, "N%d: Waiting for %d cores\n",
bdk_numa_local(), total_count - cur_count);
timeout = cur_time + period;
}
} while (cur_count < total_count);
#endif
}
/* Get the DRAM perf counters */
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1 << node))
{
const int num_dram_controllers = __bdk_dram_get_num_lmc(node);
for (int i = 0; i < num_dram_controllers; i++)
{
stop_dram_dclk[node][i] = BDK_CSR_READ(node, BDK_LMCX_DCLK_CNT(i));
stop_dram_ops[node][i] = BDK_CSR_READ(node, BDK_LMCX_OPS_CNT(i));
}
}
}
/* Get the CCPI link counters */
if (!bdk_numa_is_only_one())
{
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1 << node))
{
for (int link = 0; link < 3; link++)
{
stop_ccpi_data[node][link] = BDK_CSR_READ(node, BDK_OCX_TLKX_STAT_DATA_CNT(link));
stop_ccpi_idle[node][link] = BDK_CSR_READ(node, BDK_OCX_TLKX_STAT_IDLE_CNT(link));
stop_ccpi_err[node][link] = BDK_CSR_READ(node, BDK_OCX_TLKX_STAT_ERR_CNT(link));
}
}
}
}
/* disable progress output when batch mode is ON */
if (!(flags & BDK_DRAM_TEST_NO_PROGRESS)) {
/* Report progress percentage as complete */
printf(" %3d.%d%% complete, testing [0x%011lx:0x%011lx]\n",
100, 0, start_address, end_address - 1);
fflush(stdout);
}
if (!(flags & BDK_DRAM_TEST_NO_STATS))
{
/* Display LMC load */
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1 << node))
{
const int num_dram_controllers = __bdk_dram_get_num_lmc(node);
for (int i = 0; i < num_dram_controllers; i++)
{
uint64_t ops = stop_dram_ops[node][i] - start_dram_ops[node][i];
uint64_t dclk = stop_dram_dclk[node][i] - start_dram_dclk[node][i];
if (dclk == 0)
dclk = 1;
uint64_t percent_x10 = ops * 1000 / dclk;
printf(" Node %d, LMC%d: ops %lu, cycles %lu, used %lu.%lu%%\n",
node, i, ops, dclk, percent_x10 / 10, percent_x10 % 10);
}
}
}
if (flags & BDK_DRAM_TEST_USE_CCPI)
{
/* Display CCPI load */
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1 << node))
{
for (int link = 0; link < 3; link++)
{
uint64_t busy = stop_ccpi_data[node][link] - start_ccpi_data[node][link];
busy += stop_ccpi_err[node][link] - start_ccpi_err[node][link];
uint64_t total = stop_ccpi_idle[node][link] - start_ccpi_idle[node][link];
total += busy;
if (total == 0)
continue;
uint64_t percent_x10 = busy * 1000 / total;
printf(" Node %d, CCPI%d: busy %lu, total %lu, used %lu.%lu%%\n",
node, link, busy, total, percent_x10 / 10, percent_x10 % 10);
}
}
}
}
}
return dram_test_thread_errors;
}
/**
* Perform a memory test.
*
* @param test Test type to run
* @param start_address
* Physical address to start at
* @param length Length of memory block
* @param flags Flags to control memory test options. Zero defaults to testing all
* node with statistics and progress output.
*
* @return Number of errors found. Zero is success. Negative means the test
* did not run due to some other failure.
*/
int bdk_dram_test(int test, uint64_t start_address, uint64_t length, bdk_dram_test_flags_t flags)
{
/* These limits are arbitrary. They just make sure we aren't doing something
silly, like test a non cache line aligned memory region */
if (start_address & 0xffff)
{
bdk_error("DRAM test start address must be aligned on a 64KB boundary\n");
return -1;
}
if (length & 0xffff)
{
bdk_error("DRAM test length must be a multiple of 64KB\n");
return -1;
}
const char *name = bdk_dram_get_test_name(test);
if (name == NULL)
{
bdk_error("Invalid DRAM test number %d\n", test);
return -1;
}
/* If no nodes are selected assume the user meant all nodes */
if ((flags & (BDK_DRAM_TEST_NODE0 | BDK_DRAM_TEST_NODE1 | BDK_DRAM_TEST_NODE2 | BDK_DRAM_TEST_NODE3)) == 0)
flags |= BDK_DRAM_TEST_NODE0 | BDK_DRAM_TEST_NODE1 | BDK_DRAM_TEST_NODE2 | BDK_DRAM_TEST_NODE3;
/* Remove nodes from the flags that don't exist */
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & BDK_DRAM_TEST_USE_CCPI)
{
if (!bdk_numa_exists(node ^ 1))
flags &= ~(1 << node);
}
else
{
if (!bdk_numa_exists(node))
flags &= ~(1 << node);
}
}
/* Make sure the start address is higher that the BDK's active range */
uint64_t top_of_bdk = bdk_dram_get_top_of_bdk();
if (start_address < top_of_bdk)
start_address = top_of_bdk;
/* Clear ECC error counters before starting the test */
for (int chan = 0; chan < BDK_MAX_MEM_CHANS; chan++) {
bdk_atomic_set64(&__bdk_dram_ecc_single_bit_errors[chan], 0);
bdk_atomic_set64(&__bdk_dram_ecc_double_bit_errors[chan], 0);
}
/* Make sure at least one core from each node is running */
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (flags & (1<<node))
{
int use_node = (flags & BDK_DRAM_TEST_USE_CCPI) ? node ^ 1 : node;
if (bdk_get_running_coremask(use_node) == 0)
bdk_init_cores(use_node, 1);
}
}
/* This returns any data compare errors found */
int errors = __bdk_dram_run_test(&TEST_INFO[test], start_address, length, flags);
/* Poll for any errors right now to make sure any ECC errors are reported */
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (bdk_numa_exists(node) && bdk_error_check)
bdk_error_check(node);
}
/* Check ECC error counters after the test */
int64_t ecc_single = 0;
int64_t ecc_double = 0;
int64_t ecc_single_errs[BDK_MAX_MEM_CHANS];
int64_t ecc_double_errs[BDK_MAX_MEM_CHANS];
for (int chan = 0; chan < BDK_MAX_MEM_CHANS; chan++) {
ecc_single += (ecc_single_errs[chan] = bdk_atomic_get64(&__bdk_dram_ecc_single_bit_errors[chan]));
ecc_double += (ecc_double_errs[chan] = bdk_atomic_get64(&__bdk_dram_ecc_double_bit_errors[chan]));
}
/* Always print any ECC errors */
if (ecc_single || ecc_double)
{
printf("Test \"%s\": ECC errors, %ld/%ld/%ld/%ld corrected, %ld/%ld/%ld/%ld uncorrected\n",
name,
ecc_single_errs[0], ecc_single_errs[1], ecc_single_errs[2], ecc_single_errs[3],
ecc_double_errs[0], ecc_double_errs[1], ecc_double_errs[2], ecc_double_errs[3]);
}
if (errors || ecc_double || ecc_single) {
printf("Test \"%s\": FAIL: %ld single, %ld double, %d compare errors\n",
name, ecc_single, ecc_double, errors);
}
else
BDK_TRACE(DRAM_TEST, "Test \"%s\": PASS\n", name);
return (errors + ecc_double + ecc_single);
}
/**
* Report a DRAM address in decoded format.
*
* @param address Physical address the error occurred at
*
*/
static void __bdk_dram_report_address_decode(uint64_t address, char *buffer, int len)
{
int node, lmc, dimm, prank, lrank, bank, row, col;
bdk_dram_address_extract_info(address, &node, &lmc, &dimm, &prank, &lrank, &bank, &row, &col);
snprintf(buffer, len, "[0x%011lx] (N%d,LMC%d,DIMM%d,Rank%d/%d,Bank%02d,Row 0x%05x,Col 0x%04x)",
address, node, lmc, dimm, prank, lrank, bank, row, col);
}
/**
* Report a DRAM address in a new decoded format.
*
* @param address Physical address the error occurred at
* @param xor XOR of data read vs expected data
*
*/
static void __bdk_dram_report_address_decode_new(uint64_t address, uint64_t orig_xor, char *buffer, int len)
{
int node, lmc, dimm, prank, lrank, bank, row, col;
int byte = 8; // means no byte-lanes in error, should not happen
uint64_t bits, print_bits = 0;
uint64_t xor = orig_xor;
// find the byte-lane(s) with errors
for (int i = 0; i < 8; i++) {
bits = xor & 0xffULL;
xor >>= 8;
if (bits) {
if (byte != 8) {
byte = 9; // means more than 1 byte-lane was present
print_bits = orig_xor; // print the full original
break; // quit now
} else {
byte = i; // keep checking
print_bits = bits;
}
}
}
bdk_dram_address_extract_info(address, &node, &lmc, &dimm, &prank, &lrank, &bank, &row, &col);
snprintf(buffer, len, "N%d.LMC%d: CMP byte %d xor 0x%02lx (DIMM%d,Rank%d/%d,Bank%02d,Row 0x%05x,Col 0x%04x)[0x%011lx]",
node, lmc, byte, print_bits, dimm, prank, lrank, bank, row, col, address);
}
/**
* Report a DRAM error. Errors are not shown after MAX_ERRORS_TO_REPORT is
* exceeded. Used when a single address is involved in the failure.
*
* @param address Physical address the error occurred at
* @param data Data read from memory
* @param correct Correct data
* @param burst Which burst this is from, informational only
* @param fails -1 for no retries done, >= 0 number of failures during retries
*
* @return Zero if a message was logged, non-zero if the error limit has been reached
*/
void __bdk_dram_report_error(uint64_t address, uint64_t data, uint64_t correct, int burst, int fails)
{
char buffer[128];
char failbuf[32];
int64_t errors = bdk_atomic_fetch_and_add64(&dram_test_thread_errors, 1);
uint64_t xor = data ^ correct;
if (errors < MAX_ERRORS_TO_REPORT)
{
if (fails < 0) {
snprintf(failbuf, sizeof(failbuf), " ");
} else {
int percent_x10 = fails * 1000 / RETRY_LIMIT;
snprintf(failbuf, sizeof(failbuf), ", retries failed %3d.%d%%",
percent_x10 / 10, percent_x10 % 10);
}
__bdk_dram_report_address_decode_new(address, xor, buffer, sizeof(buffer));
bdk_error("%s%s\n", buffer, failbuf);
if (errors == MAX_ERRORS_TO_REPORT-1)
bdk_error("No further DRAM errors will be reported\n");
}
return;
}
/**
* Report a DRAM error. Errors are not shown after MAX_ERRORS_TO_REPORT is
* exceeded. Used when two addresses might be involved in the failure.
*
* @param address1 First address involved in the failure
* @param data1 Data from the first address
* @param address2 Second address involved in the failure
* @param data2 Data from second address
* @param burst Which burst this is from, informational only
* @param fails -1 for no retries done, >= 0 number of failures during retries
*
* @return Zero if a message was logged, non-zero if the error limit has been reached
*/
void __bdk_dram_report_error2(uint64_t address1, uint64_t data1, uint64_t address2, uint64_t data2,
int burst, int fails)
{
int64_t errors = bdk_atomic_fetch_and_add64(&dram_test_thread_errors, 1);
if (errors < MAX_ERRORS_TO_REPORT)
{
char buffer1[80], buffer2[80];
char failbuf[32];
if (fails < 0) {
snprintf(failbuf, sizeof(failbuf), " ");
} else {
snprintf(failbuf, sizeof(failbuf), ", retried %d failed %d", RETRY_LIMIT, fails);
}
__bdk_dram_report_address_decode(address1, buffer1, sizeof(buffer1));
__bdk_dram_report_address_decode(address2, buffer2, sizeof(buffer2));
bdk_error("compare: data1: 0x%016lx, xor: 0x%016lx%s\n"
" %s\n %s\n",
data1, data1 ^ data2, failbuf,
buffer1, buffer2);
if (errors == MAX_ERRORS_TO_REPORT-1)
bdk_error("No further DRAM errors will be reported\n");
}
return;
}
/* Report the circumstances of a failure and try re-reading the memory
* location to see if the error is transient or permanent.
*
* Note: re-reading requires using evicting addresses
*/
int __bdk_dram_retry_failure(int burst, uint64_t address, uint64_t data, uint64_t expected)
{
int refail = 0;
// bypass the retries if we are already over the limit...
if (bdk_atomic_get64(&dram_test_thread_errors) < MAX_ERRORS_TO_REPORT) {
/* Try re-reading the memory location. A transient error may fail
* on one read and work on another. Keep on retrying even when a
* read succeeds.
*/
for (int i = 0; i < RETRY_LIMIT; i++) {
__bdk_dram_flush_to_mem(address);
BDK_DCACHE_INVALIDATE;
uint64_t new = __bdk_dram_read64(address);
if (new != expected) {
refail++;
}
}
} else
refail = -1;
// this will increment the errors always, but maybe not print...
__bdk_dram_report_error(address, data, expected, burst, refail);
return 1;
}
/**
* retry_failure2
*
* @param burst
* @param address1
* @param address2
*/
int __bdk_dram_retry_failure2(int burst, uint64_t address1, uint64_t data1, uint64_t address2, uint64_t data2)
{
int refail = 0;
// bypass the retries if we are already over the limit...
if (bdk_atomic_get64(&dram_test_thread_errors) < MAX_ERRORS_TO_REPORT) {
for (int i = 0; i < RETRY_LIMIT; i++) {
__bdk_dram_flush_to_mem(address1);
__bdk_dram_flush_to_mem(address2);
BDK_DCACHE_INVALIDATE;
uint64_t d1 = __bdk_dram_read64(address1);
uint64_t d2 = __bdk_dram_read64(address2);
if (d1 != d2) {
refail++;
}
}
} else
refail = -1;
// this will increment the errors always, but maybe not print...
__bdk_dram_report_error2(address1, data1, address2, data2, burst, refail);
return 1;
}
/**
* Inject a DRAM error at a specific address in memory. The injection can either
* be a single bit inside the byte, or a double bit error in the ECC byte. Double
* bit errors may corrupt memory, causing software to crash. The corruption is
* written to memory and will continue to exist until the cache line is written
* again. After a call to this function, the BDK should report a ECC error. Double
* bit errors corrupt bits 0-1.
*
* @param address Physical address to corrupt. Any byte alignment is supported
* @param bit Bit to corrupt in the byte (0-7), or -1 to create a double bit fault in the ECC
* byte.
*/
void bdk_dram_test_inject_error(uint64_t address, int bit)
{
uint64_t aligned_address = address & -16;
int corrupt_bit = -1;
if (bit >= 0)
corrupt_bit = (address & 0xf) * 8 + bit;
/* Extract the DRAM controller information */
int node, lmc, dimm, prank, lrank, bank, row, col;
bdk_dram_address_extract_info(address, &node, &lmc, &dimm, &prank, &lrank, &bank, &row, &col);
/* Read the current data */
uint64_t data = __bdk_dram_read64(aligned_address);
/* Program LMC to inject the error */
if ((corrupt_bit >= 0) && (corrupt_bit < 64))
BDK_CSR_WRITE(node, BDK_LMCX_CHAR_MASK0(lmc), 1ull << corrupt_bit);
else if (bit == -1)
BDK_CSR_WRITE(node, BDK_LMCX_CHAR_MASK0(lmc), 3);
else
BDK_CSR_WRITE(node, BDK_LMCX_CHAR_MASK0(lmc), 0);
if (corrupt_bit >= 64)
BDK_CSR_WRITE(node, BDK_LMCX_CHAR_MASK2(lmc), 1ull << (corrupt_bit - 64));
else
BDK_CSR_WRITE(node, BDK_LMCX_CHAR_MASK2(lmc), 0);
BDK_CSR_MODIFY(c, node, BDK_LMCX_ECC_PARITY_TEST(lmc),
c.s.ecc_corrupt_idx = (address & 0x7f) >> 4;
c.s.ecc_corrupt_ena = 1);
BDK_CSR_READ(node, BDK_LMCX_ECC_PARITY_TEST(lmc));
/* Perform a write and push it to DRAM. This creates the error */
__bdk_dram_write64(aligned_address, data);
__bdk_dram_flush_to_mem(aligned_address);
/* Disable error injection */
BDK_CSR_MODIFY(c, node, BDK_LMCX_ECC_PARITY_TEST(lmc),
c.s.ecc_corrupt_ena = 0);
BDK_CSR_READ(node, BDK_LMCX_ECC_PARITY_TEST(lmc));
BDK_CSR_WRITE(node, BDK_LMCX_CHAR_MASK0(lmc), 0);
BDK_CSR_WRITE(node, BDK_LMCX_CHAR_MASK2(lmc), 0);
/* Read back the data, which should now cause an error */
printf("Loading the injected error address 0x%lx, node=%d, lmc=%d, dimm=%d, rank=%d/%d, bank=%d, row=%d, col=%d\n",
address, node, lmc, dimm, prank, lrank, bank, row, col);
__bdk_dram_read64(aligned_address);
}

View File

@ -0,0 +1,124 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-pccpf.h"
#include "libbdk-arch/bdk-csrs-rnm.h"
BDK_REQUIRE_DEFINE(RNM);
/**
* Reads 8 bits of random data from Random number generator
*
* @return random data
*/
uint8_t bdk_rng_get_random8(void)
{
return bdk_read64_uint8(bdk_numa_get_address(bdk_numa_local(), BDK_RNM_RANDOM));
}
/**
* Reads 16 bits of random data from Random number generator
*
* @return random data
*/
uint16_t bdk_rng_get_random16(void)
{
return bdk_read64_uint16(bdk_numa_get_address(bdk_numa_local(), BDK_RNM_RANDOM));
}
/**
* Reads 32 bits of random data from Random number generator
*
* @return random data
*/
uint32_t bdk_rng_get_random32(void)
{
return bdk_read64_uint32(bdk_numa_get_address(bdk_numa_local(), BDK_RNM_RANDOM));
}
/**
* Reads 64 bits of random data from Random number generator
*
* @return random data
*/
uint64_t bdk_rng_get_random64(void)
{
return bdk_read64_uint64(bdk_numa_get_address(bdk_numa_local(), BDK_RNM_RANDOM));
}
/**
* The RNM probe function
*
* @param device RNM to probe
*
* @return Zero on success, negative on failure
*/
static int probe(bdk_device_t *device)
{
bdk_device_rename(device, "N%d.RNM%d", device->node, device->instance);
return 0;
}
/**
* RNM init() function
*
* @param device RNM to initialize
*
* @return Zero on success, negative on failure
*/
static int init(bdk_device_t *device)
{
BDK_BAR_MODIFY(c, device, BDK_RNM_CTL_STATUS,
c.s.ent_en = 1;
c.s.rng_en = 1);
/* Read back after enable so we know it is done. Needed on t88 pass 2.0 emulator */
BDK_BAR_READ(device, BDK_RNM_CTL_STATUS);
/* Errata (RNM-22528) First consecutive reads to RNM_RANDOM return same
value. Before using the random entropy, read RNM_RANDOM at least once
and discard the data */
bdk_rng_get_random64();
return 0;
}
bdk_driver_t __bdk_driver_rnm = {
.id = (BDK_PCC_PROD_E_GEN << 24) | BDK_PCC_VENDOR_E_CAVIUM | (BDK_PCC_DEV_IDL_E_RNM << 16),
.probe = probe,
.init = init,
};

View File

@ -0,0 +1,221 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-gti.h"
#include "libbdk-arch/bdk-csrs-ocx.h"
/**
* Called in __bdk_init to setup the global timer
*/
void bdk_clock_setup(bdk_node_t node)
{
const bdk_node_t local_node = bdk_numa_local();
/* Check if the counter was already setup */
BDK_CSR_INIT(cntcr, node, BDK_GTI_CC_CNTCR);
if (cntcr.s.en)
return;
/* Configure GTI to tick at BDK_GTI_RATE */
uint64_t sclk = bdk_clock_get_rate(node, BDK_CLOCK_SCLK);
uint64_t inc = (BDK_GTI_RATE << 32) / sclk;
BDK_CSR_WRITE(node, BDK_GTI_CC_CNTRATE, inc);
BDK_CSR_WRITE(node, BDK_GTI_CTL_CNTFRQ, BDK_GTI_RATE);
cntcr.s.en = 1;
if (node != local_node)
{
/* Synchronize with local node. Very simple set of counter, will be
off a little */
BDK_CSR_WRITE(node, BDK_GTI_CC_CNTCV, bdk_clock_get_count(BDK_CLOCK_TIME));
}
/* Enable the counter */
BDK_CSR_WRITE(node, BDK_GTI_CC_CNTCR, cntcr.u);
BDK_CSR_READ(node, BDK_GTI_CC_CNTCR);
if (node != local_node)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
{
/* Assume the delay in each direction is the same, sync the counters */
int64_t local1 = bdk_clock_get_count(BDK_CLOCK_TIME);
int64_t remote = BDK_CSR_READ(node, BDK_GTI_CC_CNTCV);
int64_t local2 = bdk_clock_get_count(BDK_CLOCK_TIME);
int64_t expected = (local1 + local2) / 2;
BDK_CSR_WRITE(node, BDK_GTI_CC_CNTADD, expected - remote);
BDK_TRACE(INIT, "N%d.GTI: Clock synchronization with master\n"
" expected: %ld, remote %ld\n"
" Counter correction: %ld\n",
node, expected, remote, expected - remote);
}
else
{
/* Due to errata TBD, we need to use OCX_PP_CMD to write
GTI_CC_CNTMB in order for timestamps to update. These constants
are the addresses we need for both local and remote GTI_CC_CNTMB */
const uint64_t LOCAL_GTI_CC_CNTMB = bdk_numa_get_address(local_node, BDK_GTI_CC_CNTMB);
const uint64_t REMOTE_GTI_CC_CNTMB = bdk_numa_get_address(node, BDK_GTI_CC_CNTMB);
/* Build partial OCX_PP_CMD command used for writes. Address will
be filled later */
BDK_CSR_DEFINE(pp_cmd, BDK_OCX_PP_CMD);
pp_cmd.u = 0;
pp_cmd.s.wr_mask = 0xff;
const int NUM_AVERAGE = 16; /* Choose a power of two to avoid division */
int64_t local_to_remote_sum = 0;
int64_t local_to_remote_min = 1000000;
int64_t local_to_remote_max = -1000000;
int64_t remote_to_local_sum = 0;
int64_t remote_to_local_min = 1000000;
int64_t remote_to_local_max = -1000000;
for (int loop = 0; loop < NUM_AVERAGE; loop++)
{
/* Perform a write to the remote GTI_CC_CNTMB to cause timestamp
update. We don't care about the value actually written */
pp_cmd.s.addr = REMOTE_GTI_CC_CNTMB;
BDK_CSR_WRITE(local_node, BDK_OCX_PP_CMD, pp_cmd.u);
BDK_CSR_READ(local_node, BDK_OCX_PP_CMD);
int64_t remote = BDK_CSR_READ(node, BDK_GTI_CC_CNTMBTS);
int64_t local = BDK_CSR_READ(local_node, BDK_GTI_CC_CNTMBTS);
int64_t delta = remote - local;
local_to_remote_sum += delta;
if (delta < local_to_remote_min)
local_to_remote_min = delta;
if (delta > local_to_remote_max)
local_to_remote_max = delta;
/* Perform a write to the local GTI_CC_CNTMB to cause timestamp
update. We don't care about the value actually written */
pp_cmd.s.addr = LOCAL_GTI_CC_CNTMB;
BDK_CSR_WRITE(node, BDK_OCX_PP_CMD, pp_cmd.u);
BDK_CSR_READ(node, BDK_OCX_PP_CMD);
remote = BDK_CSR_READ(node, BDK_GTI_CC_CNTMBTS);
local = BDK_CSR_READ(local_node, BDK_GTI_CC_CNTMBTS);
delta = local - remote;
remote_to_local_sum += delta;
if (delta < remote_to_local_min)
remote_to_local_min = delta;
if (delta > remote_to_local_max)
remote_to_local_max = delta;
}
/* Calculate average, rounding to nearest */
int64_t local_to_remote = (local_to_remote_sum + NUM_AVERAGE/2) / NUM_AVERAGE;
int64_t remote_to_local = (remote_to_local_sum + NUM_AVERAGE/2) / NUM_AVERAGE;
/* Calculate remote node offset */
int64_t remote_offset = (remote_to_local - local_to_remote) / 2;
BDK_CSR_WRITE(node, BDK_GTI_CC_CNTADD, remote_offset);
BDK_TRACE(INIT, "N%d.GTI: Clock synchronization with master\n"
" local -> remote: min %ld, avg %ld, max %ld\n"
" remote -> local: min %ld, avg %ld, max %ld\n"
" Counter correction: %ld\n",
node,
local_to_remote_min, local_to_remote, local_to_remote_max,
remote_to_local_min, remote_to_local, remote_to_local_max,
remote_offset);
}
}
}
/**
* Get cycle count based on the clock type.
*
* @param clock - Enumeration of the clock type.
* @return - Get the number of cycles executed so far.
*/
uint64_t __bdk_clock_get_count_slow(bdk_clock_t clock)
{
bdk_node_t node = bdk_numa_local();
BDK_CSR_INIT(rst_boot, node, BDK_RST_BOOT);
if (bdk_is_platform(BDK_PLATFORM_EMULATOR))
{
/* Force RCLK and SCLK to be 1GHz on emulator */
rst_boot.s.c_mul = 20;
rst_boot.s.pnr_mul = 20;
}
uint64_t ref_cntr = BDK_CSR_READ(node, BDK_RST_REF_CNTR);
switch(clock)
{
case BDK_CLOCK_TIME:
return 0; /* Handled in fast path */
case BDK_CLOCK_MAIN_REF:
return ref_cntr;
case BDK_CLOCK_RCLK:
return ref_cntr * rst_boot.s.c_mul;
case BDK_CLOCK_SCLK:
return ref_cntr * rst_boot.s.pnr_mul;
}
return 0;
}
/**
* Get clock rate based on the clock type.
*
* @param node Node to use in a Numa setup. Can be an exact ID or a special value.
* @param clock - Enumeration of the clock type.
* @return - return the clock rate.
*/
uint64_t __bdk_clock_get_rate_slow(bdk_node_t node, bdk_clock_t clock)
{
/* This is currently defined to be 50Mhz */
const uint64_t REF_CLOCK = 50000000;
BDK_CSR_INIT(mio_rst_boot, node, BDK_RST_BOOT);
if (bdk_is_platform(BDK_PLATFORM_EMULATOR))
{
/* Force RCLK and SCLK to be 1GHz on emulator */
mio_rst_boot.s.c_mul = 20;
mio_rst_boot.s.pnr_mul = 20;
}
switch (clock)
{
case BDK_CLOCK_TIME:
return BDK_GTI_RATE; /* Programed as part of setup */
case BDK_CLOCK_MAIN_REF:
return REF_CLOCK;
case BDK_CLOCK_RCLK:
return REF_CLOCK * mio_rst_boot.s.c_mul;
case BDK_CLOCK_SCLK:
return REF_CLOCK * mio_rst_boot.s.pnr_mul;
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,197 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-gpio.h"
/* This code is an optional part of the BDK. It is only linked in
if BDK_REQUIRE() needs it */
BDK_REQUIRE_DEFINE(GPIO);
/**
* Initialize a single GPIO as either an input or output. If it is
* an output, also set its output value.
*
* @param gpio GPIO to initialize
* @param is_output Non zero if this GPIO should be an output
* @param output_value
* Value of the GPIO if it should be an output. Not used if the
* GPIO isn't an output.
*
* @return Zero on success, negative ob failure
*/
int bdk_gpio_initialize(bdk_node_t node, int gpio, int is_output, int output_value)
{
if ((gpio >= 0) && (gpio < bdk_gpio_get_num()))
{
int gpio_group = gpio >> 6;
int gpio_index = gpio & 63;
if (output_value)
bdk_gpio_set(node, gpio_group, 1ull << gpio_index);
else
bdk_gpio_clear(node, gpio_group, 1ull << gpio_index);
BDK_CSR_DEFINE(cfg, BDK_GPIO_BIT_CFGX(gpio));
cfg.u = 0;
cfg.s.tx_oe = !!is_output;
BDK_CSR_WRITE(node, BDK_GPIO_BIT_CFGX(gpio), cfg.u);
}
else
{
bdk_error("bdk_gpio_initialize: Illegal GPIO\n");
return -1;
}
return 0;
}
/**
* GPIO Read Data
*
* @param node Node GPIO block is on
* @param gpio_block GPIO block to access. Each block contains up to 64 GPIOs
*
* @return Status of the GPIO pins for the given block
*/
uint64_t bdk_gpio_read(bdk_node_t node, int gpio_block)
{
bdk_gpio_rx_dat_t gpio_rx_dat;
switch (gpio_block)
{
case 0:
gpio_rx_dat.u = BDK_CSR_READ(node, BDK_GPIO_RX_DAT);
break;
case 1:
gpio_rx_dat.u = BDK_CSR_READ(node, BDK_GPIO_RX1_DAT);
break;
default:
bdk_error("GPIO block %d not supported\n", gpio_block);
gpio_rx_dat.u = 0;
break;
}
return gpio_rx_dat.s.dat;
}
/**
* GPIO Clear pin
*
* @param node Node GPIO block is on
* @param gpio_block GPIO block to access. Each block contains up to 64 GPIOs
* @param clear_mask Bit mask to indicate which bits to drive to '0'.
*/
void bdk_gpio_clear(bdk_node_t node, int gpio_block, uint64_t clear_mask)
{
switch (gpio_block)
{
case 0:
BDK_CSR_WRITE(node, BDK_GPIO_TX_CLR, clear_mask);
break;
case 1:
BDK_CSR_WRITE(node, BDK_GPIO_TX1_CLR, clear_mask);
break;
default:
bdk_error("GPIO block %d not supported\n", gpio_block);
break;
}
}
/**
* GPIO Set pin
*
* @param node Node GPIO block is on
* @param gpio_block GPIO block to access. Each block contains up to 64 GPIOs
* @param set_mask Bit mask to indicate which bits to drive to '1'.
*/
void bdk_gpio_set(bdk_node_t node, int gpio_block, uint64_t set_mask)
{
switch (gpio_block)
{
case 0:
BDK_CSR_WRITE(node, BDK_GPIO_TX_SET, set_mask);
break;
case 1:
BDK_CSR_WRITE(node, BDK_GPIO_TX1_SET, set_mask);
break;
default:
bdk_error("GPIO block %d not supported\n", gpio_block);
break;
}
}
/** GPIO Select pin
*
* @param node CPU node
* @param gpio GPIO number
* @param pin Pin number
*/
void bdk_gpio_select_pin(bdk_node_t node, int gpio, int pin)
{
if ((gpio < 0) || (gpio >= bdk_gpio_get_num()))
{
bdk_warn("bdk_gpio_select_pin: Illegal GPIO %d\n", gpio);
return;
}
BDK_CSR_MODIFY(c, node, BDK_GPIO_BIT_CFGX(gpio), c.s.pin_sel = pin);
}
/**
* Return the number of GPIO pins on this chip
*
* @return Number of GPIO pins
*/
int bdk_gpio_get_num(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
return 51;
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
return 48;
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
return 80;
else if (CAVIUM_IS_MODEL(CAVIUM_CN93XX))
return 96;
else
{
bdk_error("bdk_gpio_get_num(): Unsupported chip");
return 0;
}
}

View File

@ -0,0 +1,270 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-ap.h"
#include "libbdk-arch/bdk-csrs-l2c.h"
#include "libbdk-arch/bdk-csrs-l2c_cbc.h"
#include "libbdk-arch/bdk-csrs-mio_fus.h"
typedef struct
{
int sets;
int ways;
bool is_locked;
} l2_node_state_t;
static l2_node_state_t l2_node_state[BDK_NUMA_MAX_NODES];
/**
* Perform one time initialization of L2 for improved
* performance. This can be called after L2 is in use.
*
* @return Zero on success, negative on failure.
*/
int bdk_l2c_initialize(bdk_node_t node)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
{
/* Tell L2 to give the IOB statically higher priority compared to the
cores. This avoids conditions where IO blocks might be starved under
very high L2 loads */
BDK_CSR_MODIFY(c, node, BDK_L2C_CTL,
c.s.rsp_arb_mode = 1;
c.s.xmc_arb_mode = 0);
}
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X) && !bdk_is_platform(BDK_PLATFORM_ASIM))
{
/* Errata: (L2C-22279) RCAS/RSTC which hits S/S can use wrong compare data */
BDK_CSR_MODIFY(c, node, BDK_L2C_CTL,
c.s.dissblkdty = 1);
/* Errata: (L2C-22249) Broadcast invals can cause starvation on the INV bus */
for (int i = 0; i < 4; i++)
BDK_CSR_MODIFY(c, node, BDK_L2C_CBCX_SCRATCH(i),
c.s.invdly = 1);
}
// FIXME: Disable partial writes on pass 2 until it is debugged
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS2_X) && !bdk_is_platform(BDK_PLATFORM_ASIM))
{
BDK_CSR_MODIFY(c, node, BDK_L2C_CTL,
c.s.dissblkdty = 1);
}
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX) && bdk_is_platform(BDK_PLATFORM_EMULATOR))
{
/* The emulator requires L2C_CTL[DISSBLKDTY] to be set */
BDK_CSR_MODIFY(c, node, BDK_L2C_CTL,
c.s.dissblkdty = 1);
}
return 0;
}
int bdk_l2c_get_core_way_partition(bdk_node_t node, int core)
{
return (BDK_CSR_READ(node, BDK_L2C_WPAR_PPX(core)) & 0xffff);
}
int bdk_l2c_set_core_way_partition(bdk_node_t node, int core, uint32_t mask)
{
uint32_t valid_mask = (1 << bdk_l2c_get_num_assoc(node)) - 1;
mask &= valid_mask;
BDK_CSR_WRITE(node, BDK_L2C_WPAR_PPX(core), mask);
return 0;
}
int bdk_l2c_set_hw_way_partition(bdk_node_t node, uint32_t mask)
{
uint32_t valid_mask = (1 << bdk_l2c_get_num_assoc(node)) - 1;
mask &= valid_mask;
BDK_CSR_WRITE(node, BDK_L2C_WPAR_IOBX(0), mask);
return 0;
}
int bdk_l2c_get_hw_way_partition(bdk_node_t node)
{
return (BDK_CSR_READ(node, BDK_L2C_WPAR_IOBX(0)) & 0xffff);
}
int bdk_l2c_lock_mem_region(bdk_node_t node, uint64_t start, uint64_t len)
{
/* Round start/end to cache line boundaries */
len += start & BDK_CACHE_LINE_MASK;
start &= ~BDK_CACHE_LINE_MASK;
len = (len + BDK_CACHE_LINE_MASK) & ~BDK_CACHE_LINE_MASK;
void *ptr = (start) ? bdk_phys_to_ptr(start) : NULL;
while (len)
{
BDK_CACHE_LCK_L2(ptr);
ptr += BDK_CACHE_LINE_SIZE;
len -= BDK_CACHE_LINE_SIZE;
}
l2_node_state[node].is_locked = true;
return 0;
}
void bdk_l2c_flush(bdk_node_t node)
{
/* The number of ways can be reduced with fuses, but the equations below
assume the max number of ways */
const int MAX_WAYS = 16;
int num_sets = bdk_l2c_get_num_sets(node);
int num_ways = bdk_l2c_get_num_assoc(node);
int is_rtg = 1; /* Clear remote tags */
for (int l2_way = 0; l2_way < num_ways; l2_way++)
{
for (int l2_set = 0; l2_set < num_sets; l2_set++)
{
uint64_t encoded = 128 * (l2_set + num_sets * (l2_way + (is_rtg * MAX_WAYS)));
BDK_CACHE_WBI_L2_INDEXED(encoded);
}
}
is_rtg = 0; /* Clear local tags */
for (int l2_way = 0; l2_way < num_ways; l2_way++)
{
for (int l2_set = 0; l2_set < num_sets; l2_set++)
{
uint64_t encoded = 128 * (l2_set + num_sets * (l2_way + (is_rtg * MAX_WAYS)));
BDK_CACHE_WBI_L2_INDEXED(encoded);
}
}
l2_node_state[node].is_locked = false;
}
int bdk_l2c_unlock_mem_region(bdk_node_t node, uint64_t start, uint64_t len)
{
/* Round start/end to cache line boundaries */
len += start & BDK_CACHE_LINE_MASK;
start &= ~BDK_CACHE_LINE_MASK;
len = (len + BDK_CACHE_LINE_MASK) & ~BDK_CACHE_LINE_MASK;
void *ptr = (start) ? bdk_phys_to_ptr(start) : NULL;
while (len > 0)
{
/* Must use invalidate version to release lock */
BDK_CACHE_WBI_L2(ptr);
ptr += BDK_CACHE_LINE_SIZE;
len -= BDK_CACHE_LINE_SIZE;
}
l2_node_state[node].is_locked = false;
return 0;
}
int bdk_l2c_get_cache_size_bytes(bdk_node_t node)
{
return bdk_l2c_get_num_sets(node) * bdk_l2c_get_num_assoc(node) * BDK_CACHE_LINE_SIZE;
}
/* Return the number of sets in the L2 Cache */
int bdk_l2c_get_num_sets(bdk_node_t node)
{
if (bdk_unlikely(l2_node_state[node].sets == 0))
{
/* Select the L2 cache */
bdk_ap_csselr_el1_t csselr_el1;
csselr_el1.u = 0;
csselr_el1.s.ind = 0;
csselr_el1.s.level = CAVIUM_IS_MODEL(CAVIUM_CN8XXX) ? 1 : 2;
BDK_MSR(CSSELR_EL1, csselr_el1.u);
/* Read its size */
bdk_ap_ccsidr_el1_t ccsidr_el1;
BDK_MRS(CCSIDR_EL1, ccsidr_el1.u);
/* Store it for use later */
l2_node_state[node].sets = ccsidr_el1.s.numsets + 1;
l2_node_state[node].ways = ccsidr_el1.s.associativity + 1;
/* Early chips didn't update the number of ways based on fusing */
if ((l2_node_state[node].ways == 16) && CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
{
/* The l2 can be reduced in 25% increments */
BDK_CSR_INIT(mio_fus_dat3, node, BDK_MIO_FUS_DAT3);
switch (mio_fus_dat3.s.l2c_crip)
{
case 3: /* 1/4 size */
l2_node_state[node].ways *= 1;
break;
case 2: /* 1/2 size */
l2_node_state[node].ways *= 2;
break;
case 1: /* 3/4 size */
l2_node_state[node].ways *= 3;
break;
default: /* Full size */
l2_node_state[node].ways *= 4;
break;
}
l2_node_state[node].ways /= 4;
}
}
return l2_node_state[node].sets;
}
/* Return the number of associations in the L2 Cache */
int bdk_l2c_get_num_assoc(bdk_node_t node)
{
/* Get the number of sets if the global sets/ways is not setup */
if (bdk_unlikely(l2_node_state[node].ways == 0))
bdk_l2c_get_num_sets(node);
return l2_node_state[node].ways;
}
/**
* Return true if the BDK has locked itself in L2
*
* @return
*/
int bdk_l2c_is_locked(bdk_node_t node)
{
/* Determining the lock state of L2 requires reading exact tags from L2
which varies per chip. Rather than deal with that complexity, we just
keep a flag around saying if the L2 lock functions have been called.
This works for the BDK as its use of locking is very simple */
return l2_node_state[node].is_locked;
}

View File

@ -0,0 +1,318 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-mio_tws.h"
#define RECOVERY_UDELAY 5
#define RECOVERY_CLK_CNT 9
#define ARBLOST_UDELAY 5000 /* 5ms */
/* This code is an optional part of the BDK. It is only linked in
if BDK_REQUIRE() needs it */
BDK_REQUIRE_DEFINE(TWSI);
/**
* Initialize the TWSI blocks. This just sets the clock rate.
* Many times stuff will work without calling this, but some
* TWSI devices will fail. This is normally called automatically
* in bdk-init-main.c.
*
* @return Zero on success, negative on failure
*/
int bdk_twsix_initialize(bdk_node_t node)
{
const int TWSI_BUS_FREQ = 100000; /* 100 KHz */
const int TWSI_THP = 24; /* TCLK half period (default 24) */
const int io_clock_hz = bdk_clock_get_rate(node, BDK_CLOCK_SCLK);
int N_divider;
int M_divider;
/* Set the TWSI clock to a conservative TWSI_BUS_FREQ. Compute the
clocks M divider based on the SCLK.
TWSI freq = (core freq) / (20 x (M+1) x (thp+1) x 2^N)
M = ((core freq) / (20 x (TWSI freq) x (thp+1) x 2^N)) - 1 */
for (N_divider = 0; N_divider < 8; N_divider++)
{
M_divider = (io_clock_hz / (20 * TWSI_BUS_FREQ * (TWSI_THP + 1) * (1 << N_divider))) - 1;
if (M_divider < 16)
break;
}
BDK_CSR_DEFINE(sw_twsi, BDK_MIO_TWSX_SW_TWSI(bus));
sw_twsi.u = 0;
sw_twsi.s.v = 1; /* Clear valid bit */
sw_twsi.s.op = 0x6; /* See EOP field */
sw_twsi.s.r = 0; /* Select CLKCTL when R = 0 */
sw_twsi.s.eop_ia = 3; /* R=0 selects CLKCTL, R=1 selects STAT */
sw_twsi.s.data = ((M_divider & 0xf) << 3) | ((N_divider & 0x7) << 0);
int num_busses = 2;
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
num_busses = 6;
for (int bus = 0; bus < num_busses; bus++)
{
/* Only init non-slave ports */
BDK_CSR_INIT(state, node, BDK_MIO_TWSX_SW_TWSI(bus));
if (!state.s.slonly)
BDK_CSR_WRITE(node, BDK_MIO_TWSX_SW_TWSI(bus), sw_twsi.u);
}
return 0;
}
/**
* Do a twsi bus recovery in the case when the last transaction
* on the bus has been left unfinished.
*
* @param twsi_id which TWSI bus to use
*/
static void bdk_twsix_recover_bus(bdk_node_t node, int twsi_id)
{
/* read TWSX_INT */
BDK_CSR_INIT(twsx_int, node, BDK_MIO_TWSX_INT(twsi_id));
for (int i = 0; i < RECOVERY_CLK_CNT * 2; i++)
{
if (!twsx_int.s.scl_ovr)
{
/* SCL shouldn't be low here */
if (!twsx_int.s.scl)
{
bdk_error("N%d.TWSI%d: SCL is stuck low\n", node, twsi_id);
return;
}
/* Break if SDA is high */
if (twsx_int.s.sda)
break;
}
twsx_int.s.scl_ovr = !twsx_int.s.scl_ovr;
BDK_CSR_WRITE(node, BDK_MIO_TWSX_INT(twsi_id), twsx_int.u);
bdk_wait_usec(RECOVERY_UDELAY);
}
/*
* Generate STOP condition using the register overrides
* in order to move the higher level controller out of
* the bad state. This is a workaround for the TWSI hardware.
*/
twsx_int.s.scl_ovr = 1;
twsx_int.s.sda_ovr = 1;
BDK_CSR_WRITE(node, BDK_MIO_TWSX_INT(twsi_id), twsx_int.u);
bdk_wait_usec(RECOVERY_UDELAY);
twsx_int.s.scl_ovr = 0;
BDK_CSR_WRITE(node, BDK_MIO_TWSX_INT(twsi_id), twsx_int.u);
bdk_wait_usec(RECOVERY_UDELAY);
twsx_int.s.sda_ovr = 0;
BDK_CSR_WRITE(node, BDK_MIO_TWSX_INT(twsi_id), twsx_int.u);
}
/**
* Do a twsi read from a 7 bit device address using an (optional)
* internal address. Up to 4 bytes can be read at a time.
*
* @param twsi_id which TWSI bus to use
* @param dev_addr Device address (7 bit)
* @param internal_addr
* Internal address. Can be 0, 1 or 2 bytes in width
* @param num_bytes Number of data bytes to read (1-4)
* @param ia_width_bytes
* Internal address size in bytes (0, 1, or 2)
*
* @return Read data, or -1 on failure
*/
int64_t bdk_twsix_read_ia(bdk_node_t node, int twsi_id, uint8_t dev_addr, uint16_t internal_addr, int num_bytes, int ia_width_bytes)
{
bdk_mio_twsx_sw_twsi_t sw_twsi_val;
bdk_mio_twsx_sw_twsi_ext_t twsi_ext;
int retry_limit = 5;
if (num_bytes < 1 || num_bytes > 4 || ia_width_bytes < 0 || ia_width_bytes > 2)
return -1;
retry:
twsi_ext.u = 0;
sw_twsi_val.u = 0;
sw_twsi_val.s.v = 1;
sw_twsi_val.s.r = 1;
sw_twsi_val.s.sovr = 1;
sw_twsi_val.s.size = num_bytes - 1;
sw_twsi_val.s.addr = dev_addr;
if (ia_width_bytes > 0)
{
sw_twsi_val.s.op = 1;
sw_twsi_val.s.ia = (internal_addr >> 3) & 0x1f;
sw_twsi_val.s.eop_ia = internal_addr & 0x7;
if (ia_width_bytes == 2)
{
sw_twsi_val.s.eia = 1;
twsi_ext.s.ia = internal_addr >> 8;
BDK_CSR_WRITE(node, BDK_MIO_TWSX_SW_TWSI_EXT(twsi_id), twsi_ext.u);
}
}
BDK_CSR_WRITE(node, BDK_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u);
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_MIO_TWSX_SW_TWSI(twsi_id), v, ==, 0, 10000))
{
bdk_warn("N%d.TWSI%d: Timeout waiting for read to complete...start recovering process\n",
node, twsi_id);
/* perform bus recovery */
bdk_twsix_recover_bus(node, twsi_id);
if (retry_limit-- > 0)
goto retry;
bdk_error("N%d.TWSI%d: Timeout waiting for operation to complete\n", node, twsi_id);
return -1;
}
sw_twsi_val.u = BDK_CSR_READ(node, BDK_MIO_TWSX_SW_TWSI(twsi_id));
if (!sw_twsi_val.s.r)
{
/* Check the reason for the failure. We may need to retry to handle multi-master
** configurations.
** Lost arbitration : 0x38, 0x68, 0xB0, 0x78
** Core busy as slave: 0x80, 0x88, 0xA0, 0xA8, 0xB8, 0xC0, 0xC8
*/
if (sw_twsi_val.s.data == 0x38
|| sw_twsi_val.s.data == 0x68
|| sw_twsi_val.s.data == 0xB0
|| sw_twsi_val.s.data == 0x78
|| sw_twsi_val.s.data == 0x80
|| sw_twsi_val.s.data == 0x88
|| sw_twsi_val.s.data == 0xA0
|| sw_twsi_val.s.data == 0xA8
|| sw_twsi_val.s.data == 0xB8
|| sw_twsi_val.s.data == 0xC8)
{
/*
* One of the arbitration lost conditions is recognized.
* The TWSI hardware has switched to the slave mode and
* expects the STOP condition on the bus.
* Make a delay before next retry.
*/
bdk_wait_usec(ARBLOST_UDELAY);
if (retry_limit-- > 0)
goto retry;
}
/* For all other errors, return an error code */
return -1;
}
return (sw_twsi_val.s.data & (0xFFFFFFFF >> (32 - num_bytes*8)));
}
/**
* Write 1-8 bytes to a TWSI device using an internal address.
*
* @param twsi_id which TWSI interface to use
* @param dev_addr TWSI device address (7 bit only)
* @param internal_addr
* TWSI internal address (0, 8, or 16 bits)
* @param num_bytes Number of bytes to write (1-8)
* @param ia_width_bytes
* internal address width, in bytes (0, 1, 2)
* @param data Data to write. Data is written MSB first on the twsi bus, and
* only the lower num_bytes bytes of the argument are valid. (If
* a 2 byte write is done, only the low 2 bytes of the argument is
* used.
*
* @return Zero on success, -1 on error
*/
int bdk_twsix_write_ia(bdk_node_t node, int twsi_id, uint8_t dev_addr, uint16_t internal_addr, int num_bytes, int ia_width_bytes, uint64_t data)
{
bdk_mio_twsx_sw_twsi_t sw_twsi_val;
bdk_mio_twsx_sw_twsi_ext_t twsi_ext;
int retry_limit = 5;
int to;
if (num_bytes < 1 || num_bytes > 8 || ia_width_bytes < 0 || ia_width_bytes > 2)
return -1;
retry:
twsi_ext.u = 0;
sw_twsi_val.u = 0;
sw_twsi_val.s.v = 1;
sw_twsi_val.s.sovr = 1;
sw_twsi_val.s.size = num_bytes - 1;
sw_twsi_val.s.addr = dev_addr;
sw_twsi_val.s.data = 0xFFFFFFFF & data;
if (ia_width_bytes > 0)
{
sw_twsi_val.s.op = 1;
sw_twsi_val.s.ia = (internal_addr >> 3) & 0x1f;
sw_twsi_val.s.eop_ia = internal_addr & 0x7;
}
if (ia_width_bytes == 2)
{
sw_twsi_val.s.eia = 1;
twsi_ext.s.ia = internal_addr >> 8;
}
if (num_bytes > 4)
twsi_ext.s.data = data >> 32;
BDK_CSR_WRITE(node, BDK_MIO_TWSX_SW_TWSI_EXT(twsi_id), twsi_ext.u);
BDK_CSR_WRITE(node, BDK_MIO_TWSX_SW_TWSI(twsi_id), sw_twsi_val.u);
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_MIO_TWSX_SW_TWSI(twsi_id), v, ==, 0, 10000))
{
bdk_warn("N%d.TWSI%d: Timeout waiting for write to complete...start recovering process\n",
node, twsi_id);
/* perform bus recovery */
bdk_twsix_recover_bus(node, twsi_id);
if (retry_limit-- > 0)
goto retry;
// After retry but still not success, report error and return
bdk_error("N%d.TWSI%d: Timeout waiting for operation to complete\n", node, twsi_id);
return -1;
}
/* Poll until reads succeed, or polling times out */
to = 100;
while (to-- > 0)
{
if (bdk_twsix_read_ia(node, twsi_id, dev_addr, 0, 1, 0) >= 0)
break;
}
if (to <= 0)
return -1;
return 0;
}

View File

@ -0,0 +1,561 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include <stdio.h>
#include <unistd.h>
#include "libbdk-arch/bdk-csrs-ap.h"
#include "libbdk-arch/bdk-csrs-l2c.h"
#include "libbdk-arch/bdk-csrs-l2c_tad.h"
#include "libbdk-arch/bdk-csrs-mio_boot.h"
#include "libbdk-arch/bdk-csrs-rom.h"
#include "libbdk-arch/bdk-csrs-uaa.h"
uint64_t __bdk_init_reg_x0; /* The contents of X0 when this image started */
uint64_t __bdk_init_reg_x1; /* The contents of X1 when this image started */
uint64_t __bdk_init_reg_pc; /* The contents of PC when this image started */
static int64_t __bdk_alive_coremask[BDK_NUMA_MAX_NODES];
/**
* Set the baud rate on a UART
*
* @param uart uart to set
* @param baudrate Baud rate (9600, 19200, 115200, etc)
* @param use_flow_control
* Non zero if hardware flow control should be enabled
*/
void bdk_set_baudrate(bdk_node_t node, int uart, int baudrate, int use_flow_control)
{
/* 1.2.1 Initialization Sequence (Power-On/Hard/Cold Reset) */
/* 1. Wait for IOI reset (srst_n) to deassert. */
/* 2. Assert all resets:
a. UAA reset: UCTL_CTL[UAA_RST] = 1
b. UCTL reset: UCTL_CTL[UCTL_RST] = 1 */
BDK_CSR_MODIFY(c, node, BDK_UAAX_UCTL_CTL(uart),
c.s.uaa_rst = 1;
c.s.uctl_rst = 1);
/* 3. Configure the HCLK:
a. Reset the clock dividers: UCTL_CTL[H_CLKDIV_RST] = 1.
b. Select the HCLK frequency
i. UCTL_CTL[H_CLKDIV] = desired value,
ii. UCTL_CTL[H_CLKDIV_EN] = 1 to enable the HCLK.
iii. Readback UCTL_CTL to ensure the values take effect.
c. Deassert the HCLK clock divider reset: UCTL_CTL[H_CLKDIV_RST] = 0. */
BDK_CSR_MODIFY(c, node, BDK_UAAX_UCTL_CTL(uart),
c.s.h_clkdiv_sel = 3; /* Run at SCLK / 6, matches emulator */
c.s.h_clk_byp_sel = 0;
c.s.h_clk_en = 1);
BDK_CSR_MODIFY(c, node, BDK_UAAX_UCTL_CTL(uart),
c.s.h_clkdiv_rst = 0);
/* 4. Wait 20 HCLK cycles from step 3 for HCLK to start and async fifo
to properly reset. */
bdk_wait(200); /* Overkill */
/* 5. Deassert UCTL and UAHC resets:
a. UCTL_CTL[UCTL_RST] = 0
b. Wait 10 HCLK cycles.
c. UCTL_CTL[UAHC_RST] = 0
d. You will have to wait 10 HCLK cycles before accessing any
HCLK-only registers. */
BDK_CSR_MODIFY(c, node, BDK_UAAX_UCTL_CTL(uart), c.s.uctl_rst = 0);
bdk_wait(100); /* Overkill */
BDK_CSR_MODIFY(c, node, BDK_UAAX_UCTL_CTL(uart), c.s.uaa_rst = 0);
bdk_wait(100); /* Overkill */
/* 6. Enable conditional SCLK of UCTL by writing UCTL_CTL[CSCLK_EN] = 1. */
BDK_CSR_MODIFY(c, node, BDK_UAAX_UCTL_CTL(uart), c.s.csclk_en = 1);
/* 7. Initialize the integer and fractional baud rate divider registers
UARTIBRD and UARTFBRD as follows:
a. Baud Rate Divisor = UARTCLK/(16xBaud Rate) = BRDI + BRDF
b. The fractional register BRDF, m is calculated as integer(BRDF x 64 + 0.5)
Example calculation:
If the required baud rate is 230400 and hclk = 4MHz then:
Baud Rate Divisor = (4x10^6)/(16x230400) = 1.085
This means BRDI = 1 and BRDF = 0.085.
Therefore, fractional part, BRDF = integer((0.085x64)+0.5) = 5
Generated baud rate divider = 1+5/64 = 1.078 */
uint64_t divisor_x_64 = bdk_clock_get_rate(node, BDK_CLOCK_SCLK) / (baudrate * 16 * 6 / 64);
if (bdk_is_platform(BDK_PLATFORM_EMULATOR))
{
/* The hardware emulator currently fixes the uart at a fixed rate */
divisor_x_64 = 64;
}
BDK_CSR_MODIFY(c, node, BDK_UAAX_IBRD(uart),
c.s.baud_divint = divisor_x_64 >> 6);
BDK_CSR_MODIFY(c, node, BDK_UAAX_FBRD(uart),
c.s.baud_divfrac = divisor_x_64 & 0x3f);
/* 8. Program the line control register UAA(0..1)_LCR_H and the control
register UAA(0..1)_CR */
BDK_CSR_MODIFY(c, node, BDK_UAAX_LCR_H(uart),
c.s.sps = 0; /* No parity */
c.s.wlen = 3; /* 8 bits */
c.s.fen = 1; /* FIFOs enabled */
c.s.stp2 = 0; /* Use one stop bit, not two */
c.s.eps = 0; /* No parity */
c.s.pen = 0; /* No parity */
c.s.brk = 0); /* Don't send a break */
BDK_CSR_MODIFY(c, node, BDK_UAAX_CR(uart),
c.s.ctsen = use_flow_control;
c.s.rtsen = use_flow_control;
c.s.out1 = 1; /* Drive data carrier detect */
c.s.rts = 0; /* Don't override RTS */
c.s.dtr = 0; /* Don't override DTR */
c.s.rxe = 1; /* Enable receive */
c.s.txe = 1; /* Enable transmit */
c.s.lbe = 0; /* Disable loopback */
c.s.uarten = 1); /* Enable uart */
}
/**
* First C code run when a BDK application starts. It is called by bdk-start.S.
*
* @param image_crc A CRC32 of the entire image before any variables might have been updated by C.
* This should match the CRC32 in the image header.
* @param reg_x0 The contents of the X0 register when the image started. In images loaded after
* the boot stub, this contains a "environment" string containing "BOARD=xxx". The
* use of this is deprecated as it has been replaced with a expandable device tree
* in X1.
* @param reg_x1 The contents of the X1 register when the image started. For all images after the
* boot stub, this contains a physical address of a device tree in memory. This
* should be used by all images to identify and configure the board we are running
* on.
* @param reg_pc This is the PC the code started at before relocation. This is useful for
* the first stage to determine if it from trusted or non-trusted code.
*/
void __bdk_init(uint32_t image_crc, uint64_t reg_x0, uint64_t reg_x1, uint64_t reg_pc) __attribute((noreturn));
void __bdk_init(uint32_t image_crc, uint64_t reg_x0, uint64_t reg_x1, uint64_t reg_pc)
{
extern void __bdk_exception_current_el_sync_sp0();
BDK_MSR(VBAR_EL3, __bdk_exception_current_el_sync_sp0);
BDK_MSR(VBAR_EL2, __bdk_exception_current_el_sync_sp0);
BDK_MSR(VBAR_EL1, __bdk_exception_current_el_sync_sp0);
/* Use Cavium specific function to change memory to normal instead of
device attributes. DCVA47=1 makes unmapped addresses behave as
non-shared memory (not inner or outer shared in ARM speak) */
bdk_ap_cvmmemctl0_el1_t cvmmemctl0_el1;
BDK_MRS(s3_0_c11_c0_4, cvmmemctl0_el1.u);
cvmmemctl0_el1.s.dcva47 = 1;
BDK_MSR(s3_0_c11_c0_4, cvmmemctl0_el1.u);
/* Setup running with no mmu */
bdk_ap_sctlr_el3_t sctlr_el3;
BDK_MRS(SCTLR_EL3, sctlr_el3.u);
sctlr_el3.s.wxn = 0; /* No write perm changes */
sctlr_el3.s.i = 1; /* Enable Icache */
sctlr_el3.s.sa = 1; /* Enable stack alignment checking */
sctlr_el3.s.cc = 1; /* Enable Dcache */
sctlr_el3.s.aa = 0; /* Allow unaligned accesses */
sctlr_el3.s.m = 0; /* Disable MMU */
BDK_MSR(SCTLR_EL3, sctlr_el3.u);
bdk_node_t node = bdk_numa_local();
bdk_numa_set_exists(node);
/* Default color, Reset scroll region and goto bottom */
static const char BANNER_1[] = "\33[0m\33[1;r\33[100;1H"
"\n\n\nCavium SOC\n";
static const char BANNER_2[] = "Locking L2 cache\n";
static const char BANNER_CRC_RIGHT[] = "PASS: CRC32 verification\n";
static const char BANNER_CRC_WRONG[] = "FAIL: CRC32 verification\n";
static const char BANNER_3[] = "Transferring to thread scheduler\n";
BDK_MSR(TPIDR_EL3, 0);
if (bdk_is_boot_core())
{
/* Initialize the platform */
__bdk_platform_init();
if (!bdk_is_platform(BDK_PLATFORM_EMULATOR) && CAVIUM_IS_MODEL(CAVIUM_CN88XX))
{
BDK_CSR_INIT(l2c_oci_ctl, node, BDK_L2C_OCI_CTL);
if (l2c_oci_ctl.s.iofrcl)
{
/* CCPI isn't being used, so don't reset if the links change */
BDK_CSR_WRITE(node, BDK_RST_OCX, 0);
BDK_CSR_READ(node, BDK_RST_OCX);
/* Force CCPI links down so they aren't trying to run while
we're configuring the QLMs */
__bdk_init_ccpi_early(1);
}
}
/* AP-23192: The DAP in pass 1.0 has an issue where its state isn't cleared for
cores in reset. Put the DAPs in reset as their associated cores are
also in reset */
if (!bdk_is_platform(BDK_PLATFORM_EMULATOR) && CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_0))
BDK_CSR_WRITE(node, BDK_RST_DBG_RESET, BDK_CSR_READ(node, BDK_RST_PP_RESET));
/* Enable the timer */
BDK_MSR(CNTFRQ_EL0, BDK_GTI_RATE); /* Needed for Asim */
bdk_clock_setup(node);
/* Only setup the uarts if they haven't been already setup */
BDK_CSR_INIT(uctl_ctl0, node, BDK_UAAX_UCTL_CTL(0));
if (!uctl_ctl0.s.h_clk_en)
bdk_set_baudrate(node, 0, BDK_UART_BAUDRATE, 0);
BDK_CSR_INIT(uctl_ctl1, node, BDK_UAAX_UCTL_CTL(1));
if (!uctl_ctl1.s.h_clk_en)
bdk_set_baudrate(node, 1, BDK_UART_BAUDRATE, 0);
__bdk_fs_init_early();
if (BDK_SHOW_BOOT_BANNERS)
write(1, BANNER_1, sizeof(BANNER_1)-1);
/* Only lock L2 if DDR3 isn't initialized */
if (bdk_is_platform(BDK_PLATFORM_HW) && !__bdk_is_dram_enabled(node))
{
if (BDK_TRACE_ENABLE_INIT)
write(1, BANNER_2, sizeof(BANNER_2)-1);
/* Lock the entire cache for chips with less than 4MB of
L2/LLC. Larger chips can use the 1/4 of the cache to
speed up DRAM init and testing */
int lock_size = bdk_l2c_get_cache_size_bytes(node);
if (lock_size >= (4 << 20))
lock_size = lock_size * 3 / 4;
bdk_l2c_lock_mem_region(node, bdk_numa_get_address(node, 0), lock_size);
/* The locked region isn't considered dirty by L2. Do read
read/write of each cache line to force each to be dirty. This
is needed across the whole line to make sure the L2 dirty bits
are all up to date */
volatile uint64_t *ptr = bdk_phys_to_ptr(bdk_numa_get_address(node, 8));
/* The above pointer got address 8 to avoid NULL pointer checking
in bdk_phys_to_ptr(). Correct it here */
ptr--;
uint64_t *end = bdk_phys_to_ptr(bdk_numa_get_address(node, bdk_l2c_get_cache_size_bytes(node)));
while (ptr < end)
{
*ptr = *ptr;
ptr++;
}
/* The above locking will cause L2 to load zeros without DRAM setup.
This will cause L2C_TADX_INT[rddislmc], which we suppress below */
BDK_CSR_DEFINE(l2c_tadx_int, BDK_L2C_TADX_INT_W1C(0));
l2c_tadx_int.u = 0;
l2c_tadx_int.s.wrdislmc = 1;
l2c_tadx_int.s.rddislmc = 1;
l2c_tadx_int.s.rdnxm = 1;
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(0), l2c_tadx_int.u);
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX) || CAVIUM_IS_MODEL(CAVIUM_CN83XX))
{
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(1), l2c_tadx_int.u);
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(2), l2c_tadx_int.u);
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(3), l2c_tadx_int.u);
}
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
{
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(4), l2c_tadx_int.u);
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(5), l2c_tadx_int.u);
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(6), l2c_tadx_int.u);
BDK_CSR_WRITE(node, BDK_L2C_TADX_INT_W1C(7), l2c_tadx_int.u);
}
}
/* Validate the image CRC */
extern void _start();
uint32_t *ptr_crc32 = (uint32_t *)(_start + 16);
uint32_t correct_crc = bdk_le32_to_cpu(*ptr_crc32);
if (correct_crc == image_crc)
write(1, BANNER_CRC_RIGHT, sizeof(BANNER_CRC_RIGHT) - 1);
else
write(1, BANNER_CRC_WRONG, sizeof(BANNER_CRC_WRONG) - 1);
if (BDK_TRACE_ENABLE_INIT)
write(1, BANNER_3, sizeof(BANNER_3)-1);
bdk_thread_initialize();
}
/* Enable the core timer */
BDK_MSR(CNTFRQ_EL0, BDK_GTI_RATE); /* Needed for Asim */
bdk_ap_cntps_ctl_el1_t cntps_ctl_el1;
cntps_ctl_el1.u = 0;
cntps_ctl_el1.s.imask = 1;
cntps_ctl_el1.s.enable = 1;
BDK_MSR(CNTPS_CTL_EL1, cntps_ctl_el1.u);
/* Setup an exception stack in case we crash */
int EX_STACK_SIZE = 16384;
void *exception_stack = malloc(EX_STACK_SIZE);
extern void __bdk_init_exception_stack(void *ptr);
__bdk_init_exception_stack(exception_stack + EX_STACK_SIZE);
bdk_atomic_add64(&__bdk_alive_coremask[node], bdk_core_to_mask());
/* Record our input registers for use later */
__bdk_init_reg_x0 = reg_x0;
__bdk_init_reg_x1 = reg_x1;
__bdk_init_reg_pc = reg_pc;
bdk_thread_first(__bdk_init_main, 0, NULL, 0);
}
/**
* Call this function to take secondary cores out of reset and have
* them start running threads
*
* @param node Node to use in a Numa setup. Can be an exact ID or a special
* value.
* @param coremask Cores to start. Zero is a shortcut for all.
*
* @return Zero on success, negative on failure.
*/
int bdk_init_cores(bdk_node_t node, uint64_t coremask)
{
extern void __bdk_start_cores();
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
{
/* Write the address of the main entry point */
BDK_TRACE(INIT, "N%d: Setting address for boot jump\n", node);
BDK_CSR_WRITE(node, BDK_MIO_BOOT_AP_JUMP, (uint64_t)__bdk_start_cores);
}
else
{
BDK_TRACE(INIT, "N%d: Setting ROM boot code\n", node);
/* Assembly for ROM memory:
d508711f ic ialluis
d503201f nop
58000040 ldr x0, 328 <branch_addr>
d61f0000 br x0
branch_addr:
Memory is little endain, so 64 bit constants have the first
instruction in the low word */
BDK_CSR_WRITE(node, BDK_ROM_MEMX(0), 0xd503201fd508711f);
BDK_CSR_WRITE(node, BDK_ROM_MEMX(1), 0xd61f000058000040);
BDK_CSR_WRITE(node, BDK_ROM_MEMX(2), (uint64_t)__bdk_start_cores);
}
/* Choose all cores by default */
if (coremask == 0)
coremask = -1;
/* Limit to the cores that aren't already running */
coremask &= ~__bdk_alive_coremask[node];
/* Limit to the cores that are specified in configuration menu */
uint64_t config_coremask = bdk_config_get_int(BDK_CONFIG_COREMASK);
if (config_coremask)
coremask &= config_coremask;
/* Limit to the cores that exist */
coremask &= (1ull<<bdk_get_num_cores(node)) - 1;
uint64_t reset = BDK_CSR_READ(node, BDK_RST_PP_RESET);
BDK_TRACE(INIT, "N%d: Cores currently in reset: 0x%lx\n", node, reset);
uint64_t need_reset_off = reset & coremask;
if (need_reset_off)
{
BDK_TRACE(INIT, "N%d: Taking cores out of reset (0x%lx)\n", node, need_reset_off);
BDK_CSR_WRITE(node, BDK_RST_PP_RESET, reset & ~need_reset_off);
/* Wait for cores to finish coming out of reset */
bdk_wait_usec(1);
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_RST_PP_PENDING, pend, ==, 0, 100000))
bdk_error("Timeout wating for reset pending to clear");
/* AP-23192: The DAP in pass 1.0 has an issue where its state isn't cleared for
cores in reset. Put the DAPs in reset as their associated cores are
also in reset */
if (!bdk_is_platform(BDK_PLATFORM_EMULATOR) && CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_0))
BDK_CSR_WRITE(node, BDK_RST_DBG_RESET, reset & ~need_reset_off);
}
BDK_TRACE(INIT, "N%d: Wait up to 1s for the cores to boot\n", node);
uint64_t timeout = bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) + bdk_clock_get_count(BDK_CLOCK_TIME);
while ((bdk_clock_get_count(BDK_CLOCK_TIME) < timeout) && ((bdk_atomic_get64(&__bdk_alive_coremask[node]) & coremask) != coremask))
{
/* Tight spin, no thread schedules */
}
if ((bdk_atomic_get64(&__bdk_alive_coremask[node]) & coremask) != coremask)
{
bdk_error("Node %d: Some cores failed to start. Alive mask 0x%lx, requested 0x%lx\n",
node, __bdk_alive_coremask[node], coremask);
return -1;
}
BDK_TRACE(INIT, "N%d: All cores booted\n", node);
return 0;
}
/**
* Put cores back in reset and power them down
*
* @param node Node to update
* @param coremask Each bit will be a core put in reset. Cores already in reset are unaffected
*
* @return Zero on success, negative on failure
*/
int bdk_reset_cores(bdk_node_t node, uint64_t coremask)
{
extern void __bdk_reset_thread(int arg1, void *arg2);
/* Limit to the cores that exist */
coremask &= (1ull<<bdk_get_num_cores(node)) - 1;
/* Update which cores are in reset */
uint64_t reset = BDK_CSR_READ(node, BDK_RST_PP_RESET);
BDK_TRACE(INIT, "N%d: Cores currently in reset: 0x%lx\n", node, reset);
coremask &= ~reset;
BDK_TRACE(INIT, "N%d: Cores to put into reset: 0x%lx\n", node, coremask);
/* Check if everything is already done */
if (coremask == 0)
return 0;
int num_cores = bdk_get_num_cores(node);
for (int core = 0; core < num_cores; core++)
{
uint64_t my_mask = 1ull << core;
/* Skip cores not in mask */
if ((coremask & my_mask) == 0)
continue;
BDK_TRACE(INIT, "N%d: Telling core %d to go into reset\n", node, core);
if (bdk_thread_create(node, my_mask, __bdk_reset_thread, 0, NULL, 0))
{
bdk_error("Failed to create thread for putting core in reset");
continue;
}
/* Clear the core in the alive mask */
bdk_atomic_fetch_and_bclr64_nosync((uint64_t*)&__bdk_alive_coremask[node], my_mask);
}
BDK_TRACE(INIT, "N%d: Waiting for all reset bits to be set\n", node);
uint64_t timeout = bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) + bdk_clock_get_count(BDK_CLOCK_TIME);
while (bdk_clock_get_count(BDK_CLOCK_TIME) < timeout)
{
reset = BDK_CSR_READ(node, BDK_RST_PP_RESET);
if ((reset & coremask) == coremask)
break;
bdk_thread_yield();
}
/* AP-23192: The DAP in pass 1.0 has an issue where its state isn't cleared for
cores in reset. Put the DAPs in reset as their associated cores are
also in reset */
if (!bdk_is_platform(BDK_PLATFORM_EMULATOR) && CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_0))
BDK_CSR_WRITE(node, BDK_RST_DBG_RESET, BDK_CSR_READ(node, BDK_RST_PP_RESET));
BDK_TRACE(INIT, "N%d: Cores now in reset: 0x%lx\n", node, reset);
return ((reset & coremask) == coremask) ? 0 : -1;
}
/**
* Call this function to take secondary nodes and cores out of
* reset and have them start running threads
*
* @param skip_cores If non-zero, cores are not started. Only the nodes are setup
* @param ccpi_sw_gbaud
* If CCPI is in software mode, this is the speed the CCPI QLMs will be configured
* for
*
* @return Zero on success, negative on failure.
*/
int bdk_init_nodes(int skip_cores, int ccpi_sw_gbaud)
{
int result = 0;
int do_oci_init = (__bdk_init_ccpi_links != NULL);
/* Only init OCI/CCPI on chips that support it */
do_oci_init &= CAVIUM_IS_MODEL(CAVIUM_CN88XX);
/* Check that the BDK config says multi-node is enabled */
if (bdk_config_get_int(BDK_CONFIG_MULTI_NODE) == 0)
do_oci_init = 0;
/* Simulation under Asim is a special case. Multi-node is simulaoted, but
not the details of the low level link */
if (do_oci_init && bdk_is_platform(BDK_PLATFORM_ASIM))
{
bdk_numa_set_exists(0);
bdk_numa_set_exists(1);
/* Skip the rest in simulation */
do_oci_init = 0;
}
if (do_oci_init)
{
if (__bdk_init_ccpi_links(ccpi_sw_gbaud) == 0)
{
/* Don't run node init if L2C_OCI_CTL shows that it has already
been done */
BDK_CSR_INIT(l2c_oci_ctl, bdk_numa_local(), BDK_L2C_OCI_CTL);
if (l2c_oci_ctl.s.enaoci == 0)
result |= __bdk_init_ccpi_multinode();
}
}
/* Start cores on all node unless it was disabled */
if (!skip_cores)
{
for (bdk_node_t node=0; node<BDK_NUMA_MAX_NODES; node++)
{
if (bdk_numa_exists(node))
result |= bdk_init_cores(node, 0);
}
}
return result;
}
/**
* Get the coremask of the cores actively running the BDK. Doesn't count cores
* that aren't booted.
*
* @param node Node to coremask the count for
*
* @return 64bit bitmask
*/
uint64_t bdk_get_running_coremask(bdk_node_t node)
{
return __bdk_alive_coremask[node];
}
/**
* Return the number of cores actively running in the BDK for the given node.
* Not an inline so it can be called from LUA.
*
* @param node Node to get the core count for
*
* @return Number of cores running. Doesn't count cores that aren't booted
*/
int bdk_get_num_running_cores(bdk_node_t node)
{
return __builtin_popcountl(bdk_get_running_coremask(node));
}

View File

@ -0,0 +1,384 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include <stdio.h>
#include <malloc.h>
#define STACK_CANARY 0x0BADBADBADBADBADull
typedef struct bdk_thread
{
struct bdk_thread *next;
uint64_t coremask;
uint64_t gpr[32]; /* Reg 31 is SP */
struct _reent lib_state;
uint64_t stack_canary;
uint64_t stack[0];
} bdk_thread_t;
typedef struct
{
bdk_thread_t* head;
bdk_thread_t* tail;
bdk_spinlock_t lock;
int64_t __padding1[16-3]; /* Stats in different cache line for speed */
int64_t stat_num_threads;
int64_t stat_no_schedulable_threads;
int64_t stat_next_calls;
int64_t stat_next_walks;
int64_t __padding2[16-4];
} bdk_thread_node_t;
static bdk_thread_node_t bdk_thread_node[BDK_NUMA_MAX_NODES];
extern void __bdk_thread_switch(bdk_thread_t* next_context, int delete_old);
/**
* Main thread body for all threads
*
* @param func User function to call
* @param arg0 First argument to the user function
* @param arg1 Second argument to the user function
*/
static void __bdk_thread_body(bdk_thread_func_t func, int arg0, void *arg1)
{
func(arg0, arg1);
bdk_thread_destroy();
}
/**
* Initialize the BDK thread library
*
* @return Zero on success, negative on failure
*/
int bdk_thread_initialize(void)
{
bdk_zero_memory(bdk_thread_node, sizeof(bdk_thread_node));
_REENT_INIT_PTR(&__bdk_thread_global_reent);
return 0;
}
static bdk_thread_t *__bdk_thread_next(void)
{
bdk_thread_node_t *t_node = &bdk_thread_node[bdk_numa_local()];
uint64_t coremask = bdk_core_to_mask();
bdk_atomic_add64_nosync(&t_node->stat_next_calls, 1);
bdk_thread_t *prev = NULL;
bdk_thread_t *next = t_node->head;
int walks = 0;
while (next && !(next->coremask & coremask))
{
prev = next;
next = next->next;
walks++;
}
if (walks)
bdk_atomic_add64_nosync(&t_node->stat_next_walks, walks);
if (next)
{
if (t_node->tail == next)
t_node->tail = prev;
if (prev)
prev->next = next->next;
else
t_node->head = next->next;
next->next = NULL;
}
else
bdk_atomic_add64_nosync(&t_node->stat_no_schedulable_threads, 1);
return next;
}
/**
* Yield the current thread and run a new one
*/
void bdk_thread_yield(void)
{
if (BDK_DBG_MAGIC_ENABLE && (bdk_numa_local() == bdk_numa_master()))
bdk_dbg_check_magic();
bdk_thread_node_t *t_node = &bdk_thread_node[bdk_numa_local()];
bdk_thread_t *current;
BDK_MRS_NV(TPIDR_EL3, current);
/* Yield can be called without a thread context during core init. The
cores call bdk_wait_usec(), which yields. In this case yielding
does nothing */
if (bdk_unlikely(!current))
return;
if (bdk_unlikely(current->stack_canary != STACK_CANARY))
bdk_fatal("bdk_thread_yield() detected a stack overflow\n");
if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
bdk_sso_process_work();
if (t_node->head == NULL)
return;
bdk_spinlock_lock(&t_node->lock);
/* Find the first thread that can run on this core */
bdk_thread_t *next = __bdk_thread_next();
/* If next is NULL then there are no other threads ready to run and we
will continue without doing anything */
if (next)
{
__bdk_thread_switch(next, 0);
/* Unlock performed in __bdk_thread_switch_complete */
return;
}
bdk_spinlock_unlock(&t_node->lock);
}
/**
* Create a new thread and return it. The thread will not be scheduled
* as it isn't put in the thread list.
*
* @param coremask Mask of cores the thread can run on. Each set bit is an allowed
* core. Zero and -1 are both shortcuts for all cores.
* @param func Function to run as a thread
* @param arg0 First argument to the function
* @param arg1 Second argument to the function
* @param stack_size Stack size for the new thread. Set to zero for the system default.
*
* @return Thread or NULL on failure
*/
static void *__bdk_thread_create(uint64_t coremask, bdk_thread_func_t func, int arg0, void *arg1, int stack_size)
{
bdk_thread_t *thread;
if (!stack_size)
stack_size = BDK_THREAD_DEFAULT_STACK_SIZE;
thread = memalign(16, sizeof(bdk_thread_t) + stack_size);
if (thread == NULL)
{
bdk_error("Unable to allocate memory for new thread\n");
return NULL;
}
memset(thread, 0, sizeof(bdk_thread_t) + stack_size);
if (coremask == 0)
coremask = -1;
thread->coremask = coremask;
thread->gpr[0] = (uint64_t)func; /* x0 = Argument 0 to __bdk_thread_body */
thread->gpr[1] = arg0; /* x1 = Argument 1 to __bdk_thread_body */
thread->gpr[2] = (uint64_t)arg1; /* x2 = Argument 2 to __bdk_thread_body */
thread->gpr[29] = 0; /* x29 = Frame pointer */
thread->gpr[30] = (uint64_t)__bdk_thread_body; /* x30 = Link register */
thread->gpr[31] = (uint64_t)thread->stack + stack_size; /* x31 = Stack pointer */
if (thread->gpr[31] & 0xf)
bdk_fatal("Stack not aligned 0x%lx\n", thread->gpr[31]);
_REENT_INIT_PTR(&thread->lib_state);
extern void __sinit(struct _reent *);
__sinit(&thread->lib_state);
thread->stack_canary = STACK_CANARY;
thread->next = NULL;
return thread;
}
/**
* Create a new thread. The thread may be scheduled to any of the
* cores supplied in the coremask. Note that a single thread is
* created and may only run on one core at a time. The thread may
* not start executing until the next yield call if all cores in
* the coremask are currently busy.
*
* @param node Node to use in a Numa setup. Can be an exact ID or a
* special value.
* @param coremask Mask of cores the thread can run on. Each set bit is an allowed
* core. Zero and -1 are both shortcuts for all cores.
* @param func Function to run as a thread
* @param arg0 First argument to the function
* @param arg1 Second argument to the function
* @param stack_size Stack size for the new thread. Set to zero for the system default.
*
* @return Zero on success, negative on failure
*/
int bdk_thread_create(bdk_node_t node, uint64_t coremask, bdk_thread_func_t func, int arg0, void *arg1, int stack_size)
{
bdk_thread_node_t *t_node = &bdk_thread_node[node];
bdk_thread_t *thread = __bdk_thread_create(coremask, func, arg0, arg1, stack_size);
if (thread == NULL)
return -1;
bdk_atomic_add64_nosync(&t_node->stat_num_threads, 1);
bdk_spinlock_lock(&t_node->lock);
if (t_node->tail)
t_node->tail->next = thread;
else
t_node->head = thread;
t_node->tail = thread;
bdk_spinlock_unlock(&t_node->lock);
BDK_SEV;
return 0;
}
/**
* Destroy the currently running thread. This never returns.
*/
void bdk_thread_destroy(void)
{
bdk_thread_node_t *t_node = &bdk_thread_node[bdk_numa_local()];
bdk_thread_t *current;
BDK_MRS_NV(TPIDR_EL3, current);
if (bdk_unlikely(!current))
bdk_fatal("bdk_thread_destroy() called without thread context\n");
if (bdk_unlikely(current->stack_canary != STACK_CANARY))
bdk_fatal("bdk_thread_destroy() detected a stack overflow\n");
fflush(NULL);
bdk_atomic_add64_nosync(&t_node->stat_num_threads, -1);
while (1)
{
if (BDK_DBG_MAGIC_ENABLE && (bdk_numa_local() == bdk_numa_master()))
bdk_dbg_check_magic();
if (t_node->head)
{
bdk_spinlock_lock(&t_node->lock);
/* Find the first thread that can run on this core */
bdk_thread_t *next = __bdk_thread_next();
/* If next is NULL then there are no other threads ready to run and we
will continue without doing anything */
if (next)
{
__bdk_thread_switch(next, 1);
bdk_fatal("bdk_thread_destroy() should never get here\n");
}
bdk_spinlock_unlock(&t_node->lock);
}
if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
bdk_sso_process_work();
BDK_WFE;
}
}
struct _reent __bdk_thread_global_reent;
struct _reent *__bdk_thread_getreent(void)
{
bdk_thread_t *current;
BDK_MRS_NV(TPIDR_EL3, current);
if (current)
return &current->lib_state;
else
return &__bdk_thread_global_reent;
}
void __bdk_thread_switch_complete(bdk_thread_t* old_context, int delete_old)
{
bdk_thread_node_t *t_node = &bdk_thread_node[bdk_numa_local()];
if (bdk_unlikely(delete_old))
{
bdk_spinlock_unlock(&t_node->lock);
free(old_context);
}
else
{
if (bdk_likely(old_context))
{
if (t_node->tail)
t_node->tail->next = old_context;
else
t_node->head = old_context;
t_node->tail = old_context;
}
bdk_spinlock_unlock(&t_node->lock);
if (bdk_likely(old_context))
BDK_SEV;
}
}
/**
* Called to create the initial thread for a CPU. Must be called
* once for each CPU.
*
* @param func Function to run as new thread. It is guaranteed that this will
* be the next thread run by the core.
* @param arg0 First thread argument
* @param arg1 Second thread argument
* @param stack_size Initial stack size, or zero for the default
*/
void bdk_thread_first(bdk_thread_func_t func, int arg0, void *arg1, int stack_size)
{
bdk_thread_node_t *t_node = &bdk_thread_node[bdk_numa_local()];
void *thread = __bdk_thread_create(bdk_core_to_mask(), func, arg0, arg1, stack_size);
if (thread)
{
bdk_atomic_add64_nosync(&t_node->stat_num_threads, 1);
bdk_spinlock_lock(&t_node->lock);
__bdk_thread_switch(thread, 0);
}
bdk_fatal("Create of __bdk_init_main thread failed\n");
}
/**
* Display statistics about the number of threads and scheduling
*/
void bdk_thread_show_stats()
{
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
{
if (!bdk_numa_exists(node))
continue;
bdk_thread_node_t *t_node = &bdk_thread_node[node];
printf("Node %d\n", node);
printf(" Active threads: %ld\n", t_node->stat_num_threads);
printf(" Schedule checks: %ld\n", t_node->stat_next_calls);
int64_t div = t_node->stat_next_calls;
if (!div)
div = 1;
printf(" Average walk depth: %ld\n",
t_node->stat_next_walks / div);
printf(" Not switching: %ld (%ld%%)\n",
t_node->stat_no_schedulable_threads,
t_node->stat_no_schedulable_threads * 100 / div);
bdk_atomic_set64(&t_node->stat_next_calls, 0);
bdk_atomic_set64(&t_node->stat_next_walks, 0);
bdk_atomic_set64(&t_node->stat_no_schedulable_threads, 0);
}
}

View File

@ -0,0 +1,286 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-fusf.h"
#include "libbdk-arch/bdk-csrs-rom.h"
/* The define BDK_TRUST_HARD_BLOW_NV controls whether the BDK will
hard blow the secure NV counter on boot. This is needed for a
production system, but can be dangerous in a development
environment. The default value of 0 is to prevent bricking of
chips due to CSIB[NVCOUNT] mistakes. BDK_TRUST_HARD_BLOW_NV must
be changed to a 1 for production. The code below will display a
warning if BDK_TRUST_HARD_BLOW_NV=0 in a trusted boot to remind
you */
#define BDK_TRUST_HARD_BLOW_NV 0
/* The CSIB used to boot will be stored here by bsk-start.S */
union bdk_rom_csib_s __bdk_trust_csib __attribute__((section("init")));
static bdk_trust_level_t __bdk_trust_level = BDK_TRUST_LEVEL_BROKEN;
/**
* Update the fused secure NV counter to reflect the CSIB[NVCOUNT] value. In
* production systems, be sure to set BDK_TRUST_HARD_BLOW_NV=1.
*/
static void __bdk_program_nv_counter(void)
{
int hw_nv = bdk_trust_get_nv_counter();
int csib_nv = __bdk_trust_csib.s.nvcnt;
if (!BDK_TRUST_HARD_BLOW_NV)
{
printf("\33[1m"); /* Bold */
bdk_warn("\n");
bdk_warn("********************************************************\n");
bdk_warn("* Configured for soft blow of secure NV counter. This\n");
bdk_warn("* build is not suitable for production trusted boot.\n");
bdk_warn("********************************************************\n");
bdk_warn("\n");
printf("\33[0m"); /* Normal */
}
/* Check if the CSIB NV counter is less than the HW fused values.
This means the image is an old rollback. Refuse to run */
if (csib_nv < hw_nv)
bdk_fatal("CSIB[NVCOUNT] is less than FUSF_CTL[ROM_T_CNT]. Image rollback not allowed\n");
/* If the CSIB NV counter matches the HW fuses, everything is
good */
if (csib_nv == hw_nv)
return;
/* CSIB NV counter is larger than the HW fuses. We must blow
fuses to move the hardware counter forward, protecting from
image rollback */
if (BDK_TRUST_HARD_BLOW_NV)
{
BDK_TRACE(INIT, "Trust: Hard blow secure NV counter to %d\n", csib_nv);
uint64_t v = 1ull << BDK_FUSF_FUSE_NUM_E_ROM_T_CNTX(csib_nv - 1);
bdk_fuse_field_hard_blow(bdk_numa_master(), BDK_FUSF_FUSE_NUM_E_FUSF_LCK, v, 0);
}
else
{
BDK_TRACE(INIT, "Trust: Soft blow secure NV counter to %d\n", csib_nv);
bdk_fuse_field_soft_blow(bdk_numa_master(), BDK_FUSF_FUSE_NUM_E_ROM_T_CNTX(csib_nv - 1));
}
}
/**
* Called by boot stub (TBL1FW) to initialize the state of trust
*/
void __bdk_trust_init(void)
{
extern uint64_t __bdk_init_reg_pc; /* The contents of PC when this image started */
const bdk_node_t node = bdk_numa_local();
volatile uint64_t *huk = bdk_phys_to_ptr(bdk_numa_get_address(node, BDK_FUSF_HUKX(0)));
/* Non-trusted boot address */
if (__bdk_init_reg_pc == 0x120000)
{
__bdk_trust_level = BDK_TRUST_LEVEL_NONE;
if (huk[0] | huk[1])
{
BDK_TRACE(INIT, "Trust: Initial image, Non-trusted boot with HUK\n");
goto fail_trust;
}
else
{
BDK_TRACE(INIT, "Trust: Initial image, Non-trusted boot without HUK\n");
goto skip_trust;
}
}
if (__bdk_init_reg_pc != 0x150000)
{
/* Not the first image */
BDK_CSR_INIT(rst_boot, node, BDK_RST_BOOT);
if (!rst_boot.s.trusted_mode)
{
__bdk_trust_level = BDK_TRUST_LEVEL_NONE;
BDK_TRACE(INIT, "Trust: Secondary image, non-trusted boot\n");
goto skip_trust;
}
int csibsize = 0;
const union bdk_rom_csib_s *csib = bdk_config_get_blob(&csibsize, BDK_CONFIG_TRUST_CSIB);
if (!csib)
{
__bdk_trust_level = BDK_TRUST_LEVEL_NONE;
BDK_TRACE(INIT, "Trust: Secondary image, non-trusted boot\n");
goto skip_trust;
}
if (csibsize != sizeof(__bdk_trust_csib))
{
BDK_TRACE(INIT, "Trust: Secondary image, Trusted boot with corrupt CSIB, trust broken\n");
goto fail_trust;
}
/* Record our trust level */
switch (csib->s.crypt)
{
case 0:
__bdk_trust_level = BDK_TRUST_LEVEL_SIGNED;
BDK_TRACE(INIT, "Trust: Secondary image, Trused boot, no encryption\n");
goto success_trust;
case 1:
__bdk_trust_level = BDK_TRUST_LEVEL_SIGNED_SSK;
BDK_TRACE(INIT, "Trust: Secondary image, Trused boot, SSK encryption\n");
goto success_trust;
case 2:
__bdk_trust_level = BDK_TRUST_LEVEL_SIGNED_BSSK;
BDK_TRACE(INIT, "Trust: Secondary image, Trused boot, BSSK encryption\n");
goto success_trust;
default:
__bdk_trust_level = BDK_TRUST_LEVEL_BROKEN;
BDK_TRACE(INIT, "Trust: Secondary image, Trusted boot, Corrupt CSIB[crypt], trust broken\n");
goto fail_trust;
}
}
/* Copy the Root of Trust public key out of the CSIB */
volatile uint64_t *rot_pub_key = bdk_key_alloc(node, 64);
if (!rot_pub_key)
{
__bdk_trust_level = BDK_TRUST_LEVEL_BROKEN;
BDK_TRACE(INIT, "Trust: Failed to allocate ROT memory, trust broken\n");
goto fail_trust;
}
rot_pub_key[0] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk0);
rot_pub_key[1] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk1);
rot_pub_key[2] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk2);
rot_pub_key[3] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk3);
rot_pub_key[4] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk4);
rot_pub_key[5] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk5);
rot_pub_key[6] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk6);
rot_pub_key[7] = bdk_le64_to_cpu(__bdk_trust_csib.s.rotpk7);
bdk_config_set_int(bdk_ptr_to_phys((void*)rot_pub_key), BDK_CONFIG_TRUST_ROT_ADDR);
BDK_TRACE(INIT, "Trust: ROT %016lx %016lx %016lx %016lx %016lx %016lx %016lx %016lx\n",
bdk_cpu_to_be64(rot_pub_key[0]), bdk_cpu_to_be64(rot_pub_key[1]),
bdk_cpu_to_be64(rot_pub_key[2]), bdk_cpu_to_be64(rot_pub_key[3]),
bdk_cpu_to_be64(rot_pub_key[4]), bdk_cpu_to_be64(rot_pub_key[5]),
bdk_cpu_to_be64(rot_pub_key[6]), bdk_cpu_to_be64(rot_pub_key[7]));
/* Update the secure NV counter with the value in the CSIB */
__bdk_program_nv_counter();
/* Create the BSSK */
if (huk[0] | huk[1])
{
uint64_t iv[2] = {0, 0};
volatile uint64_t *bssk = bdk_key_alloc(node, 16);
if (!bssk)
{
__bdk_trust_level = BDK_TRUST_LEVEL_BROKEN;
BDK_TRACE(INIT, "Trust: Failed to allocate BSSK memory, trust broken\n");
goto fail_trust;
}
BDK_TRACE(INIT, "Trust: Calculating BSSK\n");
uint64_t tmp_bssk[2];
tmp_bssk[0] = __bdk_trust_csib.s.fs0;
tmp_bssk[1] = __bdk_trust_csib.s.fs1;
bdk_aes128cbc_decrypt((void*)huk, (void*)tmp_bssk, 16, iv);
bssk[0] = tmp_bssk[0];
bssk[1] = tmp_bssk[1];
tmp_bssk[0] = 0;
tmp_bssk[1] = 0;
bdk_config_set_int(bdk_ptr_to_phys((void*)bssk), BDK_CONFIG_TRUST_BSSK_ADDR);
//BDK_TRACE(INIT, "Trust: BSSK %016lx %016lx\n", bdk_cpu_to_be64(bssk[0]), bdk_cpu_to_be64(bssk[1]));
}
/* Record our trust level */
switch (__bdk_trust_csib.s.crypt)
{
case 0:
__bdk_trust_level = BDK_TRUST_LEVEL_SIGNED;
BDK_TRACE(INIT, "Trust: Trused boot, no encryption\n");
break;
case 1:
__bdk_trust_level = BDK_TRUST_LEVEL_SIGNED_SSK;
BDK_TRACE(INIT, "Trust: Trused boot, SSK encryption\n");
break;
case 2:
__bdk_trust_level = BDK_TRUST_LEVEL_SIGNED_BSSK;
BDK_TRACE(INIT, "Trust: Trused boot, BSSK encryption\n");
break;
default:
__bdk_trust_level = BDK_TRUST_LEVEL_BROKEN;
goto fail_trust;
}
/* We started at the trusted boot address, CSIB should be
valid */
bdk_config_set_blob(sizeof(__bdk_trust_csib), &__bdk_trust_csib, BDK_CONFIG_TRUST_CSIB);
success_trust:
bdk_signed_load_public();
return;
fail_trust:
/* Hide secrets */
BDK_CSR_MODIFY(c, node, BDK_RST_BOOT,
c.s.dis_huk = 1);
BDK_TRACE(INIT, "Trust: Secrets Hidden\n");
skip_trust:
/* Erase CSIB as it is invalid */
memset(&__bdk_trust_csib, 0, sizeof(__bdk_trust_csib));
bdk_config_set_blob(0, NULL, BDK_CONFIG_TRUST_CSIB);
}
/**
* Returns the current level of trust. Must be called after
* __bdk_trust_init()
*
* @return Enumerated trsut level, see bdk_trust_level_t
*/
bdk_trust_level_t bdk_trust_get_level(void)
{
return __bdk_trust_level;
}
/**
* Return the current secure NV counter stored in the fuses
*
* @return NV counter (0-31)
*/
int bdk_trust_get_nv_counter(void)
{
/* Count leading zeros in FUSF_CTL[ROM_T_CNT] to dermine the
hardware NV value */
BDK_CSR_INIT(fusf_ctl, bdk_numa_master(), BDK_FUSF_CTL);
int hw_nv = 0;
if (fusf_ctl.s.rom_t_cnt)
hw_nv = 32 - __builtin_clz(fusf_ctl.s.rom_t_cnt);
return hw_nv;
}

View File

@ -0,0 +1,86 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Functions and macros for libdram access to CSR. These build
* on the normal BDK functions to allow logging of CSRs based on
* the libdram verbosity level. Internal use only.
*/
/**
* Write a CSR, possibly logging it based on the verbosity
* level. You should use DRAM_CSR_WRITE() as a convientent
* wrapper.
*
* @param node
* @param csr_name
* @param type
* @param busnum
* @param size
* @param address
* @param value
*/
#ifdef DRAM_CSR_WRITE_INLINE
static inline void dram_csr_write(bdk_node_t node, const char *csr_name, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value) __attribute__((always_inline));
static inline void dram_csr_write(bdk_node_t node, const char *csr_name, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value)
{
VB_PRT(VBL_CSRS, "N%d: DDR Config %s[%016lx] => %016lx\n", node, csr_name, address, value);
bdk_csr_write(node, type, busnum, size, address, value);
}
#else
extern void dram_csr_write(bdk_node_t node, const char *csr_name, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value);
#endif
/**
* Macro to write a CSR, logging if necessary
*/
#define DRAM_CSR_WRITE(node, csr, value) \
dram_csr_write(node, basename_##csr, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr, value)
/**
* Macro to make a read, modify, and write sequence easy. The "code_block"
* should be replaced with a C code block or a comma separated list of
* "name.s.field = value", without the quotes.
*/
#define DRAM_CSR_MODIFY(name, node, csr, code_block) do { \
typedef_##csr name = {.u = bdk_csr_read(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr)}; \
code_block; \
dram_csr_write(node, basename_##csr, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr, name.u); \
} while (0)

View File

@ -0,0 +1,83 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "dram-internal.h"
const char* lookup_env_parameter(const char *format, ...)
{
const char *s;
unsigned long value;
va_list args;
char buffer[64];
va_start(args, format);
vsnprintf(buffer, sizeof(buffer)-1, format, args);
buffer[sizeof(buffer)-1] = '\0';
va_end(args);
if ((s = getenv(buffer)) != NULL)
{
value = strtoul(s, NULL, 0);
error_print("Parameter found in environment: %s = \"%s\" 0x%lx (%ld)\n",
buffer, s, value, value);
}
return s;
}
const char* lookup_env_parameter_ull(const char *format, ...)
{
const char *s;
unsigned long long value;
va_list args;
char buffer[64];
va_start(args, format);
vsnprintf(buffer, sizeof(buffer)-1, format, args);
buffer[sizeof(buffer)-1] = '\0';
va_end(args);
if ((s = getenv(buffer)) != NULL)
{
value = strtoull(s, NULL, 0);
error_print("Parameter found in environment: %s = 0x%016llx\n",
buffer, value);
}
return s;
}

View File

@ -0,0 +1,48 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Functions for access the environment for DRAM tweaking.
* Intenral use only.
*/
extern const char *lookup_env_parameter(const char *format, ...) __attribute__ ((format(printf, 1, 2)));
extern const char *lookup_env_parameter_ull(const char *format, ...) __attribute__ ((format(printf, 1, 2)));

View File

@ -0,0 +1,46 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Functions for reporting DRAM init status through GPIOs.
* Useful for triggering scopes and such. Internal use only.
*/
extern void pulse_gpio_pin(bdk_node_t node, int pin, int usecs);

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,97 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Function for DDR3 init. Internal use only.
*/
extern void perform_octeon3_ddr3_sequence(bdk_node_t node, int rank_mask,
int ddr_interface_num, int sequence);
extern void perform_ddr_init_sequence(bdk_node_t node, int rank_mask,
int ddr_interface_num);
extern int ddr_memory_preserved(bdk_node_t node);
extern int init_octeon3_ddr3_interface(bdk_node_t node,
const ddr_configuration_t *ddr_configuration, uint32_t ddr_hertz,
uint32_t cpu_hertz, uint32_t ddr_ref_hertz, int board_type,
int board_rev_maj, int board_rev_min, int ddr_interface_num,
uint32_t ddr_interface_mask);
extern void
set_vref(bdk_node_t node, int ddr_interface_num, int rank,
int range, int value);
typedef struct {
unsigned char *rodt_ohms;
unsigned char *rtt_nom_ohms;
unsigned char *rtt_nom_table;
unsigned char *rtt_wr_ohms;
unsigned char *dic_ohms;
short *drive_strength;
short *dqx_strength;
} impedence_values_t;
extern impedence_values_t ddr4_impedence_values;
extern int
compute_vref_value(bdk_node_t node, int ddr_interface_num,
int rankx, int dimm_count, int rank_count,
impedence_values_t *imp_values, int is_stacked_die);
extern unsigned short
load_dac_override(int node, int ddr_interface_num,
int dac_value, int byte);
extern int
read_DAC_DBI_settings(int node, int ddr_interface_num,
int dac_or_dbi, int *settings);
extern void
display_DAC_DBI_settings(int node, int ddr_interface_num, int dac_or_dbi,
int ecc_ena, int *settings, char *title);
#define RODT_OHMS_COUNT 8
#define RTT_NOM_OHMS_COUNT 8
#define RTT_NOM_TABLE_COUNT 8
#define RTT_WR_OHMS_COUNT 8
#define DIC_OHMS_COUNT 3
#define DRIVE_STRENGTH_COUNT 15
extern uint64_t hertz_to_psecs(uint64_t hertz);
extern uint64_t psecs_to_mts(uint64_t psecs);
extern uint64_t mts_to_hertz(uint64_t mts);
extern uint64_t pretty_psecs_to_mts(uint64_t psecs);

View File

@ -0,0 +1,201 @@
#ifndef __DRAM_INTERNAL_H__
#define __DRAM_INTERNAL_H__
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* This header defines all internal API for libdram. None
* of these functions should be called by users of the library.
* This is the only header that DRAM files should include
* from the libdram directory
*/
#include "libdram.h"
#include "lib_octeon_shared.h"
#include "dram-print.h"
#include "dram-util.h"
#include "dram-csr.h"
#include "dram-env.h"
#include "dram-gpio.h"
#include "dram-spd.h"
#include "dram-l2c.h"
#include "dram-init-ddr3.h"
#undef DRAM_CSR_WRITE_INLINE
// define how many HW WL samples to take for majority voting
// MUST BE odd!!
// assume there should only be 2 possible values that will show up,
// so treat ties as a problem!!!
#define WLEVEL_LOOPS_DEFAULT 5 // NOTE: do not change this without checking the code!!!
// define how many HW RL samples per rank to take
// multiple samples will allow either:
// 1. looking for the best sample score
// 2. averaging the samples into a composite score
// symbol PICK_BEST_RANK_SCORE_NOT_AVG is used to choose
// (see dram-init-ddr3.c:
#define RLEVEL_AVG_LOOPS_DEFAULT 3
#define PICK_BEST_RANK_SCORE_NOT_AVG 1
typedef struct {
int delay;
int loop_total;
int loop_count;
int best;
uint64_t bm;
int bmerrs;
int sqerrs;
int bestsq;
} rlevel_byte_data_t;
typedef struct {
uint64_t bm;
uint8_t mstart;
uint8_t width;
int errs;
} rlevel_bitmask_t;
#define SET_DDR_DLL_CTL3(field, expr) \
do { \
ddr_dll_ctl3.cn81xx.field = (expr); \
} while (0)
#define ENCODE_DLL90_BYTE_SEL(byte_sel) ((byte_sel)+1)
#define GET_DDR_DLL_CTL3(field) \
(ddr_dll_ctl3.cn81xx.field)
#define RLEVEL_NONSEQUENTIAL_DELAY_ERROR 50
#define RLEVEL_ADJACENT_DELAY_ERROR 30
#define TWO_LMC_MASK 0x03
#define FOUR_LMC_MASK 0x0f
#define ONE_DIMM_MASK 0x01
#define TWO_DIMM_MASK 0x03
extern int initialize_ddr_clock(bdk_node_t node,
const ddr_configuration_t *ddr_configuration, uint32_t cpu_hertz,
uint32_t ddr_hertz, uint32_t ddr_ref_hertz, int ddr_interface_num,
uint32_t ddr_interface_mask);
extern int test_dram_byte(bdk_node_t node, int ddr_interface_num, uint64_t p,
uint64_t bitmask, uint64_t *xor_data);
extern int dram_tuning_mem_xor(bdk_node_t node, int ddr_interface_num, uint64_t p,
uint64_t bitmask, uint64_t *xor_data);
// "mode" arg
#define DBTRAIN_TEST 0
#define DBTRAIN_DBI 1
#define DBTRAIN_LFSR 2
extern int test_dram_byte_hw(bdk_node_t node, int ddr_interface_num,
uint64_t p, int mode, uint64_t *xor_data);
extern int run_best_hw_patterns(bdk_node_t node, int ddr_interface_num,
uint64_t p, int mode, uint64_t *xor_data);
extern int get_dimm_part_number(char *buffer, bdk_node_t node,
const dimm_config_t *dimm_config,
int ddr_type);
extern uint32_t get_dimm_serial_number(bdk_node_t node,
const dimm_config_t *dimm_config,
int ddr_type);
extern int octeon_ddr_initialize(bdk_node_t node, uint32_t cpu_hertz,
uint32_t ddr_hertz, uint32_t ddr_ref_hertz, uint32_t ddr_interface_mask,
const ddr_configuration_t *ddr_configuration, uint32_t *measured_ddr_hertz,
int board_type, int board_rev_maj, int board_rev_min);
extern uint64_t divide_nint(uint64_t dividend, uint64_t divisor);
typedef enum {
DDR3_DRAM = 3,
DDR4_DRAM = 4,
} ddr_type_t;
static inline int get_ddr_type(bdk_node_t node, const dimm_config_t *dimm_config)
{
int spd_ddr_type;
#define DEVICE_TYPE DDR4_SPD_KEY_BYTE_DEVICE_TYPE // same for DDR3 and DDR4
spd_ddr_type = read_spd(node, dimm_config, DEVICE_TYPE);
debug_print("%s:%d spd_ddr_type=0x%02x\n", __FUNCTION__, __LINE__, spd_ddr_type);
/* we return only DDR4 or DDR3 */
return (spd_ddr_type == 0x0C) ? DDR4_DRAM : DDR3_DRAM;
}
static inline int get_dimm_ecc(bdk_node_t node, const dimm_config_t *dimm_config, int ddr_type)
{
#define BUS_WIDTH(t) (((t) == DDR4_DRAM) ? DDR4_SPD_MODULE_MEMORY_BUS_WIDTH : DDR3_SPD_MEMORY_BUS_WIDTH)
return !!(read_spd(node, dimm_config, BUS_WIDTH(ddr_type)) & 8);
}
static inline int get_dimm_module_type(bdk_node_t node, const dimm_config_t *dimm_config, int ddr_type)
{
#define MODULE_TYPE DDR4_SPD_KEY_BYTE_MODULE_TYPE // same for DDR3 and DDR4
return (read_spd(node, dimm_config, MODULE_TYPE) & 0x0F);
}
extern int common_ddr4_fixups(dram_config_t *cfg, uint32_t default_udimm_speed);
#define DEFAULT_BEST_RANK_SCORE 9999999
#define MAX_RANK_SCORE_LIMIT 99 // is this OK?
unsigned short load_dll_offset(bdk_node_t node, int ddr_interface_num,
int dll_offset_mode, int byte_offset, int byte);
void change_dll_offset_enable(bdk_node_t node, int ddr_interface_num, int change);
extern int perform_dll_offset_tuning(bdk_node_t node, int dll_offset_mode, int do_tune);
extern int perform_HW_dll_offset_tuning(bdk_node_t node, int dll_offset_mode, int bytelane);
extern int perform_margin_write_voltage(bdk_node_t node);
extern int perform_margin_read_voltage(bdk_node_t node);
#define LMC_DDR3_RESET_ASSERT 0
#define LMC_DDR3_RESET_DEASSERT 1
extern void cn88xx_lmc_ddr3_reset(bdk_node_t node, int ddr_interface_num, int reset);
extern void perform_lmc_reset(bdk_node_t node, int ddr_interface_num);
extern void ddr4_mrw(bdk_node_t node, int ddr_interface_num, int rank,
int mr_wr_addr, int mr_wr_sel, int mr_wr_bg1);
#endif /* __DRAM_INTERNAL_H__ */

View File

@ -0,0 +1,69 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "dram-internal.h"
int limit_l2_ways(bdk_node_t node, int ways, int verbose)
{
int ways_max = bdk_l2c_get_num_assoc(node);
int ways_min = 0;
int errors = 0;
if (ways >= ways_min && ways <= ways_max)
{
uint32_t valid_mask = (0x1 << ways_max) - 1;
uint32_t mask = (valid_mask << ways) & valid_mask;
if (verbose)
printf("Limiting L2 to %d ways\n", ways);
for (int i = 0; i < (int)bdk_get_num_cores(node); i++)
errors += bdk_l2c_set_core_way_partition(node, i, mask);
errors += bdk_l2c_set_hw_way_partition(node, mask);
}
else
{
errors++;
printf("ERROR: invalid limit_l2_ways %d, must be between %d and %d\n",
ways, ways_min, ways_max);
}
if (errors)
puts("ERROR limiting L2 cache ways\n");
return errors;
}

View File

@ -0,0 +1,45 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Functions for controlling L2C. Internal use only.
*/
extern int limit_l2_ways(bdk_node_t node, int ways, int verbose);

View File

@ -0,0 +1,86 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Functions for diplaying output in libdram. Internal use only.
*/
typedef enum {
// low 4 bits are verbosity level
VBL_OFF = 0, // use this only to init dram_verbosity
VBL_ALL = 0, // use this only in VBL_PR() to get printf equiv
VBL_NORM = 1,
VBL_FAE = 2,
VBL_TME = 3,
VBL_DEV = 4,
VBL_DEV2 = 5,
VBL_DEV3 = 6,
VBL_DEV4 = 7,
VBL_NONE = 15, // use this only in VBL_PR() to get no printing
// upper 4 bits are special verbosities
VBL_SEQ = 16,
VBL_CSRS = 32,
VBL_SPECIAL = 48,
// force at least 8 bits for enum
VBL_LAST = 255
} dram_verbosity_t;
extern dram_verbosity_t dram_verbosity;
// "level" should be 1-7, or only one of the special bits
// let the compiler optimize the test for verbosity
#define is_verbosity_level(level) ((int)(dram_verbosity & 0x0f) >= (level))
#define is_verbosity_special(level) (((int)(dram_verbosity & 0xf0) & (level)) != 0)
#define dram_is_verbose(level) (((level) & VBL_SPECIAL) ? is_verbosity_special(level) : is_verbosity_level(level))
#define VB_PRT(level, format, ...) \
do { \
if (dram_is_verbose(level)) \
printf(format, ##__VA_ARGS__); \
} while (0)
#define ddr_print(format, ...) VB_PRT(VBL_NORM, format, ##__VA_ARGS__)
#define error_print(format, ...) printf(format, ##__VA_ARGS__)
#ifdef DEBUG_DEBUG_PRINT
#define debug_print(format, ...) printf(format, ##__VA_ARGS__)
#else
#define debug_print(format, ...) do {} while (0)
#endif

View File

@ -0,0 +1,583 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include <ctype.h>
#include "dram-internal.h"
/**
* Read the entire contents of a DIMM SPD and store it in the device tree. The
* current DRAM config is also updated, so future SPD accesses used the cached
* copy.
*
* @param node Node the DRAM config is for
* @param cfg Current DRAM config. Updated with SPD data
* @param lmc LMC to read DIMM for
* @param dimm DIMM slot for SPD to read
*
* @return Zero on success, negative on failure
*/
int read_entire_spd(bdk_node_t node, dram_config_t *cfg, int lmc, int dimm)
{
/* If pointer to data is provided, use it, otherwise read from SPD over twsi */
if (cfg->config[lmc].dimm_config_table[dimm].spd_ptr)
return 0;
if (!cfg->config[lmc].dimm_config_table[dimm].spd_addr)
return -1;
/* Figure out how to access the SPD */
int spd_addr = cfg->config[lmc].dimm_config_table[dimm].spd_addr;
int bus = spd_addr >> 12;
int address = spd_addr & 0x7f;
/* Figure out the size we will read */
int64_t dev_type = bdk_twsix_read_ia(node, bus, address, DDR4_SPD_KEY_BYTE_DEVICE_TYPE, 1, 1);
if (dev_type < 0)
return -1; /* No DIMM */
int spd_size = (dev_type == 0x0c) ? 512 : 256;
/* Allocate storage */
uint32_t *spd_buf = malloc(spd_size);
if (!spd_buf)
return -1;
uint32_t *ptr = spd_buf;
for (int bank = 0; bank < (spd_size >> 8); bank++)
{
/* this should only happen for DDR4, which has a second bank of 256 bytes */
if (bank)
bdk_twsix_write_ia(node, bus, 0x36 | bank, 0, 2, 1, 0);
int bank_size = 256;
for (int i = 0; i < bank_size; i += 4)
{
int64_t data = bdk_twsix_read_ia(node, bus, address, i, 4, 1);
if (data < 0)
{
free(spd_buf);
bdk_error("Failed to read SPD data at 0x%x\n", i + (bank << 8));
/* Restore the bank to zero */
if (bank)
bdk_twsix_write_ia(node, bus, 0x36 | 0, 0, 2, 1, 0);
return -1;
}
else
*ptr++ = bdk_be32_to_cpu(data);
}
/* Restore the bank to zero */
if (bank)
bdk_twsix_write_ia(node, bus, 0x36 | 0, 0, 2, 1, 0);
}
/* Store the SPD in the device tree */
bdk_config_set_blob(spd_size, spd_buf, BDK_CONFIG_DDR_SPD_DATA, dimm, lmc, node);
cfg->config[lmc].dimm_config_table[dimm].spd_ptr = (void*)spd_buf;
return 0;
}
/* Read an DIMM SPD value, either using TWSI to read it from the DIMM, or
* from a provided array.
*/
int read_spd(bdk_node_t node, const dimm_config_t *dimm_config, int spd_field)
{
/* If pointer to data is provided, use it, otherwise read from SPD over twsi */
if (dimm_config->spd_ptr)
return dimm_config->spd_ptr[spd_field];
else if (dimm_config->spd_addr)
{
int data;
int bus = dimm_config->spd_addr >> 12;
int address = dimm_config->spd_addr & 0x7f;
/* this should only happen for DDR4, which has a second bank of 256 bytes */
int bank = (spd_field >> 8) & 1;
if (bank) {
bdk_twsix_write_ia(node, bus, 0x36 | bank, 0, 2, 1, 0);
spd_field %= 256;
}
data = bdk_twsix_read_ia(node, bus, address, spd_field, 1, 1);
/* Restore the bank to zero */
if (bank) {
bdk_twsix_write_ia(node, bus, 0x36 | 0, 0, 2, 1, 0);
}
return data;
}
else
return -1;
}
static uint16_t ddr3_crc16(uint8_t *ptr, int count)
{
/* From DDR3 spd specification */
int crc, i;
crc = 0;
while (--count >= 0)
{
crc = crc ^ (int)*ptr++ << 8;
for (i = 0; i < 8; ++i)
if (crc & 0x8000)
crc = crc << 1 ^ 0x1021;
else
crc = crc << 1;
}
return crc & 0xFFFF;
}
static int validate_spd_checksum_ddr3(bdk_node_t node, int twsi_addr, int silent)
{
uint8_t spd_data[128];
int crc_bytes = 126;
uint16_t crc_comp;
int i;
int rv;
int ret = 1;
for (i = 0; i < 128; i++)
{
rv = bdk_twsix_read_ia(node, twsi_addr >> 12, twsi_addr & 0x7f, i, 1, 1);
if (rv < 0)
return 0; /* TWSI read error */
spd_data[i] = (uint8_t)rv;
}
/* Check byte 0 to see how many bytes checksum is over */
if (spd_data[0] & 0x80)
crc_bytes = 117;
crc_comp = ddr3_crc16(spd_data, crc_bytes);
if (spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE] != (crc_comp & 0xff) ||
spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE] != (crc_comp >> 8))
{
if (!silent) {
printf("DDR3 SPD CRC error, spd addr: 0x%x, calculated crc: 0x%04x, read crc: 0x%02x%02x\n",
twsi_addr, crc_comp,
spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE],
spd_data[DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE]);
}
ret = 0;
}
return ret;
}
static int validate_spd_checksum(bdk_node_t node, int twsi_addr, int silent)
{
int rv;
debug_print("Validating DIMM at address 0x%x\n", twsi_addr);
if (!twsi_addr) return 1; /* return OK if we are not doing real DIMMs */
/* Look up module type to determine if DDR3 or DDR4 */
rv = bdk_twsix_read_ia(node, twsi_addr >> 12, twsi_addr & 0x7f, 2, 1, 1);
if (rv >= 0xB && rv <= 0xC) /* this is DDR3 or DDR4, do same */
return validate_spd_checksum_ddr3(node, twsi_addr, silent);
if (!silent)
printf("Unrecognized DIMM type: 0x%x at spd address: 0x%x\n",
rv, twsi_addr);
return 0;
}
int validate_dimm(bdk_node_t node, const dimm_config_t *dimm_config)
{
int spd_addr;
spd_addr = dimm_config->spd_addr;
debug_print("Validating dimm spd addr: 0x%02x spd ptr: %x\n",
spd_addr, dimm_config->spd_ptr);
// if the slot is not possible
if (!spd_addr && !dimm_config->spd_ptr)
return -1;
{
int val0, val1;
int ddr_type = get_ddr_type(node, dimm_config);
switch (ddr_type)
{
case DDR3_DRAM: /* DDR3 */
case DDR4_DRAM: /* DDR4 */
debug_print("Validating DDR%d DIMM\n", ((dimm_type >> 2) & 3) + 1);
#define DENSITY_BANKS DDR4_SPD_DENSITY_BANKS // same for DDR3 and DDR4
#define ROW_COL_BITS DDR4_SPD_ADDRESSING_ROW_COL_BITS // same for DDR3 and DDR4
val0 = read_spd(node, dimm_config, DENSITY_BANKS);
val1 = read_spd(node, dimm_config, ROW_COL_BITS);
if (val0 < 0 && val1 < 0) {
debug_print("Error reading SPD for DIMM\n");
return 0; /* Failed to read dimm */
}
if (val0 == 0xff && val1 == 0xff) {
ddr_print("Blank or unreadable SPD for DIMM\n");
return 0; /* Blank SPD or otherwise unreadable device */
}
/* Don't treat bad checksums as fatal. */
validate_spd_checksum(node, spd_addr, 0);
break;
case 0x00: /* Terminator detected. Fail silently. */
return 0;
default:
debug_print("Unknown DIMM type 0x%x for DIMM @ 0x%x\n",
dimm_type, dimm_config->spd_addr);
return 0; /* Failed to read dimm */
}
}
return 1;
}
int get_dimm_part_number(char *buffer, bdk_node_t node,
const dimm_config_t *dimm_config,
int ddr_type)
{
int i;
int c;
int skipping = 1;
int strlen = 0;
#define PART_LIMIT(t) (((t) == DDR4_DRAM) ? 19 : 18)
#define PART_NUMBER(t) (((t) == DDR4_DRAM) ? DDR4_SPD_MODULE_PART_NUMBER : DDR3_SPD_MODULE_PART_NUMBER)
int limit = PART_LIMIT(ddr_type);
int offset = PART_NUMBER(ddr_type);
for (i = 0; i < limit; ++i) {
c = (read_spd(node, dimm_config, offset+i) & 0xff);
if (c == 0) // any null, we are done
break;
/* Skip leading spaces. */
if (skipping) {
if (isspace(c))
continue;
else
skipping = 0;
}
/* Put non-null non-leading-space-skipped char into buffer */
buffer[strlen] = c;
++strlen;
}
if (strlen > 0) {
i = strlen - 1; // last char put into buf
while (i >= 0 && isspace((int)buffer[i])) { // still in buf and a space
--i;
--strlen;
}
}
buffer[strlen] = 0; /* Insure that the string is terminated */
return strlen;
}
uint32_t get_dimm_serial_number(bdk_node_t node, const dimm_config_t *dimm_config, int ddr_type)
{
uint32_t serial_number = 0;
int offset;
#define SERIAL_NUMBER(t) (((t) == DDR4_DRAM) ? DDR4_SPD_MODULE_SERIAL_NUMBER : DDR3_SPD_MODULE_SERIAL_NUMBER)
offset = SERIAL_NUMBER(ddr_type);
for (int i = 0, j = 24; i < 4; ++i, j -= 8) {
serial_number |= ((read_spd(node, dimm_config, offset + i) & 0xff) << j);
}
return serial_number;
}
static uint32_t get_dimm_checksum(bdk_node_t node, const dimm_config_t *dimm_config, int ddr_type)
{
uint32_t spd_chksum;
#define LOWER_NIBBLE(t) (((t) == DDR4_DRAM) ? DDR4_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE : DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE)
#define UPPER_NIBBLE(t) (((t) == DDR4_DRAM) ? DDR4_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE : DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE)
spd_chksum = 0xff & read_spd(node, dimm_config, LOWER_NIBBLE(ddr_type));
spd_chksum |= ((0xff & read_spd(node, dimm_config, UPPER_NIBBLE(ddr_type))) << 8);
return spd_chksum;
}
static
void report_common_dimm(bdk_node_t node, const dimm_config_t *dimm_config, int dimm,
const char **dimm_types, int ddr_type, char *volt_str,
int ddr_interface_num, int num_ranks, int dram_width, int dimm_size_mb)
{
int spd_ecc;
unsigned spd_module_type;
uint32_t serial_number;
char part_number[21]; /* 20 bytes plus string terminator is big enough for either */
char *sn_str;
spd_module_type = get_dimm_module_type(node, dimm_config, ddr_type);
spd_ecc = get_dimm_ecc(node, dimm_config, ddr_type);
(void) get_dimm_part_number(part_number, node, dimm_config, ddr_type);
serial_number = get_dimm_serial_number(node, dimm_config, ddr_type);
if ((serial_number != 0) && (serial_number != 0xffffffff)) {
sn_str = "s/n";
} else {
serial_number = get_dimm_checksum(node, dimm_config, ddr_type);
sn_str = "chksum";
}
// FIXME: add output of DIMM rank/width, as in: 2Rx4, 1Rx8, etc
printf("N%d.LMC%d.DIMM%d: %d MB, DDR%d %s %dRx%d %s, p/n: %s, %s: %u, %s\n",
node, ddr_interface_num, dimm, dimm_size_mb, ddr_type,
dimm_types[spd_module_type], num_ranks, dram_width,
(spd_ecc ? "ECC" : "non-ECC"), part_number,
sn_str, serial_number, volt_str);
}
const char *ddr3_dimm_types[16] = {
/* 0000 */ "Undefined",
/* 0001 */ "RDIMM",
/* 0010 */ "UDIMM",
/* 0011 */ "SO-DIMM",
/* 0100 */ "Micro-DIMM",
/* 0101 */ "Mini-RDIMM",
/* 0110 */ "Mini-UDIMM",
/* 0111 */ "Mini-CDIMM",
/* 1000 */ "72b-SO-UDIMM",
/* 1001 */ "72b-SO-RDIMM",
/* 1010 */ "72b-SO-CDIMM"
/* 1011 */ "LRDIMM",
/* 1100 */ "16b-SO-DIMM",
/* 1101 */ "32b-SO-DIMM",
/* 1110 */ "Reserved",
/* 1111 */ "Reserved"
};
static
void report_ddr3_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
int dimm, int ddr_interface_num, int num_ranks,
int dram_width, int dimm_size_mb)
{
int spd_voltage;
char *volt_str;
spd_voltage = read_spd(node, dimm_config, DDR3_SPD_NOMINAL_VOLTAGE);
if ((spd_voltage == 0) || (spd_voltage & 3))
volt_str = "1.5V";
if (spd_voltage & 2)
volt_str = "1.35V";
if (spd_voltage & 4)
volt_str = "1.2xV";
report_common_dimm(node, dimm_config, dimm, ddr3_dimm_types,
DDR3_DRAM, volt_str, ddr_interface_num,
num_ranks, dram_width, dimm_size_mb);
}
const char *ddr4_dimm_types[16] = {
/* 0000 */ "Extended",
/* 0001 */ "RDIMM",
/* 0010 */ "UDIMM",
/* 0011 */ "SO-DIMM",
/* 0100 */ "LRDIMM",
/* 0101 */ "Mini-RDIMM",
/* 0110 */ "Mini-UDIMM",
/* 0111 */ "Reserved",
/* 1000 */ "72b-SO-RDIMM",
/* 1001 */ "72b-SO-UDIMM",
/* 1010 */ "Reserved",
/* 1011 */ "Reserved",
/* 1100 */ "16b-SO-DIMM",
/* 1101 */ "32b-SO-DIMM",
/* 1110 */ "Reserved",
/* 1111 */ "Reserved"
};
static
void report_ddr4_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
int dimm, int ddr_interface_num, int num_ranks,
int dram_width, int dimm_size_mb)
{
int spd_voltage;
char *volt_str;
spd_voltage = read_spd(node, dimm_config, DDR4_SPD_MODULE_NOMINAL_VOLTAGE);
if ((spd_voltage == 0x01) || (spd_voltage & 0x02))
volt_str = "1.2V";
if ((spd_voltage == 0x04) || (spd_voltage & 0x08))
volt_str = "TBD1 V";
if ((spd_voltage == 0x10) || (spd_voltage & 0x20))
volt_str = "TBD2 V";
report_common_dimm(node, dimm_config, dimm, ddr4_dimm_types,
DDR4_DRAM, volt_str, ddr_interface_num,
num_ranks, dram_width, dimm_size_mb);
}
void report_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
int dimm, int ddr_interface_num, int num_ranks,
int dram_width, int dimm_size_mb)
{
int ddr_type;
/* ddr_type only indicates DDR4 or DDR3 */
ddr_type = get_ddr_type(node, dimm_config);
if (ddr_type == DDR4_DRAM)
report_ddr4_dimm(node, dimm_config, dimm, ddr_interface_num,
num_ranks, dram_width, dimm_size_mb);
else
report_ddr3_dimm(node, dimm_config, dimm, ddr_interface_num,
num_ranks, dram_width, dimm_size_mb);
}
static int
get_ddr4_spd_speed(bdk_node_t node, const dimm_config_t *dimm_config)
{
int spdMTB = 125;
int spdFTB = 1;
int tCKAVGmin
= spdMTB * read_spd(node, dimm_config, DDR4_SPD_MINIMUM_CYCLE_TIME_TCKAVGMIN)
+ spdFTB * (signed char) read_spd(node, dimm_config, DDR4_SPD_MIN_CYCLE_TIME_FINE_TCKAVGMIN);
return pretty_psecs_to_mts(tCKAVGmin);
}
static int
get_ddr3_spd_speed(bdk_node_t node, const dimm_config_t *dimm_config)
{
int spd_mtb_dividend = 0xff & read_spd(node, dimm_config, DDR3_SPD_MEDIUM_TIMEBASE_DIVIDEND);
int spd_mtb_divisor = 0xff & read_spd(node, dimm_config, DDR3_SPD_MEDIUM_TIMEBASE_DIVISOR);
int spd_tck_min = 0xff & read_spd(node, dimm_config, DDR3_SPD_MINIMUM_CYCLE_TIME_TCKMIN);
short ftb_Dividend = read_spd(node, dimm_config, DDR3_SPD_FINE_TIMEBASE_DIVIDEND_DIVISOR) >> 4;
short ftb_Divisor = read_spd(node, dimm_config, DDR3_SPD_FINE_TIMEBASE_DIVIDEND_DIVISOR) & 0xf;
ftb_Divisor = (ftb_Divisor == 0) ? 1 : ftb_Divisor; /* Make sure that it is not 0 */
int mtb_psec = spd_mtb_dividend * 1000 / spd_mtb_divisor;
int tCKmin = mtb_psec * spd_tck_min;
tCKmin += ftb_Dividend *
(signed char) read_spd(node, dimm_config, DDR3_SPD_MINIMUM_CYCLE_TIME_FINE_TCKMIN)
/ ftb_Divisor;
return pretty_psecs_to_mts(tCKmin);
}
static int
speed_bin_down(int speed)
{
if (speed == 2133)
return 1866;
else if (speed == 1866)
return 1600;
else
return speed;
}
int
dram_get_default_spd_speed(bdk_node_t node, const ddr_configuration_t *ddr_config)
{
int lmc, dimm;
int speed, ret_speed = 0;
int ddr_type = get_ddr_type(node, &ddr_config[0].dimm_config_table[0]);
int dimm_speed[8], dimm_count = 0;
int dimms_per_lmc = 0;
for (lmc = 0; lmc < 4; lmc++) {
for (dimm = 0; dimm < DDR_CFG_T_MAX_DIMMS; dimm++) {
const dimm_config_t *dimm_config = &ddr_config[lmc].dimm_config_table[dimm];
if (/*dimm_config->spd_addr ||*/ dimm_config->spd_ptr)
{
speed = (ddr_type == DDR4_DRAM)
? get_ddr4_spd_speed(node, dimm_config)
: get_ddr3_spd_speed(node, dimm_config);
//printf("N%d.LMC%d.DIMM%d: SPD speed %d\n", node, lmc, dimm, speed);
dimm_speed[dimm_count] = speed;
dimm_count++;
if (lmc == 0)
dimms_per_lmc++;
}
}
}
// all DIMMs must be same speed
speed = dimm_speed[0];
for (dimm = 1; dimm < dimm_count; dimm++) {
if (dimm_speed[dimm] != speed) {
ret_speed = -1;
goto finish_up;
}
}
// if 2400 or greater, use 2133
if (speed >= 2400)
speed = 2133;
// use next speed down if 2DPC...
if (dimms_per_lmc > 1)
speed = speed_bin_down(speed);
// Update the in memory config to match the automatically calculated speed
bdk_config_set_int(speed, BDK_CONFIG_DDR_SPEED, node);
// do filtering for our jittery PLL
if (speed == 2133)
speed = 2100;
else if (speed == 1866)
speed = 1880;
// OK, return what we have...
ret_speed = mts_to_hertz(speed);
finish_up:
//printf("N%d: Returning default SPD speed %d\n", node, ret_speed);
return ret_speed;
}

View File

@ -0,0 +1,166 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Functions, enumarations, and structures related to DIMM SPDs.
* Everything in this file is internal to libdram.
*/
/* data field addresses in the DDR3 SPD eeprom */
typedef enum ddr3_spd_addrs {
DDR3_SPD_BYTES_PROGRAMMED = 0,
DDR3_SPD_REVISION = 1,
DDR3_SPD_KEY_BYTE_DEVICE_TYPE = 2,
DDR3_SPD_KEY_BYTE_MODULE_TYPE = 3,
DDR3_SPD_DENSITY_BANKS = 4,
DDR3_SPD_ADDRESSING_ROW_COL_BITS = 5,
DDR3_SPD_NOMINAL_VOLTAGE = 6,
DDR3_SPD_MODULE_ORGANIZATION = 7,
DDR3_SPD_MEMORY_BUS_WIDTH = 8,
DDR3_SPD_FINE_TIMEBASE_DIVIDEND_DIVISOR = 9,
DDR3_SPD_MEDIUM_TIMEBASE_DIVIDEND = 10,
DDR3_SPD_MEDIUM_TIMEBASE_DIVISOR = 11,
DDR3_SPD_MINIMUM_CYCLE_TIME_TCKMIN = 12,
DDR3_SPD_CAS_LATENCIES_LSB = 14,
DDR3_SPD_CAS_LATENCIES_MSB = 15,
DDR3_SPD_MIN_CAS_LATENCY_TAAMIN = 16,
DDR3_SPD_MIN_WRITE_RECOVERY_TWRMIN = 17,
DDR3_SPD_MIN_RAS_CAS_DELAY_TRCDMIN = 18,
DDR3_SPD_MIN_ROW_ACTIVE_DELAY_TRRDMIN = 19,
DDR3_SPD_MIN_ROW_PRECHARGE_DELAY_TRPMIN = 20,
DDR3_SPD_UPPER_NIBBLES_TRAS_TRC = 21,
DDR3_SPD_MIN_ACTIVE_PRECHARGE_LSB_TRASMIN = 22,
DDR3_SPD_MIN_ACTIVE_REFRESH_LSB_TRCMIN = 23,
DDR3_SPD_MIN_REFRESH_RECOVERY_LSB_TRFCMIN = 24,
DDR3_SPD_MIN_REFRESH_RECOVERY_MSB_TRFCMIN = 25,
DDR3_SPD_MIN_INTERNAL_WRITE_READ_CMD_TWTRMIN = 26,
DDR3_SPD_MIN_INTERNAL_READ_PRECHARGE_CMD_TRTPMIN = 27,
DDR3_SPD_UPPER_NIBBLE_TFAW = 28,
DDR3_SPD_MIN_FOUR_ACTIVE_WINDOW_TFAWMIN = 29,
DDR3_SPD_MINIMUM_CYCLE_TIME_FINE_TCKMIN = 34,
DDR3_SPD_MIN_CAS_LATENCY_FINE_TAAMIN = 35,
DDR3_SPD_MIN_RAS_CAS_DELAY_FINE_TRCDMIN = 36,
DDR3_SPD_MIN_ROW_PRECHARGE_DELAY_FINE_TRPMIN = 37,
DDR3_SPD_MIN_ACTIVE_REFRESH_LSB_FINE_TRCMIN = 38,
DDR3_SPD_ADDRESS_MAPPING = 63,
DDR3_SPD_MODULE_SERIAL_NUMBER = 122,
DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE = 126,
DDR3_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE = 127,
DDR3_SPD_MODULE_PART_NUMBER = 128
} ddr3_spd_addr_t;
/* data field addresses in the DDR4 SPD eeprom */
typedef enum ddr4_spd_addrs {
DDR4_SPD_BYTES_PROGRAMMED = 0,
DDR4_SPD_REVISION = 1,
DDR4_SPD_KEY_BYTE_DEVICE_TYPE = 2,
DDR4_SPD_KEY_BYTE_MODULE_TYPE = 3,
DDR4_SPD_DENSITY_BANKS = 4,
DDR4_SPD_ADDRESSING_ROW_COL_BITS = 5,
DDR4_SPD_PACKAGE_TYPE = 6,
DDR4_SPD_OPTIONAL_FEATURES = 7,
DDR4_SPD_THERMAL_REFRESH_OPTIONS = 8,
DDR4_SPD_OTHER_OPTIONAL_FEATURES = 9,
DDR4_SPD_SECONDARY_PACKAGE_TYPE = 10,
DDR4_SPD_MODULE_NOMINAL_VOLTAGE = 11,
DDR4_SPD_MODULE_ORGANIZATION = 12,
DDR4_SPD_MODULE_MEMORY_BUS_WIDTH = 13,
DDR4_SPD_MODULE_THERMAL_SENSOR = 14,
DDR4_SPD_RESERVED_BYTE15 = 15,
DDR4_SPD_RESERVED_BYTE16 = 16,
DDR4_SPD_TIMEBASES = 17,
DDR4_SPD_MINIMUM_CYCLE_TIME_TCKAVGMIN = 18,
DDR4_SPD_MAXIMUM_CYCLE_TIME_TCKAVGMAX = 19,
DDR4_SPD_CAS_LATENCIES_BYTE0 = 20,
DDR4_SPD_CAS_LATENCIES_BYTE1 = 21,
DDR4_SPD_CAS_LATENCIES_BYTE2 = 22,
DDR4_SPD_CAS_LATENCIES_BYTE3 = 23,
DDR4_SPD_MIN_CAS_LATENCY_TAAMIN = 24,
DDR4_SPD_MIN_RAS_CAS_DELAY_TRCDMIN = 25,
DDR4_SPD_MIN_ROW_PRECHARGE_DELAY_TRPMIN = 26,
DDR4_SPD_UPPER_NIBBLES_TRAS_TRC = 27,
DDR4_SPD_MIN_ACTIVE_PRECHARGE_LSB_TRASMIN = 28,
DDR4_SPD_MIN_ACTIVE_REFRESH_LSB_TRCMIN = 29,
DDR4_SPD_MIN_REFRESH_RECOVERY_LSB_TRFC1MIN = 30,
DDR4_SPD_MIN_REFRESH_RECOVERY_MSB_TRFC1MIN = 31,
DDR4_SPD_MIN_REFRESH_RECOVERY_LSB_TRFC2MIN = 32,
DDR4_SPD_MIN_REFRESH_RECOVERY_MSB_TRFC2MIN = 33,
DDR4_SPD_MIN_REFRESH_RECOVERY_LSB_TRFC4MIN = 34,
DDR4_SPD_MIN_REFRESH_RECOVERY_MSB_TRFC4MIN = 35,
DDR4_SPD_MIN_FOUR_ACTIVE_WINDOW_MSN_TFAWMIN = 36,
DDR4_SPD_MIN_FOUR_ACTIVE_WINDOW_LSB_TFAWMIN = 37,
DDR4_SPD_MIN_ROW_ACTIVE_DELAY_SAME_TRRD_SMIN = 38,
DDR4_SPD_MIN_ROW_ACTIVE_DELAY_DIFF_TRRD_LMIN = 39,
DDR4_SPD_MIN_CAS_TO_CAS_DELAY_TCCD_LMIN = 40,
DDR4_SPD_MIN_CAS_TO_CAS_DELAY_FINE_TCCD_LMIN = 117,
DDR4_SPD_MIN_ACT_TO_ACT_DELAY_SAME_FINE_TRRD_LMIN = 118,
DDR4_SPD_MIN_ACT_TO_ACT_DELAY_DIFF_FINE_TRRD_SMIN = 119,
DDR4_SPD_MIN_ACT_TO_ACT_REFRESH_DELAY_FINE_TRCMIN = 120,
DDR4_SPD_MIN_ROW_PRECHARGE_DELAY_FINE_TRPMIN = 121,
DDR4_SPD_MIN_RAS_TO_CAS_DELAY_FINE_TRCDMIN = 122,
DDR4_SPD_MIN_CAS_LATENCY_FINE_TAAMIN = 123,
DDR4_SPD_MAX_CYCLE_TIME_FINE_TCKAVGMAX = 124,
DDR4_SPD_MIN_CYCLE_TIME_FINE_TCKAVGMIN = 125,
DDR4_SPD_CYCLICAL_REDUNDANCY_CODE_LOWER_NIBBLE = 126,
DDR4_SPD_CYCLICAL_REDUNDANCY_CODE_UPPER_NIBBLE = 127,
DDR4_SPD_REFERENCE_RAW_CARD = 130,
DDR4_SPD_UDIMM_ADDR_MAPPING_FROM_EDGE = 131,
DDR4_SPD_REGISTER_MANUFACTURER_ID_LSB = 133,
DDR4_SPD_REGISTER_MANUFACTURER_ID_MSB = 134,
DDR4_SPD_REGISTER_REVISION_NUMBER = 135,
DDR4_SPD_RDIMM_ADDR_MAPPING_FROM_REGISTER_TO_DRAM = 136,
DDR4_SPD_RDIMM_REGISTER_DRIVE_STRENGTH_CTL = 137,
DDR4_SPD_RDIMM_REGISTER_DRIVE_STRENGTH_CK = 138,
DDR4_SPD_MODULE_SERIAL_NUMBER = 325,
DDR4_SPD_MODULE_PART_NUMBER = 329
} ddr4_spd_addr_t;
extern int read_entire_spd(bdk_node_t node, dram_config_t *cfg, int lmc, int dimm);
extern int read_spd(bdk_node_t node, const dimm_config_t *dimm_config, int spd_field);
extern int validate_dimm(bdk_node_t node, const dimm_config_t *dimm_config);
extern void report_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
int dimm, int ddr_interface_num, int num_ranks,
int dram_width, int dimm_size_mb);
extern int dram_get_default_spd_speed(bdk_node_t node, const ddr_configuration_t *ddr_config);
extern const char *ddr3_dimm_types[];
extern const char *ddr4_dimm_types[];

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,96 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* Small utility functions for use by libdram internally. These
* are not meant for users's of the libdram API.
*/
/**
* Standard min(a,b) macro
*/
#define min(X, Y) \
({ typeof (X) __x = (X); \
typeof (Y) __y = (Y); \
(__x < __y) ? __x : __y; })
/**
* Standard max(a,b) macro
*/
#define max(X, Y) \
({ typeof (X) __x = (X); typeof(Y) __y = (Y); \
(__x > __y) ? __x : __y; })
/**
* Absolute value of an integer
*
* @param v
*
* @return
*/
static inline int64_t _abs(int64_t v)
{
return (v < 0) ? -v : v;
}
/**
* Sign of an integer
*
* @param v
*
* @return
*/
static inline int64_t _sign(int64_t v)
{
return v < 0;
}
/**
* Divide and round results up to the next higher integer.
*
* @param dividend
* @param divisor
*
* @return
*/
static inline uint64_t divide_roundup(uint64_t dividend, uint64_t divisor)
{
return (dividend + divisor - 1) / divisor;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,124 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
extern const dimm_odt_config_t disable_odt_config[];
#define rttnom_none 0 /* Rtt_Nom disabled */
#define rttnom_60ohm 1 /* RZQ/4 = 240/4 = 60 ohms */
#define rttnom_120ohm 2 /* RZQ/2 = 240/2 = 120 ohms */
#define rttnom_40ohm 3 /* RZQ/6 = 240/6 = 40 ohms */
#define rttnom_20ohm 4 /* RZQ/12 = 240/12 = 20 ohms */
#define rttnom_30ohm 5 /* RZQ/8 = 240/8 = 30 ohms */
#define rttnom_rsrv1 6 /* Reserved */
#define rttnom_rsrv2 7 /* Reserved */
#define rttwr_none 0 /* Dynamic ODT off */
#define rttwr_60ohm 1 /* RZQ/4 = 240/4 = 60 ohms */
#define rttwr_120ohm 2 /* RZQ/2 = 240/2 = 120 ohms */
#define rttwr_rsrv1 3 /* Reserved */
#define dic_40ohm 0 /* RZQ/6 = 240/6 = 40 ohms */
#define dic_34ohm 1 /* RZQ/7 = 240/7 = 34 ohms */
#define driver_24_ohm 1
#define driver_27_ohm 2
#define driver_30_ohm 3
#define driver_34_ohm 4
#define driver_40_ohm 5
#define driver_48_ohm 6
#define driver_60_ohm 7
#define rodt_ctl_none 0
#define rodt_ctl_20_ohm 1
#define rodt_ctl_30_ohm 2
#define rodt_ctl_40_ohm 3
#define rodt_ctl_60_ohm 4
#define rodt_ctl_120_ohm 5
#define ddr4_rttnom_none 0 /* Rtt_Nom disabled */
#define ddr4_rttnom_60ohm 1 /* RZQ/4 = 240/4 = 60 ohms */
#define ddr4_rttnom_120ohm 2 /* RZQ/2 = 240/2 = 120 ohms */
#define ddr4_rttnom_40ohm 3 /* RZQ/6 = 240/6 = 40 ohms */
#define ddr4_rttnom_240ohm 4 /* RZQ/1 = 240/1 = 240 ohms */
#define ddr4_rttnom_48ohm 5 /* RZQ/5 = 240/5 = 48 ohms */
#define ddr4_rttnom_80ohm 6 /* RZQ/3 = 240/3 = 80 ohms */
#define ddr4_rttnom_34ohm 7 /* RZQ/7 = 240/7 = 34 ohms */
#define ddr4_rttwr_none 0 /* Dynamic ODT off */
#define ddr4_rttwr_120ohm 1 /* RZQ/2 = 240/2 = 120 ohms */
#define ddr4_rttwr_240ohm 2 /* RZQ/1 = 240/1 = 240 ohms */
#define ddr4_rttwr_HiZ 3 /* HiZ */
/* This setting will be available for cn78xx cn88xx pass 2 and cn73xx
pass 1. It is disabled for now. */
//#define ddr4_rttwr_80ohm 4 /* RZQ/3 = 240/3 = 80 ohms */
#define ddr4_dic_34ohm 0 /* RZQ/7 = 240/7 = 34 ohms */
#define ddr4_dic_48ohm 1 /* RZQ/5 = 240/5 = 48 ohms */
#define ddr4_rttpark_none 0 /* Rtt_Park disabled */
#define ddr4_rttpark_60ohm 1 /* RZQ/4 = 240/4 = 60 ohms */
#define ddr4_rttpark_120ohm 2 /* RZQ/2 = 240/2 = 120 ohms */
#define ddr4_rttpark_40ohm 3 /* RZQ/6 = 240/6 = 40 ohms */
#define ddr4_rttpark_240ohm 4 /* RZQ/1 = 240/1 = 240 ohms */
#define ddr4_rttpark_48ohm 5 /* RZQ/5 = 240/5 = 48 ohms */
#define ddr4_rttpark_80ohm 6 /* RZQ/3 = 240/3 = 80 ohms */
#define ddr4_rttpark_34ohm 7 /* RZQ/7 = 240/7 = 34 ohms */
#define ddr4_driver_26_ohm 2
#define ddr4_driver_30_ohm 3
#define ddr4_driver_34_ohm 4
#define ddr4_driver_40_ohm 5
#define ddr4_driver_48_ohm 6
#define ddr4_dqx_driver_24_ohm 1
#define ddr4_dqx_driver_27_ohm 2
#define ddr4_dqx_driver_30_ohm 3
#define ddr4_dqx_driver_34_ohm 4
#define ddr4_dqx_driver_40_ohm 5
#define ddr4_dqx_driver_48_ohm 6
#define ddr4_dqx_driver_60_ohm 7
#define ddr4_rodt_ctl_none 0
#define ddr4_rodt_ctl_40_ohm 1
#define ddr4_rodt_ctl_60_ohm 2
#define ddr4_rodt_ctl_80_ohm 3
#define ddr4_rodt_ctl_120_ohm 4
#define ddr4_rodt_ctl_240_ohm 5
#define ddr4_rodt_ctl_34_ohm 6
#define ddr4_rodt_ctl_48_ohm 7

View File

@ -0,0 +1,262 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
/**
* Load a "odt_*rank_config" structure
*
* @param cfg Config to fill
* @param ranks Number of ranks we're loading (1,2,4)
* @param node Node we're loading for
* @param dimm Which DIMM this is for
* @param lmc Which LMC this is for
*/
static void load_rank_data(dram_config_t *cfg, int ranks, int num_dimms, int lmc, bdk_node_t node)
{
/* Get a pointer to the structure we are filling */
dimm_odt_config_t *c;
switch (ranks)
{
case 1:
c = &cfg->config[lmc].odt_1rank_config[num_dimms - 1];
break;
case 2:
c = &cfg->config[lmc].odt_2rank_config[num_dimms - 1];
break;
case 4:
c = &cfg->config[lmc].odt_4rank_config[num_dimms - 1];
break;
default:
bdk_fatal("Unexpected number of ranks\n");
break;
}
/* Fill the global items */
c->odt_ena = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_DQX_CTL, ranks, num_dimms, lmc, node);
c->odt_mask = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_WODT_MASK, ranks, num_dimms, lmc, node);
/* Fill the per rank items */
int rank = 0;
c->odt_mask1.s.pasr_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.asr_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.srt_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_00_ext = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node) >> 2;
c->odt_mask1.s.dic_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_nom_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.db_output_impedance = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DB_OUTPUT_IMPEDANCE, ranks, num_dimms, lmc, node);
rank = 1;
c->odt_mask1.s.pasr_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.asr_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.srt_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_01_ext = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node) >> 2;
c->odt_mask1.s.dic_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_nom_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
rank = 2;
c->odt_mask1.s.pasr_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.asr_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.srt_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_10_ext = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node) >> 2;
c->odt_mask1.s.dic_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_nom_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
rank = 3;
c->odt_mask1.s.pasr_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_PASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.asr_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_ASR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.srt_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_SRT, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_wr_11_ext = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_WR, ranks, num_dimms, rank, lmc, node) >> 2;
c->odt_mask1.s.dic_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_DIC, ranks, num_dimms, rank, lmc, node);
c->odt_mask1.s.rtt_nom_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE1_RTT_NOM, ranks, num_dimms, rank, lmc, node);
rank = 0;
c->odt_mask2.s.rtt_park_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_value_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_range_00 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vrefdq_train_en = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREFDQ_TRAIN_EN, ranks, num_dimms, lmc, node);
rank = 1;
c->odt_mask2.s.rtt_park_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_value_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_range_01 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
rank = 2;
c->odt_mask2.s.rtt_park_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_value_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_range_10 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
rank = 3;
c->odt_mask2.s.rtt_park_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_RTT_PARK, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_value_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_VALUE, ranks, num_dimms, rank, lmc, node);
c->odt_mask2.s.vref_range_11 = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_MODE2_VREF_RANGE, ranks, num_dimms, rank, lmc, node);
/* Fill more global items */
c->qs_dic = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_RODT_CTL, ranks, num_dimms, lmc, node);
c->rodt_ctl = bdk_config_get_int(BDK_CONFIG_DDR_RANKS_RODT_MASK, ranks, num_dimms, lmc, node);
}
/**
* Load a DRAM configuration based on the current bdk-config settings
*
* @param node Node the DRAM config is for
*
* @return Pointer to __libdram_global_cfg, a global structure. Returns NULL if bdk-config
* lacks information about DRAM.
*/
const dram_config_t *libdram_config_load(bdk_node_t node)
{
dram_config_t *cfg = &__libdram_global_cfg;
const int MAX_LMCS = sizeof(cfg->config) / sizeof(cfg->config[0]);
/* Make all fields for the node default to zero */
memset(cfg, 0, sizeof(*cfg));
/* Fill the SPD data first as some parameters need to know the DRAM type
to lookup the correct values */
for (int lmc = 0; lmc < MAX_LMCS; lmc++)
{
for (int dimm = 0; dimm < DDR_CFG_T_MAX_DIMMS; dimm++)
{
int spd_addr = bdk_config_get_int(BDK_CONFIG_DDR_SPD_ADDR, dimm, lmc, node);
if (spd_addr)
{
cfg->config[lmc].dimm_config_table[dimm].spd_addr = spd_addr;
}
else
{
int spd_size;
const void *spd_data = bdk_config_get_blob(&spd_size, BDK_CONFIG_DDR_SPD_DATA, dimm, lmc, node);
if (spd_data && spd_size)
cfg->config[lmc].dimm_config_table[dimm].spd_ptr = spd_data;
}
}
}
/* Check that we know how to get DIMM inofmration. If not, return failure */
if (!cfg->config[0].dimm_config_table[0].spd_addr && !cfg->config[0].dimm_config_table[0].spd_ptr)
return NULL;
cfg->name = "Loaded from bdk-config";
for (int lmc = 0; lmc < MAX_LMCS; lmc++)
{
for (int num_dimms = 1; num_dimms <= DDR_CFG_T_MAX_DIMMS; num_dimms++)
{
load_rank_data(cfg, 1, num_dimms, lmc, node);
load_rank_data(cfg, 2, num_dimms, lmc, node);
load_rank_data(cfg, 4, num_dimms, lmc, node);
}
ddr_configuration_t *c = &cfg->config[lmc];
ddr3_custom_config_t *custom = &c->custom_lmc_config;
custom->min_rtt_nom_idx = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MIN_RTT_NOM_IDX, lmc, node);
custom->max_rtt_nom_idx = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MAX_RTT_NOM_IDX, lmc, node);
custom->min_rodt_ctl = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MIN_RODT_CTL, lmc, node);
custom->max_rodt_ctl = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MAX_RODT_CTL, lmc, node);
custom->ck_ctl = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_CK_CTL, lmc, node);
custom->cmd_ctl = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_CMD_CTL, lmc, node);
custom->ctl_ctl = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_CTL_CTL, lmc, node);
custom->min_cas_latency = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MIN_CAS_LATENCY, lmc, node);
custom->offset_en = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_OFFSET_EN, lmc, node);
custom->offset_udimm = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_OFFSET, "UDIMM", lmc, node);
custom->offset_rdimm = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_OFFSET, "RDIMM", lmc, node);
custom->rlevel_compute = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMPUTE, lmc, node);
custom->rlevel_comp_offset_udimm = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMP_OFFSET, "UDIMM", lmc, node);
custom->rlevel_comp_offset_rdimm = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_RLEVEL_COMP_OFFSET, "RDIMM", lmc, node);
custom->ddr2t_udimm = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DDR2T, "UDIMM", lmc, node);
custom->ddr2t_rdimm = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DDR2T, "RDIMM", lmc, node);
custom->disable_sequential_delay_check = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DISABLE_SEQUENTIAL_DELAY_CHECK, lmc, node);
custom->maximum_adjacent_rlevel_delay_increment
= bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MAXIMUM_ADJACENT_RLEVEL_DELAY_INCREMENT, lmc, node);
custom->parity = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_PARITY, lmc, node);
custom->fprch2 = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_FPRCH2, lmc, node);
custom->mode32b = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MODE32B, lmc, node);
custom->measured_vref = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_MEASURED_VREF, lmc, node);
/* CN80XX only supports 32bit mode */
if (cavium_is_altpkg(CAVIUM_CN81XX))
custom->mode32b = 1;
/* Loop through 8 bytes, plus ecc byte */
#define NUM_BYTES 9 /* Max bytes on LMC (8 plus ECC) */
static int8_t dll_write_offset[NUM_BYTES];
static int8_t dll_read_offset[NUM_BYTES];
for (int b = 0; b < NUM_BYTES; b++)
{
dll_write_offset[b] = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DLL_WRITE_OFFSET, b, lmc, node);
dll_read_offset[b] = bdk_config_get_int(BDK_CONFIG_DDR_CUSTOM_DLL_READ_OFFSET, b, lmc, node);
}
custom->dll_write_offset = dll_write_offset;
custom->dll_read_offset = dll_read_offset;
}
int is_ddr4 = (cfg->config[0].odt_1rank_config[0].odt_mask2.u != 0);
int speed = bdk_config_get_int(BDK_CONFIG_DDR_SPEED, node);
switch (speed)
{
case 0: // AUTO
cfg->ddr_clock_hertz = 0;
break;
case 800:
case 1600:
case 2400:
cfg->ddr_clock_hertz = (uint64_t)speed * 1000000 / 2;
break;
case 666:
cfg->ddr_clock_hertz = 333333333;
break;
case 1066:
cfg->ddr_clock_hertz = 533333333;
break;
case 1333:
cfg->ddr_clock_hertz = 666666666;
break;
case 1866:
if (is_ddr4)
cfg->ddr_clock_hertz = 940000000;
else
cfg->ddr_clock_hertz = 933333333;
break;
case 2133:
cfg->ddr_clock_hertz = 1050000000;
break;
default:
bdk_warn("Unsupported DRAM speed of %d MT/s\n", speed);
cfg->ddr_clock_hertz = speed * 1000000 / 2;
break;
}
return cfg;
};

View File

@ -0,0 +1,718 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include <bdk.h>
#include "libbdk-arch/bdk-csrs-mio_fus.h"
#include "dram-internal.h"
/* This global variable is accessed through dram_is_verbose() to determine
the verbosity level. Use that function instead of setting it directly */
dram_verbosity_t dram_verbosity = VBL_OFF; /* init this here so we could set a non-zero default */
static uint32_t measured_ddr_hertz[BDK_NUMA_MAX_NODES];
/* The various DRAM configs in the libdram/configs directory need space
to store the DRAM config. Since only one config is ever in active use
at a time, store the configs in __libdram_global_cfg. In a multi-node
setup, independent calls to get the DRAM config will load first node 0's
config, then node 1's */
dram_config_t __libdram_global_cfg;
static void bdk_dram_clear_mem(bdk_node_t node)
{
if (!bdk_is_platform(BDK_PLATFORM_ASIM)) {
uint64_t mbytes = bdk_dram_get_size_mbytes(node);
uint64_t skip = (node == bdk_numa_master()) ? bdk_dram_get_top_of_bdk() : 0;
uint64_t len = (mbytes << 20) - skip;
BDK_TRACE(DRAM, "N%d: Clearing DRAM\n", node);
if (skip)
{
/* All memory below skip may contain valid data, so we can't clear
it. We still need to make sure all cache lines in this area are
fully dirty so that ECC bits will be updated on store. A single
write to the cache line isn't good enough because partial LMC
writes may be enabled */
ddr_print("N%d: Rewriting DRAM: start 0 length 0x%lx\n", node, skip);
volatile uint64_t *ptr = bdk_phys_to_ptr(bdk_numa_get_address(node, 8));
/* The above pointer got address 8 to avoid NULL pointer checking
in bdk_phys_to_ptr(). Correct it here */
ptr--;
uint64_t *end = bdk_phys_to_ptr(bdk_numa_get_address(node, skip));
while (ptr < end)
{
*ptr = *ptr;
ptr++;
}
}
ddr_print("N%d: Clearing DRAM: start 0x%lx length 0x%lx\n", node, skip, len);
bdk_zero_memory(bdk_phys_to_ptr(bdk_numa_get_address(node, skip)), len);
BDK_TRACE(DRAM, "N%d: DRAM clear complete\n", node);
}
}
static void bdk_dram_clear_ecc(bdk_node_t node)
{
/* Clear any DRAM errors set during init */
BDK_TRACE(DRAM, "N%d: Clearing LMC ECC errors\n", node);
int num_lmc = __bdk_dram_get_num_lmc(node);
for (int lmc = 0; lmc < num_lmc; lmc++) {
DRAM_CSR_WRITE(node, BDK_LMCX_INT(lmc), BDK_CSR_READ(node, BDK_LMCX_INT(lmc)));
}
}
static void bdk_dram_enable_ecc_reporting(bdk_node_t node)
{
/* Enable LMC ECC error HW reporting */
int num_lmc = __bdk_dram_get_num_lmc(node);
BDK_TRACE(DRAM, "N%d: Enable LMC ECC error reporting\n", node);
for (int lmc = 0; lmc < num_lmc; lmc++) {
// NOTE: this must be done for pass 2.x
// enable ECC interrupts to allow ECC error info in LMCX_INT
if (! CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X)) { // added 81xx and 83xx
DRAM_CSR_WRITE(node, BDK_LMCX_INT_ENA_W1S(lmc), -1ULL);
BDK_CSR_INIT(lmc_int_ena_w1s, node, BDK_LMCX_INT_ENA_W1S(lmc));
ddr_print("N%d.LMC%d: %-36s : 0x%08lx\n",
node, lmc, "LMC_INT_ENA_W1S", lmc_int_ena_w1s.u);
}
}
}
static void bdk_dram_disable_ecc_reporting(bdk_node_t node)
{
/* Disable LMC ECC error HW reporting */
int num_lmc = __bdk_dram_get_num_lmc(node);
BDK_TRACE(DRAM, "N%d: Disable LMC ECC error reporting\n", node);
for (int lmc = 0; lmc < num_lmc; lmc++) {
// NOTE: this must be done for pass 2.x
// disable ECC interrupts to prevent ECC error info in LMCX_INT
if (! CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X)) { // added 81xx and 83xx
DRAM_CSR_WRITE(node, BDK_LMCX_INT_ENA_W1C(lmc), -1ULL);
BDK_CSR_INIT(lmc_int_ena_w1c, node, BDK_LMCX_INT_ENA_W1C(lmc));
ddr_print("N%d.LMC%d: %-36s : 0x%08lx\n",
node, lmc, "LMC_INT_ENA_W1C", lmc_int_ena_w1c.u);
}
}
}
// this routine simply makes the calls to the tuning routines and returns any errors
static int bdk_libdram_tune_node(int node)
{
int errs, tot_errs;
int do_dllro_hw = 0; // default to NO
int do_dllwo = 0; // default to NO
int do_eccdll = 0; // default to NO
const char *str;
BDK_CSR_INIT(lmc_config, node, BDK_LMCX_CONFIG(0)); // FIXME: probe LMC0
do_eccdll = (lmc_config.s.ecc_ena != 0); // change to ON if ECC enabled
// FIXME!!! make 81xx always use HW-assist tuning
if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
do_dllro_hw = 1;
// Automatically tune the data byte DLL read offsets
// always done by default, but allow use of HW-assist
// NOTE: HW-assist will also tune the ECC byte
str = getenv("ddr_tune_hw_offsets");
if (str)
do_dllro_hw = !!strtoul(str, NULL, 0);
BDK_TRACE(DRAM, "N%d: Starting DLL Read Offset Tuning for LMCs\n", node);
if (!do_dllro_hw || (lmc_config.s.mode32b != 0)) {
errs = perform_dll_offset_tuning(node, 2, /* tune */1);
} else {
errs = perform_HW_dll_offset_tuning(node, /* read */2, 0x0A/* all bytelanes */);
}
BDK_TRACE(DRAM, "N%d: Finished DLL Read Offset Tuning for LMCs, %d errors)\n",
node, errs);
tot_errs = errs;
// disabled by default for now, does not seem to be needed?
// Automatically tune the data byte DLL write offsets
// allow override of default setting
str = getenv("ddr_tune_write_offsets");
if (str)
do_dllwo = !!strtoul(str, NULL, 0);
if (do_dllwo) {
BDK_TRACE(DRAM, "N%d: Starting DLL Write Offset Tuning for LMCs\n", node);
errs = perform_dll_offset_tuning(node, /* write */1, /* tune */1);
BDK_TRACE(DRAM, "N%d: Finished DLL Write Offset Tuning for LMCs, %d errors)\n",
node, errs);
tot_errs += errs;
}
// disabled by default for now, does not seem to be needed much?
// Automatically tune the ECC byte DLL read offsets
// FIXME? allow override of the filtering
// FIXME? allow programmatic override, not via envvar?
str = getenv("ddr_tune_ecc_enable");
if (str)
do_eccdll = !!strtoul(str, NULL, 10);
if (do_eccdll && !do_dllro_hw && (lmc_config.s.mode32b == 0)) { // do not do HW-assist twice for ECC
BDK_TRACE(DRAM, "N%d: Starting ECC DLL Read Offset Tuning for LMCs\n", node);
errs = perform_HW_dll_offset_tuning(node, 2, 8/* ECC bytelane */);
BDK_TRACE(DRAM, "N%d: Finished ECC DLL Read Offset Tuning for LMCs, %d errors\n",
node, errs);
tot_errs += errs;
}
return tot_errs;
}
// this routine makes the calls to the tuning routines when criteria are met
// intended to be called for automated tuning, to apply filtering...
#define IS_DDR4 1
#define IS_DDR3 0
#define IS_RDIMM 1
#define IS_UDIMM 0
#define IS_1SLOT 1
#define IS_2SLOT 0
// FIXME: DDR3 is not tuned
static const uint32_t ddr_speed_filter[2][2][2] = {
[IS_DDR4] = {
[IS_RDIMM] = {
[IS_1SLOT] = 940,
[IS_2SLOT] = 800
},
[IS_UDIMM] = {
[IS_1SLOT] = 1050,
[IS_2SLOT] = 940
},
},
[IS_DDR3] = {
[IS_RDIMM] = {
[IS_1SLOT] = 0, // disabled
[IS_2SLOT] = 0 // disabled
},
[IS_UDIMM] = {
[IS_1SLOT] = 0, // disabled
[IS_2SLOT] = 0 // disabled
}
}
};
static int bdk_libdram_maybe_tune_node(int node)
{
const char *str;
// FIXME: allow an override here so that all configs can be tuned or none
// If the envvar is defined, always either force it or avoid it accordingly
if ((str = getenv("ddr_tune_all_configs")) != NULL) {
int tune_it = !!strtoul(str, NULL, 0);
printf("N%d: DRAM auto-tuning %s.\n", node, (tune_it) ? "forced" : "avoided");
return (tune_it) ? bdk_libdram_tune_node(node) : 0;
}
// filter the tuning calls here...
// determine if we should/can run automatically for this configuration
//
// FIXME: tune only when the configuration indicates it will help:
// DDR type, RDIMM or UDIMM, 1-slot or 2-slot, and speed
//
uint32_t ddr_speed = divide_nint(libdram_get_freq_from_pll(node, 0), 1000000); // sample LMC0
BDK_CSR_INIT(lmc_config, node, BDK_LMCX_CONFIG(0)); // sample LMC0
int is_ddr4 = !!__bdk_dram_is_ddr4(node, 0);
int is_rdimm = !!__bdk_dram_is_rdimm(node, 0);
int is_1slot = !!(lmc_config.s.init_status < 4); // HACK, should do better
int do_tune = 0;
uint32_t ddr_min_speed = ddr_speed_filter[is_ddr4][is_rdimm][is_1slot];
do_tune = (ddr_min_speed && (ddr_speed > ddr_min_speed));
ddr_print("N%d: DDR%d %cDIMM %d-slot at %d MHz %s eligible for auto-tuning.\n",
node, (is_ddr4)?4:3, (is_rdimm)?'R':'U', (is_1slot)?1:2,
ddr_speed, (do_tune)?"is":"is not");
// call the tuning routines, done filtering...
return ((do_tune) ? bdk_libdram_tune_node(node) : 0);
}
/**
* This is the main DRAM init function. Users of libdram should call this function,
* avoiding the other internal function. As a rule, functions starting with
* "libdram_*" are part of the external API and should be used.
*
* @param node Node to initialize. This may not be the same node as the one running the code
* @param dram_config
* DRAM configuration to use
* @param ddr_clock_override
* If non-zeo, this overrides the DRAM clock speed in the config structure. This
* allows quickly testing of different DRAM speeds without modifying the basic
* config. If zero, the DRAM speed in the config is used.
*
* @return Amount of memory in MB. Zero or negative is a failure.
*/
int libdram_config(int node, const dram_config_t *dram_config, int ddr_clock_override)
{
if (bdk_is_platform(BDK_PLATFORM_ASIM))
return bdk_dram_get_size_mbytes(node);
/* Boards may need to mux the TWSI connection between THUNDERX and the BMC.
This allows the BMC to monitor DIMM temeratures and health */
int gpio_select = bdk_config_get_int(BDK_CONFIG_DRAM_CONFIG_GPIO);
if (gpio_select != -1)
bdk_gpio_initialize(bdk_numa_master(), gpio_select, 1, 1);
/* Read all the SPDs and store them in the device tree. They are needed by
later software to populate SMBIOS information */
for (int lmc = 0; lmc < 4; lmc++)
for (int dimm = 0; dimm < DDR_CFG_T_MAX_DIMMS; dimm++)
read_entire_spd(node, (dram_config_t *)dram_config, lmc, dimm);
const ddr_configuration_t *ddr_config = dram_config->config;
int ddr_clock_hertz = (ddr_clock_override) ? ddr_clock_override : dram_config->ddr_clock_hertz;
if (ddr_clock_hertz == 0) // 0 == AUTO
{
ddr_clock_hertz = dram_get_default_spd_speed(node, ddr_config);
if (ddr_clock_hertz < 0) {
printf("N%d: DRAM init: AUTO clock ILLEGAL configuration\n", node);
return -1;
}
}
int errs;
// At this point, we only know the desired clock rate (ddr_clock_hertz).
// We do not know whether we are configuring RDIMMs.
// We also do not yet know if 100MHz alternate refclk is actually available.
// so, if we are being asked for 2133MT/s or better, we still need to do:
// 1. probe for RDIMMs (if not, 50MHz refclk is good enough)
// 2. determine if 100MHz refclk is there, and switch to it before starting any configuration
//
// NOTES:
// 1. dclk_alt_refclk_sel need only be set on LMC0 (see above disabled code)
// 2. I think we need to first probe to see if we need it, and configure it then if dictated use
// 3. then go on to configure at the selected refclk
int ddr_refclk_hertz = bdk_clock_get_rate(node, BDK_CLOCK_MAIN_REF);
int alt_refclk = bdk_config_get_int(BDK_CONFIG_DDR_ALT_REFCLK, node);
char *str = getenv("ddr_100mhz_refclk");
if (str) { // if the envvar was found, force it to that setting
int do_100mhz = !!strtoul(str, NULL, 0);
alt_refclk = (do_100mhz) ? 100 : 50;
}
dram_verbosity = bdk_config_get_int(BDK_CONFIG_DRAM_VERBOSE);
// Here we check for fuses that limit the number of LMCs we can configure,
// but only on 83XX and 88XX...
int lmc_limit = 4;
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX) || CAVIUM_IS_MODEL(CAVIUM_CN83XX)) {
BDK_CSR_INIT(mio_fus_dat2, node, BDK_MIO_FUS_DAT2);
if (mio_fus_dat2.s.lmc_half) {
lmc_limit = (CAVIUM_IS_MODEL(CAVIUM_CN88XX)) ? 2 : 1; // limit LMCs to half present
error_print("Only %d LMC(s)s supported for this Thunder model\n", lmc_limit);
}
}
/* We need to calculate the interface mask based on the provided SPD
addresses/contents */
uint32_t interface_mask = 0;
for (int i = 0; i < lmc_limit; i++)
{
// We need to check only DIMM 0 of each LMC for possible presence of the LMC.
// This trusts that the board database is correctly configured.
// Empty DIMM slots in present LMCs will be detected later.
if (ddr_config[i].dimm_config_table[0].spd_addr ||
ddr_config[i].dimm_config_table[0].spd_ptr)
interface_mask |= 1 << i;
// we know whether alternate refclk is always wanted
// we also know already if we want 2133 MT/s
// if alt refclk not always wanted, then probe DDR and DIMM type
// if DDR4 and RDIMMs, then set desired refclk to 100MHz, otherwise to default (50MHz)
// depend on ddr_initialize() to do the refclk selection and validation
if (i == 0) { // only check for LMC0
if (alt_refclk) { // if alternate refclk was specified, let it override everything
ddr_refclk_hertz = alt_refclk * 1000000;
ddr_print("N%d: DRAM init: %d MHz refclk is REQUESTED ALWAYS\n", node, alt_refclk);
} else if (ddr_clock_hertz > 1000000000) { // if more than 2000 MT/s
int ddr_type = get_ddr_type(node, &ddr_config[0].dimm_config_table[0]);
int spd_dimm_type = get_dimm_module_type(node, &ddr_config[0].dimm_config_table[0], ddr_type);
// is DDR4 and RDIMM just to be sure
if ((ddr_type == DDR4_DRAM) &&
((spd_dimm_type == 1) || (spd_dimm_type == 5) || (spd_dimm_type == 8))) {
ddr_refclk_hertz = 100000000; // yes, we require 100MHz refclk, so set it
ddr_print("N%d: DRAM init: 100 MHz refclk is REQUIRED\n", node);
}
} // if (ddr_clock_hertz > 1000000000)
} // if (i == 0)
}
BDK_TRACE(DRAM, "N%d: DRAM init started (hertz=%d, refclk=%d, config=%p)\n",
node, ddr_clock_hertz, ddr_refclk_hertz, dram_config);
debug_print("N%d: DRAM init started (hertz=%d, refclk=%d, config=%p)\n",
node, ddr_clock_hertz, ddr_refclk_hertz, dram_config);
BDK_TRACE(DRAM, "N%d: Calling DRAM init\n", node);
measured_ddr_hertz[node] = 0;
int mbytes = octeon_ddr_initialize(node,
bdk_clock_get_rate(node, BDK_CLOCK_RCLK),
ddr_clock_hertz,
ddr_refclk_hertz,
interface_mask,
ddr_config,
&measured_ddr_hertz[node],
0,
0,
0);
BDK_TRACE(DRAM, "N%d: DRAM init returned %d, measured %u Hz\n",
node, mbytes, measured_ddr_hertz[node]);
// do not tune or mess with memory if there was an init problem...
if (mbytes > 0) {
bdk_dram_disable_ecc_reporting(node);
// call the tuning routines, with filtering...
BDK_TRACE(DRAM, "N%d: Calling DRAM tuning\n", node);
errs = bdk_libdram_maybe_tune_node(node);
BDK_TRACE(DRAM, "N%d: DRAM tuning returned %d errors\n",
node, errs);
// finally, clear memory and any left-over ECC errors
bdk_dram_clear_mem(node);
bdk_dram_clear_ecc(node);
bdk_dram_enable_ecc_reporting(node);
}
/* Boards may need to mux the TWSI connection between THUNDERX and the BMC.
This allows the BMC to monitor DIMM temeratures and health */
if (gpio_select != -1)
bdk_gpio_initialize(bdk_numa_master(), gpio_select, 1, 0);
return mbytes;
}
/**
* This is the main DRAM tuning function. Users of libdram should call this function,
* avoiding the other internal function. As a rule, functions starting with
* "libdram_*" are part of the external API and should be used.
*
* @param node Node to tune. This may not be the same node as the one running the code
*
* @return Success or Fail
*/
int libdram_tune(int node)
{
int tot_errs;
int l2c_is_locked = bdk_l2c_is_locked(node);
dram_verbosity = bdk_config_get_int(BDK_CONFIG_DRAM_VERBOSE);
// the only way this entry point should be called is from a MENU item,
// so, enable any non-running cores on this node, and leave them
// running at the end...
ddr_print("N%d: %s: Starting cores (mask was 0x%lx)\n",
node, __FUNCTION__, bdk_get_running_coremask(node));
bdk_init_cores(node, ~0ULL);
// must test for L2C locked here, cannot go on with it unlocked
// FIXME: but we only need to worry about Node 0???
if (node == 0) {
if (!l2c_is_locked) { // is unlocked, must lock it now
ddr_print("N%d: %s: L2C was unlocked - locking it now\n", node, __FUNCTION__);
// FIXME: this should be common-ized; it currently matches bdk_init()...
bdk_l2c_lock_mem_region(node, 0, bdk_l2c_get_cache_size_bytes(node) * 3 / 4);
} else {
ddr_print("N%d: %s: L2C was already locked - continuing\n", node, __FUNCTION__);
}
} else {
ddr_print("N%d: %s: non-zero node, not worrying about L2C lock status\n", node, __FUNCTION__);
}
// call the tuning routines, no filtering...
tot_errs = bdk_libdram_tune_node(node);
// FIXME: only for node 0, unlock L2C if it was unlocked before...
if (node == 0) {
if (!l2c_is_locked) { // it was Node 0 and unlocked, must re-unlock it now
ddr_print("N%d: Node 0 L2C was unlocked before - unlocking it now\n", node);
// FIXME: this should be common-ized; it currently matches bdk_init()...
bdk_l2c_unlock_mem_region(node, 0, bdk_l2c_get_cache_size_bytes(node) * 3 / 4);
} else {
ddr_print("N%d: %s: L2C was already locked - leaving it locked\n", node, __FUNCTION__);
}
} else {
ddr_print("N%d: %s: non-zero node, not worrying about L2C lock status\n", node, __FUNCTION__);
}
// make sure to clear memory and any ECC errs when done...
bdk_dram_clear_mem(node);
bdk_dram_clear_ecc(node);
return tot_errs;
}
/**
* This is the main function for DRAM margining of Write Voltage.
* Users of libdram should call this function,
* avoiding the other internal function. As a rule, functions starting with
* "libdram_*" are part of the external API and should be used.
*
* @param node Node to test. This may not be the same node as the one running the code
*
* @return Success or Fail
*/
static
int libdram_margin_write_voltage(int node)
{
int tot_errs;
// call the margining routine
tot_errs = perform_margin_write_voltage(node);
// make sure to clear memory and any ECC errs when done...
bdk_dram_clear_mem(node);
bdk_dram_clear_ecc(node);
return tot_errs;
}
/**
* This is the main function for DRAM margining of Read Voltage.
* Users of libdram should call this function,
* avoiding the other internal function. As a rule, functions starting with
* "libdram_*" are part of the external API and should be used.
*
* @param node Node to test. This may not be the same node as the one running the code
*
* @return Success or Fail
*/
static
int libdram_margin_read_voltage(int node)
{
int tot_errs;
// call the margining routine
tot_errs = perform_margin_read_voltage(node);
// make sure to clear memory and any ECC errs when done...
bdk_dram_clear_mem(node);
bdk_dram_clear_ecc(node);
return tot_errs;
}
/**
* This is the main function for DRAM margining of Write Timing.
* Users of libdram should call this function,
* avoiding the other internal function. As a rule, functions starting with
* "libdram_*" are part of the external API and should be used.
*
* @param node Node to test. This may not be the same node as the one running the code
*
* @return Success or Fail
*/
static
int libdram_margin_write_timing(int node)
{
int tot_errs;
// call the tuning routine, tell it we are margining not tuning...
tot_errs = perform_dll_offset_tuning(node, /* write offsets */1, /* margin */0);
// make sure to clear memory and any ECC errs when done...
bdk_dram_clear_mem(node);
bdk_dram_clear_ecc(node);
return tot_errs;
}
/**
* This is the main function for DRAM margining of Read Timing.
* Users of libdram should call this function,
* avoiding the other internal function. As a rule, functions starting with
* "libdram_*" are part of the external API and should be used.
*
* @param node Node to test. This may not be the same node as the one running the code
*
* @return Success or Fail
*/
static
int libdram_margin_read_timing(int node)
{
int tot_errs;
// call the tuning routine, tell it we are margining not tuning...
tot_errs = perform_dll_offset_tuning(node, /* read offsets */2, /* margin */0);
// make sure to clear memory and any ECC errs when done...
bdk_dram_clear_mem(node);
bdk_dram_clear_ecc(node);
return tot_errs;
}
/**
* This is the main function for all DRAM margining.
* Users of libdram should call this function,
* avoiding the other internal function. As a rule, functions starting with
* "libdram_*" are part of the external API and should be used.
*
* @param node Node to test. This may not be the same node as the one running the code
*
* @return Success or Fail
*/
int libdram_margin(int node)
{
int ret_rt, ret_wt, ret_rv, ret_wv;
char *risk[2] = { "Low Risk", "Needs Review" };
int l2c_is_locked = bdk_l2c_is_locked(node);
// for now, no margining on 81xx, until we can reduce the dynamic runtime size...
if (CAVIUM_IS_MODEL(CAVIUM_CN81XX)) {
printf("Sorry, margining is not available on 81xx yet...\n");
return 0;
}
dram_verbosity = bdk_config_get_int(BDK_CONFIG_DRAM_VERBOSE);
// the only way this entry point should be called is from a MENU item,
// so, enable any non-running cores on this node, and leave them
// running at the end...
ddr_print("N%d: %s: Starting cores (mask was 0x%lx)\n",
node, __FUNCTION__, bdk_get_running_coremask(node));
bdk_init_cores(node, ~0ULL);
// must test for L2C locked here, cannot go on with it unlocked
// FIXME: but we only need to worry about Node 0???
if (node == 0) {
if (!l2c_is_locked) { // is unlocked, must lock it now
ddr_print("N%d: %s: L2C was unlocked - locking it now\n", node, __FUNCTION__);
// FIXME: this should be common-ized; it currently matches bdk_init()...
bdk_l2c_lock_mem_region(node, 0, bdk_l2c_get_cache_size_bytes(node) * 3 / 4);
} else {
ddr_print("N%d: %s: L2C was already locked - continuing\n", node, __FUNCTION__);
}
} else {
ddr_print("N%d: %s: non-zero node, not worrying about L2C lock status\n", node, __FUNCTION__);
}
debug_print("N%d: Starting DRAM Margin ALL\n", node);
ret_rt = libdram_margin_read_timing(node);
ret_wt = libdram_margin_write_timing(node);
ret_rv = libdram_margin_read_voltage(node);
ret_wv = libdram_margin_write_voltage(node);
debug_print("N%d: DRAM Margin ALL finished\n", node);
/*
>>> Summary from DDR Margining tool:
>>> N0: Read Timing Margin : Low Risk
>>> N0: Write Timing Margin : Low Risk
>>> N0: Read Voltage Margin : Low Risk
>>> N0: Write Voltage Margin : Low Risk
*/
printf(" \n");
printf("-------------------------------------\n");
printf(" \n");
printf("Summary from DDR Margining tool\n");
printf("N%d: Read Timing Margin : %s\n", node, risk[!!ret_rt]);
printf("N%d: Write Timing Margin : %s\n", node, risk[!!ret_wt]);
// these may not have been done due to DDR3 and/or THUNDER pass 1.x
// FIXME? would it be better to print an appropriate message here?
if (ret_rv != -1) printf("N%d: Read Voltage Margin : %s\n", node, risk[!!ret_rv]);
if (ret_wv != -1) printf("N%d: Write Voltage Margin : %s\n", node, risk[!!ret_wv]);
printf(" \n");
printf("-------------------------------------\n");
printf(" \n");
// FIXME: only for node 0, unlock L2C if it was unlocked before...
if (node == 0) {
if (!l2c_is_locked) { // it was Node 0 and unlocked, must re-unlock it now
ddr_print("N%d: Node 0 L2C was unlocked before - unlocking it now\n", node);
// FIXME: this should be common-ized; it currently matches bdk_init()...
bdk_l2c_unlock_mem_region(node, 0, bdk_l2c_get_cache_size_bytes(node) * 3 / 4);
} else {
ddr_print("N%d: %s: L2C was already locked - leaving it locked\n", node, __FUNCTION__);
}
} else {
ddr_print("N%d: %s: non-zero node, not worrying about L2C lock status\n", node, __FUNCTION__);
}
return 0;
}
/**
* Get the measured DRAM frequency after a call to libdram_config
*
* @param node Node to get frequency for
*
* @return Frequency in Hz
*/
uint32_t libdram_get_freq(int node)
{
return measured_ddr_hertz[node];
}
/**
* Get the measured DRAM frequency from the DDR_PLL_CTL CSR
*
* @param node Node to get frequency for
*
* @return Frequency in Hz
*/
uint32_t libdram_get_freq_from_pll(int node, int lmc)
{
static const uint8_t _en[] = {1, 2, 3, 4, 5, 6, 7, 8, 10, 12};
BDK_CSR_INIT(c, node, BDK_LMCX_DDR_PLL_CTL(0));
// we check the alternate refclk select bit in LMC0 to indicate 100MHz use
// assumption: the alternate refclk is setup for 100MHz
uint64_t ddr_ref_hertz = (c.s.dclk_alt_refclk_sel) ? 100000000 : bdk_clock_get_rate(node, BDK_CLOCK_MAIN_REF);
uint64_t en = _en[c.cn83xx.ddr_ps_en];
uint64_t calculated_ddr_hertz = ddr_ref_hertz * (c.cn83xx.clkf + 1) / ((c.cn83xx.clkr + 1) * en);
return calculated_ddr_hertz;
}
#ifndef DRAM_CSR_WRITE_INLINE
void dram_csr_write(bdk_node_t node, const char *csr_name, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value)
{
VB_PRT(VBL_CSRS, "N%d: DDR Config %s[%016lx] => %016lx\n", node, csr_name, address, value);
bdk_csr_write(node, type, busnum, size, address, value);
}
#endif

View File

@ -0,0 +1,80 @@
#ifndef __BDK_H__
#define __BDK_H__
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Master include file for all BDK function.
*
* <hr>$Revision: 49448 $<hr>
*/
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include "../libbdk-arch/bdk-arch.h"
#include "../libbdk-os/bdk-os.h"
#include "../libfatfs/ff.h"
#include "../libfatfs/diskio.h"
#ifndef BDK_BUILD_HOST
#include "../libbdk-hal/bdk-hal.h"
#include "../libbdk-boot/bdk-boot.h"
#include "../libbdk-dram/bdk-dram.h"
#include "../libbdk-driver/bdk-driver.h"
#include "../libbdk-trust/bdk-trust.h"
#include "../libdram/libdram.h"
#include "bdk-functions.h"
#endif
#include "../libbdk-lua/bdk-lua.h"
#include "../libbdk-bist/bist.h"
/**
* @mainpage
*
* This document goes through the internal details of the BDK. Its purpose is
* to serve as a API reference for people writing applications. Users of the
* BDK's binary applications do not need these details.
*/
#endif

View File

@ -0,0 +1,85 @@
#ifndef __BDK_ARCH_H__
#define __BDK_ARCH_H__
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Master include file for architecture support. Use bdk.h
* instead of including this file directly.
*
* <hr>$Revision: 49448 $<hr>
*/
#ifndef __BYTE_ORDER
#if !defined(__ORDER_BIG_ENDIAN__) || !defined(__ORDER_LITTLE_ENDIAN__) || !defined(__BYTE_ORDER__)
#error Unable to determine Endian mode
#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define __BYTE_ORDER __ORDER_BIG_ENDIAN__
#define BDK_LITTLE_ENDIAN_STRUCT __attribute__ ((scalar_storage_order("little-endian")))
#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define __BYTE_ORDER __ORDER_LITTLE_ENDIAN__
#define BDK_LITTLE_ENDIAN_STRUCT
#else
#error Unable to determine Endian mode
#endif
#define __BIG_ENDIAN __ORDER_BIG_ENDIAN__
#define __LITTLE_ENDIAN __ORDER_LITTLE_ENDIAN__
#endif
#include "bdk-require.h"
#include "bdk-swap.h"
#ifndef BDK_BUILD_HOST
#include "bdk-asm.h"
#endif
#include "bdk-model.h"
#include "bdk-numa.h"
#include "bdk-csr.h"
#ifndef BDK_BUILD_HOST
#include "bdk-lmt.h"
#endif
#include "bdk-warn.h"
#include "bdk-version.h"
#ifndef BDK_BUILD_HOST
#include "bdk-fuse.h"
#include "bdk-platform.h"
#endif
#endif

View File

@ -0,0 +1,94 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* This is file defines ASM primitives for the executive.
* <hr>$Revision: 53373 $<hr>
*
* @defgroup asm Assembly support
* @{
*/
/* This header file can be included from a .S file. Keep non-preprocessor
things under !__ASSEMBLER__. */
#ifndef __ASSEMBLER__
/* turn the variable name into a string */
#define __BDK_TMP_STR(x) __BDK_TMP_STR2(x)
#define __BDK_TMP_STR2(x) #x
#define __BDK_VASTR(...) #__VA_ARGS__
#define BDK_MRS_NV(reg, val) asm ("mrs %x[rd]," #reg : [rd] "=r" (val))
#define BDK_MRS(reg, val) asm volatile ("mrs %x[rd]," #reg : [rd] "=r" (val))
#define BDK_MSR(reg, val) asm volatile ("msr " #reg ",%x[rd]" : : [rd] "r" (val))
/* other useful stuff */
#define BDK_MB asm volatile ("dmb sy" : : :"memory") /* Full memory barrier, like MIPS SYNC */
#define BDK_WMB asm volatile ("dmb st" : : :"memory") /* Write memory barreir, like MIPS SYNCW */
#define BDK_WFE asm volatile ("wfe" : : :"memory") /* Wait for event */
#define BDK_SEV asm volatile ("sev" : : :"memory") /* Send global event */
#define BDK_DSB asm volatile ("dsb sy" : : :"memory") /* DSB */
// normal prefetches that use the pref instruction
#define BDK_PREFETCH_PREFX(type, address, offset) asm volatile ("PRFUM " type ", [%[rbase],%[off]]" : : [rbase] "r" (address), [off] "I" (offset))
// a normal prefetch
#define BDK_PREFETCH(address, offset) BDK_PREFETCH_PREFX("PLDL1KEEP", address, offset)
#define BDK_ICACHE_INVALIDATE { asm volatile ("ic iallu" : : ); } // invalidate entire icache
#define BDK_SYS_CVMCACHE_WBI_L2 "#0,c11,c1,#2" // L2 Cache Cache Hit Writeback Invalidate
#define BDK_SYS_CVMCACHE_WB_L2 "#0,c11,c1,#3" // L2 Cache Hit Writeback
#define BDK_SYS_CVMCACHE_LCK_L2 "#0,c11,c1,#4" // L2 Cache Fetch and Lock
#define BDK_SYS_CVMCACHE_WBI_L2_INDEXED "#0,c11,c0,#5" // L2 Cache Index Writeback Invalidate
#define BDK_SYS_CVMCACHE_LTG_L2_INDEXED "#0,c11,c0,#7" // L2 Cache Index Load Tag
#define BDK_SYS_CVMCACHE_INVALL_DC "#0,c11,c0,#2" // L1 Dcache Invalidate
#define BDK_CACHE_WBI_L2(address) { asm volatile ("sys " BDK_SYS_CVMCACHE_WBI_L2 ", %0" : : "r" (address)); } // Push to memory, invalidate, and unlock
#define BDK_CACHE_WBI_L2_INDEXED(encoded) { asm volatile ("sys " BDK_SYS_CVMCACHE_WBI_L2_INDEXED ", %0" : : "r" (encoded)); } // Push to memory, invalidate, and unlock, index by set/way
#define BDK_CACHE_WB_L2(address) { asm volatile ("sys " BDK_SYS_CVMCACHE_WB_L2 ", %0" : : "r" (address)); } // Push to memory, don't invalidate, don't unlock
#define BDK_CACHE_LCK_L2(address) { asm volatile ("sys " BDK_SYS_CVMCACHE_LCK_L2 ", %0" : : "r" (address)); } // Lock into L2
#define BDK_DCACHE_INVALIDATE { asm volatile ("sys " BDK_SYS_CVMCACHE_INVALL_DC ", xzr"); } // Invalidate the entire Dcache on local core
#define BDK_CACHE_LTG_L2_INDEXED(encoded) { asm volatile ("sys " BDK_SYS_CVMCACHE_LTG_L2_INDEXED ", %0" : : "r" (encoded)); } // Load L2 TAG, index by set/way
#define BDK_STORE_PAIR(ptr, data1, data2) { asm volatile ("stp %x[d1], %x[d2], [%[b]]" : [mem] "+m" (*(__uint128_t*)ptr) : [b] "r" (ptr), [d1] "r" (data1), [d2] "r" (data2)); }
#endif /* __ASSEMBLER__ */
/** @} */

View File

@ -0,0 +1,324 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions and macros for accessing Cavium CSRs.
*
* <hr>$Revision: 49448 $<hr>
*
* @defgroup csr CSR support
* @{
*/
/**
* Possible CSR bus types
*/
typedef enum {
BDK_CSR_TYPE_DAB, /**< External debug 64bit CSR */
BDK_CSR_TYPE_DAB32b, /**< External debug 32bit CSR */
BDK_CSR_TYPE_MDSB, /**< CN93XX: Memory Diagnostic Serial Bus?, not memory mapped */
BDK_CSR_TYPE_NCB, /**< Fast 64bit CSR */
BDK_CSR_TYPE_NCB32b, /**< Fast 32bit CSR */
BDK_CSR_TYPE_PCCBR,
BDK_CSR_TYPE_PCCPF,
BDK_CSR_TYPE_PCCVF,
BDK_CSR_TYPE_PCICONFIGRC, /**< PCIe config address (RC mode) */
BDK_CSR_TYPE_PCICONFIGEP, /**< PCIe config address (EP mode) */
BDK_CSR_TYPE_PCICONFIGEP_SHADOW, /**< CN93XX: PCIEP register invisible to host, not memory mapped */
BDK_CSR_TYPE_PCICONFIGEPVF, /**< CN93XX: PCIEP registers only on vertain PEMs, not memory mapped */
BDK_CSR_TYPE_PEXP, /**< PCIe BAR 0 address only */
BDK_CSR_TYPE_PEXP_NCB, /**< NCB-direct and PCIe BAR0 address */
BDK_CSR_TYPE_RSL, /**< Slow 64bit CSR */
BDK_CSR_TYPE_RSL32b, /**< Slow 32bit CSR */
BDK_CSR_TYPE_RVU_PF_BAR0, /**< Index into RVU PF BAR0 */
BDK_CSR_TYPE_RVU_PF_BAR2, /**< Index into RVU PF BAR2 */
BDK_CSR_TYPE_RVU_PFVF_BAR2, /**< Index into RVU PF or VF BAR2 */
BDK_CSR_TYPE_RVU_VF_BAR2, /**< Index into RVU VF BAR2 */
BDK_CSR_TYPE_SYSREG, /**< Core system register */
} bdk_csr_type_t;
#define BDK_CSR_DB_MAX_PARAM 4
typedef struct __attribute__ ((packed)) {
uint32_t name_index : 20;/**< Index into __bdk_csr_db_string where the name is */
uint32_t base_index : 14;/**< Index into __bdk_csr_db_number where the base address is */
uint8_t unused : 5;
bdk_csr_type_t type : 5; /**< Enum type from above */
uint8_t width : 4; /**< CSR width in bytes */
uint16_t field_index; /**< Index into __bdk_csr_db_fieldList where the fields start */
uint16_t range[BDK_CSR_DB_MAX_PARAM]; /**< Index into __bdk_csr_db_range where the range is */
uint16_t param_inc[BDK_CSR_DB_MAX_PARAM]; /**< Index into __bdk_csr_db_number where the param multiplier is */
} __bdk_csr_db_type_t;
typedef struct __attribute__ ((packed)) {
uint32_t name_index : 20;/**< Index into __bdk_csr_db_string where the name is */
uint32_t start_bit : 6; /**< LSB of the field */
uint32_t stop_bit : 6; /**< MSB of the field */
} __bdk_csr_db_field_t;
typedef struct {
uint32_t model;
const int16_t *data; /**< Array of integers indexing __bdk_csr_db_csr */
} __bdk_csr_db_map_t;
extern void __bdk_csr_fatal(const char *name, int num_args, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4) __attribute__ ((noreturn));
extern int bdk_csr_decode(const char *name, uint64_t value);
extern int bdk_csr_field(const char *csr_name, int field_start_bit, const char **field_name);
extern uint64_t bdk_csr_read_by_name(bdk_node_t node, const char *name);
extern int bdk_csr_write_by_name(bdk_node_t node, const char *name, uint64_t value);
extern int __bdk_csr_lookup_index(const char *name, int params[]);
extern int bdk_csr_get_name(const char *last_name, char *buffer);
struct bdk_readline_tab;
extern struct bdk_readline_tab *__bdk_csr_get_tab_complete() BDK_WEAK;
extern uint64_t bdk_sysreg_read(int node, int core, uint64_t regnum);
extern void bdk_sysreg_write(int node, int core, uint64_t regnum, uint64_t value);
#ifndef BDK_BUILD_HOST
/**
* Read a value from a CSR. Normally this function should not be
* used directly. Instead use the macro BDK_CSR_READ that fills
* in the parameters to this function for you.
*
* @param node Node to use in a Numa setup. Can be an exact ID or a special value.
* @param type Bus type the CSR is on
* @param busnum Bus number the CSR is on
* @param size Width of the CSR in bytes
* @param address The address of the CSR
*
* @return The value of the CSR
*/
static inline uint64_t bdk_csr_read(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address) __attribute__ ((always_inline));
static inline uint64_t bdk_csr_read(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address)
{
extern uint64_t __bdk_csr_read_slow(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address);
switch (type)
{
case BDK_CSR_TYPE_DAB:
case BDK_CSR_TYPE_DAB32b:
case BDK_CSR_TYPE_NCB:
case BDK_CSR_TYPE_NCB32b:
case BDK_CSR_TYPE_PEXP_NCB:
case BDK_CSR_TYPE_RSL:
case BDK_CSR_TYPE_RSL32b:
case BDK_CSR_TYPE_RVU_PF_BAR0:
case BDK_CSR_TYPE_RVU_PF_BAR2:
case BDK_CSR_TYPE_RVU_PFVF_BAR2:
case BDK_CSR_TYPE_RVU_VF_BAR2:
address |= (uint64_t)(node&3) << 44;
/* Note: This code assume a 1:1 mapping of all of address space.
It is designed to run with the MMU disabled */
switch (size)
{
case 1:
return *(volatile uint8_t *)address;
case 2:
return bdk_le16_to_cpu(*(volatile uint16_t *)address);
case 4:
return bdk_le32_to_cpu(*(volatile uint32_t *)address);
default:
return bdk_le64_to_cpu(*(volatile uint64_t *)address);
}
default:
return __bdk_csr_read_slow(node, type, busnum, size, address);
}
}
/**
* Wrate a value to a CSR. Normally this function should not be
* used directly. Instead use the macro BDK_CSR_WRITE that fills
* in the parameters to this function for you.
*
* @param node Node to use in a Numa setup. Can be an exact ID or a special value.
* @param type Bus type the CSR is on
* @param busnum Bus number the CSR is on
* @param size Width of the CSR in bytes
* @param address The address of the CSR
* @param value Value to write to the CSR
*/
static inline void bdk_csr_write(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value) __attribute__ ((always_inline));
static inline void bdk_csr_write(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value)
{
extern void __bdk_csr_write_slow(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address, uint64_t value);
switch (type)
{
case BDK_CSR_TYPE_DAB:
case BDK_CSR_TYPE_DAB32b:
case BDK_CSR_TYPE_NCB:
case BDK_CSR_TYPE_NCB32b:
case BDK_CSR_TYPE_PEXP_NCB:
case BDK_CSR_TYPE_RSL:
case BDK_CSR_TYPE_RSL32b:
case BDK_CSR_TYPE_RVU_PF_BAR0:
case BDK_CSR_TYPE_RVU_PF_BAR2:
case BDK_CSR_TYPE_RVU_PFVF_BAR2:
case BDK_CSR_TYPE_RVU_VF_BAR2:
address |= (uint64_t)(node&3) << 44;
/* Note: This code assume a 1:1 mapping of all of address space.
It is designed to run with the MMU disabled */
switch (size)
{
case 1:
*(volatile uint8_t *)address = value;
break;
case 2:
*(volatile uint16_t *)address = bdk_cpu_to_le16(value);
break;
case 4:
*(volatile uint32_t *)address = bdk_cpu_to_le32(value);
break;
default:
*(volatile uint64_t *)address = bdk_cpu_to_le64(value);
break;
}
break;
default:
__bdk_csr_write_slow(node, type, busnum, size, address, value);
}
}
#else
#define bdk_csr_read thunder_remote_read_csr
#define bdk_csr_write thunder_remote_write_csr
#endif
/**
* This macro makes it easy to define a variable of the correct
* type for a CSR.
*/
#define BDK_CSR_DEFINE(name, csr) typedef_##csr name
/**
* This macro makes it easy to define a variable and initialize it
* with a CSR.
*/
#define BDK_CSR_INIT(name, node, csr) typedef_##csr name = {.u = bdk_csr_read(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr)}
/**
* Macro to read a CSR
*/
#define BDK_CSR_READ(node, csr) bdk_csr_read(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr)
/**
* Macro to write a CSR
*/
#define BDK_CSR_WRITE(node, csr, value) bdk_csr_write(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), csr, value)
/**
* Macro to make a read, modify, and write sequence easy. The "code_block"
* should be replaced with a C code block or a comma separated list of
* "name.s.field = value", without the quotes.
*/
#define BDK_CSR_MODIFY(name, node, csr, code_block) do { \
uint64_t _tmp_address = csr; \
typedef_##csr name = {.u = bdk_csr_read(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address)}; \
code_block; \
bdk_csr_write(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address, name.u); \
} while (0)
/**
* This macro spins on a field waiting for it to reach a value. It
* is common in code to need to wait for a specific field in a CSR
* to match a specific value. Conceptually this macro expands to:
*
* 1) read csr at "address" with a csr typedef of "type"
* 2) Check if ("type".s."field" "op" "value")
* 3) If #2 isn't true loop to #1 unless too much time has passed.
*/
#define BDK_CSR_WAIT_FOR_FIELD(node, csr, field, op, value, timeout_usec) \
({int result; \
do { \
uint64_t done = bdk_clock_get_count(BDK_CLOCK_TIME) + (uint64_t)timeout_usec * \
bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) / 1000000; \
typedef_##csr c; \
uint64_t _tmp_address = csr; \
while (1) \
{ \
c.u = bdk_csr_read(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address); \
if ((c.s.field) op (value)) { \
result = 0; \
break; \
} else if (bdk_clock_get_count(BDK_CLOCK_TIME) > done) { \
result = -1; \
break; \
} else \
bdk_thread_yield(); \
} \
} while (0); \
result;})
/**
* This macro spins on a field waiting for it to reach a value. It
* is common in code to need to wait for a specific field in a CSR
* to match a specific value. Conceptually this macro expands to:
*
* 1) read csr at "address" with a csr typedef of "type"
* 2) Check if ("type"."chip"."field" "op" "value")
* 3) If #2 isn't true loop to #1 unless too much time has passed.
*
* Note that usage of this macro should be avoided. When future chips
* change bit locations, the compiler will not catch those changes
* with this macro. Changes silently do the wrong thing at runtime.
*/
#define BDK_CSR_WAIT_FOR_CHIP_FIELD(node, csr, chip, field, op, value, timeout_usec) \
({int result; \
do { \
uint64_t done = bdk_clock_get_count(BDK_CLOCK_TIME) + (uint64_t)timeout_usec * \
bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) / 1000000; \
typedef_##csr c; \
uint64_t _tmp_address = csr; \
while (1) \
{ \
c.u = bdk_csr_read(node, bustype_##csr, busnum_##csr, sizeof(typedef_##csr), _tmp_address); \
if ((c.chip.field) op (value)) { \
result = 0; \
break; \
} else if (bdk_clock_get_count(BDK_CLOCK_TIME) > done) { \
result = -1; \
break; \
} else \
bdk_thread_yield(); \
} \
} while (0); \
result;})
/** @} */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,643 @@
#ifndef __BDK_CSRS_FUS_H__
#define __BDK_CSRS_FUS_H__
/* This file is auto-generated. Do not edit */
/***********************license start***************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Configuration and status register (CSR) address and type definitions for
* Cavium FUS.
*
* This file is auto generated. Do not edit.
*
*/
/**
* Enumeration fus_bar_e
*
* Fuse Base Address Register Enumeration
* Enumerates the base address registers.
*/
#define BDK_FUS_BAR_E_FUS_PF_BAR0 (0x87e003000000ll)
#define BDK_FUS_BAR_E_FUS_PF_BAR0_SIZE 0x10000ull
/**
* Enumeration fus_fuse_num_e
*
* INTERNAL: Fuse Number Enumeration
*
* Enumerates the fuse numbers.
*/
#define BDK_FUS_FUSE_NUM_E_ALT_BANKX(a) (0xf80 + (a))
#define BDK_FUS_FUSE_NUM_E_ALT_FUSEX(a) (0x7b + (a))
#define BDK_FUS_FUSE_NUM_E_AP_CRIPPLEX(a) (0x180 + (a))
#define BDK_FUS_FUSE_NUM_E_AP_NOCRYPTOX(a) (0x200 + (a))
#define BDK_FUS_FUSE_NUM_E_AP_POWER_LIMITX(a) (0x259 + (a))
#define BDK_FUS_FUSE_NUM_E_BCH_DISABLE (0x202)
#define BDK_FUS_FUSE_NUM_E_BISR_FUSED_ONLY (0x53)
#define BDK_FUS_FUSE_NUM_E_BSR_LOBE_DISABLEX(a) (0x290 + (a))
#define BDK_FUS_FUSE_NUM_E_CGX_CRIPPLEX(a) (0x228 + (a))
#define BDK_FUS_FUSE_NUM_E_CHIP_IDX(a) (8 + (a))
#define BDK_FUS_FUSE_NUM_E_CHIP_TYPEX(a) (0 + (a))
#define BDK_FUS_FUSE_NUM_E_CORE_INIT_MULX(a) (0x43 + (a))
#define BDK_FUS_FUSE_NUM_E_CORE_INIT_PLL (0x4a)
#define BDK_FUS_FUSE_NUM_E_CORE_MAX_MULX(a) (0x4b + (a))
#define BDK_FUS_FUSE_NUM_E_CPT0_NOCRYPTOX(a) (0x255 + (a))
#define BDK_FUS_FUSE_NUM_E_CPT1_NOCRYPTOX(a) (0x257 + (a))
#define BDK_FUS_FUSE_NUM_E_CPT_EXE_DISABLEX(a) (0x580 + (a))
#define BDK_FUS_FUSE_NUM_E_CPT_INIT_MULX(a) (0x5d + (a))
#define BDK_FUS_FUSE_NUM_E_CPT_INIT_PLL (0x64)
#define BDK_FUS_FUSE_NUM_E_CPT_MAX_MULX(a) (0x65 + (a))
#define BDK_FUS_FUSE_NUM_E_DESX(a) (0x540 + (a))
#define BDK_FUS_FUSE_NUM_E_DFA_INFO_CLMX(a) (0x220 + (a))
#define BDK_FUS_FUSE_NUM_E_DFA_INFO_DTEX(a) (0x21d + (a))
#define BDK_FUS_FUSE_NUM_E_DLL0_PD_DELAYX(a) (0x88 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL0_SETTINGSX(a) (0x80 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL10_PD_DELAYX(a) (0x100 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL10_SETTINGSX(a) (0xf8 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL11_PD_DELAYX(a) (0x10c + (a))
#define BDK_FUS_FUSE_NUM_E_DLL11_SETTINGSX(a) (0x104 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL12_PD_DELAYX(a) (0x118 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL12_SETTINGSX(a) (0x110 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL13_PD_DELAYX(a) (0x124 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL13_SETTINGSX(a) (0x11c + (a))
#define BDK_FUS_FUSE_NUM_E_DLL14_PD_DELAYX(a) (0x130 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL14_SETTINGSX(a) (0x128 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL15_PD_DELAYX(a) (0x13c + (a))
#define BDK_FUS_FUSE_NUM_E_DLL15_SETTINGSX(a) (0x134 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL1_PD_DELAYX(a) (0x94 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL1_SETTINGSX(a) (0x8c + (a))
#define BDK_FUS_FUSE_NUM_E_DLL2_PD_DELAYX(a) (0xa0 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL2_SETTINGSX(a) (0x98 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL3_PD_DELAYX(a) (0xac + (a))
#define BDK_FUS_FUSE_NUM_E_DLL3_SETTINGSX(a) (0xa4 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL4_PD_DELAYX(a) (0xb8 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL4_SETTINGSX(a) (0xb0 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL5_PD_DELAYX(a) (0xc4 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL5_SETTINGSX(a) (0xbc + (a))
#define BDK_FUS_FUSE_NUM_E_DLL6_PD_DELAYX(a) (0xd0 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL6_SETTINGSX(a) (0xc8 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL7_PD_DELAYX(a) (0xdc + (a))
#define BDK_FUS_FUSE_NUM_E_DLL7_SETTINGSX(a) (0xd4 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL8_PD_DELAYX(a) (0xe8 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL8_SETTINGSX(a) (0xe0 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL9_PD_DELAYX(a) (0xf4 + (a))
#define BDK_FUS_FUSE_NUM_E_DLL9_SETTINGSX(a) (0xec + (a))
#define BDK_FUS_FUSE_NUM_E_DLL_INIT_SETTINGSX(a) (0x6c + (a))
#define BDK_FUS_FUSE_NUM_E_DLL_LOCK_FREEZE (0x54)
#define BDK_FUS_FUSE_NUM_E_DLL_REFRESH_RATEX(a) (0x55 + (a))
#define BDK_FUS_FUSE_NUM_E_DRO_CRIPPLE (0x73)
#define BDK_FUS_FUSE_NUM_E_EFUS_LCK_CFG (0x78)
#define BDK_FUS_FUSE_NUM_E_EFUS_LCK_MAN (0x79)
#define BDK_FUS_FUSE_NUM_E_EFUS_LCK_PRD (0x7a)
#define BDK_FUS_FUSE_NUM_E_EMA0X(a) (0x10 + (a))
#define BDK_FUS_FUSE_NUM_E_EMA1X(a) (0x16 + (a))
#define BDK_FUS_FUSE_NUM_E_EMA2X(a) (0x1c + (a))
#define BDK_FUS_FUSE_NUM_E_EMA3X(a) (0x23 + (a))
#define BDK_FUS_FUSE_NUM_E_EMA4X(a) (0x25 + (a))
#define BDK_FUS_FUSE_NUM_E_EMA5 (0x28)
#define BDK_FUS_FUSE_NUM_E_FDFX(a) (0xa00 + (a))
#define BDK_FUS_FUSE_NUM_E_GSER_ERCX(a) (0xf00 + (a))
#define BDK_FUS_FUSE_NUM_E_LLC_CRIPPLEX(a) (0x216 + (a))
#define BDK_FUS_FUSE_NUM_E_LMC_CRIPPLEX(a) (0x283 + (a))
#define BDK_FUS_FUSE_NUM_E_LMC_HALF (0x203)
#define BDK_FUS_FUSE_NUM_E_METAL_FIXX(a) (0x2c + (a))
#define BDK_FUS_FUSE_NUM_E_MFG_INFOX(a) (0x400 + (a))
#define BDK_FUS_FUSE_NUM_E_MLC_CRIPPLEX(a) (0x219 + (a))
#define BDK_FUS_FUSE_NUM_E_NODE1TRAPENA (0x250)
#define BDK_FUS_FUSE_NUM_E_NODFA_CP2 (0x21c)
#define BDK_FUS_FUSE_NUM_E_NPC_CRIPPLE (0x280)
#define BDK_FUS_FUSE_NUM_E_OCX_CRIPPLE (0x227)
#define BDK_FUS_FUSE_NUM_E_PDFX(a) (0x640 + (a))
#define BDK_FUS_FUSE_NUM_E_PEM_CRIPPLEX(a) (0x230 + (a))
#define BDK_FUS_FUSE_NUM_E_PNR_INIT_MULX(a) (0x34 + (a))
#define BDK_FUS_FUSE_NUM_E_PNR_INIT_PLL (0x3b)
#define BDK_FUS_FUSE_NUM_E_PNR_MAX_MULX(a) (0x3c + (a))
#define BDK_FUS_FUSE_NUM_E_POWER_LIMITX(a) (0x225 + (a))
#define BDK_FUS_FUSE_NUM_E_PVTX(a) (0x680 + (a))
#define BDK_FUS_FUSE_NUM_E_RAID_CRIPPLE (0x224)
#define BDK_FUS_FUSE_NUM_E_REFCLK_CHECK (0x52)
#define BDK_FUS_FUSE_NUM_E_REPAIRX(a) (0x1000 + (a))
#define BDK_FUS_FUSE_NUM_E_ROM_INFOX(a) (0x3f0 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD140X(a) (0x140 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD205 (0x205)
#define BDK_FUS_FUSE_NUM_E_RSVD251X(a) (0x251 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD254 (0x254)
#define BDK_FUS_FUSE_NUM_E_RSVD25BX(a) (0x25b + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD264X(a) (0x264 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD281 (0x281)
#define BDK_FUS_FUSE_NUM_E_RSVD282 (0x282)
#define BDK_FUS_FUSE_NUM_E_RSVD28B (0x28b)
#define BDK_FUS_FUSE_NUM_E_RSVD28F (0x28f)
#define BDK_FUS_FUSE_NUM_E_RSVD29X(a) (0x29 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD29DX(a) (0x29d + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD31X(a) (0x31 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD74 (0x74)
#define BDK_FUS_FUSE_NUM_E_RSVD780X(a) (0x780 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD801X(a) (0x801 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVD914X(a) (0x914 + (a))
#define BDK_FUS_FUSE_NUM_E_RSVDE00X(a) (0xe00 + (a))
#define BDK_FUS_FUSE_NUM_E_RUN_PLATFORMX(a) (0x75 + (a))
#define BDK_FUS_FUSE_NUM_E_RVU_CRIPPLE (0x28e)
#define BDK_FUS_FUSE_NUM_E_SATA_CRIPPLEX(a) (0x260 + (a))
#define BDK_FUS_FUSE_NUM_E_SERIALX(a) (0x500 + (a))
#define BDK_FUS_FUSE_NUM_E_SSO_CRIPPLE (0x253)
#define BDK_FUS_FUSE_NUM_E_TGGX(a) (0x600 + (a))
#define BDK_FUS_FUSE_NUM_E_TS0_M_CX(a) (0x810 + (a))
#define BDK_FUS_FUSE_NUM_E_TS0_N_OFFX(a) (0x81c + (a))
#define BDK_FUS_FUSE_NUM_E_TS0_STROBE_COMP_DLYX(a) (0x827 + (a))
#define BDK_FUS_FUSE_NUM_E_TS1_M_CX(a) (0x82a + (a))
#define BDK_FUS_FUSE_NUM_E_TS1_N_OFFX(a) (0x836 + (a))
#define BDK_FUS_FUSE_NUM_E_TS1_STROBE_COMP_DLYX(a) (0x841 + (a))
#define BDK_FUS_FUSE_NUM_E_TS2_M_CX(a) (0x844 + (a))
#define BDK_FUS_FUSE_NUM_E_TS2_N_OFFX(a) (0x850 + (a))
#define BDK_FUS_FUSE_NUM_E_TS2_STROBE_COMP_DLYX(a) (0x85b + (a))
#define BDK_FUS_FUSE_NUM_E_TS3_M_CX(a) (0x85e + (a))
#define BDK_FUS_FUSE_NUM_E_TS3_N_OFFX(a) (0x86a + (a))
#define BDK_FUS_FUSE_NUM_E_TS3_STROBE_COMP_DLYX(a) (0x875 + (a))
#define BDK_FUS_FUSE_NUM_E_TS4_M_CX(a) (0x878 + (a))
#define BDK_FUS_FUSE_NUM_E_TS4_N_OFFX(a) (0x884 + (a))
#define BDK_FUS_FUSE_NUM_E_TS4_STROBE_COMP_DLYX(a) (0x88f + (a))
#define BDK_FUS_FUSE_NUM_E_TS5_M_CX(a) (0x892 + (a))
#define BDK_FUS_FUSE_NUM_E_TS5_N_OFFX(a) (0x89e + (a))
#define BDK_FUS_FUSE_NUM_E_TS5_STROBE_COMP_DLYX(a) (0x8a9 + (a))
#define BDK_FUS_FUSE_NUM_E_TS6_M_CX(a) (0x8ac + (a))
#define BDK_FUS_FUSE_NUM_E_TS6_N_OFFX(a) (0x8b8 + (a))
#define BDK_FUS_FUSE_NUM_E_TS6_STROBE_COMP_DLYX(a) (0x8c3 + (a))
#define BDK_FUS_FUSE_NUM_E_TS7_M_CX(a) (0x8c6 + (a))
#define BDK_FUS_FUSE_NUM_E_TS7_N_OFFX(a) (0x8d2 + (a))
#define BDK_FUS_FUSE_NUM_E_TS7_STROBE_COMP_DLYX(a) (0x8dd + (a))
#define BDK_FUS_FUSE_NUM_E_TS8_M_CX(a) (0x8e0 + (a))
#define BDK_FUS_FUSE_NUM_E_TS8_N_OFFX(a) (0x8ec + (a))
#define BDK_FUS_FUSE_NUM_E_TS8_STROBE_COMP_DLYX(a) (0x8f7 + (a))
#define BDK_FUS_FUSE_NUM_E_TS9_M_CX(a) (0x8fa + (a))
#define BDK_FUS_FUSE_NUM_E_TS9_N_OFFX(a) (0x906 + (a))
#define BDK_FUS_FUSE_NUM_E_TS9_STROBE_COMP_DLYX(a) (0x911 + (a))
#define BDK_FUS_FUSE_NUM_E_TS_CALBRATED (0x800)
#define BDK_FUS_FUSE_NUM_E_USBDRD_CRIPPLEX(a) (0x28c + (a))
#define BDK_FUS_FUSE_NUM_E_ZIP_CRIPPLEX(a) (0x206 + (a))
#define BDK_FUS_FUSE_NUM_E_ZIP_CTL_DISABLE (0x204)
/**
* Register (RSL) fus_bnk_dat#
*
* Fuse Bank Store Register
* The initial state of FUS_BNK_DAT() is as if bank6 were just read,
* i.e. DAT* = fus[895:768].
*/
union bdk_fus_bnk_datx
{
uint64_t u;
struct bdk_fus_bnk_datx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](R/W/H) Efuse bank store. For read operations, [DAT] gets the fus bank last read. For write
operations, the [DAT] determines which fuses to blow. */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](R/W/H) Efuse bank store. For read operations, [DAT] gets the fus bank last read. For write
operations, the [DAT] determines which fuses to blow. */
#endif /* Word 0 - End */
} s;
/* struct bdk_fus_bnk_datx_s cn; */
};
typedef union bdk_fus_bnk_datx bdk_fus_bnk_datx_t;
static inline uint64_t BDK_FUS_BNK_DATX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUS_BNK_DATX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=1))
return 0x87e003001520ll + 8ll * ((a) & 0x1);
__bdk_csr_fatal("FUS_BNK_DATX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUS_BNK_DATX(a) bdk_fus_bnk_datx_t
#define bustype_BDK_FUS_BNK_DATX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUS_BNK_DATX(a) "FUS_BNK_DATX"
#define device_bar_BDK_FUS_BNK_DATX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUS_BNK_DATX(a) (a)
#define arguments_BDK_FUS_BNK_DATX(a) (a),-1,-1,-1
/**
* Register (RSL) fus_cache#
*
* Fuse Cache Register
* This register returns the cached state of every fuse, organized into 64-fuse
* chunks. Each bit corresponds to a fuse enumerated by FUS_FUSE_NUM_E.
*/
union bdk_fus_cachex
{
uint64_t u;
struct bdk_fus_cachex_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t data : 64; /**< [ 63: 0](RO/H) Reads the cached fuse value.
Modifications to the cache will take effect on the next
chip domain reset and are lost on a cold domain reset. */
#else /* Word 0 - Little Endian */
uint64_t data : 64; /**< [ 63: 0](RO/H) Reads the cached fuse value.
Modifications to the cache will take effect on the next
chip domain reset and are lost on a cold domain reset. */
#endif /* Word 0 - End */
} s;
/* struct bdk_fus_cachex_s cn; */
};
typedef union bdk_fus_cachex bdk_fus_cachex_t;
static inline uint64_t BDK_FUS_CACHEX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUS_CACHEX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=63))
return 0x87e003001000ll + 8ll * ((a) & 0x3f);
__bdk_csr_fatal("FUS_CACHEX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUS_CACHEX(a) bdk_fus_cachex_t
#define bustype_BDK_FUS_CACHEX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUS_CACHEX(a) "FUS_CACHEX"
#define device_bar_BDK_FUS_CACHEX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUS_CACHEX(a) (a)
#define arguments_BDK_FUS_CACHEX(a) (a),-1,-1,-1
/**
* Register (RSL) fus_const
*
* Fuse Constants Register
*/
union bdk_fus_const
{
uint64_t u;
struct bdk_fus_const_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_16_63 : 48;
uint64_t repair_banks : 8; /**< [ 15: 8](RO) Number of 128-bit memory repair banks present. */
uint64_t fuse_banks : 8; /**< [ 7: 0](RO) Number of 128-bit general purpose fuse banks present. */
#else /* Word 0 - Little Endian */
uint64_t fuse_banks : 8; /**< [ 7: 0](RO) Number of 128-bit general purpose fuse banks present. */
uint64_t repair_banks : 8; /**< [ 15: 8](RO) Number of 128-bit memory repair banks present. */
uint64_t reserved_16_63 : 48;
#endif /* Word 0 - End */
} s;
/* struct bdk_fus_const_s cn; */
};
typedef union bdk_fus_const bdk_fus_const_t;
#define BDK_FUS_CONST BDK_FUS_CONST_FUNC()
static inline uint64_t BDK_FUS_CONST_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUS_CONST_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e003001578ll;
__bdk_csr_fatal("FUS_CONST", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUS_CONST bdk_fus_const_t
#define bustype_BDK_FUS_CONST BDK_CSR_TYPE_RSL
#define basename_BDK_FUS_CONST "FUS_CONST"
#define device_bar_BDK_FUS_CONST 0x0 /* PF_BAR0 */
#define busnum_BDK_FUS_CONST 0
#define arguments_BDK_FUS_CONST -1,-1,-1,-1
/**
* Register (RSL) fus_prog
*
* INTERNAL: Fuse Programming Register
*/
union bdk_fus_prog
{
uint64_t u;
struct bdk_fus_prog_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_16_63 : 48;
uint64_t efuse : 1; /**< [ 15: 15](R/W) Efuse storage. When set, the data is written directly to the efuse
bank. When cleared, data is soft blown to local storage.
A soft blown fuse is subject to lockdown fuses.
Soft blown fuses will become active after a chip domain reset
but will not persist through a cold domain reset. */
uint64_t voltage : 1; /**< [ 14: 14](RO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be set when
programming fuses (ie. [EFUSE] and [PROG] set). */
uint64_t reserved_13 : 1;
uint64_t prog : 1; /**< [ 12: 12](R/W/H) Internal:
When written to one by software, blow the fuse bank. Hardware will
clear the field when the program operation is complete.
To write a bank of fuses, software must write the fuse data into
FUS_BNK_DAT(). Then it writes the ADDR and EFUSE fields of this register
and sets the PROG bit. Hardware will clear the [PROG] when the write is
completed. New fuses will become active after a chip domain reset. */
uint64_t reserved_11 : 1;
uint64_t addr : 7; /**< [ 10: 4](R/W) Indicates which of the banks of 128 fuses to blow. Software
should not change this field while the FUS_PROG[PROG] bit is set. */
uint64_t reserved_0_3 : 4;
#else /* Word 0 - Little Endian */
uint64_t reserved_0_3 : 4;
uint64_t addr : 7; /**< [ 10: 4](R/W) Indicates which of the banks of 128 fuses to blow. Software
should not change this field while the FUS_PROG[PROG] bit is set. */
uint64_t reserved_11 : 1;
uint64_t prog : 1; /**< [ 12: 12](R/W/H) Internal:
When written to one by software, blow the fuse bank. Hardware will
clear the field when the program operation is complete.
To write a bank of fuses, software must write the fuse data into
FUS_BNK_DAT(). Then it writes the ADDR and EFUSE fields of this register
and sets the PROG bit. Hardware will clear the [PROG] when the write is
completed. New fuses will become active after a chip domain reset. */
uint64_t reserved_13 : 1;
uint64_t voltage : 1; /**< [ 14: 14](RO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be set when
programming fuses (ie. [EFUSE] and [PROG] set). */
uint64_t efuse : 1; /**< [ 15: 15](R/W) Efuse storage. When set, the data is written directly to the efuse
bank. When cleared, data is soft blown to local storage.
A soft blown fuse is subject to lockdown fuses.
Soft blown fuses will become active after a chip domain reset
but will not persist through a cold domain reset. */
uint64_t reserved_16_63 : 48;
#endif /* Word 0 - End */
} s;
/* struct bdk_fus_prog_s cn; */
};
typedef union bdk_fus_prog bdk_fus_prog_t;
#define BDK_FUS_PROG BDK_FUS_PROG_FUNC()
static inline uint64_t BDK_FUS_PROG_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUS_PROG_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e003001510ll;
__bdk_csr_fatal("FUS_PROG", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUS_PROG bdk_fus_prog_t
#define bustype_BDK_FUS_PROG BDK_CSR_TYPE_RSL
#define basename_BDK_FUS_PROG "FUS_PROG"
#define device_bar_BDK_FUS_PROG 0x0 /* PF_BAR0 */
#define busnum_BDK_FUS_PROG 0
#define arguments_BDK_FUS_PROG -1,-1,-1,-1
/**
* Register (RSL) fus_rcmd
*
* Fuse Read Command Register
* Read Fuse Banks.
*/
union bdk_fus_rcmd
{
uint64_t u;
struct bdk_fus_rcmd_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_16_63 : 48;
uint64_t efuse : 1; /**< [ 15: 15](R/W) Efuse storage. When set, the return data is from the efuse
bank directly. When cleared data is read from the local storage. */
uint64_t voltage : 1; /**< [ 14: 14](RO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be cleared when
reading fuses directly (ie. [EFUSE] and [PEND] set). */
uint64_t reserved_13 : 1;
uint64_t pend : 1; /**< [ 12: 12](R/W/H) Software sets this bit to one on a write operation that starts
the fuse read operation. Hardware clears this bit when the read
operation is complete and FUS_BNK_DAT() is valid.
FUS_READ_TIMES[RDSTB_WH] determines the time for the operation
to complete. */
uint64_t reserved_11 : 1;
uint64_t addr : 7; /**< [ 10: 4](R/W) Address. Specifies the bank address of 128 fuses to read.
Software should not change this field while [PEND]
is set. It must wait for the hardware to clear it. */
uint64_t reserved_0_3 : 4;
#else /* Word 0 - Little Endian */
uint64_t reserved_0_3 : 4;
uint64_t addr : 7; /**< [ 10: 4](R/W) Address. Specifies the bank address of 128 fuses to read.
Software should not change this field while [PEND]
is set. It must wait for the hardware to clear it. */
uint64_t reserved_11 : 1;
uint64_t pend : 1; /**< [ 12: 12](R/W/H) Software sets this bit to one on a write operation that starts
the fuse read operation. Hardware clears this bit when the read
operation is complete and FUS_BNK_DAT() is valid.
FUS_READ_TIMES[RDSTB_WH] determines the time for the operation
to complete. */
uint64_t reserved_13 : 1;
uint64_t voltage : 1; /**< [ 14: 14](RO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be cleared when
reading fuses directly (ie. [EFUSE] and [PEND] set). */
uint64_t efuse : 1; /**< [ 15: 15](R/W) Efuse storage. When set, the return data is from the efuse
bank directly. When cleared data is read from the local storage. */
uint64_t reserved_16_63 : 48;
#endif /* Word 0 - End */
} s;
/* struct bdk_fus_rcmd_s cn; */
};
typedef union bdk_fus_rcmd bdk_fus_rcmd_t;
#define BDK_FUS_RCMD BDK_FUS_RCMD_FUNC()
static inline uint64_t BDK_FUS_RCMD_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUS_RCMD_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e003001500ll;
__bdk_csr_fatal("FUS_RCMD", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUS_RCMD bdk_fus_rcmd_t
#define bustype_BDK_FUS_RCMD BDK_CSR_TYPE_RSL
#define basename_BDK_FUS_RCMD "FUS_RCMD"
#define device_bar_BDK_FUS_RCMD 0x0 /* PF_BAR0 */
#define busnum_BDK_FUS_RCMD 0
#define arguments_BDK_FUS_RCMD -1,-1,-1,-1
/**
* Register (RSL) fus_read_times
*
* Fuse Read Times Register
* The reset values correspond to accesses of internal fuses with PLL reference clock
* up to 115 MHz. If any of the formulas below result in a value less than 0x0, the
* corresponding timing parameter should be set to zero.
*
* Prior to issuing a read operation to the fuse banks (via FUS_RCMD),
* this register should be written with the timing parameters that will be read.
* This register should not be written while FUS_RCMD[PEND] = 1.
*/
union bdk_fus_read_times
{
uint64_t u;
struct bdk_fus_read_times_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_32_63 : 32;
uint64_t done : 4; /**< [ 31: 28](R/W) Hold time of CSB, PGENB, and LOAD with respect to falling edge
of STROBE for read and write mode in PLL_REF_CLK + 1 cycles.
Timing specs are th_CS = 6 ns, th_PG = 10 ns, th_LD_p = 7 ns.
Default of 0x0 yields 8.7 ns at 115 MHz. */
uint64_t ahd : 4; /**< [ 27: 24](R/W) Hold time of A with respect to falling edge of STROBE
for read and write modes in PLL_REF_CLK + 1 cycles.
Timing spec of tsu_A_r and tsu_A_p is 3 ns min.
Default of 0x0 yields 8.7 ns at 115MHz. */
uint64_t wrstb_wh : 12; /**< [ 23: 12](R/W) Pulse width high of STROBE in write mode in PLL_REF_CLK + 1 cycles.
Timing spec of twh_SB_p is 9.8 us max.
Default of 0x3E8 yields 8.7 us at 115MHz. */
uint64_t rdstb_wh : 4; /**< [ 11: 8](R/W) Pulse width high of STROBE in read mode in PLL_REF_CLK + 1 cycles.
Timing spec of twh_SB_p is 20 ns min.
Default of 0x2 yields 26.1 ns at 115 MHz. */
uint64_t asu : 4; /**< [ 7: 4](R/W) Setup time of A to rising edge of STROBE for read and write
modes in PLL_REF_CLK cycles.
Timing spec of tsu_A_r and tsu_A_p is 12 ns min.
Default of 0x1 yields 17.4 ns at 115 MHz. */
uint64_t setup : 4; /**< [ 3: 0](R/W) Setup time of CSB, PGENB, LOAD to rising edge of STROBE
in read and write modes in PLL_REF_CLK + 1 cycles.
tsu_CS = 16 ns, tsu_PG = 14 ns, tsu_LD_r = 10 ns.
Default of 0x0 yields 8.7 ns plus ASU cycles at 115 MHz. */
#else /* Word 0 - Little Endian */
uint64_t setup : 4; /**< [ 3: 0](R/W) Setup time of CSB, PGENB, LOAD to rising edge of STROBE
in read and write modes in PLL_REF_CLK + 1 cycles.
tsu_CS = 16 ns, tsu_PG = 14 ns, tsu_LD_r = 10 ns.
Default of 0x0 yields 8.7 ns plus ASU cycles at 115 MHz. */
uint64_t asu : 4; /**< [ 7: 4](R/W) Setup time of A to rising edge of STROBE for read and write
modes in PLL_REF_CLK cycles.
Timing spec of tsu_A_r and tsu_A_p is 12 ns min.
Default of 0x1 yields 17.4 ns at 115 MHz. */
uint64_t rdstb_wh : 4; /**< [ 11: 8](R/W) Pulse width high of STROBE in read mode in PLL_REF_CLK + 1 cycles.
Timing spec of twh_SB_p is 20 ns min.
Default of 0x2 yields 26.1 ns at 115 MHz. */
uint64_t wrstb_wh : 12; /**< [ 23: 12](R/W) Pulse width high of STROBE in write mode in PLL_REF_CLK + 1 cycles.
Timing spec of twh_SB_p is 9.8 us max.
Default of 0x3E8 yields 8.7 us at 115MHz. */
uint64_t ahd : 4; /**< [ 27: 24](R/W) Hold time of A with respect to falling edge of STROBE
for read and write modes in PLL_REF_CLK + 1 cycles.
Timing spec of tsu_A_r and tsu_A_p is 3 ns min.
Default of 0x0 yields 8.7 ns at 115MHz. */
uint64_t done : 4; /**< [ 31: 28](R/W) Hold time of CSB, PGENB, and LOAD with respect to falling edge
of STROBE for read and write mode in PLL_REF_CLK + 1 cycles.
Timing specs are th_CS = 6 ns, th_PG = 10 ns, th_LD_p = 7 ns.
Default of 0x0 yields 8.7 ns at 115 MHz. */
uint64_t reserved_32_63 : 32;
#endif /* Word 0 - End */
} s;
/* struct bdk_fus_read_times_s cn; */
};
typedef union bdk_fus_read_times bdk_fus_read_times_t;
#define BDK_FUS_READ_TIMES BDK_FUS_READ_TIMES_FUNC()
static inline uint64_t BDK_FUS_READ_TIMES_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUS_READ_TIMES_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e003001570ll;
__bdk_csr_fatal("FUS_READ_TIMES", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUS_READ_TIMES bdk_fus_read_times_t
#define bustype_BDK_FUS_READ_TIMES BDK_CSR_TYPE_RSL
#define basename_BDK_FUS_READ_TIMES "FUS_READ_TIMES"
#define device_bar_BDK_FUS_READ_TIMES 0x0 /* PF_BAR0 */
#define busnum_BDK_FUS_READ_TIMES 0
#define arguments_BDK_FUS_READ_TIMES -1,-1,-1,-1
/**
* Register (RSL) fus_soft_repair
*
* INTERNAL: Fuse Soft Repair Register
*
* Internal:
* Aka `soft blow'. Upon reset fuse repairs are loaded into FUS_FUSE_NUM_E::REPAIR()
* fuses as they are loaded into the memories.
*/
union bdk_fus_soft_repair
{
uint64_t u;
struct bdk_fus_soft_repair_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_48_63 : 16;
uint64_t auto_dly : 16; /**< [ 47: 32](R/W/H) Internal:
Autoblow Delay. Power supply ramp delay in 1uS increments from enabling
[AUTOBLOW] to programming first bit. */
uint64_t reserved_18_31 : 14;
uint64_t autoblow : 1; /**< [ 17: 17](R/W/H) Internal:
Set to initiate burning of defect fuses to fuse macro. Clears when fuses are
blown. */
uint64_t reserved_16 : 1;
uint64_t numdefects : 8; /**< [ 15: 8](RO/H) Internal:
After reset/BIST indicates the number of memory defects reported. Defects are
stored in fuses FUS_FUSE_NUM_E::REPAIR() from index [NUMREPAIRS]*32 to
([NUMREPAIRS]*32 + [NUMDEFECTS]*32 - 1). */
uint64_t numrepairs : 8; /**< [ 7: 0](R/W) Internal:
Indicates the number of repairs loaded from repair mem to the memories on
the last chip/core/mcp/scp reset. */
#else /* Word 0 - Little Endian */
uint64_t numrepairs : 8; /**< [ 7: 0](R/W) Internal:
Indicates the number of repairs loaded from repair mem to the memories on
the last chip/core/mcp/scp reset. */
uint64_t numdefects : 8; /**< [ 15: 8](RO/H) Internal:
After reset/BIST indicates the number of memory defects reported. Defects are
stored in fuses FUS_FUSE_NUM_E::REPAIR() from index [NUMREPAIRS]*32 to
([NUMREPAIRS]*32 + [NUMDEFECTS]*32 - 1). */
uint64_t reserved_16 : 1;
uint64_t autoblow : 1; /**< [ 17: 17](R/W/H) Internal:
Set to initiate burning of defect fuses to fuse macro. Clears when fuses are
blown. */
uint64_t reserved_18_31 : 14;
uint64_t auto_dly : 16; /**< [ 47: 32](R/W/H) Internal:
Autoblow Delay. Power supply ramp delay in 1uS increments from enabling
[AUTOBLOW] to programming first bit. */
uint64_t reserved_48_63 : 16;
#endif /* Word 0 - End */
} s;
/* struct bdk_fus_soft_repair_s cn; */
};
typedef union bdk_fus_soft_repair bdk_fus_soft_repair_t;
#define BDK_FUS_SOFT_REPAIR BDK_FUS_SOFT_REPAIR_FUNC()
static inline uint64_t BDK_FUS_SOFT_REPAIR_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUS_SOFT_REPAIR_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e003001540ll;
__bdk_csr_fatal("FUS_SOFT_REPAIR", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUS_SOFT_REPAIR bdk_fus_soft_repair_t
#define bustype_BDK_FUS_SOFT_REPAIR BDK_CSR_TYPE_RSL
#define basename_BDK_FUS_SOFT_REPAIR "FUS_SOFT_REPAIR"
#define device_bar_BDK_FUS_SOFT_REPAIR 0x0 /* PF_BAR0 */
#define busnum_BDK_FUS_SOFT_REPAIR 0
#define arguments_BDK_FUS_SOFT_REPAIR -1,-1,-1,-1
#endif /* __BDK_CSRS_FUS_H__ */

View File

@ -0,0 +1,939 @@
#ifndef __BDK_CSRS_FUSF_H__
#define __BDK_CSRS_FUSF_H__
/* This file is auto-generated. Do not edit */
/***********************license start***************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Configuration and status register (CSR) address and type definitions for
* Cavium FUSF.
*
* This file is auto generated. Do not edit.
*
*/
/**
* Enumeration fusf_bar_e
*
* Field Fuse Base Address Register Enumeration
* Enumerates the base address registers.
*/
#define BDK_FUSF_BAR_E_FUSF_PF_BAR0 (0x87e004000000ll)
#define BDK_FUSF_BAR_E_FUSF_PF_BAR0_SIZE 0x10000ull
/**
* Enumeration fusf_fuse_num_e
*
* Field Fuse Fuse Number Enumeration
* Enumerates the fuse numbers.
*/
#define BDK_FUSF_FUSE_NUM_E_CRYPT_NO_DIS (0xe)
#define BDK_FUSF_FUSE_NUM_E_CRYPT_SSK_DIS (0xf)
#define BDK_FUSF_FUSE_NUM_E_DIS_HUK (0xd)
#define BDK_FUSF_FUSE_NUM_E_EKX(a) (0x500 + (a))
#define BDK_FUSF_FUSE_NUM_E_FJ_CORE0 (0xc)
#define BDK_FUSF_FUSE_NUM_E_FJ_DIS (9)
#define BDK_FUSF_FUSE_NUM_E_FJ_TIMEOUTX(a) (0xa + (a))
#define BDK_FUSF_FUSE_NUM_E_FUSF_LCK (0)
#define BDK_FUSF_FUSE_NUM_E_HUKX(a) (0x480 + (a))
#define BDK_FUSF_FUSE_NUM_E_MFG_LCK (6)
#define BDK_FUSF_FUSE_NUM_E_ROM_SCRIPT_DISABLE (0x1e)
#define BDK_FUSF_FUSE_NUM_E_ROM_T_CNTX(a) (0x20 + (a))
#define BDK_FUSF_FUSE_NUM_E_ROTPKX(a) (0x300 + (a))
#define BDK_FUSF_FUSE_NUM_E_ROT_LCK (2)
#define BDK_FUSF_FUSE_NUM_E_RSVD128X(a) (0x80 + (a))
#define BDK_FUSF_FUSE_NUM_E_RSVD16X(a) (0x10 + (a))
#define BDK_FUSF_FUSE_NUM_E_RSVD256X(a) (0x100 + (a))
#define BDK_FUSF_FUSE_NUM_E_RSVD4X(a) (4 + (a))
#define BDK_FUSF_FUSE_NUM_E_RSVD5 (5)
#define BDK_FUSF_FUSE_NUM_E_RSVD512X(a) (0x200 + (a))
#define BDK_FUSF_FUSE_NUM_E_RSVD64X(a) (0x40 + (a))
#define BDK_FUSF_FUSE_NUM_E_RSVD7 (7)
#define BDK_FUSF_FUSE_NUM_E_SPI_SAFEMODE (0x1f)
#define BDK_FUSF_FUSE_NUM_E_SSKX(a) (0x400 + (a))
#define BDK_FUSF_FUSE_NUM_E_SSK_LCK (1)
#define BDK_FUSF_FUSE_NUM_E_SWX(a) (0x600 + (a))
#define BDK_FUSF_FUSE_NUM_E_SW_LCK (3)
#define BDK_FUSF_FUSE_NUM_E_TRUST_DIS (4)
#define BDK_FUSF_FUSE_NUM_E_TRUST_LVL_CHK (7)
#define BDK_FUSF_FUSE_NUM_E_TZ_FORCE2 (8)
/**
* Register (RSL) fusf_bnk_dat#
*
* Field Fuse Bank Store Register
* The initial state of FUSF_BNK_DAT() is as if bank15 were just read.
* i.e. DAT* = fus[2047:1920].
*/
union bdk_fusf_bnk_datx
{
uint64_t u;
struct bdk_fusf_bnk_datx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SR/W/H) Efuse bank store. For read operations, the DAT gets the fus bank last read. For write
operations, the DAT determines which fuses to blow. */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SR/W/H) Efuse bank store. For read operations, the DAT gets the fus bank last read. For write
operations, the DAT determines which fuses to blow. */
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_bnk_datx_s cn8; */
struct bdk_fusf_bnk_datx_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SR/W/H) Efuse bank store. For read operations, [DAT] gets the fus bank last read. For write
operations, [DAT] determines which fuses to blow. */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SR/W/H) Efuse bank store. For read operations, [DAT] gets the fus bank last read. For write
operations, [DAT] determines which fuses to blow. */
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_fusf_bnk_datx bdk_fusf_bnk_datx_t;
static inline uint64_t BDK_FUSF_BNK_DATX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_BNK_DATX(unsigned long a)
{
if (a<=1)
return 0x87e004000120ll + 8ll * ((a) & 0x1);
__bdk_csr_fatal("FUSF_BNK_DATX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUSF_BNK_DATX(a) bdk_fusf_bnk_datx_t
#define bustype_BDK_FUSF_BNK_DATX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_BNK_DATX(a) "FUSF_BNK_DATX"
#define device_bar_BDK_FUSF_BNK_DATX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_BNK_DATX(a) (a)
#define arguments_BDK_FUSF_BNK_DATX(a) (a),-1,-1,-1
/**
* Register (RSL) fusf_const
*
* Field Fuse Constants Register
*/
union bdk_fusf_const
{
uint64_t u;
struct bdk_fusf_const_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_8_63 : 56;
uint64_t fuse_banks : 8; /**< [ 7: 0](SRO) Number of 128-bit field fuse banks present. */
#else /* Word 0 - Little Endian */
uint64_t fuse_banks : 8; /**< [ 7: 0](SRO) Number of 128-bit field fuse banks present. */
uint64_t reserved_8_63 : 56;
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_const_s cn; */
};
typedef union bdk_fusf_const bdk_fusf_const_t;
#define BDK_FUSF_CONST BDK_FUSF_CONST_FUNC()
static inline uint64_t BDK_FUSF_CONST_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_CONST_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e004000130ll;
__bdk_csr_fatal("FUSF_CONST", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUSF_CONST bdk_fusf_const_t
#define bustype_BDK_FUSF_CONST BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_CONST "FUSF_CONST"
#define device_bar_BDK_FUSF_CONST 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_CONST 0
#define arguments_BDK_FUSF_CONST -1,-1,-1,-1
/**
* Register (RSL) fusf_ctl
*
* Field Fuse Control Register
*/
union bdk_fusf_ctl
{
uint64_t u;
struct bdk_fusf_ctl_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t rom_t_cnt : 32; /**< [ 63: 32](SRO) ROM trusted counter. Reads field fuses FUSF_FUSE_NUM_E::ROM_T_CNT(). */
uint64_t spi_safemode : 1; /**< [ 31: 31](SRO) Reserved.
Internal:
SPI safemode. Reads field fuses FUSF_FUSE_NUM_E::SPI_SAFEMODE. */
uint64_t rom_script_disable : 1; /**< [ 30: 30](SRO) ROM script disable. Reads field fuses FUSF_FUSE_NUM_E::ROM_SCRIPT_DISABLE. */
uint64_t fuse16 : 14; /**< [ 29: 16](SRO) Reserved. */
uint64_t crypt_ssk_dis : 1; /**< [ 15: 15](SRO) SSK crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_SSK_DIS. */
uint64_t crypt_no_dis : 1; /**< [ 14: 14](SRO) No-crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_NO_DIS. */
uint64_t fj_dis_huk : 1; /**< [ 13: 13](SRO) Flash-jump HUK secret hiding. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS_HUK. */
uint64_t fj_core0 : 1; /**< [ 12: 12](SRO) Flash-jump core 0 only. Reads field fuse FUSF_FUSE_NUM_E::FJ_CORE0. */
uint64_t fj_timeout : 2; /**< [ 11: 10](SRO) Flash-jump timeout. Reads field fuse FUSF_FUSE_NUM_E::FJ_TIMEOUT(). */
uint64_t fj_dis : 1; /**< [ 9: 9](SRO) Flash-jump disable. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS. */
uint64_t tz_force2 : 1; /**< [ 8: 8](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t trust_lvl_chk : 1; /**< [ 7: 7](SRO) Trust level check. Reads field fuse FUSF_FUSE_NUM_E::TRUST_LVL_CHK. */
uint64_t mfg_lck : 1; /**< [ 6: 6](SRO) Manufacturing lock. Reads field fuse FUSF_FUSE_NUM_E::MFG_LCK. */
uint64_t fuse5 : 1; /**< [ 5: 5](SRO) Unallocated fuse. */
uint64_t trust_dis : 1; /**< [ 4: 4](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t sw_lck : 1; /**< [ 3: 3](SRO) Software fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SW_LCK. */
uint64_t rot_lck : 1; /**< [ 2: 2](SRO) Root-of-trust fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::ROT_LCK. */
uint64_t ssk_lck : 1; /**< [ 1: 1](SRO) Secret symmetric key fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SSK_LCK. */
uint64_t fusf_lck : 1; /**< [ 0: 0](SRO) Total field fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::FUSF_LCK. */
#else /* Word 0 - Little Endian */
uint64_t fusf_lck : 1; /**< [ 0: 0](SRO) Total field fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::FUSF_LCK. */
uint64_t ssk_lck : 1; /**< [ 1: 1](SRO) Secret symmetric key fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SSK_LCK. */
uint64_t rot_lck : 1; /**< [ 2: 2](SRO) Root-of-trust fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::ROT_LCK. */
uint64_t sw_lck : 1; /**< [ 3: 3](SRO) Software fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SW_LCK. */
uint64_t trust_dis : 1; /**< [ 4: 4](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t fuse5 : 1; /**< [ 5: 5](SRO) Unallocated fuse. */
uint64_t mfg_lck : 1; /**< [ 6: 6](SRO) Manufacturing lock. Reads field fuse FUSF_FUSE_NUM_E::MFG_LCK. */
uint64_t trust_lvl_chk : 1; /**< [ 7: 7](SRO) Trust level check. Reads field fuse FUSF_FUSE_NUM_E::TRUST_LVL_CHK. */
uint64_t tz_force2 : 1; /**< [ 8: 8](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t fj_dis : 1; /**< [ 9: 9](SRO) Flash-jump disable. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS. */
uint64_t fj_timeout : 2; /**< [ 11: 10](SRO) Flash-jump timeout. Reads field fuse FUSF_FUSE_NUM_E::FJ_TIMEOUT(). */
uint64_t fj_core0 : 1; /**< [ 12: 12](SRO) Flash-jump core 0 only. Reads field fuse FUSF_FUSE_NUM_E::FJ_CORE0. */
uint64_t fj_dis_huk : 1; /**< [ 13: 13](SRO) Flash-jump HUK secret hiding. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS_HUK. */
uint64_t crypt_no_dis : 1; /**< [ 14: 14](SRO) No-crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_NO_DIS. */
uint64_t crypt_ssk_dis : 1; /**< [ 15: 15](SRO) SSK crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_SSK_DIS. */
uint64_t fuse16 : 14; /**< [ 29: 16](SRO) Reserved. */
uint64_t rom_script_disable : 1; /**< [ 30: 30](SRO) ROM script disable. Reads field fuses FUSF_FUSE_NUM_E::ROM_SCRIPT_DISABLE. */
uint64_t spi_safemode : 1; /**< [ 31: 31](SRO) Reserved.
Internal:
SPI safemode. Reads field fuses FUSF_FUSE_NUM_E::SPI_SAFEMODE. */
uint64_t rom_t_cnt : 32; /**< [ 63: 32](SRO) ROM trusted counter. Reads field fuses FUSF_FUSE_NUM_E::ROM_T_CNT(). */
#endif /* Word 0 - End */
} s;
struct bdk_fusf_ctl_cn8
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t rom_t_cnt : 32; /**< [ 63: 32](SRO) ROM trusted counter. Reads field fuses FUSF_FUSE_NUM_E::ROM_T_CNT(). */
uint64_t reserved_16_31 : 16;
uint64_t crypt_ssk_dis : 1; /**< [ 15: 15](SRO) SSK crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_SSK_DIS. */
uint64_t crypt_no_dis : 1; /**< [ 14: 14](SRO) No-crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_NO_DIS. */
uint64_t fj_dis_huk : 1; /**< [ 13: 13](SRO) Flash-jump HUK secret hiding. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS_HUK. */
uint64_t fj_core0 : 1; /**< [ 12: 12](SRO) Flash-jump core 0 only. Reads field fuse FUSF_FUSE_NUM_E::FJ_CORE0. */
uint64_t fj_timeout : 2; /**< [ 11: 10](SRO) Flash-jump timeout. Reads field fuse FUSF_FUSE_NUM_E::FJ_TIMEOUT(). */
uint64_t fj_dis : 1; /**< [ 9: 9](SRO) Flash-jump disable. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS. */
uint64_t tz_force2 : 1; /**< [ 8: 8](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t reserved_4_7 : 4;
uint64_t sw_lck : 1; /**< [ 3: 3](SRO) Software fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SW_LCK. */
uint64_t rot_lck : 1; /**< [ 2: 2](SRO) Root-of-trust fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::ROT_LCK. */
uint64_t ssk_lck : 1; /**< [ 1: 1](SRO) Secret symmetric key fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SSK_LCK. */
uint64_t fusf_lck : 1; /**< [ 0: 0](SRO) Total field fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::FUSF_LCK. */
#else /* Word 0 - Little Endian */
uint64_t fusf_lck : 1; /**< [ 0: 0](SRO) Total field fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::FUSF_LCK. */
uint64_t ssk_lck : 1; /**< [ 1: 1](SRO) Secret symmetric key fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SSK_LCK. */
uint64_t rot_lck : 1; /**< [ 2: 2](SRO) Root-of-trust fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::ROT_LCK. */
uint64_t sw_lck : 1; /**< [ 3: 3](SRO) Software fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SW_LCK. */
uint64_t reserved_4_7 : 4;
uint64_t tz_force2 : 1; /**< [ 8: 8](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t fj_dis : 1; /**< [ 9: 9](SRO) Flash-jump disable. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS. */
uint64_t fj_timeout : 2; /**< [ 11: 10](SRO) Flash-jump timeout. Reads field fuse FUSF_FUSE_NUM_E::FJ_TIMEOUT(). */
uint64_t fj_core0 : 1; /**< [ 12: 12](SRO) Flash-jump core 0 only. Reads field fuse FUSF_FUSE_NUM_E::FJ_CORE0. */
uint64_t fj_dis_huk : 1; /**< [ 13: 13](SRO) Flash-jump HUK secret hiding. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS_HUK. */
uint64_t crypt_no_dis : 1; /**< [ 14: 14](SRO) No-crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_NO_DIS. */
uint64_t crypt_ssk_dis : 1; /**< [ 15: 15](SRO) SSK crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_SSK_DIS. */
uint64_t reserved_16_31 : 16;
uint64_t rom_t_cnt : 32; /**< [ 63: 32](SRO) ROM trusted counter. Reads field fuses FUSF_FUSE_NUM_E::ROM_T_CNT(). */
#endif /* Word 0 - End */
} cn8;
struct bdk_fusf_ctl_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t rom_t_cnt : 32; /**< [ 63: 32](SRO) ROM trusted counter. Reads field fuses FUSF_FUSE_NUM_E::ROM_T_CNT(). */
uint64_t spi_safemode : 1; /**< [ 31: 31](SRO) Reserved.
Internal:
SPI safemode. Reads field fuses FUSF_FUSE_NUM_E::SPI_SAFEMODE. */
uint64_t rom_script_disable : 1; /**< [ 30: 30](SRO) ROM script disable. Reads field fuses FUSF_FUSE_NUM_E::ROM_SCRIPT_DISABLE. */
uint64_t fuse16 : 14; /**< [ 29: 16](SRO) Reserved. */
uint64_t crypt_ssk_dis : 1; /**< [ 15: 15](SRO) SSK crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_SSK_DIS. */
uint64_t crypt_no_dis : 1; /**< [ 14: 14](SRO) No-crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_NO_DIS. */
uint64_t fj_dis_huk : 1; /**< [ 13: 13](SRO) Flash-jump HUK secret hiding. Reads field fuse FUSF_FUSE_NUM_E::DIS_HUK. */
uint64_t fj_core0 : 1; /**< [ 12: 12](SRO) Flash-jump core 0 only. Reads field fuse FUSF_FUSE_NUM_E::FJ_CORE0. */
uint64_t fj_timeout : 2; /**< [ 11: 10](SRO) Flash-jump timeout. Reads field fuse FUSF_FUSE_NUM_E::FJ_TIMEOUT(). */
uint64_t fj_dis : 1; /**< [ 9: 9](SRO) Flash-jump disable. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS. */
uint64_t tz_force2 : 1; /**< [ 8: 8](SRO) Trusted mode force override. Reads field fuse FUSF_FUSE_NUM_E::TZ_FORCE2. */
uint64_t trust_lvl_chk : 1; /**< [ 7: 7](SRO) Trust level check. Reads field fuse FUSF_FUSE_NUM_E::TRUST_LVL_CHK. */
uint64_t mfg_lck : 1; /**< [ 6: 6](SRO) Manufacturing lock. Reads field fuse FUSF_FUSE_NUM_E::MFG_LCK. */
uint64_t fuse5 : 1; /**< [ 5: 5](SRO) Unallocated fuse. */
uint64_t trust_dis : 1; /**< [ 4: 4](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t sw_lck : 1; /**< [ 3: 3](SRO) Software fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SW_LCK. */
uint64_t rot_lck : 1; /**< [ 2: 2](SRO) Root-of-trust fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::ROT_LCK. */
uint64_t ssk_lck : 1; /**< [ 1: 1](SRO) Secret symmetric key fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SSK_LCK. */
uint64_t fusf_lck : 1; /**< [ 0: 0](SRO) Total field fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::FUSF_LCK. */
#else /* Word 0 - Little Endian */
uint64_t fusf_lck : 1; /**< [ 0: 0](SRO) Total field fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::FUSF_LCK. */
uint64_t ssk_lck : 1; /**< [ 1: 1](SRO) Secret symmetric key fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SSK_LCK. */
uint64_t rot_lck : 1; /**< [ 2: 2](SRO) Root-of-trust fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::ROT_LCK. */
uint64_t sw_lck : 1; /**< [ 3: 3](SRO) Software fuse lockdown. Reads field fuse FUSF_FUSE_NUM_E::SW_LCK. */
uint64_t trust_dis : 1; /**< [ 4: 4](SRO) Disable Trustzone. Reads field fuse FUSF_FUSE_NUM_E::TRUST_DIS. */
uint64_t fuse5 : 1; /**< [ 5: 5](SRO) Unallocated fuse. */
uint64_t mfg_lck : 1; /**< [ 6: 6](SRO) Manufacturing lock. Reads field fuse FUSF_FUSE_NUM_E::MFG_LCK. */
uint64_t trust_lvl_chk : 1; /**< [ 7: 7](SRO) Trust level check. Reads field fuse FUSF_FUSE_NUM_E::TRUST_LVL_CHK. */
uint64_t tz_force2 : 1; /**< [ 8: 8](SRO) Trusted mode force override. Reads field fuse FUSF_FUSE_NUM_E::TZ_FORCE2. */
uint64_t fj_dis : 1; /**< [ 9: 9](SRO) Flash-jump disable. Reads field fuse FUSF_FUSE_NUM_E::FJ_DIS. */
uint64_t fj_timeout : 2; /**< [ 11: 10](SRO) Flash-jump timeout. Reads field fuse FUSF_FUSE_NUM_E::FJ_TIMEOUT(). */
uint64_t fj_core0 : 1; /**< [ 12: 12](SRO) Flash-jump core 0 only. Reads field fuse FUSF_FUSE_NUM_E::FJ_CORE0. */
uint64_t fj_dis_huk : 1; /**< [ 13: 13](SRO) Flash-jump HUK secret hiding. Reads field fuse FUSF_FUSE_NUM_E::DIS_HUK. */
uint64_t crypt_no_dis : 1; /**< [ 14: 14](SRO) No-crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_NO_DIS. */
uint64_t crypt_ssk_dis : 1; /**< [ 15: 15](SRO) SSK crypt disable. Reads field fuse FUSF_FUSE_NUM_E::CRYPT_SSK_DIS. */
uint64_t fuse16 : 14; /**< [ 29: 16](SRO) Reserved. */
uint64_t rom_script_disable : 1; /**< [ 30: 30](SRO) ROM script disable. Reads field fuses FUSF_FUSE_NUM_E::ROM_SCRIPT_DISABLE. */
uint64_t spi_safemode : 1; /**< [ 31: 31](SRO) Reserved.
Internal:
SPI safemode. Reads field fuses FUSF_FUSE_NUM_E::SPI_SAFEMODE. */
uint64_t rom_t_cnt : 32; /**< [ 63: 32](SRO) ROM trusted counter. Reads field fuses FUSF_FUSE_NUM_E::ROM_T_CNT(). */
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_fusf_ctl bdk_fusf_ctl_t;
#define BDK_FUSF_CTL BDK_FUSF_CTL_FUNC()
static inline uint64_t BDK_FUSF_CTL_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_CTL_FUNC(void)
{
return 0x87e004000000ll;
}
#define typedef_BDK_FUSF_CTL bdk_fusf_ctl_t
#define bustype_BDK_FUSF_CTL BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_CTL "FUSF_CTL"
#define device_bar_BDK_FUSF_CTL 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_CTL 0
#define arguments_BDK_FUSF_CTL -1,-1,-1,-1
/**
* Register (RSL) fusf_eco
*
* INTERNAL: FUSF ECO Register
*/
union bdk_fusf_eco
{
uint64_t u;
struct bdk_fusf_eco_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_32_63 : 32;
uint64_t eco_rw : 32; /**< [ 31: 0](R/W) ECO flops.
This field is always reinitialized on a chip domain reset. */
#else /* Word 0 - Little Endian */
uint64_t eco_rw : 32; /**< [ 31: 0](R/W) ECO flops.
This field is always reinitialized on a chip domain reset. */
uint64_t reserved_32_63 : 32;
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_eco_s cn; */
};
typedef union bdk_fusf_eco bdk_fusf_eco_t;
#define BDK_FUSF_ECO BDK_FUSF_ECO_FUNC()
static inline uint64_t BDK_FUSF_ECO_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_ECO_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e004000118ll;
__bdk_csr_fatal("FUSF_ECO", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUSF_ECO bdk_fusf_eco_t
#define bustype_BDK_FUSF_ECO BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_ECO "FUSF_ECO"
#define device_bar_BDK_FUSF_ECO 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_ECO 0
#define arguments_BDK_FUSF_ECO -1,-1,-1,-1
/**
* Register (RSL) fusf_ek#
*
* Field Fuse ECC Private Endorsement Key Registers
*/
union bdk_fusf_ekx
{
uint64_t u;
struct bdk_fusf_ekx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) ECC private endorsement key. Reads field fuses FUSF_FUSE_NUM_E::EK(). */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) ECC private endorsement key. Reads field fuses FUSF_FUSE_NUM_E::EK(). */
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_ekx_s cn; */
};
typedef union bdk_fusf_ekx bdk_fusf_ekx_t;
static inline uint64_t BDK_FUSF_EKX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_EKX(unsigned long a)
{
if (a<=3)
return 0x87e0040000a0ll + 8ll * ((a) & 0x3);
__bdk_csr_fatal("FUSF_EKX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUSF_EKX(a) bdk_fusf_ekx_t
#define bustype_BDK_FUSF_EKX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_EKX(a) "FUSF_EKX"
#define device_bar_BDK_FUSF_EKX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_EKX(a) (a)
#define arguments_BDK_FUSF_EKX(a) (a),-1,-1,-1
/**
* Register (RSL) fusf_huk#
*
* Field Fuse Hardware Unique Key Registers
*/
union bdk_fusf_hukx
{
uint64_t u;
struct bdk_fusf_hukx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Hardware unique key (HUK). Reads field fuses FUSF_FUSE_NUM_E::HUK(). */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Hardware unique key (HUK). Reads field fuses FUSF_FUSE_NUM_E::HUK(). */
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_hukx_s cn; */
};
typedef union bdk_fusf_hukx bdk_fusf_hukx_t;
static inline uint64_t BDK_FUSF_HUKX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_HUKX(unsigned long a)
{
if (a<=1)
return 0x87e004000090ll + 8ll * ((a) & 0x1);
__bdk_csr_fatal("FUSF_HUKX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUSF_HUKX(a) bdk_fusf_hukx_t
#define bustype_BDK_FUSF_HUKX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_HUKX(a) "FUSF_HUKX"
#define device_bar_BDK_FUSF_HUKX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_HUKX(a) (a)
#define arguments_BDK_FUSF_HUKX(a) (a),-1,-1,-1
/**
* Register (RSL) fusf_prog
*
* Field Fuse Programming Register
*/
union bdk_fusf_prog
{
uint64_t u;
struct bdk_fusf_prog_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_16_63 : 48;
uint64_t efuse : 1; /**< [ 15: 15](SR/W) Efuse storage. When set, the data is written directly to the efuse
bank. When cleared, data is soft blown to local storage.
A soft blown fuse is subject to lockdown fuses.
Soft blown fuses will become active after a chip domain reset
but will not persist through a cold domain reset. */
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be set when
programming fuses (ie. [EFUSE] and [PROG] set). */
uint64_t reserved_8_13 : 6;
uint64_t addr : 4; /**< [ 7: 4](SR/W) Indicates which of bank of 128 fuses to blow. Software
should not change this field while the FUSF_PROG[PROG] bit is set. */
uint64_t reserved_3 : 1;
uint64_t prog_pin : 1; /**< [ 2: 2](SRO) Efuse program voltage (EFUS_PROG) is applied.
Internal:
Indicates state of pi_efuse_pgm_ext not pi_efuse_pgm_int. */
uint64_t sft : 1; /**< [ 1: 1](SR/W/H) When set with [PROG], causes only the local storage to change and will not blow
any fuses. Hardware will clear when the program operation is complete. */
uint64_t reserved_0 : 1;
#else /* Word 0 - Little Endian */
uint64_t reserved_0 : 1;
uint64_t sft : 1; /**< [ 1: 1](SR/W/H) When set with [PROG], causes only the local storage to change and will not blow
any fuses. Hardware will clear when the program operation is complete. */
uint64_t prog_pin : 1; /**< [ 2: 2](SRO) Efuse program voltage (EFUS_PROG) is applied.
Internal:
Indicates state of pi_efuse_pgm_ext not pi_efuse_pgm_int. */
uint64_t reserved_3 : 1;
uint64_t addr : 4; /**< [ 7: 4](SR/W) Indicates which of bank of 128 fuses to blow. Software
should not change this field while the FUSF_PROG[PROG] bit is set. */
uint64_t reserved_8_13 : 6;
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be set when
programming fuses (ie. [EFUSE] and [PROG] set). */
uint64_t efuse : 1; /**< [ 15: 15](SR/W) Efuse storage. When set, the data is written directly to the efuse
bank. When cleared, data is soft blown to local storage.
A soft blown fuse is subject to lockdown fuses.
Soft blown fuses will become active after a chip domain reset
but will not persist through a cold domain reset. */
uint64_t reserved_16_63 : 48;
#endif /* Word 0 - End */
} s;
struct bdk_fusf_prog_cn88xxp1
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_4_63 : 60;
uint64_t volt_en : 1; /**< [ 3: 3](SWO) Enable programming voltage. Asserts EFUSE_ENABLE_L opep-drain output pin. */
uint64_t prog_pin : 1; /**< [ 2: 2](SRO) Efuse program voltage (EFUS_PROG) is applied.
Internal:
Indicates state of pi_efuse_pgm_ext not pi_efuse_pgm_int. */
uint64_t sft : 1; /**< [ 1: 1](SR/W/H) When set with [PROG], causes only the local storage to change and will not blow
any fuses. Hardware will clear when the program operation is complete. */
uint64_t prog : 1; /**< [ 0: 0](SR/W/H) When written to 1 by software, blow the fuse bank. Hardware clears this bit when
the program operation is complete.
To write a bank of fuses, software must set FUSF_WADR[ADDR] to the bank to be
programmed and then set each bit within FUSF_BNK_DATX to indicate which fuses to blow.
Once FUSF_WADR[ADDR], and DAT are setup, software can write to FUSF_PROG[PROG]
to start the bank write and poll on [PROG]. Once PROG is clear, the bank write
is complete. MIO_FUS_READ_TIMES[WRSTB_WH] set the time for the hardware to
clear this bit. A soft blow is still subject to lockdown fuses. After a
soft/warm reset, the chip behaves as though the fuses were actually blown. A
cold reset restores the actual fuse values. */
#else /* Word 0 - Little Endian */
uint64_t prog : 1; /**< [ 0: 0](SR/W/H) When written to 1 by software, blow the fuse bank. Hardware clears this bit when
the program operation is complete.
To write a bank of fuses, software must set FUSF_WADR[ADDR] to the bank to be
programmed and then set each bit within FUSF_BNK_DATX to indicate which fuses to blow.
Once FUSF_WADR[ADDR], and DAT are setup, software can write to FUSF_PROG[PROG]
to start the bank write and poll on [PROG]. Once PROG is clear, the bank write
is complete. MIO_FUS_READ_TIMES[WRSTB_WH] set the time for the hardware to
clear this bit. A soft blow is still subject to lockdown fuses. After a
soft/warm reset, the chip behaves as though the fuses were actually blown. A
cold reset restores the actual fuse values. */
uint64_t sft : 1; /**< [ 1: 1](SR/W/H) When set with [PROG], causes only the local storage to change and will not blow
any fuses. Hardware will clear when the program operation is complete. */
uint64_t prog_pin : 1; /**< [ 2: 2](SRO) Efuse program voltage (EFUS_PROG) is applied.
Internal:
Indicates state of pi_efuse_pgm_ext not pi_efuse_pgm_int. */
uint64_t volt_en : 1; /**< [ 3: 3](SWO) Enable programming voltage. Asserts EFUSE_ENABLE_L opep-drain output pin. */
uint64_t reserved_4_63 : 60;
#endif /* Word 0 - End */
} cn88xxp1;
struct bdk_fusf_prog_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_16_63 : 48;
uint64_t efuse : 1; /**< [ 15: 15](SR/W) Efuse storage. When set, the data is written directly to the efuse
bank. When cleared, data is soft blown to local storage.
A soft blown fuse is subject to lockdown fuses.
Soft blown fuses will become active after a chip domain reset
but will not persist through a cold domain reset. */
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be set when
programming fuses (ie. [EFUSE] and [PROG] set). */
uint64_t volt_en : 1; /**< [ 13: 13](SR/W) Enable programming voltage. Asserts EFUSE_ENABLE_L open-drain output pin. */
uint64_t prog : 1; /**< [ 12: 12](SR/W/H) Internal:
When written to one by software, blow the fuse bank. Hardware will
clear the field when the program operation is complete.
To write a bank of fuses, software must write the fuse data into
FUSF_BNK_DAT(). Then it writes the ADDR and EFUSE fields of this register
and sets the PROG bit. Hardware will clear the [PROG] when the write is
completed. New fuses will become active after a chip domain reset. */
uint64_t reserved_8_11 : 4;
uint64_t addr : 4; /**< [ 7: 4](SR/W) Indicates which of bank of 128 fuses to blow. Software
should not change this field while the FUSF_PROG[PROG] bit is set. */
uint64_t reserved_0_3 : 4;
#else /* Word 0 - Little Endian */
uint64_t reserved_0_3 : 4;
uint64_t addr : 4; /**< [ 7: 4](SR/W) Indicates which of bank of 128 fuses to blow. Software
should not change this field while the FUSF_PROG[PROG] bit is set. */
uint64_t reserved_8_11 : 4;
uint64_t prog : 1; /**< [ 12: 12](SR/W/H) Internal:
When written to one by software, blow the fuse bank. Hardware will
clear the field when the program operation is complete.
To write a bank of fuses, software must write the fuse data into
FUSF_BNK_DAT(). Then it writes the ADDR and EFUSE fields of this register
and sets the PROG bit. Hardware will clear the [PROG] when the write is
completed. New fuses will become active after a chip domain reset. */
uint64_t volt_en : 1; /**< [ 13: 13](SR/W) Enable programming voltage. Asserts EFUSE_ENABLE_L open-drain output pin. */
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be set when
programming fuses (ie. [EFUSE] and [PROG] set). */
uint64_t efuse : 1; /**< [ 15: 15](SR/W) Efuse storage. When set, the data is written directly to the efuse
bank. When cleared, data is soft blown to local storage.
A soft blown fuse is subject to lockdown fuses.
Soft blown fuses will become active after a chip domain reset
but will not persist through a cold domain reset. */
uint64_t reserved_16_63 : 48;
#endif /* Word 0 - End */
} cn9;
struct bdk_fusf_prog_cn81xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_4_63 : 60;
uint64_t volt_en : 1; /**< [ 3: 3](SR/W) Enable programming voltage. Asserts EFUSE_ENABLE_L open-drain output pin. */
uint64_t prog_pin : 1; /**< [ 2: 2](SRO) Efuse program voltage (EFUS_PROG) is applied.
Internal:
Indicates state of pi_efuse_pgm_ext not pi_efuse_pgm_int. */
uint64_t sft : 1; /**< [ 1: 1](SR/W/H) When set with [PROG], causes only the local storage to change and will not blow
any fuses. Hardware will clear when the program operation is complete. */
uint64_t prog : 1; /**< [ 0: 0](SR/W/H) When written to 1 by software, blow the fuse bank. Hardware clears this bit when
the program operation is complete.
To write a bank of fuses, software must set FUSF_WADR[ADDR] to the bank to be
programmed and then set each bit within FUSF_BNK_DATX to indicate which fuses to blow.
Once FUSF_WADR[ADDR], and DAT are setup, software can write to FUSF_PROG[PROG]
to start the bank write and poll on [PROG]. Once PROG is clear, the bank write
is complete. MIO_FUS_READ_TIMES[WRSTB_WH] set the time for the hardware to
clear this bit. A soft blow is still subject to lockdown fuses. After a
soft/warm reset, the chip behaves as though the fuses were actually blown. A
cold reset restores the actual fuse values. */
#else /* Word 0 - Little Endian */
uint64_t prog : 1; /**< [ 0: 0](SR/W/H) When written to 1 by software, blow the fuse bank. Hardware clears this bit when
the program operation is complete.
To write a bank of fuses, software must set FUSF_WADR[ADDR] to the bank to be
programmed and then set each bit within FUSF_BNK_DATX to indicate which fuses to blow.
Once FUSF_WADR[ADDR], and DAT are setup, software can write to FUSF_PROG[PROG]
to start the bank write and poll on [PROG]. Once PROG is clear, the bank write
is complete. MIO_FUS_READ_TIMES[WRSTB_WH] set the time for the hardware to
clear this bit. A soft blow is still subject to lockdown fuses. After a
soft/warm reset, the chip behaves as though the fuses were actually blown. A
cold reset restores the actual fuse values. */
uint64_t sft : 1; /**< [ 1: 1](SR/W/H) When set with [PROG], causes only the local storage to change and will not blow
any fuses. Hardware will clear when the program operation is complete. */
uint64_t prog_pin : 1; /**< [ 2: 2](SRO) Efuse program voltage (EFUS_PROG) is applied.
Internal:
Indicates state of pi_efuse_pgm_ext not pi_efuse_pgm_int. */
uint64_t volt_en : 1; /**< [ 3: 3](SR/W) Enable programming voltage. Asserts EFUSE_ENABLE_L open-drain output pin. */
uint64_t reserved_4_63 : 60;
#endif /* Word 0 - End */
} cn81xx;
/* struct bdk_fusf_prog_cn81xx cn83xx; */
/* struct bdk_fusf_prog_cn81xx cn88xxp2; */
};
typedef union bdk_fusf_prog bdk_fusf_prog_t;
#define BDK_FUSF_PROG BDK_FUSF_PROG_FUNC()
static inline uint64_t BDK_FUSF_PROG_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_PROG_FUNC(void)
{
return 0x87e004000110ll;
}
#define typedef_BDK_FUSF_PROG bdk_fusf_prog_t
#define bustype_BDK_FUSF_PROG BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_PROG "FUSF_PROG"
#define device_bar_BDK_FUSF_PROG 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_PROG 0
#define arguments_BDK_FUSF_PROG -1,-1,-1,-1
/**
* Register (RSL) fusf_rcmd
*
* Field Fuse Read Command Register
* To read an efuse, software writes FUSF_RCMD[ADDR, PEND] with the byte address of
* the fuse in
* question, then software can poll FUSF_RCMD[PEND]. When [PEND] is clear and if the efuse read
* went to the efuse banks (e.g. EFUSE was set on the read), software can read FUSF_BNK_DATx
* which contains all 128 fuses in the bank associated in ADDR.
*/
union bdk_fusf_rcmd
{
uint64_t u;
struct bdk_fusf_rcmd_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_15_63 : 49;
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be cleared when
reading fuses directly (ie. [EFUSE] and [PEND] set). */
uint64_t reserved_13 : 1;
uint64_t pend : 1; /**< [ 12: 12](SR/W/H) Software sets this bit on a write to start FUSE read operation.
Hardware clears the bit when the read is complete and the DAT is
valid. MIO_FUS_READ_TIMES[RDSTB_WH] determines the time for this
operation. */
uint64_t reserved_11 : 1;
uint64_t addr_hi : 2; /**< [ 10: 9](SR/W) Upper fuse address bits to extend space beyond 2k fuses. Valid range is
0x0. Enumerated by FUSF_FUSE_NUM_E\<9:8\>. */
uint64_t reserved_0_8 : 9;
#else /* Word 0 - Little Endian */
uint64_t reserved_0_8 : 9;
uint64_t addr_hi : 2; /**< [ 10: 9](SR/W) Upper fuse address bits to extend space beyond 2k fuses. Valid range is
0x0. Enumerated by FUSF_FUSE_NUM_E\<9:8\>. */
uint64_t reserved_11 : 1;
uint64_t pend : 1; /**< [ 12: 12](SR/W/H) Software sets this bit on a write to start FUSE read operation.
Hardware clears the bit when the read is complete and the DAT is
valid. MIO_FUS_READ_TIMES[RDSTB_WH] determines the time for this
operation. */
uint64_t reserved_13 : 1;
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be cleared when
reading fuses directly (ie. [EFUSE] and [PEND] set). */
uint64_t reserved_15_63 : 49;
#endif /* Word 0 - End */
} s;
struct bdk_fusf_rcmd_cn8
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_24_63 : 40;
uint64_t reserved_16_23 : 8;
uint64_t reserved_13_15 : 3;
uint64_t pend : 1; /**< [ 12: 12](SR/W/H) Software sets this bit on a write to start FUSE read operation.
Hardware clears the bit when the read is complete and the DAT is
valid. MIO_FUS_READ_TIMES[RDSTB_WH] determines the time for this
operation. */
uint64_t reserved_11 : 1;
uint64_t addr_hi : 2; /**< [ 10: 9](SR/W) Upper fuse address bits to extend space beyond 2k fuses. Valid range is
0x0. Enumerated by FUSF_FUSE_NUM_E\<9:8\>. */
uint64_t efuse : 1; /**< [ 8: 8](SR/W) When set, return data from the efuse storage rather than the local storage.
Software should not change this field while the FUSF_RCMD[PEND] is set.
It should wait for the hardware to clear the bit first. */
uint64_t addr : 8; /**< [ 7: 0](SR/W) The byte address of the fuse to read. Enumerated by FUSF_FUSE_NUM_E\<7:0\>. */
#else /* Word 0 - Little Endian */
uint64_t addr : 8; /**< [ 7: 0](SR/W) The byte address of the fuse to read. Enumerated by FUSF_FUSE_NUM_E\<7:0\>. */
uint64_t efuse : 1; /**< [ 8: 8](SR/W) When set, return data from the efuse storage rather than the local storage.
Software should not change this field while the FUSF_RCMD[PEND] is set.
It should wait for the hardware to clear the bit first. */
uint64_t addr_hi : 2; /**< [ 10: 9](SR/W) Upper fuse address bits to extend space beyond 2k fuses. Valid range is
0x0. Enumerated by FUSF_FUSE_NUM_E\<9:8\>. */
uint64_t reserved_11 : 1;
uint64_t pend : 1; /**< [ 12: 12](SR/W/H) Software sets this bit on a write to start FUSE read operation.
Hardware clears the bit when the read is complete and the DAT is
valid. MIO_FUS_READ_TIMES[RDSTB_WH] determines the time for this
operation. */
uint64_t reserved_13_15 : 3;
uint64_t reserved_16_23 : 8;
uint64_t reserved_24_63 : 40;
#endif /* Word 0 - End */
} cn8;
struct bdk_fusf_rcmd_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_16_63 : 48;
uint64_t efuse : 1; /**< [ 15: 15](SR/W) Efuse storage. When set, the return data is from the efuse
bank directly. When cleared data is read from the local storage. */
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be cleared when
reading fuses directly (ie. [EFUSE] and [PEND] set). */
uint64_t reserved_13 : 1;
uint64_t pend : 1; /**< [ 12: 12](SR/W/H) Software sets this bit to one on a write operation that starts
the fuse read operation. Hardware clears this bit when the read
operation is complete and FUS_BNK_DAT() is valid.
FUS_READ_TIMES[RDSTB_WH] determines the time for the operation
to complete. */
uint64_t reserved_8_11 : 4;
uint64_t addr : 4; /**< [ 7: 4](SR/W) Address. Specifies the bank address of 128 fuses to read.
Software should not change this field while [PEND]
is set. It must wait for the hardware to clear it. */
uint64_t reserved_0_3 : 4;
#else /* Word 0 - Little Endian */
uint64_t reserved_0_3 : 4;
uint64_t addr : 4; /**< [ 7: 4](SR/W) Address. Specifies the bank address of 128 fuses to read.
Software should not change this field while [PEND]
is set. It must wait for the hardware to clear it. */
uint64_t reserved_8_11 : 4;
uint64_t pend : 1; /**< [ 12: 12](SR/W/H) Software sets this bit to one on a write operation that starts
the fuse read operation. Hardware clears this bit when the read
operation is complete and FUS_BNK_DAT() is valid.
FUS_READ_TIMES[RDSTB_WH] determines the time for the operation
to complete. */
uint64_t reserved_13 : 1;
uint64_t voltage : 1; /**< [ 14: 14](SRO) Efuse programming voltage status. When set, EFUSE banks have
programming voltage applied. Required to be cleared when
reading fuses directly (ie. [EFUSE] and [PEND] set). */
uint64_t efuse : 1; /**< [ 15: 15](SR/W) Efuse storage. When set, the return data is from the efuse
bank directly. When cleared data is read from the local storage. */
uint64_t reserved_16_63 : 48;
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_fusf_rcmd bdk_fusf_rcmd_t;
#define BDK_FUSF_RCMD BDK_FUSF_RCMD_FUNC()
static inline uint64_t BDK_FUSF_RCMD_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_RCMD_FUNC(void)
{
return 0x87e004000100ll;
}
#define typedef_BDK_FUSF_RCMD bdk_fusf_rcmd_t
#define bustype_BDK_FUSF_RCMD BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_RCMD "FUSF_RCMD"
#define device_bar_BDK_FUSF_RCMD 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_RCMD 0
#define arguments_BDK_FUSF_RCMD -1,-1,-1,-1
/**
* Register (RSL) fusf_rotpk#
*
* Field Fuse Root-of-Trust Public Key Registers
*/
union bdk_fusf_rotpkx
{
uint64_t u;
struct bdk_fusf_rotpkx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Hash of the root-of-trust public key (ROTPK). Reads field fuses FUSF_FUSE_NUM_E::ROTPK(). */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Hash of the root-of-trust public key (ROTPK). Reads field fuses FUSF_FUSE_NUM_E::ROTPK(). */
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_rotpkx_s cn; */
};
typedef union bdk_fusf_rotpkx bdk_fusf_rotpkx_t;
static inline uint64_t BDK_FUSF_ROTPKX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_ROTPKX(unsigned long a)
{
if (a<=3)
return 0x87e004000060ll + 8ll * ((a) & 0x3);
__bdk_csr_fatal("FUSF_ROTPKX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUSF_ROTPKX(a) bdk_fusf_rotpkx_t
#define bustype_BDK_FUSF_ROTPKX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_ROTPKX(a) "FUSF_ROTPKX"
#define device_bar_BDK_FUSF_ROTPKX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_ROTPKX(a) (a)
#define arguments_BDK_FUSF_ROTPKX(a) (a),-1,-1,-1
/**
* Register (RSL) fusf_ssk#
*
* Field Fuse Secret Symmetric Key Registers
*/
union bdk_fusf_sskx
{
uint64_t u;
struct bdk_fusf_sskx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Secret symmetric key (SSK). Reads field fuses FUSF_FUSE_NUM_E::SSK(). */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Secret symmetric key (SSK). Reads field fuses FUSF_FUSE_NUM_E::SSK(). */
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_sskx_s cn; */
};
typedef union bdk_fusf_sskx bdk_fusf_sskx_t;
static inline uint64_t BDK_FUSF_SSKX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_SSKX(unsigned long a)
{
if (a<=1)
return 0x87e004000080ll + 8ll * ((a) & 0x1);
__bdk_csr_fatal("FUSF_SSKX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUSF_SSKX(a) bdk_fusf_sskx_t
#define bustype_BDK_FUSF_SSKX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_SSKX(a) "FUSF_SSKX"
#define device_bar_BDK_FUSF_SSKX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_SSKX(a) (a)
#define arguments_BDK_FUSF_SSKX(a) (a),-1,-1,-1
/**
* Register (RSL) fusf_sw#
*
* Field Fuse Software Fuses Registers
*/
union bdk_fusf_swx
{
uint64_t u;
struct bdk_fusf_swx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Software assigned fuse data. Reads field fuses FUSF_FUSE_NUM_E::SW(). */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO) Software assigned fuse data. Reads field fuses FUSF_FUSE_NUM_E::SW(). */
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_swx_s cn; */
};
typedef union bdk_fusf_swx bdk_fusf_swx_t;
static inline uint64_t BDK_FUSF_SWX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_SWX(unsigned long a)
{
if (a<=7)
return 0x87e0040000c0ll + 8ll * ((a) & 0x7);
__bdk_csr_fatal("FUSF_SWX", 1, a, 0, 0, 0);
}
#define typedef_BDK_FUSF_SWX(a) bdk_fusf_swx_t
#define bustype_BDK_FUSF_SWX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_SWX(a) "FUSF_SWX"
#define device_bar_BDK_FUSF_SWX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_SWX(a) (a)
#define arguments_BDK_FUSF_SWX(a) (a),-1,-1,-1
/**
* Register (RSL) fusf_wadr
*
* Field Fuse Write Address Register
*/
union bdk_fusf_wadr
{
uint64_t u;
struct bdk_fusf_wadr_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_4_63 : 60;
uint64_t addr : 4; /**< [ 3: 0](SR/W) Indicates which of the banks of 128 fuses to blow. Enumerated by FUSF_FUSE_NUM_E\<10:7\>. */
#else /* Word 0 - Little Endian */
uint64_t addr : 4; /**< [ 3: 0](SR/W) Indicates which of the banks of 128 fuses to blow. Enumerated by FUSF_FUSE_NUM_E\<10:7\>. */
uint64_t reserved_4_63 : 60;
#endif /* Word 0 - End */
} s;
/* struct bdk_fusf_wadr_s cn; */
};
typedef union bdk_fusf_wadr bdk_fusf_wadr_t;
#define BDK_FUSF_WADR BDK_FUSF_WADR_FUNC()
static inline uint64_t BDK_FUSF_WADR_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_FUSF_WADR_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
return 0x87e004000108ll;
__bdk_csr_fatal("FUSF_WADR", 0, 0, 0, 0, 0);
}
#define typedef_BDK_FUSF_WADR bdk_fusf_wadr_t
#define bustype_BDK_FUSF_WADR BDK_CSR_TYPE_RSL
#define basename_BDK_FUSF_WADR "FUSF_WADR"
#define device_bar_BDK_FUSF_WADR 0x0 /* PF_BAR0 */
#define busnum_BDK_FUSF_WADR 0
#define arguments_BDK_FUSF_WADR -1,-1,-1,-1
#endif /* __BDK_CSRS_FUSF_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,150 @@
#ifndef __BDK_CSRS_LMT_H__
#define __BDK_CSRS_LMT_H__
/* This file is auto-generated. Do not edit */
/***********************license start***************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Configuration and status register (CSR) address and type definitions for
* Cavium LMT.
*
* This file is auto generated. Do not edit.
*
*/
/**
* Register (RVU_PFVF_BAR2) lmt_lf_lmtcancel
*
* RVU VF LMT Cancel Register
*/
union bdk_lmt_lf_lmtcancel
{
uint64_t u;
struct bdk_lmt_lf_lmtcancel_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t data : 64; /**< [ 63: 0](WO) This register's address is used to perform an AP LMTCANCEL operation. This is
only used by code executing on AP cores and has no function when accessed by
other entities.
Internal:
LMTLINE and LMTCANCEL addresses are consumed by APs and never received by
RVU. See also RVU_BLOCK_ADDR_E::LMT. */
#else /* Word 0 - Little Endian */
uint64_t data : 64; /**< [ 63: 0](WO) This register's address is used to perform an AP LMTCANCEL operation. This is
only used by code executing on AP cores and has no function when accessed by
other entities.
Internal:
LMTLINE and LMTCANCEL addresses are consumed by APs and never received by
RVU. See also RVU_BLOCK_ADDR_E::LMT. */
#endif /* Word 0 - End */
} s;
/* struct bdk_lmt_lf_lmtcancel_s cn; */
};
typedef union bdk_lmt_lf_lmtcancel bdk_lmt_lf_lmtcancel_t;
#define BDK_LMT_LF_LMTCANCEL BDK_LMT_LF_LMTCANCEL_FUNC()
static inline uint64_t BDK_LMT_LF_LMTCANCEL_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_LMT_LF_LMTCANCEL_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x850200100400ll;
__bdk_csr_fatal("LMT_LF_LMTCANCEL", 0, 0, 0, 0, 0);
}
#define typedef_BDK_LMT_LF_LMTCANCEL bdk_lmt_lf_lmtcancel_t
#define bustype_BDK_LMT_LF_LMTCANCEL BDK_CSR_TYPE_RVU_PFVF_BAR2
#define basename_BDK_LMT_LF_LMTCANCEL "LMT_LF_LMTCANCEL"
#define device_bar_BDK_LMT_LF_LMTCANCEL 0x2 /* BAR2 */
#define busnum_BDK_LMT_LF_LMTCANCEL 0
#define arguments_BDK_LMT_LF_LMTCANCEL -1,-1,-1,-1
/**
* Register (RVU_PFVF_BAR2) lmt_lf_lmtline#
*
* RVU VF LMT Line Registers
*/
union bdk_lmt_lf_lmtlinex
{
uint64_t u;
struct bdk_lmt_lf_lmtlinex_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t data : 64; /**< [ 63: 0](WO) This register's address is the 128-byte LMTLINE used to form LMTST
operations. This is only used by code executing on AP cores and has no function
when accessed by other entities.
Internal:
LMTLINE and LMTCANCEL addresses are consumed by APs and never received by
RVU. See also RVU_BLOCK_ADDR_E::LMT. */
#else /* Word 0 - Little Endian */
uint64_t data : 64; /**< [ 63: 0](WO) This register's address is the 128-byte LMTLINE used to form LMTST
operations. This is only used by code executing on AP cores and has no function
when accessed by other entities.
Internal:
LMTLINE and LMTCANCEL addresses are consumed by APs and never received by
RVU. See also RVU_BLOCK_ADDR_E::LMT. */
#endif /* Word 0 - End */
} s;
/* struct bdk_lmt_lf_lmtlinex_s cn; */
};
typedef union bdk_lmt_lf_lmtlinex bdk_lmt_lf_lmtlinex_t;
static inline uint64_t BDK_LMT_LF_LMTLINEX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_LMT_LF_LMTLINEX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=15))
return 0x850200100000ll + 8ll * ((a) & 0xf);
__bdk_csr_fatal("LMT_LF_LMTLINEX", 1, a, 0, 0, 0);
}
#define typedef_BDK_LMT_LF_LMTLINEX(a) bdk_lmt_lf_lmtlinex_t
#define bustype_BDK_LMT_LF_LMTLINEX(a) BDK_CSR_TYPE_RVU_PFVF_BAR2
#define basename_BDK_LMT_LF_LMTLINEX(a) "LMT_LF_LMTLINEX"
#define device_bar_BDK_LMT_LF_LMTLINEX(a) 0x2 /* BAR2 */
#define busnum_BDK_LMT_LF_LMTLINEX(a) (a)
#define arguments_BDK_LMT_LF_LMTLINEX(a) (a),-1,-1,-1
#endif /* __BDK_CSRS_LMT_H__ */

View File

@ -0,0 +1,537 @@
#ifndef __BDK_CSRS_MIO_BOOT_H__
#define __BDK_CSRS_MIO_BOOT_H__
/* This file is auto-generated. Do not edit */
/***********************license start***************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Configuration and status register (CSR) address and type definitions for
* Cavium MIO_BOOT.
*
* This file is auto generated. Do not edit.
*
*/
/**
* Enumeration mio_boot_bar_e
*
* MIO Boot Base Address Register Enumeration
* Enumerates the base address registers.
*/
#define BDK_MIO_BOOT_BAR_E_MIO_BOOT_PF_BAR0 (0x87e000000000ll)
#define BDK_MIO_BOOT_BAR_E_MIO_BOOT_PF_BAR0_SIZE 0x800000ull
/**
* Register (RSL) mio_boot_ap_jump
*
* MIO Boot AP Jump Address Register
*/
union bdk_mio_boot_ap_jump
{
uint64_t u;
struct bdk_mio_boot_ap_jump_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t addr : 64; /**< [ 63: 0](SR/W) Boot address. This register contains the address the internal boot loader
will jump to after reset. */
#else /* Word 0 - Little Endian */
uint64_t addr : 64; /**< [ 63: 0](SR/W) Boot address. This register contains the address the internal boot loader
will jump to after reset. */
#endif /* Word 0 - End */
} s;
/* struct bdk_mio_boot_ap_jump_s cn; */
};
typedef union bdk_mio_boot_ap_jump bdk_mio_boot_ap_jump_t;
#define BDK_MIO_BOOT_AP_JUMP BDK_MIO_BOOT_AP_JUMP_FUNC()
static inline uint64_t BDK_MIO_BOOT_AP_JUMP_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_MIO_BOOT_AP_JUMP_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
return 0x87e0000000d0ll;
__bdk_csr_fatal("MIO_BOOT_AP_JUMP", 0, 0, 0, 0, 0);
}
#define typedef_BDK_MIO_BOOT_AP_JUMP bdk_mio_boot_ap_jump_t
#define bustype_BDK_MIO_BOOT_AP_JUMP BDK_CSR_TYPE_RSL
#define basename_BDK_MIO_BOOT_AP_JUMP "MIO_BOOT_AP_JUMP"
#define device_bar_BDK_MIO_BOOT_AP_JUMP 0x0 /* PF_BAR0 */
#define busnum_BDK_MIO_BOOT_AP_JUMP 0
#define arguments_BDK_MIO_BOOT_AP_JUMP -1,-1,-1,-1
/**
* Register (RSL) mio_boot_bist_stat
*
* MIO Boot BIST Status Register
* The boot BIST status register contains the BIST status for the MIO boot memories: 0 = pass, 1
* = fail.
*/
union bdk_mio_boot_bist_stat
{
uint64_t u;
struct bdk_mio_boot_bist_stat_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_16_63 : 48;
uint64_t stat : 16; /**< [ 15: 0](RO/H) BIST status.
Internal:
\<0\> = mio.mio_boot.mio_boot_fifo.mem.
\<1\> = mio.mio_boot.mio_boot_rsp.mem.
\<2\> = mio.mio_boot.mio_boot_dma.mem.
\<3\> = mio.mio_nbt.mio_nbt_fifo.mem.
\<4\> = mio.mio_emm.bufs.mem.mem.
\<5\> = mio.mio_nbr.ncbo_crd_fif_mem0.
\<6\> = mio.csr.csr_fifo.
\<7\> = mio_boot_rom/mio_boot_rom1 (internal bootroms).
\<8\> = mio.mio_rsl.mio_pcc.gpi_pcc.
\<9\> = mio.mio_pbus.mio_pbus_fifo.mem.
\<10\> = mio.mio_pbus.mio_pbus_rsp.mem.
\<11\> = mio.mio_ndf.mio_ndf_bufs.ndf_buf.
\<12\> = mio.mio_ndf.ndf_ncb_rcv_fif.
\<13\> = mio.mio_pcm.mio_pcm_ctl.dmamem.
\<14\> = mio.mio_pcm.mio_pcm_ctl.maskmem.
\<15\> = mio.mio_nbt.mio_nbt_pfifo.mem. */
#else /* Word 0 - Little Endian */
uint64_t stat : 16; /**< [ 15: 0](RO/H) BIST status.
Internal:
\<0\> = mio.mio_boot.mio_boot_fifo.mem.
\<1\> = mio.mio_boot.mio_boot_rsp.mem.
\<2\> = mio.mio_boot.mio_boot_dma.mem.
\<3\> = mio.mio_nbt.mio_nbt_fifo.mem.
\<4\> = mio.mio_emm.bufs.mem.mem.
\<5\> = mio.mio_nbr.ncbo_crd_fif_mem0.
\<6\> = mio.csr.csr_fifo.
\<7\> = mio_boot_rom/mio_boot_rom1 (internal bootroms).
\<8\> = mio.mio_rsl.mio_pcc.gpi_pcc.
\<9\> = mio.mio_pbus.mio_pbus_fifo.mem.
\<10\> = mio.mio_pbus.mio_pbus_rsp.mem.
\<11\> = mio.mio_ndf.mio_ndf_bufs.ndf_buf.
\<12\> = mio.mio_ndf.ndf_ncb_rcv_fif.
\<13\> = mio.mio_pcm.mio_pcm_ctl.dmamem.
\<14\> = mio.mio_pcm.mio_pcm_ctl.maskmem.
\<15\> = mio.mio_nbt.mio_nbt_pfifo.mem. */
uint64_t reserved_16_63 : 48;
#endif /* Word 0 - End */
} s;
/* struct bdk_mio_boot_bist_stat_s cn81xx; */
struct bdk_mio_boot_bist_stat_cn88xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_9_63 : 55;
uint64_t stat : 9; /**< [ 8: 0](RO/H) BIST status.
Internal:
\<0\> = mio.mio_boot.mio_boot_fifo.mem.
\<1\> = mio.mio_boot.mio_boot_rsp.mem.
\<2\> = mio.mio_boot.mio_boot_dma.mem.
\<3\> = mio.mio_nbt.mio_nbt_fifo.mem.
\<4\> = mio.mio_emm.bufs.mem.mem.
\<5\> = mio.mio_nbr.ncbo_crd_fif_mem0.
\<6\> = mio.csr.csr_fifo.
\<7\> = mio_boot_rom/mio_boot_rom1 (internal bootroms).
\<8\> = mio.mio_rsl.mio_pcc.gpi_pcc. */
#else /* Word 0 - Little Endian */
uint64_t stat : 9; /**< [ 8: 0](RO/H) BIST status.
Internal:
\<0\> = mio.mio_boot.mio_boot_fifo.mem.
\<1\> = mio.mio_boot.mio_boot_rsp.mem.
\<2\> = mio.mio_boot.mio_boot_dma.mem.
\<3\> = mio.mio_nbt.mio_nbt_fifo.mem.
\<4\> = mio.mio_emm.bufs.mem.mem.
\<5\> = mio.mio_nbr.ncbo_crd_fif_mem0.
\<6\> = mio.csr.csr_fifo.
\<7\> = mio_boot_rom/mio_boot_rom1 (internal bootroms).
\<8\> = mio.mio_rsl.mio_pcc.gpi_pcc. */
uint64_t reserved_9_63 : 55;
#endif /* Word 0 - End */
} cn88xx;
struct bdk_mio_boot_bist_stat_cn83xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_13_63 : 51;
uint64_t stat : 13; /**< [ 12: 0](RO/H) BIST status.
Internal:
\<0\> = mio.mio_boot.mio_boot_fifo.mem.
\<1\> = mio.mio_boot.mio_boot_rsp.mem.
\<2\> = mio.mio_boot.mio_boot_dma.mem.
\<3\> = mio.mio_nbt.mio_nbt_fifo.mem.
\<4\> = mio.mio_emm.bufs.mem.mem.
\<5\> = mio.mio_nbr.ncbo_crd_fif_mem0.
\<6\> = mio.csr.csr_fifo.
\<7\> = mio_boot_rom/mio_boot_rom1 (internal bootroms).
\<8\> = mio.mio_rsl.mio_pcc.gpi_pcc.
\<9\> = mio.mio_pbus.mio_pbus_fifo.mem.
\<10\> = mio.mio_pbus.mio_pbus_rsp.mem.
\<11\> = mio.mio_ndf.mio_ndf_bufs.ndf_buf.
\<12\> = mio.mio_ndf.ndf_ncb_rcv_fif. */
#else /* Word 0 - Little Endian */
uint64_t stat : 13; /**< [ 12: 0](RO/H) BIST status.
Internal:
\<0\> = mio.mio_boot.mio_boot_fifo.mem.
\<1\> = mio.mio_boot.mio_boot_rsp.mem.
\<2\> = mio.mio_boot.mio_boot_dma.mem.
\<3\> = mio.mio_nbt.mio_nbt_fifo.mem.
\<4\> = mio.mio_emm.bufs.mem.mem.
\<5\> = mio.mio_nbr.ncbo_crd_fif_mem0.
\<6\> = mio.csr.csr_fifo.
\<7\> = mio_boot_rom/mio_boot_rom1 (internal bootroms).
\<8\> = mio.mio_rsl.mio_pcc.gpi_pcc.
\<9\> = mio.mio_pbus.mio_pbus_fifo.mem.
\<10\> = mio.mio_pbus.mio_pbus_rsp.mem.
\<11\> = mio.mio_ndf.mio_ndf_bufs.ndf_buf.
\<12\> = mio.mio_ndf.ndf_ncb_rcv_fif. */
uint64_t reserved_13_63 : 51;
#endif /* Word 0 - End */
} cn83xx;
};
typedef union bdk_mio_boot_bist_stat bdk_mio_boot_bist_stat_t;
#define BDK_MIO_BOOT_BIST_STAT BDK_MIO_BOOT_BIST_STAT_FUNC()
static inline uint64_t BDK_MIO_BOOT_BIST_STAT_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_MIO_BOOT_BIST_STAT_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
return 0x87e0000000f8ll;
__bdk_csr_fatal("MIO_BOOT_BIST_STAT", 0, 0, 0, 0, 0);
}
#define typedef_BDK_MIO_BOOT_BIST_STAT bdk_mio_boot_bist_stat_t
#define bustype_BDK_MIO_BOOT_BIST_STAT BDK_CSR_TYPE_RSL
#define basename_BDK_MIO_BOOT_BIST_STAT "MIO_BOOT_BIST_STAT"
#define device_bar_BDK_MIO_BOOT_BIST_STAT 0x0 /* PF_BAR0 */
#define busnum_BDK_MIO_BOOT_BIST_STAT 0
#define arguments_BDK_MIO_BOOT_BIST_STAT -1,-1,-1,-1
/**
* Register (RSL) mio_boot_pin_defs
*
* MIO Boot Pin Defaults Register
* This register reflects the value of some of the pins sampled
* at the rising edge of PLL_DCOK. The GPIO pins sampled at
* the same time are available in the GPIO_STRAP csr.
*/
union bdk_mio_boot_pin_defs
{
uint64_t u;
struct bdk_mio_boot_pin_defs_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_18_63 : 46;
uint64_t uart1_rts : 1; /**< [ 17: 17](RO) State of UART1_RTS_N pin strap sampled when DCOK asserts. */
uint64_t uart0_rts : 1; /**< [ 16: 16](RO) State of UART0_RTS_N pin strap sampled when DCOK asserts. */
uint64_t reserved_11_15 : 5;
uint64_t rgm_supply : 2; /**< [ 10: 9](RO) RGMII power supply setting based on VDD_RGM_SUPPLY_SELECT pin:
0x2 = 2.5V.
_ All other values reserved. */
uint64_t emm_supply : 3; /**< [ 8: 6](RO) EMMC power supply settings.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
#else /* Word 0 - Little Endian */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t emm_supply : 3; /**< [ 8: 6](RO) EMMC power supply settings.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t rgm_supply : 2; /**< [ 10: 9](RO) RGMII power supply setting based on VDD_RGM_SUPPLY_SELECT pin:
0x2 = 2.5V.
_ All other values reserved. */
uint64_t reserved_11_15 : 5;
uint64_t uart0_rts : 1; /**< [ 16: 16](RO) State of UART0_RTS_N pin strap sampled when DCOK asserts. */
uint64_t uart1_rts : 1; /**< [ 17: 17](RO) State of UART1_RTS_N pin strap sampled when DCOK asserts. */
uint64_t reserved_18_63 : 46;
#endif /* Word 0 - End */
} s;
struct bdk_mio_boot_pin_defs_cn81xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_18_63 : 46;
uint64_t uart1_rts : 1; /**< [ 17: 17](RO) State of UART1_RTS_N pin strap sampled when DCOK asserts. */
uint64_t uart0_rts : 1; /**< [ 16: 16](RO) Reference clock select. State of UART0_RTS_N pin sampled when DCOK asserts.
0 = Board supplies 100 MHz to DLM_REF_CLK\<1\> (divided by 2 internally).
1 = Board supplies 50 MHz to PLL_REFCLK. */
uint64_t reserved_11_15 : 5;
uint64_t rgm_supply : 2; /**< [ 10: 9](RO) RGMII power supply setting based on VDD_RGM_SUPPLY_SELECT pin:
0x2 = 2.5V.
_ All other values reserved. */
uint64_t emm_supply : 3; /**< [ 8: 6](RO) EMMC power supply settings.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
#else /* Word 0 - Little Endian */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t emm_supply : 3; /**< [ 8: 6](RO) EMMC power supply settings.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t rgm_supply : 2; /**< [ 10: 9](RO) RGMII power supply setting based on VDD_RGM_SUPPLY_SELECT pin:
0x2 = 2.5V.
_ All other values reserved. */
uint64_t reserved_11_15 : 5;
uint64_t uart0_rts : 1; /**< [ 16: 16](RO) Reference clock select. State of UART0_RTS_N pin sampled when DCOK asserts.
0 = Board supplies 100 MHz to DLM_REF_CLK\<1\> (divided by 2 internally).
1 = Board supplies 50 MHz to PLL_REFCLK. */
uint64_t uart1_rts : 1; /**< [ 17: 17](RO) State of UART1_RTS_N pin strap sampled when DCOK asserts. */
uint64_t reserved_18_63 : 46;
#endif /* Word 0 - End */
} cn81xx;
struct bdk_mio_boot_pin_defs_cn88xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_6_63 : 58;
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
#else /* Word 0 - Little Endian */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t reserved_6_63 : 58;
#endif /* Word 0 - End */
} cn88xx;
struct bdk_mio_boot_pin_defs_cn83xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_18_63 : 46;
uint64_t uart1_rts : 1; /**< [ 17: 17](RO) State of UART1_RTS_N pin strap sampled when DCOK asserts. */
uint64_t uart0_rts : 1; /**< [ 16: 16](RO) State of UART0_RTS_N pin strap sampled when DCOK asserts. */
uint64_t reserved_9_15 : 7;
uint64_t emm_supply : 3; /**< [ 8: 6](RO) EMMC power supply settings.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
#else /* Word 0 - Little Endian */
uint64_t io_supply : 3; /**< [ 2: 0](RO) I/O power supply setting based on VDD_IO_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t smi_supply : 3; /**< [ 5: 3](RO) SMI power supply setting based on VDD_SMI_SUPPLY_SELECT pin:
0x2 = 2.5V.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t emm_supply : 3; /**< [ 8: 6](RO) EMMC power supply settings.
0x4 = 3.3V.
_ All other values reserved. */
uint64_t reserved_9_15 : 7;
uint64_t uart0_rts : 1; /**< [ 16: 16](RO) State of UART0_RTS_N pin strap sampled when DCOK asserts. */
uint64_t uart1_rts : 1; /**< [ 17: 17](RO) State of UART1_RTS_N pin strap sampled when DCOK asserts. */
uint64_t reserved_18_63 : 46;
#endif /* Word 0 - End */
} cn83xx;
};
typedef union bdk_mio_boot_pin_defs bdk_mio_boot_pin_defs_t;
#define BDK_MIO_BOOT_PIN_DEFS BDK_MIO_BOOT_PIN_DEFS_FUNC()
static inline uint64_t BDK_MIO_BOOT_PIN_DEFS_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_MIO_BOOT_PIN_DEFS_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
return 0x87e0000000c0ll;
__bdk_csr_fatal("MIO_BOOT_PIN_DEFS", 0, 0, 0, 0, 0);
}
#define typedef_BDK_MIO_BOOT_PIN_DEFS bdk_mio_boot_pin_defs_t
#define bustype_BDK_MIO_BOOT_PIN_DEFS BDK_CSR_TYPE_RSL
#define basename_BDK_MIO_BOOT_PIN_DEFS "MIO_BOOT_PIN_DEFS"
#define device_bar_BDK_MIO_BOOT_PIN_DEFS 0x0 /* PF_BAR0 */
#define busnum_BDK_MIO_BOOT_PIN_DEFS 0
#define arguments_BDK_MIO_BOOT_PIN_DEFS -1,-1,-1,-1
/**
* Register (RSL) mio_boot_rom_limit
*
* MIO Boot ROM Limit Register
* This register contains the largest valid address in the internal bootrom.
*/
union bdk_mio_boot_rom_limit
{
uint64_t u;
struct bdk_mio_boot_rom_limit_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_17_63 : 47;
uint64_t addr : 17; /**< [ 16: 0](SR/W/H) End of ROM address. This field specifies the first invalid address in ROM_MEM();
access to a ROM_MEM() address at or above this address will return a fault and zeros.
Writes to this register which attempt to set an [ADDR] greater than the previous [ADDR]
setting are ignored.
Internal:
If trusted boot mode, resets to the size of the internal
bootrom (0x4000), ROM boot instructions may then write to decrease the value. If
non-trusted boot resets to a value read from ROM_MEM() at address MAX - 12, just
before the CRC. */
#else /* Word 0 - Little Endian */
uint64_t addr : 17; /**< [ 16: 0](SR/W/H) End of ROM address. This field specifies the first invalid address in ROM_MEM();
access to a ROM_MEM() address at or above this address will return a fault and zeros.
Writes to this register which attempt to set an [ADDR] greater than the previous [ADDR]
setting are ignored.
Internal:
If trusted boot mode, resets to the size of the internal
bootrom (0x4000), ROM boot instructions may then write to decrease the value. If
non-trusted boot resets to a value read from ROM_MEM() at address MAX - 12, just
before the CRC. */
uint64_t reserved_17_63 : 47;
#endif /* Word 0 - End */
} s;
/* struct bdk_mio_boot_rom_limit_s cn; */
};
typedef union bdk_mio_boot_rom_limit bdk_mio_boot_rom_limit_t;
#define BDK_MIO_BOOT_ROM_LIMIT BDK_MIO_BOOT_ROM_LIMIT_FUNC()
static inline uint64_t BDK_MIO_BOOT_ROM_LIMIT_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_MIO_BOOT_ROM_LIMIT_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
return 0x87e0000000d8ll;
__bdk_csr_fatal("MIO_BOOT_ROM_LIMIT", 0, 0, 0, 0, 0);
}
#define typedef_BDK_MIO_BOOT_ROM_LIMIT bdk_mio_boot_rom_limit_t
#define bustype_BDK_MIO_BOOT_ROM_LIMIT BDK_CSR_TYPE_RSL
#define basename_BDK_MIO_BOOT_ROM_LIMIT "MIO_BOOT_ROM_LIMIT"
#define device_bar_BDK_MIO_BOOT_ROM_LIMIT 0x0 /* PF_BAR0 */
#define busnum_BDK_MIO_BOOT_ROM_LIMIT 0
#define arguments_BDK_MIO_BOOT_ROM_LIMIT -1,-1,-1,-1
/**
* Register (RSL) mio_boot_thr
*
* MIO Boot Threshold Register
* The boot-threshold register contains MIO boot-threshold values.
*/
union bdk_mio_boot_thr
{
uint64_t u;
struct bdk_mio_boot_thr_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_14_63 : 50;
uint64_t fif_cnt : 6; /**< [ 13: 8](RO/H) Current FIFO count. */
uint64_t reserved_6_7 : 2;
uint64_t fif_thr : 6; /**< [ 5: 0](R/W) NCB busy threshold. Should always read 0x19 (the only legal value). */
#else /* Word 0 - Little Endian */
uint64_t fif_thr : 6; /**< [ 5: 0](R/W) NCB busy threshold. Should always read 0x19 (the only legal value). */
uint64_t reserved_6_7 : 2;
uint64_t fif_cnt : 6; /**< [ 13: 8](RO/H) Current FIFO count. */
uint64_t reserved_14_63 : 50;
#endif /* Word 0 - End */
} s;
/* struct bdk_mio_boot_thr_s cn81xx; */
struct bdk_mio_boot_thr_cn88xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_14_63 : 50;
uint64_t fif_cnt : 6; /**< [ 13: 8](RO/H) Current NCB FIFO count. */
uint64_t reserved_6_7 : 2;
uint64_t fif_thr : 6; /**< [ 5: 0](R/W) NCB busy threshold. Should always read 0x19 (the only legal value). */
#else /* Word 0 - Little Endian */
uint64_t fif_thr : 6; /**< [ 5: 0](R/W) NCB busy threshold. Should always read 0x19 (the only legal value). */
uint64_t reserved_6_7 : 2;
uint64_t fif_cnt : 6; /**< [ 13: 8](RO/H) Current NCB FIFO count. */
uint64_t reserved_14_63 : 50;
#endif /* Word 0 - End */
} cn88xx;
/* struct bdk_mio_boot_thr_s cn83xx; */
};
typedef union bdk_mio_boot_thr bdk_mio_boot_thr_t;
#define BDK_MIO_BOOT_THR BDK_MIO_BOOT_THR_FUNC()
static inline uint64_t BDK_MIO_BOOT_THR_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_MIO_BOOT_THR_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
return 0x87e0000000b0ll;
__bdk_csr_fatal("MIO_BOOT_THR", 0, 0, 0, 0, 0);
}
#define typedef_BDK_MIO_BOOT_THR bdk_mio_boot_thr_t
#define bustype_BDK_MIO_BOOT_THR BDK_CSR_TYPE_RSL
#define basename_BDK_MIO_BOOT_THR "MIO_BOOT_THR"
#define device_bar_BDK_MIO_BOOT_THR 0x0 /* PF_BAR0 */
#define busnum_BDK_MIO_BOOT_THR 0
#define arguments_BDK_MIO_BOOT_THR -1,-1,-1,-1
#endif /* __BDK_CSRS_MIO_BOOT_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,738 @@
#ifndef __BDK_CSRS_RNM_H__
#define __BDK_CSRS_RNM_H__
/* This file is auto-generated. Do not edit */
/***********************license start***************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Configuration and status register (CSR) address and type definitions for
* Cavium RNM.
*
* This file is auto generated. Do not edit.
*
*/
/**
* Enumeration rnm_bar_e
*
* RNM Base Address Register Enumeration
* Enumerates the base address registers.
*/
#define BDK_RNM_BAR_E_RNM_PF_BAR0 (0x87e040000000ll)
#define BDK_RNM_BAR_E_RNM_PF_BAR0_SIZE 0x100000ull
#define BDK_RNM_BAR_E_RNM_VF_BAR0 (0x840000800000ll)
#define BDK_RNM_BAR_E_RNM_VF_BAR0_SIZE 0x100000ull
/**
* Register (RSL) rnm_bist_status
*
* RNM BIST Status Register
* This register is the RNM memory BIST status register, indicating status of built-in self-
* tests. 0 = passed BIST, 1 = failed BIST.
*/
union bdk_rnm_bist_status
{
uint64_t u;
struct bdk_rnm_bist_status_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_0_63 : 64;
#else /* Word 0 - Little Endian */
uint64_t reserved_0_63 : 64;
#endif /* Word 0 - End */
} s;
struct bdk_rnm_bist_status_cn81xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_2_63 : 62;
uint64_t nz : 1; /**< [ 1: 1](RO/H) Status of the no-zeros memory BIST. 0 = passed BIST, 1 = failed BIST. */
uint64_t nml : 1; /**< [ 0: 0](RO/H) Status of the normal memory BIST. 0 = passed BIST, 1 = failed BIST. */
#else /* Word 0 - Little Endian */
uint64_t nml : 1; /**< [ 0: 0](RO/H) Status of the normal memory BIST. 0 = passed BIST, 1 = failed BIST. */
uint64_t nz : 1; /**< [ 1: 1](RO/H) Status of the no-zeros memory BIST. 0 = passed BIST, 1 = failed BIST. */
uint64_t reserved_2_63 : 62;
#endif /* Word 0 - End */
} cn81xx;
struct bdk_rnm_bist_status_cn88xx
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_2_63 : 62;
uint64_t rrc : 1; /**< [ 1: 1](RO/H) Status of the RRC memory block BIST. 0 = passed BIST, 1 = failed BIST. */
uint64_t mem : 1; /**< [ 0: 0](RO/H) Status of MEM memory block BIST. 0 = passed BIST, 1 = failed BIST. */
#else /* Word 0 - Little Endian */
uint64_t mem : 1; /**< [ 0: 0](RO/H) Status of MEM memory block BIST. 0 = passed BIST, 1 = failed BIST. */
uint64_t rrc : 1; /**< [ 1: 1](RO/H) Status of the RRC memory block BIST. 0 = passed BIST, 1 = failed BIST. */
uint64_t reserved_2_63 : 62;
#endif /* Word 0 - End */
} cn88xx;
/* struct bdk_rnm_bist_status_cn81xx cn83xx; */
};
typedef union bdk_rnm_bist_status bdk_rnm_bist_status_t;
#define BDK_RNM_BIST_STATUS BDK_RNM_BIST_STATUS_FUNC()
static inline uint64_t BDK_RNM_BIST_STATUS_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_BIST_STATUS_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
return 0x87e040000008ll;
__bdk_csr_fatal("RNM_BIST_STATUS", 0, 0, 0, 0, 0);
}
#define typedef_BDK_RNM_BIST_STATUS bdk_rnm_bist_status_t
#define bustype_BDK_RNM_BIST_STATUS BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_BIST_STATUS "RNM_BIST_STATUS"
#define device_bar_BDK_RNM_BIST_STATUS 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_BIST_STATUS 0
#define arguments_BDK_RNM_BIST_STATUS -1,-1,-1,-1
/**
* Register (RSL) rnm_bp_test
*
* INTERNAL: RNM Backpressure Test Register
*/
union bdk_rnm_bp_test
{
uint64_t u;
struct bdk_rnm_bp_test_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t enable : 3; /**< [ 63: 61](R/W) Enable test mode. For diagnostic use only.
Internal:
Once a bit is set, random backpressure is generated
at the corresponding point to allow for more frequent backpressure.
\<63\> = Normal random number memory writes.
\<62\> = No-zeros random number memory writes.
\<61\> = No-zeros random number memory reads. */
uint64_t reserved_24_60 : 37;
uint64_t bp_cfg : 6; /**< [ 23: 18](R/W) Backpressure weight. For diagnostic use only.
Internal:
There are 2 backpressure configuration bits per enable, with the two bits
defined as 0x0=100% of the time, 0x1=75% of the time, 0x2=50% of the time,
0x3=25% of the time.
\<23:22\> = Normal random number memory writes.
\<21:20\> = No-zeros random number memory writes.
\<19:18\> = No-zeros random number memory reads. */
uint64_t reserved_12_17 : 6;
uint64_t lfsr_freq : 12; /**< [ 11: 0](R/W) Test LFSR update frequency in coprocessor-clocks minus one. */
#else /* Word 0 - Little Endian */
uint64_t lfsr_freq : 12; /**< [ 11: 0](R/W) Test LFSR update frequency in coprocessor-clocks minus one. */
uint64_t reserved_12_17 : 6;
uint64_t bp_cfg : 6; /**< [ 23: 18](R/W) Backpressure weight. For diagnostic use only.
Internal:
There are 2 backpressure configuration bits per enable, with the two bits
defined as 0x0=100% of the time, 0x1=75% of the time, 0x2=50% of the time,
0x3=25% of the time.
\<23:22\> = Normal random number memory writes.
\<21:20\> = No-zeros random number memory writes.
\<19:18\> = No-zeros random number memory reads. */
uint64_t reserved_24_60 : 37;
uint64_t enable : 3; /**< [ 63: 61](R/W) Enable test mode. For diagnostic use only.
Internal:
Once a bit is set, random backpressure is generated
at the corresponding point to allow for more frequent backpressure.
\<63\> = Normal random number memory writes.
\<62\> = No-zeros random number memory writes.
\<61\> = No-zeros random number memory reads. */
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_bp_test_s cn; */
};
typedef union bdk_rnm_bp_test bdk_rnm_bp_test_t;
#define BDK_RNM_BP_TEST BDK_RNM_BP_TEST_FUNC()
static inline uint64_t BDK_RNM_BP_TEST_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_BP_TEST_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e040000028ll;
__bdk_csr_fatal("RNM_BP_TEST", 0, 0, 0, 0, 0);
}
#define typedef_BDK_RNM_BP_TEST bdk_rnm_bp_test_t
#define bustype_BDK_RNM_BP_TEST BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_BP_TEST "RNM_BP_TEST"
#define device_bar_BDK_RNM_BP_TEST 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_BP_TEST 0
#define arguments_BDK_RNM_BP_TEST -1,-1,-1,-1
/**
* Register (RSL) rnm_const
*
* RNM PF Constants Register
* This register is used for software discovery.
*/
union bdk_rnm_const
{
uint64_t u;
struct bdk_rnm_const_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_0_63 : 64;
#else /* Word 0 - Little Endian */
uint64_t reserved_0_63 : 64;
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_const_s cn; */
};
typedef union bdk_rnm_const bdk_rnm_const_t;
#define BDK_RNM_CONST BDK_RNM_CONST_FUNC()
static inline uint64_t BDK_RNM_CONST_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_CONST_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
return 0x87e040000030ll;
__bdk_csr_fatal("RNM_CONST", 0, 0, 0, 0, 0);
}
#define typedef_BDK_RNM_CONST bdk_rnm_const_t
#define bustype_BDK_RNM_CONST BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_CONST "RNM_CONST"
#define device_bar_BDK_RNM_CONST 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_CONST 0
#define arguments_BDK_RNM_CONST -1,-1,-1,-1
/**
* Register (RSL) rnm_ctl_status
*
* RNM Control and Status Register
* This register is the RNM control register.
* This register is secure only to prevent the nonsecure world from affecting
* secure-world clients using true random numbers.
*/
union bdk_rnm_ctl_status
{
uint64_t u;
struct bdk_rnm_ctl_status_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_11_63 : 53;
uint64_t eer_lck : 1; /**< [ 10: 10](SRO/H) Encryption enable register locked. */
uint64_t eer_val : 1; /**< [ 9: 9](SRO/H) Dormant encryption key match. */
uint64_t ent_sel : 4; /**< [ 8: 5](SR/W) Select input to RNM FIFO.
0x0 = 0-7.
0x1 = 8-15.
0x2 = 16-23.
0x3 = 24-31.
0x4 = 32-39.
0x5 = 40-47.
0x6 = 48-55.
0x7 = 56-63.
0x8 = 64-71.
0x9 = 72-79.
0xA = 80-87.
0xB = 88-95.
0xC = 96-103.
0xD = 104-111.
0xE = 112-119.
0xF = 120-127. */
uint64_t exp_ent : 1; /**< [ 4: 4](SR/W) Exported entropy enable for random number generator. The next random number is
available 80 coprocessor-clock cycles after switching this bit from zero to one. The
next random number is available 730 coprocessor-clock cycles after switching this
bit from one to zero. */
uint64_t rng_rst : 1; /**< [ 3: 3](SR/W) Reset the RNG. Setting this bit to one cancels the generation of the current random
number. The next random number is available 730 coprocessor-clock cycles after this
bit is cleared if [EXP_ENT] is set to zero. The next random number is available 80
coprocessor-clock cycles after this bit is cleared if [EXP_ENT] is set to one. This bit is
not automatically cleared. */
uint64_t rnm_rst : 1; /**< [ 2: 2](SR/W) Reset the RNM. Setting this bit to 1 drops all RNM transactions in flight and clears
all stored numbers in the random number memory. Any outstanding NCBO credits will
not be returned. RNM will not respond to any pending NCBI grants. RNM can accept
new requests immediately after reset is cleared. This bit is not automatically
cleared and will not reset any CSR fields. */
uint64_t rng_en : 1; /**< [ 1: 1](SR/W) Enables the output of the RNG. */
uint64_t ent_en : 1; /**< [ 0: 0](SR/W) Entropy enable for random number generator. */
#else /* Word 0 - Little Endian */
uint64_t ent_en : 1; /**< [ 0: 0](SR/W) Entropy enable for random number generator. */
uint64_t rng_en : 1; /**< [ 1: 1](SR/W) Enables the output of the RNG. */
uint64_t rnm_rst : 1; /**< [ 2: 2](SR/W) Reset the RNM. Setting this bit to 1 drops all RNM transactions in flight and clears
all stored numbers in the random number memory. Any outstanding NCBO credits will
not be returned. RNM will not respond to any pending NCBI grants. RNM can accept
new requests immediately after reset is cleared. This bit is not automatically
cleared and will not reset any CSR fields. */
uint64_t rng_rst : 1; /**< [ 3: 3](SR/W) Reset the RNG. Setting this bit to one cancels the generation of the current random
number. The next random number is available 730 coprocessor-clock cycles after this
bit is cleared if [EXP_ENT] is set to zero. The next random number is available 80
coprocessor-clock cycles after this bit is cleared if [EXP_ENT] is set to one. This bit is
not automatically cleared. */
uint64_t exp_ent : 1; /**< [ 4: 4](SR/W) Exported entropy enable for random number generator. The next random number is
available 80 coprocessor-clock cycles after switching this bit from zero to one. The
next random number is available 730 coprocessor-clock cycles after switching this
bit from one to zero. */
uint64_t ent_sel : 4; /**< [ 8: 5](SR/W) Select input to RNM FIFO.
0x0 = 0-7.
0x1 = 8-15.
0x2 = 16-23.
0x3 = 24-31.
0x4 = 32-39.
0x5 = 40-47.
0x6 = 48-55.
0x7 = 56-63.
0x8 = 64-71.
0x9 = 72-79.
0xA = 80-87.
0xB = 88-95.
0xC = 96-103.
0xD = 104-111.
0xE = 112-119.
0xF = 120-127. */
uint64_t eer_val : 1; /**< [ 9: 9](SRO/H) Dormant encryption key match. */
uint64_t eer_lck : 1; /**< [ 10: 10](SRO/H) Encryption enable register locked. */
uint64_t reserved_11_63 : 53;
#endif /* Word 0 - End */
} s;
struct bdk_rnm_ctl_status_cn8
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_12_63 : 52;
uint64_t dis_mak : 1; /**< [ 11: 11](SR/W1S/H) Disable use of master AES KEY. */
uint64_t eer_lck : 1; /**< [ 10: 10](SRO/H) Encryption enable register locked. */
uint64_t eer_val : 1; /**< [ 9: 9](SRO/H) Dormant encryption key match. */
uint64_t ent_sel : 4; /**< [ 8: 5](SR/W) Select input to RNM FIFO.
0x0 = 0-7.
0x1 = 8-15.
0x2 = 16-23.
0x3 = 24-31.
0x4 = 32-39.
0x5 = 40-47.
0x6 = 48-55.
0x7 = 56-63.
0x8 = 64-71.
0x9 = 72-79.
0xA = 80-87.
0xB = 88-95.
0xC = 96-103.
0xD = 104-111.
0xE = 112-119.
0xF = 120-127. */
uint64_t exp_ent : 1; /**< [ 4: 4](SR/W) Exported entropy enable for random number generator. The next random number is
available 80 coprocessor-clock cycles after switching this bit from zero to one. The
next random number is available 730 coprocessor-clock cycles after switching this
bit from one to zero. */
uint64_t rng_rst : 1; /**< [ 3: 3](SR/W) Reset the RNG. Setting this bit to one cancels the generation of the current random
number. The next random number is available 730 coprocessor-clock cycles after this
bit is cleared if [EXP_ENT] is set to zero. The next random number is available 80
coprocessor-clock cycles after this bit is cleared if [EXP_ENT] is set to one. This bit is
not automatically cleared. */
uint64_t rnm_rst : 1; /**< [ 2: 2](SR/W) Reset the RNM. Setting this bit to 1 drops all RNM transactions in flight and clears
all stored numbers in the random number memory. Any outstanding NCBO credits will
not be returned. RNM will not respond to any pending NCBI grants. RNM can accept
new requests immediately after reset is cleared. This bit is not automatically
cleared and will not reset any CSR fields. */
uint64_t rng_en : 1; /**< [ 1: 1](SR/W) Enables the output of the RNG. */
uint64_t ent_en : 1; /**< [ 0: 0](SR/W) Entropy enable for random number generator. */
#else /* Word 0 - Little Endian */
uint64_t ent_en : 1; /**< [ 0: 0](SR/W) Entropy enable for random number generator. */
uint64_t rng_en : 1; /**< [ 1: 1](SR/W) Enables the output of the RNG. */
uint64_t rnm_rst : 1; /**< [ 2: 2](SR/W) Reset the RNM. Setting this bit to 1 drops all RNM transactions in flight and clears
all stored numbers in the random number memory. Any outstanding NCBO credits will
not be returned. RNM will not respond to any pending NCBI grants. RNM can accept
new requests immediately after reset is cleared. This bit is not automatically
cleared and will not reset any CSR fields. */
uint64_t rng_rst : 1; /**< [ 3: 3](SR/W) Reset the RNG. Setting this bit to one cancels the generation of the current random
number. The next random number is available 730 coprocessor-clock cycles after this
bit is cleared if [EXP_ENT] is set to zero. The next random number is available 80
coprocessor-clock cycles after this bit is cleared if [EXP_ENT] is set to one. This bit is
not automatically cleared. */
uint64_t exp_ent : 1; /**< [ 4: 4](SR/W) Exported entropy enable for random number generator. The next random number is
available 80 coprocessor-clock cycles after switching this bit from zero to one. The
next random number is available 730 coprocessor-clock cycles after switching this
bit from one to zero. */
uint64_t ent_sel : 4; /**< [ 8: 5](SR/W) Select input to RNM FIFO.
0x0 = 0-7.
0x1 = 8-15.
0x2 = 16-23.
0x3 = 24-31.
0x4 = 32-39.
0x5 = 40-47.
0x6 = 48-55.
0x7 = 56-63.
0x8 = 64-71.
0x9 = 72-79.
0xA = 80-87.
0xB = 88-95.
0xC = 96-103.
0xD = 104-111.
0xE = 112-119.
0xF = 120-127. */
uint64_t eer_val : 1; /**< [ 9: 9](SRO/H) Dormant encryption key match. */
uint64_t eer_lck : 1; /**< [ 10: 10](SRO/H) Encryption enable register locked. */
uint64_t dis_mak : 1; /**< [ 11: 11](SR/W1S/H) Disable use of master AES KEY. */
uint64_t reserved_12_63 : 52;
#endif /* Word 0 - End */
} cn8;
struct bdk_rnm_ctl_status_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_12_63 : 52;
uint64_t zuc_en : 1; /**< [ 11: 11](SR/W) Enable output of the ZUC engine. Before setting this bit software must write to
all RNM_ZUC_INIT_LFSR(), and RNM_ZUC_INIT_NLF() registers. */
uint64_t eer_lck : 1; /**< [ 10: 10](SRO/H) Encryption enable register locked. */
uint64_t eer_val : 1; /**< [ 9: 9](SRO/H) Dormant encryption key match. */
uint64_t ent_sel : 4; /**< [ 8: 5](SR/W) Select input to RNM FIFO.
0x0 = 0-7.
0x1 = 8-15.
0x2 = 16-23.
0x3 = 24-31.
0x4 = 32-39.
0x5 = 40-47.
0x6 = 48-55.
0x7 = 56-63.
0x8 = 64-71.
0x9 = 72-79.
0xA = 80-87.
0xB = 88-95.
0xC = 96-103.
0xD = 104-111.
0xE = 112-119.
0xF = 120-127. */
uint64_t exp_ent : 1; /**< [ 4: 4](SR/W) Exported entropy enable for random number generator. The next random number is
available 80 coprocessor-clock cycles after switching this bit from zero to one. The
next random number is available 730 coprocessor-clock cycles after switching this
bit from one to zero. */
uint64_t rng_rst : 1; /**< [ 3: 3](SR/W) Reset the RNG. Setting this bit to one cancels the generation of the current random
number. The next random number is available 730 coprocessor-clock cycles after this
bit is cleared if [EXP_ENT] is set to zero. The next random number is available 80
coprocessor-clock cycles after this bit is cleared if [EXP_ENT] is set to one. This bit is
not automatically cleared. */
uint64_t rnm_rst : 1; /**< [ 2: 2](SRO) Reserved. Writes are ignored for backward compatibility. */
uint64_t rng_en : 1; /**< [ 1: 1](SR/W) Enables the output of the RNG. */
uint64_t ent_en : 1; /**< [ 0: 0](SR/W) Entropy enable for random number generator. */
#else /* Word 0 - Little Endian */
uint64_t ent_en : 1; /**< [ 0: 0](SR/W) Entropy enable for random number generator. */
uint64_t rng_en : 1; /**< [ 1: 1](SR/W) Enables the output of the RNG. */
uint64_t rnm_rst : 1; /**< [ 2: 2](SRO) Reserved. Writes are ignored for backward compatibility. */
uint64_t rng_rst : 1; /**< [ 3: 3](SR/W) Reset the RNG. Setting this bit to one cancels the generation of the current random
number. The next random number is available 730 coprocessor-clock cycles after this
bit is cleared if [EXP_ENT] is set to zero. The next random number is available 80
coprocessor-clock cycles after this bit is cleared if [EXP_ENT] is set to one. This bit is
not automatically cleared. */
uint64_t exp_ent : 1; /**< [ 4: 4](SR/W) Exported entropy enable for random number generator. The next random number is
available 80 coprocessor-clock cycles after switching this bit from zero to one. The
next random number is available 730 coprocessor-clock cycles after switching this
bit from one to zero. */
uint64_t ent_sel : 4; /**< [ 8: 5](SR/W) Select input to RNM FIFO.
0x0 = 0-7.
0x1 = 8-15.
0x2 = 16-23.
0x3 = 24-31.
0x4 = 32-39.
0x5 = 40-47.
0x6 = 48-55.
0x7 = 56-63.
0x8 = 64-71.
0x9 = 72-79.
0xA = 80-87.
0xB = 88-95.
0xC = 96-103.
0xD = 104-111.
0xE = 112-119.
0xF = 120-127. */
uint64_t eer_val : 1; /**< [ 9: 9](SRO/H) Dormant encryption key match. */
uint64_t eer_lck : 1; /**< [ 10: 10](SRO/H) Encryption enable register locked. */
uint64_t zuc_en : 1; /**< [ 11: 11](SR/W) Enable output of the ZUC engine. Before setting this bit software must write to
all RNM_ZUC_INIT_LFSR(), and RNM_ZUC_INIT_NLF() registers. */
uint64_t reserved_12_63 : 52;
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_rnm_ctl_status bdk_rnm_ctl_status_t;
#define BDK_RNM_CTL_STATUS BDK_RNM_CTL_STATUS_FUNC()
static inline uint64_t BDK_RNM_CTL_STATUS_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_CTL_STATUS_FUNC(void)
{
return 0x87e040000000ll;
}
#define typedef_BDK_RNM_CTL_STATUS bdk_rnm_ctl_status_t
#define bustype_BDK_RNM_CTL_STATUS BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_CTL_STATUS "RNM_CTL_STATUS"
#define device_bar_BDK_RNM_CTL_STATUS 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_CTL_STATUS 0
#define arguments_BDK_RNM_CTL_STATUS -1,-1,-1,-1
/**
* Register (RSL) rnm_eer_dbg
*
* INTERNAL: RNM Encryption Enable Debug Register
*
* This register is the encryption enable debug register.
*/
union bdk_rnm_eer_dbg
{
uint64_t u;
struct bdk_rnm_eer_dbg_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO/H) Dormant encryption debug info. */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](SRO/H) Dormant encryption debug info. */
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_eer_dbg_s cn; */
};
typedef union bdk_rnm_eer_dbg bdk_rnm_eer_dbg_t;
#define BDK_RNM_EER_DBG BDK_RNM_EER_DBG_FUNC()
static inline uint64_t BDK_RNM_EER_DBG_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_EER_DBG_FUNC(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
return 0x87e040000018ll;
__bdk_csr_fatal("RNM_EER_DBG", 0, 0, 0, 0, 0);
}
#define typedef_BDK_RNM_EER_DBG bdk_rnm_eer_dbg_t
#define bustype_BDK_RNM_EER_DBG BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_EER_DBG "RNM_EER_DBG"
#define device_bar_BDK_RNM_EER_DBG 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_EER_DBG 0
#define arguments_BDK_RNM_EER_DBG -1,-1,-1,-1
/**
* Register (RSL) rnm_eer_key
*
* RNM Encryption Enable Register
* This register is the encryption enable register.
*/
union bdk_rnm_eer_key
{
uint64_t u;
struct bdk_rnm_eer_key_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t key : 64; /**< [ 63: 0](SWO) Dormant encryption key. If dormant crypto is fuse-enabled, crypto can be enabled by
writing this register with the correct key. */
#else /* Word 0 - Little Endian */
uint64_t key : 64; /**< [ 63: 0](SWO) Dormant encryption key. If dormant crypto is fuse-enabled, crypto can be enabled by
writing this register with the correct key. */
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_eer_key_s cn; */
};
typedef union bdk_rnm_eer_key bdk_rnm_eer_key_t;
#define BDK_RNM_EER_KEY BDK_RNM_EER_KEY_FUNC()
static inline uint64_t BDK_RNM_EER_KEY_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_EER_KEY_FUNC(void)
{
return 0x87e040000010ll;
}
#define typedef_BDK_RNM_EER_KEY bdk_rnm_eer_key_t
#define bustype_BDK_RNM_EER_KEY BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_EER_KEY "RNM_EER_KEY"
#define device_bar_BDK_RNM_EER_KEY 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_EER_KEY 0
#define arguments_BDK_RNM_EER_KEY -1,-1,-1,-1
/**
* Register (NCB) rnm_random
*
* RNM Random Register
*/
union bdk_rnm_random
{
uint64_t u;
struct bdk_rnm_random_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](RO/H) Generated random number. This register may be accessed with a 8, 16, 32 or 64-bit
operation. This register is on a independent page, and may be mapped into guest operating
systems. */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](RO/H) Generated random number. This register may be accessed with a 8, 16, 32 or 64-bit
operation. This register is on a independent page, and may be mapped into guest operating
systems. */
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_random_s cn8; */
struct bdk_rnm_random_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](RO/H) Generated random number. This register may be accessed with a 8, 16, 32 or 64-bit
operation. This register is on a independent page, and may be mapped into guest operating
systems. Accesses to RNM_RANDOM larger than 64 bits will return 0x0 and fault. */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](RO/H) Generated random number. This register may be accessed with a 8, 16, 32 or 64-bit
operation. This register is on a independent page, and may be mapped into guest operating
systems. Accesses to RNM_RANDOM larger than 64 bits will return 0x0 and fault. */
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_rnm_random bdk_rnm_random_t;
#define BDK_RNM_RANDOM BDK_RNM_RANDOM_FUNC()
static inline uint64_t BDK_RNM_RANDOM_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_RANDOM_FUNC(void)
{
return 0x840000800000ll;
}
#define typedef_BDK_RNM_RANDOM bdk_rnm_random_t
#define bustype_BDK_RNM_RANDOM BDK_CSR_TYPE_NCB
#define basename_BDK_RNM_RANDOM "RNM_RANDOM"
#define device_bar_BDK_RNM_RANDOM 0x0 /* VF_BAR0 */
#define busnum_BDK_RNM_RANDOM 0
#define arguments_BDK_RNM_RANDOM -1,-1,-1,-1
/**
* Register (RSL) rnm_serial_num
*
* RNM Fuse Serial Number Register
*/
union bdk_rnm_serial_num
{
uint64_t u;
struct bdk_rnm_serial_num_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t dat : 64; /**< [ 63: 0](RO/H) Dormant encryption serial number. */
#else /* Word 0 - Little Endian */
uint64_t dat : 64; /**< [ 63: 0](RO/H) Dormant encryption serial number. */
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_serial_num_s cn; */
};
typedef union bdk_rnm_serial_num bdk_rnm_serial_num_t;
#define BDK_RNM_SERIAL_NUM BDK_RNM_SERIAL_NUM_FUNC()
static inline uint64_t BDK_RNM_SERIAL_NUM_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_SERIAL_NUM_FUNC(void)
{
return 0x87e040000020ll;
}
#define typedef_BDK_RNM_SERIAL_NUM bdk_rnm_serial_num_t
#define bustype_BDK_RNM_SERIAL_NUM BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_SERIAL_NUM "RNM_SERIAL_NUM"
#define device_bar_BDK_RNM_SERIAL_NUM 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_SERIAL_NUM 0
#define arguments_BDK_RNM_SERIAL_NUM -1,-1,-1,-1
/**
* Register (RSL) rnm_zuc_init_lfsr#
*
* RNM ZUC LFSR Initialization Register
* This register is used to initialize the state of the 16 state elements in RNM's ZUC
* LFSR. See RNM_CTL_STATUS[ZUC_EN].
*
* Before writing to this register, RNM_CTL_STATUS[ZUC_EN] must be zero to turn off the
* ZUC engine.
*/
union bdk_rnm_zuc_init_lfsrx
{
uint64_t u;
struct bdk_rnm_zuc_init_lfsrx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_31_63 : 33;
uint64_t lfsr : 31; /**< [ 30: 0](SWO) Write the state of one ZUC LFSR element. */
#else /* Word 0 - Little Endian */
uint64_t lfsr : 31; /**< [ 30: 0](SWO) Write the state of one ZUC LFSR element. */
uint64_t reserved_31_63 : 33;
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_zuc_init_lfsrx_s cn; */
};
typedef union bdk_rnm_zuc_init_lfsrx bdk_rnm_zuc_init_lfsrx_t;
static inline uint64_t BDK_RNM_ZUC_INIT_LFSRX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_ZUC_INIT_LFSRX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=15))
return 0x87e040000100ll + 8ll * ((a) & 0xf);
__bdk_csr_fatal("RNM_ZUC_INIT_LFSRX", 1, a, 0, 0, 0);
}
#define typedef_BDK_RNM_ZUC_INIT_LFSRX(a) bdk_rnm_zuc_init_lfsrx_t
#define bustype_BDK_RNM_ZUC_INIT_LFSRX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_ZUC_INIT_LFSRX(a) "RNM_ZUC_INIT_LFSRX"
#define device_bar_BDK_RNM_ZUC_INIT_LFSRX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_ZUC_INIT_LFSRX(a) (a)
#define arguments_BDK_RNM_ZUC_INIT_LFSRX(a) (a),-1,-1,-1
/**
* Register (RSL) rnm_zuc_init_nlf#
*
* RNM ZUC LFSR Initialization Register
* This register is used to initialize the state of the two 32-bit memory cells in
* ZUC's nonlinear function. See RNM_CTL_STATUS[ZUC_EN].
*
* Before writing to this register, RNM_CTL_STATUS[ZUC_EN] must be zero to turn off the
* ZUC engine.
*/
union bdk_rnm_zuc_init_nlfx
{
uint64_t u;
struct bdk_rnm_zuc_init_nlfx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint64_t reserved_32_63 : 32;
uint64_t r_state : 32; /**< [ 31: 0](SWO) Write the state of one ZUC nonlinear function element. */
#else /* Word 0 - Little Endian */
uint64_t r_state : 32; /**< [ 31: 0](SWO) Write the state of one ZUC nonlinear function element. */
uint64_t reserved_32_63 : 32;
#endif /* Word 0 - End */
} s;
/* struct bdk_rnm_zuc_init_nlfx_s cn; */
};
typedef union bdk_rnm_zuc_init_nlfx bdk_rnm_zuc_init_nlfx_t;
static inline uint64_t BDK_RNM_ZUC_INIT_NLFX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_RNM_ZUC_INIT_NLFX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=1))
return 0x87e040000200ll + 8ll * ((a) & 0x1);
__bdk_csr_fatal("RNM_ZUC_INIT_NLFX", 1, a, 0, 0, 0);
}
#define typedef_BDK_RNM_ZUC_INIT_NLFX(a) bdk_rnm_zuc_init_nlfx_t
#define bustype_BDK_RNM_ZUC_INIT_NLFX(a) BDK_CSR_TYPE_RSL
#define basename_BDK_RNM_ZUC_INIT_NLFX(a) "RNM_ZUC_INIT_NLFX"
#define device_bar_BDK_RNM_ZUC_INIT_NLFX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_RNM_ZUC_INIT_NLFX(a) (a)
#define arguments_BDK_RNM_ZUC_INIT_NLFX(a) (a),-1,-1,-1
#endif /* __BDK_CSRS_RNM_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,975 @@
#ifndef __BDK_CSRS_SGP_H__
#define __BDK_CSRS_SGP_H__
/* This file is auto-generated. Do not edit */
/***********************license start***************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
* This Software, including technical data, may be subject to U.S. export control
* laws, including the U.S. Export Administration Act and its associated
* regulations, and may be subject to export or import regulations in other
* countries.
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM NETWORKS MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT TO
* THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY REPRESENTATION OR
* DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT DEFECTS, AND CAVIUM
* SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES OF TITLE,
* MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR PURPOSE, LACK OF
* VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR
* CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK ARISING OUT OF USE OR
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Configuration and status register (CSR) address and type definitions for
* Cavium SGP.
*
* This file is auto generated. Do not edit.
*
*/
/**
* Enumeration sgp_bar_e
*
* SGPIO Base Address Register Enumeration
* Enumerates the base address registers.
*/
#define BDK_SGP_BAR_E_SGP_PF_BAR0_CN8 (0x87e027000000ll)
#define BDK_SGP_BAR_E_SGP_PF_BAR0_CN8_SIZE 0x800000ull
#define BDK_SGP_BAR_E_SGP_PF_BAR0_CN9 (0x87e027000000ll)
#define BDK_SGP_BAR_E_SGP_PF_BAR0_CN9_SIZE 0x80000ull
/**
* Enumeration sgp_tx_act_e
*
* SGPIO Transmit Activity Enumeration
* Enumerates the values of SGP_TX()[*_ACT].
*/
#define BDK_SGP_TX_ACT_E_A_OFF_ON (3)
#define BDK_SGP_TX_ACT_E_A_ON_OFF (2)
#define BDK_SGP_TX_ACT_E_BRIEF_END (4)
#define BDK_SGP_TX_ACT_E_BRIEF_START (5)
#define BDK_SGP_TX_ACT_E_B_OFF_ON (7)
#define BDK_SGP_TX_ACT_E_B_ON_OFF (6)
#define BDK_SGP_TX_ACT_E_STATIC_OFF (0)
#define BDK_SGP_TX_ACT_E_STATIC_ON (1)
/**
* Enumeration sgp_tx_err_e
*
* SGPIO Transmit Error Enumeration
* Enumerates the values of SGP_TX()[*_ERR].
*/
#define BDK_SGP_TX_ERR_E_A_OFF_ON (3)
#define BDK_SGP_TX_ERR_E_A_ON_OFF (2)
#define BDK_SGP_TX_ERR_E_B_OFF_ON (7)
#define BDK_SGP_TX_ERR_E_B_ON_OFF (6)
#define BDK_SGP_TX_ERR_E_STATIC_OFF (0)
#define BDK_SGP_TX_ERR_E_STATIC_ON (1)
#define BDK_SGP_TX_ERR_E_STATIC_ON4 (4)
#define BDK_SGP_TX_ERR_E_STATIC_ON5 (5)
/**
* Enumeration sgp_tx_loc_e
*
* SGPIO Transmit Locate Enumeration
* Enumerates the values of SGP_TX()[*_LOC].
*/
#define BDK_SGP_TX_LOC_E_A_OFF_ON (3)
#define BDK_SGP_TX_LOC_E_A_ON_OFF (2)
#define BDK_SGP_TX_LOC_E_STATIC_OFF (0)
#define BDK_SGP_TX_LOC_E_STATIC_ON (1)
/**
* Register (RSL32b) sgp_cfg0
*
* SGPIO Configuration 0 Register
*/
union bdk_sgp_cfg0
{
uint32_t u;
struct bdk_sgp_cfg0_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t drive_cnt : 8; /**< [ 31: 24](RO) Number of supported drives.
Internal:
Corresponds to SATA(0..15). */
uint32_t gp_cnt : 4; /**< [ 23: 20](RO) Number of general purpose data registers. */
uint32_t cfg_cnt : 3; /**< [ 19: 17](RO) Number of configuration registers. */
uint32_t ena : 1; /**< [ 16: 16](R/W) SGPIO enable. Enables the SGPIO inputs and outputs. When zero the bus is not driven,
inputs are zero, and shifts do not occur. A change from enabled to disabled does not take
effect until the current bit-stream has completed. */
uint32_t ver : 4; /**< [ 15: 12](RO) Version. */
uint32_t reserved_0_11 : 12;
#else /* Word 0 - Little Endian */
uint32_t reserved_0_11 : 12;
uint32_t ver : 4; /**< [ 15: 12](RO) Version. */
uint32_t ena : 1; /**< [ 16: 16](R/W) SGPIO enable. Enables the SGPIO inputs and outputs. When zero the bus is not driven,
inputs are zero, and shifts do not occur. A change from enabled to disabled does not take
effect until the current bit-stream has completed. */
uint32_t cfg_cnt : 3; /**< [ 19: 17](RO) Number of configuration registers. */
uint32_t gp_cnt : 4; /**< [ 23: 20](RO) Number of general purpose data registers. */
uint32_t drive_cnt : 8; /**< [ 31: 24](RO) Number of supported drives.
Internal:
Corresponds to SATA(0..15). */
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_cfg0_s cn; */
};
typedef union bdk_sgp_cfg0 bdk_sgp_cfg0_t;
#define BDK_SGP_CFG0 BDK_SGP_CFG0_FUNC()
static inline uint64_t BDK_SGP_CFG0_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_CFG0_FUNC(void)
{
return 0x87e027000000ll;
}
#define typedef_BDK_SGP_CFG0 bdk_sgp_cfg0_t
#define bustype_BDK_SGP_CFG0 BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_CFG0 "SGP_CFG0"
#define device_bar_BDK_SGP_CFG0 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_CFG0 0
#define arguments_BDK_SGP_CFG0 -1,-1,-1,-1
/**
* Register (RSL32b) sgp_cfg1
*
* SGPIO Configuration 1 Register
*/
union bdk_sgp_cfg1
{
uint32_t u;
struct bdk_sgp_cfg1_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_24_31 : 8;
uint32_t blink_b : 4; /**< [ 23: 20](R/W) Blink generator rate B. */
uint32_t blink_a : 4; /**< [ 19: 16](R/W) Blink generator rate A:
0x0 = 1/8 second.
0x1 = 2/8 second.
...
0xF = 16/8 seconds. */
uint32_t force_off : 4; /**< [ 15: 12](R/W) Force activity off time. The minimum amount of time to disable the activity indicator if
it has been continually enabled for the [MAX_ON] time, and the SGP_TX()[*_ACT] is
0x4 or 0x5.
0x0 = No minimum.
0x1 = 1/8 second.
...
0xF = 15/8 seconds. */
uint32_t max_on : 4; /**< [ 11: 8](R/W) Maximum activity on time. The maximum amount of time to enable the activity indicator if
SGP_TX()[*_ACT] is 0x4 or 0x5. Note all drives will not reach the [MAX_ON] time
simultaneously, the pattern will appear somewhat random.
0x0 = No maximum.
0x1 = 1/4 second.
...
0xF = 15/4 seconds. */
uint32_t stretch_off : 4; /**< [ 7: 4](R/W) Stretch activity off. The minimum amount of time to disable the activity indicator if
SGP_TX()[*_ACT] is 0x4 or 0x5.
0x0 = No minimum.
0x1 = 1/64 second.
...
0xF = 15/64 seconds. */
uint32_t stretch_on : 4; /**< [ 3: 0](R/W) Stretch activity on. The minimum amount of time to enable the activity indicator if
SGP_TX()[*_ACT] is 0x4 or 0x5.
0x0 = 1/64 second.
0x1 = 2/64 second.
...
0xF = 16/64 seconds. */
#else /* Word 0 - Little Endian */
uint32_t stretch_on : 4; /**< [ 3: 0](R/W) Stretch activity on. The minimum amount of time to enable the activity indicator if
SGP_TX()[*_ACT] is 0x4 or 0x5.
0x0 = 1/64 second.
0x1 = 2/64 second.
...
0xF = 16/64 seconds. */
uint32_t stretch_off : 4; /**< [ 7: 4](R/W) Stretch activity off. The minimum amount of time to disable the activity indicator if
SGP_TX()[*_ACT] is 0x4 or 0x5.
0x0 = No minimum.
0x1 = 1/64 second.
...
0xF = 15/64 seconds. */
uint32_t max_on : 4; /**< [ 11: 8](R/W) Maximum activity on time. The maximum amount of time to enable the activity indicator if
SGP_TX()[*_ACT] is 0x4 or 0x5. Note all drives will not reach the [MAX_ON] time
simultaneously, the pattern will appear somewhat random.
0x0 = No maximum.
0x1 = 1/4 second.
...
0xF = 15/4 seconds. */
uint32_t force_off : 4; /**< [ 15: 12](R/W) Force activity off time. The minimum amount of time to disable the activity indicator if
it has been continually enabled for the [MAX_ON] time, and the SGP_TX()[*_ACT] is
0x4 or 0x5.
0x0 = No minimum.
0x1 = 1/8 second.
...
0xF = 15/8 seconds. */
uint32_t blink_a : 4; /**< [ 19: 16](R/W) Blink generator rate A:
0x0 = 1/8 second.
0x1 = 2/8 second.
...
0xF = 16/8 seconds. */
uint32_t blink_b : 4; /**< [ 23: 20](R/W) Blink generator rate B. */
uint32_t reserved_24_31 : 8;
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_cfg1_s cn; */
};
typedef union bdk_sgp_cfg1 bdk_sgp_cfg1_t;
#define BDK_SGP_CFG1 BDK_SGP_CFG1_FUNC()
static inline uint64_t BDK_SGP_CFG1_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_CFG1_FUNC(void)
{
return 0x87e027000004ll;
}
#define typedef_BDK_SGP_CFG1 bdk_sgp_cfg1_t
#define bustype_BDK_SGP_CFG1 BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_CFG1 "SGP_CFG1"
#define device_bar_BDK_SGP_CFG1 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_CFG1 0
#define arguments_BDK_SGP_CFG1 -1,-1,-1,-1
/**
* Register (RSL32b) sgp_imp_clk
*
* SGPIO Implementation Clock Register
*/
union bdk_sgp_imp_clk
{
uint32_t u;
struct bdk_sgp_imp_clk_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_27_31 : 5;
uint32_t div : 27; /**< [ 26: 0](R/W) Coprocessor-clock divisor. Number of coprocessor clock cycles per
GPIO_SCLOCK. May only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are
clear. Should be programmed to yield a frequency between 64 Hz and 100 kHz;
reset value assumes a coprocessor clock of 800 MHz and a SGPIO_SCLOCK of 100
KHz. */
#else /* Word 0 - Little Endian */
uint32_t div : 27; /**< [ 26: 0](R/W) Coprocessor-clock divisor. Number of coprocessor clock cycles per
GPIO_SCLOCK. May only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are
clear. Should be programmed to yield a frequency between 64 Hz and 100 kHz;
reset value assumes a coprocessor clock of 800 MHz and a SGPIO_SCLOCK of 100
KHz. */
uint32_t reserved_27_31 : 5;
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_imp_clk_s cn8; */
struct bdk_sgp_imp_clk_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_27_31 : 5;
uint32_t div : 27; /**< [ 26: 0](R/W) 100 MHz reference-clock divisor. Number of 100 MHz reference clock cycles per
SGPIO_SCLOCK. May only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are
clear. Should be programmed to yield a frequency between 64 Hz and 100 kHz;
reset value assumes a SGPIO_SCLOCK of 100 KHz. */
#else /* Word 0 - Little Endian */
uint32_t div : 27; /**< [ 26: 0](R/W) 100 MHz reference-clock divisor. Number of 100 MHz reference clock cycles per
SGPIO_SCLOCK. May only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are
clear. Should be programmed to yield a frequency between 64 Hz and 100 kHz;
reset value assumes a SGPIO_SCLOCK of 100 KHz. */
uint32_t reserved_27_31 : 5;
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_sgp_imp_clk bdk_sgp_imp_clk_t;
#define BDK_SGP_IMP_CLK BDK_SGP_IMP_CLK_FUNC()
static inline uint64_t BDK_SGP_IMP_CLK_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_IMP_CLK_FUNC(void)
{
return 0x87e027030010ll;
}
#define typedef_BDK_SGP_IMP_CLK bdk_sgp_imp_clk_t
#define bustype_BDK_SGP_IMP_CLK BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_IMP_CLK "SGP_IMP_CLK"
#define device_bar_BDK_SGP_IMP_CLK 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_IMP_CLK 0
#define arguments_BDK_SGP_IMP_CLK -1,-1,-1,-1
/**
* Register (RSL32b) sgp_imp_ctl
*
* SGPIO Implementation Control Register
*/
union bdk_sgp_imp_ctl
{
uint32_t u;
struct bdk_sgp_imp_ctl_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_5_31 : 27;
uint32_t datains : 3; /**< [ 4: 2](R/W) Number of SGP_SDATAIN connections:
0x0 = No SGP_SDATAIN, all input shift data will be zero.
0x1 = SGP_SDATAIN(0) for drives 0-15.
0x2 = SGP_SDATAIN(0) for drives 0-7, (1) for drives 8-15.
0x3 = SGP_SDATAIN(0) for drives 0-3, (1) for drives 4-7, (2) for drives 8-11, (3) for
drives 12-15.
0x4-0x7 = Reserved. */
uint32_t hold : 1; /**< [ 1: 1](R/W) Hold shift. When set, automatic shifts will not occur, and the SGP_TX_GP_CFG[COUNT] must
be used to initiate a shift operation. */
uint32_t busy : 1; /**< [ 0: 0](RO/H) Shift in progress. */
#else /* Word 0 - Little Endian */
uint32_t busy : 1; /**< [ 0: 0](RO/H) Shift in progress. */
uint32_t hold : 1; /**< [ 1: 1](R/W) Hold shift. When set, automatic shifts will not occur, and the SGP_TX_GP_CFG[COUNT] must
be used to initiate a shift operation. */
uint32_t datains : 3; /**< [ 4: 2](R/W) Number of SGP_SDATAIN connections:
0x0 = No SGP_SDATAIN, all input shift data will be zero.
0x1 = SGP_SDATAIN(0) for drives 0-15.
0x2 = SGP_SDATAIN(0) for drives 0-7, (1) for drives 8-15.
0x3 = SGP_SDATAIN(0) for drives 0-3, (1) for drives 4-7, (2) for drives 8-11, (3) for
drives 12-15.
0x4-0x7 = Reserved. */
uint32_t reserved_5_31 : 27;
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_imp_ctl_s cn8; */
struct bdk_sgp_imp_ctl_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_5_31 : 27;
uint32_t datains : 3; /**< [ 4: 2](R/W) Number of SGPIO_SDATAIN connections:
0x0 = No SGPIO_SDATAIN, all input shift data will be zero.
0x1 = SGPIO_SDATAIN\<0\> for drives 0-19.
0x2 = SGPIO_SDATAIN\<0\> for drives 0-15, \<1\> for drives 16-19.
0x3 = SGPIO_SDATAIN\<0\> for drives 0-7, \<1\> for drives 8-15, \<2\> for drives 16-19.
0x4 = SGPIO_SDATAIN\<0\> for drives 0-3, \<1\> for drives 4-7, \<2\> for drives 8-11, \<3\> for
drives 12-15, \<4\> for drives 16-19.
0x5-0x7 = Reserved. */
uint32_t hold : 1; /**< [ 1: 1](R/W) Hold shift. When set, automatic shifts will not occur, and the SGP_TX_GP_CFG[COUNT] must
be used to initiate a shift operation. */
uint32_t busy : 1; /**< [ 0: 0](RO/H) Shift in progress. */
#else /* Word 0 - Little Endian */
uint32_t busy : 1; /**< [ 0: 0](RO/H) Shift in progress. */
uint32_t hold : 1; /**< [ 1: 1](R/W) Hold shift. When set, automatic shifts will not occur, and the SGP_TX_GP_CFG[COUNT] must
be used to initiate a shift operation. */
uint32_t datains : 3; /**< [ 4: 2](R/W) Number of SGPIO_SDATAIN connections:
0x0 = No SGPIO_SDATAIN, all input shift data will be zero.
0x1 = SGPIO_SDATAIN\<0\> for drives 0-19.
0x2 = SGPIO_SDATAIN\<0\> for drives 0-15, \<1\> for drives 16-19.
0x3 = SGPIO_SDATAIN\<0\> for drives 0-7, \<1\> for drives 8-15, \<2\> for drives 16-19.
0x4 = SGPIO_SDATAIN\<0\> for drives 0-3, \<1\> for drives 4-7, \<2\> for drives 8-11, \<3\> for
drives 12-15, \<4\> for drives 16-19.
0x5-0x7 = Reserved. */
uint32_t reserved_5_31 : 27;
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_sgp_imp_ctl bdk_sgp_imp_ctl_t;
#define BDK_SGP_IMP_CTL BDK_SGP_IMP_CTL_FUNC()
static inline uint64_t BDK_SGP_IMP_CTL_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_IMP_CTL_FUNC(void)
{
return 0x87e027030000ll;
}
#define typedef_BDK_SGP_IMP_CTL bdk_sgp_imp_ctl_t
#define bustype_BDK_SGP_IMP_CTL BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_IMP_CTL "SGP_IMP_CTL"
#define device_bar_BDK_SGP_IMP_CTL 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_IMP_CTL 0
#define arguments_BDK_SGP_IMP_CTL -1,-1,-1,-1
/**
* Register (RSL32b) sgp_imp_drive#
*
* SGPIO Implementation Drive Map Register
*/
union bdk_sgp_imp_drivex
{
uint32_t u;
struct bdk_sgp_imp_drivex_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_9_31 : 23;
uint32_t pres_det : 1; /**< [ 8: 8](R/W) "Presence detect. If set, logically OR SGPIO_SDATAIN's ID#.0 bit with any GPIO related
present detect and send to the relevant SATA controller's mechanical presence detect." */
uint32_t reserved_5_7 : 3;
uint32_t ctrlr : 5; /**< [ 4: 0](R/W) SATA controller attached to this index's SGPIO drive. Indicates which SATA(0..15) connects
to the corresponding indexed SGPIO drive 0..15. Resets to the index number; controller 0
for drive 0, controller 1 for drive 1, etc.
If SGP_TX()[D0_ACT]..[D3_ACT] = SGP_TX_ACT_E::BRIEF_START or
SGP_TX_ACT_E::BRIEF_END, the activity input will come from SATA controller
number [CTRLR]. Else, the activity indication is controlled by software alone.
If [PRES_DET] is set, SATA controller number [CTRLR] will receive the indexed drive's
presence detect. */
#else /* Word 0 - Little Endian */
uint32_t ctrlr : 5; /**< [ 4: 0](R/W) SATA controller attached to this index's SGPIO drive. Indicates which SATA(0..15) connects
to the corresponding indexed SGPIO drive 0..15. Resets to the index number; controller 0
for drive 0, controller 1 for drive 1, etc.
If SGP_TX()[D0_ACT]..[D3_ACT] = SGP_TX_ACT_E::BRIEF_START or
SGP_TX_ACT_E::BRIEF_END, the activity input will come from SATA controller
number [CTRLR]. Else, the activity indication is controlled by software alone.
If [PRES_DET] is set, SATA controller number [CTRLR] will receive the indexed drive's
presence detect. */
uint32_t reserved_5_7 : 3;
uint32_t pres_det : 1; /**< [ 8: 8](R/W) "Presence detect. If set, logically OR SGPIO_SDATAIN's ID#.0 bit with any GPIO related
present detect and send to the relevant SATA controller's mechanical presence detect." */
uint32_t reserved_9_31 : 23;
#endif /* Word 0 - End */
} s;
struct bdk_sgp_imp_drivex_cn8
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_9_31 : 23;
uint32_t pres_det : 1; /**< [ 8: 8](R/W) "Presence detect. If set, logically OR SGPIO_SDATAIN's ID#.0 bit with any GPIO related
present detect and send to the relevant SATA controller's mechanical presence detect." */
uint32_t reserved_4_7 : 4;
uint32_t ctrlr : 4; /**< [ 3: 0](R/W) SATA controller attached to this index's SGPIO drive. Indicates which SATA(0..15) connects
to the corresponding indexed SGPIO drive 0..15. Resets to the index number; controller 0
for drive 0, controller 1 for drive 1, etc.
If SGP_TX()[D0_ACT]..[D3_ACT] = SGP_TX_ACT_E::BRIEF_START or
SGP_TX_ACT_E::BRIEF_END, the activity input will come from SATA controller
number [CTRLR]. Else, the activity indication is controlled by software alone.
If [PRES_DET] is set, SATA controller number [CTRLR] will receive the indexed drive's
presence detect. */
#else /* Word 0 - Little Endian */
uint32_t ctrlr : 4; /**< [ 3: 0](R/W) SATA controller attached to this index's SGPIO drive. Indicates which SATA(0..15) connects
to the corresponding indexed SGPIO drive 0..15. Resets to the index number; controller 0
for drive 0, controller 1 for drive 1, etc.
If SGP_TX()[D0_ACT]..[D3_ACT] = SGP_TX_ACT_E::BRIEF_START or
SGP_TX_ACT_E::BRIEF_END, the activity input will come from SATA controller
number [CTRLR]. Else, the activity indication is controlled by software alone.
If [PRES_DET] is set, SATA controller number [CTRLR] will receive the indexed drive's
presence detect. */
uint32_t reserved_4_7 : 4;
uint32_t pres_det : 1; /**< [ 8: 8](R/W) "Presence detect. If set, logically OR SGPIO_SDATAIN's ID#.0 bit with any GPIO related
present detect and send to the relevant SATA controller's mechanical presence detect." */
uint32_t reserved_9_31 : 23;
#endif /* Word 0 - End */
} cn8;
struct bdk_sgp_imp_drivex_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_9_31 : 23;
uint32_t pres_det : 1; /**< [ 8: 8](R/W) "Presence detect. If set, logically OR SGPIO_SDATAIN's ID#.0 bit with any GPIO related
present detect and send to the relevant SATA controller's mechanical presence detect." */
uint32_t reserved_5_7 : 3;
uint32_t ctrlr : 5; /**< [ 4: 0](R/W) SATA controller attached to this index's SGPIO drive. Indicates which SATA(0..19) connects
to the corresponding indexed SGPIO drive 0..19. Resets to the index number; controller 0
for drive 0, controller 1 for drive 1, etc.
If SGP_TX()[D0_ACT]..[D3_ACT] = SGP_TX_ACT_E::BRIEF_START or
SGP_TX_ACT_E::BRIEF_END, the activity input will come from SATA controller
number [CTRLR]. Else, the activity indication is controlled by software alone.
If [PRES_DET] is set, SATA controller number [CTRLR] will receive the indexed drive's
presence detect. */
#else /* Word 0 - Little Endian */
uint32_t ctrlr : 5; /**< [ 4: 0](R/W) SATA controller attached to this index's SGPIO drive. Indicates which SATA(0..19) connects
to the corresponding indexed SGPIO drive 0..19. Resets to the index number; controller 0
for drive 0, controller 1 for drive 1, etc.
If SGP_TX()[D0_ACT]..[D3_ACT] = SGP_TX_ACT_E::BRIEF_START or
SGP_TX_ACT_E::BRIEF_END, the activity input will come from SATA controller
number [CTRLR]. Else, the activity indication is controlled by software alone.
If [PRES_DET] is set, SATA controller number [CTRLR] will receive the indexed drive's
presence detect. */
uint32_t reserved_5_7 : 3;
uint32_t pres_det : 1; /**< [ 8: 8](R/W) "Presence detect. If set, logically OR SGPIO_SDATAIN's ID#.0 bit with any GPIO related
present detect and send to the relevant SATA controller's mechanical presence detect." */
uint32_t reserved_9_31 : 23;
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_sgp_imp_drivex bdk_sgp_imp_drivex_t;
static inline uint64_t BDK_SGP_IMP_DRIVEX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_IMP_DRIVEX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX) && (a<=15))
return 0x87e027040000ll + 8ll * ((a) & 0xf);
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=19))
return 0x87e027040000ll + 8ll * ((a) & 0x1f);
__bdk_csr_fatal("SGP_IMP_DRIVEX", 1, a, 0, 0, 0);
}
#define typedef_BDK_SGP_IMP_DRIVEX(a) bdk_sgp_imp_drivex_t
#define bustype_BDK_SGP_IMP_DRIVEX(a) BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_IMP_DRIVEX(a) "SGP_IMP_DRIVEX"
#define device_bar_BDK_SGP_IMP_DRIVEX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_IMP_DRIVEX(a) (a)
#define arguments_BDK_SGP_IMP_DRIVEX(a) (a),-1,-1,-1
/**
* Register (RSL32b) sgp_imp_sec_clk
*
* SGPIO Implementation Seconds Clock Register
*/
union bdk_sgp_imp_sec_clk
{
uint32_t u;
struct bdk_sgp_imp_sec_clk_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_16_31 : 16;
uint32_t div : 16; /**< [ 15: 0](R/W) Coprocessor-clock seconds divisor. Number of GPIO_SCLOCKs per 1/64th second. May
only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are clear. Should be
programmed to yield a frequency of 64 Hz; reset value assumes GPIO_SCLOCK of 100
kHz. */
#else /* Word 0 - Little Endian */
uint32_t div : 16; /**< [ 15: 0](R/W) Coprocessor-clock seconds divisor. Number of GPIO_SCLOCKs per 1/64th second. May
only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are clear. Should be
programmed to yield a frequency of 64 Hz; reset value assumes GPIO_SCLOCK of 100
kHz. */
uint32_t reserved_16_31 : 16;
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_imp_sec_clk_s cn8; */
struct bdk_sgp_imp_sec_clk_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_16_31 : 16;
uint32_t div : 16; /**< [ 15: 0](R/W) 100 MHz reference-clock seconds divisor. Number of SGPIO_SCLOCK cycles per 1/64th
second. May only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are
clear. Should be programmed to yield a frequency of 64 Hz; reset value assumes
SGPIO_SCLOCK of 100 kHz. */
#else /* Word 0 - Little Endian */
uint32_t div : 16; /**< [ 15: 0](R/W) 100 MHz reference-clock seconds divisor. Number of SGPIO_SCLOCK cycles per 1/64th
second. May only be changed when SGP_CFG0[ENA] and SGP_IMP_CTL[BUSY] are
clear. Should be programmed to yield a frequency of 64 Hz; reset value assumes
SGPIO_SCLOCK of 100 kHz. */
uint32_t reserved_16_31 : 16;
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_sgp_imp_sec_clk bdk_sgp_imp_sec_clk_t;
#define BDK_SGP_IMP_SEC_CLK BDK_SGP_IMP_SEC_CLK_FUNC()
static inline uint64_t BDK_SGP_IMP_SEC_CLK_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_IMP_SEC_CLK_FUNC(void)
{
return 0x87e027030020ll;
}
#define typedef_BDK_SGP_IMP_SEC_CLK bdk_sgp_imp_sec_clk_t
#define bustype_BDK_SGP_IMP_SEC_CLK BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_IMP_SEC_CLK "SGP_IMP_SEC_CLK"
#define device_bar_BDK_SGP_IMP_SEC_CLK 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_IMP_SEC_CLK 0
#define arguments_BDK_SGP_IMP_SEC_CLK -1,-1,-1,-1
/**
* Register (RSL32b) sgp_rx#
*
* SGPIO Receive Registers
*/
union bdk_sgp_rxx
{
uint32_t u;
struct bdk_sgp_rxx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_27_31 : 5;
uint32_t rx3 : 3; /**< [ 26: 24](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 3+4*index. */
uint32_t reserved_19_23 : 5;
uint32_t rx2 : 3; /**< [ 18: 16](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 2+4*index. */
uint32_t reserved_11_15 : 5;
uint32_t rx1 : 3; /**< [ 10: 8](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 1+4*index. */
uint32_t reserved_3_7 : 5;
uint32_t rx0 : 3; /**< [ 2: 0](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 0+4*index. */
#else /* Word 0 - Little Endian */
uint32_t rx0 : 3; /**< [ 2: 0](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 0+4*index. */
uint32_t reserved_3_7 : 5;
uint32_t rx1 : 3; /**< [ 10: 8](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 1+4*index. */
uint32_t reserved_11_15 : 5;
uint32_t rx2 : 3; /**< [ 18: 16](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 2+4*index. */
uint32_t reserved_19_23 : 5;
uint32_t rx3 : 3; /**< [ 26: 24](RO/H) Three bits received on SGPIO_SDATAIN corresponding to drive 3+4*index. */
uint32_t reserved_27_31 : 5;
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_rxx_s cn; */
};
typedef union bdk_sgp_rxx bdk_sgp_rxx_t;
static inline uint64_t BDK_SGP_RXX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_RXX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX) && (a<=3))
return 0x87e027000400ll + 4ll * ((a) & 0x3);
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=4))
return 0x87e027000400ll + 4ll * ((a) & 0x7);
__bdk_csr_fatal("SGP_RXX", 1, a, 0, 0, 0);
}
#define typedef_BDK_SGP_RXX(a) bdk_sgp_rxx_t
#define bustype_BDK_SGP_RXX(a) BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_RXX(a) "SGP_RXX"
#define device_bar_BDK_SGP_RXX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_RXX(a) (a)
#define arguments_BDK_SGP_RXX(a) (a),-1,-1,-1
/**
* Register (RSL32b) sgp_rx_gp#
*
* SGPIO Receive GPIO Registers
*/
union bdk_sgp_rx_gpx
{
uint32_t u;
struct bdk_sgp_rx_gpx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t sdatain3 : 8; /**< [ 31: 24](RO/H) See [SDATAIN0]. */
uint32_t sdatain2 : 8; /**< [ 23: 16](RO/H) See [SDATAIN0]. */
uint32_t sdatain1 : 8; /**< [ 15: 8](RO/H) See [SDATAIN0]. */
uint32_t sdatain0 : 8; /**< [ 7: 0](RO/H) Raw data shifted from SGPIO_SDATAIN. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_RX_GP(1)[SDATAIN3]\<0\>.
_ Bit 8 (ID2.2): SGP_RX_GP(1)[SDATAIN2]\<0\>.
_ Bit 16 (ID5.1): SGP_RX_GP(1)[SDATAIN1]\<0\>.
_ Bit 24 (ID8.0): SGP_RX_GP(1)[SDATAIN0]\<0\>.
_ Bit 32 (ID10.2): SGP_RX_GP(2)[SDATAIN3]\<0\>.
_ Bit 40 (ID13.1): SGP_RX_GP(2)[SDATAIN2]\<0\>.
_ Bit 47 (ID15.2): SGP_RX_GP(2)[SDATAIN2]\<7\>.
SGP_RX_GP(2)[SDATAIN1/SDATAIN0] are always zero. */
#else /* Word 0 - Little Endian */
uint32_t sdatain0 : 8; /**< [ 7: 0](RO/H) Raw data shifted from SGPIO_SDATAIN. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_RX_GP(1)[SDATAIN3]\<0\>.
_ Bit 8 (ID2.2): SGP_RX_GP(1)[SDATAIN2]\<0\>.
_ Bit 16 (ID5.1): SGP_RX_GP(1)[SDATAIN1]\<0\>.
_ Bit 24 (ID8.0): SGP_RX_GP(1)[SDATAIN0]\<0\>.
_ Bit 32 (ID10.2): SGP_RX_GP(2)[SDATAIN3]\<0\>.
_ Bit 40 (ID13.1): SGP_RX_GP(2)[SDATAIN2]\<0\>.
_ Bit 47 (ID15.2): SGP_RX_GP(2)[SDATAIN2]\<7\>.
SGP_RX_GP(2)[SDATAIN1/SDATAIN0] are always zero. */
uint32_t sdatain1 : 8; /**< [ 15: 8](RO/H) See [SDATAIN0]. */
uint32_t sdatain2 : 8; /**< [ 23: 16](RO/H) See [SDATAIN0]. */
uint32_t sdatain3 : 8; /**< [ 31: 24](RO/H) See [SDATAIN0]. */
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_rx_gpx_s cn8; */
struct bdk_sgp_rx_gpx_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t sdatain3 : 8; /**< [ 31: 24](RO/H) See [SDATAIN0]. */
uint32_t sdatain2 : 8; /**< [ 23: 16](RO/H) See [SDATAIN0]. */
uint32_t sdatain1 : 8; /**< [ 15: 8](RO/H) See [SDATAIN0]. */
uint32_t sdatain0 : 8; /**< [ 7: 0](RO/H) Raw data shifted from SGPIO_SDATAIN. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_RX_GP(1)[SDATAIN3]\<0\>.
_ Bit 8 (ID2.2): SGP_RX_GP(1)[SDATAIN2]\<0\>.
_ Bit 16 (ID5.1): SGP_RX_GP(1)[SDATAIN1]\<0\>.
_ Bit 24 (ID8.0): SGP_RX_GP(1)[SDATAIN0]\<0\>.
_ Bit 32 (ID10.2): SGP_RX_GP(2)[SDATAIN3]\<0\>.
_ Bit 40 (ID13.1): SGP_RX_GP(2)[SDATAIN2]\<0\>.
_ Bit 48 (ID16.0): SGP_RX_GP(2)[SDATAIN1]\<0\>.
_ Bit 56 (ID18.2): SGP_RX_GP(2)[SDATAIN0]\<0\>.
_ Bit 59 (ID19.2): SGP_RX_GP(2)[SDATAIN0]\<3\>. */
#else /* Word 0 - Little Endian */
uint32_t sdatain0 : 8; /**< [ 7: 0](RO/H) Raw data shifted from SGPIO_SDATAIN. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_RX_GP(1)[SDATAIN3]\<0\>.
_ Bit 8 (ID2.2): SGP_RX_GP(1)[SDATAIN2]\<0\>.
_ Bit 16 (ID5.1): SGP_RX_GP(1)[SDATAIN1]\<0\>.
_ Bit 24 (ID8.0): SGP_RX_GP(1)[SDATAIN0]\<0\>.
_ Bit 32 (ID10.2): SGP_RX_GP(2)[SDATAIN3]\<0\>.
_ Bit 40 (ID13.1): SGP_RX_GP(2)[SDATAIN2]\<0\>.
_ Bit 48 (ID16.0): SGP_RX_GP(2)[SDATAIN1]\<0\>.
_ Bit 56 (ID18.2): SGP_RX_GP(2)[SDATAIN0]\<0\>.
_ Bit 59 (ID19.2): SGP_RX_GP(2)[SDATAIN0]\<3\>. */
uint32_t sdatain1 : 8; /**< [ 15: 8](RO/H) See [SDATAIN0]. */
uint32_t sdatain2 : 8; /**< [ 23: 16](RO/H) See [SDATAIN0]. */
uint32_t sdatain3 : 8; /**< [ 31: 24](RO/H) See [SDATAIN0]. */
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_sgp_rx_gpx bdk_sgp_rx_gpx_t;
static inline uint64_t BDK_SGP_RX_GPX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_RX_GPX(unsigned long a)
{
if ((a>=1)&&(a<=2))
return 0x87e027000800ll + 4ll * ((a) & 0x3);
__bdk_csr_fatal("SGP_RX_GPX", 1, a, 0, 0, 0);
}
#define typedef_BDK_SGP_RX_GPX(a) bdk_sgp_rx_gpx_t
#define bustype_BDK_SGP_RX_GPX(a) BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_RX_GPX(a) "SGP_RX_GPX"
#define device_bar_BDK_SGP_RX_GPX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_RX_GPX(a) (a)
#define arguments_BDK_SGP_RX_GPX(a) (a),-1,-1,-1
/**
* Register (RSL32b) sgp_rx_gp_cfg
*
* SGPIO Receive GPIO Configuration Register
*/
union bdk_sgp_rx_gp_cfg
{
uint32_t u;
struct bdk_sgp_rx_gp_cfg_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_24_31 : 8;
uint32_t count : 8; /**< [ 23: 16](RO/H) Number of repetitions remaining. A [COUNT] of 0xFF indicates infinite repetitions are remaining. */
uint32_t reserved_0_15 : 16;
#else /* Word 0 - Little Endian */
uint32_t reserved_0_15 : 16;
uint32_t count : 8; /**< [ 23: 16](RO/H) Number of repetitions remaining. A [COUNT] of 0xFF indicates infinite repetitions are remaining. */
uint32_t reserved_24_31 : 8;
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_rx_gp_cfg_s cn; */
};
typedef union bdk_sgp_rx_gp_cfg bdk_sgp_rx_gp_cfg_t;
#define BDK_SGP_RX_GP_CFG BDK_SGP_RX_GP_CFG_FUNC()
static inline uint64_t BDK_SGP_RX_GP_CFG_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_RX_GP_CFG_FUNC(void)
{
return 0x87e027000800ll;
}
#define typedef_BDK_SGP_RX_GP_CFG bdk_sgp_rx_gp_cfg_t
#define bustype_BDK_SGP_RX_GP_CFG BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_RX_GP_CFG "SGP_RX_GP_CFG"
#define device_bar_BDK_SGP_RX_GP_CFG 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_RX_GP_CFG 0
#define arguments_BDK_SGP_RX_GP_CFG -1,-1,-1,-1
/**
* Register (RSL32b) sgp_tx#
*
* SGPIO Transmit Registers
*/
union bdk_sgp_txx
{
uint32_t u;
struct bdk_sgp_txx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t d3_act : 3; /**< [ 31: 29](R/W) Drive 3+4*index's activity state. */
uint32_t d3_loc : 2; /**< [ 28: 27](R/W) Drive 3+4*index's locate state. */
uint32_t d3_err : 3; /**< [ 26: 24](R/W) Drive 3+4*index's error state. */
uint32_t d2_act : 3; /**< [ 23: 21](R/W) Drive 2+4*index's activity state. */
uint32_t d2_loc : 2; /**< [ 20: 19](R/W) Drive 2+4*index's locate state. */
uint32_t d2_err : 3; /**< [ 18: 16](R/W) Drive 2+4*index's error state. */
uint32_t d1_act : 3; /**< [ 15: 13](R/W) Drive 1+4*index's activity state. */
uint32_t d1_loc : 2; /**< [ 12: 11](R/W) Drive 1+4*index's locate state. */
uint32_t d1_err : 3; /**< [ 10: 8](R/W) Drive 1+4*index's error state. */
uint32_t d0_act : 3; /**< [ 7: 5](R/W) Drive 0+4*index's activity state, enumerated by SGP_TX_ACT_E. */
uint32_t d0_loc : 2; /**< [ 4: 3](R/W) Drive 0+4*index's locate state, enumerated by SGP_TX_LOC_E. */
uint32_t d0_err : 3; /**< [ 2: 0](R/W) Drive 0+4*index's error state, enumerated by SGP_TX_ERR_E. */
#else /* Word 0 - Little Endian */
uint32_t d0_err : 3; /**< [ 2: 0](R/W) Drive 0+4*index's error state, enumerated by SGP_TX_ERR_E. */
uint32_t d0_loc : 2; /**< [ 4: 3](R/W) Drive 0+4*index's locate state, enumerated by SGP_TX_LOC_E. */
uint32_t d0_act : 3; /**< [ 7: 5](R/W) Drive 0+4*index's activity state, enumerated by SGP_TX_ACT_E. */
uint32_t d1_err : 3; /**< [ 10: 8](R/W) Drive 1+4*index's error state. */
uint32_t d1_loc : 2; /**< [ 12: 11](R/W) Drive 1+4*index's locate state. */
uint32_t d1_act : 3; /**< [ 15: 13](R/W) Drive 1+4*index's activity state. */
uint32_t d2_err : 3; /**< [ 18: 16](R/W) Drive 2+4*index's error state. */
uint32_t d2_loc : 2; /**< [ 20: 19](R/W) Drive 2+4*index's locate state. */
uint32_t d2_act : 3; /**< [ 23: 21](R/W) Drive 2+4*index's activity state. */
uint32_t d3_err : 3; /**< [ 26: 24](R/W) Drive 3+4*index's error state. */
uint32_t d3_loc : 2; /**< [ 28: 27](R/W) Drive 3+4*index's locate state. */
uint32_t d3_act : 3; /**< [ 31: 29](R/W) Drive 3+4*index's activity state. */
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_txx_s cn; */
};
typedef union bdk_sgp_txx bdk_sgp_txx_t;
static inline uint64_t BDK_SGP_TXX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_TXX(unsigned long a)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX) && (a<=3))
return 0x87e027000c00ll + 4ll * ((a) & 0x3);
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=4))
return 0x87e027000c00ll + 4ll * ((a) & 0x7);
__bdk_csr_fatal("SGP_TXX", 1, a, 0, 0, 0);
}
#define typedef_BDK_SGP_TXX(a) bdk_sgp_txx_t
#define bustype_BDK_SGP_TXX(a) BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_TXX(a) "SGP_TXX"
#define device_bar_BDK_SGP_TXX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_TXX(a) (a)
#define arguments_BDK_SGP_TXX(a) (a),-1,-1,-1
/**
* Register (RSL32b) sgp_tx_gp#
*
* SGPIO Transmit GPIO Registers
*/
union bdk_sgp_tx_gpx
{
uint32_t u;
struct bdk_sgp_tx_gpx_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t sdataout3 : 8; /**< [ 31: 24](R/W) See [SDATAOUT0]. */
uint32_t sdataout2 : 8; /**< [ 23: 16](R/W) See [SDATAOUT0]. */
uint32_t sdataout1 : 8; /**< [ 15: 8](R/W) See [SDATAOUT0]. */
uint32_t sdataout0 : 8; /**< [ 7: 0](R/W) Raw data to shift onto SGPIO_SDATAOUT. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_TX_GP(1)[SDATAOUT3]\<0\>.
_ Bit 8 (ID2.2): SGP_TX_GP(1)[SDATAOUT2]\<0\>.
_ Bit 16 (ID5.1): SGP_TX_GP(1)[SDATAOUT1]\<0\>.
_ Bit 24 (ID8.0): SGP_TX_GP(1)[SDATAOUT0]\<0\>.
_ Bit 32 (ID10.2): SGP_TX_GP(2)[SDATAOUT3]\<0\>.
_ Bit 40 (ID13.1): SGP_TX_GP(2)[SDATAOUT2]\<0\>.
_ Bit 47 (ID15.2): SGP_TX_GP(2)[SDATAOUT2]\<7\>.
SGP_TX_GP(2)[SDATAOUT1/SDATAOUT0] are ignored. */
#else /* Word 0 - Little Endian */
uint32_t sdataout0 : 8; /**< [ 7: 0](R/W) Raw data to shift onto SGPIO_SDATAOUT. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_TX_GP(1)[SDATAOUT3]\<0\>.
_ Bit 8 (ID2.2): SGP_TX_GP(1)[SDATAOUT2]\<0\>.
_ Bit 16 (ID5.1): SGP_TX_GP(1)[SDATAOUT1]\<0\>.
_ Bit 24 (ID8.0): SGP_TX_GP(1)[SDATAOUT0]\<0\>.
_ Bit 32 (ID10.2): SGP_TX_GP(2)[SDATAOUT3]\<0\>.
_ Bit 40 (ID13.1): SGP_TX_GP(2)[SDATAOUT2]\<0\>.
_ Bit 47 (ID15.2): SGP_TX_GP(2)[SDATAOUT2]\<7\>.
SGP_TX_GP(2)[SDATAOUT1/SDATAOUT0] are ignored. */
uint32_t sdataout1 : 8; /**< [ 15: 8](R/W) See [SDATAOUT0]. */
uint32_t sdataout2 : 8; /**< [ 23: 16](R/W) See [SDATAOUT0]. */
uint32_t sdataout3 : 8; /**< [ 31: 24](R/W) See [SDATAOUT0]. */
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_tx_gpx_s cn8; */
struct bdk_sgp_tx_gpx_cn9
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t sdataout3 : 8; /**< [ 31: 24](R/W) See [SDATAOUT0]. */
uint32_t sdataout2 : 8; /**< [ 23: 16](R/W) See [SDATAOUT0]. */
uint32_t sdataout1 : 8; /**< [ 15: 8](R/W) See [SDATAOUT0]. */
uint32_t sdataout0 : 8; /**< [ 7: 0](R/W) Raw data to shift onto SGPIO_SDATAOUT. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_TX_GP(1)[SDATAOUT3]\<0\>.
_ Bit 8 (ID2.2): SGP_TX_GP(1)[SDATAOUT2]\<0\>.
_ Bit 16 (ID5.1): SGP_TX_GP(1)[SDATAOUT1]\<0\>.
_ Bit 24 (ID8.0): SGP_TX_GP(1)[SDATAOUT0]\<0\>.
_ Bit 32 (ID10.2): SGP_TX_GP(2)[SDATAOUT3]\<0\>.
_ Bit 40 (ID13.1): SGP_TX_GP(2)[SDATAOUT2]\<0\>.
_ Bit 47 (ID15.2): SGP_TX_GP(2)[SDATAOUT2]\<7\>.
_ Bit 48 (ID16.0): SGP_TX_GP(2)[SDATAOUT1]\<0\>.
_ Bit 56 (ID18.2): SGP_TX_GP(2)[SDATAOUT0]\<0\>.
_ Bit 59 (ID19.2): SGP_TX_GP(2)[SDATAOUT0]\<3\>. */
#else /* Word 0 - Little Endian */
uint32_t sdataout0 : 8; /**< [ 7: 0](R/W) Raw data to shift onto SGPIO_SDATAOUT. The bits are not in natural 32-bit form; they are
assigned to registers as follows:
_ Bit 0 (ID0.0): SGP_TX_GP(1)[SDATAOUT3]\<0\>.
_ Bit 8 (ID2.2): SGP_TX_GP(1)[SDATAOUT2]\<0\>.
_ Bit 16 (ID5.1): SGP_TX_GP(1)[SDATAOUT1]\<0\>.
_ Bit 24 (ID8.0): SGP_TX_GP(1)[SDATAOUT0]\<0\>.
_ Bit 32 (ID10.2): SGP_TX_GP(2)[SDATAOUT3]\<0\>.
_ Bit 40 (ID13.1): SGP_TX_GP(2)[SDATAOUT2]\<0\>.
_ Bit 47 (ID15.2): SGP_TX_GP(2)[SDATAOUT2]\<7\>.
_ Bit 48 (ID16.0): SGP_TX_GP(2)[SDATAOUT1]\<0\>.
_ Bit 56 (ID18.2): SGP_TX_GP(2)[SDATAOUT0]\<0\>.
_ Bit 59 (ID19.2): SGP_TX_GP(2)[SDATAOUT0]\<3\>. */
uint32_t sdataout1 : 8; /**< [ 15: 8](R/W) See [SDATAOUT0]. */
uint32_t sdataout2 : 8; /**< [ 23: 16](R/W) See [SDATAOUT0]. */
uint32_t sdataout3 : 8; /**< [ 31: 24](R/W) See [SDATAOUT0]. */
#endif /* Word 0 - End */
} cn9;
};
typedef union bdk_sgp_tx_gpx bdk_sgp_tx_gpx_t;
static inline uint64_t BDK_SGP_TX_GPX(unsigned long a) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_TX_GPX(unsigned long a)
{
if ((a>=1)&&(a<=2))
return 0x87e027001000ll + 4ll * ((a) & 0x3);
__bdk_csr_fatal("SGP_TX_GPX", 1, a, 0, 0, 0);
}
#define typedef_BDK_SGP_TX_GPX(a) bdk_sgp_tx_gpx_t
#define bustype_BDK_SGP_TX_GPX(a) BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_TX_GPX(a) "SGP_TX_GPX"
#define device_bar_BDK_SGP_TX_GPX(a) 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_TX_GPX(a) (a)
#define arguments_BDK_SGP_TX_GPX(a) (a),-1,-1,-1
/**
* Register (RSL32b) sgp_tx_gp_cfg
*
* SGPIO Transmit GPIO Configuration Register
*/
union bdk_sgp_tx_gp_cfg
{
uint32_t u;
struct bdk_sgp_tx_gp_cfg_s
{
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
uint32_t reserved_28_31 : 4;
uint32_t sload : 4; /**< [ 27: 24](R/W) Pattern to transmit on SGPIO_SLOAD at the start of each general purpose bit stream.
[SLOAD]\<0\> is the first bit (L0), \<3\> is the last bit (L3). */
uint32_t count : 8; /**< [ 23: 16](R/W) Number of times to transmit the SGP_TX_GP(1..2) pattern and receive
into SGP_RX_GP(1..2). A [COUNT] of 0xFF transmits continuously until [COUNT] is set to
non-0xFF. */
uint32_t reserved_0_15 : 16;
#else /* Word 0 - Little Endian */
uint32_t reserved_0_15 : 16;
uint32_t count : 8; /**< [ 23: 16](R/W) Number of times to transmit the SGP_TX_GP(1..2) pattern and receive
into SGP_RX_GP(1..2). A [COUNT] of 0xFF transmits continuously until [COUNT] is set to
non-0xFF. */
uint32_t sload : 4; /**< [ 27: 24](R/W) Pattern to transmit on SGPIO_SLOAD at the start of each general purpose bit stream.
[SLOAD]\<0\> is the first bit (L0), \<3\> is the last bit (L3). */
uint32_t reserved_28_31 : 4;
#endif /* Word 0 - End */
} s;
/* struct bdk_sgp_tx_gp_cfg_s cn; */
};
typedef union bdk_sgp_tx_gp_cfg bdk_sgp_tx_gp_cfg_t;
#define BDK_SGP_TX_GP_CFG BDK_SGP_TX_GP_CFG_FUNC()
static inline uint64_t BDK_SGP_TX_GP_CFG_FUNC(void) __attribute__ ((pure, always_inline));
static inline uint64_t BDK_SGP_TX_GP_CFG_FUNC(void)
{
return 0x87e027001000ll;
}
#define typedef_BDK_SGP_TX_GP_CFG bdk_sgp_tx_gp_cfg_t
#define bustype_BDK_SGP_TX_GP_CFG BDK_CSR_TYPE_RSL32b
#define basename_BDK_SGP_TX_GP_CFG "SGP_TX_GP_CFG"
#define device_bar_BDK_SGP_TX_GP_CFG 0x0 /* PF_BAR0 */
#define busnum_BDK_SGP_TX_GP_CFG 0
#define arguments_BDK_SGP_TX_GP_CFG -1,-1,-1,-1
#endif /* __BDK_CSRS_SGP_H__ */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,117 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for reading Cavium chip fuses.
*
* <hr>$Revision: 49448 $<hr>
*/
/**
* Read a single fuse bit
*
* @param fuse Fuse number (0-1024)
*
* @return fuse value: 0 or 1
*/
extern int bdk_fuse_read(bdk_node_t node, int fuse);
/**
* Read a range of fuses
*
* @param node Node to read from
* @param fuse Fuse number
* @param width Number of fuses to read, max of 64
*
* @return Fuse value
*/
extern uint64_t bdk_fuse_read_range(bdk_node_t node, int fuse, int width);
/**
* Soft blow a fuse. Soft blown fuses keep there new value over soft resets, but
* not power cycles.
*
* @param node Node to blow
* @param fuse Fuse to blow
*
* @return Zero on success, negative on failure
*/
extern int bdk_fuse_soft_blow(bdk_node_t node, int fuse);
/**
* Read a single fuse bit from the field set (FUSF)
*
* @param fuse Fuse number (0-1024)
*
* @return fuse value: 0 or 1
*/
extern int bdk_fuse_field_read(bdk_node_t node, int fuse);
/**
* Soft blow a fuse in the field set (FUSF). Soft blown fuses
* keep there new value over soft resets, but not power cycles.
*
* @param node Node to blow
* @param fuse Fuse to blow
*
* @return Zero on success, negative on failure
*/
extern int bdk_fuse_field_soft_blow(bdk_node_t node, int fuse);
/**
* Hard blow fuses in the field set (FUSF). Up to 128 fuses in a bank
* are blown at the same time
*
* @param node Node to blow
* @param start_fuse First fuses to blow. Must be on a 128 bit boundary.
* This fuse is blown to match the LSB of fuse 0.
* @param fuses0 First 64 fuse values. Bits with a 1 are blown. LSB
* of fuses0 maps to start_fuse. MSB of fuses0 maps to
* (start_fuse + 63).
* @param fuses1 Second 64 fuse values. Bits with a 1 are blown. LSB
* of fuses1 maps to (start_fuse + 64). MSB of fuses1
* maps to (start_fuse + 127).
*
* @return Zero on success, negative on failure
*/
extern int bdk_fuse_field_hard_blow(bdk_node_t node, int start_fuse, uint64_t fuses0, uint64_t fuses1);

View File

@ -0,0 +1,100 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Defiens and functions for performing LMT operations, such as
* LMTST and LMTCANCEL
*
* @defgroup lmt Local Memory Transaction (LMT) support
* @{
*/
#include "libbdk-arch/bdk-csrs-lmt.h"
/**
* Address of the LMT store area in physical memory
*/
#define __BDK_LMTLINE_CN83XX 0x87F100000000ull
/**
* Flush the LMTLINE area of all previous writes and clear the valid flag
*/
static inline void bdk_lmt_cancel(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
*(volatile uint64_t *)(__BDK_LMTLINE_CN83XX | (1 << 10)) = 0;
else
BDK_CSR_WRITE(bdk_numa_local(), BDK_LMT_LF_LMTCANCEL, 0);
}
/**
* Return a volatile pointer to the LMTLINE area in 64bit words. Good programming
* practice would to always store sequencially, incrementing the pointer for each
* word written.
*
* @return Voltaile uint64_t pointer to LMTLINE
*/
static inline volatile uint64_t *bdk_lmt_store_ptr(void)
{
if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
return (volatile uint64_t *)__BDK_LMTLINE_CN83XX;
else
return (volatile uint64_t *)BDK_LMT_LF_LMTLINEX(0);
}
/**
* Send the data stored to LMTLINE to an IO block. This call may
* fail if the hardware has invalidated the LMTLINE area. If it
* fails, you must issue all LMT stores again and redo this
* call. Note the return status of this function is backwards
* to most BDK functions. It matches the LMTST hardware result.
*
* @param io_address 48 bit IO address where the LMTLINE data will be sent
*
* @return Zero on failure, non-zero on success
*/
static inline int bdk_lmt_submit(uint64_t io_address)
{
int64_t result = 0;
asm volatile ("LDEOR xzr,%x[rf],[%[rs]]" : [rf] "=r"(result): [rs] "r"(io_address));
return bdk_le64_to_cpu(result);
}
/** @} */

View File

@ -0,0 +1,170 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for determining which Cavium chip you are running
* on.
*
* <hr>$Revision: 49448 $<hr>
* @addtogroup chips
* @{
*/
/* Flag bits in top byte. The top byte of MIDR_EL1 is defined
as ox43, the Cavium implementer code. In this number, bits
7,5,4 are defiend as zero. We use these bits to signal
that revision numbers should be ignored. It isn't ideal
that these are in the middle of an already defined field,
but this keeps the model numbers as 32 bits */
#define __OM_IGNORE_REVISION 0x80000000
#define __OM_IGNORE_MINOR_REVISION 0x20000000
#define __OM_IGNORE_MODEL 0x10000000
#define CAVIUM_CN88XX_PASS1_0 0x430f0a10
#define CAVIUM_CN88XX_PASS1_1 0x430f0a11
#define CAVIUM_CN88XX_PASS2_0 0x431f0a10
#define CAVIUM_CN88XX_PASS2_1 0x431f0a11
#define CAVIUM_CN88XX_PASS2_2 0x431f0a12
#define CAVIUM_CN88XX (CAVIUM_CN88XX_PASS1_0 | __OM_IGNORE_REVISION)
#define CAVIUM_CN88XX_PASS1_X (CAVIUM_CN88XX_PASS1_0 | __OM_IGNORE_MINOR_REVISION)
#define CAVIUM_CN88XX_PASS2_X (CAVIUM_CN88XX_PASS2_0 | __OM_IGNORE_MINOR_REVISION)
/* Note CN86XX will also match the CN88XX macros above. See comment in
CAVIUM_IS_MODEL() about MIO_FUS_FUSE_NUM_E::CHIP_IDX bits 6-7 */
#define CAVIUM_CN83XX_PASS1_0 0x430f0a30
#define CAVIUM_CN83XX (CAVIUM_CN83XX_PASS1_0 | __OM_IGNORE_REVISION)
#define CAVIUM_CN83XX_PASS1_X (CAVIUM_CN83XX_PASS1_0 | __OM_IGNORE_MINOR_REVISION)
#define CAVIUM_CN81XX_PASS1_0 0x430f0a20
#define CAVIUM_CN81XX (CAVIUM_CN81XX_PASS1_0 | __OM_IGNORE_REVISION)
#define CAVIUM_CN81XX_PASS1_X (CAVIUM_CN81XX_PASS1_0 | __OM_IGNORE_MINOR_REVISION)
/* Note CN80XX will also match the CN81XX macros above. See comment in
CAVIUM_IS_MODEL() about MIO_FUS_FUSE_NUM_E::CHIP_IDX bits 6-7 */
#define CAVIUM_CN93XX_PASS1_0 0x430f0b20
#define CAVIUM_CN93XX (CAVIUM_CN93XX_PASS1_0 | __OM_IGNORE_REVISION)
#define CAVIUM_CN93XX_PASS1_X (CAVIUM_CN93XX_PASS1_0 | __OM_IGNORE_MINOR_REVISION)
/* These match entire families of chips */
#define CAVIUM_CN8XXX (CAVIUM_CN88XX_PASS1_0 | __OM_IGNORE_MODEL)
#define CAVIUM_CN9XXX (CAVIUM_CN93XX_PASS1_0 | __OM_IGNORE_MODEL)
static inline uint64_t cavium_get_model() __attribute__ ((pure, always_inline));
static inline uint64_t cavium_get_model()
{
#ifdef BDK_BUILD_HOST
extern uint32_t thunder_remote_get_model(void) __attribute__ ((pure));
return thunder_remote_get_model();
#else
uint64_t result;
asm ("mrs %[rd],MIDR_EL1" : [rd] "=r" (result));
return result;
#endif
}
/**
* Return non-zero if the chip matech the passed model.
*
* @param arg_model One of the CAVIUM_* constants for chip models and passes
*
* @return Non-zero if match
*/
static inline int CAVIUM_IS_MODEL(uint32_t arg_model) __attribute__ ((pure, always_inline));
static inline int CAVIUM_IS_MODEL(uint32_t arg_model)
{
const uint32_t FAMILY = 0xff00; /* Bits 15:8, generation t8x=0xa, t9x=0xb */
const uint32_t PARTNUM = 0xfff0; /* Bits 15:4, chip t88=0x81, t81=0xa2, t83=0xa3, etc */
const uint32_t VARIANT = 0xf00000; /* Bits 23:20, major pass */
const uint32_t REVISION = 0xf; /* Bits 3:0, minor pass */
/* Note that the model matching here is unaffected by
MIO_FUS_FUSE_NUM_E::CHIP_IDX bits 6-7, which are the alternate package
fuses. These bits don't affect MIDR_EL1, so:
CN80XX will match CN81XX (CHIP_IDX 6 is set for 676 ball package)
CN80XX will match CN81XX (CHIP_IDX 7 is set for 555 ball package)
CN86XX will match CN88XX (CHIP_IDX 6 is set for 676 ball package)
Alternate package parts are detected using MIO_FUS_DAT2[chip_id],
specifically the upper two bits */
uint32_t my_model = cavium_get_model();
uint32_t mask;
if (arg_model & __OM_IGNORE_MODEL)
mask = FAMILY; /* Matches chip generation (CN8XXX, CN9XXX) */
else if (arg_model & __OM_IGNORE_REVISION)
mask = PARTNUM; /* Matches chip model (CN88XX, CN81XX, CN83XX) */
else if (arg_model & __OM_IGNORE_MINOR_REVISION)
mask = PARTNUM | VARIANT; /* Matches chip model and major version */
else
mask = PARTNUM | VARIANT | REVISION; /* Matches chip model, major version, and minor version */
return ((arg_model & mask) == (my_model & mask));
}
/**
* Return non-zero if the die is in an alternate package. The
* normal is_model() checks will treat alternate package parts
* as all the same, where this function can be used to detect
* them. The return value is the upper two bits of
* MIO_FUS_DAT2[chip_id]. Most alternate packages use bit 6,
* which will return 1 here. Parts with a second alternative
* will use bit 7, which will return 2.
*
* @param arg_model One of the CAVIUM_* constants for chip models and passes
*
* @return Non-zero if an alternate package
* 0 = Normal package
* 1 = Alternate package 1 (CN86XX, CN80XX with 555 balls)
* 2 = Alternate package 2 (CN80XX with 676 balls)
* 3 = Alternate package 3 (Currently unused)
*/
extern int cavium_is_altpkg(uint32_t arg_model);
/**
* Return the SKU string for a chip
*
* @param node Node to get SKU for
*
* @return Chip's SKU
*/
extern const char* bdk_model_get_sku(int node);
/** @} */

View File

@ -0,0 +1,139 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for dealing with multiple chips organized into a
* NUMA cluster.
*
* <hr>$Revision: 49448 $<hr>
*/
typedef enum
{
BDK_NODE_0 = 0,
BDK_NODE_1 = 1,
BDK_NODE_2 = 2,
BDK_NODE_3 = 3,
BDK_NUMA_MAX_NODES = 4
} bdk_node_t;
/**
* Return the local node number
*
* @return Node number
*/
static inline bdk_node_t bdk_numa_local(void) __attribute__ ((always_inline, pure));
static inline bdk_node_t bdk_numa_local(void)
{
#ifndef BDK_BUILD_HOST
int mpidr_el1;
BDK_MRS_NV(MPIDR_EL1, mpidr_el1);
int result;
result = (mpidr_el1 >> 16) & 0xff;
return BDK_NODE_0 + result;
#else
return BDK_NODE_0; /* FIXME: choose remote node */
#endif
}
/**
* Return the master node number
*
* @return Node number
*/
static inline bdk_node_t bdk_numa_master(void)
{
extern int __bdk_numa_master_node;
return __bdk_numa_master_node;
}
/**
* Get a bitmask of the nodes that exist
*
* @return bitmask
*/
extern uint64_t bdk_numa_get_exists_mask(void);
/**
* Add a node to the exists mask
*
* @param node Node to add
*/
extern void bdk_numa_set_exists(bdk_node_t node);
/**
* Return true if a node exists
*
* @param node Node to check
*
* @return Non zero if the node exists
*/
extern int bdk_numa_exists(bdk_node_t node);
/**
* Return true if there is only one node
*
* @return
*/
extern int bdk_numa_is_only_one();
/**
* Given a physical address without a node, return the proper physical address
* for the given node.
*
* @param node Node to create address for
* @param pa Base physical address
*
* @return Node specific address
*/
static inline uint64_t bdk_numa_get_address(bdk_node_t node, uint64_t pa) __attribute__((pure,always_inline));
static inline uint64_t bdk_numa_get_address(bdk_node_t node, uint64_t pa)
{
if (pa & (1ull << 47))
pa |= (uint64_t)(node&3) << 44;
else if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
pa |= (uint64_t)(node & 3) << 40; /* CN8XXX uses bits [41:40] for nodes */
else
pa |= (uint64_t)(node & 3) << 44; /* CN9XXX uses bits [45:44] for nodes */
return pa;
}

View File

@ -0,0 +1,82 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for information about the run platform.
*
* <hr>$Revision: 49448 $<hr>
* @addtogroup hal
* @{
*/
/**
* This typedef defines the possible platforms for the BDK. The
* numbers represent fuse setting in Fuses[197:195].
*/
typedef enum
{
BDK_PLATFORM_HW = 0,
BDK_PLATFORM_EMULATOR = 1,
BDK_PLATFORM_RTL = 2,
BDK_PLATFORM_ASIM = 3,
} bdk_platform_t;
/**
* Check which platform we are currently running on. This allows a BDK binary to
* run on various platforms without a recompile.
*
* @param platform Platform to check for
*
* @return Non zero if we are on the platform
*/
static inline int bdk_is_platform(bdk_platform_t platform) __attribute__ ((pure, always_inline));
static inline int bdk_is_platform(bdk_platform_t platform)
{
extern bdk_platform_t __bdk_platform;
return (__bdk_platform == platform);
}
/**
* Call to initialize the platform state
*/
extern void __bdk_platform_init();
/** @} */

View File

@ -0,0 +1,107 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions and macros to control what parts of the BDK are linked in
*
* <hr>$Revision: 49448 $<hr>
* @defgroup require Component linking control
* @{
*/
/**
* Optional parts of the BDK code are pulled in by adding
* BDK_REQUIRE() lines to the function bdk_require_depends().
* Component symbols are defined as weak so that they are not
* linked in unless a BDK_REQUIRE() pulls them in.
*/
#define BDK_REQUIRE(component) \
do \
{ \
extern char __bdk_require_symbol_##component; \
bdk_warn_if(__bdk_require_symbol_##component, \
"Require of %s failed\n", #component); \
} while (0)
/**
* The following macro defines a special symbol in a C file to
* define it as a require component. Referencing this symbol
* causes all objects defined in the C file to be pulled in. This
* symbol should only be referenced by using the BDK_REQUIRE()
* macro in the function bdk_require_depends().
*/
#define BDK_REQUIRE_DEFINE(component) \
char __bdk_require_symbol_##component; \
char __bdk_is_required_symbol_##component
/**
* Return if a component has been required. Useful for if
* statements around referencing of weak symbols.
*/
#define BDK_IS_REQUIRED(component) \
({int is_required; \
do \
{ \
extern char __bdk_is_required_symbol_##component __attribute__((weak));\
is_required = (&__bdk_is_required_symbol_##component != NULL); \
} while (0); \
is_required;})
/**
* The require macros use weak symbols to control if components
* are linked in. All directly referenced symbols in a component
* must be defined a weak. This causes the component to only be
* pulled in by the linker if the symbol defined by
* BDK_REQUIRE_DEFINE is used.
*/
#define BDK_WEAK __attribute__((weak))
/**
* This function is not defined by the BDK libraries. It must be
* defined by all BDK applications. It should be empty except for
* containing BDK_REQUIRE() lines. The bdk-init code has a strong
* reference to bdk_requires_depends() which then contains strong
* references to all needed components.
*/
extern void __bdk_require_depends(void);
/** @} */

View File

@ -0,0 +1,130 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Utility functions for endian swapping
*
* <hr>$Revision: 32636 $<hr>
*
* @addtogroup hal
* @{
*/
/**
* Byte swap a 16 bit number
*
* @param x 16 bit number
* @return Byte swapped result
*/
static inline uint16_t bdk_swap16(uint16_t x)
{
return ((uint16_t)((((uint16_t)(x) & (uint16_t)0x00ffU) << 8) |
(((uint16_t)(x) & (uint16_t)0xff00U) >> 8) ));
}
/**
* Byte swap a 32 bit number
*
* @param x 32 bit number
* @return Byte swapped result
*/
static inline uint32_t bdk_swap32(uint32_t x)
{
#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
return __builtin_bswap32(x);
#else
x = ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF);
x = (x>>16) | (x<<16);
return x;
#endif
}
/**
* Byte swap a 64 bit number
*
* @param x 64 bit number
* @return Byte swapped result
*/
static inline uint64_t bdk_swap64(uint64_t x)
{
#if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3))
return __builtin_bswap64(x);
#else
x = ((x<< 8)&0xFF00FF00FF00FF00ULL) | ((x>> 8)&0x00FF00FF00FF00FFULL);
x = ((x<<16)&0xFFFF0000FFFF0000ULL) | ((x>>16)&0x0000FFFF0000FFFFULL);
return (x>>32) | (x<<32);
#endif
}
#if __BYTE_ORDER == __BIG_ENDIAN
#define bdk_cpu_to_le16(x) bdk_swap16(x)
#define bdk_cpu_to_le32(x) bdk_swap32(x)
#define bdk_cpu_to_le64(x) bdk_swap64(x)
#define bdk_cpu_to_be16(x) (x)
#define bdk_cpu_to_be32(x) (x)
#define bdk_cpu_to_be64(x) (x)
#else
#define bdk_cpu_to_le16(x) (x)
#define bdk_cpu_to_le32(x) (x)
#define bdk_cpu_to_le64(x) (x)
#define bdk_cpu_to_be16(x) bdk_swap16(x)
#define bdk_cpu_to_be32(x) bdk_swap32(x)
#define bdk_cpu_to_be64(x) bdk_swap64(x)
#endif
#define bdk_le16_to_cpu(x) bdk_cpu_to_le16(x)
#define bdk_le32_to_cpu(x) bdk_cpu_to_le32(x)
#define bdk_le64_to_cpu(x) bdk_cpu_to_le64(x)
#define bdk_be16_to_cpu(x) bdk_cpu_to_be16(x)
#define bdk_be32_to_cpu(x) bdk_cpu_to_be32(x)
#define bdk_be64_to_cpu(x) bdk_cpu_to_be64(x)
/** @} */

View File

@ -0,0 +1,59 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for identifying BDK build version.
*
* <hr>$Revision$<hr>
*/
extern const char bdk_version_str[];
/**
* Return BDK version string
*
* @return BDK version string
*/
static inline const char *bdk_version_string(void)
{
return bdk_version_str;
}

View File

@ -0,0 +1,104 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for reporting errors and warnings.
*
* <hr>$Revision: 49448 $<hr>
*
* @defgroup stdio Standard IO related functions
* @{
*/
extern void __bdk_die(void) __attribute__ ((noreturn));
extern void bdk_fatal(const char *format, ...) __attribute__ ((noreturn, format(printf, 1, 2)));
extern void bdk_error(const char *format, ...) __attribute__ ((format(printf, 1, 2)));
extern void bdk_warn(const char *format, ...) __attribute__ ((format(printf, 1, 2)));
#define bdk_warn_if(expression, format, ...) if (bdk_unlikely(expression)) bdk_warn(format, ##__VA_ARGS__)
/* The following defines control detailed tracing of various parts of the
BDK. Each one can be enabled(1) or disabled(0) independently. These
should be disabled unless you are trying to debug something specific */
typedef enum
{
BDK_TRACE_ENABLE_BGX, /* BGX networking block */
BDK_TRACE_ENABLE_DRAM, /* DRAM initialzation */
BDK_TRACE_ENABLE_DRAM_TEST, /* DRAM test code */
BDK_TRACE_ENABLE_INIT, /* Early initialization, before main() */
BDK_TRACE_ENABLE_ECAM, /* ECAM initialization */
BDK_TRACE_ENABLE_QLM, /* QLM related debug */
BDK_TRACE_ENABLE_EMMC, /* eMMC related debug */
BDK_TRACE_ENABLE_PCIE, /* PCIe link init */
BDK_TRACE_ENABLE_PCIE_CONFIG, /* PCIe config space reads / writes */
BDK_TRACE_ENABLE_SATA, /* SATA/AHCI related debug */
BDK_TRACE_ENABLE_CCPI, /* Multi-node related debug */
BDK_TRACE_ENABLE_FATFS, /* FatFs related debug */
BDK_TRACE_ENABLE_MPI, /* MPI related debug */
BDK_TRACE_ENABLE_ENV, /* Environment variables related debug */
BDK_TRACE_ENABLE_FPA, /* Free Pool Allocator */
BDK_TRACE_ENABLE_PKI, /* Packet Input */
BDK_TRACE_ENABLE_PKO, /* Packet Output */
BDK_TRACE_ENABLE_SSO, /* SSO */
BDK_TRACE_ENABLE_DEVICE, /* ECAM based device framework */
BDK_TRACE_ENABLE_DEVICE_SCAN, /* ECAM based device scanning detail */
BDK_TRACE_ENABLE_NIC, /* Virtual NIC */
BDK_TRACE_ENABLE_FDT_OS, /* Device tree passed to OS */
BDK_TRACE_ENABLE_USB_XHCI, /* USB XHCI block */
BDK_TRACE_ENABLE_PHY, /* Ethernet Phy drivers debug */
__BDK_TRACE_ENABLE_LAST, /* Must always be last value */
} bdk_trace_enable_t;
/* See bdk-config.c to change the trace level for before config files are loaded */
extern uint64_t bdk_trace_enables;
/**
* Macro for low level tracing of BDK functions. When enabled,
* these translate to printf() calls. The "area" is a string
* that is appended to "BDK_TRACE_ENABLE_" to figure out which
* enable macro to use. The macro expects a ';' after it.
*/
#define BDK_TRACE(area, format, ...) do { \
if (bdk_trace_enables & (1ull << BDK_TRACE_ENABLE_##area)) \
printf(#area ": " format, ##__VA_ARGS__); \
} while (0)
/** @} */

View File

@ -0,0 +1,43 @@
#ifndef __LIBBDK_BIST_H
#define __LIBBDK_BIST_H
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
void bdk_bist_check();
#endif

View File

@ -0,0 +1,41 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
void efuse_read_all_o3(unsigned char *efuse_ptr, int cached_read);
void dump_fuses(void);
int num_fuses(void);

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for BGX
*
* @addtogroup boot
* @{
*/
/**
* Configure BGX on all nodes as part of booting
*/
extern void bdk_boot_bgx(void);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for CCPI
*
* @addtogroup boot
* @{
*/
/**
* Initialize the CCPI links and bringup the other nodes
*/
extern void bdk_boot_ccpi(void);
/** @} */

View File

@ -0,0 +1,60 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for DRAM
*
* @addtogroup boot
* @{
*/
/**
* Configure DRAM on a specific node
*
* @param node Node to configure
* @param override_for_speed
* If non-zero, the DRAM init code will use this for the
* DRAM clock speed. This is used for SLT and should not
* be used otherwise.
*/
extern void bdk_boot_dram(bdk_node_t node, int override_for_speed);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for GPIO
*
* @addtogroup boot
* @{
*/
/**
* Configure GPIO on all nodes as part of booting
*/
extern void bdk_boot_gpio(void);
/** @} */

View File

@ -0,0 +1,86 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for displaying and retrieving infomration about the
* boot environment
*
* @addtogroup boot
* @{
*/
/**
* Display information about strapping and other hard configuration items for
* the specified node
*
* @param node Node to display
*/
void bdk_boot_info_strapping(bdk_node_t node);
/**
* Return a string containing information about the chip's manufacture wafer
*
* @param node Node to query
*
* @return Static string, reused on each call
*/
const char* bdk_boot_info_wafer(bdk_node_t node);
/**
* Return a string containing the chip's unique serial number
*
* @param node Node to query
*
* @return Static string, reused on each call
*/
const char* bdk_boot_info_serial(bdk_node_t node);
/**
* Return a string containing the chip's unique ID
*
* @param node Node to query
*
* @return Static string, reused on each call
*/
const char* bdk_boot_info_unique_id(bdk_node_t node);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for MDIO
*
* @addtogroup boot
* @{
*/
/**
* Configure MDIO on all nodes as part of booting
*/
extern void bdk_boot_mdio(void);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for PCIe
*
* @addtogroup boot
* @{
*/
/**
* Configure PCIe on all nodes as part of booting
*/
extern void bdk_boot_pcie(void);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for QLM
*
* @addtogroup boot
* @{
*/
/**
* Configure QLM on all nodes as part of booting
*/
extern void bdk_boot_qlm(void);
/** @} */

View File

@ -0,0 +1,94 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Interface to report boot status
*
* @addtogroup boot
* @{
*/
/**
* Possible boot statuses that can be reported
*/
typedef enum
{
/* Codes for boot stub */
BDK_BOOT_STATUS_BOOT_STUB_STARTING = 0x000,
BDK_BOOT_STATUS_BOOT_STUB_WAITING_FOR_KEY = 0x001,
BDK_BOOT_STATUS_BOOT_STUB_BOOT_MENU_KEY = 0x102, /* Signal boot complete as stopped by user */
BDK_BOOT_STATUS_BOOT_STUB_NO_BOOT_MENU_KEY = 0x003,
BDK_BOOT_STATUS_BOOT_STUB_LOAD_FAILED = 0x004,
/* Codes for init.bin */
BDK_BOOT_STATUS_INIT_STARTING = 0x005,
BDK_BOOT_STATUS_INIT_NODE0_DRAM = 0x006,
BDK_BOOT_STATUS_INIT_NODE0_DRAM_COMPLETE = 0x007,
BDK_BOOT_STATUS_INIT_NODE0_DRAM_FAILED = 0x008,
BDK_BOOT_STATUS_INIT_CCPI = 0x009,
BDK_BOOT_STATUS_INIT_CCPI_COMPLETE = 0x00a,
BDK_BOOT_STATUS_INIT_CCPI_FAILED = 0x00b,
BDK_BOOT_STATUS_INIT_NODE1_DRAM = 0x00c,
BDK_BOOT_STATUS_INIT_NODE1_DRAM_COMPLETE = 0x00d,
BDK_BOOT_STATUS_INIT_NODE1_DRAM_FAILED = 0x00e,
BDK_BOOT_STATUS_INIT_QLM = 0x00f,
BDK_BOOT_STATUS_INIT_QLM_COMPLETE = 0x010,
BDK_BOOT_STATUS_INIT_QLM_FAILED = 0x011,
BDK_BOOT_STATUS_INIT_LOAD_ATF = 0x012,
BDK_BOOT_STATUS_INIT_LOAD_DIAGNOSTICS = 0x013,
BDK_BOOT_STATUS_INIT_LOAD_FAILED = 0x014,
/* Codes for diagnostics.bin */
BDK_BOOT_STATUS_DIAG_STARTING = 0x015,
BDK_BOOT_STATUS_DIAG_COMPLETE = 0x116, /* Signal boot complete */
/* Special codes */
BDK_BOOT_STATUS_REQUEST_POWER_CYCLE = 0x0f2, /* Don't continue, power cycle */
} bdk_boot_status_t;
/**
* Report boot status to the BMC or whomever might care. This function
* will return quickly except for a status of "power cycle". In the power cycle
* case it is assumed the board is in a bad state and should not continue until
* a power cycle restarts us.
*
* @param status Status to report. Enumerated in bdk_boot_status_t
*/
extern void bdk_boot_status(bdk_boot_status_t status);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for TWSI
*
* @addtogroup boot
* @{
*/
/**
* Configure TWSI on all nodes as part of booting
*/
extern void bdk_boot_twsi(void);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for USB
*
* @addtogroup boot
* @{
*/
/**
* Configure USB on all nodes as part of booting
*/
extern void bdk_boot_usb(void);
/** @} */

View File

@ -0,0 +1,69 @@
#ifndef __BDK_BOOT_H__
#define __BDK_BOOT_H__
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Master include file for functions related to boot images and
* their operation. Any BDK based image booting on hardware has
* a number of common tasks it needs to do. This header includes
* the API functions in this category. Use bdk.h instead of
* including this file directly.
*
* @defgroup boot Boot related support functions
*/
#include "bdk-boot-bgx.h"
#include "bdk-boot-ccpi.h"
#include "bdk-boot-dram.h"
#include "bdk-boot-gpio.h"
#include "bdk-boot-info.h"
#include "bdk-boot-mdio.h"
#include "bdk-boot-pcie.h"
#include "bdk-boot-qlm.h"
#include "bdk-boot-status.h"
#include "bdk-boot-twsi.h"
#include "bdk-boot-usb.h"
#include "bdk-image.h"
#include "bdk-watchdog.h"
#include "bdk-xmodem.h"
#endif

View File

@ -0,0 +1,105 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Utility functions for handling binary images
*
* <hr>$Revision: 49448 $<hr>
*
* @defgroup image Binary image utility functions
* @{
*/
/**
* Structure present at the beginning of BDK images
*/
typedef struct
{
uint32_t instruction; /* Raw instruction for skipping header */
uint32_t length; /* Length of the image, includes header */
uint64_t magic; /* Magic string "THUNDERX" */
uint32_t crc32; /* CRC32 of image + header. These bytes are zero when calculating the CRC */
uint32_t reserved1; /* Zero, reserved for future use */
char name[64]; /* ASCII Image name. Must always end in zero */
char version[32]; /* ASCII Version. Must always end in zero */
uint64_t reserved[17]; /* Zero, reserved for future use */
} BDK_LITTLE_ENDIAN_STRUCT bdk_image_header_t;
/**
* Validate image header
*
* @param header Header to validate
*
* @return 1 if header is valid, zero if invalid
*/
extern int bdk_image_header_is_valid(const bdk_image_header_t *header);
/**
* Verify image at the given address is good
*
* @param image Pointer to the image
*
* @return Zero on success, negative on failure
*/
extern int bdk_image_verify(const void *image);
/**
* Read a image header from a file
*
* @param handle File handel to read from
* @param header Pointer to header structure to fill
*
* @return Zero on success, negative on failure
*/
extern int bdk_image_read_header(FILE *handle, bdk_image_header_t *header);
/**
* Read a image from a file and boot it, replacing the current running BDK image
*
* @param filename File to read the image from
* @param loc Offset into file for image. This is normally zero for normal files. Device
* files, such as /dev/mem, will use this to locate the image.
*
* @return Negative on failure. On success this function never returns.
*/
extern int bdk_image_boot(const char *filename, uint64_t loc);
/** @} */

View File

@ -0,0 +1,81 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Utility functions for controlling the watchdog during boot
*
* @defgroup watchdog Watchdog related functions
* @{
*/
/**
* Setup the watchdog to expire in timeout_ms milliseconds. When the watchdog
* expires, the chip three things happen:
* 1) Expire 1: interrupt that is ignored by the BDK
* 2) Expire 2: DEL3T interrupt, which is disabled and ignored
* 3) Expire 3: Soft reset of the chip
*
* Since we want a soft reset, we actually program the watchdog to expire at
* the timeout / 3.
*
* @param timeout_ms Timeout in milliseconds. If this is zero, the timeout is taken from the
* global configuration option BDK_BRD_CFG_WATCHDOG_TIMEOUT
*/
extern void bdk_watchdog_set(unsigned int timeout_ms);
/**
* Signal the watchdog that we are still running
*/
extern void bdk_watchdog_poke(void);
/**
* Disable the hardware watchdog
*/
extern void bdk_watchdog_disable(void);
/**
* Return true if the watchdog is configured and running
*
* @return Non-zero if watchdog is running
*/
extern int bdk_watchdog_is_running(void);
/** @} */

View File

@ -0,0 +1,59 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Boot services for XMODEM transfers
*
* @addtogroup boot
* @{
*/
/**
* Receive a file through Xmodem and write it to an internal file.
*
* @param dest_file File to write to
* @param offset Offset into the file to write
*
* @return Zero on success, negative on failure
*/
extern int bdk_xmodem_upload(const char *dest_file, uint64_t offset);
/** @} */

View File

@ -0,0 +1,118 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for configuring DRAM.
*
* <hr>$Revision: 49448 $<hr>
*
* @defgroup dram DRAM related functions
* @{
*/
#include "../libdram/libdram.h"
/**
* Lookup a DRAM configuration by name and intialize dram with it
*
* @param node Node to configure
* @param ddr_clock_override
* If non zero, override the DRAM frequency specified in the config with
* this value
*
* @return Amount of DRAM in MB, or negative on failure
*/
extern int bdk_dram_config(int node, int ddr_clock_override);
/**
* Do DRAM configuration tuning
*
* @param node Node to tune
*
* @return Success or Fail
*/
extern int bdk_dram_tune(int node);
/**
* Do DRAM Margin all tests
*
* @param node Node to tune
*
* @return None
*/
extern void bdk_dram_margin(int node);
/**
* Get the amount of DRAM configured for a node. This is read from the LMC
* controller after DRAM is setup.
*
* @param node Node to query
*
* @return Size in megabytes
*/
extern uint64_t bdk_dram_get_size_mbytes(int node);
/**
* Return the string of info about the current node's DRAM configuration.
*
* @param node node to retrieve
*
* @return String or NULL
*/
extern const char* bdk_dram_get_info_string(int node);
/**
* Return the highest address currently used by the BDK. This address will
* be about 4MB above the top of the BDK to make sure small growths between the
* call and its use don't cause corruption. Any call to memory allocation can
* change this value.
*
* @return Size of the BDK in bytes
*/
extern uint64_t bdk_dram_get_top_of_bdk(void);
extern int __bdk_dram_get_num_lmc(bdk_node_t node);
extern int __bdk_dram_is_ddr4(bdk_node_t node, int lmc);
extern int __bdk_dram_is_rdimm(bdk_node_t node, int lmc);
extern uint32_t __bdk_dram_get_row_mask(bdk_node_t node, int lmc);
extern uint32_t __bdk_dram_get_col_mask(bdk_node_t node, int lmc);
extern int __bdk_dram_get_num_bank_bits(bdk_node_t node, int lmc);
/** @} */

View File

@ -0,0 +1,198 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Functions for configuring DRAM.
*
* <hr>$Revision: 49448 $<hr>
*
* @defgroup dram DRAM related functions
* @{
*/
/**
* Flags to pass to DRAM tests to control behavior
*/
typedef enum
{
/* Which nodes to check. If none are specified, default to all */
BDK_DRAM_TEST_NODE0 = 1 << BDK_NODE_0,
BDK_DRAM_TEST_NODE1 = 1 << BDK_NODE_1,
BDK_DRAM_TEST_NODE2 = 1 << BDK_NODE_2,
BDK_DRAM_TEST_NODE3 = 1 << BDK_NODE_3,
BDK_DRAM_TEST_NO_STOP_ERROR = 1 << 8, /**< Don't stop running tests on errors, continue counting all errors */
BDK_DRAM_TEST_NO_PROGRESS = 1 << 9, /**< Don't report progress percentage during run, for batch runs */
BDK_DRAM_TEST_NO_STATS = 1 << 10, /**< Don't report usage status for LMC, or CCPI with USE_CCPI */
BDK_DRAM_TEST_NO_BANNERS = 1 << 11, /**< Don't display banenrs at beginning of test */
BDK_DRAM_TEST_USE_CCPI = 1 << 12, /**< Test using other node across CCPI. Use to verify CCPI. This
automatically enables CCPI usage reporting unless NO_STATS is
also specified */
} bdk_dram_test_flags_t;
/**
* Convert a test enumeration into a string
*
* @param test Test to convert
*
* @return String for display
*/
extern const char* bdk_dram_get_test_name(int test);
/**
* Perform a memory test.
*
* @param test Test type to run
* @param start_address
* Physical address to start at
* @param length Length of memory block
* @param flags Flags to control memory test options. Zero defaults to testing all
* node with statistics and progress output.
*
* @return Number of errors found. Zero is success. Negative means the test
* did not run due to some other failure.
*/
extern int
bdk_dram_test(int test, uint64_t start_address, uint64_t length,
bdk_dram_test_flags_t flags);
/**
* Given a physical DRAM address, extract information about the node, LMC, DIMM,
* rank, bank, row, and column that was accessed.
*
* @param address Physical address to decode
* @param node Node the address was for
* @param lmc LMC controller the address was for
* @param dimm DIMM the address was for
* @param prank Physical RANK on the DIMM
* @param lrank Logical RANK on the DIMM
* @param bank BANK on the DIMM
* @param row Row on the DIMM
* @param col Column on the DIMM
*/
extern void
bdk_dram_address_extract_info(uint64_t address, int *node, int *lmc, int *dimm,
int *prank, int *lrank, int *bank, int *row, int *col);
/**
* Construct a physical address given the node, LMC, DIMM, rank, bank, row, and column.
*
* @param node Node the address was for
* @param lmc LMC controller the address was for
* @param dimm DIMM the address was for
* @param prank Physical RANK on the DIMM
* @param lrank Logical RANK on the DIMM
* @param bank BANK on the DIMM
* @param row Row on the DIMM
* @param col Column on the DIMM
*/
extern uint64_t
bdk_dram_address_construct_info(bdk_node_t node, int lmc, int dimm,
int prank, int lrank, int bank, int row, int col);
/**
* Inject a DRAM error at a specific address in memory. The injection can either
* be a single bit inside the byte, or a double bit error in the ECC byte. Double
* bit errors may corrupt memory, causing software to crash. The corruption is
* written to memory and will continue to exist until the cache line is written
* again. After a call to this function, the BDK should report a ECC error. Double
* bit errors corrupt bits 0-1.
*
* @param address Physical address to corrupt. Any byte alignment is supported
* @param bit Bit to corrupt in the byte (0-7), or -1 to create a double bit fault in the ECC
* byte.
*/
extern void bdk_dram_test_inject_error(uint64_t address, int bit);
/* These variables count the number of ECC errors. They should only be accessed atomically */
/* Keep the counts per memory channel (LMC) for more detail. */
#define BDK_MAX_MEM_CHANS 4
extern int64_t __bdk_dram_ecc_single_bit_errors[BDK_MAX_MEM_CHANS];
extern int64_t __bdk_dram_ecc_double_bit_errors[BDK_MAX_MEM_CHANS];
/* These are internal support functions */
extern void __bdk_dram_flush_to_mem(uint64_t address);
extern void __bdk_dram_flush_to_mem_range(uint64_t area, uint64_t max_address);
extern void __bdk_dram_report_error(uint64_t address, uint64_t data, uint64_t correct, int burst, int fails);
extern void __bdk_dram_report_error2(uint64_t address1, uint64_t data1, uint64_t address2, uint64_t data2, int burst, int fails);
extern int __bdk_dram_retry_failure(int burst, uint64_t address, uint64_t data, uint64_t expected);
extern int __bdk_dram_retry_failure2(int burst, uint64_t address1, uint64_t data1, uint64_t address2, uint64_t data2);
static inline void __bdk_dram_write64(uint64_t address, uint64_t data)
{
/* The DRAM code doesn't use the normal bdk_phys_to_ptr() because of the
NULL check in it. This greatly slows down the memory tests */
volatile uint64_t *ptr = (void*)address;
*ptr = data;
}
static inline uint64_t __bdk_dram_read64(uint64_t address)
{
/* The DRAM code doesn't use the normal bdk_phys_to_ptr() because of the
NULL check in it. This greatly slows down the memory tests */
volatile uint64_t *ptr = (void*)address;
return *ptr;
}
/* This is the function prototype that all test must use. "start_address" is
the first byte to be tested (inclusive), "end_address" is the address right
after the region (exclusive). For example, if start_address equals
end_address, no memory will be tested */
typedef int (*__bdk_dram_test_t)(uint64_t start_address, uint64_t end_address, int bursts);
/* These are the actual tests that get run. Each test is meant to be run with
a small range and repeated on lots of cores and large ranges. The return
value is the number of errors found */
extern int __bdk_dram_test_mem_address_bus(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_checkerboard(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_data_bus(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_leftwalk0(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_leftwalk1(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_random(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_rightwalk0(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_rightwalk1(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_rows(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_self_addr(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_solid(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_mem_xor(uint64_t start_address, uint64_t end_address, int bursts);
extern int __bdk_dram_test_fast_scan(uint64_t area, uint64_t max_address, int bursts);
/** @} */

View File

@ -0,0 +1,54 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* Master include file for dram configuration and testing. Use bdk.h
* instead of including this file directly.
*
* <hr>$Revision: 49448 $<hr>
* @defgroup dram DRAM related functions
* @{
*/
#include "bdk-dram-config.h"
#include "bdk-dram-test.h"
/** @} */

View File

@ -0,0 +1,153 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
#include "libbdk-arch/bdk-csrs-sgp.h"
/**
* @file
*
* Serial GPIO interface (SGPIO)
*
* <hr>$Revision: 49448 $<hr>
*
* @addtogroup hal
* @{
*/
#ifndef _BDK_DRIVER_SGPIO_H_
#define _BDK_DRIVER_SGPIO_H_
typedef enum
{
BDK_SGPIO_LED_ACT,
BDK_SGPIO_LED_LOC,
BDK_SGPIO_LED_ERR,
} bdk_sgpio_led_t;
typedef enum
{
BDK_SGPIO_STATIC_ON = BDK_SGP_TX_ACT_E_STATIC_ON,
BDK_SGPIO_STATIC_OFF = BDK_SGP_TX_ACT_E_STATIC_OFF,
BDK_SGPIO_BLINK = BDK_SGP_TX_ACT_E_A_ON_OFF,
} bdk_sgpio_led_state_t;
/**
* Get the SGPIO controller state
*
* @param node CPU node number
*
* @return 1 == Controller is enabled, 0 == Controller is disabled
*/
int bdk_sgpio_is_enabled(bdk_node_t node);
/**
* Set the mode for a specific LED.
*
* @param node CPU node number
* @param drive Drive number of LED (0-15)
* @param led LED type:
* BDK_SGPIO_LED_ACT
* BDK_SGPIO_LED_ERR
* BDK_SGPIO_LED_LOC
*
* @return
*/
void bdk_sgpio_set_led_state(bdk_node_t node, int drive, int led, int state);
/**
* Get the mode for a specific LED.
*
* @param node CPU node number
* @param drive Drive number of LED (0-15)
* @param led LED type:
* BDK_SGPIO_LED_ACT
* BDK_SGPIO_LED_ERR
* BDK_SGPIO_LED_LOC
*
* @return LED state:
* BDK_SGPIO_STATIC_ON
* BDK_SGPIO_STATIC_OFF
* BDK_SGPIO_BLINK
*/
int bdk_sgpio_get_led_state(bdk_node_t node, int drive, int led);
/**
* Set the controller's SCLOCK frequency
*
* @param node CPU node number
* @param freq Frequency to set
*
* @return Zero on success, negative on failure
*/
int bdk_sgpio_set_sclock(bdk_node_t node, int freq);
/**
* Enable / disable controller
*
* @param node CPU node number
* @param ena zero = disable, non-zero = enable
*
* @return
*/
void bdk_sgpio_enable_controller(bdk_node_t node, int ena);
/**
* Set up SGPIO pin muxing based on environment.
*
* @param node CPU node number
*
* @return Zero on success, negative on failure
*/
int bdk_sgpio_setup_gpio_pins(bdk_node_t node);
/**
* Initialize the SGPIO controller.
* - Set up the SGPIO pin muxing as per configuration environment.
* - Turn all LEDs off
* - Set the blink rate to 1/2 second
* - Enable the controller
*
* @param node CPU node number
*
* @return Zero on success, negative on failure
*/
int bdk_sgpio_initialize(bdk_node_t node);
/** @} */
#endif /* _BDK_DRIVER_SGPIO_H_ */

View File

@ -0,0 +1,71 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* bdk_driver_t represents drivers for devices connected using
* ECAMs. This are discover by scanning the ECAMs and
* instantiating devices for what is found.
*
* @defgroup driver ECAM Attached Drivers
* @addtogroup driver
* @{
*/
#include "bdk-driver-sgpio.h"
/**
* Defines the main entry points for a device driver
*/
typedef struct bdk_driver_s
{
struct bdk_driver_s *next; /* Used by bdk-device to maintian list */
uint32_t id; /* ECAM device ID */
int (*probe)(bdk_device_t *device);
int (*init)(bdk_device_t *device);
} bdk_driver_t;
/**
* Called by the BDK to register all loaded drivers with bdk-device.
*
* @return Zero on success, negative on failure
*/
extern int __bdk_driver_register_all(void) BDK_WEAK;
/** @} */

View File

@ -0,0 +1,155 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
* Functions for accessing memory and CSRs when we are compiling
* natively.
*
* <hr>$Revision: 38306 $<hr>
*/
/**
* Convert a memory pointer (void*) into a hardware compatible
* memory address (uint64_t). Cavium hardware widgets don't
* understand logical addresses.
*
* @param ptr C style memory pointer
* @return Hardware physical address
*/
static inline uint64_t bdk_ptr_to_phys(void *ptr) __attribute__ ((pure, always_inline));
static inline uint64_t bdk_ptr_to_phys(void *ptr)
{
bdk_warn_if(!ptr, "bdk_ptr_to_phys() passed a NULL\n");
return (long)ptr;
}
/**
* Convert a hardware physical address (uint64_t) into a
* memory pointer (void *).
*
* @param physical_address
* Hardware physical address to memory
* @return Pointer to memory
*/
static inline void *bdk_phys_to_ptr(uint64_t physical_address) __attribute__ ((pure, always_inline));
static inline void *bdk_phys_to_ptr(uint64_t physical_address)
{
bdk_warn_if(physical_address==0, "bdk_phys_to_ptr() passed a zero address\n");
return (void*)(long)physical_address;
}
/* We have a full 64bit ABI. Writing to a 64bit address can be done with
a simple volatile pointer */
#define BDK_BUILD_WRITE64(TYPE) \
static inline void bdk_write64_##TYPE(uint64_t addr, TYPE##_t val) __attribute__ ((always_inline)); \
static inline void bdk_write64_##TYPE(uint64_t addr, TYPE##_t val) \
{ \
*(volatile TYPE##_t *)bdk_phys_to_ptr(addr) = val; \
}
/* We have a full 64bit ABI. Writing to a 64bit address can be done with
a simple volatile pointer */
#define BDK_BUILD_READ64(TYPE) \
static inline TYPE##_t bdk_read64_##TYPE(uint64_t addr) __attribute__ ((always_inline)); \
static inline TYPE##_t bdk_read64_##TYPE(uint64_t addr) \
{ \
return *(volatile TYPE##_t *)bdk_phys_to_ptr(addr); \
}
/* The following defines 8 functions for writing to a 64bit address. Each
takes two arguments, the address and the value to write.
bdk_write64_int64 bdk_write64_uint64
bdk_write64_int32 bdk_write64_uint32
bdk_write64_int16 bdk_write64_uint16
bdk_write64_int8 bdk_write64_uint8 */
BDK_BUILD_WRITE64(int64)
BDK_BUILD_WRITE64(int32)
BDK_BUILD_WRITE64(int16)
BDK_BUILD_WRITE64(int8)
BDK_BUILD_WRITE64(uint64)
BDK_BUILD_WRITE64(uint32)
BDK_BUILD_WRITE64(uint16)
BDK_BUILD_WRITE64(uint8)
/* The following defines 8 functions for reading from a 64bit address. Each
takes the address as the only argument
bdk_read64_int64 bdk_read64_uint64
bdk_read64_int32 bdk_read64_uint32
bdk_read64_int16 bdk_read64_uint16
bdk_read64_int8 bdk_read64_uint8 */
BDK_BUILD_READ64(int64)
BDK_BUILD_READ64(int32)
BDK_BUILD_READ64(int16)
BDK_BUILD_READ64(int8)
BDK_BUILD_READ64(uint64)
BDK_BUILD_READ64(uint32)
BDK_BUILD_READ64(uint16)
BDK_BUILD_READ64(uint8)
/**
* Returns the number of bits set in the provided value.
* Simple wrapper for POP instruction.
*
* @param val 32 bit value to count set bits in
*
* @return Number of bits set
*/
static inline uint32_t bdk_pop(uint32_t val)
{
return __builtin_popcount(val);
}
/**
* Returns the number of bits set in the provided value.
* Simple wrapper for DPOP instruction.
*
* @param val 64 bit value to count set bits in
*
* @return Number of bits set
*/
static inline int bdk_dpop(uint64_t val)
{
return __builtin_popcountl(val);
}

View File

@ -0,0 +1,133 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
* Function prototypes for accessing memory and CSRs.
*
* <hr>$Revision: 38306 $<hr>
*
* @addtogroup hal
* @{
*/
#define BDK_FUNCTION static inline
/**
* Convert a memory pointer (void*) into a hardware compatible
* memory address (uint64_t). Cavium hardware widgets don't
* understand logical addresses.
*
* @param ptr C style memory pointer
* @return Hardware physical address
*/
BDK_FUNCTION uint64_t bdk_ptr_to_phys(void *ptr);
/**
* Convert a hardware physical address (uint64_t) into a
* memory pointer (void *).
*
* @param physical_address
* Hardware physical address to memory
* @return Pointer to memory
*/
BDK_FUNCTION void *bdk_phys_to_ptr(uint64_t physical_address);
BDK_FUNCTION void bdk_write64_int64(uint64_t address, int64_t value);
BDK_FUNCTION void bdk_write64_uint64(uint64_t address, uint64_t value);
BDK_FUNCTION void bdk_write64_int32(uint64_t address, int32_t value);
BDK_FUNCTION void bdk_write64_uint32(uint64_t address, uint32_t value);
BDK_FUNCTION void bdk_write64_int16(uint64_t address, int16_t value);
BDK_FUNCTION void bdk_write64_uint16(uint64_t address, uint16_t value);
BDK_FUNCTION void bdk_write64_int8(uint64_t address, int8_t value);
BDK_FUNCTION void bdk_write64_uint8(uint64_t address, uint8_t value);
BDK_FUNCTION int64_t bdk_read64_int64(uint64_t address);
BDK_FUNCTION uint64_t bdk_read64_uint64(uint64_t address);
BDK_FUNCTION int32_t bdk_read64_int32(uint64_t address);
BDK_FUNCTION uint32_t bdk_read64_uint32(uint64_t address);
BDK_FUNCTION int16_t bdk_read64_int16(uint64_t address);
BDK_FUNCTION uint16_t bdk_read64_uint16(uint64_t address);
BDK_FUNCTION int8_t bdk_read64_int8(uint64_t address);
BDK_FUNCTION uint8_t bdk_read64_uint8(uint64_t address);
/**
* Returns the number of bits set in the provided value.
* Simple wrapper for POP instruction.
*
* @param val 32 bit value to count set bits in
*
* @return Number of bits set
*/
BDK_FUNCTION uint32_t bdk_pop(uint32_t val);
/**
* Returns the number of bits set in the provided value.
* Simple wrapper for DPOP instruction.
*
* @param val 64 bit value to count set bits in
*
* @return Number of bits set
*/
BDK_FUNCTION int bdk_dpop(uint64_t val);
/**
* Wait for the specified number of core clock cycles
*
* @param cycles
*/
extern void bdk_wait(uint64_t cycles);
/**
* Wait for the specified number of micro seconds
*
* @param usec micro seconds to wait
*/
extern void bdk_wait_usec(uint64_t usec);
/**
* Perform a soft reset of the chip
*
* @return
*/
extern void bdk_reset_chip(bdk_node_t node);
#undef BDK_FUNCTION
/** @} */

View File

@ -0,0 +1,541 @@
/***********************license start***********************************
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
* reserved.
*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* * Neither the name of Cavium Inc. nor the names of
* its contributors may be used to endorse or promote products
* derived from this software without specific prior written
* permission.
*
* This Software, including technical data, may be subject to U.S. export
* control laws, including the U.S. Export Administration Act and its
* associated regulations, and may be subject to export or import
* regulations in other countries.
*
* TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
* AND WITH ALL FAULTS AND CAVIUM INC. MAKES NO PROMISES, REPRESENTATIONS OR
* WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH RESPECT
* TO THE SOFTWARE, INCLUDING ITS CONDITION, ITS CONFORMITY TO ANY
* REPRESENTATION OR DESCRIPTION, OR THE EXISTENCE OF ANY LATENT OR PATENT
* DEFECTS, AND CAVIUM SPECIFICALLY DISCLAIMS ALL IMPLIED (IF ANY) WARRANTIES
* OF TITLE, MERCHANTABILITY, NONINFRINGEMENT, FITNESS FOR A PARTICULAR
* PURPOSE, LACK OF VIRUSES, ACCURACY OR COMPLETENESS, QUIET ENJOYMENT,
* QUIET POSSESSION OR CORRESPONDENCE TO DESCRIPTION. THE ENTIRE RISK
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
***********************license end**************************************/
/**
* @file
*
* This file provides atomic operations
*
* @addtogroup hal
* @{
*/
/**
* Atomically adds a signed value to a 32 bit (aligned) memory location.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints. (This should NOT be used for reference counting -
* use the standard version instead.)
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*/
static inline void bdk_atomic_add32_nosync(int32_t *ptr, int32_t incr)
{
/* Atomic add with no ordering */
asm volatile ("ldadd %w[i], wzr, [%[b]]"
: [r] "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
}
/**
* Atomically adds a signed value to a 32 bit (aligned) memory location.
*
* Memory access ordering is enforced before/after the atomic operation,
* so no additional 'sync' instructions are required.
*
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*/
static inline void bdk_atomic_add32(int32_t *ptr, int32_t incr)
{
/* Atomic add with acquire and release */
asm volatile ("ldaddal %w[i], wzr, [%[b]]"
: "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
}
/**
* Atomically sets a 32 bit (aligned) memory location to a value
*
* @param ptr address of memory to set
* @param value value to set memory location to.
*/
static inline void bdk_atomic_set32(int32_t *ptr, int32_t value)
{
/* Implies a release */
asm volatile ("stlr %w[v], [%[b]]"
: "+m" (*ptr)
: [v] "r" (value), [b] "r" (ptr)
: "memory");
}
/**
* Returns the current value of a 32 bit (aligned) memory
* location.
*
* @param ptr Address of memory to get
* @return Value of the memory
*/
static inline int32_t bdk_atomic_get32(int32_t *ptr)
{
return *(volatile int32_t *)ptr;
}
/**
* Atomically adds a signed value to a 64 bit (aligned) memory location.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints. (This should NOT be used for reference counting -
* use the standard version instead.)
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*/
static inline void bdk_atomic_add64_nosync(int64_t *ptr, int64_t incr)
{
/* Atomic add with no ordering */
asm volatile ("ldadd %x[i], xzr, [%[b]]"
: [r] "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
}
/**
* Atomically adds a signed value to a 64 bit (aligned) memory location.
*
* Memory access ordering is enforced before/after the atomic operation,
* so no additional 'sync' instructions are required.
*
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*/
static inline void bdk_atomic_add64(int64_t *ptr, int64_t incr)
{
/* Atomic add with acquire and release */
asm volatile ("ldaddal %x[i], xzr, [%[b]]"
: [r] "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
}
/**
* Atomically sets a 64 bit (aligned) memory location to a value
*
* @param ptr address of memory to set
* @param value value to set memory location to.
*/
static inline void bdk_atomic_set64(int64_t *ptr, int64_t value)
{
/* Implies a release */
asm volatile ("stlr %x[v], [%[b]]"
: "+m" (*ptr)
: [v] "r" (value), [b] "r" (ptr)
: "memory");
}
/**
* Returns the current value of a 64 bit (aligned) memory
* location.
*
* @param ptr Address of memory to get
* @return Value of the memory
*/
static inline int64_t bdk_atomic_get64(int64_t *ptr)
{
return *(volatile int64_t *)ptr;
}
/**
* Atomically compares the old value with the value at ptr, and if they match,
* stores new_val to ptr.
* If *ptr and old don't match, function returns failure immediately.
* If *ptr and old match, function spins until *ptr updated to new atomically, or
* until *ptr and old no longer match
*
* Does no memory synchronization.
*
* @return 1 on success (match and store)
* 0 on no match
*/
static inline int bdk_atomic_compare_and_store32_nosync(uint32_t *ptr, uint32_t old_val, uint32_t new_val) __attribute__((always_inline));
static inline int bdk_atomic_compare_and_store32_nosync(uint32_t *ptr, uint32_t old_val, uint32_t new_val)
{
uint32_t val = old_val;
/* CN88XX pass 1.x has errata AP-22500: GlobalSync request during a multi-cycle ATOMIC stalls forever
Don't use compare and swap on these chips */
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
{
asm volatile ("1: ldxr %w[v], [%[b]] \n"
" cmp %w[v], %w[o] \n"
" b.ne 2f \n"
" stxr %w[v], %w[n], [%[b]]\n" /* Returns zero on success */
" cbnz %w[v], 1b \n"
" mov %w[v], %w[o] \n"
"2: \n"
: [mem] "+m" (*ptr), [v] "=&r" (val)
: [b] "r" (ptr), [n] "r" (new_val), [o] "r" (old_val)
: );
}
else
{
asm volatile ("cas %w[o], %w[n], [%[b]]"
: [mem] "+m" (*ptr), [o] "+r" (val)
: [b] "r" (ptr), [n] "r" (new_val)
: );
}
return old_val == val;
}
/**
* Atomically compares the old value with the value at ptr, and if they match,
* stores new_val to ptr.
* If *ptr and old don't match, function returns failure immediately.
* If *ptr and old match, function spins until *ptr updated to new atomically, or
* until *ptr and old no longer match
*
* Does memory synchronization that is required to use this as a locking primitive.
*
* @return 1 on success (match and store)
* 0 on no match
*/
static inline int bdk_atomic_compare_and_store32(uint32_t *ptr, uint32_t old_val, uint32_t new_val) __attribute__((always_inline));
static inline int bdk_atomic_compare_and_store32(uint32_t *ptr, uint32_t old_val, uint32_t new_val)
{
uint32_t val = old_val;
/* CN88XX pass 1.x has errata AP-22500: GlobalSync request during a multi-cycle ATOMIC stalls forever
Don't use compare and swap on these chips */
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
{
asm volatile ("1: ldaxr %w[v], [%[b]] \n"
" cmp %w[v], %w[o] \n"
" b.ne 2f \n"
" stlxr %w[v], %w[n], [%[b]]\n" /* Returns zero on success */
" cbnz %w[v], 1b \n"
" mov %w[v], %w[o] \n"
"2: \n"
: [mem] "+m" (*ptr), [v] "=&r" (val)
: [b] "r" (ptr), [n] "r" (new_val), [o] "r" (old_val)
: );
}
else
{
asm volatile ("casal %w[o], %w[n], [%[b]]"
: [mem] "+m" (*ptr), [o] "+r" (val)
: [b] "r" (ptr), [n] "r" (new_val)
: );
}
return old_val == val;
}
/**
* Atomically compares the old value with the value at ptr, and if they match,
* stores new_val to ptr.
* If *ptr and old don't match, function returns failure immediately.
* If *ptr and old match, function spins until *ptr updated to new atomically, or
* until *ptr and old no longer match
*
* Does no memory synchronization.
*
* @return 1 on success (match and store)
* 0 on no match
*/
static inline int bdk_atomic_compare_and_store64_nosync(uint64_t *ptr, uint64_t old_val, uint64_t new_val) __attribute__((always_inline));
static inline int bdk_atomic_compare_and_store64_nosync(uint64_t *ptr, uint64_t old_val, uint64_t new_val)
{
uint32_t val = old_val;
/* CN88XX pass 1.x has errata AP-22500: GlobalSync request during a multi-cycle ATOMIC stalls forever
Don't use compare and swap on these chips */
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
{
asm volatile ("1: ldxr %x[v], [%[b]] \n"
" cmp %x[v], %x[o] \n"
" b.ne 2f \n"
" stxr %x[v], %x[n], [%[b]]\n" /* Returns zero on success */
" cbnz %x[v], 1b \n"
" mov %x[v], %x[o] \n"
"2: \n"
: [mem] "+m" (*ptr), [v] "=&r" (val)
: [b] "r" (ptr), [n] "r" (new_val), [o] "r" (old_val)
: );
}
else
{
asm volatile ("cas %x[o], %x[n], [%[b]]"
: [mem] "+m" (*ptr), [o] "+r" (val)
: [b] "r" (ptr), [n] "r" (new_val)
: );
}
return old_val == val;
}
/**
* Atomically compares the old value with the value at ptr, and if they match,
* stores new_val to ptr.
* If *ptr and old don't match, function returns failure immediately.
* If *ptr and old match, function spins until *ptr updated to new atomically, or
* until *ptr and old no longer match
*
* Does memory synchronization that is required to use this as a locking primitive.
*
* @return 1 on success (match and store)
* 0 on no match
*/
static inline int bdk_atomic_compare_and_store64(uint64_t *ptr, uint64_t old_val, uint64_t new_val) __attribute__((always_inline));
static inline int bdk_atomic_compare_and_store64(uint64_t *ptr, uint64_t old_val, uint64_t new_val)
{
uint32_t val = old_val;
/* CN88XX pass 1.x has errata AP-22500: GlobalSync request during a multi-cycle ATOMIC stalls forever
Don't use compare and swap on these chips */
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
{
asm volatile ("1: ldaxr %x[v], [%[b]] \n"
" cmp %x[v], %x[o] \n"
" b.ne 2f \n"
" stlxr %x[v], %x[n], [%[b]]\n" /* Returns zero on success */
" cbnz %x[v], 1b \n"
" mov %x[v], %x[o] \n"
"2: \n"
: [mem] "+m" (*ptr), [v] "=&r" (val)
: [b] "r" (ptr), [n] "r" (new_val), [o] "r" (old_val)
: );
}
else
{
asm volatile ("casal %x[o], %x[n], [%[b]]"
: [mem] "+m" (*ptr), [o] "+r" (val)
: [b] "r" (ptr), [n] "r" (new_val)
: );
}
return old_val == val;
}
/**
* Atomically adds a signed value to a 64 bit (aligned) memory location,
* and returns previous value.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints. (This should NOT be used for reference counting -
* use the standard version instead.)
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*
* @return Value of memory location before increment
*/
static inline int64_t bdk_atomic_fetch_and_add64_nosync(int64_t *ptr, int64_t incr)
{
int64_t result;
/* Atomic add with no ordering */
asm volatile ("ldadd %x[i], %x[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
return result;
}
/**
* Atomically adds a signed value to a 64 bit (aligned) memory location,
* and returns previous value.
*
* Memory access ordering is enforced before/after the atomic operation,
* so no additional 'sync' instructions are required.
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*
* @return Value of memory location before increment
*/
static inline int64_t bdk_atomic_fetch_and_add64(int64_t *ptr, int64_t incr)
{
int64_t result;
/* Atomic add with acquire/release */
asm volatile ("ldaddal %x[i], %x[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
return result;
}
/**
* Atomically adds a signed value to a 32 bit (aligned) memory location,
* and returns previous value.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints. (This should NOT be used for reference counting -
* use the standard version instead.)
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*
* @return Value of memory location before increment
*/
static inline int32_t bdk_atomic_fetch_and_add32_nosync(int32_t *ptr, int32_t incr)
{
int32_t result;
/* Atomic add with no ordering */
asm volatile ("ldadd %w[i], %w[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
return result;
}
/**
* Atomically adds a signed value to a 32 bit (aligned) memory location,
* and returns previous value.
*
* Memory access ordering is enforced before/after the atomic operation,
* so no additional 'sync' instructions are required.
*
* @param ptr address in memory to add incr to
* @param incr amount to increment memory location by (signed)
*
* @return Value of memory location before increment
*/
static inline int32_t bdk_atomic_fetch_and_add32(int32_t *ptr, int32_t incr)
{
int32_t result;
/* Atomic add with acquire/release */
asm volatile ("ldaddal %w[i], %w[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (incr), [b] "r" (ptr)
: "memory");
return result;
}
/**
* Atomically set bits in a 64 bit (aligned) memory location,
* and returns previous value.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints.
*
* @param ptr address in memory
* @param mask mask of bits to set
*
* @return Value of memory location before setting bits
*/
static inline uint64_t bdk_atomic_fetch_and_bset64_nosync(uint64_t *ptr, uint64_t mask)
{
uint64_t result;
/* Atomic or with no ordering */
asm volatile ("ldset %x[i], %x[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (mask), [b] "r" (ptr)
: "memory");
return result;
}
/**
* Atomically set bits in a 32 bit (aligned) memory location,
* and returns previous value.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints.
*
* @param ptr address in memory
* @param mask mask of bits to set
*
* @return Value of memory location before setting bits
*/
static inline uint32_t bdk_atomic_fetch_and_bset32_nosync(uint32_t *ptr, uint32_t mask)
{
uint32_t result;
/* Atomic or with no ordering */
asm volatile ("ldset %w[i], %w[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (mask), [b] "r" (ptr)
: "memory");
return result;
}
/**
* Atomically clear bits in a 64 bit (aligned) memory location,
* and returns previous value.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints.
*
* @param ptr address in memory
* @param mask mask of bits to clear
*
* @return Value of memory location before clearing bits
*/
static inline uint64_t bdk_atomic_fetch_and_bclr64_nosync(uint64_t *ptr, uint64_t mask)
{
uint64_t result;
/* Atomic and with no ordering */
asm volatile ("ldclr %x[i], %x[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (mask), [b] "r" (ptr)
: "memory");
return result;
}
/**
* Atomically clear bits in a 32 bit (aligned) memory location,
* and returns previous value.
*
* This version does not perform 'sync' operations to enforce memory
* operations. This should only be used when there are no memory operation
* ordering constraints.
*
* @param ptr address in memory
* @param mask mask of bits to clear
*
* @return Value of memory location before clearing bits
*/
static inline uint32_t bdk_atomic_fetch_and_bclr32_nosync(uint32_t *ptr, uint32_t mask)
{
uint32_t result;
/* Atomic and with no ordering */
asm volatile ("ldclr %w[i], %w[r], [%[b]]"
: [r] "=r" (result), "+m" (*ptr)
: [i] "r" (mask), [b] "r" (ptr)
: "memory");
return result;
}
/** @} */

Some files were not shown because too many files have changed in this diff Show More