soc/cavium: Integrate BDK files into coreboot
* Make it compile. * Fix whitespace errors. * Fix printf formats. * Add missing headers includes * Guard headers with ifdefs Compile DRAM init code in romstage. Compile QLM, PCIe, RNG, PHY, GPIO, MDIO init code in ramstage. Change-Id: I0a93219a14bfb6ebe41103a825d5032b11e7f2c6 Signed-off-by: David Hendricks <dhendricks@fb.com> Reviewed-on: https://review.coreboot.org/25089 Reviewed-by: Philipp Deppenwiese <zaolin.daisuki@gmail.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
committed by
Philipp Deppenwiese
parent
d837e66007
commit
7d48ac5c7d
@ -2,3 +2,4 @@ subdirs-y += amd
|
||||
subdirs-y += google
|
||||
subdirs-y += intel
|
||||
subdirs-y += siemens
|
||||
subdirs-y += cavium
|
||||
|
70
src/vendorcode/cavium/Kconfig
Normal file
70
src/vendorcode/cavium/Kconfig
Normal file
@ -0,0 +1,70 @@
|
||||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright 2017-present Facebook, Inc.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
config CAVIUM_BDK
|
||||
def_bool n
|
||||
select HAVE_DEBUG_RAM_SETUP
|
||||
help
|
||||
Build Cavium's BDK in romstage.
|
||||
|
||||
if CAVIUM_BDK
|
||||
|
||||
menu "BDK"
|
||||
|
||||
config CAVIUM_BDK_VERBOSE_INIT
|
||||
bool "Enable verbose init"
|
||||
depends on CAVIUM_BDK
|
||||
help
|
||||
Build Cavium's BDK with verbose init code.
|
||||
|
||||
config CAVIUM_BDK_VERBOSE_DRAM
|
||||
bool "Enable verbose dram init"
|
||||
default y if DEBUG_RAM_SETUP
|
||||
depends on CAVIUM_BDK
|
||||
help
|
||||
Build Cavium's BDK with verbose dram init code.
|
||||
|
||||
config CAVIUM_BDK_VERBOSE_DRAM_TEST
|
||||
bool "Enable verbose raminit tests"
|
||||
depends on CAVIUM_BDK
|
||||
help
|
||||
Build Cavium's BDK with verbose DRAM testing code.
|
||||
|
||||
config CAVIUM_BDK_VERBOSE_QLM
|
||||
bool "Enable verbose qlm init"
|
||||
depends on CAVIUM_BDK
|
||||
help
|
||||
Build Cavium's BDK with verbose QLM code.
|
||||
|
||||
config CAVIUM_BDK_VERBOSE_PCIE_CONFIG
|
||||
bool "Enable verbose pcie config"
|
||||
depends on CAVIUM_BDK
|
||||
help
|
||||
Build Cavium's BDK with verbose PCIe config code.
|
||||
|
||||
config CAVIUM_BDK_VERBOSE_PCIE
|
||||
bool "Enable verbose pcie init"
|
||||
depends on CAVIUM_BDK
|
||||
help
|
||||
Build Cavium's BDK with verbose PCIe code.
|
||||
|
||||
config CAVIUM_BDK_VERBOSE_PHY
|
||||
bool "Enable verbose phy init"
|
||||
depends on CAVIUM_BDK
|
||||
help
|
||||
Build Cavium's BDK with verbose PHY code.
|
||||
endmenu
|
||||
|
||||
endif
|
92
src/vendorcode/cavium/Makefile.inc
Normal file
92
src/vendorcode/cavium/Makefile.inc
Normal file
@ -0,0 +1,92 @@
|
||||
##
|
||||
## This file is part of the coreboot project.
|
||||
##
|
||||
## Copyright 2017-present Facebook, Inc.
|
||||
##
|
||||
## This program is free software; you can redistribute it and/or modify
|
||||
## it under the terms of the GNU General Public License as published by
|
||||
## the Free Software Foundation; version 2 of the License.
|
||||
##
|
||||
## This program is distributed in the hope that it will be useful,
|
||||
## but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
## GNU General Public License for more details.
|
||||
##
|
||||
|
||||
ifeq ($(CONFIG_CAVIUM_BDK),y)
|
||||
|
||||
romstage-y += bdk/libbdk-arch/bdk-csr.c
|
||||
romstage-y += bdk/libbdk-arch/bdk-model.c
|
||||
romstage-y += bdk/libbdk-arch/bdk-numa.c
|
||||
romstage-y += bdk/libbdk-boot/bdk-boot-status.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-address.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-config.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-size.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-test.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-test-addrbus.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-test-databus.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-test-fastscan.c
|
||||
romstage-y += bdk/libbdk-dram/bdk-dram-test-patfil.c
|
||||
romstage-y += bdk/libbdk-driver/bdk-driver-rnm.c
|
||||
romstage-y += bdk/libbdk-hal/bdk-clock.c
|
||||
romstage-y += bdk/libbdk-hal/bdk-config.c
|
||||
romstage-y += bdk/libbdk-hal/bdk-gpio.c
|
||||
romstage-y += bdk/libbdk-hal/bdk-l2c.c
|
||||
romstage-y += bdk/libbdk-os/bdk-init.c
|
||||
romstage-y += bdk/libbdk-trust/bdk-trust.c
|
||||
romstage-y += bdk/libdram/dram-env.c
|
||||
romstage-y += bdk/libdram/dram-init-ddr3.c
|
||||
romstage-y += bdk/libdram/dram-l2c.c
|
||||
romstage-y += bdk/libdram/dram-spd.c
|
||||
romstage-y += bdk/libdram/dram-tune-ddr3.c
|
||||
romstage-y += bdk/libdram/lib_octeon_shared.c
|
||||
romstage-y += bdk/libdram/libdram.c
|
||||
romstage-y += bdk/libdram/libdram-config-load.c
|
||||
romstage-y += bdk/libbdk-hal/bdk-access.c
|
||||
|
||||
# FIXME: Get rid of lame_string.c
|
||||
romstage-y += bdk/lame_string.c
|
||||
|
||||
CPPFLAGS_common += -Isrc/vendorcode/cavium/include/bdk
|
||||
|
||||
# For bdk_dram_get_size_mbytes()
|
||||
ramstage-y += bdk/libbdk-dram/bdk-dram-size.c
|
||||
|
||||
ramstage-y += bdk/libbdk-hal/bdk-config.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-qlm.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-pcie-cn8xxx.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-pcie.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-gpio.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-ecam-io.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-usb.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-access.c
|
||||
|
||||
ramstage-y += bdk/libbdk-arch/bdk-csr.c
|
||||
ramstage-y += bdk/libbdk-arch/bdk-model.c
|
||||
ramstage-y += bdk/libbdk-arch/bdk-numa.c
|
||||
ramstage-y += bdk/libbdk-hal/qlm/bdk-qlm-common.c
|
||||
ramstage-y += bdk/libbdk-hal/qlm/bdk-qlm-errata-cn8xxx.c
|
||||
ramstage-y += bdk/libbdk-hal/qlm/bdk-qlm-common-sata.c
|
||||
ramstage-y += bdk/libbdk-hal/qlm/bdk-qlm-margin-cn8xxx.c
|
||||
|
||||
ramstage-y += bdk/libbdk-boot/bdk-boot-qlm.c
|
||||
ramstage-y += bdk/libbdk-boot/bdk-boot-pcie.c
|
||||
ramstage-y += bdk/libbdk-boot/bdk-boot-usb.c
|
||||
ramstage-y += bdk/libbdk-boot/bdk-boot-gpio.c
|
||||
ramstage-y += bdk/libbdk-boot/bdk-boot.c
|
||||
|
||||
ramstage-y += bdk/libbdk-hal/if/bdk-if-phy.c
|
||||
ramstage-y += bdk/libbdk-hal/if/bdk-if-phy-marvell.c
|
||||
ramstage-y += bdk/libbdk-hal/if/bdk-if-phy-vetesse-8514.c
|
||||
ramstage-y += bdk/libbdk-hal/if/bdk-if-phy-vetesse.c
|
||||
ramstage-y += bdk/libbdk-driver/bdk-driver-mdio.c
|
||||
ramstage-y += bdk/libbdk-driver/bdk-driver-rnm.c
|
||||
ramstage-y += bdk/libbdk-hal/device/bdk-device.c
|
||||
ramstage-y += bdk/libbdk-hal/bdk-ecam.c
|
||||
|
||||
# FIXME: Get rid of lame_string.c
|
||||
ramstage-y += bdk/lame_string.c
|
||||
|
||||
ramstage-$(CONFIG_SOC_CAVIUM_CN81XX) += bdk/libbdk-hal/qlm/bdk-qlm-cn81xx.c
|
||||
|
||||
endif
|
149
src/vendorcode/cavium/bdk/lame_string.c
Normal file
149
src/vendorcode/cavium/bdk/lame_string.c
Normal file
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* string.c: hastily cobbled-together string functions
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include <lame_string.h>
|
||||
|
||||
static int char_to_val(char c)
|
||||
{
|
||||
if (c >= '0' && c <= '9') /* digits */
|
||||
return c - '0';
|
||||
if (c >= 'A' && c <= 'F') /* uppercase */
|
||||
return c - 'A' + 10;
|
||||
if (c >= 'a' && c <= 'f') /* lowercase */
|
||||
return c - 'a' + 10;
|
||||
return -1;
|
||||
}
|
||||
|
||||
unsigned long long int strtoull(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
unsigned long long int val;
|
||||
size_t i, error = 0;
|
||||
|
||||
/* TODO: enforce lameness of this API for now... */
|
||||
assert((base == 0) || (base == 16) || base == 10);
|
||||
|
||||
if (!nptr)
|
||||
return 0;
|
||||
|
||||
/* Trim whitespace */
|
||||
for (i = 0; i < strlen(nptr); i++)
|
||||
if (nptr[i] != ' ')
|
||||
break;
|
||||
|
||||
if (base == 0) {
|
||||
/* Autodetect base */
|
||||
if (strlen(&nptr[i]) >= 2 && ((nptr[i] == '0') &&
|
||||
((nptr[i + 1] == 'x') || (nptr[i + 1] == 'X')))) {
|
||||
base = 16;
|
||||
i += 2; /* start loop after prefix */
|
||||
} else
|
||||
base = 10;
|
||||
}
|
||||
|
||||
val = 0;
|
||||
for (; i < strlen(nptr); i++) {
|
||||
if (base == 16) {
|
||||
if (!isxdigit(nptr[i])) {
|
||||
if (*endptr)
|
||||
*endptr = (char *)&nptr[i];
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!isdigit(nptr[i])) {
|
||||
if (*endptr)
|
||||
*endptr = (char *)&nptr[i];
|
||||
error = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
val *= base;
|
||||
val += char_to_val(nptr[i]);
|
||||
}
|
||||
|
||||
if (error) {
|
||||
printk(BIOS_ERR, "Failed to convert string '%s', base %d to "
|
||||
"int\n", nptr, base);
|
||||
return 0;
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
unsigned long long int u = strtol(nptr, endptr, base);
|
||||
/* FIXME: check for overflow (u > max) */
|
||||
return (unsigned long int)u;
|
||||
}
|
||||
|
||||
long int strtol(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
unsigned long long int u;
|
||||
int is_neg = 0;
|
||||
const char *p;
|
||||
long int ret;
|
||||
|
||||
if (nptr[0] == '-') {
|
||||
is_neg = 1;
|
||||
p = &nptr[1];
|
||||
} else {
|
||||
p = &nptr[0];
|
||||
}
|
||||
u = strtoull(p, NULL, base);
|
||||
/* FIXME: check for overflow (u > max) */
|
||||
if (is_neg)
|
||||
ret = 0 - (long int)u;
|
||||
else
|
||||
ret = (long int)u;
|
||||
return ret;
|
||||
}
|
||||
|
||||
long long int strtoll(const char *nptr, char **endptr, int base)
|
||||
{
|
||||
unsigned long long int u;
|
||||
int is_neg = 0;
|
||||
const char *p;
|
||||
long long int ret;
|
||||
|
||||
if (nptr[0] == '-') {
|
||||
is_neg = 1;
|
||||
p = &nptr[1];
|
||||
} else {
|
||||
p = &nptr[0];
|
||||
}
|
||||
u = strtoull(p, NULL, base);
|
||||
/* FIXME: check for overflow (sign-bit set) */
|
||||
if (is_neg)
|
||||
ret = 0 - (long long int)u;
|
||||
else
|
||||
ret = (long long int)u;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* FIXME: replace sscanf() usage for bdk_config_get_int. returns number of
|
||||
* strings converted, so 1 if successful and 0 if not */
|
||||
int str_to_int(const char *str, int64_t *val)
|
||||
{
|
||||
*val = strtol(str, NULL, 10);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* FIXME: replace sscanf() usage for bdk_config_get_int. returns number of
|
||||
* strings converted, so 1 if successful and 0 if not */
|
||||
int str_to_hex(const char *str, int64_t *val)
|
||||
{
|
||||
*val = strtol(str, NULL, 16);
|
||||
return 1;
|
||||
}
|
@ -37,9 +37,10 @@
|
||||
* 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"
|
||||
#include "libbdk-arch/bdk-csrs-rst.h"
|
||||
#include "libbdk-hal/bdk-pcie.h"
|
||||
|
||||
#ifndef BDK_BUILD_HOST
|
||||
|
||||
@ -87,9 +88,6 @@ uint64_t __bdk_csr_read_slow(bdk_node_t node, bdk_csr_type_t type, int busnum, i
|
||||
|
||||
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)
|
||||
{
|
||||
@ -201,9 +199,6 @@ void __bdk_csr_write_slow(bdk_node_t node, bdk_csr_type_t type, int busnum, int
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "libbdk-arch/bdk-csrs-mio_fus.h"
|
||||
#include "libbdk-arch/bdk-csrs-fus.h"
|
||||
#include "libbdk-arch/bdk-csrs-fusf.h"
|
||||
#include <libbdk-hal/bdk-clock.h>
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
|
||||
/*
|
||||
Format of a SKU
|
||||
@ -100,562 +102,6 @@ typedef struct
|
||||
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
|
||||
@ -694,234 +140,3 @@ int cavium_is_altpkg(uint32_t arg_model)
|
||||
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];
|
||||
}
|
||||
|
@ -37,11 +37,18 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
#include <stdio.h>
|
||||
#include <libbdk-hal/bdk-atomic.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;
|
||||
/*
|
||||
* FIXME(dhendrix): can't include bdk-spinlock.h, compile complains:
|
||||
* {standard input}:40: Error: selected processor does not support `ldadda x3,x5,[x2]'
|
||||
*/
|
||||
|
||||
//int __bdk_numa_master_node = -1; /* Which node is the master */
|
||||
int __bdk_numa_master_node = 0; /* FIXME(dhendrix): assume 0 */
|
||||
//static int __bdk_numa_exists_mask = 0; /* Bitmask of nodes that exist */
|
||||
static int __bdk_numa_exists_mask = 1; /* FIXME(dhendrix): assume 0x01 */
|
||||
//static bdk_spinlock_t __bdk_numa_lock;
|
||||
|
||||
/**
|
||||
* Get a bitmask of the nodes that exist
|
||||
@ -60,11 +67,8 @@ uint64_t bdk_numa_get_exists_mask(void)
|
||||
*/
|
||||
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);
|
||||
/* FIXME(dhendrix): stub. */
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -76,7 +80,8 @@ void bdk_numa_set_exists(bdk_node_t node)
|
||||
*/
|
||||
int bdk_numa_exists(bdk_node_t node)
|
||||
{
|
||||
return __bdk_numa_exists_mask & (1 << node);
|
||||
/* FIXME(dhendrix): stub */
|
||||
return node == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,6 +91,7 @@ int bdk_numa_exists(bdk_node_t node)
|
||||
*/
|
||||
extern int bdk_numa_is_only_one()
|
||||
{
|
||||
return __bdk_numa_exists_mask == 1;
|
||||
/* FIXME(dhendrix): stub */
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -36,47 +36,35 @@
|
||||
* 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"
|
||||
#include "libbdk-hal/bdk-config.h"
|
||||
#include "libbdk-hal/bdk-gpio.h"
|
||||
#include "libbdk-boot/bdk-boot-gpio.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Functions for information about the run platform.
|
||||
*
|
||||
* <hr>$Revision: 49448 $<hr>
|
||||
* @addtogroup hal
|
||||
* @{
|
||||
* Configure GPIO on all nodes as part of booting
|
||||
*/
|
||||
|
||||
/**
|
||||
* This typedef defines the possible platforms for the BDK. The
|
||||
* numbers represent fuse setting in Fuses[197:195].
|
||||
*/
|
||||
typedef enum
|
||||
void bdk_boot_gpio(void)
|
||||
{
|
||||
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);
|
||||
const int NUM_GPIO = bdk_gpio_get_num();
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (bdk_numa_exists(n))
|
||||
{
|
||||
for (int gpio = 0; gpio < NUM_GPIO; gpio++)
|
||||
{
|
||||
int pin_sel = bdk_config_get_int(BDK_CONFIG_GPIO_PIN_SELECT, gpio, n);
|
||||
if (pin_sel >= 0)
|
||||
{
|
||||
BDK_TRACE(INIT, "Connecting N%d.GPIO%d to pin select 0x%x\n",
|
||||
n, gpio, pin_sel);
|
||||
bdk_gpio_select_pin(n, gpio, pin_sel);
|
||||
}
|
||||
int invert = bdk_config_get_int(BDK_CONFIG_GPIO_POLARITY, gpio, n);
|
||||
if (invert)
|
||||
BDK_CSR_MODIFY(c, n, BDK_GPIO_BIT_CFGX(gpio), c.s.pin_xor = 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call to initialize the platform state
|
||||
*/
|
||||
extern void __bdk_platform_init();
|
||||
|
||||
/** @} */
|
@ -36,19 +36,33 @@
|
||||
* 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 <string.h>
|
||||
#include "libbdk-hal/if/bdk-if.h"
|
||||
#include "libbdk-hal/bdk-qlm.h"
|
||||
#include "libbdk-arch/bdk-csrs-pem.h"
|
||||
#include "libbdk-boot/bdk-boot-pcie.h"
|
||||
#include "libbdk-hal/bdk-pcie.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Boot services for BGX
|
||||
*
|
||||
* @addtogroup boot
|
||||
* @{
|
||||
* Configure PCIe on all nodes as part of booting
|
||||
*/
|
||||
|
||||
/**
|
||||
* Configure BGX on all nodes as part of booting
|
||||
*/
|
||||
extern void bdk_boot_bgx(void);
|
||||
|
||||
/** @} */
|
||||
void bdk_boot_pcie(void)
|
||||
{
|
||||
/* Initialize PCIe and bring up the link */
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (bdk_numa_exists(n))
|
||||
{
|
||||
for (int p = 0; p < bdk_pcie_get_num_ports(n); p++)
|
||||
{
|
||||
/* Only init PCIe that are attached to QLMs */
|
||||
if (bdk_qlm_get_qlm_num(n, BDK_IF_PCIE, p, 0) != -1)
|
||||
{
|
||||
BDK_TRACE(INIT, "Initializing PCIe%d on Node %d\n", p, n);
|
||||
bdk_pcie_rc_initialize(n, p);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
515
src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-qlm.c
Normal file
515
src/vendorcode/cavium/bdk/libbdk-boot/bdk-boot-qlm.c
Normal file
@ -0,0 +1,515 @@
|
||||
/***********************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 <string.h>
|
||||
#include "libbdk-hal/if/bdk-if.h"
|
||||
#include "libbdk-hal/bdk-qlm.h"
|
||||
#include "libbdk-hal/bdk-utils.h"
|
||||
#include "libbdk-boot/bdk-boot-qlm.h"
|
||||
#include "libbdk-hal/bdk-config.h"
|
||||
#include "libbdk-hal/bdk-twsi.h"
|
||||
|
||||
static void boot_init_qlm_clk(void)
|
||||
{
|
||||
/* Setup reference clocks */
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (!bdk_numa_exists(n))
|
||||
continue;
|
||||
|
||||
int num_qlms = bdk_qlm_get_num(n);
|
||||
|
||||
BDK_TRACE(INIT, "Initializing QLM clocks on Node %d\n", n);
|
||||
for (int qlm = 0; qlm < num_qlms; qlm++)
|
||||
{
|
||||
bdk_qlm_clock_t clk = bdk_config_get_int(BDK_CONFIG_QLM_CLK, n, qlm);
|
||||
if (BDK_QLM_CLK_LAST == clk) /* no entry */
|
||||
continue;
|
||||
|
||||
if (clk > BDK_QLM_CLK_LAST)
|
||||
{
|
||||
bdk_warn("Invalid clock source %d for QLM%d on node %d. Not configuring.\n",
|
||||
clk, qlm, n);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (0 != bdk_qlm_set_clock(n, qlm, clk))
|
||||
{
|
||||
bdk_error("Error setting clock source %d for QLM%d on node %d. Ignoring.\n",
|
||||
clk, qlm, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a node and DLM/QLM, return the possible BGX lanes connected to it. This
|
||||
* is needed to determine which PHY address to use for SFP/SFP+ detection.
|
||||
*
|
||||
* @param node Node the DLM/QLM is on
|
||||
* @param qlm DLM/QLM to find the BGX for
|
||||
* @param bgx Output: The BGX instance number, or -1 on failure
|
||||
* @param bgx_lane_mask
|
||||
* Output: Which BGX indexes may be connected to this port
|
||||
*/
|
||||
static void find_bgx(int node, int qlm, int *bgx, int *bgx_lane_mask)
|
||||
{
|
||||
*bgx = -1;
|
||||
*bgx_lane_mask = 0;
|
||||
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
|
||||
{
|
||||
switch (qlm)
|
||||
{
|
||||
case 0: /* BGX0 -> QLM0 */
|
||||
case 1: /* BGX1 -> QLM1 */
|
||||
*bgx = qlm;
|
||||
*bgx_lane_mask = 0xf;
|
||||
return;
|
||||
default:
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: No BGX for this QLM, illegal config\n", node, qlm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
|
||||
{
|
||||
switch (qlm)
|
||||
{
|
||||
case 2: /* BGX0 -> QLM2 */
|
||||
*bgx = 0;
|
||||
*bgx_lane_mask = 0xf;
|
||||
return;
|
||||
case 3: /* BGX1 -> QLM3 */
|
||||
*bgx = 1;
|
||||
*bgx_lane_mask = 0xf;
|
||||
return;
|
||||
case 4: /* BGX3 -> DLM4 */
|
||||
*bgx = 3;
|
||||
*bgx_lane_mask = 0x3;
|
||||
return;
|
||||
case 5: /* BGX2 -> DLM5 */
|
||||
*bgx = 2;
|
||||
*bgx_lane_mask = 0x3;
|
||||
return;
|
||||
case 6: /* BGX2 -> DLM6 */
|
||||
*bgx = 2;
|
||||
*bgx_lane_mask = 0xc;
|
||||
return;
|
||||
default:
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: No BGX for this QLM, illegal config\n", node, qlm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
|
||||
{
|
||||
switch (qlm)
|
||||
{
|
||||
case 0: /* BGX0 -> DLM0 */
|
||||
*bgx = 0;
|
||||
*bgx_lane_mask = 0x3;
|
||||
return;
|
||||
case 1: /* BGX0 -> DLM1 */
|
||||
*bgx = 0;
|
||||
*bgx_lane_mask = 0xc;
|
||||
return;
|
||||
case 2: /* BGX1 -> DLM2 */
|
||||
*bgx = 1;
|
||||
*bgx_lane_mask = 0x3;
|
||||
return;
|
||||
case 3: /* BGX1 -> DLM3 */
|
||||
*bgx = 1;
|
||||
*bgx_lane_mask = 0xc;
|
||||
return;
|
||||
default:
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: No BGX for this QLM, illegal config\n", node, qlm);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
bdk_error("N%d.QLM%d: Unsupported chip, update %s()\n", node, qlm, __FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the DLM/QLM mode based on a SFP/SFP+ connected to the port. Note that
|
||||
* the CN8XXX parts can't control mode per lane, so all SFP/SFP+ on a DLM/QLM must
|
||||
* be the same mode. This code is sloppy about finding the BGX PHY for the DLM/QLM
|
||||
* because not all lanes may be used.
|
||||
*
|
||||
* @param node Node to determine mode for
|
||||
* @param qlm DLM/QLM the SFP/SFP+ is connected to
|
||||
*
|
||||
* @return QLM mode or -1 on failure
|
||||
*/
|
||||
static int init_sfp(int node, int qlm)
|
||||
{
|
||||
int mode = BDK_QLM_MODE_XFI_4X1; /* Default to XFI if detection fails */
|
||||
int bgx = -1;
|
||||
int bgx_lane_mask = 0;
|
||||
|
||||
find_bgx(node, qlm, &bgx, &bgx_lane_mask);
|
||||
if (bgx == -1)
|
||||
return mode;
|
||||
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: Checking for SFP/SFP+\n", node, qlm);
|
||||
|
||||
for (int index = 0; index < 4; index++)
|
||||
{
|
||||
/* Skip BGX indexes that aren't applicable */
|
||||
if ((bgx_lane_mask & (1 << index)) == 0)
|
||||
continue;
|
||||
/* Lookup the PHY address for this BGX port */
|
||||
int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, node, bgx, index);
|
||||
/* SFP/SFP+ are connected with TWSI, so only check ports with
|
||||
PHYs connected with TWSI */
|
||||
if ((phy_addr & BDK_IF_PHY_TYPE_MASK) != BDK_IF_PHY_TWSI)
|
||||
continue;
|
||||
|
||||
/* For TWSI:
|
||||
Bits[31:24]: Node ID, 0xff for device node
|
||||
Bits[23:16]: TWSI internal address width in bytes (0-2)
|
||||
Bits[15:12]: 2=TWSI
|
||||
Bits[11:8]: TWSI bus number
|
||||
Bits[7:0]: TWSI address */
|
||||
int n = (phy_addr >> 24) & 0xff;
|
||||
int twsi_ia_width = (phy_addr >> 16) & 0xff;
|
||||
int twsi_bus = (phy_addr >> 8) & 0xf;
|
||||
int twsi_addr = 0x50; /* From SFP spec */
|
||||
if (n == 0xff)
|
||||
n = node;
|
||||
|
||||
/* Read bytes 0-3 from eeprom. Note read is big endian, so byte 0 is
|
||||
bits 31:24 in the result */
|
||||
int64_t eeprom_00_03 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 0, 4, twsi_ia_width);
|
||||
if (eeprom_00_03 == -1)
|
||||
{
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index);
|
||||
continue;
|
||||
}
|
||||
int64_t eeprom_04_07 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 4, 4, twsi_ia_width);
|
||||
if (eeprom_04_07 == -1)
|
||||
{
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index);
|
||||
continue;
|
||||
}
|
||||
int64_t eeprom_08_11 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 8, 4, twsi_ia_width);
|
||||
if (eeprom_08_11 == -1)
|
||||
{
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index);
|
||||
continue;
|
||||
}
|
||||
int64_t eeprom_12 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 12, 1, twsi_ia_width);
|
||||
if (eeprom_12 == -1)
|
||||
{
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ eeprom access failed\n", node, qlm, bgx, index);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Byte 0: Identifier, should be 0x03 for SFP/SFP+
|
||||
0x03 = SFP of SFP+
|
||||
0x0c = QSFP
|
||||
0x0d = QSFP+ */
|
||||
if (bdk_extract(eeprom_00_03, 24, 8) != 0x03)
|
||||
{
|
||||
/* Byte 0 of eeprom should be 0x03 for SFP/SFP+ */
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ not detected\n", node, qlm, bgx, index);
|
||||
continue;
|
||||
}
|
||||
/* Byte 1: Extended Identifier, should be 0x04 */
|
||||
if (bdk_extract(eeprom_00_03, 16, 8) != 0x04)
|
||||
{
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d.%d SFP/SFP+ incorrect extended identifier\n", node, qlm, bgx, index);
|
||||
continue;
|
||||
}
|
||||
/* Byte 2: Connector
|
||||
Value Description of connector
|
||||
00h Unknown or unspecified
|
||||
01h SC
|
||||
02h Fibre Channel Style 1 copper connector
|
||||
03h Fibre Channel Style 2 copper connector
|
||||
04h BNC/TNC
|
||||
05h Fibre Channel coaxial headers
|
||||
06h FiberJack
|
||||
07h LC
|
||||
08h MT-RJ
|
||||
09h MU
|
||||
0Ah SG
|
||||
0Bh Optical pigtail
|
||||
0Ch MPO Parallel Optic
|
||||
0Dh-1Fh Reserved, Unallocated
|
||||
20h HSSDC II
|
||||
21h Copper Pigtail
|
||||
22h RJ45
|
||||
23h-7Fh Reserved, Unallocated
|
||||
80-FFh Vendor specific */
|
||||
bool isOptical = false;
|
||||
switch (bdk_extract(eeprom_00_03, 8, 8))
|
||||
{
|
||||
case 0x01: /* SC - Short channel */
|
||||
case 0x07: /* LC - Long channel */
|
||||
case 0x0B: /* Optical pigtail */
|
||||
isOptical = true;
|
||||
break;
|
||||
}
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: SFP/SFP+ eeprom Bytes[0:3] 0x%0llx, Bytes[4:7] 0x%08llx, [8:11] 0x%08llx [12] 0x%02llx\n",
|
||||
node, qlm, eeprom_00_03, eeprom_04_07, eeprom_08_11, eeprom_12);
|
||||
/* Byte 3: Transceiver info first byte. See comments below */
|
||||
/* Byte 3, bits 4-7 correspond to 10G Ethernet speeds */
|
||||
/* 10G Ethernet Compliance Codes
|
||||
Byte 3[7] 10G BASE-ER (Fiber - Extended Reach)
|
||||
Byte 3[6] 10G BASE-LRM (Fiber - Long reach multi-mode)
|
||||
Byte 3[5] 10G BASE-LR (Fiber - Long reach)
|
||||
Byte 3[4] 10G BASE-SR (Fiber - Short reach) */
|
||||
bool isXFI = bdk_extract(eeprom_00_03, 0, 8) != 0;
|
||||
/* Byte 6, bits 0-7 correspond to Gigabit Ethernet speeds */
|
||||
/* Gigabit Ethernet Compliance Codes
|
||||
Byte 6[7] BASE-PX
|
||||
Byte 6[6] BASE-BX10
|
||||
Byte 6[5] 100BASE-FX
|
||||
Byte 6[4] 100BASE-LX/LX10 (Fiber)
|
||||
Byte 6[3] 1000BASE-T (Twisted pair)
|
||||
Byte 6[2] 1000BASE-CX (Shielded balanced copper)
|
||||
Byte 6[1] 1000BASE-LX (Fiber)
|
||||
Byte 6[0] 1000BASE-SX (Fiber) */
|
||||
bool isSGMII = bdk_extract(eeprom_04_07, 8, 8) != 0;
|
||||
/* Byte 12 is the nominal bit rate, units of 100 MBits/sec. */
|
||||
int bit_rate = eeprom_12 * 100;
|
||||
if (bit_rate)
|
||||
{
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: Nominal bit rate %d MBits/sec\n",
|
||||
node, qlm, bit_rate);
|
||||
isXFI = (bit_rate >= 10000);
|
||||
isSGMII = (bit_rate <= 2500);
|
||||
}
|
||||
|
||||
if (isXFI)
|
||||
{
|
||||
mode = BDK_QLM_MODE_XFI_4X1;
|
||||
if (isOptical)
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: SFP+ selecting XFI Optical\n", node, qlm);
|
||||
else
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: SFP+ selecting XFI Copper\n", node, qlm);
|
||||
}
|
||||
else if (isSGMII)
|
||||
{
|
||||
mode = BDK_QLM_MODE_SGMII_4X1;
|
||||
if (isOptical)
|
||||
{
|
||||
/* This should be 1000BASE-X, gigabit over fiber */
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: SFP selecting SGMII Optical\n", node, qlm);
|
||||
}
|
||||
else /* This should be SGMII, gigabit over copper */
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: SFP selecting SGMII Copper\n", node, qlm);
|
||||
}
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the DLM/QLM mode based on a QSFP/QSFP+ connected to
|
||||
* the port. This code is sloppy about finding the BGX PHY for
|
||||
* the DLM/QLM because not all lanes may be used.
|
||||
*
|
||||
* @param node Node to determine mode for
|
||||
* @param qlm DLM/QLM the SFP/SFP+ is connected to
|
||||
*
|
||||
* @return QLM mode or -1 on failure
|
||||
*/
|
||||
static int init_qsfp(int node, int qlm)
|
||||
{
|
||||
int mode = BDK_QLM_MODE_XLAUI_1X4; /* Default to XLAUI if detection fails */
|
||||
int bgx = -1;
|
||||
int bgx_lane_mask = 0;
|
||||
|
||||
find_bgx(node, qlm, &bgx, &bgx_lane_mask);
|
||||
if (bgx == -1)
|
||||
return mode;
|
||||
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: Checking for QSFP/QSFP+\n", node, qlm);
|
||||
int index = 0;
|
||||
|
||||
/* Lookup the PHY address for this BGX port */
|
||||
int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, node, bgx, index);
|
||||
/* QSFP/QSFP+ are connected with TWSI, so only check ports with
|
||||
PHYs connected with TWSI */
|
||||
if ((phy_addr & BDK_IF_PHY_TYPE_MASK) != BDK_IF_PHY_TWSI)
|
||||
return mode;
|
||||
|
||||
/* For TWSI:
|
||||
Bits[31:24]: Node ID, 0xff for device node
|
||||
Bits[23:16]: TWSI internal address width in bytes (0-2)
|
||||
Bits[15:12]: 2=TWSI
|
||||
Bits[11:8]: TWSI bus number
|
||||
Bits[7:0]: TWSI address */
|
||||
int n = (phy_addr >> 24) & 0xff;
|
||||
int twsi_ia_width = (phy_addr >> 16) & 0xff;
|
||||
int twsi_bus = (phy_addr >> 8) & 0xf;
|
||||
int twsi_addr = 0x50; /* From SFP spec */
|
||||
if (n == 0xff)
|
||||
n = node;
|
||||
|
||||
/* Byte 0: Identifier, should be 0x03 for SFP/SFP+
|
||||
0x03 = SFP of SFP+
|
||||
0x0c = QSFP
|
||||
0x0d = QSFP+ */
|
||||
int64_t eeprom_00 = bdk_twsix_read_ia(n, twsi_bus, twsi_addr, 0, 1, twsi_ia_width);
|
||||
switch (eeprom_00)
|
||||
{
|
||||
case 0x03:
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d QSFP/QSFP+ contains a SFP+\n", node, qlm, bgx);
|
||||
mode = init_sfp(node, qlm);
|
||||
break;
|
||||
case 0x0c:
|
||||
case 0x0d:
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d Found a QSFP/QSFP+, assuming 40G\n", node, qlm, bgx);
|
||||
mode = BDK_QLM_MODE_XLAUI_1X4;
|
||||
break;
|
||||
default:
|
||||
BDK_TRACE(INIT, "N%d.QLM%d: BGX%d QSFP/QSFP+ not detected\n", node, qlm, bgx);
|
||||
break;
|
||||
}
|
||||
return mode;
|
||||
}
|
||||
|
||||
static void boot_init_qlm_mode(void)
|
||||
{
|
||||
/* Check if QLM autoconfig is requested */
|
||||
int qlm_auto = bdk_config_get_int(BDK_CONFIG_QLM_AUTO_CONFIG);
|
||||
if (qlm_auto)
|
||||
{
|
||||
/* Auto configuration of QLMs
|
||||
*/
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (bdk_numa_exists(n))
|
||||
{
|
||||
BDK_TRACE(INIT, "Initializing QLMs on Node %d\n", n);
|
||||
bdk_qlm_auto_config(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* Check if QLM autoconfig from DIP switch settings is requested
|
||||
*/
|
||||
else if (bdk_config_get_int(BDK_CONFIG_QLM_DIP_AUTO_CONFIG))
|
||||
{
|
||||
BDK_TRACE(INIT, "Reading DIP Switch settings for QLM Auto configuration\n");
|
||||
|
||||
/* Auto configuration of QLMs
|
||||
*/
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (bdk_numa_exists(n))
|
||||
{
|
||||
BDK_TRACE(INIT, "Initializing QLMs on Node %d\n", n);
|
||||
if (bdk_qlm_dip_auto_config(n))
|
||||
bdk_error("QLM Auto configuration failed!\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialize the QLMs based on configuration file settings
|
||||
*/
|
||||
|
||||
boot_init_qlm_clk();
|
||||
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (!bdk_numa_exists(n))
|
||||
continue;
|
||||
|
||||
int num_qlms = bdk_qlm_get_num(n);
|
||||
|
||||
BDK_TRACE(INIT, "Initializing QLMs on Node %d\n", n);
|
||||
for (int qlm = 0; qlm < num_qlms; qlm++)
|
||||
{
|
||||
const char *cfg_val;
|
||||
|
||||
cfg_val = bdk_config_get_str(BDK_CONFIG_QLM_MODE, n, qlm);
|
||||
if (!cfg_val)
|
||||
continue;
|
||||
|
||||
int mode;
|
||||
int freq;
|
||||
/* Check for special token telling us to configure the QLM
|
||||
based on the SFP/SFP+/QSFP/QSFP+ plugged into the system. */
|
||||
if ((strcmp(cfg_val, "SFP+") == 0) || (strcmp(cfg_val, "QSFP+") == 0))
|
||||
{
|
||||
if (strcmp(cfg_val, "SFP+") == 0)
|
||||
mode = init_sfp(n, qlm);
|
||||
else
|
||||
mode = init_qsfp(n, qlm);
|
||||
|
||||
if (mode == BDK_QLM_MODE_SGMII_4X1)
|
||||
freq = 1250;
|
||||
else
|
||||
freq = 10321;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode = bdk_qlm_cfg_string_to_mode(cfg_val);
|
||||
freq = bdk_config_get_int(BDK_CONFIG_QLM_FREQ, n, qlm);
|
||||
}
|
||||
if (-1 == mode)
|
||||
{
|
||||
bdk_error("Invalid QLM mode string '%s' for QLM%d on node %d. "
|
||||
"Not configuring.\n", cfg_val, qlm, n);
|
||||
continue;
|
||||
}
|
||||
if (-1 == freq)
|
||||
{
|
||||
bdk_error("No frequency setting for QLM%d on node %d. "
|
||||
"Not configuring.\n", qlm, n);
|
||||
continue;
|
||||
}
|
||||
|
||||
bdk_qlm_set_mode(n, qlm, mode, freq, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure QLM on all nodes as part of booting
|
||||
*/
|
||||
void bdk_boot_qlm(void)
|
||||
{
|
||||
boot_init_qlm_mode();
|
||||
}
|
@ -38,6 +38,8 @@
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
#include "libbdk-arch/bdk-csrs-mio_tws.h"
|
||||
#include "libbdk-boot/bdk-boot-status.h"
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
|
||||
/**
|
||||
* Report boot status to the BMC or whomever might care. This function
|
||||
|
@ -37,23 +37,26 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
#include "libbdk-arch/bdk-csrs-ocla.h"
|
||||
#include <libbdk-hal/bdk-usb.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-boot/bdk-boot-usb.h>
|
||||
|
||||
bdk_platform_t __bdk_platform;
|
||||
|
||||
void __bdk_platform_init()
|
||||
/**
|
||||
* Configure USB on all nodes as part of booting
|
||||
*/
|
||||
void bdk_boot_usb(void)
|
||||
{
|
||||
BDK_CSR_INIT(c, bdk_numa_master(), BDK_OCLAX_CONST(0));
|
||||
if (c.u == 0)
|
||||
/* Initialize USB, ready for standard XHCI driver */
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
__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;
|
||||
if (bdk_numa_exists(n))
|
||||
{
|
||||
for (int p = 0; p < 2; p++)
|
||||
{
|
||||
int usb_refclock = bdk_config_get_int(BDK_CONFIG_USB_REFCLK_SRC, n,p);
|
||||
BDK_TRACE(INIT, "Initializing USB%d on Node %d clock type %d\n", p, n, usb_refclock);
|
||||
bdk_usb_initialize(n, p, usb_refclock);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,51 +36,63 @@
|
||||
* 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 <string.h>
|
||||
#include "libbdk-hal/if/bdk-if.h"
|
||||
#include "libbdk-arch/bdk-csrs-pem.h"
|
||||
#include "libbdk-boot/bdk-boot-pcie.h"
|
||||
#include "libbdk-boot/bdk-boot-qlm.h"
|
||||
#include "libbdk-boot/bdk-boot-usb.h"
|
||||
#include "libbdk-hal/bdk-pcie.h"
|
||||
#include "libbdk-hal/bdk-mdio.h"
|
||||
#include "libbdk-hal/bdk-qlm.h"
|
||||
#include "libbdk-hal/bdk-ecam.h"
|
||||
#include "libbdk-hal/bdk-rng.h"
|
||||
#include "libbdk-boot/bdk-boot-gpio.h"
|
||||
#include "libbdk-arch/bdk-csrs-iobn.h"
|
||||
#include "libbdk-arch/bdk-csrs-dap.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
* Functions for displaying and retrieving infomration about the
|
||||
* boot environment
|
||||
*
|
||||
* @addtogroup boot
|
||||
* @{
|
||||
* Configure hardware
|
||||
*/
|
||||
void bdk_boot(void)
|
||||
{
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (bdk_numa_exists(n))
|
||||
{
|
||||
/* Allow CAP access from cores so we can read system registers through
|
||||
memory mapped addresses. See bdk_sysreg_read() */
|
||||
BDK_CSR_MODIFY(c, n, BDK_DAP_IMP_DAR, c.s.caben = 1);
|
||||
|
||||
/* Enable IOBN */
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX) || CAVIUM_IS_MODEL(CAVIUM_CN81XX))
|
||||
{
|
||||
BDK_CSR_MODIFY(c, n, BDK_IOBNX_NCB0_HP(0),
|
||||
c.s.hp = 1);
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
|
||||
BDK_CSR_MODIFY(c, n, BDK_IOBNX_NCB0_HP(1),
|
||||
c.s.hp = 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
bdk_ecam_scan_all(n);
|
||||
bdk_mdio_init(n);
|
||||
bdk_qlm_init(n);
|
||||
bdk_rng_init(n);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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);
|
||||
bdk_boot_gpio();
|
||||
bdk_boot_usb();
|
||||
bdk_boot_qlm();
|
||||
bdk_boot_pcie();
|
||||
|
||||
/**
|
||||
* 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);
|
||||
|
||||
/** @} */
|
||||
/* Initialize PHYs */
|
||||
for (bdk_node_t n = BDK_NODE_0; n < BDK_NUMA_MAX_NODES; n++)
|
||||
{
|
||||
if (bdk_numa_exists(n))
|
||||
{
|
||||
bdk_if_phy_setup(n);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/***********************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;
|
||||
}
|
||||
|
@ -72,9 +72,9 @@ bdk_dram_address_extract_info(uint64_t address, int *node, int *lmc, int *dimm,
|
||||
|
||||
/* LMC number is probably aliased */
|
||||
if (l2c_ctl.s.disidxalias)
|
||||
*lmc = EXTRACT(address, 7, xbits);
|
||||
*lmc = EXTRACT(address, 7, xbits);
|
||||
else
|
||||
*lmc = EXTRACT(address, 7, xbits) ^ EXTRACT(address, bitno, xbits) ^ EXTRACT(address, 12, xbits);
|
||||
*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));
|
||||
@ -176,7 +176,7 @@ bdk_dram_address_construct_info(bdk_node_t node, int lmc, int dimm,
|
||||
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);
|
||||
new_lmc ^= EXTRACT(address, bitno, xbits) ^ EXTRACT(address, 12, xbits);
|
||||
INSERT(address, new_lmc, 7, xbits);
|
||||
|
||||
return address;
|
||||
|
@ -37,7 +37,9 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-hal/bdk-l2c.h>
|
||||
|
||||
BDK_REQUIRE_DEFINE(DRAM_CONFIG);
|
||||
|
||||
@ -72,22 +74,6 @@ int bdk_dram_config(int node, int ddr_clock_override)
|
||||
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
|
||||
*
|
||||
@ -144,7 +130,9 @@ uint64_t bdk_dram_get_top_of_bdk(void)
|
||||
* 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));
|
||||
/* FIXME(dhendrix): we only care about node 0 */
|
||||
// uint64_t top_of_bdk = (bdk_ptr_to_phys(sbrk(0)) & bdk_build_mask(40));
|
||||
uint64_t top_of_bdk = 0;
|
||||
uint64_t l2_size = bdk_l2c_get_cache_size_bytes(bdk_numa_master());
|
||||
if (top_of_bdk <= l2_size)
|
||||
{
|
||||
|
@ -37,6 +37,8 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
|
||||
|
||||
/**
|
||||
* Return the number of LMC controllers in use
|
||||
@ -92,7 +94,7 @@ static int __bdk_dram_is_lmc_in_dreset(bdk_node_t node, int lmc)
|
||||
*
|
||||
* @param node Node to probe
|
||||
*
|
||||
*/
|
||||
*/
|
||||
uint32_t __bdk_dram_get_row_mask(bdk_node_t node, int lmc)
|
||||
{
|
||||
// PROTECT!!!
|
||||
@ -108,7 +110,7 @@ uint32_t __bdk_dram_get_row_mask(bdk_node_t node, int lmc)
|
||||
*
|
||||
* @param node Node to probe
|
||||
*
|
||||
*/
|
||||
*/
|
||||
uint32_t __bdk_dram_get_col_mask(bdk_node_t node, int lmc)
|
||||
{
|
||||
// PROTECT!!!
|
||||
@ -124,7 +126,7 @@ uint32_t __bdk_dram_get_col_mask(bdk_node_t node, int lmc)
|
||||
*
|
||||
* @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)
|
||||
@ -181,9 +183,6 @@ int __bdk_dram_is_rdimm(bdk_node_t node, int lmc)
|
||||
*/
|
||||
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;
|
||||
@ -192,21 +191,13 @@ uint64_t bdk_dram_get_size_mbytes(int node)
|
||||
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;
|
||||
}
|
||||
// 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;
|
||||
}
|
||||
|
@ -37,6 +37,7 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include "bdk.h"
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
|
||||
/* Used for all memory reads/writes related to the test */
|
||||
#define READ64(address) __bdk_dram_read64(address)
|
||||
|
@ -38,6 +38,8 @@
|
||||
***********************license end**************************************/
|
||||
#include "bdk.h"
|
||||
|
||||
#include <libbdk-hal/bdk-utils.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)
|
||||
@ -97,7 +99,7 @@ static int read_data_bus_burst(uint64_t address, int bursts)
|
||||
*/
|
||||
static int write_data_bus_burst(uint64_t address, int bursts)
|
||||
{
|
||||
BDK_TRACE(DRAM_TEST, "[0x%016lx:0x%016lx] Writing incrementing digits\n",
|
||||
BDK_TRACE(DRAM_TEST, "[0x%016llx:0x%016llx] Writing incrementing digits\n",
|
||||
address, address + 127);
|
||||
/* Loop over the burst so people using a scope have time to capture
|
||||
traces */
|
||||
@ -164,7 +166,7 @@ static int read_data_bus_walk(uint64_t address, int burst, uint64_t pattern)
|
||||
*/
|
||||
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",
|
||||
BDK_TRACE(DRAM_TEST, "[0x%016llx:0x%016llx] Writing walking pattern 0x%016llx\n",
|
||||
address, address + 127, pattern);
|
||||
|
||||
uint64_t a = address;
|
||||
|
@ -37,6 +37,7 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include "bdk.h"
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
|
||||
/* Used for all memory reads/writes related to the test */
|
||||
#define READ64(address) __bdk_dram_read64(address)
|
||||
|
@ -37,6 +37,8 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include "bdk.h"
|
||||
#include <libbdk-hal/bdk-rng.h>
|
||||
#include <libbdk-hal/bdk-utils.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
|
||||
@ -286,7 +288,7 @@ static int test_mem_march_c(uint64_t area, uint64_t max_address, uint64_t patter
|
||||
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);
|
||||
BDK_TRACE(DRAM_TEST, " [0x%016llx:0x%016llx] Phase1, address incrementing, pattern 0x%016llx\n", area, max_address-1, pattern);
|
||||
for (uint64_t address = area; address < max_address; address += 8)
|
||||
WRITE64(address, pattern);
|
||||
|
||||
@ -294,7 +296,7 @@ static int test_mem_march_c(uint64_t area, uint64_t max_address, uint64_t patter
|
||||
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);
|
||||
BDK_TRACE(DRAM_TEST, " [0x%016llx:0x%016llx] Phase2, address incrementing, pattern 0x%016llx\n", area, max_address-1, ~pattern);
|
||||
for (uint64_t address = area; address < max_address; address += 8)
|
||||
{
|
||||
uint64_t data = READ64(address);
|
||||
@ -307,7 +309,7 @@ static int test_mem_march_c(uint64_t area, uint64_t max_address, uint64_t patter
|
||||
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);
|
||||
BDK_TRACE(DRAM_TEST, " [0x%016llx:0x%016llx] Phase3, address incrementing, pattern 0x%016llx\n", area, max_address-1, pattern);
|
||||
for (uint64_t address = area; address < max_address; address += 8)
|
||||
{
|
||||
uint64_t data = READ64(address);
|
||||
@ -320,7 +322,7 @@ static int test_mem_march_c(uint64_t area, uint64_t max_address, uint64_t patter
|
||||
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);
|
||||
BDK_TRACE(DRAM_TEST, " [0x%016llx:0x%016llx] Phase4, address decrementing, pattern 0x%016llx\n", area, max_address-1, ~pattern);
|
||||
uint64_t end = max_address - sizeof(uint64_t);
|
||||
for (uint64_t address = end; address >= area; address -= 8)
|
||||
{
|
||||
@ -334,7 +336,7 @@ static int test_mem_march_c(uint64_t area, uint64_t max_address, uint64_t patter
|
||||
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);
|
||||
BDK_TRACE(DRAM_TEST, " [0x%016llx:0x%016llx] Phase5, address decrementing, pattern 0x%016llx\n", area, max_address-1, pattern);
|
||||
for (uint64_t address = end; address >= area; address -= 8)
|
||||
{
|
||||
uint64_t data = READ64(address);
|
||||
@ -347,7 +349,7 @@ static int test_mem_march_c(uint64_t area, uint64_t max_address, uint64_t patter
|
||||
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);
|
||||
BDK_TRACE(DRAM_TEST, " [0x%016llx:0x%016llx] Phase6, address incrementing\n", area, max_address-1);
|
||||
for (uint64_t address = area; address < max_address; address += 8)
|
||||
{
|
||||
uint64_t data = READ64(address);
|
||||
@ -660,7 +662,7 @@ int __bdk_dram_test_mem_xor(uint64_t area, uint64_t max_address, int bursts)
|
||||
WRITE64(address1 , p);
|
||||
WRITE64(address1 + offset, p);
|
||||
address1 += 8;
|
||||
p += pincr;
|
||||
p += pincr;
|
||||
}
|
||||
__bdk_dram_flush_to_mem_range(area, max_address);
|
||||
BDK_DCACHE_INVALIDATE;
|
||||
@ -674,7 +676,7 @@ int __bdk_dram_test_mem_xor(uint64_t area, uint64_t max_address, int bursts)
|
||||
address1 = area;
|
||||
|
||||
this_pattern = bdk_rng_get_random64();
|
||||
pattern2 ^= this_pattern;
|
||||
pattern2 ^= this_pattern;
|
||||
|
||||
while (address1 < area2)
|
||||
{
|
||||
@ -693,13 +695,13 @@ int __bdk_dram_test_mem_xor(uint64_t area, uint64_t max_address, int bursts)
|
||||
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
|
||||
* 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.
|
||||
* will be out of sync, giving spurious errors.
|
||||
*/
|
||||
address1 = area;
|
||||
ppred = pbase;
|
||||
ppred = pbase;
|
||||
|
||||
while (address1 < area2)
|
||||
{
|
||||
@ -712,21 +714,21 @@ int __bdk_dram_test_mem_xor(uint64_t area, uint64_t max_address, int bursts)
|
||||
d1 = READ64(address1 );
|
||||
d2 = READ64(address1 + offset);
|
||||
|
||||
p = ppred ^ pattern2;
|
||||
p = ppred ^ pattern2;
|
||||
|
||||
if (bdk_unlikely(d1 != p)) {
|
||||
failures += __bdk_dram_retry_failure(burst, address1, 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);
|
||||
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;
|
||||
ppred += pincr;
|
||||
|
||||
} /* while (address1 < area2) */
|
||||
} /* for (int burst = 0; burst < bursts; burst++) */
|
||||
@ -761,7 +763,7 @@ int __bdk_dram_test_mem_rows(uint64_t area, uint64_t max_address, int bursts)
|
||||
WRITE64(address1 , pattern2);
|
||||
WRITE64(address1 + offset, pattern2);
|
||||
address1 += 8;
|
||||
pattern2 = ~pattern2; // flip for next slots
|
||||
pattern2 = ~pattern2; // flip for next slots
|
||||
}
|
||||
|
||||
__bdk_dram_flush_to_mem_range(area, max_address);
|
||||
@ -771,7 +773,7 @@ int __bdk_dram_test_mem_rows(uint64_t area, uint64_t max_address, int bursts)
|
||||
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.
|
||||
* alternate passes, the data flips from 0 to 1 and vice versa.
|
||||
*/
|
||||
address1 = area;
|
||||
|
||||
@ -796,8 +798,8 @@ int __bdk_dram_test_mem_rows(uint64_t area, uint64_t max_address, int bursts)
|
||||
* 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
|
||||
pattern1 = ~pattern1; // flip the starting pattern to match above loop
|
||||
pattern2 = pattern1; // slots have been flipped by the above loop
|
||||
|
||||
while (address1 < area2)
|
||||
{
|
||||
@ -810,18 +812,18 @@ int __bdk_dram_test_mem_rows(uint64_t area, uint64_t max_address, int bursts)
|
||||
d2 = READ64(address1 + offset);
|
||||
|
||||
if (bdk_unlikely(d1 != pattern2)) {
|
||||
failures += __bdk_dram_retry_failure(burst, address1, 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);
|
||||
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
|
||||
pattern2 = ~pattern2; // flip for next pair of slots
|
||||
}
|
||||
}
|
||||
return failures;
|
||||
|
@ -40,6 +40,14 @@
|
||||
#include "libbdk-arch/bdk-csrs-gti.h"
|
||||
#include "libbdk-arch/bdk-csrs-ocx.h"
|
||||
|
||||
#include <bdk-minimal.h> /* for printf --> printk */
|
||||
#include <libbdk-dram/bdk-dram-test.h>
|
||||
#include <libbdk-hal/bdk-atomic.h>
|
||||
#include <libbdk-hal/bdk-clock.h>
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
#include <libbdk-os/bdk-init.h>
|
||||
#include <libbdk-os/bdk-thread.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);
|
||||
@ -170,7 +178,7 @@ static void dram_test_thread(int arg, void *arg1)
|
||||
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_TRACE(DRAM_TEST, " Node %d, core %d, Testing [0x%011llx:0x%011llx]\n",
|
||||
bdk_numa_local(), bdk_get_core_num() & 127, start_address, end_address - 1);
|
||||
test_info->test_func(start_address, end_address, bursts);
|
||||
|
||||
@ -197,7 +205,7 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
{
|
||||
/* 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);
|
||||
BDK_TRACE(DRAM_TEST, "DRAM available per node: %llu MB\n", max_address);
|
||||
max_address <<= 20;
|
||||
|
||||
/* Make sure we have enough */
|
||||
@ -218,13 +226,13 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
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);
|
||||
BDK_TRACE(DRAM_TEST, "DRAM max address: 0x%011llx\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);
|
||||
bdk_error("Start address is larger than the amount of memory: 0x%011llx versus 0x%011llx\n",
|
||||
start_address, max_address);
|
||||
return -1;
|
||||
}
|
||||
if (length == (uint64_t)-1)
|
||||
@ -260,8 +268,8 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
}
|
||||
}
|
||||
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);
|
||||
printf("Starting Test \"%s\" for [0x%011llx:0x%011llx] 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];
|
||||
@ -332,15 +340,15 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
/* Poke the watchdog */
|
||||
BDK_CSR_WRITE(bdk_numa_local(), BDK_GTI_CWD_POKEX(0), 0);
|
||||
|
||||
/* disable progress output when batch mode is ON */
|
||||
/* 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",
|
||||
printf(" %3d.%d%% complete, testing [0x%011llx:0x%011llx]\r",
|
||||
percent_x10 / 10, percent_x10 % 10, work_address, work_address + size - 1);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
||||
|
||||
work_address += size;
|
||||
|
||||
@ -357,17 +365,8 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
{
|
||||
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++;
|
||||
}
|
||||
dram_test_thread(per_node, (void *)test_info);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -384,7 +383,6 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
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) {
|
||||
@ -430,7 +428,7 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
if (!(flags & BDK_DRAM_TEST_NO_PROGRESS)) {
|
||||
|
||||
/* Report progress percentage as complete */
|
||||
printf(" %3d.%d%% complete, testing [0x%011lx:0x%011lx]\n",
|
||||
printf(" %3d.%d%% complete, testing [0x%011llx:0x%011llx]\n",
|
||||
100, 0, start_address, end_address - 1);
|
||||
fflush(stdout);
|
||||
}
|
||||
@ -450,7 +448,7 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
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",
|
||||
printf(" Node %d, LMC%d: ops %llu, cycles %llu, used %llu.%llu%%\n",
|
||||
node, i, ops, dclk, percent_x10 / 10, percent_x10 % 10);
|
||||
}
|
||||
}
|
||||
@ -471,7 +469,7 @@ static int __bdk_dram_run_test(const dram_test_info_t *test_info, uint64_t start
|
||||
if (total == 0)
|
||||
continue;
|
||||
uint64_t percent_x10 = busy * 1000 / total;
|
||||
printf(" Node %d, CCPI%d: busy %lu, total %lu, used %lu.%lu%%\n",
|
||||
printf(" Node %d, CCPI%d: busy %llu, total %llu, used %llu.%llu%%\n",
|
||||
node, link, busy, total, percent_x10 / 10, percent_x10 % 10);
|
||||
}
|
||||
}
|
||||
@ -543,11 +541,13 @@ int bdk_dram_test(int test, uint64_t start_address, uint64_t length, bdk_dram_te
|
||||
|
||||
/* 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);
|
||||
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 */
|
||||
/* FIXME(dhendrix): we only care about core0 on node0 for now */
|
||||
#if 0
|
||||
for (bdk_node_t node = BDK_NODE_0; node < BDK_NUMA_MAX_NODES; node++)
|
||||
{
|
||||
if (flags & (1<<node))
|
||||
@ -557,17 +557,11 @@ int bdk_dram_test(int test, uint64_t start_address, uint64_t length, bdk_dram_te
|
||||
bdk_init_cores(use_node, 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 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;
|
||||
@ -582,14 +576,14 @@ int bdk_dram_test(int test, uint64_t start_address, uint64_t length, bdk_dram_te
|
||||
/* 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]);
|
||||
printf("Test \"%s\": ECC errors, %lld/%lld/%lld/%lld corrected, %lld/%lld/%lld/%lld 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);
|
||||
printf("Test \"%s\": FAIL: %lld single, %lld double, %d compare errors\n",
|
||||
name, ecc_single, ecc_double, errors);
|
||||
}
|
||||
else
|
||||
BDK_TRACE(DRAM_TEST, "Test \"%s\": PASS\n", name);
|
||||
@ -610,7 +604,7 @@ static void __bdk_dram_report_address_decode(uint64_t address, char *buffer, int
|
||||
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);
|
||||
address, node, lmc, dimm, prank, lrank, bank, row, col);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -632,22 +626,22 @@ static void __bdk_dram_report_address_decode_new(uint64_t address, uint64_t orig
|
||||
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
|
||||
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
|
||||
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);
|
||||
node, lmc, byte, print_bits, dimm, prank, lrank, bank, row, col, address);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -671,15 +665,15 @@ void __bdk_dram_report_error(uint64_t address, uint64_t data, uint64_t correct,
|
||||
|
||||
if (errors < MAX_ERRORS_TO_REPORT)
|
||||
{
|
||||
if (fails < 0) {
|
||||
snprintf(failbuf, sizeof(failbuf), " ");
|
||||
} else {
|
||||
if (fails < 0) {
|
||||
snprintf(failbuf, sizeof(failbuf), " ");
|
||||
} else {
|
||||
int percent_x10 = fails * 1000 / RETRY_LIMIT;
|
||||
snprintf(failbuf, sizeof(failbuf), ", retries failed %3d.%d%%",
|
||||
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_dram_report_address_decode_new(address, xor, buffer, sizeof(buffer));
|
||||
bdk_error("%s%s\n", buffer, failbuf);
|
||||
|
||||
if (errors == MAX_ERRORS_TO_REPORT-1)
|
||||
@ -702,26 +696,26 @@ void __bdk_dram_report_error(uint64_t address, uint64_t data, uint64_t correct,
|
||||
* @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)
|
||||
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];
|
||||
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));
|
||||
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);
|
||||
bdk_error("compare: data1: 0x%016llx, xor: 0x%016llx%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");
|
||||
@ -741,23 +735,23 @@ int __bdk_dram_retry_failure(int burst, uint64_t address, uint64_t data, uint64_
|
||||
// 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++) {
|
||||
/* 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;
|
||||
__bdk_dram_flush_to_mem(address);
|
||||
BDK_DCACHE_INVALIDATE;
|
||||
|
||||
uint64_t new = __bdk_dram_read64(address);
|
||||
uint64_t new = __bdk_dram_read64(address);
|
||||
|
||||
if (new != expected) {
|
||||
refail++;
|
||||
}
|
||||
}
|
||||
if (new != expected) {
|
||||
refail++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
refail = -1;
|
||||
refail = -1;
|
||||
|
||||
// this will increment the errors always, but maybe not print...
|
||||
__bdk_dram_report_error(address, data, expected, burst, refail);
|
||||
@ -779,20 +773,20 @@ int __bdk_dram_retry_failure2(int burst, uint64_t address1, uint64_t data1, uint
|
||||
// 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;
|
||||
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);
|
||||
uint64_t d1 = __bdk_dram_read64(address1);
|
||||
uint64_t d2 = __bdk_dram_read64(address2);
|
||||
|
||||
if (d1 != d2) {
|
||||
refail++;
|
||||
}
|
||||
}
|
||||
if (d1 != d2) {
|
||||
refail++;
|
||||
}
|
||||
}
|
||||
} else
|
||||
refail = -1;
|
||||
refail = -1;
|
||||
|
||||
// this will increment the errors always, but maybe not print...
|
||||
__bdk_dram_report_error2(address1, data1, address2, data2, burst, refail);
|
||||
@ -854,7 +848,7 @@ void bdk_dram_test_inject_error(uint64_t address, int bit)
|
||||
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",
|
||||
printf("Loading the injected error address 0x%llx, 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);
|
||||
}
|
||||
|
351
src/vendorcode/cavium/bdk/libbdk-driver/bdk-driver-mdio.c
Normal file
351
src/vendorcode/cavium/bdk/libbdk-driver/bdk-driver-mdio.c
Normal file
@ -0,0 +1,351 @@
|
||||
/***********************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-smi.h>
|
||||
#include <libbdk-hal/device/bdk-device.h>
|
||||
#include <libbdk-hal/bdk-mdio.h>
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
if BDK_REQUIRE() needs it */
|
||||
BDK_REQUIRE_DEFINE(MDIO);
|
||||
|
||||
/* To maintain backwards compatibility for the old MDIO API we need
|
||||
to lookup the MDIO device on the ECAM bus by ID. This defines
|
||||
the ID */
|
||||
#define MDIO_DEVID ((BDK_PCC_PROD_E_GEN << 24) | BDK_PCC_VENDOR_E_CAVIUM | (BDK_PCC_DEV_IDL_E_SMI << 16))
|
||||
|
||||
#define BDK_MDIO_TIMEOUT 100000 /* 100 millisec */
|
||||
|
||||
/* Operating request encodings. */
|
||||
#define MDIO_CLAUSE_22_WRITE 0
|
||||
#define MDIO_CLAUSE_22_READ 1
|
||||
|
||||
#define MDIO_CLAUSE_45_ADDRESS 0
|
||||
#define MDIO_CLAUSE_45_WRITE 1
|
||||
#define MDIO_CLAUSE_45_READ_INC 2
|
||||
#define MDIO_CLAUSE_45_READ 3
|
||||
|
||||
/**
|
||||
* Helper function to put MDIO interface into clause 45 mode
|
||||
*
|
||||
* @param bus_id
|
||||
*/
|
||||
static void __bdk_mdio_set_clause45_mode(const bdk_device_t *device, int bus_id)
|
||||
{
|
||||
bdk_smi_x_clk_t smi_clk;
|
||||
/* Put bus into clause 45 mode */
|
||||
smi_clk.u = BDK_BAR_READ(device, BDK_SMI_X_CLK(bus_id));
|
||||
if (smi_clk.s.mode != 1)
|
||||
{
|
||||
smi_clk.s.mode = 1;
|
||||
smi_clk.s.preamble = 1;
|
||||
BDK_BAR_WRITE(device, BDK_SMI_X_CLK(bus_id), smi_clk.u);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to put MDIO interface into clause 22 mode
|
||||
*
|
||||
* @param bus_id
|
||||
*/
|
||||
static void __bdk_mdio_set_clause22_mode(const bdk_device_t *device, int bus_id)
|
||||
{
|
||||
bdk_smi_x_clk_t smi_clk;
|
||||
/* Put bus into clause 22 mode */
|
||||
smi_clk.u = BDK_BAR_READ(device, BDK_SMI_X_CLK(bus_id));
|
||||
if (smi_clk.s.mode != 0)
|
||||
{
|
||||
smi_clk.s.mode = 0;
|
||||
BDK_BAR_WRITE(device, BDK_SMI_X_CLK(bus_id), smi_clk.u);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @INTERNAL
|
||||
* Function to read SMIX_RD_DAT and check for timeouts. This
|
||||
* code sequence is done fairly often, so put in in one spot.
|
||||
*
|
||||
* @param bus_id SMI/MDIO bus to read
|
||||
*
|
||||
* @return Value of SMIX_RD_DAT. pending will be set on
|
||||
* a timeout.
|
||||
*/
|
||||
static bdk_smi_x_rd_dat_t __bdk_mdio_read_rd_dat(const bdk_device_t *device, int bus_id)
|
||||
{
|
||||
bdk_smi_x_rd_dat_t smi_rd;
|
||||
uint64_t done = bdk_clock_get_count(BDK_CLOCK_TIME) + (uint64_t)BDK_MDIO_TIMEOUT *
|
||||
bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) / 1000000;
|
||||
do
|
||||
{
|
||||
smi_rd.u = BDK_BAR_READ(device, BDK_SMI_X_RD_DAT(bus_id));
|
||||
} while (smi_rd.s.pending && (bdk_clock_get_count(BDK_CLOCK_TIME) < done));
|
||||
return smi_rd;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform an MII read. This function is used to read PHY
|
||||
* registers controlling auto negotiation.
|
||||
*
|
||||
* @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
|
||||
* support multiple busses.
|
||||
* @param phy_id The MII phy id
|
||||
* @param location Register location to read
|
||||
*
|
||||
* @return Result from the read or -1 on failure
|
||||
*/
|
||||
int bdk_mdio_read(bdk_node_t node, int bus_id, int phy_id, int location)
|
||||
{
|
||||
const bdk_device_t *device = bdk_device_lookup(node, MDIO_DEVID, 0);
|
||||
if (!device)
|
||||
{
|
||||
bdk_error("MDIO: ECAM device not found\n");
|
||||
return -1;
|
||||
}
|
||||
bdk_smi_x_cmd_t smi_cmd;
|
||||
bdk_smi_x_rd_dat_t smi_rd;
|
||||
|
||||
__bdk_mdio_set_clause22_mode(device, bus_id);
|
||||
|
||||
smi_cmd.u = 0;
|
||||
smi_cmd.s.phy_op = MDIO_CLAUSE_22_READ;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = location;
|
||||
BDK_BAR_WRITE(device, BDK_SMI_X_CMD(bus_id), smi_cmd.u);
|
||||
|
||||
smi_rd = __bdk_mdio_read_rd_dat(device, bus_id);
|
||||
if (smi_rd.s.val)
|
||||
return smi_rd.s.dat;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Perform an MII write. This function is used to write PHY
|
||||
* registers controlling auto negotiation.
|
||||
*
|
||||
* @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
|
||||
* support multiple busses.
|
||||
* @param phy_id The MII phy id
|
||||
* @param location Register location to write
|
||||
* @param val Value to write
|
||||
*
|
||||
* @return -1 on error
|
||||
* 0 on success
|
||||
*/
|
||||
int bdk_mdio_write(bdk_node_t node, int bus_id, int phy_id, int location, int val)
|
||||
{
|
||||
const bdk_device_t *device = bdk_device_lookup(node, MDIO_DEVID, 0);
|
||||
if (!device)
|
||||
{
|
||||
bdk_error("MDIO: ECAM device not found\n");
|
||||
return -1;
|
||||
}
|
||||
bdk_smi_x_cmd_t smi_cmd;
|
||||
bdk_smi_x_wr_dat_t smi_wr;
|
||||
|
||||
__bdk_mdio_set_clause22_mode(device, bus_id);
|
||||
|
||||
smi_wr.u = 0;
|
||||
smi_wr.s.dat = val;
|
||||
BDK_BAR_WRITE(device, BDK_SMI_X_WR_DAT(bus_id), smi_wr.u);
|
||||
|
||||
smi_cmd.u = 0;
|
||||
smi_cmd.s.phy_op = MDIO_CLAUSE_22_WRITE;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = location;
|
||||
BDK_BAR_WRITE(device, BDK_SMI_X_CMD(bus_id), smi_cmd.u);
|
||||
|
||||
if (BDK_BAR_WAIT_FOR_FIELD(device, BDK_SMI_X_WR_DAT(bus_id), pending, ==, 0, BDK_MDIO_TIMEOUT))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an IEEE 802.3 clause 45 MII read. This function is used to read PHY
|
||||
* registers controlling auto negotiation.
|
||||
*
|
||||
* @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
|
||||
* support multiple busses.
|
||||
* @param phy_id The MII phy id
|
||||
* @param device MDIO Manageable Device (MMD) id
|
||||
* @param location Register location to read
|
||||
*
|
||||
* @return Result from the read or -1 on failure
|
||||
*/
|
||||
|
||||
int bdk_mdio_45_read(bdk_node_t node, int bus_id, int phy_id, int device, int location)
|
||||
{
|
||||
const bdk_device_t *ecam_device = bdk_device_lookup(node, MDIO_DEVID, 0);
|
||||
if (!ecam_device)
|
||||
{
|
||||
bdk_error("MDIO: ECAM device not found\n");
|
||||
return -1;
|
||||
}
|
||||
bdk_smi_x_cmd_t smi_cmd;
|
||||
bdk_smi_x_rd_dat_t smi_rd;
|
||||
bdk_smi_x_wr_dat_t smi_wr;
|
||||
|
||||
__bdk_mdio_set_clause45_mode(ecam_device, bus_id);
|
||||
|
||||
smi_wr.u = 0;
|
||||
smi_wr.s.dat = location;
|
||||
BDK_BAR_WRITE(ecam_device, BDK_SMI_X_WR_DAT(bus_id), smi_wr.u);
|
||||
|
||||
smi_cmd.u = 0;
|
||||
smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = device;
|
||||
BDK_BAR_WRITE(ecam_device, BDK_SMI_X_CMD(bus_id), smi_cmd.u);
|
||||
|
||||
if (BDK_BAR_WAIT_FOR_FIELD(ecam_device, BDK_SMI_X_WR_DAT(bus_id), pending, ==, 0, BDK_MDIO_TIMEOUT))
|
||||
{
|
||||
bdk_error("bdk_mdio_45_read: bus_id %d phy_id %2d device %2d register %2d TIME OUT(address)\n", bus_id, phy_id, device, location);
|
||||
return -1;
|
||||
}
|
||||
|
||||
smi_cmd.u = 0;
|
||||
smi_cmd.s.phy_op = MDIO_CLAUSE_45_READ;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = device;
|
||||
BDK_BAR_WRITE(ecam_device, BDK_SMI_X_CMD(bus_id), smi_cmd.u);
|
||||
|
||||
smi_rd = __bdk_mdio_read_rd_dat(ecam_device, bus_id);
|
||||
if (smi_rd.s.pending)
|
||||
{
|
||||
bdk_error("bdk_mdio_45_read: bus_id %d phy_id %2d device %2d register %2d TIME OUT(data)\n", bus_id, phy_id, device, location);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (smi_rd.s.val)
|
||||
return smi_rd.s.dat;
|
||||
else
|
||||
{
|
||||
bdk_error("bdk_mdio_45_read: bus_id %d phy_id %2d device %2d register %2d INVALID READ\n", bus_id, phy_id, device, location);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an IEEE 802.3 clause 45 MII write. This function is used to write PHY
|
||||
* registers controlling auto negotiation.
|
||||
*
|
||||
* @param bus_id MDIO bus number. Zero on most chips, but some chips (ex CN56XX)
|
||||
* support multiple busses.
|
||||
* @param phy_id The MII phy id
|
||||
* @param device MDIO Manageable Device (MMD) id
|
||||
* @param location Register location to write
|
||||
* @param val Value to write
|
||||
*
|
||||
* @return -1 on error
|
||||
* 0 on success
|
||||
*/
|
||||
int bdk_mdio_45_write(bdk_node_t node, int bus_id, int phy_id, int device, int location,
|
||||
int val)
|
||||
{
|
||||
const bdk_device_t *ecam_device = bdk_device_lookup(node, MDIO_DEVID, 0);
|
||||
if (!ecam_device)
|
||||
{
|
||||
bdk_error("MDIO: ECAM device not found\n");
|
||||
return -1;
|
||||
}
|
||||
bdk_smi_x_cmd_t smi_cmd;
|
||||
bdk_smi_x_wr_dat_t smi_wr;
|
||||
|
||||
__bdk_mdio_set_clause45_mode(ecam_device, bus_id);
|
||||
|
||||
smi_wr.u = 0;
|
||||
smi_wr.s.dat = location;
|
||||
BDK_BAR_WRITE(ecam_device, BDK_SMI_X_WR_DAT(bus_id), smi_wr.u);
|
||||
|
||||
smi_cmd.u = 0;
|
||||
smi_cmd.s.phy_op = MDIO_CLAUSE_45_ADDRESS;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = device;
|
||||
BDK_BAR_WRITE(ecam_device, BDK_SMI_X_CMD(bus_id), smi_cmd.u);
|
||||
|
||||
if (BDK_BAR_WAIT_FOR_FIELD(ecam_device, BDK_SMI_X_WR_DAT(bus_id), pending, ==, 0, BDK_MDIO_TIMEOUT))
|
||||
return -1;
|
||||
|
||||
smi_wr.u = 0;
|
||||
smi_wr.s.dat = val;
|
||||
BDK_BAR_WRITE(ecam_device, BDK_SMI_X_WR_DAT(bus_id), smi_wr.u);
|
||||
|
||||
smi_cmd.u = 0;
|
||||
smi_cmd.s.phy_op = MDIO_CLAUSE_45_WRITE;
|
||||
smi_cmd.s.phy_adr = phy_id;
|
||||
smi_cmd.s.reg_adr = device;
|
||||
BDK_BAR_WRITE(ecam_device, BDK_SMI_X_CMD(bus_id), smi_cmd.u);
|
||||
|
||||
if (BDK_BAR_WAIT_FOR_FIELD(ecam_device, BDK_SMI_X_WR_DAT(bus_id), pending, ==, 0, BDK_MDIO_TIMEOUT))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* MDIO init() function
|
||||
*
|
||||
* @param device MDIO/SMI to initialize
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_mdio_init(bdk_node_t node)
|
||||
{
|
||||
const bdk_device_t *device = bdk_device_lookup(node, MDIO_DEVID, 0);
|
||||
if (!device)
|
||||
{
|
||||
bdk_error("MDIO: ECAM device not found\n");
|
||||
return -1;
|
||||
}
|
||||
/* Change drive strength bits to fix issues when a QLM cable
|
||||
is connected, creating a long spur path */
|
||||
BDK_CSR_MODIFY(c, device->node, BDK_SMI_DRV_CTL,
|
||||
c.s.pctl = 7; /* 30 ohm */
|
||||
c.s.nctl = 7); /* 30 ohm */
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
BDK_BAR_MODIFY(c, device, BDK_SMI_X_EN(i), c.s.en = 1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,7 +22,8 @@
|
||||
*
|
||||
* 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
|
||||
* associateint bdk_rng_init(bdk_node_t node)
|
||||
* d 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"
|
||||
@ -40,6 +41,10 @@
|
||||
#include "libbdk-arch/bdk-csrs-pccpf.h"
|
||||
#include "libbdk-arch/bdk-csrs-rnm.h"
|
||||
|
||||
#include <libbdk-hal/bdk-rng.h>
|
||||
#include <libbdk-hal/device/bdk-device.h>
|
||||
#define RNG_DEVID ((BDK_PCC_PROD_E_GEN << 24) | BDK_PCC_VENDOR_E_CAVIUM | (BDK_PCC_DEV_IDL_E_RNM << 16))
|
||||
|
||||
BDK_REQUIRE_DEFINE(RNM);
|
||||
|
||||
/**
|
||||
@ -83,19 +88,6 @@ 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
|
||||
*
|
||||
@ -103,13 +95,20 @@ static int probe(bdk_device_t *device)
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
static int init(bdk_device_t *device)
|
||||
int bdk_rng_init(bdk_node_t node)
|
||||
{
|
||||
const bdk_device_t *device = bdk_device_lookup(node, RNG_DEVID, 0);
|
||||
if (!device)
|
||||
{
|
||||
bdk_error("RNM: ECAM device not found\n");
|
||||
return -1;
|
||||
}
|
||||
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 */
|
||||
/* Read back after enable so we know it is done. Needed on t88 pass 2.0 emulator and t81 real hardware !!!! */
|
||||
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 */
|
||||
@ -117,8 +116,3 @@ static int init(bdk_device_t *device)
|
||||
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,
|
||||
};
|
||||
|
@ -36,24 +36,35 @@
|
||||
* 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-uaa.h"
|
||||
#include "libbdk-arch/bdk-csrs-rst.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Perform a soft reset of the chip
|
||||
*
|
||||
* Functions for identifying BDK build version.
|
||||
*
|
||||
* <hr>$Revision$<hr>
|
||||
* @return
|
||||
*/
|
||||
|
||||
|
||||
extern const char bdk_version_str[];
|
||||
|
||||
/**
|
||||
* Return BDK version string
|
||||
*
|
||||
* @return BDK version string
|
||||
*/
|
||||
static inline const char *bdk_version_string(void)
|
||||
void bdk_reset_chip(bdk_node_t node)
|
||||
{
|
||||
return bdk_version_str;
|
||||
fflush(NULL);
|
||||
|
||||
/* Wait for TX fifo to empty */
|
||||
while (1)
|
||||
{
|
||||
BDK_CSR_INIT(fr, node, BDK_UAAX_FR(0));
|
||||
if (fr.s.txfe)
|
||||
break;
|
||||
}
|
||||
|
||||
/* RST_OCX is not cleared by a chip reset. Clear it now to avoid repeated
|
||||
resets due to CCPI state changes during reset */
|
||||
BDK_CSR_WRITE(node, BDK_RST_OCX, 0);
|
||||
BDK_CSR_READ(node, BDK_RST_OCX);
|
||||
|
||||
bdk_rst_soft_rst_t rst_soft_rst;
|
||||
rst_soft_rst.u = 0;
|
||||
rst_soft_rst.s.soft_rst = 1;
|
||||
BDK_CSR_WRITE(node, BDK_RST_SOFT_RST, rst_soft_rst.u);
|
||||
}
|
||||
|
@ -37,123 +37,10 @@
|
||||
* 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
#include <libbdk-arch/bdk-csrs-gti.h>
|
||||
#include <libbdk-arch/bdk-csrs-ocx.h>
|
||||
#include <libbdk-hal/bdk-clock.h>
|
||||
#include <libbdk-arch/bdk-csrs-rst.h>
|
||||
|
||||
/**
|
||||
* Get cycle count based on the clock type.
|
||||
@ -165,12 +52,6 @@ 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)
|
||||
{
|
||||
@ -199,12 +80,6 @@ uint64_t __bdk_clock_get_rate_slow(bdk_node_t node, bdk_clock_t clock)
|
||||
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:
|
||||
|
File diff suppressed because it is too large
Load Diff
373
src/vendorcode/cavium/bdk/libbdk-hal/bdk-ecam-io.c
Normal file
373
src/vendorcode/cavium/bdk/libbdk-hal/bdk-ecam-io.c
Normal file
@ -0,0 +1,373 @@
|
||||
/***********************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-ecam.h"
|
||||
#include "libbdk-arch/bdk-csrs-gser.h"
|
||||
#include "libbdk-arch/bdk-csrs-pccpf.h"
|
||||
#include "libbdk-arch/bdk-csrs-pem.h"
|
||||
#include "libbdk-hal/device/bdk-device.h"
|
||||
#include "libbdk-hal/bdk-ecam.h"
|
||||
|
||||
#if 1 /* Support CN88XX pass 1.0 */
|
||||
/*******************************************************************
|
||||
*******************************************************************
|
||||
These functions are related to CN88XX pass 1.0 errata and do not
|
||||
apply to any other chip
|
||||
*******************************************************************
|
||||
*******************************************************************/
|
||||
|
||||
/**
|
||||
* Errata (ECAM-22630) ECAM function accesses can fault
|
||||
* For some errata workaround we need a check to tell if a ECAM access is to a
|
||||
* valid intenral device. This function decodes a pcc_dev_con_e enumeration and
|
||||
* checks if the supplied arguments match it. This should only
|
||||
* ever be called on CN88XX pass 1.0.
|
||||
*
|
||||
* @param ecam ECAM to check
|
||||
* @param bus ECAM bus number
|
||||
* @param dev Device to check
|
||||
* @param fn sub function of device
|
||||
* @param dev_con Enumeration to match against
|
||||
*
|
||||
* @return Non zero if the device matches
|
||||
*/
|
||||
static int is_internal_cn88xxp1_0(const bdk_device_t *device, int dev_con)
|
||||
{
|
||||
union bdk_pcc_dev_con_s d = { .u = dev_con };
|
||||
return (d.cn8.ecam == device->ecam) && (d.s.bus == device->bus) && (d.s.func == ((device->dev<<3)|device->func));
|
||||
}
|
||||
|
||||
/**
|
||||
* Errata (ECAM-22630) ECAM function accesses can fault
|
||||
* This is a companion to the function above to determine if the ECAM device is
|
||||
* any of the valid internal devices. This should only ever be
|
||||
* called on CN88XX pass 1.0.
|
||||
*
|
||||
* @param ecam ECAM to check
|
||||
* @param bus ECAM bus number
|
||||
* @param dev Device to check
|
||||
* @param fn sub function of device
|
||||
*
|
||||
* @return Non zero if the device matches
|
||||
*/
|
||||
static int is_any_internal_cn88xxp1_0(const bdk_device_t *device)
|
||||
{
|
||||
/* Errata (ECAM-22630) ECAM function accesses can fault
|
||||
CN88XXP1.0: The ECAM has a bug where accessing a non-existent
|
||||
device causes an exception. This is a list of all valid devices
|
||||
for CN88XX pass 1.0 */
|
||||
static const uint32_t INTERNAL_DEVICES_CN88XXP1_0[] = {
|
||||
BDK_PCC_DEV_CON_E_BGXX(0),
|
||||
BDK_PCC_DEV_CON_E_BGXX(1),
|
||||
BDK_PCC_DEV_CON_E_DAP,
|
||||
BDK_PCC_DEV_CON_E_DFA,
|
||||
BDK_PCC_DEV_CON_E_FUSF,
|
||||
BDK_PCC_DEV_CON_E_GIC_CN8,
|
||||
BDK_PCC_DEV_CON_E_GPIO_CN8,
|
||||
BDK_PCC_DEV_CON_E_GSERX(0),
|
||||
BDK_PCC_DEV_CON_E_GSERX(1),
|
||||
BDK_PCC_DEV_CON_E_GSERX(10),
|
||||
BDK_PCC_DEV_CON_E_GSERX(11),
|
||||
BDK_PCC_DEV_CON_E_GSERX(12),
|
||||
BDK_PCC_DEV_CON_E_GSERX(13),
|
||||
BDK_PCC_DEV_CON_E_GSERX(2),
|
||||
BDK_PCC_DEV_CON_E_GSERX(3),
|
||||
BDK_PCC_DEV_CON_E_GSERX(4),
|
||||
BDK_PCC_DEV_CON_E_GSERX(5),
|
||||
BDK_PCC_DEV_CON_E_GSERX(6),
|
||||
BDK_PCC_DEV_CON_E_GSERX(7),
|
||||
BDK_PCC_DEV_CON_E_GSERX(8),
|
||||
BDK_PCC_DEV_CON_E_GSERX(9),
|
||||
BDK_PCC_DEV_CON_E_GTI_CN8,
|
||||
BDK_PCC_DEV_CON_E_IOBNX(0),
|
||||
BDK_PCC_DEV_CON_E_IOBNX(1),
|
||||
BDK_PCC_DEV_CON_E_KEY,
|
||||
BDK_PCC_DEV_CON_E_L2C,
|
||||
BDK_PCC_DEV_CON_E_L2C_CBCX(0),
|
||||
BDK_PCC_DEV_CON_E_L2C_CBCX(1),
|
||||
BDK_PCC_DEV_CON_E_L2C_CBCX(2),
|
||||
BDK_PCC_DEV_CON_E_L2C_CBCX(3),
|
||||
BDK_PCC_DEV_CON_E_L2C_MCIX(0),
|
||||
BDK_PCC_DEV_CON_E_L2C_MCIX(1),
|
||||
BDK_PCC_DEV_CON_E_L2C_MCIX(2),
|
||||
BDK_PCC_DEV_CON_E_L2C_MCIX(3),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(0),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(1),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(2),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(3),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(4),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(5),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(6),
|
||||
BDK_PCC_DEV_CON_E_L2C_TADX(7),
|
||||
BDK_PCC_DEV_CON_E_LMCX(0),
|
||||
BDK_PCC_DEV_CON_E_LMCX(1),
|
||||
BDK_PCC_DEV_CON_E_LMCX(2),
|
||||
BDK_PCC_DEV_CON_E_LMCX(3),
|
||||
BDK_PCC_DEV_CON_E_MIO_BOOT,
|
||||
BDK_PCC_DEV_CON_E_MIO_EMM,
|
||||
BDK_PCC_DEV_CON_E_MIO_FUS,
|
||||
BDK_PCC_DEV_CON_E_MIO_PTP,
|
||||
BDK_PCC_DEV_CON_E_MIO_TWSX(0),
|
||||
BDK_PCC_DEV_CON_E_MIO_TWSX(1),
|
||||
BDK_PCC_DEV_CON_E_MIO_TWSX(2),
|
||||
BDK_PCC_DEV_CON_E_MIO_TWSX(3),
|
||||
BDK_PCC_DEV_CON_E_MIO_TWSX(4),
|
||||
BDK_PCC_DEV_CON_E_MIO_TWSX(5),
|
||||
BDK_PCC_DEV_CON_E_MPI,
|
||||
BDK_PCC_DEV_CON_E_MRML,
|
||||
BDK_PCC_DEV_CON_E_NCSI,
|
||||
BDK_PCC_DEV_CON_E_NIC_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_OCLAX_CN8(0),
|
||||
BDK_PCC_DEV_CON_E_OCLAX_CN8(1),
|
||||
BDK_PCC_DEV_CON_E_OCLAX_CN8(2),
|
||||
BDK_PCC_DEV_CON_E_OCLAX_CN8(3),
|
||||
BDK_PCC_DEV_CON_E_OCLAX_CN8(4),
|
||||
BDK_PCC_DEV_CON_E_OCX,
|
||||
BDK_PCC_DEV_CON_E_PCCBR_DFA,
|
||||
BDK_PCC_DEV_CON_E_PCCBR_MRML,
|
||||
BDK_PCC_DEV_CON_E_PCCBR_NIC_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_PCCBR_RAD_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_PCCBR_ZIP_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_PCIERC0_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_PCIERC1_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_PCIERC2_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_PCIERC3_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_PCIERC4,
|
||||
BDK_PCC_DEV_CON_E_PCIERC5,
|
||||
BDK_PCC_DEV_CON_E_PEMX(0),
|
||||
BDK_PCC_DEV_CON_E_PEMX(1),
|
||||
BDK_PCC_DEV_CON_E_PEMX(2),
|
||||
BDK_PCC_DEV_CON_E_PEMX(3),
|
||||
BDK_PCC_DEV_CON_E_PEMX(4),
|
||||
BDK_PCC_DEV_CON_E_PEMX(5),
|
||||
BDK_PCC_DEV_CON_E_RAD_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_RNM_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_RST,
|
||||
BDK_PCC_DEV_CON_E_SATA0_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_SATA1_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_SATA10,
|
||||
BDK_PCC_DEV_CON_E_SATA11,
|
||||
BDK_PCC_DEV_CON_E_SATA12,
|
||||
BDK_PCC_DEV_CON_E_SATA13,
|
||||
BDK_PCC_DEV_CON_E_SATA14,
|
||||
BDK_PCC_DEV_CON_E_SATA15,
|
||||
BDK_PCC_DEV_CON_E_SATA2,
|
||||
BDK_PCC_DEV_CON_E_SATA3,
|
||||
BDK_PCC_DEV_CON_E_SATA4,
|
||||
BDK_PCC_DEV_CON_E_SATA5,
|
||||
BDK_PCC_DEV_CON_E_SATA6,
|
||||
BDK_PCC_DEV_CON_E_SATA7,
|
||||
BDK_PCC_DEV_CON_E_SATA8,
|
||||
BDK_PCC_DEV_CON_E_SATA9,
|
||||
BDK_PCC_DEV_CON_E_SGP,
|
||||
BDK_PCC_DEV_CON_E_SLI0_CN88XX,
|
||||
BDK_PCC_DEV_CON_E_SLI1,
|
||||
BDK_PCC_DEV_CON_E_SMI,
|
||||
BDK_PCC_DEV_CON_E_SMMU0_CN8,
|
||||
BDK_PCC_DEV_CON_E_SMMU1,
|
||||
BDK_PCC_DEV_CON_E_SMMU2,
|
||||
BDK_PCC_DEV_CON_E_SMMU3,
|
||||
BDK_PCC_DEV_CON_E_TNS,
|
||||
BDK_PCC_DEV_CON_E_UAAX_CN8(0),
|
||||
BDK_PCC_DEV_CON_E_UAAX_CN8(1),
|
||||
BDK_PCC_DEV_CON_E_USBHX(0),
|
||||
BDK_PCC_DEV_CON_E_USBHX(1),
|
||||
BDK_PCC_DEV_CON_E_VRMX(0),
|
||||
BDK_PCC_DEV_CON_E_VRMX(1),
|
||||
BDK_PCC_DEV_CON_E_ZIP_CN88XX,
|
||||
0,
|
||||
};
|
||||
|
||||
int loc = 0;
|
||||
while (INTERNAL_DEVICES_CN88XXP1_0[loc])
|
||||
{
|
||||
if (is_internal_cn88xxp1_0(device, INTERNAL_DEVICES_CN88XXP1_0[loc]))
|
||||
return 1;
|
||||
loc++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int is_accessable_cn88xxp1_0(const bdk_device_t *device)
|
||||
{
|
||||
/* Errata (ECAM-22630) ECAM function accesses can fault */
|
||||
/* Skip internal devices that don't exists */
|
||||
if (!is_any_internal_cn88xxp1_0(device))
|
||||
return 0;
|
||||
|
||||
/* Errata (ECAM-23020) PCIERC transactions fault unless PEM is
|
||||
out of reset. The PCIe ports don't work until the PEM is
|
||||
turned on. Check for one of the PCIe ports */
|
||||
int pem = -1;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_PCIERC0_CN88XX))
|
||||
pem = 0;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_PCIERC1_CN88XX))
|
||||
pem = 1;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_PCIERC2_CN88XX))
|
||||
pem = 2;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_PCIERC3_CN88XX))
|
||||
pem = 3;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_PCIERC4))
|
||||
pem = 4;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_PCIERC5))
|
||||
pem = 5;
|
||||
if (pem != -1)
|
||||
{
|
||||
BDK_CSR_INIT(pem_on, device->node, BDK_PEMX_ON(pem));
|
||||
if (!pem_on.s.pemon || !pem_on.s.pemoor)
|
||||
return 0;
|
||||
}
|
||||
|
||||
{
|
||||
/* SATA ports should be hidden if they aren't configured at the QLM */
|
||||
int qlm = -1;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA0_CN88XX) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA1_CN88XX) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA2) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA3))
|
||||
qlm = 2;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA4) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA5) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA6) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA7))
|
||||
qlm = 3;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA8) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA9) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA10) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA11))
|
||||
qlm = 6;
|
||||
if (is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA12) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA13) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA14) ||
|
||||
is_internal_cn88xxp1_0(device, BDK_PCC_DEV_CON_E_SATA15))
|
||||
qlm = 7;
|
||||
if (qlm != -1)
|
||||
{
|
||||
BDK_CSR_INIT(cfg, device->node, BDK_GSERX_CFG(qlm));
|
||||
if (!cfg.s.sata)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* Support CN88XX pass 1.0 */
|
||||
|
||||
/**
|
||||
* Build an ECAM config space request address for a device
|
||||
*
|
||||
* @param device Device being accessed
|
||||
* @param reg Register to access
|
||||
*
|
||||
* @return 64bit IO address
|
||||
*/
|
||||
uint64_t __bdk_ecam_build_address(const bdk_device_t *device, int reg)
|
||||
{
|
||||
/* CN88XX pass 1.0 had a plethora of errata related to ECAM access. This
|
||||
checks to make sure we're allowed to access this location based on
|
||||
the various errata */
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_0) && !is_accessable_cn88xxp1_0(device))
|
||||
return 0;
|
||||
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
|
||||
{
|
||||
/* Build the address */
|
||||
union bdk_ecam_cfg_addr_s address;
|
||||
address.u = BDK_ECAM_BAR_E_ECAMX_PF_BAR2(device->ecam);
|
||||
address.s.node = device->node;
|
||||
address.s.bus = device->bus;
|
||||
address.s.func = device->dev << 3 | device->func;
|
||||
address.s.addr = reg;
|
||||
return address.u;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Build the address. The architects decided to make it different
|
||||
from CN8XXX for no obvious reason */
|
||||
union bdk_ecam_cfg_addr_s address;
|
||||
address.u = BDK_ECAM_BAR_E_ECAMX_PF_BAR2(0);
|
||||
address.s.node = device->node;
|
||||
address.s.dmn = device->ecam;
|
||||
address.s.bus = device->bus;
|
||||
address.s.func = device->dev << 3 | device->func;
|
||||
address.s.addr = reg;
|
||||
return address.u;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from an ECAM
|
||||
*
|
||||
* @param device Device to read from
|
||||
* @param reg Register to read
|
||||
*
|
||||
* @return Result of the read of -1 on failure
|
||||
*/
|
||||
uint32_t bdk_ecam_read32(const bdk_device_t *device, int reg)
|
||||
{
|
||||
uint64_t address = __bdk_ecam_build_address(device, reg);
|
||||
uint32_t result;
|
||||
if (address)
|
||||
result = bdk_le32_to_cpu(bdk_read64_uint32(address));
|
||||
else
|
||||
result = 0xffffffff;
|
||||
|
||||
/* Errata ECAM-22630: CN88XX pass 1.x, except pass 1.0, will return zero
|
||||
for non-existent devices instead of ones. We look for this special case
|
||||
for 32bit reads for reg=0 so we can scan device properly */
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X) && (reg == 0) && (result == 0))
|
||||
result = 0xffffffff;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to an ECAM register
|
||||
*
|
||||
* @param device Device to write to
|
||||
* @param reg Register to write
|
||||
* @param value Value to write
|
||||
*/
|
||||
void bdk_ecam_write32(const bdk_device_t *device, int reg, uint32_t value)
|
||||
{
|
||||
uint64_t address = __bdk_ecam_build_address(device, reg);
|
||||
if (address)
|
||||
bdk_write64_uint32(address, bdk_cpu_to_le32(value));
|
||||
}
|
||||
|
216
src/vendorcode/cavium/bdk/libbdk-hal/bdk-ecam.c
Normal file
216
src/vendorcode/cavium/bdk/libbdk-hal/bdk-ecam.c
Normal file
@ -0,0 +1,216 @@
|
||||
/***********************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 <string.h>
|
||||
#include "libbdk-arch/bdk-csrs-ecam.h"
|
||||
#include "libbdk-arch/bdk-csrs-pccbr.h"
|
||||
#include "libbdk-arch/bdk-csrs-pccpf.h"
|
||||
#include "libbdk-arch/bdk-csrs-rvu.h"
|
||||
#include "libbdk-hal/device/bdk-device.h"
|
||||
#include "libbdk-hal/bdk-ecam.h"
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
if BDK_REQUIRE() needs it */
|
||||
BDK_REQUIRE_DEFINE(ECAM);
|
||||
|
||||
/**
|
||||
* Walk an ECAM finding all internal devices. Each internal
|
||||
* device is then added to the list of device maintained by
|
||||
* bdk-device.
|
||||
*
|
||||
* @param node Node to walk
|
||||
* @param ecam Ecam to walk
|
||||
* @param bus Zero on first call. Will be non-zero when sub busses are walked
|
||||
*/
|
||||
static void ecam_walk_internal_bus(bdk_node_t node, int ecam, int bus)
|
||||
{
|
||||
/* Create a fake bdk-device to pass around until we create the
|
||||
real device */
|
||||
bdk_device_t device;
|
||||
memset(&device, 0, sizeof(device));
|
||||
device.node = node;
|
||||
device.ecam = ecam;
|
||||
device.bus = bus;
|
||||
|
||||
/* Scan all possible device IDs on the bus */
|
||||
for (int dev = 0; dev < 32; dev++)
|
||||
{
|
||||
/* Update the current scan location */
|
||||
device.dev = dev;
|
||||
device.func = 0;
|
||||
|
||||
uint32_t device_id = bdk_ecam_read32(&device, BDK_PCCPF_XXX_ID);
|
||||
|
||||
/* Only add devices that exist. Our internal devices can have function
|
||||
zero missing. The all ones we get back matches the multi-function
|
||||
check, but not a bridge. This means the later code works fine */
|
||||
if (device_id != (uint32_t)-1)
|
||||
bdk_device_add(device.node, device.ecam, device.bus, device.dev, device.func);
|
||||
|
||||
/* Check for Multi function and Bridge devices */
|
||||
BDK_CSR_DEFINE(clsize, BDK_PCCPF_XXX_CLSIZE);
|
||||
clsize.u = bdk_ecam_read32(&device, BDK_PCCPF_XXX_CLSIZE);
|
||||
int ismultifunction = (clsize.s.hdrtype & 0x80);
|
||||
int isbridge = (clsize.s.hdrtype & 0x7f) == 1;
|
||||
|
||||
if (ismultifunction)
|
||||
{
|
||||
/* Scan for other functions on multifunction devices */
|
||||
for (int func = 1; func < 8; func++)
|
||||
{
|
||||
/* Check if we're past all functions */
|
||||
device.func = func;
|
||||
device_id = bdk_ecam_read32(&device, BDK_PCCPF_XXX_ID);
|
||||
if (device_id != (uint32_t)-1)
|
||||
bdk_device_add(device.node, device.ecam, device.bus, device.dev, device.func);
|
||||
}
|
||||
device.func = 0;
|
||||
}
|
||||
if (isbridge)
|
||||
{
|
||||
/* Internal bus numbers are hard coded. Read the bus ID */
|
||||
bdk_pccbr_xxx_bus_t ibus;
|
||||
ibus.u = bdk_ecam_read32(&device, BDK_PCCBR_XXX_BUS);
|
||||
/* Asim used to have a bug where bus number were zero, report errors
|
||||
for those */
|
||||
if (ibus.s.sbnum == 0)
|
||||
{
|
||||
bdk_error("N%d:E%d:%d:%d.%d: Secondary bus number is zero\n",
|
||||
device.node, device.ecam, device.bus, device.dev, device.func);
|
||||
}
|
||||
/* Real PCIe external device use high bus numbers, so skip them */
|
||||
else if (ibus.s.sbnum < 16)
|
||||
{
|
||||
ecam_walk_internal_bus(node, ecam, ibus.s.sbnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of internal ECAMS on a node.
|
||||
*
|
||||
* @param node Node to query
|
||||
*
|
||||
* @return Number of ECAMs available
|
||||
*/
|
||||
int bdk_ecam_get_num(bdk_node_t node)
|
||||
{
|
||||
/* CN88XX lacks the ECAM_CONST for finding the number of ECAMs */
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX))
|
||||
return 4;
|
||||
else if (CAVIUM_IS_MODEL(CAVIUM_CN93XX))
|
||||
return 3; /* Map ECAMs to the first 3 domains */
|
||||
else
|
||||
{
|
||||
BDK_CSR_INIT(ecam_const, node, BDK_ECAMX_CONST(0));
|
||||
if (ecam_const.s.ecams == 0)
|
||||
{
|
||||
bdk_error("N%d.ECAM: Number of ecams incorrect in ECAMX_CONST\n", node);
|
||||
return 1;
|
||||
}
|
||||
return ecam_const.s.ecams;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize RVU functions for use by the BDK. This doesn't setup the hardware
|
||||
* behind RVU, juse allows register access to it. The BDK uses a static RVU
|
||||
* configuration where everything is accessable from RVU PF0.
|
||||
*
|
||||
* @param node Node to initialize
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
static int __bdk_ecam_rvu_init(bdk_node_t node)
|
||||
{
|
||||
const int rvu_pf = 0;
|
||||
/* Enable PF access to all blocks */
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_CPTX_CFG(rvu_pf, 0),
|
||||
c.s.num_lfs = 1); // FIXME: How many LFs?
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_INT_CFG(rvu_pf),
|
||||
c.s.msix_offset = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_MSIX_CFG(rvu_pf),
|
||||
c.s.pf_msixt_offset = 0;
|
||||
c.s.pf_msixt_sizem1 = 0;
|
||||
c.s.vf_msixt_offset = 0;
|
||||
c.s.vf_msixt_sizem1 = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_NIXX_CFG(rvu_pf, 0),
|
||||
c.s.has_lf = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_NPA_CFG(rvu_pf),
|
||||
c.s.has_lf = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_SSO_CFG(rvu_pf),
|
||||
c.s.num_lfs = 1); // FIXME: How many LFs?
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_SSOW_CFG(rvu_pf),
|
||||
c.s.num_lfs = 1); // FIXME: How many LFs?
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_TIM_CFG(rvu_pf),
|
||||
c.s.num_lfs = 1); // FIXME: How many LFs?
|
||||
/* Enable RVU with full access */
|
||||
BDK_CSR_MODIFY(c, node, BDK_RVU_PRIV_PFX_CFG(rvu_pf),
|
||||
c.s.me_flr_ena = 1;
|
||||
c.s.af_ena = 1;
|
||||
c.s.ena = 1;
|
||||
c.s.nvf = 0;
|
||||
c.s.first_hwvf = 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Scan all ECAMs for devices and add them to bdk-device
|
||||
*
|
||||
* @param node Node to scan
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_ecam_scan_all(bdk_node_t node)
|
||||
{
|
||||
/* RVU must be setup before we scan the bus otherwise it doesn't
|
||||
show up */
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
|
||||
__bdk_ecam_rvu_init(node);
|
||||
|
||||
int num_ecams = bdk_ecam_get_num(node);
|
||||
for (int ecam = 0; ecam < num_ecams; ecam++)
|
||||
ecam_walk_internal_bus(node, ecam, 0);
|
||||
|
||||
bdk_device_init();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
#include "libbdk-arch/bdk-csrs-gpio.h"
|
||||
#include "libbdk-hal/bdk-gpio.h"
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
if BDK_REQUIRE() needs it */
|
||||
|
@ -41,6 +41,8 @@
|
||||
#include "libbdk-arch/bdk-csrs-l2c.h"
|
||||
#include "libbdk-arch/bdk-csrs-l2c_cbc.h"
|
||||
#include "libbdk-arch/bdk-csrs-mio_fus.h"
|
||||
#include "libbdk-hal/bdk-l2c.h"
|
||||
#include "libbdk-hal/bdk-utils.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -51,56 +53,6 @@ typedef struct
|
||||
|
||||
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;
|
||||
@ -120,82 +72,11 @@ int bdk_l2c_set_hw_way_partition(bdk_node_t node, uint32_t 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;
|
||||
@ -254,17 +135,22 @@ int bdk_l2c_get_num_assoc(bdk_node_t 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)
|
||||
int bdk_l2c_unlock_mem_region(bdk_node_t node, uint64_t start, uint64_t len)
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
1090
src/vendorcode/cavium/bdk/libbdk-hal/bdk-nic.c
Normal file
1090
src/vendorcode/cavium/bdk/libbdk-hal/bdk-nic.c
Normal file
File diff suppressed because it is too large
Load Diff
1263
src/vendorcode/cavium/bdk/libbdk-hal/bdk-pcie-cn8xxx.c
Normal file
1263
src/vendorcode/cavium/bdk/libbdk-hal/bdk-pcie-cn8xxx.c
Normal file
File diff suppressed because it is too large
Load Diff
221
src/vendorcode/cavium/bdk/libbdk-hal/bdk-pcie.c
Normal file
221
src/vendorcode/cavium/bdk/libbdk-hal/bdk-pcie.c
Normal 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-hal/bdk-pcie.h"
|
||||
#include "libbdk-hal/bdk-utils.h"
|
||||
#include "libbdk-hal/if/bdk-if.h"
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
if BDK_REQUIRE() needs it */
|
||||
BDK_REQUIRE_DEFINE(PCIE);
|
||||
|
||||
/**
|
||||
* Read 8bits from a Device's config space
|
||||
*
|
||||
* @param pcie_port PCIe port the device is on
|
||||
* @param bus Sub bus
|
||||
* @param dev Device ID
|
||||
* @param fn Device sub function
|
||||
* @param reg Register to access
|
||||
*
|
||||
* @return Result of the read
|
||||
*/
|
||||
uint8_t bdk_pcie_config_read8(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg)
|
||||
{
|
||||
uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Read8(bus=%d, dev=%d, fn=%d, reg=0x%x, internal=0x%llx)\n",
|
||||
node, pcie_port, bus, dev, fn, reg, address);
|
||||
uint8_t result;
|
||||
if (address)
|
||||
result = bdk_read64_uint8(address);
|
||||
else
|
||||
result = 0xff;
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Result=0x%02x\n", node, pcie_port, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read 16bits from a Device's config space
|
||||
*
|
||||
* @param pcie_port PCIe port the device is on
|
||||
* @param bus Sub bus
|
||||
* @param dev Device ID
|
||||
* @param fn Device sub function
|
||||
* @param reg Register to access
|
||||
*
|
||||
* @return Result of the read
|
||||
*/
|
||||
uint16_t bdk_pcie_config_read16(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg)
|
||||
{
|
||||
uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Read16(bus=%d, dev=%d, fn=%d, reg=0x%x, internal=0x%llx)\n",
|
||||
node, pcie_port, bus, dev, fn, reg, address);
|
||||
uint16_t result;
|
||||
if (address)
|
||||
result = bdk_le16_to_cpu(bdk_read64_uint16(address));
|
||||
else
|
||||
result = 0xffff;
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Result=0x%04x\n", node, pcie_port, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Read 32bits from a Device's config space
|
||||
*
|
||||
* @param pcie_port PCIe port the device is on
|
||||
* @param bus Sub bus
|
||||
* @param dev Device ID
|
||||
* @param fn Device sub function
|
||||
* @param reg Register to access
|
||||
*
|
||||
* @return Result of the read
|
||||
*/
|
||||
uint32_t bdk_pcie_config_read32(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg)
|
||||
{
|
||||
uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Read32(bus=%d, dev=%d, fn=%d, reg=0x%x, internal=0x%llx)\n",
|
||||
node, pcie_port, bus, dev, fn, reg, address);
|
||||
|
||||
uint32_t result;
|
||||
if (address)
|
||||
result = bdk_le32_to_cpu(bdk_read64_uint32(address));
|
||||
else
|
||||
result = 0xffffffff;
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Result=0x%08x\n", node, pcie_port, result);
|
||||
|
||||
/* Errata ECAM-22630: CN88XX pass 1.x, except pass 1.0, will return zero
|
||||
for non-existent devices instead of ones. We look for this special case
|
||||
for 32bit reads for reg=0 so we can scan device properly */
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X) && (reg == 0) && (result == 0))
|
||||
result = 0xffffffff;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write 8bits to a Device's config space
|
||||
*
|
||||
* @param pcie_port PCIe port the device is on
|
||||
* @param bus Sub bus
|
||||
* @param dev Device ID
|
||||
* @param fn Device sub function
|
||||
* @param reg Register to access
|
||||
* @param val Value to write
|
||||
*/
|
||||
void bdk_pcie_config_write8(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg, uint8_t val)
|
||||
{
|
||||
uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Write8(bus=%d, dev=%d, fn=%d, reg=0x%x, val=0x%02x, internal=0x%llx)\n",
|
||||
node, pcie_port, bus, dev, fn, reg, val, address);
|
||||
if (address)
|
||||
bdk_write64_uint8(address, val);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write 16bits to a Device's config space
|
||||
*
|
||||
* @param pcie_port PCIe port the device is on
|
||||
* @param bus Sub bus
|
||||
* @param dev Device ID
|
||||
* @param fn Device sub function
|
||||
* @param reg Register to access
|
||||
* @param val Value to write
|
||||
*/
|
||||
void bdk_pcie_config_write16(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg, uint16_t val)
|
||||
{
|
||||
uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Write16(bus=%d, dev=%d, fn=%d, reg=0x%x, val=0x%04x, internal=0x%llx)\n",
|
||||
node, pcie_port, bus, dev, fn, reg, val, address);
|
||||
if (address)
|
||||
bdk_write64_uint16(address, bdk_cpu_to_le16(val));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Write 32bits to a Device's config space
|
||||
*
|
||||
* @param pcie_port PCIe port the device is on
|
||||
* @param bus Sub bus
|
||||
* @param dev Device ID
|
||||
* @param fn Device sub function
|
||||
* @param reg Register to access
|
||||
* @param val Value to write
|
||||
*/
|
||||
void bdk_pcie_config_write32(bdk_node_t node, int pcie_port, int bus, int dev, int fn, int reg, uint32_t val)
|
||||
{
|
||||
uint64_t address = pcie_build_config_addr(node, pcie_port, bus, dev, fn, reg);
|
||||
BDK_TRACE(PCIE_CONFIG, "N%d.PCIe%d: Config Write32(bus=%d, dev=%d, fn=%d, reg=0x%x, val=0x%08x, internal=0x%llx)\n",
|
||||
node, pcie_port, bus, dev, fn, reg, val, address);
|
||||
if (address)
|
||||
bdk_write64_uint32(address, bdk_cpu_to_le32(val));
|
||||
}
|
||||
|
||||
/**
|
||||
* Read 64bits from PCIe using a memory transaction
|
||||
*
|
||||
* @param node Node to read from
|
||||
* @param pcie_port PCIe port to read
|
||||
* @param address PCIe address to read
|
||||
*
|
||||
* @return Result of the read
|
||||
*/
|
||||
uint64_t bdk_pcie_mem_read64(bdk_node_t node, int pcie_port, uint64_t address)
|
||||
{
|
||||
uint64_t base_address = bdk_pcie_get_base_address(node, pcie_port, BDK_PCIE_MEM_NORMAL);
|
||||
return bdk_read64_uint64(base_address + address);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write 64bits to PCIe memory
|
||||
*
|
||||
* @param node Node to write to
|
||||
* @param pcie_port PCIe port to use
|
||||
* @param address Address to write
|
||||
* @param data Data to write
|
||||
*/
|
||||
void bdk_pcie_mem_write64(bdk_node_t node, int pcie_port, uint64_t address, uint64_t data)
|
||||
{
|
||||
uint64_t base_address = bdk_pcie_get_base_address(node, pcie_port, BDK_PCIE_MEM_NORMAL);
|
||||
bdk_write64_uint64(base_address + address, data);
|
||||
}
|
||||
|
423
src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c
Normal file
423
src/vendorcode/cavium/bdk/libbdk-hal/bdk-qlm.c
Normal file
@ -0,0 +1,423 @@
|
||||
/***********************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 <string.h>
|
||||
#include "libbdk-arch/bdk-csrs-gser.h"
|
||||
#include "libbdk-arch/bdk-csrs-gsern.h"
|
||||
#include "libbdk-hal/if/bdk-if.h"
|
||||
#include "libbdk-hal/bdk-qlm.h"
|
||||
#include "libbdk-hal/qlm/bdk-qlm-common.h"
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
if BDK_REQUIRE() needs it */
|
||||
BDK_REQUIRE_DEFINE(QLM);
|
||||
|
||||
/**
|
||||
* Convert a mode into a configuration variable string value
|
||||
*
|
||||
* @param mode Mode to convert
|
||||
*
|
||||
* @return configuration value string
|
||||
*/
|
||||
const char *bdk_qlm_mode_to_cfg_str(bdk_qlm_modes_t mode)
|
||||
{
|
||||
#define MODE_CASE(m) case m: return #m+13
|
||||
switch (mode)
|
||||
{
|
||||
MODE_CASE(BDK_QLM_MODE_DISABLED);
|
||||
MODE_CASE(BDK_QLM_MODE_PCIE_1X1);
|
||||
MODE_CASE(BDK_QLM_MODE_PCIE_2X1);
|
||||
MODE_CASE(BDK_QLM_MODE_PCIE_1X2);
|
||||
MODE_CASE(BDK_QLM_MODE_PCIE_1X4);
|
||||
MODE_CASE(BDK_QLM_MODE_PCIE_1X8);
|
||||
MODE_CASE(BDK_QLM_MODE_PCIE_1X16);
|
||||
|
||||
MODE_CASE(BDK_QLM_MODE_SATA_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_SATA_2X1);
|
||||
|
||||
MODE_CASE(BDK_QLM_MODE_ILK);
|
||||
MODE_CASE(BDK_QLM_MODE_SGMII_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_SGMII_2X1);
|
||||
MODE_CASE(BDK_QLM_MODE_SGMII_1X1);
|
||||
MODE_CASE(BDK_QLM_MODE_XAUI_1X4);
|
||||
MODE_CASE(BDK_QLM_MODE_RXAUI_2X2);
|
||||
MODE_CASE(BDK_QLM_MODE_RXAUI_1X2);
|
||||
MODE_CASE(BDK_QLM_MODE_OCI);
|
||||
MODE_CASE(BDK_QLM_MODE_XFI_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_XFI_2X1);
|
||||
MODE_CASE(BDK_QLM_MODE_XFI_1X1);
|
||||
MODE_CASE(BDK_QLM_MODE_XLAUI_1X4);
|
||||
MODE_CASE(BDK_QLM_MODE_10G_KR_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_10G_KR_2X1);
|
||||
MODE_CASE(BDK_QLM_MODE_10G_KR_1X1);
|
||||
MODE_CASE(BDK_QLM_MODE_40G_KR4_1X4);
|
||||
MODE_CASE(BDK_QLM_MODE_QSGMII_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_25G_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_25G_2X1);
|
||||
MODE_CASE(BDK_QLM_MODE_50G_2X2);
|
||||
MODE_CASE(BDK_QLM_MODE_50G_1X2);
|
||||
MODE_CASE(BDK_QLM_MODE_100G_1X4);
|
||||
MODE_CASE(BDK_QLM_MODE_25G_KR_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_25G_KR_2X1);
|
||||
MODE_CASE(BDK_QLM_MODE_50G_KR_2X2);
|
||||
MODE_CASE(BDK_QLM_MODE_50G_KR_1X2);
|
||||
MODE_CASE(BDK_QLM_MODE_100G_KR4_1X4);
|
||||
MODE_CASE(BDK_QLM_MODE_USXGMII_4X1);
|
||||
MODE_CASE(BDK_QLM_MODE_USXGMII_2X1);
|
||||
|
||||
case BDK_QLM_MODE_LAST: break; /* fall through error */
|
||||
}
|
||||
return "INVALID_QLM_MODE_VALUE";
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a configuration variable value string into a mode
|
||||
*
|
||||
* @param val Configuration variable value
|
||||
*
|
||||
* @return mode
|
||||
*/
|
||||
bdk_qlm_modes_t bdk_qlm_cfg_string_to_mode(const char *val)
|
||||
{
|
||||
bdk_qlm_modes_t mode;
|
||||
|
||||
for (mode = 0; mode < BDK_QLM_MODE_LAST; mode++)
|
||||
{
|
||||
if (0 == strcmp(val, bdk_qlm_mode_to_cfg_str(mode)))
|
||||
{
|
||||
return mode;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a mode into a human understandable string
|
||||
*
|
||||
* @param mode Mode to convert
|
||||
*
|
||||
* @return Easy to read string
|
||||
*/
|
||||
const char *bdk_qlm_mode_tostring(bdk_qlm_modes_t mode)
|
||||
{
|
||||
const char *result = "Unknown, update bdk_qlm_mode_tostring()";
|
||||
switch (mode)
|
||||
{
|
||||
case BDK_QLM_MODE_DISABLED:
|
||||
result = "Disabled";
|
||||
break;
|
||||
case BDK_QLM_MODE_PCIE_1X1:
|
||||
result = "1 PCIe, 1 lane";
|
||||
break;
|
||||
case BDK_QLM_MODE_PCIE_2X1:
|
||||
result = "2 PCIe, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_PCIE_1X2:
|
||||
result = "1 PCIe, 2 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_PCIE_1X4:
|
||||
result = "1 PCIe, 4 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_PCIE_1X8:
|
||||
result = "1 PCIe, 8 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_PCIE_1X16:
|
||||
result = "1 PCIe, 16 lanes";
|
||||
break;
|
||||
|
||||
case BDK_QLM_MODE_SATA_4X1:
|
||||
result = "4 SATA, one lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_SATA_2X1:
|
||||
result = "2 SATA, one lane each";
|
||||
break;
|
||||
|
||||
case BDK_QLM_MODE_ILK:
|
||||
result = "Interlaken";
|
||||
break;
|
||||
case BDK_QLM_MODE_SGMII_4X1:
|
||||
result = "4 SGMII, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_SGMII_2X1:
|
||||
result = "2 SGMII, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_SGMII_1X1:
|
||||
result = "1 SGMII, 1 lane";
|
||||
break;
|
||||
case BDK_QLM_MODE_XAUI_1X4:
|
||||
result = "1 XAUI, 4 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_RXAUI_2X2:
|
||||
result = "2 RXAUI, 2 lanes each";
|
||||
break;
|
||||
case BDK_QLM_MODE_RXAUI_1X2:
|
||||
result = "1 RXAUI, 2 lanes each";
|
||||
break;
|
||||
case BDK_QLM_MODE_OCI:
|
||||
result = "Cavium Coherent Processor Interconnect";
|
||||
break;
|
||||
case BDK_QLM_MODE_XFI_4X1:
|
||||
result = "4 XFI, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_XFI_2X1:
|
||||
result = "2 XFI, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_XFI_1X1:
|
||||
result = "1 XFI, 1 lane";
|
||||
break;
|
||||
case BDK_QLM_MODE_XLAUI_1X4:
|
||||
result = "1 XLAUI, 4 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_10G_KR_4X1:
|
||||
result = "4 10GBASE-KR, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_10G_KR_2X1:
|
||||
result = "2 10GBASE-KR, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_10G_KR_1X1:
|
||||
result = "1 10GBASE-KR, 1 lane";
|
||||
break;
|
||||
case BDK_QLM_MODE_40G_KR4_1X4:
|
||||
result = "1 40GBASE-KR4, 4 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_QSGMII_4X1:
|
||||
result = "4 QSGMII, 1 lane";
|
||||
break;
|
||||
case BDK_QLM_MODE_25G_4X1:
|
||||
result = "4 25G, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_25G_2X1:
|
||||
result = "2 25G, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_50G_2X2:
|
||||
result = "2 50G, 2 lanes each";
|
||||
break;
|
||||
case BDK_QLM_MODE_50G_1X2:
|
||||
result = "1 50G, 2 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_100G_1X4:
|
||||
result = "1 100G, 4 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_25G_KR_4X1:
|
||||
result = "4 25G, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_25G_KR_2X1:
|
||||
result = "2 25G, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_50G_KR_2X2:
|
||||
result = "2 50G, 2 lanes each";
|
||||
break;
|
||||
case BDK_QLM_MODE_50G_KR_1X2:
|
||||
result = "1 50G, 2 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_100G_KR4_1X4:
|
||||
result = "1 100G, 4 lanes";
|
||||
break;
|
||||
case BDK_QLM_MODE_USXGMII_4X1:
|
||||
result = "4 USXGMII, 1 lane each";
|
||||
break;
|
||||
case BDK_QLM_MODE_USXGMII_2X1:
|
||||
result = "2 USXGMII, 1 lane each";
|
||||
break;
|
||||
|
||||
case BDK_QLM_MODE_LAST:
|
||||
break; /* fallthrough error */
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int bdk_qlm_measure_clock(bdk_node_t node, int qlm)
|
||||
{
|
||||
int ref_clock = __bdk_qlm_measure_refclock(node, qlm);
|
||||
BDK_TRACE(QLM, "N%d.QLM%d: Ref clock %d Hz\n", node, qlm, ref_clock);
|
||||
|
||||
return ref_clock;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the QLM's clock source.
|
||||
*
|
||||
* @param node Node to use in a Numa setup
|
||||
* @param qlm QLM to configure
|
||||
* @param clk Clock source for QLM
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_qlm_set_clock(bdk_node_t node, int qlm, bdk_qlm_clock_t clk)
|
||||
{
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
|
||||
{
|
||||
int sel;
|
||||
int com1;
|
||||
switch (clk)
|
||||
{
|
||||
case BDK_QLM_CLK_COMMON_0:
|
||||
sel = 1;
|
||||
com1 = 0;
|
||||
break;
|
||||
case BDK_QLM_CLK_COMMON_1:
|
||||
sel = 1;
|
||||
com1 = 1;
|
||||
break;
|
||||
case BDK_QLM_CLK_EXTERNAL:
|
||||
sel = 0;
|
||||
com1 = 0;
|
||||
break;
|
||||
default:
|
||||
bdk_warn("Unrecognized clock mode %d for QLM%d on node %d.\n",
|
||||
clk, qlm, node);
|
||||
return -1;
|
||||
}
|
||||
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_REFCLK_SEL(qlm),
|
||||
c.s.com_clk_sel = sel;
|
||||
c.s.use_com1 = com1);
|
||||
}
|
||||
else
|
||||
{
|
||||
int cclksel;
|
||||
switch (clk)
|
||||
{
|
||||
case BDK_QLM_CLK_COMMON_0:
|
||||
cclksel = 0;
|
||||
break;
|
||||
case BDK_QLM_CLK_COMMON_1:
|
||||
cclksel = 1;
|
||||
break;
|
||||
case BDK_QLM_CLK_COMMON_2:
|
||||
cclksel = 2;
|
||||
break;
|
||||
case BDK_QLM_CLK_EXTERNAL:
|
||||
cclksel = 3;
|
||||
break;
|
||||
default:
|
||||
bdk_warn("Unrecognized clock mode %d for QLM%d on node %d.\n",
|
||||
clk, qlm, node);
|
||||
return -1;
|
||||
}
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERNX_COMMON_REFCLK_BCFG(qlm),
|
||||
c.s.pwdn = (clk == BDK_QLM_CLK_EXTERNAL) ? 0 : 1;
|
||||
c.s.cclksel = cclksel);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display an eye diagram for the given QLM lane. The eye data can be in "eye", or
|
||||
* captured during the call if "eye" is NULL.
|
||||
*
|
||||
* @param node Node to use in numa setup
|
||||
* @param qlm QLM to use
|
||||
* @param qlm_lane Which lane
|
||||
* @param format Display format. 0 = raw, 1 = Color ASCII
|
||||
* @param eye Eye data to display, or NULL if the data should be captured.
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_qlm_eye_display(bdk_node_t node, int qlm, int qlm_lane, int format, const bdk_qlm_eye_t *eye)
|
||||
{
|
||||
int result;
|
||||
int need_free = 0;
|
||||
if (eye == NULL)
|
||||
{
|
||||
bdk_qlm_eye_t *eye_data = malloc(sizeof(bdk_qlm_eye_t));
|
||||
if (eye_data == NULL)
|
||||
{
|
||||
bdk_error("Failed to allocate space for eye\n");
|
||||
return -1;
|
||||
}
|
||||
if (bdk_qlm_eye_capture(node, qlm, qlm_lane, eye_data))
|
||||
return -1;
|
||||
eye = eye_data;
|
||||
}
|
||||
|
||||
/* Calculate the max eye width */
|
||||
int eye_area = 0;
|
||||
int eye_width = 0;
|
||||
for (int y = 0; y < eye->height; y++)
|
||||
{
|
||||
int width = 0;
|
||||
for (int x = 0; x < eye->width; x++)
|
||||
{
|
||||
if (eye->data[y][x] == 0)
|
||||
{
|
||||
width++;
|
||||
eye_area++;
|
||||
}
|
||||
}
|
||||
if (width > eye_width)
|
||||
eye_width = width;
|
||||
}
|
||||
|
||||
/* Calculate the max eye height */
|
||||
int eye_height = 0;
|
||||
for (int x = 0; x < eye->width; x++)
|
||||
{
|
||||
int height = 0;
|
||||
for (int y = 0; y < eye->height; y++)
|
||||
{
|
||||
if (eye->data[y][x] == 0)
|
||||
{
|
||||
height++;
|
||||
eye_area++;
|
||||
}
|
||||
}
|
||||
if (height > eye_height)
|
||||
eye_height = height;
|
||||
}
|
||||
|
||||
printf("\nEye Diagram for Node %d, QLM %d, Lane %d\n", node, qlm, qlm_lane);
|
||||
|
||||
if (format == 0) /* Raw */
|
||||
{
|
||||
for (int y = 0; y < eye->height; y++)
|
||||
{
|
||||
for (int x = 0; x < eye->width; x++)
|
||||
printf("%u\t", eye->data[y][x]);
|
||||
printf("\n");
|
||||
}
|
||||
result = 0;
|
||||
}
|
||||
else
|
||||
result = -1;
|
||||
|
||||
if (need_free)
|
||||
free((void*)eye);
|
||||
return result;
|
||||
}
|
1117
src/vendorcode/cavium/bdk/libbdk-hal/bdk-sata.c
Normal file
1117
src/vendorcode/cavium/bdk/libbdk-hal/bdk-sata.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,318 +0,0 @@
|
||||
/***********************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;
|
||||
}
|
683
src/vendorcode/cavium/bdk/libbdk-hal/bdk-usb.c
Normal file
683
src/vendorcode/cavium/bdk/libbdk-hal/bdk-usb.c
Normal file
@ -0,0 +1,683 @@
|
||||
/***********************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>
|
||||
#include <libbdk-arch/bdk-csrs-usbdrd.h>
|
||||
#include <libbdk-arch/bdk-csrs-usbh.h>
|
||||
#include <libbdk-hal/bdk-usb.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
if BDK_REQUIRE() needs it */
|
||||
BDK_REQUIRE_DEFINE(USB);
|
||||
|
||||
/**
|
||||
* Write to DWC3 indirect debug control register
|
||||
*
|
||||
* @param node Node to write to
|
||||
* @param usb_port USB port to write to
|
||||
* @param val 32bit value to write
|
||||
*/
|
||||
static void write_cr_dbg_cfg(bdk_node_t node, int usb_port, uint64_t val)
|
||||
{
|
||||
if (!CAVIUM_IS_MODEL(CAVIUM_CN88XX))
|
||||
BDK_CSR_WRITE(node, BDK_USBDRDX_UCTL_PORTX_CR_DBG_CFG(usb_port, 0), val);
|
||||
else
|
||||
BDK_CSR_WRITE(node, BDK_USBHX_UCTL_PORTX_CR_DBG_CFG(usb_port, 0), val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll the DWC3 internal status until the ACK bit matches a desired value. Return
|
||||
* the final status.
|
||||
*
|
||||
* @param node Node to query
|
||||
* @param usb_port USB port to query
|
||||
* @param desired_ack
|
||||
* Desired ACK bit state
|
||||
*
|
||||
* @return Final status with ACK at correct state
|
||||
*/
|
||||
static bdk_usbdrdx_uctl_portx_cr_dbg_status_t get_cr_dbg_status(bdk_node_t node, int usb_port, int desired_ack)
|
||||
{
|
||||
const int TIMEOUT = 1000000; /* 1 sec */
|
||||
bdk_usbdrdx_uctl_portx_cr_dbg_status_t status;
|
||||
if (!CAVIUM_IS_MODEL(CAVIUM_CN88XX))
|
||||
{
|
||||
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_USBDRDX_UCTL_PORTX_CR_DBG_STATUS(usb_port, 0), ack, ==, desired_ack, TIMEOUT))
|
||||
{
|
||||
BDK_TRACE(USB_XHCI, "N%d.USB%d: Timeout waiting for indirect ACK\n", node, usb_port);
|
||||
status.u = -1;
|
||||
}
|
||||
else
|
||||
status.u = BDK_CSR_READ(node, BDK_USBDRDX_UCTL_PORTX_CR_DBG_STATUS(usb_port, 0));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_USBHX_UCTL_PORTX_CR_DBG_STATUS(usb_port, 0), ack, ==, desired_ack, TIMEOUT))
|
||||
{
|
||||
BDK_TRACE(USB_XHCI, "N%d.USB%d: Timeout waiting for indirect ACK\n", node, usb_port);
|
||||
status.u = -1;
|
||||
}
|
||||
else
|
||||
status.u = BDK_CSR_READ(node, BDK_USBHX_UCTL_PORTX_CR_DBG_STATUS(usb_port, 0));
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an indirect read of an internal register inside the DWC3 usb block
|
||||
*
|
||||
* @param node Node to read
|
||||
* @param usb_port USB port to read
|
||||
* @param addr Indirect register address
|
||||
*
|
||||
* @return Value of the indirect register
|
||||
*/
|
||||
static uint32_t dwc3_uphy_indirect_read(bdk_node_t node, int usb_port, uint32_t addr)
|
||||
{
|
||||
bdk_usbdrdx_uctl_portx_cr_dbg_cfg_t dbg_cfg;
|
||||
bdk_usbdrdx_uctl_portx_cr_dbg_status_t status;
|
||||
|
||||
/* See the CSR description for USBHX_UCTL_PORTX_CR_DBG_CFG, which describes
|
||||
the steps implemented by this function */
|
||||
|
||||
dbg_cfg.u = 0;
|
||||
dbg_cfg.s.data_in = addr;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
dbg_cfg.s.cap_addr = 1;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
status = get_cr_dbg_status(node, usb_port, 1);
|
||||
if (status.u == (uint64_t)-1)
|
||||
return 0xffffffff;
|
||||
|
||||
write_cr_dbg_cfg(node, usb_port, 0);
|
||||
get_cr_dbg_status(node, usb_port, 0);
|
||||
|
||||
dbg_cfg.u = 0;
|
||||
dbg_cfg.s.read = 1;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
status = get_cr_dbg_status(node, usb_port, 1);
|
||||
|
||||
write_cr_dbg_cfg(node, usb_port, 0);
|
||||
get_cr_dbg_status(node, usb_port, 0);
|
||||
|
||||
return status.s.data_out;
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform an indirect write of an internal register inside the DWC3 usb block
|
||||
*
|
||||
* @param node Node to write
|
||||
* @param usb_port USB port to write
|
||||
* @param addr Indirect register address
|
||||
* @param value Value for write
|
||||
*/
|
||||
static void dwc3_uphy_indirect_write(bdk_node_t node, int usb_port, uint32_t addr, uint16_t value)
|
||||
{
|
||||
bdk_usbdrdx_uctl_portx_cr_dbg_cfg_t dbg_cfg;
|
||||
|
||||
/* See the CSR description for USBHX_UCTL_PORTX_CR_DBG_CFG, which describes
|
||||
the steps implemented by this function */
|
||||
|
||||
dbg_cfg.u = 0;
|
||||
dbg_cfg.s.data_in = addr;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
dbg_cfg.s.cap_addr = 1;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
get_cr_dbg_status(node, usb_port, 1);
|
||||
|
||||
write_cr_dbg_cfg(node, usb_port, 0);
|
||||
get_cr_dbg_status(node, usb_port, 0);
|
||||
|
||||
dbg_cfg.u = 0;
|
||||
dbg_cfg.s.data_in = value;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
dbg_cfg.s.cap_data = 1;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
get_cr_dbg_status(node, usb_port, 1);
|
||||
|
||||
write_cr_dbg_cfg(node, usb_port, 0);
|
||||
get_cr_dbg_status(node, usb_port, 0);
|
||||
|
||||
dbg_cfg.u = 0;
|
||||
dbg_cfg.s.write = 1;
|
||||
write_cr_dbg_cfg(node, usb_port, dbg_cfg.u);
|
||||
|
||||
get_cr_dbg_status(node, usb_port, 1);
|
||||
|
||||
write_cr_dbg_cfg(node, usb_port, 0);
|
||||
get_cr_dbg_status(node, usb_port, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Errata USB-29206 - The USB HS PLL in all 28nm devices has a
|
||||
* design issue that may cause the VCO to lock up on
|
||||
* initialization. The Synopsys VCO is designed with an even
|
||||
* number of stages and no kick-start circuit, which makes us
|
||||
* believe that there is no question a latched up
|
||||
* (non-oscillating) state is possible. The workaround is to
|
||||
* check the PLL lock bit, which is just based on a counter and
|
||||
* will not set if the VCO is not oscillating, and if it's not
|
||||
* set do a power down/power up cycle on the PLL, which tests
|
||||
* have proven is much more likely to guarantee the VCO will
|
||||
* start oscillating. Part of the problem appears to be that
|
||||
* the normal init sequence holds the VCO in reset during the
|
||||
* power up sequence, whereas the plain power up/down sequence
|
||||
* does not, so the voltage changing may be helping the circuit
|
||||
* to oscillate.
|
||||
*
|
||||
* @param node Node to check
|
||||
* @param usb_port USB port to check
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
static int dwc3_uphy_check_pll(bdk_node_t node, int usb_port)
|
||||
{
|
||||
/* Internal indirect register that reports if the phy PLL has lock. This will
|
||||
be 1 if lock, 0 if no lock */
|
||||
const int DWC3_INT_IND_PLL_LOCK_REG = 0x200b;
|
||||
/* Internal indirect UPHY register that controls the power to the UPHY PLL */
|
||||
const int DWC3_INT_IND_UPHY_PLL_PU = 0x2012;
|
||||
/* Write enable bit for DWC3_INT_IND_PLL_POWER_CTL */
|
||||
const int DWC3_INT_IND_UPHY_PLL_PU_WE = 0x20;
|
||||
/* Power enable bit for DWC3_INT_IND_PLL_POWER_CTL */
|
||||
const int DWC3_INT_IND_UPHY_PLL_PU_POWER_EN = 0x02;
|
||||
|
||||
uint32_t pll_locked = dwc3_uphy_indirect_read(node, usb_port, DWC3_INT_IND_PLL_LOCK_REG);
|
||||
int retry_count = 0;
|
||||
while (!pll_locked)
|
||||
{
|
||||
if (retry_count >= 3)
|
||||
{
|
||||
bdk_error("N%d.USB%d: USB2 PLL failed to lock\n", node, usb_port);
|
||||
return -1;
|
||||
}
|
||||
|
||||
retry_count++;
|
||||
BDK_TRACE(USB_XHCI, "N%d.USB%d: USB2 PLL didn't lock, retry %d\n", node, usb_port, retry_count);
|
||||
|
||||
/* Turn on write enable for PLL power control */
|
||||
uint32_t pwr_val = dwc3_uphy_indirect_read(node, usb_port, DWC3_INT_IND_UPHY_PLL_PU);
|
||||
pwr_val |= DWC3_INT_IND_UPHY_PLL_PU_WE;
|
||||
dwc3_uphy_indirect_write(node, usb_port, DWC3_INT_IND_UPHY_PLL_PU, pwr_val);
|
||||
|
||||
/* Power down the PLL */
|
||||
pwr_val &= ~DWC3_INT_IND_UPHY_PLL_PU_POWER_EN;
|
||||
dwc3_uphy_indirect_write(node, usb_port, DWC3_INT_IND_UPHY_PLL_PU, pwr_val);
|
||||
bdk_wait_usec(1000);
|
||||
|
||||
/* Power on the PLL */
|
||||
pwr_val |= DWC3_INT_IND_UPHY_PLL_PU_POWER_EN;
|
||||
dwc3_uphy_indirect_write(node, usb_port, DWC3_INT_IND_UPHY_PLL_PU, pwr_val);
|
||||
bdk_wait_usec(1000);
|
||||
|
||||
/* Check for PLL Lock again */
|
||||
pll_locked = dwc3_uphy_indirect_read(node, usb_port, DWC3_INT_IND_PLL_LOCK_REG);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the clocks for USB such that it is ready for a generic XHCI driver
|
||||
*
|
||||
* @param node Node to init
|
||||
* @param usb_port Port to intialize
|
||||
* @param clock_type Type of clock connected to the usb port
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
|
||||
int bdk_usb_initialize(bdk_node_t node, int usb_port, bdk_usb_clock_t clock_type)
|
||||
{
|
||||
int is_usbdrd = !CAVIUM_IS_MODEL(CAVIUM_CN88XX);
|
||||
|
||||
/* Perform the following steps to initiate a cold reset. */
|
||||
|
||||
/* 1. Wait for all voltages to reach a stable state. Ensure the
|
||||
reference clock is up and stable.
|
||||
a. If 3.3V is up first, 0.85V must be soon after (within tens of ms). */
|
||||
|
||||
/* 2. Wait for IOI reset to deassert. */
|
||||
|
||||
/* 3. If Over Current indication and/or Port Power Control features
|
||||
are desired, program the GPIO CSRs appropriately.
|
||||
a. For Over Current Indication, select a GPIO for the input and
|
||||
program GPIO_USBH_CTL[SEL].
|
||||
b. For Port Power Control, set one of
|
||||
GPIO_BIT_CFG(0..19)[OUTPUT_SEL] = USBH_VBUS_CTRL. */
|
||||
|
||||
/* 4. Assert all resets:
|
||||
a. UPHY reset: USBDRD(0..1)_UCTL_CTL[UPHY_RST] = 1
|
||||
b. UAHC reset: USBDRD(0..1)_UCTL_CTL[UAHC_RST] = 1
|
||||
c. UCTL reset: USBDRD(0..1)_UCTL_CTL[UCTL_RST] = 1 */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.uphy_rst = 1;
|
||||
c.s.uahc_rst = 1;
|
||||
c.s.uctl_rst = 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.uphy_rst = 1;
|
||||
c.s.uahc_rst = 1;
|
||||
c.s.uctl_rst = 1);
|
||||
}
|
||||
|
||||
/* 5. Configure the controller clock:
|
||||
a. Reset the clock dividers: USBDRD(0..1)_UCTL_CTL[H_CLKDIV_RST] = 1.
|
||||
b. Select the controller clock frequency
|
||||
USBDRD(0..1)_UCTL_CTL[H_CLKDIV] = desired value.
|
||||
USBDRD(0..1)_UCTL_CTL[H_CLKDIV_EN] = 1 to enable the controller
|
||||
clock.
|
||||
Read USBDRD(0..1)_UCTL_CTL to ensure the values take effect.
|
||||
c. Deassert the controller clock divider reset: USB-
|
||||
DRD(0..1)_UCTL_CTL[H_CLKDIV_RST] = 0. */
|
||||
uint64_t sclk_rate = bdk_clock_get_rate(node, BDK_CLOCK_SCLK);
|
||||
uint64_t divider = (sclk_rate + 300000000-1) / 300000000;
|
||||
/*
|
||||
** According to HRM Rules are:
|
||||
** - clock must be below 300MHz
|
||||
** USB3 full-rate requires 150 MHz or better
|
||||
** USB3 requires 125 MHz
|
||||
** USB2 full rate requires 90 MHz
|
||||
** USB2 requires 62.5 MHz
|
||||
*/
|
||||
if (divider <= 1)
|
||||
divider = 0;
|
||||
else if (divider <= 2)
|
||||
divider = 1;
|
||||
else if (divider <= 4)
|
||||
divider = 2;
|
||||
else if (divider <= 6)
|
||||
divider = 3;
|
||||
else if (divider <= 8)
|
||||
divider = 4;
|
||||
else if (divider <= 16)
|
||||
divider = 5;
|
||||
else if (divider <= 24)
|
||||
divider = 6;
|
||||
else
|
||||
divider = 7;
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.h_clkdiv_rst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.h_clkdiv_sel = divider;
|
||||
c.s.h_clk_en = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.h_clkdiv_rst = 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.h_clkdiv_rst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.h_clkdiv_sel = divider;
|
||||
c.s.h_clk_en = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.h_clkdiv_rst = 0);
|
||||
}
|
||||
{
|
||||
static bool printit[2] = {true,true};
|
||||
if (printit[usb_port]) {
|
||||
uint64_t fr_div;
|
||||
if (divider < 5) fr_div = divider * 2;
|
||||
else fr_div = 8 * (divider - 3);
|
||||
uint64_t freq = (typeof(freq)) (sclk_rate / fr_div);
|
||||
const char *token;
|
||||
if (freq < 62500000ULL) token = "???Low";
|
||||
else if (freq < 90000000ULL) token = "USB2";
|
||||
else if (freq < 125000000ULL) token = "USB2 Full";
|
||||
else if (freq < 150000000ULL) token = "USB3";
|
||||
else token = "USB3 Full";
|
||||
BDK_TRACE(USB_XHCI, "Freq %lld - %s\n",
|
||||
(unsigned long long)freq, token);
|
||||
printit[usb_port] = false;
|
||||
}
|
||||
}
|
||||
|
||||
/* 6. Configure the strap signals in USBDRD(0..1)_UCTL_CTL.
|
||||
a. Reference clock configuration (see Table 31.2): USB-
|
||||
DRD(0..1)_UCTL_CTL[REF_CLK_FSEL, MPLL_MULTIPLIER,
|
||||
REF_CLK_SEL, REF_CLK_DIV2].
|
||||
b. Configure and enable spread-spectrum for SuperSpeed:
|
||||
USBDRD(0..1)_UCTL_CTL[SSC_RANGE, SSC_EN, SSC_REF_CLK_SEL].
|
||||
c. Enable USBDRD(0..1)_UCTL_CTL[REF_SSP_EN].
|
||||
d. Configure PHY ports:
|
||||
USBDRD(0..1)_UCTL_CTL[USB*_PORT_PERM_ATTACH, USB*_PORT_DISABLE]. */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
int ref_clk_src = 0;
|
||||
int ref_clk_fsel = 0x27;
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN83XX)) {
|
||||
if (BDK_USB_CLOCK_SS_PAD_HS_PAD != clock_type) {
|
||||
bdk_error("Node %d usb_port %d: usb clock type %d is invalid\n", node, usb_port, clock_type);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX)) {
|
||||
switch (clock_type)
|
||||
{
|
||||
default:
|
||||
bdk_error("Node %d usb_port %d: usb clock type %d is invalid\n", node, usb_port, clock_type);
|
||||
return -1;
|
||||
case BDK_USB_CLOCK_SS_PAD_HS_PAD : ref_clk_src = 2; break;
|
||||
case BDK_USB_CLOCK_SS_REF0_HS_REF0 : ref_clk_src = 0; break; /* Superspeed and high speed use DLM/QLM ref clock 0 */
|
||||
case BDK_USB_CLOCK_SS_REF1_HS_REF1 : ref_clk_src = 1; break; /* Superspeed and high speed use DLM/QLM ref clock 1 */
|
||||
case BDK_USB_CLOCK_SS_PAD_HS_PLL : ref_clk_src = 6; ref_clk_fsel = 0x7; break; /* Superspeed uses PAD clock, high speed uses PLL ref clock */
|
||||
case BDK_USB_CLOCK_SS_REF0_HS_PLL : ref_clk_src = 4; ref_clk_fsel = 0x7; break; /* Superspeed uses DLM/QLM ref clock 0, high speed uses PLL ref clock */
|
||||
case BDK_USB_CLOCK_SS_REF1_HS_PLL: ref_clk_src = 5; ref_clk_fsel =0x7; break; /* Superspeed uses DLM/QLM ref clock 1, high speed uses PLL ref clock */
|
||||
}
|
||||
}
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.ref_clk_fsel = ref_clk_fsel;
|
||||
c.s.mpll_multiplier = 0x19;
|
||||
c.s.ref_clk_sel = ref_clk_src;
|
||||
c.s.ref_clk_div2 = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.ssc_en = 1;
|
||||
c.s.ssc_ref_clk_sel = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.ref_ssp_en = 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BDK_USB_CLOCK_SS_PAD_HS_PAD != clock_type) {
|
||||
bdk_error("Node %d usb_port %d: usb clock type %d is invalid\n", node, usb_port, clock_type);
|
||||
return -1;
|
||||
}
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.ref_clk_fsel = 0x27;
|
||||
c.s.mpll_multiplier = 0;
|
||||
c.s.ref_clk_sel = 0;
|
||||
c.s.ref_clk_div2 = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.ssc_en = 1;
|
||||
c.s.ssc_ref_clk_sel = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.ref_ssp_en = 1);
|
||||
}
|
||||
/* Hardware default is for ports to be enabled and not perm attach. Don't
|
||||
change it */
|
||||
|
||||
/* 7. The PHY resets in lowest-power mode. Power up the per-port PHY
|
||||
logic by enabling the following:
|
||||
a. USBDRD(0..1)_UCTL_CTL [HS_POWER_EN] if high-speed/full-speed/low-
|
||||
speed functionality needed.
|
||||
b. USBDRD(0..1)_UCTL_CTL [SS_POWER_EN] if SuperSpeed functionality
|
||||
needed. */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.hs_power_en = 1;
|
||||
c.s.ss_power_en = 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.hs_power_en = 1;
|
||||
c.s.ss_power_en = 1);
|
||||
}
|
||||
|
||||
/* 8. Wait 10 controller-clock cycles from step 5. for controller clock
|
||||
to start and async FIFO to properly reset. */
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 9. Deassert UCTL and UAHC resets:
|
||||
a. USBDRD(0..1)_UCTL_CTL[UCTL_RST] = 0
|
||||
b. USBDRD(0..1)_UCTL_CTL[UAHC_RST] = 0
|
||||
c. [optional] For port-power control:
|
||||
- Set one of GPIO_BIT_CFG(0..47)[PIN_SEL] = USB0_VBUS_CTRLor USB1_VBUS_CTRL.
|
||||
- Set USBDRD(0..1)_UCTL_HOST_CFG[PPC_EN] = 1 and USBDRD(0..1)_UCTL_HOST_CFG[PPC_ACTIVE_HIGH_EN] = 1.
|
||||
- Wait for the external power management chip to power the VBUS.ional port-power control.
|
||||
]
|
||||
d. You will have to wait 10 controller-clock cycles before accessing
|
||||
any controller-clock-only registers. */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.uctl_rst = 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.uctl_rst = 0);
|
||||
}
|
||||
bdk_wait_usec(1);
|
||||
|
||||
int usb_gpio = bdk_config_get_int(BDK_CONFIG_USB_PWR_GPIO, node, usb_port);
|
||||
int usb_polarity = bdk_config_get_int(BDK_CONFIG_USB_PWR_GPIO_POLARITY, node, usb_port);
|
||||
if (-1 != usb_gpio) {
|
||||
int gsrc = BDK_GPIO_PIN_SEL_E_USBX_VBUS_CTRL_CN88XX(usb_port);
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX)) {
|
||||
gsrc = BDK_GPIO_PIN_SEL_E_USBX_VBUS_CTRL_CN88XX(usb_port);
|
||||
}
|
||||
else if (CAVIUM_IS_MODEL(CAVIUM_CN81XX)) {
|
||||
gsrc = BDK_GPIO_PIN_SEL_E_USBX_VBUS_CTRL_CN81XX(usb_port);
|
||||
}
|
||||
else if (CAVIUM_IS_MODEL(CAVIUM_CN83XX)) {
|
||||
gsrc = BDK_GPIO_PIN_SEL_E_USBX_VBUS_CTRL_CN83XX(usb_port);}
|
||||
else {
|
||||
bdk_error("USB_VBUS_CTRL GPIO: unknown chip model\n");
|
||||
}
|
||||
|
||||
BDK_CSR_MODIFY(c,node,BDK_GPIO_BIT_CFGX(usb_gpio),
|
||||
c.s.pin_sel = gsrc;
|
||||
c.s.pin_xor = (usb_polarity) ? 0 : 1;
|
||||
);
|
||||
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_HOST_CFG(usb_port),
|
||||
c.s.ppc_en = 1;
|
||||
c.s.ppc_active_high_en = 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_HOST_CFG(usb_port),
|
||||
c.s.ppc_en = 1;
|
||||
c.s.ppc_active_high_en = 1);
|
||||
}
|
||||
bdk_wait_usec(100000);
|
||||
}
|
||||
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.uahc_rst = 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.uahc_rst = 0);
|
||||
}
|
||||
|
||||
bdk_wait_usec(100000);
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 10. Enable conditional coprocessor clock of UCTL by writing USB-
|
||||
DRD(0..1)_UCTL_CTL[CSCLK_EN] = 1. */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
|
||||
{
|
||||
/* CN9XXX make coprocessor clock automatic */
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.cn83xx.csclk_en = 1);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.csclk_en = 1);
|
||||
}
|
||||
|
||||
/* 11. Set USBDRD(0..1)_UCTL_CTL[DRD_MODE] to 1 for device mode, 0 for
|
||||
host mode. */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.drd_mode = 0);
|
||||
}
|
||||
|
||||
/* 12. Soft reset the UPHY and UAHC logic via the UAHC controls:
|
||||
a. USBDRD(0..1)_UAHC_GUSB2PHYCFG(0)[PHYSOFTRST] = 1
|
||||
b. USBDRD(0..1)_UAHC_GUSB3PIPECTL(0)[PHYSOFTRST] = 1
|
||||
c. USBDRD(0..1)_UAHC_GCTL[CORESOFTRESET] = 1 */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UAHC_GUSB2PHYCFGX(usb_port, 0),
|
||||
c.s.physoftrst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UAHC_GUSB3PIPECTLX(usb_port, 0),
|
||||
c.s.physoftrst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UAHC_GCTL(usb_port),
|
||||
c.s.coresoftreset = 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UAHC_GUSB2PHYCFGX(usb_port, 0),
|
||||
c.s.physoftrst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UAHC_GUSB3PIPECTLX(usb_port, 0),
|
||||
c.s.physoftrst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UAHC_GCTL(usb_port),
|
||||
c.s.coresoftreset = 1);
|
||||
}
|
||||
|
||||
/* 13. Program USBDRD(0..1)_UAHC_GCTL[PRTCAPDIR] to 0x2 for device mode
|
||||
or 0x1 for host mode. */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UAHC_GCTL(usb_port),
|
||||
c.s.prtcapdir = 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UAHC_GCTL(usb_port),
|
||||
c.s.prtcapdir = 1);
|
||||
}
|
||||
|
||||
/* 14. Wait 10us after step 13. for the PHY to complete its reset. */
|
||||
bdk_wait_usec(10);
|
||||
|
||||
/* 15. Deassert UPHY reset: USBDRD(0..1)_UCTL_CTL[UPHY_RST] = 0. */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UCTL_CTL(usb_port),
|
||||
c.s.uphy_rst = 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UCTL_CTL(usb_port),
|
||||
c.s.uphy_rst = 0);
|
||||
}
|
||||
|
||||
/* 16. Wait for at least 45us after step 15. for UPHY to output
|
||||
stable PHYCLOCK. */
|
||||
bdk_wait_usec(45);
|
||||
|
||||
/* Workround Errata USB-29206 */
|
||||
if (dwc3_uphy_check_pll(node, usb_port))
|
||||
return -1;
|
||||
|
||||
/* 17. Initialize any other strap signals necessary and make sure they
|
||||
propagate by reading back the last register written.
|
||||
a. UCTL
|
||||
USBDRD(0..1)_UCTL_PORT0_CFG_*[*_TUNE]
|
||||
USBDRD(0..1)_UCTL_PORT0_CFG_*[PCS_*]
|
||||
USBDRD(0..1)_UCTL_PORT0_CFG_*[LANE0_TX_TERM_OFFSET]
|
||||
USBDRD(0..1)_UCTL_PORT0_CFG_*[TX_VBOOST_LVL]
|
||||
USBDRD(0..1)_UCTL__PORT0_CFG_*[LOS_BIAS]
|
||||
USBDRD(0..1)_UCTL_HOST_CFG
|
||||
USBDRD(0..1)_UCTL_SHIM_CFG
|
||||
b. UAHC: only the following UAHC registers are accessible during
|
||||
CoreSoftReset.
|
||||
USBDRD(0..1)_UAHC_GCTL
|
||||
USBDRD(0..1)_UAHC_GUCTL
|
||||
USBDRD(0..1)_UAHC_GSTS
|
||||
USBDRD(0..1)_UAHC_GUID
|
||||
USBDRD(0..1)_UAHC_GUSB2PHYCFG(0)
|
||||
USBDRD(0..1)_UAHC_GUSB3PIPECTL(0) */
|
||||
|
||||
/* 18. Release soft reset the UPHY and UAHC logic via the UAHC controls:
|
||||
a. USBDRD(0..1)_UAHC_GUSB2PHYCFG(0)[PHYSOFTRST] = 0
|
||||
b. USBDRD(0..1)_UAHC_GUSB3PIPECTL(0)[PHYSOFTRST] = 0
|
||||
c. USBDRD(0..1)_UAHC_GCTL[CORESOFTRESET] = 0 */
|
||||
if (is_usbdrd)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UAHC_GUSB2PHYCFGX(usb_port, 0),
|
||||
c.s.physoftrst = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UAHC_GUSB3PIPECTLX(usb_port, 0),
|
||||
c.s.physoftrst = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBDRDX_UAHC_GCTL(usb_port),
|
||||
c.s.coresoftreset = 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UAHC_GUSB2PHYCFGX(usb_port, 0),
|
||||
c.s.physoftrst = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UAHC_GUSB3PIPECTLX(usb_port, 0),
|
||||
c.s.physoftrst = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_USBHX_UAHC_GCTL(usb_port),
|
||||
c.s.coresoftreset = 0);
|
||||
}
|
||||
|
||||
/* 19. Configure the remaining UAHC_G* registers as needed, including
|
||||
any that were not configured in step 17.-b. */
|
||||
|
||||
/* 20. Initialize the USB controller:
|
||||
a. To initialize the UAHC as a USB host controller, the application
|
||||
should perform the steps described in the xHCI specification
|
||||
(UAHC_X* registers). The xHCI sequence starts with poll for a 0 in
|
||||
USBDRD(0..1)_UAHC_USBSTS[CNR].
|
||||
b. To initialize the UAHC as a device, the application should TBD. The
|
||||
device initiation sequence starts with a device soft reset by
|
||||
setting USBDRD(0..1)_UAHC_DCTL[CSFTRST] = 1 and wait for a read
|
||||
operation to return 0. */
|
||||
return 0;
|
||||
}
|
721
src/vendorcode/cavium/bdk/libbdk-hal/device/bdk-device.c
Normal file
721
src/vendorcode/cavium/bdk/libbdk-hal/device/bdk-device.c
Normal file
@ -0,0 +1,721 @@
|
||||
/***********************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 <string.h>
|
||||
#include "libbdk-arch/bdk-csrs-ap.h"
|
||||
#include "libbdk-arch/bdk-csrs-pccpf.h"
|
||||
#include "libbdk-hal/bdk-ecam.h"
|
||||
#include "libbdk-hal/device/bdk-device.h"
|
||||
#include "libbdk-hal/bdk-config.h"
|
||||
#include "libbdk-driver/bdk-driver.h"
|
||||
#include "libbdk-hal/bdk-utils.h"
|
||||
|
||||
static struct bdk_driver_s *driver_list = NULL;
|
||||
|
||||
#define DEVICE_GROW 64
|
||||
static bdk_device_t *device_list = NULL;
|
||||
static int device_list_count = 0;
|
||||
static int device_list_max = 0;
|
||||
|
||||
/**
|
||||
* Called to register a new driver with the bdk-device system. Drivers are probed
|
||||
* and initialized as device are found for them. If devices have already been
|
||||
* added before the driver was registered, the driver will be probed and
|
||||
* initialized before this function returns.
|
||||
*
|
||||
* @param driver Driver functions
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_device_add_driver(struct bdk_driver_s *driver)
|
||||
{
|
||||
driver->next = driver_list;
|
||||
driver_list = driver;
|
||||
BDK_TRACE(DEVICE, "Added driver for %08x\n", driver->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup the correct driver for a device
|
||||
*
|
||||
* @param device Device to lookup
|
||||
*
|
||||
* @return Driver, or NULL on failure
|
||||
*/
|
||||
static const bdk_driver_t *lookup_driver(const bdk_device_t *device)
|
||||
{
|
||||
const bdk_driver_t *drv = driver_list;
|
||||
while (drv)
|
||||
{
|
||||
if (drv->id == device->id)
|
||||
return drv;
|
||||
drv = drv->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate the fields of a new device from the ECAM
|
||||
*
|
||||
* @param device Device to populate
|
||||
*/
|
||||
static void populate_device(bdk_device_t *device)
|
||||
{
|
||||
/* The default name may be replaced by the driver with something easier to read */
|
||||
snprintf(device->name, sizeof(device->name), "N%d.E%d:%d:%d.%d",
|
||||
device->node, device->ecam, device->bus, device->dev, device->func);
|
||||
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Populating device\n", device->name);
|
||||
|
||||
/* Get the current chip ID and pass. We'll need this to fill in version
|
||||
information for the device */
|
||||
bdk_ap_midr_el1_t midr_el1;
|
||||
BDK_MRS(MIDR_EL1, midr_el1.u);
|
||||
|
||||
/* PCCPF_XXX_VSEC_SCTL[RID] with the revision of the chip,
|
||||
read from fuses */
|
||||
BDK_CSR_DEFINE(sctl, BDK_PCCPF_XXX_VSEC_SCTL);
|
||||
sctl.u = bdk_ecam_read32(device, BDK_PCCPF_XXX_VSEC_SCTL);
|
||||
sctl.s.rid = midr_el1.s.revision | (midr_el1.s.variant<<3);
|
||||
sctl.s.node = device->node; /* Program node bits */
|
||||
sctl.s.ea = bdk_config_get_int(BDK_CONFIG_PCIE_EA);
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
|
||||
sctl.s.ea = 0; /* EA is not supported on CN88XX pass 1.x */
|
||||
else
|
||||
sctl.s.ea = bdk_config_get_int(BDK_CONFIG_PCIE_EA);
|
||||
bdk_ecam_write32(device, BDK_PCCPF_XXX_VSEC_SCTL, sctl.u);
|
||||
|
||||
/* Read the Device ID */
|
||||
device->id = bdk_ecam_read32(device, BDK_PCCPF_XXX_ID);
|
||||
|
||||
/* Read the Device Type so we know how to handle BARs */
|
||||
bdk_pccpf_xxx_clsize_t clsize;
|
||||
clsize.u = bdk_ecam_read32(device, BDK_PCCPF_XXX_CLSIZE);
|
||||
int isbridge = (clsize.s.hdrtype & 0x7f) == 1;
|
||||
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Device ID: 0x%08x%s\n", device->name, device->id,
|
||||
(isbridge) ? " (Bridge)" : "");
|
||||
|
||||
/* Loop through all the BARs */
|
||||
int max_bar = (isbridge) ? BDK_PCCPF_XXX_BAR0U : BDK_PCCPF_XXX_BAR4U;
|
||||
int bar = BDK_PCCPF_XXX_BAR0L;
|
||||
unsigned guess_instance = 0;
|
||||
while (bar <= max_bar)
|
||||
{
|
||||
int bar_index = (bar - BDK_PCCPF_XXX_BAR0L) / 8;
|
||||
/* Read the BAR address and config bits [3:0] */
|
||||
uint64_t address = bdk_ecam_read32(device, bar);
|
||||
int ismem = !(address & 1); /* Bit 0: 0 = mem, 1 = io */
|
||||
int is64 = ismem && (address & 4); /* Bit 2: 0 = 32 bit, 1 = 64 bit if mem */
|
||||
/* Bit 3: 1 = Is prefetchable. We on't care for now */
|
||||
|
||||
/* All internal BARs should be 64 bit. Skip if BAR isn't as that means
|
||||
it is using Enhanced Allocation (EA) */
|
||||
if (!is64)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: BAR%d Disabled or EA bar skipped (0x%08llx)\n", device->name, bar_index, address);
|
||||
bar += 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the upper part of 64bit BARs */
|
||||
address |= (uint64_t)bdk_ecam_read32(device, bar + 4) << 32;
|
||||
|
||||
/* Write the bits to determine the size */
|
||||
bdk_ecam_write32(device, bar, -1);
|
||||
bdk_ecam_write32(device, bar + 4, -1);
|
||||
uint64_t size_mask = (uint64_t)bdk_ecam_read32(device, bar + 4) << 32;
|
||||
size_mask |= bdk_ecam_read32(device, bar);
|
||||
/* Make sure the node bits are correct in the address */
|
||||
address = (address & ~(3UL << 44)) | ((uint64_t)device->node << 44);
|
||||
/* Restore address value */
|
||||
bdk_ecam_write32(device, bar, address);
|
||||
bdk_ecam_write32(device, bar + 4, address >> 32);
|
||||
|
||||
/* Convert the size into a power of 2 bits */
|
||||
int size_bits = bdk_dpop(~size_mask | 0xf);
|
||||
if (size_bits <= 4)
|
||||
size_bits = 0;
|
||||
|
||||
/* Store the BAR info */
|
||||
device->bar[bar_index].address = address & ~0xfull;
|
||||
device->bar[bar_index].size2 = size_bits;
|
||||
device->bar[bar_index].flags = address & 0xf;
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: BAR%d 0x%llx/%d flags=0x%x\n",
|
||||
device->name, bar_index, device->bar[bar_index].address,
|
||||
device->bar[bar_index].size2, device->bar[bar_index].flags);
|
||||
/* Move to the next BAR */
|
||||
bar += 8;
|
||||
}
|
||||
|
||||
/* Walk the PCI capabilities looking for PCIe support and EA headers */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Walking PCI capabilites\n", device->name);
|
||||
int has_pcie = 0;
|
||||
bdk_pccpf_xxx_cap_ptr_t cap_ptr;
|
||||
cap_ptr.u = bdk_ecam_read32(device, BDK_PCCPF_XXX_CAP_PTR);
|
||||
int cap_loc = cap_ptr.s.cp;
|
||||
while (cap_loc)
|
||||
{
|
||||
uint32_t cap = bdk_ecam_read32(device, cap_loc);
|
||||
int cap_id = cap & 0xff;
|
||||
int cap_next = (cap >> 8) & 0xff;
|
||||
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: PCI Capability 0x%02x ID:0x%02x Next:0x%02x\n",
|
||||
device->name, cap_loc, cap_id, cap_next);
|
||||
|
||||
if (cap_id == 0x10)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: PCIe\n", device->name);
|
||||
has_pcie = 1;
|
||||
}
|
||||
else if (cap_id == 0x01)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: PCI Power Management Interface\n", device->name);
|
||||
/* Do nothing for now */
|
||||
}
|
||||
else if (cap_id == 0x11)
|
||||
{
|
||||
bdk_pccpf_xxx_msix_cap_hdr_t msix_cap_hdr;
|
||||
bdk_pccpf_xxx_msix_table_t msix_table;
|
||||
bdk_pccpf_xxx_msix_pba_t msix_pba;
|
||||
msix_cap_hdr.u = cap;
|
||||
msix_table.u = bdk_ecam_read32(device, cap_loc + 4);
|
||||
msix_pba.u = bdk_ecam_read32(device, cap_loc + 8);
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: MSI-X Entries:%d, Func Mask:%d, Enable:%d\n",
|
||||
device->name, msix_cap_hdr.s.msixts + 1, msix_cap_hdr.s.funm, msix_cap_hdr.s.msixen);
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Table BAR%d, Offset:0x%x\n",
|
||||
device->name, msix_table.s.msixtbir, msix_table.s.msixtoffs * 8);
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: PBA BAR%d, Offset:0x%x\n",
|
||||
device->name, msix_pba.s.msixpbir, msix_pba.s.msixpoffs * 8);
|
||||
}
|
||||
else if (cap_id == 0x05)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: MSI\n", device->name);
|
||||
/* Do nothing for now */
|
||||
}
|
||||
else if (cap_id == 0x14)
|
||||
{
|
||||
bdk_pccpf_xxx_ea_cap_hdr_t ea_cap_hdr;
|
||||
ea_cap_hdr.u = cap;
|
||||
cap_loc += 4;
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Enhanced Allocation, %d entries\n",
|
||||
device->name, ea_cap_hdr.s.num_entries);
|
||||
if (isbridge)
|
||||
{
|
||||
cap = bdk_ecam_read32(device, cap_loc);
|
||||
cap_loc += 4;
|
||||
int fixed_secondary_bus = cap & 0xff;
|
||||
int fixed_subordinate_bus = cap & 0xff;
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Fixed Secondary Bus:0x%02x Fixed Subordinate Bus:0x%02x\n",
|
||||
device->name, fixed_secondary_bus, fixed_subordinate_bus);
|
||||
}
|
||||
for (int entry = 0; entry < ea_cap_hdr.s.num_entries; entry++)
|
||||
{
|
||||
union bdk_pcc_ea_entry_s ea_entry;
|
||||
memset(&ea_entry, 0, sizeof(ea_entry));
|
||||
uint32_t *ptr = (uint32_t *)&ea_entry;
|
||||
*ptr++ = bdk_ecam_read32(device, cap_loc);
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
/* For big endian we actually need the previous data
|
||||
shifted 32 bits */
|
||||
*ptr = ptr[-1];
|
||||
#endif
|
||||
asm volatile ("" ::: "memory"); /* Needed by gcc 5.0 to detect aliases on ea_entry */
|
||||
int entry_size = ea_entry.s.entry_size;
|
||||
for (int i = 0; i < entry_size; i++)
|
||||
{
|
||||
*ptr++ = bdk_ecam_read32(device, cap_loc + 4*i + 4);
|
||||
}
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
/* The upper and lower 32bits need to be swapped */
|
||||
ea_entry.u[0] = (ea_entry.u[0] >> 32) | (ea_entry.u[0] << 32);
|
||||
ea_entry.u[1] = (ea_entry.u[1] >> 32) | (ea_entry.u[1] << 32);
|
||||
ea_entry.u[2] = (ea_entry.u[2] >> 32) | (ea_entry.u[2] << 32);
|
||||
#endif
|
||||
asm volatile ("" ::: "memory"); /* Needed by gcc 5.0 to detect aliases on ea_entry */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Enable:%d Writeable:%d Secondary Prop:0x%02x Primary Prop:0x%02x BEI:%d Size:%d\n",
|
||||
device->name, ea_entry.s.enable, ea_entry.s.w, ea_entry.s.sec_prop, ea_entry.s.pri_prop, ea_entry.s.bei, ea_entry.s.entry_size);
|
||||
if (ea_entry.s.entry_size > 0)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Base:0x%08x 64bit:%d\n",
|
||||
device->name, ea_entry.s.basel << 2, ea_entry.s.base64);
|
||||
}
|
||||
if (ea_entry.s.entry_size > 1)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: MaxOffset:0x%08x 64bit:%d\n",
|
||||
device->name, (ea_entry.s.offsetl << 2) | 3, ea_entry.s.offset64);
|
||||
}
|
||||
if (ea_entry.s.entry_size > 2)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: BaseUpper:0x%08x\n",
|
||||
device->name, ea_entry.s.baseh);
|
||||
}
|
||||
if (ea_entry.s.entry_size > 3)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: MaxOffsetUpper:0x%08x\n",
|
||||
device->name, ea_entry.s.offseth);
|
||||
}
|
||||
if (ea_entry.s.enable)
|
||||
{
|
||||
uint64_t base = (uint64_t)ea_entry.s.baseh << 32;
|
||||
base |= (uint64_t)ea_entry.s.basel << 2;
|
||||
/* Make sure the node bits are correct in the address */
|
||||
base = (base & ~(3UL << 44)) | ((uint64_t)device->node << 44);
|
||||
uint64_t offset = (uint64_t)ea_entry.s.offseth << 32;
|
||||
offset |= ((uint64_t)ea_entry.s.offsetl << 2) | 3;
|
||||
switch (ea_entry.s.bei)
|
||||
{
|
||||
case 0: /* BAR 0 */
|
||||
case 2: /* BAR 1 */
|
||||
case 4: /* BAR 2 */
|
||||
{
|
||||
int bar_index = ea_entry.s.bei/2;
|
||||
device->bar[bar_index].address = base;
|
||||
device->bar[bar_index].size2 = bdk_dpop(offset);
|
||||
device->bar[bar_index].flags = ea_entry.s.base64 << 2;
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Updated BAR%d 0x%llx/%d flags=0x%x\n",
|
||||
device->name, bar_index, device->bar[bar_index].address,
|
||||
device->bar[bar_index].size2, device->bar[bar_index].flags);
|
||||
if (0 == ea_entry.s.bei) {
|
||||
/* PEMs eg PCIEEP and PCIERC do not have instance id
|
||||
** We can calculate it for PCIERC based on BAR0 allocation.
|
||||
** PCIEEP will be dropped by probe
|
||||
*/
|
||||
guess_instance = (device->bar[bar_index].address >> 24) & 7;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 9: /* SR-IOV BAR 0 */
|
||||
case 11: /* SR-IOV BAR 1 */
|
||||
case 13: /* SR-IOV BAR 2 */
|
||||
// FIXME
|
||||
break;
|
||||
}
|
||||
}
|
||||
cap_loc += ea_entry.s.entry_size * 4 + 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown PCI capability */
|
||||
bdk_warn("%s: ECAM device unknown PCI capability 0x%x\n", device->name, cap_id);
|
||||
}
|
||||
cap_loc = cap_next;
|
||||
}
|
||||
|
||||
/* Walk the PCIe capabilities looking for instance header */
|
||||
if (has_pcie)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Walking PCIe capabilites\n", device->name);
|
||||
cap_loc = 0x100;
|
||||
while (cap_loc)
|
||||
{
|
||||
uint32_t cap = bdk_ecam_read32(device, cap_loc);
|
||||
int cap_id = cap & 0xffff;
|
||||
int cap_ver = (cap >> 16) & 0xf;
|
||||
int cap_next = cap >> 20;
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: PCIe Capability 0x%03x ID:0x%04x Version:0x%x Next:0x%03x\n",
|
||||
device->name, cap_loc, cap_id, cap_ver, cap_next);
|
||||
if (cap_id == 0xe)
|
||||
{
|
||||
/* ARI. Do nothing for now */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: ARI\n", device->name);
|
||||
}
|
||||
else if (cap_id == 0xb)
|
||||
{
|
||||
/* Vendor specific*/
|
||||
int vsec_id = bdk_ecam_read32(device, cap_loc + 4);
|
||||
int vsec_id_id = vsec_id & 0xffff;
|
||||
int vsec_id_rev = (vsec_id >> 16) & 0xf;
|
||||
int vsec_id_len = vsec_id >> 20;
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Vendor ID: 0x%04x Rev: 0x%x Size 0x%03x\n",
|
||||
device->name, vsec_id_id, vsec_id_rev, vsec_id_len);
|
||||
switch (vsec_id_id)
|
||||
{
|
||||
case 0x0001: /* RAS Data Path */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Vendor RAS Data Path\n", device->name);
|
||||
break;
|
||||
|
||||
case 0x0002: /* RAS DES */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Vendor RAS DES\n", device->name);
|
||||
break;
|
||||
|
||||
case 0x00a0: /* Cavium common */
|
||||
case 0x00a1: /* Cavium CN88XX */
|
||||
case 0x00a2: /* Cavium CN81XX */
|
||||
case 0x00a3: /* Cavium CN83XX */
|
||||
if ((vsec_id_rev == 1) || (vsec_id_rev == 2))
|
||||
{
|
||||
int vsec_ctl = bdk_ecam_read32(device, cap_loc + 8);
|
||||
int vsec_ctl_inst_num = vsec_ctl & 0xff;
|
||||
int vsec_ctl_subnum = (vsec_ctl >> 8) & 0xff;
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Cavium Instance: 0x%02x Static Bus: 0x%02x\n",
|
||||
device->name, vsec_ctl_inst_num, vsec_ctl_subnum);
|
||||
int vsec_sctl = bdk_ecam_read32(device, cap_loc + 12);
|
||||
int vsec_sctl_rid = (vsec_sctl >> 16) & 0xff;
|
||||
if (vsec_id_rev == 2)
|
||||
{
|
||||
int vsec_sctl_pi = (vsec_sctl >> 24) & 0xff; /* Only in Rev 2 */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Revision ID: 0x%02x Programming Interface: 0x%02x\n",
|
||||
device->name, vsec_sctl_rid, vsec_sctl_pi);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Revision ID: 0x%02x\n",
|
||||
device->name, vsec_sctl_rid);
|
||||
}
|
||||
/* Record the device instance */
|
||||
device->instance = vsec_ctl_inst_num;
|
||||
}
|
||||
else
|
||||
{
|
||||
bdk_warn("%s: ECAM device Unknown Cavium extension revision\n", device->name);
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* Unknown Vendor extension */
|
||||
bdk_warn("%s: ECAM device unknown vendor extension ID 0x%x\n", device->name, vsec_id_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (cap_id == 0x10)
|
||||
{
|
||||
/* Single Root I/O Virtualization (SR-IOV) */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: SR-IOV\n", device->name);
|
||||
/* Loop through all the SR-IOV BARs */
|
||||
bar = cap_loc + 0x24;
|
||||
while (bar <= (cap_loc + 0x3c))
|
||||
{
|
||||
int bar_index = (bar - 0x24 - cap_loc) / 8;
|
||||
/* Read the BAR address and config bits [3:0] */
|
||||
uint64_t address = bdk_ecam_read32(device, bar);
|
||||
int ismem = !(address & 1); /* Bit 0: 0 = mem, 1 = io */
|
||||
int is64 = ismem && (address & 4); /* Bit 2: 0 = 32 bit, 1 = 64 bit if mem */
|
||||
/* Bit 3: 1 = Is prefetchable. We don't care for now */
|
||||
|
||||
/* All internal BARs should be 64 bit. Skip if BAR isn't as that means
|
||||
it is using Enhanced Allocation (EA) */
|
||||
if (!is64)
|
||||
{
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: SR-IOV BAR%d Disabled or EA bar skipped (0x%08llx)\n", device->name, bar_index, address);
|
||||
bar += 8;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Get the upper part of 64bit BARs */
|
||||
address |= (uint64_t)bdk_ecam_read32(device, bar + 4) << 32;
|
||||
|
||||
/* Write the bits to determine the size */
|
||||
bdk_ecam_write32(device, bar, -1);
|
||||
bdk_ecam_write32(device, bar + 4, -1);
|
||||
uint64_t size_mask = (uint64_t)bdk_ecam_read32(device, bar + 4) << 32;
|
||||
size_mask |= bdk_ecam_read32(device, bar);
|
||||
/* Make sure the node bits are correct in the address */
|
||||
address = (address & ~(3UL << 44)) | ((uint64_t)device->node << 44);
|
||||
/* Restore address value */
|
||||
bdk_ecam_write32(device, bar, address);
|
||||
bdk_ecam_write32(device, bar + 4, address >> 32);
|
||||
|
||||
/* Convert the size into a power of 2 bits */
|
||||
int size_bits = bdk_dpop(size_mask | 0xf);
|
||||
if (size_bits <= 4)
|
||||
size_bits = 0;
|
||||
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: SR-IOV BAR%d 0x%llx/%d flags=0x%llx\n",
|
||||
device->name, bar_index, address & ~0xfull,
|
||||
size_bits, address & 0xf);
|
||||
/* Move to the next BAR */
|
||||
bar += 8;
|
||||
}
|
||||
}
|
||||
else if (cap_id == 0x01)
|
||||
{
|
||||
/* Advanced Error Reporting Capability */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Advanced Error Reporting\n", device->name);
|
||||
}
|
||||
else if (cap_id == 0x19)
|
||||
{
|
||||
/* Secondary PCI Express Extended Capability */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Secondary PCI Express Extended\n", device->name);
|
||||
}
|
||||
else if (cap_id == 0x15)
|
||||
{
|
||||
/* PCI Express Resizable BAR (RBAR) Capability */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: PCI Express Resizable BAR (RBAR)\n", device->name);
|
||||
}
|
||||
else if (cap_id == 0x0d)
|
||||
{
|
||||
/* Extended access control := ACS Extended Capability */
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: ACS\n", device->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Unknown PCIe capability */
|
||||
bdk_warn("%s: ECAM device unknown PCIe capability 0x%x\n", device->name, cap_id);
|
||||
}
|
||||
cap_loc = cap_next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bdk_error("%s: ECAM device didn't have a PCIe capability\n", device->name);
|
||||
}
|
||||
if (BDK_NO_DEVICE_INSTANCE == device->instance) {
|
||||
device->instance = guess_instance;
|
||||
}
|
||||
BDK_TRACE(DEVICE_SCAN, "%s: Device populated\n", device->name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the ECAM code whan a new device is detected in the system
|
||||
*
|
||||
* @param node Node the ECAM is on
|
||||
* @param ecam ECAM the device is on
|
||||
* @param bus Bus number for the device
|
||||
* @param dev Device number
|
||||
* @param func Function number
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_device_add(bdk_node_t node, int ecam, int bus, int dev, int func)
|
||||
{
|
||||
if (device_list_count == device_list_max)
|
||||
{
|
||||
int grow = device_list_max + DEVICE_GROW;
|
||||
bdk_device_t *tmp = malloc(grow * sizeof(bdk_device_t));
|
||||
if (!tmp)
|
||||
memcpy(tmp, device_list, device_list_max * sizeof(bdk_device_t));
|
||||
free(device_list);
|
||||
if (tmp == NULL)
|
||||
{
|
||||
bdk_error("bdk-device: Failed to allocate space for device\n");
|
||||
return -1;
|
||||
}
|
||||
device_list = tmp;
|
||||
device_list_max = grow;
|
||||
}
|
||||
|
||||
bdk_device_t *device = &device_list[device_list_count++];
|
||||
memset(device, 0, sizeof(*device));
|
||||
|
||||
device->state = BDK_DEVICE_STATE_NOT_PROBED;
|
||||
device->node = node;
|
||||
device->ecam = ecam;
|
||||
device->bus = bus;
|
||||
device->dev = dev;
|
||||
device->func = func;
|
||||
device->instance = BDK_NO_DEVICE_INSTANCE;
|
||||
populate_device(device);
|
||||
|
||||
const bdk_driver_t *drv = lookup_driver(device);
|
||||
if (drv)
|
||||
BDK_TRACE(DEVICE, "%s: Added device\n", device->name);
|
||||
else
|
||||
BDK_TRACE(DEVICE, "%s: Added device without driver (0x%08x)\n", device->name, device->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Rename a device. Called by driver to give devices friendly names
|
||||
*
|
||||
* @param device Device to rename
|
||||
* @param format Printf style format string
|
||||
*/
|
||||
void bdk_device_rename(bdk_device_t *device, const char *format, ...)
|
||||
{
|
||||
char tmp[sizeof(device->name)];
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
vsnprintf(tmp, sizeof(tmp), format, args);
|
||||
va_end(args);
|
||||
tmp[sizeof(tmp) - 1] = 0;
|
||||
BDK_TRACE(DEVICE, "%s: Renamed to %s\n", device->name, tmp);
|
||||
strcpy(device->name, tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by the ECAM code once all devices have been added
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_device_init(void)
|
||||
{
|
||||
/* Probe all devices first */
|
||||
for (int i = 0; i < device_list_count; i++)
|
||||
{
|
||||
bdk_device_t *dev = &device_list[i];
|
||||
const bdk_driver_t *drv = lookup_driver(dev);
|
||||
if (drv == NULL)
|
||||
continue;
|
||||
if (dev->state == BDK_DEVICE_STATE_NOT_PROBED)
|
||||
{
|
||||
BDK_TRACE(DEVICE, "%s: Probing\n", dev->name);
|
||||
if (drv->probe(dev))
|
||||
{
|
||||
BDK_TRACE(DEVICE, "%s: Probe failed\n", dev->name);
|
||||
dev->state = BDK_DEVICE_STATE_PROBE_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_TRACE(DEVICE, "%s: Probe complete\n", dev->name);
|
||||
dev->state = BDK_DEVICE_STATE_PROBED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do init() after all the probes. See comments in top of bdk-device.h */
|
||||
for (int i = 0; i < device_list_count; i++)
|
||||
{
|
||||
bdk_device_t *dev = &device_list[i];
|
||||
const bdk_driver_t *drv = lookup_driver(dev);
|
||||
if (drv == NULL)
|
||||
continue;
|
||||
if (dev->state == BDK_DEVICE_STATE_PROBED)
|
||||
{
|
||||
BDK_TRACE(DEVICE, "%s: Initializing\n", dev->name);
|
||||
if (drv->init(dev))
|
||||
{
|
||||
BDK_TRACE(DEVICE, "%s: Init failed\n", dev->name);
|
||||
dev->state = BDK_DEVICE_STATE_INIT_FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_TRACE(DEVICE, "%s: Init complete\n", dev->name);
|
||||
dev->state = BDK_DEVICE_STATE_READY;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lookup a device by ECAM ID and internal instance number. This can be used by
|
||||
* one device to find a handle to an associated device. For example, PKI would
|
||||
* use this function to get a handle to the FPA.
|
||||
*
|
||||
* @param node Node to lookup for
|
||||
* @param id ECAM ID
|
||||
* @param instance Cavium internal instance number
|
||||
*
|
||||
* @return Device pointer, or NULL if the device isn't found
|
||||
*/
|
||||
const bdk_device_t *bdk_device_lookup(bdk_node_t node, uint32_t id, int instance)
|
||||
{
|
||||
for (int i = 0; i < device_list_count; i++)
|
||||
{
|
||||
bdk_device_t *dev = &device_list[i];
|
||||
if ((dev->node == node) && (dev->id == id) && (dev->instance == instance))
|
||||
return dev;
|
||||
}
|
||||
BDK_TRACE(DEVICE, "No device found for node %d, ID %08x, instance %d\n", node, id, instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read from a device BAR
|
||||
*
|
||||
* @param device Device to read from
|
||||
* @param bar Which BAR to read from (0-3)
|
||||
* @param size Size of the read
|
||||
* @param offset Offset into the BAR
|
||||
*
|
||||
* @return Value read
|
||||
*/
|
||||
uint64_t bdk_bar_read(const bdk_device_t *device, int bar, int size, uint64_t offset)
|
||||
{
|
||||
uint64_t address = offset & bdk_build_mask(device->bar[bar/2].size2);
|
||||
address += device->bar[bar/2].address;
|
||||
if (offset+size > (1ULL << device->bar[bar/2].size2)) {
|
||||
/* The CSR address passed in offset doesn't contain the node number. Copy it
|
||||
from the BAR address */
|
||||
offset |= address & (0x3ull << 44);
|
||||
if (address != offset)
|
||||
bdk_fatal("BAR read address 0x%llx doesn't match CSR address 0x%llx\n", address, offset);
|
||||
}
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
return bdk_read64_uint8(address);
|
||||
case 2:
|
||||
return bdk_le16_to_cpu(bdk_read64_uint16(address));
|
||||
case 4:
|
||||
return bdk_le32_to_cpu(bdk_read64_uint32(address));
|
||||
case 8:
|
||||
return bdk_le64_to_cpu(bdk_read64_uint64(address));
|
||||
}
|
||||
bdk_fatal("%s: Unexpected read size %d\n", device->name, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write to a device BAR
|
||||
*
|
||||
* @param device Device to write to
|
||||
* @param bar Which BAR to read from (0-3)
|
||||
* @param size Size of the write
|
||||
* @param offset Offset into the BAR
|
||||
* @param value Value to write
|
||||
*/
|
||||
void bdk_bar_write(const bdk_device_t *device, int bar, int size, uint64_t offset, uint64_t value)
|
||||
{
|
||||
uint64_t address = offset & bdk_build_mask(device->bar[bar/2].size2);
|
||||
address += device->bar[bar/2].address;
|
||||
if (offset+size > (1ULL << device->bar[bar/2].size2)) {
|
||||
/* The CSR address passed in offset doesn't contain the node number. Copy it
|
||||
from the BAR address */
|
||||
offset |= address & (0x3ull << 44);
|
||||
if (address != offset)
|
||||
bdk_fatal("BAR write address 0x%llx doesn't match CSR address 0x%llx\n", address, offset);
|
||||
}
|
||||
switch (size)
|
||||
{
|
||||
case 1:
|
||||
bdk_write64_uint8(address, value);
|
||||
return;
|
||||
case 2:
|
||||
bdk_write64_uint16(address, bdk_cpu_to_le16(value));
|
||||
return;
|
||||
case 4:
|
||||
bdk_write64_uint32(address, bdk_cpu_to_le32(value));
|
||||
return;
|
||||
case 8:
|
||||
bdk_write64_uint64(address, bdk_cpu_to_le64(value));
|
||||
return;
|
||||
}
|
||||
bdk_fatal("%s: Unexpected write size %d\n", device->name, size);
|
||||
}
|
115
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-marvell.c
Normal file
115
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-marvell.c
Normal file
@ -0,0 +1,115 @@
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2016 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-hal/bdk-mdio.h>
|
||||
#include <libbdk-hal/bdk-qlm.h>
|
||||
#include <libbdk-hal/if/bdk-if.h>
|
||||
|
||||
/**
|
||||
* Setup marvell PHYs
|
||||
* This function sets up one port in a marvell 88E1512 in SGMII mode
|
||||
*/
|
||||
static void setup_marvell_phy(bdk_node_t node, int mdio_bus, int mdio_addr)
|
||||
{
|
||||
int phy_status = 0;
|
||||
|
||||
BDK_TRACE(PHY, "%s In SGMII mode for Marvell PHY 88E1512\n", __FUNCTION__);
|
||||
/* Switch to Page 18 */
|
||||
phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 22, 18);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 22);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
|
||||
/* Change the Phy System mode from RGMII(default hw reset mode) to SGMII */
|
||||
phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 20, 1);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
|
||||
/* Requires a Software reset */
|
||||
phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 20, 0x8001);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 20);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
|
||||
/* Change the Page back to 0 */
|
||||
phy_status = bdk_mdio_write(node, mdio_bus, mdio_addr, 22, 0);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 22);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 17);
|
||||
if (phy_status < 0)
|
||||
return;
|
||||
}
|
||||
|
||||
int bdk_if_phy_marvell_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr)
|
||||
{
|
||||
BDK_TRACE(PHY,"In %s\n",__FUNCTION__);
|
||||
|
||||
/* Check if the PHY is marvell PHY we expect */
|
||||
int phy_status = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1);
|
||||
if (phy_status != 0x0141)
|
||||
return 0;
|
||||
|
||||
/* Check that the GSER mode is SGMII */
|
||||
/* Switch the marvell PHY to the correct mode */
|
||||
bdk_qlm_modes_t qlm_mode = bdk_qlm_get_mode(node, qlm);
|
||||
|
||||
BDK_TRACE(PHY,"%s: QLM:%d QLM_MODE:%d\n",__FUNCTION__, qlm, qlm_mode);
|
||||
|
||||
if ((qlm_mode != BDK_QLM_MODE_SGMII_1X1) &&
|
||||
(qlm_mode != BDK_QLM_MODE_SGMII_2X1))
|
||||
return 0;
|
||||
|
||||
BDK_TRACE(PHY,"%s: Detected Marvell Phy in SGMII mode\n", __FUNCTION__);
|
||||
for (int port = 0; port < 2; port++)
|
||||
{
|
||||
setup_marvell_phy(node, mdio_bus, phy_addr + port);
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,224 @@
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2016 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-hal/if/bdk-if.h>
|
||||
#include <libbdk-hal/bdk-mdio.h>
|
||||
#include <libbdk-hal/bdk-qlm.h>
|
||||
|
||||
#define VSC_PHY_STD_PAGE (0x0)
|
||||
#define VSC_PHY_EXT1_PAGE (0x1)
|
||||
#define VSC_PHY_EXT2_PAGE (0x2)
|
||||
#define VSC_PHY_EXT3_PAGE (0x3)
|
||||
#define VSC_PHY_EXT4_PAGE (0x4)
|
||||
#define VSC_PHY_GPIO_PAGE (0x10)
|
||||
#define VSC_PHY_TEST_PAGE (0x2A30)
|
||||
#define VSC_PHY_TR_PAGE (0x52B5)
|
||||
|
||||
const uint16_t init_script_rev_a[] = {
|
||||
// Op, Page, Reg, Value, Mask
|
||||
// 0, 1, 2, 3, 4
|
||||
// --, ------, ----, ------, -----
|
||||
0, 0x0000, 0x1f, 0x0000, 0xffff,
|
||||
1, 0x0000, 0x16, 0x0001, 0x0001,
|
||||
0, 0x0001, 0x1f, 0x2A30, 0xffff,
|
||||
1, 0x2A30, 0x08, 0x8000, 0x8000,
|
||||
0, 0x2A30, 0x1f, 0x52B5, 0xffff,
|
||||
0, 0x52B5, 0x12, 0x0068, 0xffff,
|
||||
0, 0x52B5, 0x11, 0x8980, 0xffff,
|
||||
0, 0x52B5, 0x10, 0x8f90, 0xffff,
|
||||
0, 0x52B5, 0x12, 0x0000, 0xffff,
|
||||
0, 0x52B5, 0x11, 0x0003, 0xffff,
|
||||
0, 0x52B5, 0x10, 0x8796, 0xffff,
|
||||
0, 0x52B5, 0x12, 0x0050, 0xffff,
|
||||
0, 0x52B5, 0x11, 0x100f, 0xffff,
|
||||
0, 0x52B5, 0x10, 0x87fa, 0xffff,
|
||||
0, 0x52B5, 0x1f, 0x2A30, 0xffff,
|
||||
1, 0x2A30, 0x08, 0x0000, 0x8000,
|
||||
0, 0x2A30, 0x1f, 0x0000, 0xffff,
|
||||
1, 0x0000, 0x16, 0x0000, 0x0001,
|
||||
0xf, 0xffff, 0xff, 0xffff, 0xffff
|
||||
};
|
||||
|
||||
static void wr_masked(bdk_node_t node, int mdio_bus, int phy_addr, int reg, int value, int mask)
|
||||
{
|
||||
int nmask = ~mask;
|
||||
int old = bdk_mdio_read(node, mdio_bus, phy_addr, reg);
|
||||
int vmask = value & mask;
|
||||
int newv = old & nmask;
|
||||
newv = newv | vmask;
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, reg, newv);
|
||||
}
|
||||
static void vitesse_init_script(bdk_node_t node, int mdio_bus, int phy_addr)
|
||||
{
|
||||
const uint16_t *ptr;
|
||||
uint16_t reg_addr;
|
||||
uint16_t reg_val;
|
||||
uint16_t mask;
|
||||
|
||||
BDK_TRACE(PHY,"In %s\n",__FUNCTION__);
|
||||
BDK_TRACE(PHY,"Loading init script for VSC8514\n");
|
||||
|
||||
ptr = init_script_rev_a;
|
||||
while (*ptr != 0xf)
|
||||
{
|
||||
reg_addr = *(ptr+2);
|
||||
reg_val = *(ptr+3);
|
||||
mask = *(ptr+4);
|
||||
ptr+=5;
|
||||
if (mask != 0xffff)
|
||||
{
|
||||
wr_masked(node, mdio_bus, phy_addr, reg_addr,reg_val,mask);
|
||||
}
|
||||
else
|
||||
{
|
||||
bdk_mdio_write(node,mdio_bus,phy_addr,reg_addr,reg_val);
|
||||
}
|
||||
}
|
||||
|
||||
BDK_TRACE(PHY,"loading init script is done\n");
|
||||
|
||||
}
|
||||
|
||||
static void vitesse_program(bdk_node_t node, int mdio_bus, int phy_addr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup Vitesse PHYs
|
||||
* This function sets up one port in a Vitesse VSC8514
|
||||
*/
|
||||
static void setup_vitesse_phy(bdk_node_t node, int mdio_bus, int phy_addr)
|
||||
{
|
||||
/*setting MAC if*/
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_GPIO_PAGE);
|
||||
wr_masked(node,mdio_bus,phy_addr, 19, 0x4000, 0xc000);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x80e0);
|
||||
|
||||
/*Setting media if*/
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_STD_PAGE);
|
||||
// Reg23, 10:8 Select copper, CAT5 copper only
|
||||
wr_masked(node,mdio_bus,phy_addr, 23, 0x0000, 0x0700);
|
||||
|
||||
// Reg0:15, soft Reset
|
||||
wr_masked(node,mdio_bus,phy_addr, 0, 0x8000, 0x8000);
|
||||
int time_out = 100;
|
||||
while (time_out && bdk_mdio_read(node,mdio_bus,phy_addr, 0) & 0x8000)
|
||||
{
|
||||
bdk_wait_usec(100000);
|
||||
time_out--;
|
||||
}
|
||||
|
||||
if (time_out == 0)
|
||||
{
|
||||
BDK_TRACE(PHY,"setting PHY TIME OUT\n");
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_TRACE(PHY,"Setting a phy port is done\n");
|
||||
}
|
||||
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_EXT3_PAGE);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 16, 0x80);
|
||||
// Select main registers
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, VSC_PHY_STD_PAGE);
|
||||
|
||||
/*
|
||||
|
||||
if (LOOP_INTERNAL)
|
||||
{
|
||||
reg0 = bdk_mdio_read(node, mdio_bus, phy_addr, 0);
|
||||
reg0 = bdk_insert(reg0, 1, 14, 1);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 0, reg0);
|
||||
}
|
||||
|
||||
// Far end loopback (External side)
|
||||
if (LOOP_EXTERNAL)
|
||||
{
|
||||
reg23 = bdk_mdio_read(node, mdio_bus, phy_addr, 23);
|
||||
reg23 = bdk_insert(reg23, 1, 3, 1);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 23, reg23);
|
||||
}
|
||||
|
||||
|
||||
// Dump registers
|
||||
if (false)
|
||||
{
|
||||
printf("\nVitesse PHY register dump, PHY address %d, mode %s\n",
|
||||
phy_addr, (qsgmii) ? "QSGMII" : "SGMII");
|
||||
int phy_addr = 4;
|
||||
for (int reg_set = 0; reg_set <= 0x10; reg_set += 0x10)
|
||||
{
|
||||
printf("\nDump registers with reg[31]=0x%x\n", reg_set);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, reg_set);
|
||||
for (int reg=0; reg < 32; reg++)
|
||||
printf("reg[%02d]=0x%x\n", reg, bdk_mdio_read(node, mdio_bus, phy_addr, reg));
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
//static void vetesse_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr)
|
||||
int bdk_if_phy_vsc8514_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr)
|
||||
{
|
||||
/* Check if the PHY is Vetesse PHY we expect */
|
||||
int phy_status_1 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1);
|
||||
int phy_status_2 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID2);
|
||||
if (phy_status_1 != 0x0007 || phy_status_2 != 0x0670)
|
||||
{
|
||||
bdk_error("The PHY on this board is NOT VSC8514.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Check that the GSER mode is SGMII or QSGMII */
|
||||
bdk_qlm_modes_t qlm_mode = bdk_qlm_get_mode(node, qlm);
|
||||
if (qlm_mode != BDK_QLM_MODE_QSGMII_4X1)
|
||||
return -1;
|
||||
|
||||
vitesse_init_script(node, mdio_bus, phy_addr);
|
||||
vitesse_program(node, mdio_bus, phy_addr);
|
||||
|
||||
/* VSC8514 just support QSGMII */
|
||||
for (int port = 0; port < 4; port++)
|
||||
setup_vitesse_phy(node, mdio_bus, phy_addr + port);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
395
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-xfi.c
Normal file
395
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse-xfi.c
Normal file
@ -0,0 +1,395 @@
|
||||
/***********************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-hal/if/bdk-if.h>
|
||||
#include <libbdk-hal/bdk-mdio.h>
|
||||
#include <libbdk-hal/bdk-twsi.h>
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
* if BDK_REQUIRE() needs it */
|
||||
//BDK_REQUIRE(TWSI);
|
||||
BDK_REQUIRE_DEFINE(XFI);
|
||||
|
||||
/*
|
||||
Rate Select Settings
|
||||
Mode State : 6/8
|
||||
Rate Select State : 0
|
||||
RSEL1 : 0
|
||||
RSEL0 : 0
|
||||
Ref Clock Gen(MHz) : 156.25
|
||||
Data Rate(Gbps) : 10.3125
|
||||
Description : 10 GbE
|
||||
|
||||
|
||||
Data Rate Detection Configuration Registers
|
||||
|
||||
Mode Pin Settings:
|
||||
Mode State : 0
|
||||
MODE1 : 0
|
||||
MODE0 : 0
|
||||
Mode : Two-wire serial interface mode
|
||||
|
||||
LOS Pin Strap Mode Settings
|
||||
Mode State : 2/6/8
|
||||
State : 4
|
||||
LOS1 : Float
|
||||
LOS0 : Float
|
||||
LOS Amplitude(mVpp) : 20
|
||||
LOS Hysteresis(dB) : 2
|
||||
|
||||
Input Equalization Retimer Mode Settings
|
||||
Mode State : 6/8
|
||||
EQ State : 0
|
||||
EQ1 : 0
|
||||
EQ0 : 0
|
||||
EQ(dB) : Auto
|
||||
DFE : Auto
|
||||
Comment : Full Auto
|
||||
|
||||
Input Equalization Re-Driver Mode Settings
|
||||
Mode State :
|
||||
EQ State : 0
|
||||
EQ1 : 0
|
||||
EQ0 : 0
|
||||
EQ(dB) : Auto
|
||||
DFE : APowered Down
|
||||
Comment : Analog EQ Only
|
||||
|
||||
|
||||
|
||||
Output De-Emphasis Retimer Mode Settings
|
||||
Mode State : 6/8
|
||||
DE State : 3
|
||||
TX1 : Float
|
||||
TX0 : 0
|
||||
PRE c(-1) mA : -1
|
||||
MAIN c( 0) mA : 15
|
||||
POST c(+1) mA : 4
|
||||
DC Amplitude(mV): 500
|
||||
De-Emphasis(dB) : -6.02
|
||||
Comment :
|
||||
|
||||
|
||||
Output De-Emphasis Re-Driver Mode Settings
|
||||
Mode State : 2
|
||||
DE State : 3
|
||||
TX1 : Float
|
||||
TX0 : 0
|
||||
Frequency(Gbps) : 10.3125
|
||||
DC Amplitude(mV): 600
|
||||
De-Emphasis(dB) : 4
|
||||
Comment : 10GbE
|
||||
|
||||
|
||||
*/
|
||||
|
||||
static int debug = 0;
|
||||
|
||||
#define xfi_printf(fmt, args...) \
|
||||
do { \
|
||||
if(debug == 1){ \
|
||||
printf(fmt, ##args); \
|
||||
} \
|
||||
} while(0)
|
||||
|
||||
|
||||
int bdk_xfi_vsc7224_dump(int twsi_id, int unit){
|
||||
bdk_node_t node=0;
|
||||
uint8_t dev_addr=0x10 + unit;
|
||||
uint16_t internal_addr=0x7F;
|
||||
int num_bytes=2;
|
||||
int ia_width_bytes=1;
|
||||
uint64_t data=0;
|
||||
int p, i;
|
||||
uint64_t result[0x100] = {0};
|
||||
|
||||
uint64_t pagenum[9] = {0x00, 0x01, 0x02, 0x03, 0x20, 0x21, 0x30, 0x31, 0x40};
|
||||
|
||||
for(p=0; p < (sizeof(pagenum)/sizeof(pagenum[0])); p++){
|
||||
data = pagenum[p];
|
||||
bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, data);
|
||||
for(i=0x80; i<=0xFF; i++){
|
||||
result[i] = 0x00;
|
||||
result[i] = bdk_twsix_read_ia(node, twsi_id, dev_addr, (uint16_t)i, num_bytes, ia_width_bytes);
|
||||
}
|
||||
for(i=0x80; i<=0xFF; i++){
|
||||
if(i==0x80){
|
||||
printf("\npage_%02X[0x100] = {\n", (uint8_t)pagenum[p]);
|
||||
}
|
||||
if(i % 8 == 0){
|
||||
printf("/* 0x%2X */", i);
|
||||
}
|
||||
printf(" 0x%04X,", (uint16_t)result[i]);
|
||||
if(i==0xFF){
|
||||
printf("};");
|
||||
}
|
||||
if((i+1) % 8 == 0){
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* XFI ReTimer/ReDriver Mode Settings */
|
||||
|
||||
/*
|
||||
power down regs:
|
||||
Page Reg Position Mask val RegFieldName
|
||||
0x00 0x89 b07 0x0080 1 PD_INBUF
|
||||
0x00 0x8A b10 0x0400 1 PD_DFECRU
|
||||
0x00 0x8A b01 0x0002 1 PD_DFE
|
||||
0x00 0x8A b00 0x0001 1 PD_DFEADAPT
|
||||
0x00 0x97 b15 0x8000 1 ASYN_SYNN
|
||||
0x00 0x97 b09 0x0200 1 PD_OD
|
||||
0x00 0xA0 b11 0x0800 1 PD_LOS
|
||||
0x00 0xA4 b15 0x8000 1 PD_CH
|
||||
0x00 0xB5 b07 0x0080 1 PD_INBUF
|
||||
0x00 0xB9 b15 0x8000 1 ASYN_SYNN
|
||||
0x00 0xB9 b09 0x0200 1 PD_OD
|
||||
0x00 0xBF b07 0x0080 1 PD_INBUF
|
||||
0x00 0xF0 b15 0x8000 1 ASYN_SYNN
|
||||
0x00 0xF0 b09 0x0200 1 PD_OD
|
||||
0x00 0xF6 b07 0x0080 1 PD_INBUF
|
||||
0x00 0xFA b15 0x8000 1 ASYN_SYNN
|
||||
0x00 0xFA b09 0x0200 1 PD_OD
|
||||
*/
|
||||
struct regmap{
|
||||
short int page;
|
||||
unsigned char reg;
|
||||
unsigned short int retimer;
|
||||
unsigned short int redriver;
|
||||
};
|
||||
|
||||
/* This table only applies to SFF8104 */
|
||||
struct regmap xfiregmap[64] = {
|
||||
//CH 0
|
||||
{0x00, 0x84, 0x0800, 0x0000}, //EQTABLE_DCOFF0 (0n_84)
|
||||
{0x00, 0x8A, 0x7000, 0x0400}, //DFECRU_CTRL (0n_8A)
|
||||
{0x00, 0x8B, 0x4060, 0x0000}, //DFECRU_CFVF_CFAP (0n_8B)
|
||||
{0x00, 0x90, 0xDE85, 0x0000}, //DFECRU_DFEAUTO (0n_90)
|
||||
{0x00, 0x91, 0x2020, 0x0000}, //DFECRU_BTMX_BFMX (0n_91)
|
||||
{0x00, 0x92, 0x0860, 0x0000}, //DFECRU_DXMX_TRMX (0n_92)
|
||||
{0x00, 0x93, 0x6000, 0x0000}, //DFECRU_TRMN_ERRI (0n_93)
|
||||
{0x00, 0x94, 0x0001, 0x0000}, //DFECRU_DFEMODE (0n_94)
|
||||
{0x00, 0x95, 0x0008, 0x0000}, //DFECRU_RATESEL (0n_95)
|
||||
{0x00, 0x97, 0x0000, 0x8080}, //OUTDRVCTRL (0n_97)
|
||||
{0x00, 0x99, 0x001E, 0x0014}, //KR_MAINTAP (0n_99)
|
||||
{0x00, 0x9A, 0x000B, 0x0000}, //KR_PRETAP (0n_9A)
|
||||
{0x00, 0x9B, 0x0010, 0x0000}, //KR_POSTTAP (0n_9B)
|
||||
{0x00, 0x9E, 0x03E8, 0x07D0}, //LOSASSRT (0n_9E)
|
||||
{0x00, 0x9F, 0x04EA, 0x09D5}, //LOSDASSRT (0n_9F)
|
||||
{0x00, 0xB2, 0x0888, 0x0000}, //NA
|
||||
|
||||
//CH 1
|
||||
{0x01, 0x84, 0x0800, 0x0000},
|
||||
{0x01, 0x8A, 0x7000, 0x0400},
|
||||
{0x01, 0x8B, 0x4060, 0x0000},
|
||||
{0x01, 0x90, 0xDE85, 0x0000},
|
||||
{0x01, 0x91, 0x2020, 0x0000},
|
||||
{0x01, 0x92, 0x0860, 0x0000},
|
||||
{0x01, 0x93, 0x6000, 0x0000},
|
||||
{0x01, 0x94, 0x0001, 0x0000},
|
||||
{0x01, 0x95, 0x0008, 0x0000},
|
||||
{0x01, 0x97, 0x0000, 0x8080},
|
||||
{0x01, 0x99, 0x001E, 0x0014},
|
||||
{0x01, 0x9A, 0x000B, 0x0000},
|
||||
{0x01, 0x9B, 0x0010, 0x0000},
|
||||
{0x01, 0x9E, 0x03E8, 0x07D0},
|
||||
{0x01, 0x9F, 0x04EA, 0x09D5},
|
||||
{0x01, 0xB2, 0x0888, 0x0000},
|
||||
|
||||
//POWER_DOWN Channel 2 and 3
|
||||
{0x02, 0x8A, 0x0400, 0x0400},
|
||||
{0x02, 0xA4, 0x8000, 0x8000},
|
||||
{0x03, 0x8A, 0x0400, 0x0400},
|
||||
{0x03, 0xA4, 0x8000, 0x8000},
|
||||
|
||||
{0x30, 0x80, 0x3453, 0x0000}, //FSYNM_NVAL (3f_80)
|
||||
{0x30, 0x81, 0x00F6, 0x0000}, //FSYNFVAL_MSB (3f_81)
|
||||
{0x30, 0x82, 0x8800, 0x0000}, //FSYNFVAL_LSB (3f_82)
|
||||
{0x30, 0x83, 0x000F, 0x0000}, //FSYNRVAL_MSB (3f_83)
|
||||
{0x30, 0x84, 0xB5E0, 0x0000}, //FSYNRVAL_LSB (3f_84)
|
||||
{0x30, 0x85, 0x0000, 0x0400}, //FSYNTST (3f_85)
|
||||
|
||||
{0x40, 0x80, 0x4C00, 0x0000}, //ANMUXSEL (40_80)
|
||||
{0x40, 0x81, 0x4000, 0x0000}, //DGMUXCTRL (40_81)
|
||||
{0x40, 0x82, 0x7800, 0xC000}, //RCKINCTRL (40_82)
|
||||
{0x40, 0x84, 0x0020, 0x0000}, //CHRCKSEL (40_84)
|
||||
|
||||
{-1, 0, 0, 0},
|
||||
};
|
||||
|
||||
int bdk_vsc7224_modeset(int twsi_id, int unit, int xfi_mode){
|
||||
bdk_node_t node=0;
|
||||
uint8_t dev_addr=0x10 + unit;
|
||||
uint16_t internal_addr=0x7F;
|
||||
uint16_t page=0;
|
||||
int num_bytes=2;
|
||||
int ia_width_bytes=1;
|
||||
uint64_t data=0;
|
||||
int val=0;
|
||||
int ret = 0, r=0;
|
||||
uint16_t reg = 0;
|
||||
|
||||
if(xfi_mode==0){
|
||||
printf("XFI Mode Retimer\n");
|
||||
}else{
|
||||
printf("XFI Mode Redriver\n");
|
||||
}
|
||||
|
||||
while(xfiregmap[r].page != -1){
|
||||
page = xfiregmap[r].page;
|
||||
reg = xfiregmap[r].reg;
|
||||
if(xfi_mode==0){
|
||||
data = xfiregmap[r].retimer;
|
||||
}else{
|
||||
data = xfiregmap[r].redriver;
|
||||
}
|
||||
ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)page);
|
||||
if(ret !=0){
|
||||
printf("XFI init Error\n");
|
||||
break;
|
||||
}
|
||||
ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes, data);
|
||||
if(ret !=0){
|
||||
printf("XFI init Error\n");
|
||||
break;
|
||||
}
|
||||
val = bdk_twsix_read_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes);
|
||||
if(val == -1){
|
||||
printf("XFI Read Reg Failed @ page:reg :: %2X:%2X \n",page, reg);
|
||||
break;
|
||||
}else{
|
||||
xfi_printf(" Page: reg: data: val :: %2X:%2X:%04X:%04X\n", page, reg, (uint16_t)data, val);
|
||||
}
|
||||
r++;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int bdk_vsc7224_regmap_modeget(int twsi_id, int unit){
|
||||
bdk_node_t node=0;
|
||||
uint8_t dev_addr=0x10 + unit;
|
||||
uint16_t internal_addr=0x7F;
|
||||
uint16_t page=0;
|
||||
int num_bytes=2;
|
||||
int ia_width_bytes=1;
|
||||
//uint64_t data=0;
|
||||
uint16_t reg = 0;
|
||||
int ret = 0, r=0;
|
||||
int data;
|
||||
|
||||
printf("\n===========================================\n");
|
||||
printf("Page :Reg :Value :Retimer :Redriver\n");
|
||||
printf("===========================================\n");
|
||||
while(xfiregmap[r].page != -1){
|
||||
page = xfiregmap[r].page;
|
||||
reg = xfiregmap[r].reg;
|
||||
|
||||
ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)page);
|
||||
if(ret !=0){
|
||||
printf("XFI init Error\n");
|
||||
break;
|
||||
}
|
||||
data = bdk_twsix_read_ia(node, twsi_id, dev_addr, reg, num_bytes, ia_width_bytes);
|
||||
if(data == -1){
|
||||
printf("XFI Read Reg Failed @ page:reg :: %2X:%2X \n",page, reg);
|
||||
break;
|
||||
}
|
||||
printf(" %02X: %02X: %04X: %04X: %04X\n", page, reg, (uint16_t)data, xfiregmap[r].retimer, xfiregmap[r].redriver);
|
||||
r++;
|
||||
}
|
||||
printf("=======================================\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdk_vsc7224_wp_regs(int twsi_id, int unit, int xfi_wp){
|
||||
bdk_node_t node=0;
|
||||
uint8_t dev_addr=0x10 + unit;
|
||||
uint16_t internal_addr=0x7E;
|
||||
uint16_t data=0x0000;
|
||||
int num_bytes=2;
|
||||
int ia_width_bytes=1;
|
||||
int ret =0;
|
||||
|
||||
if(xfi_wp == 1){
|
||||
data = 0x0000;
|
||||
}else{
|
||||
data = 0xFFFF;
|
||||
}
|
||||
|
||||
ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)data);
|
||||
if(ret !=0){
|
||||
printf("XFI VSC7224 Write Protect Error\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdk_vsc7224_set_reg(int twsi_id, int unit, int page, int reg, int val){
|
||||
bdk_node_t node=0;
|
||||
uint8_t dev_addr=0x10 + unit;
|
||||
uint16_t internal_addr = reg;
|
||||
int num_bytes=2;
|
||||
int ia_width_bytes=1;
|
||||
int ret=0;
|
||||
|
||||
xfi_printf(" Unit: Page: reg: val :: %02x:%2X:%2X:%04X\n", unit, page, reg, val & 0xFFFF);
|
||||
ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, 0x7F, num_bytes, ia_width_bytes, (uint64_t)(page & 0xFF));
|
||||
if (ret) {
|
||||
printf("XFI VSC7224 TWSI Set Page Register Error\n");
|
||||
}
|
||||
|
||||
ret = bdk_twsix_write_ia(node, twsi_id, dev_addr, internal_addr, num_bytes, ia_width_bytes, (uint64_t)(val & 0xFFFF));
|
||||
if (ret) {
|
||||
printf("XFI VSC7224 TWSI Set Register Error\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int bdk_vsc7224_debug(int _debug){
|
||||
debug =_debug;
|
||||
return 0;
|
||||
}
|
372
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse.c
Normal file
372
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy-vetesse.c
Normal file
@ -0,0 +1,372 @@
|
||||
/***********************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-hal/if/bdk-if.h>
|
||||
#include <libbdk-hal/bdk-mdio.h>
|
||||
#include <libbdk-hal/bdk-qlm.h>
|
||||
|
||||
static bool LOOP_INTERNAL = false;
|
||||
static bool LOOP_EXTERNAL = false;
|
||||
|
||||
static uint8_t patch_arr[] = {
|
||||
0x44, 0x83, 0x02, 0x42, 0x12, 0x02, 0x44, 0x93, 0x02, 0x44,
|
||||
0xca, 0x02, 0x44, 0x4d, 0x02, 0x43, 0xef, 0xed, 0xff, 0xe5,
|
||||
0xfc, 0x54, 0x38, 0x64, 0x20, 0x70, 0x08, 0x65, 0xff, 0x70,
|
||||
0x04, 0xed, 0x44, 0x80, 0xff, 0x22, 0x8f, 0x19, 0x7b, 0xbb,
|
||||
0x7d, 0x0e, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60,
|
||||
0x03, 0x02, 0x41, 0xf9, 0xe4, 0xf5, 0x1a, 0x74, 0x01, 0x7e,
|
||||
0x00, 0xa8, 0x1a, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33,
|
||||
0xce, 0xd8, 0xf9, 0xff, 0xef, 0x55, 0x19, 0x70, 0x03, 0x02,
|
||||
0x41, 0xed, 0x85, 0x1a, 0xfb, 0x7b, 0xbb, 0xe4, 0xfd, 0xff,
|
||||
0x12, 0x3d, 0xd7, 0xef, 0x4e, 0x60, 0x03, 0x02, 0x41, 0xed,
|
||||
0xe5, 0x1a, 0x54, 0x02, 0x75, 0x1d, 0x00, 0x25, 0xe0, 0x25,
|
||||
0xe0, 0xf5, 0x1c, 0xe4, 0x78, 0xc5, 0xf6, 0xd2, 0x02, 0x12,
|
||||
0x41, 0xfa, 0x7b, 0xff, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d,
|
||||
0xd7, 0xef, 0x4e, 0x60, 0x03, 0x02, 0x41, 0xe7, 0xc2, 0x02,
|
||||
0x74, 0xc7, 0x25, 0x1a, 0xf9, 0x74, 0xe7, 0x25, 0x1a, 0xf8,
|
||||
0xe6, 0x27, 0xf5, 0x1b, 0xe5, 0x1d, 0x24, 0x5b, 0x12, 0x44,
|
||||
0x2a, 0x12, 0x3e, 0xda, 0x7b, 0xfc, 0x7d, 0x11, 0x7f, 0x07,
|
||||
0x12, 0x3d, 0xd7, 0x78, 0xcc, 0xef, 0xf6, 0x78, 0xc1, 0xe6,
|
||||
0xfe, 0xef, 0xd3, 0x9e, 0x40, 0x06, 0x78, 0xcc, 0xe6, 0x78,
|
||||
0xc1, 0xf6, 0x12, 0x41, 0xfa, 0x7b, 0xec, 0x7d, 0x12, 0x7f,
|
||||
0x07, 0x12, 0x3d, 0xd7, 0x78, 0xcb, 0xef, 0xf6, 0xbf, 0x07,
|
||||
0x06, 0x78, 0xc3, 0x76, 0x1a, 0x80, 0x1f, 0x78, 0xc5, 0xe6,
|
||||
0xff, 0x60, 0x0f, 0xc3, 0xe5, 0x1b, 0x9f, 0xff, 0x78, 0xcb,
|
||||
0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x2f, 0x80, 0x07, 0x78, 0xcb,
|
||||
0xe6, 0x85, 0x1b, 0xf0, 0xa4, 0x78, 0xc3, 0xf6, 0xe4, 0x78,
|
||||
0xc2, 0xf6, 0x78, 0xc2, 0xe6, 0xff, 0xc3, 0x08, 0x96, 0x40,
|
||||
0x03, 0x02, 0x41, 0xd1, 0xef, 0x54, 0x03, 0x60, 0x33, 0x14,
|
||||
0x60, 0x46, 0x24, 0xfe, 0x60, 0x42, 0x04, 0x70, 0x4b, 0xef,
|
||||
0x24, 0x02, 0xff, 0xe4, 0x33, 0xfe, 0xef, 0x78, 0x02, 0xce,
|
||||
0xa2, 0xe7, 0x13, 0xce, 0x13, 0xd8, 0xf8, 0xff, 0xe5, 0x1d,
|
||||
0x24, 0x5c, 0xcd, 0xe5, 0x1c, 0x34, 0xf0, 0xcd, 0x2f, 0xff,
|
||||
0xed, 0x3e, 0xfe, 0x12, 0x44, 0x6a, 0x7d, 0x11, 0x80, 0x0b,
|
||||
0x78, 0xc2, 0xe6, 0x70, 0x04, 0x7d, 0x11, 0x80, 0x02, 0x7d,
|
||||
0x12, 0x7f, 0x07, 0x12, 0x3e, 0x9a, 0x8e, 0x1e, 0x8f, 0x1f,
|
||||
0x80, 0x03, 0xe5, 0x1e, 0xff, 0x78, 0xc5, 0xe6, 0x06, 0x24,
|
||||
0xcd, 0xf8, 0xa6, 0x07, 0x78, 0xc2, 0x06, 0xe6, 0xb4, 0x1a,
|
||||
0x0a, 0xe5, 0x1d, 0x24, 0x5c, 0x12, 0x44, 0x2a, 0x12, 0x3e,
|
||||
0xda, 0x78, 0xc5, 0xe6, 0x65, 0x1b, 0x70, 0x82, 0x75, 0xdb,
|
||||
0x20, 0x75, 0xdb, 0x28, 0x12, 0x44, 0x42, 0x12, 0x44, 0x42,
|
||||
0xe5, 0x1a, 0x12, 0x44, 0x35, 0xe5, 0x1a, 0xc3, 0x13, 0x12,
|
||||
0x44, 0x35, 0x78, 0xc5, 0x16, 0xe6, 0x24, 0xcd, 0xf8, 0xe6,
|
||||
0xff, 0x7e, 0x08, 0x1e, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02,
|
||||
0xc3, 0x13, 0xd8, 0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0xf5,
|
||||
0xdb, 0xef, 0xa8, 0x06, 0x08, 0x80, 0x02, 0xc3, 0x13, 0xd8,
|
||||
0xfc, 0xfd, 0xc4, 0x33, 0x54, 0xe0, 0x44, 0x08, 0xf5, 0xdb,
|
||||
0xee, 0x70, 0xd8, 0x78, 0xc5, 0xe6, 0x70, 0xc8, 0x75, 0xdb,
|
||||
0x10, 0x02, 0x40, 0xfd, 0x78, 0xc2, 0xe6, 0xc3, 0x94, 0x17,
|
||||
0x50, 0x0e, 0xe5, 0x1d, 0x24, 0x62, 0x12, 0x42, 0x08, 0xe5,
|
||||
0x1d, 0x24, 0x5c, 0x12, 0x42, 0x08, 0x20, 0x02, 0x03, 0x02,
|
||||
0x40, 0x76, 0x05, 0x1a, 0xe5, 0x1a, 0xc3, 0x94, 0x04, 0x50,
|
||||
0x03, 0x02, 0x40, 0x3a, 0x22, 0xe5, 0x1d, 0x24, 0x5c, 0xff,
|
||||
0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x44, 0x6a, 0x22, 0xff,
|
||||
0xe5, 0x1c, 0x34, 0xf0, 0xfe, 0x12, 0x44, 0x6a, 0x22, 0xd2,
|
||||
0x00, 0x75, 0xfb, 0x03, 0xab, 0x7e, 0xaa, 0x7d, 0x7d, 0x19,
|
||||
0x7f, 0x03, 0x12, 0x3e, 0xda, 0xe5, 0x7e, 0x54, 0x0f, 0x24,
|
||||
0xf3, 0x60, 0x03, 0x02, 0x42, 0xb9, 0x12, 0x44, 0xa3, 0x12,
|
||||
0x44, 0xaa, 0xd8, 0xfb, 0xff, 0x20, 0xe2, 0x2a, 0x13, 0x92,
|
||||
0x04, 0xef, 0xa2, 0xe1, 0x92, 0x03, 0x30, 0x04, 0x1f, 0xe4,
|
||||
0xf5, 0x10, 0xe5, 0x10, 0x24, 0x17, 0xfd, 0x7b, 0x54, 0x7f,
|
||||
0x04, 0x12, 0x3d, 0xd7, 0x74, 0x25, 0x25, 0x10, 0xf8, 0xa6,
|
||||
0x07, 0x05, 0x10, 0xe5, 0x10, 0xc3, 0x94, 0x02, 0x40, 0xe4,
|
||||
0x12, 0x44, 0xa3, 0x12, 0x44, 0xaa, 0xd8, 0xfb, 0x54, 0x05,
|
||||
0x64, 0x04, 0x70, 0x27, 0x78, 0xc4, 0xe6, 0x78, 0xc6, 0xf6,
|
||||
0xe5, 0x7d, 0xff, 0x33, 0x95, 0xe0, 0xef, 0x54, 0x0f, 0x78,
|
||||
0xc4, 0xf6, 0x12, 0x42, 0xcf, 0x20, 0x04, 0x0c, 0x12, 0x44,
|
||||
0xa3, 0x12, 0x44, 0xaa, 0xd8, 0xfb, 0x13, 0x92, 0x05, 0x22,
|
||||
0xc2, 0x05, 0x22, 0x12, 0x44, 0xa3, 0x12, 0x44, 0xaa, 0xd8,
|
||||
0xfb, 0x54, 0x05, 0x64, 0x05, 0x70, 0x1e, 0x78, 0xc4, 0x7d,
|
||||
0xb8, 0x12, 0x42, 0xc5, 0x78, 0xc1, 0x7d, 0x74, 0x12, 0x42,
|
||||
0xc5, 0xe4, 0x78, 0xc1, 0xf6, 0x22, 0x7b, 0x01, 0x7a, 0x00,
|
||||
0x7d, 0xee, 0x7f, 0x92, 0x12, 0x38, 0xbd, 0x22, 0xe6, 0xfb,
|
||||
0x7a, 0x00, 0x7f, 0x92, 0x12, 0x38, 0xbd, 0x22, 0x78, 0xc1,
|
||||
0xe6, 0xfb, 0x7a, 0x00, 0x7d, 0x74, 0x7f, 0x92, 0x12, 0x38,
|
||||
0xbd, 0xe4, 0x78, 0xc1, 0xf6, 0xf5, 0x11, 0x74, 0x01, 0x7e,
|
||||
0x00, 0xa8, 0x11, 0x08, 0x80, 0x05, 0xc3, 0x33, 0xce, 0x33,
|
||||
0xce, 0xd8, 0xf9, 0xff, 0x78, 0xc4, 0xe6, 0xfd, 0xef, 0x5d,
|
||||
0x60, 0x44, 0x85, 0x11, 0xfb, 0xe5, 0x11, 0x54, 0x02, 0x25,
|
||||
0xe0, 0x25, 0xe0, 0xfe, 0xe4, 0x24, 0x5b, 0xfb, 0xee, 0x12,
|
||||
0x44, 0x2d, 0x12, 0x3e, 0xda, 0x7b, 0x40, 0x7d, 0x11, 0x7f,
|
||||
0x07, 0x12, 0x3d, 0xd7, 0x74, 0xc7, 0x25, 0x11, 0xf8, 0xa6,
|
||||
0x07, 0x7b, 0x11, 0x7d, 0x12, 0x7f, 0x07, 0x12, 0x3d, 0xd7,
|
||||
0xef, 0x4e, 0x60, 0x09, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76,
|
||||
0x04, 0x80, 0x07, 0x74, 0xe7, 0x25, 0x11, 0xf8, 0x76, 0x0a,
|
||||
0x05, 0x11, 0xe5, 0x11, 0xc3, 0x94, 0x04, 0x40, 0x9a, 0x78,
|
||||
0xc6, 0xe6, 0x70, 0x15, 0x78, 0xc4, 0xe6, 0x60, 0x10, 0x75,
|
||||
0xd9, 0x38, 0x75, 0xdb, 0x10, 0x7d, 0xfe, 0x12, 0x43, 0x7d,
|
||||
0x7d, 0x76, 0x12, 0x43, 0x7d, 0x79, 0xc6, 0xe7, 0x78, 0xc4,
|
||||
0x66, 0xff, 0x60, 0x03, 0x12, 0x40, 0x25, 0x78, 0xc4, 0xe6,
|
||||
0x70, 0x09, 0xfb, 0xfa, 0x7d, 0xfe, 0x7f, 0x8e, 0x12, 0x38,
|
||||
0xbd, 0x22, 0x7b, 0x01, 0x7a, 0x00, 0x7f, 0x8e, 0x12, 0x38,
|
||||
0xbd, 0x22, 0xe4, 0xf5, 0x19, 0x74, 0x25, 0x25, 0x19, 0xf8,
|
||||
0xe6, 0x64, 0x03, 0x60, 0x51, 0xe5, 0x19, 0x24, 0x17, 0xfd,
|
||||
0x7b, 0xeb, 0x7f, 0x04, 0x12, 0x3d, 0xd7, 0x8f, 0xfb, 0x7b,
|
||||
0x22, 0x7d, 0x18, 0x7f, 0x06, 0x12, 0x3d, 0xd7, 0xef, 0x64,
|
||||
0x01, 0x4e, 0x60, 0x1c, 0x7d, 0x1c, 0xe4, 0xff, 0x12, 0x3e,
|
||||
0x9a, 0xef, 0x54, 0x1b, 0x64, 0x0a, 0x70, 0x15, 0x7b, 0xcc,
|
||||
0x7d, 0x10, 0xff, 0x12, 0x3d, 0xd7, 0xef, 0x64, 0x01, 0x4e,
|
||||
0x70, 0x07, 0x12, 0x44, 0xb1, 0x7b, 0x03, 0x80, 0x0a, 0x12,
|
||||
0x44, 0xb1, 0x74, 0x25, 0x25, 0x19, 0xf8, 0xe6, 0xfb, 0x7a,
|
||||
0x00, 0x7d, 0x54, 0x12, 0x38, 0xbd, 0x05, 0x19, 0xe5, 0x19,
|
||||
0xc3, 0x94, 0x02, 0x40, 0x9c, 0x22, 0xe5, 0x7e, 0x30, 0xe5,
|
||||
0x35, 0x30, 0xe4, 0x0b, 0x7b, 0x02, 0x7d, 0x33, 0x7f, 0x35,
|
||||
0x12, 0x36, 0x29, 0x80, 0x10, 0x7b, 0x01, 0x7d, 0x33, 0x7f,
|
||||
0x35, 0x12, 0x36, 0x29, 0x90, 0x47, 0xd2, 0xe0, 0x44, 0x04,
|
||||
0xf0, 0x90, 0x47, 0xd2, 0xe0, 0x54, 0xf7, 0xf0, 0x90, 0x47,
|
||||
0xd1, 0xe0, 0x44, 0x10, 0xf0, 0x7b, 0x05, 0x7d, 0x84, 0x7f,
|
||||
0x86, 0x12, 0x36, 0x29, 0x22, 0xfb, 0xe5, 0x1c, 0x34, 0xf0,
|
||||
0xfa, 0x7d, 0x10, 0x7f, 0x07, 0x22, 0x54, 0x01, 0xc4, 0x33,
|
||||
0x54, 0xe0, 0xf5, 0xdb, 0x44, 0x08, 0xf5, 0xdb, 0x22, 0xf5,
|
||||
0xdb, 0x75, 0xdb, 0x08, 0xf5, 0xdb, 0x75, 0xdb, 0x08, 0x22,
|
||||
0xe5, 0x7e, 0x54, 0x0f, 0x64, 0x01, 0x70, 0x0d, 0xe5, 0x7e,
|
||||
0x30, 0xe4, 0x08, 0x90, 0x47, 0xd0, 0xe0, 0x44, 0x02, 0xf0,
|
||||
0x22, 0x90, 0x47, 0xd0, 0xe0, 0x54, 0xfd, 0xf0, 0x22, 0xab,
|
||||
0x07, 0xaa, 0x06, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3e, 0xda,
|
||||
0x7b, 0xff, 0x7d, 0x10, 0x7f, 0x07, 0x12, 0x3d, 0xd7, 0xef,
|
||||
0x4e, 0x60, 0xf3, 0x22, 0x12, 0x44, 0xc5, 0x12, 0x44, 0xbb,
|
||||
0x90, 0x47, 0xfa, 0xe0, 0x54, 0xf8, 0x44, 0x02, 0xf0, 0x22,
|
||||
0x30, 0x04, 0x03, 0x12, 0x43, 0x87, 0x78, 0xc4, 0xe6, 0xff,
|
||||
0x60, 0x03, 0x12, 0x40, 0x25, 0x22, 0xe5, 0x7e, 0xae, 0x7d,
|
||||
0x78, 0x04, 0x22, 0xce, 0xa2, 0xe7, 0x13, 0xce, 0x13, 0x22,
|
||||
0xe5, 0x19, 0x24, 0x17, 0x54, 0x1f, 0x44, 0x80, 0xff, 0x22,
|
||||
0xe4, 0x78, 0xc4, 0xf6, 0xc2, 0x05, 0x78, 0xc1, 0xf6, 0x22,
|
||||
0xc2, 0x04, 0xc2, 0x03, 0x22, 0x22
|
||||
};
|
||||
|
||||
/**
|
||||
* Setup Vitesse PHYs
|
||||
* This function sets up one port in a Vitesse VSC8574 for
|
||||
* either SGMII or QSGMII
|
||||
*/
|
||||
static void setup_vitesse_phy(bdk_node_t node, int mdio_bus, int phy_addr, bool qsgmii)
|
||||
{
|
||||
// Select "G" registers
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x10);
|
||||
// Reg 19G, bit 15:14
|
||||
// 0 = SGMII
|
||||
// 1 = QSGMII
|
||||
int reg19 = bdk_mdio_read(node, mdio_bus, phy_addr, 19);
|
||||
int reg18;
|
||||
if (qsgmii)
|
||||
{
|
||||
// QSGMII
|
||||
reg19 = (reg19 & ~(3 << 14)) | (1 << 14);
|
||||
reg18 = 0x80e0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// SGMII
|
||||
reg19 = (reg19 & ~(3 << 14)) | (0 << 14);
|
||||
reg18 = 0x80f0;
|
||||
}
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 19, reg19);
|
||||
// Write 18G, change all 4 ports
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 18, reg18);
|
||||
// Select main registers
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0);
|
||||
// Reg23, 10:8 Select copper
|
||||
int reg23 = bdk_mdio_read(node, mdio_bus, phy_addr, 23);
|
||||
reg23 = (reg23 & ~(7 << 8)) | (0 << 8);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 23, reg23);
|
||||
// Reg0, Reset
|
||||
int reg0 = bdk_mdio_read(node, mdio_bus, phy_addr, 0);
|
||||
reg0 |= (1 << 15);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 0, reg0);
|
||||
// Reg 16E3, bit 7 auto negotiation
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 3);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 16, 0x80);
|
||||
// Select main registers
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0);
|
||||
// Near end loopback (Thunder side)
|
||||
if (LOOP_INTERNAL)
|
||||
{
|
||||
reg0 = bdk_mdio_read(node, mdio_bus, phy_addr, 0);
|
||||
reg0 |= (1 << 14);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 0, reg0);
|
||||
}
|
||||
|
||||
// Far end loopback (External side)
|
||||
if (LOOP_EXTERNAL)
|
||||
{
|
||||
reg23 = bdk_mdio_read(node, mdio_bus, phy_addr, 23);
|
||||
reg23 |= (1 << 3);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 23, reg23);
|
||||
}
|
||||
}
|
||||
|
||||
static void wr_masked(bdk_node_t node, int mdio_bus, int phy_addr, int reg, int value, int mask)
|
||||
{
|
||||
int nmask = ~mask;
|
||||
int old = bdk_mdio_read(node, mdio_bus, phy_addr, reg);
|
||||
int vmask = value & mask;
|
||||
int newv = old & nmask;
|
||||
newv = newv | vmask;
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, reg, newv);
|
||||
}
|
||||
|
||||
static void vitesse_program(bdk_node_t node, int mdio_bus, int phy_addr)
|
||||
{
|
||||
printf("Programming Vitesse PHY at address %d\n", phy_addr);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x800f);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010);
|
||||
|
||||
int reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18);
|
||||
int timeout = 10;
|
||||
while ((reg18g & (1<<15)) && (timeout > 0))
|
||||
{
|
||||
bdk_wait_usec(100000);
|
||||
reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18);
|
||||
timeout = timeout - 1;
|
||||
}
|
||||
if (timeout == 0)
|
||||
bdk_error("Vetesse: Timeout waiting for complete\n");
|
||||
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0000);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010);
|
||||
wr_masked(node, mdio_bus, phy_addr, 12, 0x0000, 0x0800);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 9, 0x005b);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 10, 0x005b);
|
||||
wr_masked(node, mdio_bus, phy_addr, 12, 0x0800, 0x0800);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x800f);
|
||||
wr_masked(node, mdio_bus, phy_addr, 0, 0x0000, 0x8000);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x0000);
|
||||
wr_masked(node, mdio_bus, phy_addr, 12, 0x0000, 0x0800);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x10);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 0, 0x7009);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 12, 0x5002);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 11, 0x0000);
|
||||
|
||||
for (unsigned int i=0; i<sizeof(patch_arr); i++)
|
||||
{
|
||||
int d = 0x5000 | patch_arr[i];
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 12, d);
|
||||
}
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 12, 0x0000);
|
||||
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 3, 0x3eb7);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 4, 0x4012);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 12, 0x0100);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 0, 0x4018);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 0, 0xc018);
|
||||
|
||||
// below verifies CRC is correct in 8051 RAM. CRC is 16-bit.
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0001);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 25, 0x4000);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 26, sizeof(patch_arr) + 1);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0010);
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 18, 0x8008);
|
||||
|
||||
reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18);
|
||||
timeout = 10;
|
||||
while ((reg18g & (1<<15)) && (timeout > 0))
|
||||
{
|
||||
bdk_wait_usec(100000);
|
||||
reg18g = bdk_mdio_read(node, mdio_bus, phy_addr, 18);
|
||||
timeout = timeout - 1;
|
||||
}
|
||||
if (timeout == 0)
|
||||
bdk_error("Vetesse: Timeout waiting for complete\n");
|
||||
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0001);
|
||||
|
||||
int crc_calculated = bdk_mdio_read(node, mdio_bus, phy_addr, 25);
|
||||
if (crc_calculated != 0xB7C2)
|
||||
printf("8051 crc_calculated = 0x%x, expected_crc = 0x%x\n", crc_calculated, 0xB7C2);
|
||||
|
||||
bdk_mdio_write(node, mdio_bus, phy_addr, 31, 0x0000);
|
||||
}
|
||||
|
||||
//static void vetesse_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr)
|
||||
int bdk_if_phy_vetesse_setup(bdk_node_t node, int qlm, int mdio_bus, int phy_addr)
|
||||
{
|
||||
/* Check if the PHY is Vetesse PHY we expect */
|
||||
int phy_status = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1);
|
||||
if (phy_status != 0x0007)
|
||||
return 0;
|
||||
|
||||
/* Check that the GSER mode is SGMII or QSGMII */
|
||||
bdk_qlm_modes_t qlm_mode = bdk_qlm_get_mode(node, qlm);
|
||||
if ((qlm_mode != BDK_QLM_MODE_SGMII_1X1) &&
|
||||
(qlm_mode != BDK_QLM_MODE_SGMII_2X1) &&
|
||||
(qlm_mode != BDK_QLM_MODE_SGMII_4X1) &&
|
||||
(qlm_mode != BDK_QLM_MODE_QSGMII_4X1))
|
||||
return 0;
|
||||
|
||||
/* Program the Vetesse PHY */
|
||||
vitesse_program(node, mdio_bus, phy_addr);
|
||||
|
||||
/* Switch the Vitesse PHY to the correct mode */
|
||||
bool is_qsgmii = (qlm_mode == BDK_QLM_MODE_QSGMII_4X1);
|
||||
if (is_qsgmii)
|
||||
{
|
||||
for (int port = 0; port < 4; port++)
|
||||
setup_vitesse_phy(node, mdio_bus, phy_addr + port, true);
|
||||
}
|
||||
else
|
||||
setup_vitesse_phy(node, mdio_bus, phy_addr, false);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int bdk_if_phy_vetesse_setup(bdk_node_t node)
|
||||
{
|
||||
for (int bgx = 0; bgx < 4; bgx++)
|
||||
{
|
||||
int port = 0;
|
||||
int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, node, bgx, port);
|
||||
if (phy_addr != -1)
|
||||
{
|
||||
int node = (phy_addr >> 24) & 0xff;
|
||||
int mdio_bus = (phy_addr >> 8) & 0xff;
|
||||
int mdio_addr = phy_addr & 0xff;
|
||||
if (node == 0xff)
|
||||
node = bdk_numa_local();
|
||||
if ((phy_addr & BDK_IF_PHY_TYPE_MASK) == BDK_IF_PHY_MDIO)
|
||||
{
|
||||
int qlm = bdk_qlm_get(node, BDK_IF_BGX, bgx, port);
|
||||
if (qlm != -1)
|
||||
vetesse_setup(node, qlm, mdio_bus, mdio_addr);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
445
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy.c
Normal file
445
src/vendorcode/cavium/bdk/libbdk-hal/if/bdk-if-phy.c
Normal file
@ -0,0 +1,445 @@
|
||||
/***********************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-hal/if/bdk-if.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-hal/bdk-mdio.h>
|
||||
#include <libbdk-hal/bdk-qlm.h>
|
||||
#include <libbdk-hal/bdk-twsi.h>
|
||||
|
||||
/**
|
||||
* Called when the PHY is connected through TWSI
|
||||
*
|
||||
* @param dev_node Node the ethernet device is on
|
||||
* @param phy_addr Encoded address, see bdk-if.h for format
|
||||
*
|
||||
* @return Link status
|
||||
*/
|
||||
static bdk_if_link_t __bdk_if_phy_get_twsi(bdk_node_t dev_node, int phy_addr)
|
||||
{
|
||||
/* For TWSI:
|
||||
Bits[31:24]: Node ID, 0xff for device node
|
||||
Bits[23:16]: TWSI internal address width in bytes (0-2)
|
||||
Bits[15:12]: 2=TWSI
|
||||
Bits[11:8]: TWSI bus number
|
||||
Bits[7:0]: TWSI address */
|
||||
int node = (phy_addr >> 24) & 0xff;
|
||||
int twsi_ia_width = (phy_addr >> 16) & 0xff;
|
||||
int twsi_bus = (phy_addr >> 8) & 0xf;
|
||||
int twsi_addr = phy_addr & 0xff;
|
||||
if (node == 0xff)
|
||||
node = dev_node;
|
||||
|
||||
bdk_if_link_t result;
|
||||
result.u64 = 0;
|
||||
|
||||
/* This is from the Avago SFP 1G Module data sheet
|
||||
Register 17 (Extended Status 1) */
|
||||
int64_t phy_status = bdk_twsix_read_ia(node, twsi_bus, twsi_addr, 17, 2, twsi_ia_width);
|
||||
if (phy_status != -1)
|
||||
{
|
||||
int speed = (phy_status >> 14)& 3;
|
||||
int duplex = (phy_status >> 13)& 1;
|
||||
int resolved = (phy_status >> 11)& 1;
|
||||
int link = (phy_status >> 10)& 1;
|
||||
if (resolved)
|
||||
{
|
||||
result.s.up = link;
|
||||
result.s.full_duplex = duplex;
|
||||
switch (speed)
|
||||
{
|
||||
case 0: /* 10 Mbps */
|
||||
result.s.speed = 10;
|
||||
break;
|
||||
case 1: /* 100 Mbps */
|
||||
result.s.speed = 100;
|
||||
break;
|
||||
case 2: /* 1 Gbps */
|
||||
result.s.speed = 1000;
|
||||
break;
|
||||
case 3: /* Illegal */
|
||||
result.u64 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the status of a PHY
|
||||
*
|
||||
* @param dev_node Node the ethernet device is on
|
||||
* @param phy_addr Encoded PHY address, see bdk-if.h for format
|
||||
*
|
||||
* @return Link status
|
||||
*/
|
||||
bdk_if_link_t __bdk_if_phy_get(bdk_node_t dev_node, int phy_addr)
|
||||
{
|
||||
int node = (phy_addr >> 24) & 0xff;
|
||||
int mdio_bus = (phy_addr >> 8) & 0xff;
|
||||
int mdio_addr = phy_addr & 0xff;
|
||||
if (node == 0xff)
|
||||
node = dev_node;
|
||||
int phy_status;
|
||||
bdk_if_link_t result;
|
||||
result.u64 = 0;
|
||||
|
||||
/* PHY address of -1 menas there is no PHY and we should have never
|
||||
gotten here */
|
||||
if (phy_addr == -1)
|
||||
return result;
|
||||
|
||||
/* A PHY address with the special value 0x1000 represents a PHY we can't
|
||||
connect to through MDIO which is assumed to be at 1Gbps */
|
||||
if (phy_addr == BDK_IF_PHY_FIXED_1GB)
|
||||
{
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 1;
|
||||
result.s.speed = 1000;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* A PHY address with the special value 0x1001 represents a PHY we can't
|
||||
connect to through MDIO which is assumed to be at 100Mbps */
|
||||
if (phy_addr == BDK_IF_PHY_FIXED_100MB)
|
||||
{
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 1;
|
||||
result.s.speed = 100;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Check for a PHY connected through TWSI */
|
||||
if ((phy_addr & BDK_IF_PHY_TYPE_MASK) == BDK_IF_PHY_TWSI)
|
||||
return __bdk_if_phy_get_twsi(dev_node, phy_addr);
|
||||
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, BDK_MDIO_PHY_REG_ID1);
|
||||
if ((phy_status <= 0) || (phy_status == 0xffff))
|
||||
return result;
|
||||
|
||||
switch (phy_status)
|
||||
{
|
||||
case 0x0141: /* Marvell */
|
||||
{
|
||||
|
||||
/* This code assumes we are using a Marvell Gigabit PHY. All the
|
||||
speed information can be read from register 17 in one go. Somebody
|
||||
using a different PHY will need to handle it above in the board
|
||||
specific area */
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 17);
|
||||
if (phy_status < 0)
|
||||
return result;
|
||||
|
||||
/* If the resolve bit 11 isn't set, see if autoneg is turned off
|
||||
(bit 12, reg 0). The resolve bit doesn't get set properly when
|
||||
autoneg is off, so force it */
|
||||
if ((phy_status & (1<<11)) == 0)
|
||||
{
|
||||
bdk_mdio_phy_reg_control_t control;
|
||||
int phy_c = bdk_mdio_read(node, mdio_bus, mdio_addr, BDK_MDIO_PHY_REG_CONTROL);
|
||||
if (phy_c < 0)
|
||||
return result;
|
||||
control.u16 = phy_c;
|
||||
if (control.s.autoneg_enable == 0)
|
||||
phy_status |= 1<<11;
|
||||
}
|
||||
|
||||
/* Only return a link if the PHY has finished auto negotiation
|
||||
and set the resolved bit (bit 11) */
|
||||
if (phy_status & (1<<11))
|
||||
{
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = ((phy_status>>13)&1);
|
||||
switch ((phy_status>>14)&3)
|
||||
{
|
||||
case 0: /* 10 Mbps */
|
||||
result.s.speed = 10;
|
||||
break;
|
||||
case 1: /* 100 Mbps */
|
||||
result.s.speed = 100;
|
||||
break;
|
||||
case 2: /* 1 Gbps */
|
||||
result.s.speed = 1000;
|
||||
break;
|
||||
case 3: /* Illegal */
|
||||
result.u64 = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x0022: /* Kendin */
|
||||
{
|
||||
/* Register 1Fh - PHY Control */
|
||||
/* Micrel KSZ9031RNX, EBB8104 RGMII transceiver */
|
||||
/* Reports as "Kendin" in BDK_MDIO_PHY_REG_ID1 */
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x1F);
|
||||
if (phy_status & (1 << 6)) // Speed Status - 1000Base-T
|
||||
{
|
||||
result.s.up = 1;
|
||||
result.s.speed = 1000;
|
||||
}
|
||||
else if (phy_status & (1 << 5)) // Speed Status - 100Base-TX
|
||||
{
|
||||
result.s.up = 1;
|
||||
result.s.speed = 100;
|
||||
}
|
||||
else if (phy_status & (1 << 4)) // Speed Status - 10Base-T
|
||||
{
|
||||
result.s.up = 1;
|
||||
result.s.speed = 10;
|
||||
}
|
||||
if (phy_status & (1 << 3)) // Duplex Status
|
||||
{
|
||||
result.s.full_duplex = 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 0x0007: /* Vitesse */
|
||||
{
|
||||
/* Auxiliary Control and Status, Address 28 (0x1C) */
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x1c);
|
||||
result.s.full_duplex = (phy_status>>5)&1;
|
||||
switch ((phy_status>>3) & 3)
|
||||
{
|
||||
case 0:
|
||||
result.s.speed = 10;
|
||||
result.s.up = 1;
|
||||
break;
|
||||
case 1:
|
||||
result.s.speed = 100;
|
||||
result.s.up = 1;
|
||||
break;
|
||||
default:
|
||||
result.s.speed = 1000;
|
||||
break;
|
||||
}
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x01);
|
||||
result.s.up = (phy_status>>2)&1;
|
||||
break;
|
||||
}
|
||||
default: /* Treat like Broadcom */
|
||||
{
|
||||
/* Below we are going to read SMI/MDIO register 0x19 which works
|
||||
on Broadcom parts */
|
||||
phy_status = bdk_mdio_read(node, mdio_bus, mdio_addr, 0x19);
|
||||
if (phy_status < 0)
|
||||
return result;
|
||||
|
||||
switch ((phy_status>>8) & 0x7)
|
||||
{
|
||||
case 0:
|
||||
result.u64 = 0;
|
||||
break;
|
||||
case 1:
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 0;
|
||||
result.s.speed = 10;
|
||||
break;
|
||||
case 2:
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 1;
|
||||
result.s.speed = 10;
|
||||
break;
|
||||
case 3:
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 0;
|
||||
result.s.speed = 100;
|
||||
break;
|
||||
case 4:
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 1;
|
||||
result.s.speed = 100;
|
||||
break;
|
||||
case 5:
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 1;
|
||||
result.s.speed = 100;
|
||||
break;
|
||||
case 6:
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 0;
|
||||
result.s.speed = 1000;
|
||||
break;
|
||||
case 7:
|
||||
result.s.up = 1;
|
||||
result.s.full_duplex = 1;
|
||||
result.s.speed = 1000;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If link is down, return all fields as zero. */
|
||||
if (!result.s.up)
|
||||
result.u64 = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* PHY XS initialization, primarily for RXAUI
|
||||
*
|
||||
* @param dev_node Node the ethernet device is on
|
||||
* @param phy_addr Encoded PHY address, see bdk-if.h for format
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
void __bdk_if_phy_xs_init(bdk_node_t dev_node, int phy_addr)
|
||||
{
|
||||
/* This code only supports PHYs connected through MDIO */
|
||||
if ((phy_addr & BDK_IF_PHY_TYPE_MASK) != BDK_IF_PHY_MDIO)
|
||||
return;
|
||||
|
||||
int node = (phy_addr >> 24) & 0xff;
|
||||
int mdio_bus = (phy_addr >> 8) & 0xff;
|
||||
int mdio_addr = phy_addr & 0xff;
|
||||
if (node == 0xff)
|
||||
node = dev_node;
|
||||
|
||||
/* Read the PMA/PMD Device Identifier (1.2, 1.3)
|
||||
OUI is spread across both registers */
|
||||
int dev_addr = 1;
|
||||
int reg_addr = 2;
|
||||
int phy_id1 = bdk_mdio_45_read(node, mdio_bus, mdio_addr, dev_addr, reg_addr);
|
||||
if (phy_id1 == -1)
|
||||
return;
|
||||
reg_addr = 3;
|
||||
int phy_id2 = bdk_mdio_45_read(node, mdio_bus, mdio_addr, dev_addr, reg_addr);
|
||||
if (phy_id2 == -1)
|
||||
return;
|
||||
int model_number = (phy_id2 >> 4) & 0x3F;
|
||||
int oui = phy_id1;
|
||||
oui <<= 6;
|
||||
oui |= (phy_id2 >> 10) & 0x3F;
|
||||
switch (oui)
|
||||
{
|
||||
case 0x5016: /* Marvell */
|
||||
if (model_number == 9) /* 88X3140/3120 */
|
||||
{
|
||||
BDK_TRACE(BGX, "N%d.MDIO%d.%d: Performing PHY reset on Marvell RXAUI PHY\n",
|
||||
node, mdio_bus, mdio_addr);
|
||||
dev_addr = 4;
|
||||
reg_addr = 0;
|
||||
/* Write bit 15, Software Reset, in PHY XS Control 1 (4.0). On CN78xx,
|
||||
sometimes the PHY/BGX gets stuck in local fault mode, link never comes up,
|
||||
and this appears to clear it up. Haven't seen this on CN81xx or T88,
|
||||
but the reset seems like cheap insurance. */
|
||||
if (bdk_mdio_45_write(node, mdio_bus, mdio_addr, dev_addr, reg_addr, (1 << 15)))
|
||||
{
|
||||
bdk_error("PHY XS: MDIO write to (%d.%d) failed\n", dev_addr, reg_addr);
|
||||
return;
|
||||
}
|
||||
|
||||
int reset_pending = 1;
|
||||
while (reset_pending)
|
||||
{
|
||||
reset_pending = bdk_mdio_45_read(node, mdio_bus, mdio_addr, dev_addr, reg_addr);
|
||||
reset_pending &= (1 << 15);
|
||||
}
|
||||
|
||||
/* Adjust the RXAUI TX Level for Marvell PHY, per Brendan Metzner
|
||||
write 5 to register 4.49155 */
|
||||
reg_addr = 49155;
|
||||
if (bdk_mdio_45_write(node, mdio_bus, mdio_addr, dev_addr, reg_addr, 5))
|
||||
{
|
||||
bdk_error("PHY XS: MDIO write to (%d.%d) failed\n", dev_addr, reg_addr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: /* Unknown PHY, or no PHY present */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int bdk_if_phy_setup(bdk_node_t dev_node)
|
||||
{
|
||||
/* 81xx has only 2 BGX (BGX0-BGX1); BGX2 is RGMII */
|
||||
for (int bgx = 0; bgx < 2; bgx++)
|
||||
{
|
||||
int port = 0;
|
||||
int phy_addr = bdk_config_get_int(BDK_CONFIG_PHY_ADDRESS, dev_node, bgx, port);
|
||||
if (phy_addr != -1)
|
||||
{
|
||||
int node = (phy_addr >> 24) & 0xff;
|
||||
int mdio_bus = (phy_addr >> 8) & 0xff;
|
||||
int mdio_addr = phy_addr & 0xff;
|
||||
if (node == 0xff)
|
||||
node = bdk_numa_local();
|
||||
if ((phy_addr & BDK_IF_PHY_TYPE_MASK) == BDK_IF_PHY_MDIO)
|
||||
{
|
||||
int qlm = bdk_qlm_get_qlm_num(node, BDK_IF_BGX, bgx, port);
|
||||
if (qlm == -1)
|
||||
continue;
|
||||
|
||||
BDK_TRACE(PHY, "N%d.BGX%d.%d: Configuring ...\n", node, bgx, port);
|
||||
|
||||
/* Check PHY id */
|
||||
int phy_status_1 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID1);
|
||||
int phy_status_2 = bdk_mdio_read(node, mdio_bus, phy_addr, BDK_MDIO_PHY_REG_ID2);
|
||||
|
||||
/* Vitesse */
|
||||
if (phy_status_1 == 0x0007)
|
||||
{
|
||||
if (phy_status_2 == 0x0670)
|
||||
{
|
||||
bdk_if_phy_vsc8514_setup(node, qlm, mdio_bus, mdio_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
bdk_if_phy_vetesse_setup(node, qlm, mdio_bus, mdio_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Marvell */
|
||||
else if (phy_status_1 == 0x0141)
|
||||
bdk_if_phy_marvell_setup(node, qlm, mdio_bus, mdio_addr);
|
||||
else
|
||||
BDK_TRACE(PHY, "N%d.BGX%d.%d: Unknown PHY %x\n", node, bgx, port, phy_status_1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
1003
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-cn81xx.c
Normal file
1003
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-cn81xx.c
Normal file
File diff suppressed because it is too large
Load Diff
625
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-common-sata.c
Normal file
625
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-common-sata.c
Normal file
@ -0,0 +1,625 @@
|
||||
/***********************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-hal/if/bdk-if.h"
|
||||
#include "libbdk-hal/bdk-qlm.h"
|
||||
#include "libbdk-hal/qlm/bdk-qlm-common.h"
|
||||
#include "libbdk-arch/bdk-csrs-gser.h"
|
||||
#include "libbdk-arch/bdk-csrs-sata.h"
|
||||
|
||||
/**
|
||||
* Initialize a DLM/QLM for use with SATA controllers
|
||||
*
|
||||
* @param node Node to intialize
|
||||
* @param qlm Which DLM/QLM to init
|
||||
* @param baud_mhz QLM speed in Gbaud
|
||||
* @param sata_first First SATA controller connected to this DLM/QLM
|
||||
* @param sata_last Last SATA controller connected to this DLM/QLM (inclusive)
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int __bdk_qlm_set_sata_cn8xxx(bdk_node_t node, int qlm, int baud_mhz, int sata_first, int sata_last)
|
||||
{
|
||||
const int NUM_LANES = sata_last - sata_first + 1;
|
||||
const int MAX_A_CLK = 333000000; /* Max of 333Mhz */
|
||||
|
||||
/* 26.4.1 Cold Reset */
|
||||
/* 1. Ensure that the SerDes reference clock is up and stable. */
|
||||
/* Already done */
|
||||
|
||||
/* 2. Optionally program the GPIO CSRs for SATA features.
|
||||
a. For cold-presence detect, select a GPIO for the input and program GPI-
|
||||
O_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E::SATA(0..15)_CP_DET.
|
||||
b. For mechanical-presence detect, select a GPIO for the input and program
|
||||
GPIO_BIT_CFG(0..50)[PIN_SEL] = GPI-
|
||||
O_PIN_SEL_E::SATA(0..15)_MP_SWITCH.
|
||||
c. For BIST board-test loopback, select a GPIO for the input and program GPI-
|
||||
O_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E:::SATA_LAB_LB.
|
||||
d. For LED activity, select a GPIO for the output and program GPI-
|
||||
O_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E:::SATA(0..15)_ACT_LED.
|
||||
e. For cold-presence power-on-device, select a GPIO for the output and program
|
||||
GPIO_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E:::SATA(0..15)_CP_-
|
||||
POD. */
|
||||
/* Skipping */
|
||||
|
||||
/* 3. Optionally program the SGPIO unit. */
|
||||
/* Skipping */
|
||||
|
||||
/* 4. Assert all resets:
|
||||
a. UAHC reset: SATA(0..15)_UCTL_CTL[SATA_UAHC_RST] = 1
|
||||
b. UCTL reset: SATA(0..15)_UCTL_CTL[SATA_UCTL_RST] = 1 */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.sata_uahc_rst = 1;
|
||||
c.s.sata_uctl_rst = 1);
|
||||
}
|
||||
|
||||
/* 5. Configure the ACLK:
|
||||
a. Reset the clock dividers: SATA(0..15)_UCTL_CTL[A_CLKDIV_RST] = 1.
|
||||
b. Select the ACLK frequency (refer to maximum values in Table 26 1).
|
||||
i. SATA(0..15)_UCTL_CTL[A_CLKDIV_SEL] = desired value,
|
||||
ii. SATA(0..15)_UCTL_CTL[A_CLK_EN] = 1 to enable the ACLK.
|
||||
c. Deassert the ACLK clock divider reset:
|
||||
SATA(0..15)_UCTL_CTL[A_CLKDIV_RST] = 0. */
|
||||
int divisor = (bdk_clock_get_rate(node, BDK_CLOCK_SCLK) + MAX_A_CLK - 1) / MAX_A_CLK;
|
||||
int a_clkdiv;
|
||||
/* This screwy if logic is from the description of
|
||||
SATAX_UCTL_CTL[a_clkdiv_sel] in the CSR */
|
||||
if (divisor <= 4)
|
||||
{
|
||||
a_clkdiv = divisor - 1;
|
||||
/* Divisor matches calculated value */
|
||||
}
|
||||
else if (divisor <= 6)
|
||||
{
|
||||
a_clkdiv = 4;
|
||||
divisor = 6;
|
||||
}
|
||||
else if (divisor <= 8)
|
||||
{
|
||||
a_clkdiv = 5;
|
||||
divisor = 8;
|
||||
}
|
||||
else if (divisor <= 16)
|
||||
{
|
||||
a_clkdiv = 6;
|
||||
divisor = 16;
|
||||
}
|
||||
else if (divisor <= 24)
|
||||
{
|
||||
a_clkdiv = 7;
|
||||
divisor = 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
bdk_error("Unable to determine SATA clock divisor\n");
|
||||
return -1;
|
||||
}
|
||||
/* Calculate the final clock rate */
|
||||
int a_clk = bdk_clock_get_rate(node, BDK_CLOCK_SCLK) / divisor;
|
||||
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.a_clkdiv_rst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.a_clk_byp_sel = 0;
|
||||
c.s.a_clkdiv_sel = a_clkdiv;
|
||||
c.s.a_clk_en = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.a_clkdiv_rst = 0);
|
||||
}
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 8. Configure PHY for SATA. Refer to Section 21.1.2. */
|
||||
/* Done below, section 24.1.2.3 */
|
||||
|
||||
/* 9. TBD: Poll QLM2_MPLL_STATUS for MPLL lock */
|
||||
/* Not needed */
|
||||
|
||||
/* 10. Initialize UAHC as described in the AHCI specification
|
||||
(UAHC_* registers). */
|
||||
/* Done when a SATA driver is initialized */
|
||||
|
||||
/* 24.1.2.3 SATA Configuration
|
||||
Software must perform the following steps to configure the GSER_WEST
|
||||
for a SATA application. Note that the GSERW steps are on a QLM basis. */
|
||||
|
||||
/* 1. Configure the SATA controller (refer to Chapter 26). */
|
||||
/* This is the code above */
|
||||
|
||||
/* 2. Configure the QLM Reference clock.
|
||||
Set GSER(0..13)_REFCLK_SEL[COM_CLK_SEL] = 1 to source the reference
|
||||
clock from the external clock multiplexer.
|
||||
Configure GSER(0..13)_REFCLK_SEL[USE_COM1]:
|
||||
0 = use QLMC_REF_CLK0_P/N
|
||||
1 = use QLMC_REF_CLK1_P/N */
|
||||
/* Already done */
|
||||
|
||||
/* Make sure the PHY is in reset before we reconfig */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_PHY_CTL(qlm),
|
||||
c.s.phy_reset = 1);
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 3. Configure the QLM for SATA mode: set GSER(0..13)_CFG[SATA] = 1. */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_CFG(qlm),
|
||||
c.u = 0;
|
||||
c.s.sata = 1);
|
||||
|
||||
/* 9. Clear the appropriate lane resets:
|
||||
GSER(0..13)_SATA_LANE_RST[Ln_RST] = 0, where n is the lane number 0-3. */
|
||||
BDK_CSR_WRITE(node, BDK_GSERX_SATA_LANE_RST(qlm), 0);
|
||||
BDK_CSR_READ(node, BDK_GSERX_SATA_LANE_RST(qlm));
|
||||
|
||||
/* We'll check for the SATA_PCS Ready in step 8a below */
|
||||
/* Short 1 usec wait */
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 4. Take the PHY out of reset: write GSER(0..13)_PHY_CTL[PHY_RESET] = 0. */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_PHY_CTL(qlm),
|
||||
c.s.phy_reset = 0);
|
||||
|
||||
/* 4a. Poll for PHY RST_RDY indicating the PHY has initialized before
|
||||
trying to access internal registers to reconfigure for SATA */
|
||||
/* 8. Wait for GSER(0..13)_QLM_STAT[RST_RDY] = 1, indicating that the PHY
|
||||
has been reconfigured and PLLs are locked. */
|
||||
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_GSERX_QLM_STAT(qlm), rst_rdy, ==, 1, 10000))
|
||||
{
|
||||
bdk_error("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Workaround for errata GSER-30310: SATA HDD Not Ready due to
|
||||
PHY SDLL/LDLL lockup at 3GHz */
|
||||
for (int slice = 0; slice < NUM_LANES / 2; slice++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_SLICEX_PCIE1_MODE(qlm, slice),
|
||||
c.s.rx_pi_bwsel = 1;
|
||||
c.s.rx_ldll_bwsel = 1;
|
||||
c.s.rx_sdll_bwsel = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_SLICEX_PCIE2_MODE(qlm, slice),
|
||||
c.s.rx_pi_bwsel = 1;
|
||||
c.s.rx_ldll_bwsel = 1;
|
||||
c.s.rx_sdll_bwsel = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_SLICEX_PCIE3_MODE(qlm, slice),
|
||||
c.s.rx_pi_bwsel = 1;
|
||||
c.s.rx_ldll_bwsel = 1;
|
||||
c.s.rx_sdll_bwsel = 1);
|
||||
}
|
||||
|
||||
/* 5. Change the P2 termination
|
||||
GSERn_RX_PWR_CTRL_P2[P2_RX_SUBBLK_PD<0>] = 0 (termination) */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_RX_PWR_CTRL_P2(qlm),
|
||||
c.s.p2_rx_subblk_pd &= 0x1e);
|
||||
|
||||
/* 6. Modify the electrical IDLE detect on delay: set
|
||||
GSER(0..13)_LANE(0..3)_MISC_CFG_0[EIE_DET_STL_ON_TIME] = 0x4 */
|
||||
for (int lane = 0; lane < NUM_LANES; lane++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_MISC_CFG_0(qlm, lane),
|
||||
c.s.eie_det_stl_on_time = 4);
|
||||
}
|
||||
|
||||
/* 7. Modify the PLL and lane-protocol-mode registers to configure the
|
||||
PHY for SATA */
|
||||
/* Errata (GSER-26724) SATA never indicates GSER QLM_STAT[RST_RDY]
|
||||
We program PLL_PX_MODE_0 last due to this errata */
|
||||
for (int p=0; p<3; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_PLL_PX_MODE_1(qlm, p),
|
||||
c.s.pll_16p5en = 0x0;
|
||||
c.s.pll_cpadj = 0x2;
|
||||
c.s.pll_pcie3en = 0;
|
||||
c.s.pll_opr = 0x0;
|
||||
c.s.pll_div = 0x1e);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANE_PX_MODE_0(qlm, p),
|
||||
c.s.ctle = 0x0;
|
||||
c.s.pcie = 0;
|
||||
c.s.tx_ldiv = 0x0;
|
||||
c.s.rx_ldiv = 2 - p;
|
||||
c.s.srate = 0;
|
||||
c.s.tx_mode = 3;
|
||||
c.s.rx_mode = 3);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANE_PX_MODE_1(qlm, p),
|
||||
c.s.vma_fine_cfg_sel = 0;
|
||||
c.s.vma_mm = 1;
|
||||
c.s.cdr_fgain = 0xa;
|
||||
c.s.ph_acc_adj = 0x15);
|
||||
}
|
||||
for (int p=0; p<3; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_PLL_PX_MODE_0(qlm, p),
|
||||
c.s.pll_icp = 0x1;
|
||||
c.s.pll_rloop = 0x3;
|
||||
c.s.pll_pcs_div = 0x5);
|
||||
}
|
||||
|
||||
for (int s = 0; s < NUM_LANES / 2; s++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_SLICEX_RX_SDLL_CTRL(qlm, s),
|
||||
c.s.pcs_sds_oob_clk_ctrl = 2;
|
||||
c.s.pcs_sds_rx_sdll_tune = 0;
|
||||
c.s.pcs_sds_rx_sdll_swsel = 0);
|
||||
}
|
||||
|
||||
for (int lane = 0; lane < NUM_LANES; lane++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_MISC_CFG_0(qlm, lane),
|
||||
c.s.use_pma_polarity = 0;
|
||||
c.s.cfg_pcs_loopback = 0;
|
||||
c.s.pcs_tx_mode_ovrrd_en = 0;
|
||||
c.s.pcs_rx_mode_ovrrd_en = 0;
|
||||
c.s.cfg_eie_det_cnt = 0;
|
||||
c.s.eie_det_stl_on_time = 4;
|
||||
c.s.eie_det_stl_off_time = 0;
|
||||
c.s.tx_bit_order = 1;
|
||||
c.s.rx_bit_order = 1);
|
||||
}
|
||||
|
||||
/* 8. Wait for GSER(0..13)_QLM_STAT[RST_RDY] = 1, indicating that the PHY
|
||||
has been reconfigured and PLLs are locked. */
|
||||
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_GSERX_QLM_STAT(qlm), rst_rdy, ==, 1, 10000))
|
||||
{
|
||||
bdk_error("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
|
||||
return -1;
|
||||
}
|
||||
/* 8a. Check that the SATA_PCS is "Ready" here, should be but check it */
|
||||
/* Poll GSERX_SATA_STATUS for PX_RDY = 1 */
|
||||
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_GSERX_SATA_STATUS(qlm), p0_rdy, ==, 1, 10000))
|
||||
{
|
||||
bdk_error("QLM%d: Timeout waiting for GSERX_SATA_STATUS[p0_rdy]\n", qlm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Add 1ms delay for everything to stabilize*/
|
||||
bdk_wait_usec(1000);
|
||||
|
||||
/* Apply any custom tuning */
|
||||
__bdk_qlm_tune(node, qlm, BDK_QLM_MODE_SATA_4X1, baud_mhz);
|
||||
bdk_wait_usec(1000);
|
||||
|
||||
|
||||
/* 6. Deassert UCTL and UAHC resets:
|
||||
a. SATA(0..15)_UCTL_CTL[SATA_UAHC_RST] = 0
|
||||
b. SATA(0..15)_UCTL_CTL[SATA_UCTL_RST] = 0
|
||||
c. Wait 10 ACLK cycles before accessing any ACLK-only registers. */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.sata_uahc_rst = 0;
|
||||
c.s.sata_uctl_rst = 0);
|
||||
}
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 7. Enable conditional SCLK of UCTL by writing
|
||||
SATA(0..15)_UCTL_CTL[CSCLK_EN] = 1. */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
|
||||
{
|
||||
/* CN9XXX make coprocessor clock automatic */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.cn8.csclk_en = 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check BIST on the SATA controller. Start BIST in parallel on the
|
||||
controllers */
|
||||
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
/* Make sure BIST is configured properly before we start it. We
|
||||
want full BIST, not just CLEAR */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.clear_bist = 0;
|
||||
c.s.start_bist = 0);
|
||||
/* Start BIST */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.start_bist = 1);
|
||||
}
|
||||
bdk_wait_usec(1000);
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_INIT(bist, node, BDK_SATAX_UCTL_BIST_STATUS(p));
|
||||
if (bist.u)
|
||||
bdk_error("N%d.SATA%d: Controller failed BIST (0x%llx)\n", node, p, bist.u);
|
||||
else
|
||||
BDK_TRACE(SATA, "N%d.SATA%d: Passed BIST\n", node, p);
|
||||
}
|
||||
/* Clear start_bist so it is ready for the next run */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.start_bist = 0);
|
||||
}
|
||||
|
||||
int spd;
|
||||
if (baud_mhz < 3000)
|
||||
spd = 1;
|
||||
else if (baud_mhz < 6000)
|
||||
spd = 2;
|
||||
else
|
||||
spd = 3;
|
||||
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
/* From the synopsis data book, SATAX_UAHC_GBL_TIMER1MS is the
|
||||
AMBA clock in MHz * 1000, which is a_clk(Hz) / 1000 */
|
||||
BDK_TRACE(QLM, "QLM%d: SATA%d set to %d Hz\n", qlm, p, a_clk);
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_GBL_TIMER1MS(p),
|
||||
c.s.timv = a_clk / 1000);
|
||||
/* Set speed */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_P0_SCTL(p),
|
||||
c.s.ipm = 3; /* Disable parial and slumber power management */
|
||||
c.s.spd = spd);
|
||||
/* The following SATA setup is from the AHCI 1.3 spec, section
|
||||
10.1.1, Firmware Specific Initialization. */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_GBL_CAP(p),
|
||||
c.s.sss = 1; /* Support staggered spin-up */
|
||||
c.s.smps = 1); /* Support mechanical presence switch */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_GBL_PI(p),
|
||||
c.s.pi = 1); /* One port per controller */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_P0_CMD(p),
|
||||
c.s.hpcp = 1; /* Hot-plug-capable support */
|
||||
c.s.mpsp = 1; /* Mechanical presence switch attached to port */
|
||||
c.s.cpd = 1); /* Cold-presence detection */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize a DLM/QLM for use with SATA controllers
|
||||
*
|
||||
* @param node Node to intialize
|
||||
* @param qlm Which DLM/QLM to init
|
||||
* @param baud_mhz QLM speed in Gbaud
|
||||
* @param sata_first First SATA controller connected to this DLM/QLM
|
||||
* @param sata_last Last SATA controller connected to this DLM/QLM (inclusive)
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int __bdk_qlm_set_sata_cn9xxx(bdk_node_t node, int qlm, int baud_mhz, int sata_first, int sata_last)
|
||||
{
|
||||
//const int NUM_LANES = sata_last - sata_first + 1;
|
||||
const int MAX_A_CLK = 333000000; /* Max of 333Mhz */
|
||||
|
||||
/* 26.4.1 Cold Reset */
|
||||
/* 1. Ensure that the SerDes reference clock is up and stable. */
|
||||
/* Already done */
|
||||
|
||||
/* 2. Optionally program the GPIO CSRs for SATA features.
|
||||
a. For cold-presence detect, select a GPIO for the input and program GPI-
|
||||
O_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E::SATA(0..15)_CP_DET.
|
||||
b. For mechanical-presence detect, select a GPIO for the input and program
|
||||
GPIO_BIT_CFG(0..50)[PIN_SEL] = GPI-
|
||||
O_PIN_SEL_E::SATA(0..15)_MP_SWITCH.
|
||||
c. For BIST board-test loopback, select a GPIO for the input and program GPI-
|
||||
O_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E:::SATA_LAB_LB.
|
||||
d. For LED activity, select a GPIO for the output and program GPI-
|
||||
O_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E:::SATA(0..15)_ACT_LED.
|
||||
e. For cold-presence power-on-device, select a GPIO for the output and program
|
||||
GPIO_BIT_CFG(0..50)[PIN_SEL] = GPIO_PIN_SEL_E:::SATA(0..15)_CP_-
|
||||
POD. */
|
||||
/* Skipping */
|
||||
|
||||
/* 3. Optionally program the SGPIO unit. */
|
||||
/* Skipping */
|
||||
|
||||
/* 4. Assert all resets:
|
||||
a. UAHC reset: SATA(0..15)_UCTL_CTL[SATA_UAHC_RST] = 1
|
||||
b. UCTL reset: SATA(0..15)_UCTL_CTL[SATA_UCTL_RST] = 1 */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.sata_uahc_rst = 1;
|
||||
c.s.sata_uctl_rst = 1);
|
||||
}
|
||||
|
||||
/* 5. Configure the ACLK:
|
||||
a. Reset the clock dividers: SATA(0..15)_UCTL_CTL[A_CLKDIV_RST] = 1.
|
||||
b. Select the ACLK frequency (refer to maximum values in Table 26 1).
|
||||
i. SATA(0..15)_UCTL_CTL[A_CLKDIV_SEL] = desired value,
|
||||
ii. SATA(0..15)_UCTL_CTL[A_CLK_EN] = 1 to enable the ACLK.
|
||||
c. Deassert the ACLK clock divider reset:
|
||||
SATA(0..15)_UCTL_CTL[A_CLKDIV_RST] = 0. */
|
||||
int divisor = (bdk_clock_get_rate(node, BDK_CLOCK_SCLK) + MAX_A_CLK - 1) / MAX_A_CLK;
|
||||
int a_clkdiv;
|
||||
/* This screwy if logic is from the description of
|
||||
SATAX_UCTL_CTL[a_clkdiv_sel] in the CSR */
|
||||
if (divisor <= 4)
|
||||
{
|
||||
a_clkdiv = divisor - 1;
|
||||
/* Divisor matches calculated value */
|
||||
}
|
||||
else if (divisor <= 6)
|
||||
{
|
||||
a_clkdiv = 4;
|
||||
divisor = 6;
|
||||
}
|
||||
else if (divisor <= 8)
|
||||
{
|
||||
a_clkdiv = 5;
|
||||
divisor = 8;
|
||||
}
|
||||
else if (divisor <= 16)
|
||||
{
|
||||
a_clkdiv = 6;
|
||||
divisor = 16;
|
||||
}
|
||||
else if (divisor <= 24)
|
||||
{
|
||||
a_clkdiv = 7;
|
||||
divisor = 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
bdk_error("Unable to determine SATA clock divisor\n");
|
||||
return -1;
|
||||
}
|
||||
/* Calculate the final clock rate */
|
||||
int a_clk = bdk_clock_get_rate(node, BDK_CLOCK_SCLK) / divisor;
|
||||
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.a_clkdiv_rst = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.a_clk_byp_sel = 0;
|
||||
c.s.a_clkdiv_sel = a_clkdiv;
|
||||
c.s.a_clk_en = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.a_clkdiv_rst = 0);
|
||||
}
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 8. Configure PHY for SATA. Refer to Section 21.1.2. */
|
||||
/* Done below, section 24.1.2.3 */
|
||||
|
||||
/* 9. TBD: Poll QLM2_MPLL_STATUS for MPLL lock */
|
||||
/* Not needed */
|
||||
|
||||
/* 10. Initialize UAHC as described in the AHCI specification
|
||||
(UAHC_* registers). */
|
||||
/* Done when a SATA driver is initialized */
|
||||
|
||||
/* 24.1.2.3 SATA Configuration
|
||||
Software must perform the following steps to configure the GSER_WEST
|
||||
for a SATA application. Note that the GSERW steps are on a QLM basis. */
|
||||
|
||||
/* 1. Configure the SATA controller (refer to Chapter 26). */
|
||||
/* This is the code above */
|
||||
|
||||
/* 2. Configure the QLM Reference clock.
|
||||
Set GSER(0..13)_REFCLK_SEL[COM_CLK_SEL] = 1 to source the reference
|
||||
clock from the external clock multiplexer.
|
||||
Configure GSER(0..13)_REFCLK_SEL[USE_COM1]:
|
||||
0 = use QLMC_REF_CLK0_P/N
|
||||
1 = use QLMC_REF_CLK1_P/N */
|
||||
/* Already done */
|
||||
|
||||
// FIXME: GSERN setup
|
||||
|
||||
/* 6. Deassert UCTL and UAHC resets:
|
||||
a. SATA(0..15)_UCTL_CTL[SATA_UAHC_RST] = 0
|
||||
b. SATA(0..15)_UCTL_CTL[SATA_UCTL_RST] = 0
|
||||
c. Wait 10 ACLK cycles before accessing any ACLK-only registers. */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.sata_uahc_rst = 0;
|
||||
c.s.sata_uctl_rst = 0);
|
||||
}
|
||||
bdk_wait_usec(1);
|
||||
|
||||
/* 7. Enable conditional SCLK of UCTL by writing
|
||||
SATA(0..15)_UCTL_CTL[CSCLK_EN] = 1. */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN8XXX))
|
||||
{
|
||||
/* CN9XXX make coprocessor clock automatic */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.cn8.csclk_en = 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check BIST on the SATA controller. Start BIST in parallel on the
|
||||
controllers */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
/* Make sure BIST is configured properly before we start it. We
|
||||
want full BIST, not just CLEAR */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.clear_bist = 0;
|
||||
c.s.start_bist = 0);
|
||||
/* Start BIST */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.start_bist = 1);
|
||||
}
|
||||
bdk_wait_usec(1000);
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_INIT(bist, node, BDK_SATAX_UCTL_BIST_STATUS(p));
|
||||
if (bist.u)
|
||||
bdk_error("N%d.SATA%d: Controller failed BIST (0x%llx)\n", node, p, bist.u);
|
||||
else
|
||||
BDK_TRACE(SATA, "N%d.SATA%d: Passed BIST\n", node, p);
|
||||
}
|
||||
/* Clear start_bist so it is ready for the next run */
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UCTL_CTL(p),
|
||||
c.s.start_bist = 0);
|
||||
}
|
||||
|
||||
int spd;
|
||||
if (baud_mhz < 3000)
|
||||
spd = 1;
|
||||
else if (baud_mhz < 6000)
|
||||
spd = 2;
|
||||
else
|
||||
spd = 3;
|
||||
|
||||
for (int p = sata_first; p <= sata_last; p++)
|
||||
{
|
||||
/* From the synopsis data book, SATAX_UAHC_GBL_TIMER1MS is the
|
||||
AMBA clock in MHz * 1000, which is a_clk(Hz) / 1000 */
|
||||
BDK_TRACE(QLM, "QLM%d: SATA%d set to %d Hz\n", qlm, p, a_clk);
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_GBL_TIMER1MS(p),
|
||||
c.s.timv = a_clk / 1000);
|
||||
/* Set speed */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_P0_SCTL(p),
|
||||
c.s.ipm = 3; /* Disable parial and slumber power management */
|
||||
c.s.spd = spd);
|
||||
/* The following SATA setup is from the AHCI 1.3 spec, section
|
||||
10.1.1, Firmware Specific Initialization. */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_GBL_CAP(p),
|
||||
c.s.sss = 1; /* Support staggered spin-up */
|
||||
c.s.smps = 1); /* Support mechanical presence switch */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_GBL_PI(p),
|
||||
c.s.pi = 1); /* One port per controller */
|
||||
BDK_CSR_MODIFY(c, node, BDK_SATAX_UAHC_P0_CMD(p),
|
||||
c.s.hpcp = 1; /* Hot-plug-capable support */
|
||||
c.s.mpsp = 1; /* Mechanical presence switch attached to port */
|
||||
c.s.cpd = 1); /* Cold-presence detection */
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
1636
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-common.c
Normal file
1636
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-common.c
Normal file
File diff suppressed because it is too large
Load Diff
398
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-errata-cn8xxx.c
Normal file
398
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-errata-cn8xxx.c
Normal file
@ -0,0 +1,398 @@
|
||||
/***********************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-gser.h"
|
||||
#include "libbdk-arch/bdk-csrs-rst.h"
|
||||
#include "libbdk-hal/qlm/bdk-qlm-errata-cn8xxx.h"
|
||||
|
||||
/**
|
||||
* Delay for the specified microseconds. When this code runs on secondary nodes
|
||||
* before full init, the normal bdk-clock functions do not work. This function
|
||||
* serves as a replacement that runs everywhere.
|
||||
*
|
||||
* @param usec Microseconds to wait
|
||||
*/
|
||||
static void wait_usec(bdk_node_t node, uint64_t usec)
|
||||
{
|
||||
const uint64_t REF_CLOCK = 50000000; /* This is currently defined to be 50Mhz */
|
||||
uint64_t refclock = BDK_CSR_READ(node, BDK_RST_REF_CNTR);
|
||||
uint64_t timeout = refclock + REF_CLOCK * usec / 1000000;
|
||||
while (refclock < timeout)
|
||||
{
|
||||
refclock = BDK_CSR_READ(node, BDK_RST_REF_CNTR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Errata GSER-25992 - RX EQ Default Settings Update<p>
|
||||
* For all GSER and all lanes when not PCIe EP:
|
||||
* set GSER()_LANE()_RX_CFG_4[CFG_RX_ERRDET_CTRL<13:8>] = 13 (decimal)
|
||||
* set GSER()_LANE()_RX_CTLE_CTRL[PCS_SDS_RX_CTLE_BIAS_CTRL] = 3
|
||||
* Applied when SERDES are configured for 8G and 10G.<p>
|
||||
* Applies to:
|
||||
* CN88XX pass 1.x
|
||||
* Fixed in hardware:
|
||||
* CN88XX pass 2.x
|
||||
* CN81XX
|
||||
* CN83XX
|
||||
*
|
||||
* @param node Node to apply errata fix for
|
||||
* @param qlm QLM to apply errata fix to
|
||||
* @param baud_mhz QLM speed in Mhz
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int __bdk_qlm_errata_gser_25992(bdk_node_t node, int qlm, int baud_mhz)
|
||||
{
|
||||
if (!CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
|
||||
return 0;
|
||||
if (baud_mhz < 8000)
|
||||
return 0;
|
||||
|
||||
int num_lanes = 4; /* Only applies to CN88XX, where always 4 lanes */
|
||||
for (int lane = 0; lane < num_lanes; lane++)
|
||||
{
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_RX_CTLE_CTRL(qlm, lane),
|
||||
c.s.pcs_sds_rx_ctle_bias_ctrl = 3);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_RX_CFG_4(qlm, lane),
|
||||
c.s.cfg_rx_errdet_ctrl = 0xcd6f);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* (GSER-26150) 10G PHY PLL Temperature Failure
|
||||
*
|
||||
* 10 Gb temperature excursions can cause lock failure. Change
|
||||
* the calibration point of the VCO at start up to shift some
|
||||
* available range of the VCO from -deltaT direction to the
|
||||
* +deltaT ramp direction allowing a greater range of VCO
|
||||
* temperatures before experiencing the failure.
|
||||
*
|
||||
* Applies to:
|
||||
* CN88XX pass 1.x
|
||||
* Fix in hardware:
|
||||
* CN88XX pass 2.x
|
||||
* CN81XX
|
||||
* CN83XX
|
||||
*
|
||||
* Only applies to QLMs running 8G and 10G
|
||||
*
|
||||
* @param node Node to apply errata to
|
||||
* @param qlm QLM to apply errata fix to
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int __bdk_qlm_errata_gser_26150(bdk_node_t node, int qlm, int baud_mhz)
|
||||
{
|
||||
if (!CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
|
||||
return 0;
|
||||
if (baud_mhz < 8000)
|
||||
return 0;
|
||||
|
||||
int num_lanes = 4; /* Only applies to CN88XX, where always 4 lanes */
|
||||
|
||||
BDK_CSR_INIT(gserx_cfg, node, BDK_GSERX_CFG(qlm));
|
||||
if (gserx_cfg.s.pcie)
|
||||
{
|
||||
/* Update PLL parameters */
|
||||
/* Step 1: Set GSER()_GLBL_PLL_CFG_3[PLL_VCTRL_SEL_LCVCO_VAL] = 0x2, and
|
||||
GSER()_GLBL_PLL_CFG_3[PCS_SDS_PLL_VCO_AMP] = 0 */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_GLBL_PLL_CFG_3(qlm),
|
||||
c.s.pll_vctrl_sel_lcvco_val = 0x2;
|
||||
c.s.pcs_sds_pll_vco_amp = 0);
|
||||
/* Step 2: Set GSER()_GLBL_MISC_CONFIG_1[PCS_SDS_TRIM_CHP_REG] = 0x2. */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_GLBL_MISC_CONFIG_1(qlm),
|
||||
c.s.pcs_sds_trim_chp_reg = 0x2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Applying this errata twice causes problems */
|
||||
BDK_CSR_INIT(pll_cfg_3, node, BDK_GSERX_GLBL_PLL_CFG_3(qlm));
|
||||
if (pll_cfg_3.s.pll_vctrl_sel_lcvco_val == 0x2)
|
||||
return 0;
|
||||
|
||||
/* Put PHY in P2 Power-down state Need to Power down all lanes in a
|
||||
QLM/DLM to force PHY to P2 state */
|
||||
for (int i=0; i<num_lanes; i++)
|
||||
{
|
||||
/* Step 1: Set GSER()_LANE(lane_n)_PCS_CTLIFC_0[CFG_TX_PSTATE_REQ_OVERRD_VAL] = 0x3
|
||||
Select P2 power state for Tx lane */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_0(qlm, i),
|
||||
c.s.cfg_tx_pstate_req_ovrrd_val = 0x3);
|
||||
/* Step 2: Set GSER()_LANE(lane_n)_PCS_CTLIFC_1[CFG_RX_PSTATE_REQ_OVERRD_VAL] = 0x3
|
||||
Select P2 power state for Rx lane */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_1(qlm, i),
|
||||
c.s.cfg_rx_pstate_req_ovrrd_val = 0x3);
|
||||
/* Step 3: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_TX_PSTATE_REQ_OVRRD_EN] = 1
|
||||
Enable Tx power state override and Set
|
||||
GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_RX_PSTATE_REQ_OVRRD_EN] = 1
|
||||
Enable Rx power state override */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, i),
|
||||
c.s.cfg_tx_pstate_req_ovrrd_en = 0x1;
|
||||
c.s.cfg_rx_pstate_req_ovrrd_en = 0X1);
|
||||
/* Step 4: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CTLIFC_OVRRD_REQ] = 1
|
||||
Start the CTLIFC override state machine */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, i),
|
||||
c.s.ctlifc_ovrrd_req = 0x1);
|
||||
}
|
||||
|
||||
/* Update PLL parameters */
|
||||
/* Step 5: Set GSER()_GLBL_PLL_CFG_3[PLL_VCTRL_SEL_LCVCO_VAL] = 0x2, and
|
||||
GSER()_GLBL_PLL_CFG_3[PCS_SDS_PLL_VCO_AMP] = 0 */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_GLBL_PLL_CFG_3(qlm),
|
||||
c.s.pll_vctrl_sel_lcvco_val = 0x2;
|
||||
c.s.pcs_sds_pll_vco_amp = 0);
|
||||
/* Step 6: Set GSER()_GLBL_MISC_CONFIG_1[PCS_SDS_TRIM_CHP_REG] = 0x2. */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_GLBL_MISC_CONFIG_1(qlm),
|
||||
c.s.pcs_sds_trim_chp_reg = 0x2);
|
||||
/* Wake up PHY and transition to P0 Power-up state to bring-up the lanes,
|
||||
need to wake up all PHY lanes */
|
||||
for (int i=0; i<num_lanes; i++)
|
||||
{
|
||||
/* Step 7: Set GSER()_LANE(lane_n)_PCS_CTLIFC_0[CFG_TX_PSTATE_REQ_OVERRD_VAL] = 0x0
|
||||
Select P0 power state for Tx lane */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_0(qlm, i),
|
||||
c.s.cfg_tx_pstate_req_ovrrd_val = 0x0);
|
||||
/* Step 8: Set GSER()_LANE(lane_n)_PCS_CTLIFC_1[CFG_RX_PSTATE_REQ_OVERRD_VAL] = 0x0
|
||||
Select P0 power state for Rx lane */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_1(qlm, i),
|
||||
c.s.cfg_rx_pstate_req_ovrrd_val = 0x0);
|
||||
/* Step 9: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_TX_PSTATE_REQ_OVRRD_EN] = 1
|
||||
Enable Tx power state override and Set
|
||||
GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_RX_PSTATE_REQ_OVRRD_EN] = 1
|
||||
Enable Rx power state override */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, i),
|
||||
c.s.cfg_tx_pstate_req_ovrrd_en = 0x1;
|
||||
c.s.cfg_rx_pstate_req_ovrrd_en = 0X1);
|
||||
/* Step 10: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CTLIFC_OVRRD_REQ] = 1
|
||||
Start the CTLIFC override state machine */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, i),
|
||||
c.s.ctlifc_ovrrd_req = 0x1);
|
||||
}
|
||||
|
||||
/* Step 11: Wait 10 msec */
|
||||
wait_usec(node, 10000);
|
||||
|
||||
/* Release Lane Tx/Rx Power state override enables. */
|
||||
for (int i=0; i<num_lanes; i++)
|
||||
{
|
||||
/* Step 12: Set GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_TX_PSTATE_REQ_OVRRD_EN] = 0
|
||||
Disable Tx power state override and Set
|
||||
GSER()_LANE(lane_n)_PCS_CTLIFC_2[CFG_RX_PSTATE_REQ_OVRRD_EN] = 0
|
||||
Disable Rx power state override */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, i),
|
||||
c.s.cfg_tx_pstate_req_ovrrd_en = 0x0;
|
||||
c.s.cfg_rx_pstate_req_ovrrd_en = 0X0);
|
||||
}
|
||||
/* Step 13: Poll GSER()_PLL_STAT.[PLL_LOCK] = 1
|
||||
Poll and check that PLL is locked */
|
||||
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_GSERX_PLL_STAT(qlm), pll_lock, ==, 1, 10000))
|
||||
{
|
||||
bdk_error("QLM%d: Timeout waiting for GSERX_PLL_STAT[pll_lock]\n", qlm);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Step 14: Poll GSER()_QLM_STAT.[RST_RDY] = 1
|
||||
Poll and check that QLM/DLM is Ready */
|
||||
if (BDK_CSR_WAIT_FOR_FIELD(node, BDK_GSERX_QLM_STAT(qlm), rst_rdy, ==, 1, 10000))
|
||||
{
|
||||
bdk_error("QLM%d: Timeout waiting for GSERX_QLM_STAT[rst_rdy]\n", qlm);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Errata (GSER-26636) 10G-KR/40G-KR - Inverted Tx Coefficient Direction Change
|
||||
* Applied to all 10G standards (required for KR) but also applied to other
|
||||
* standards in case software training is used.
|
||||
* Applies to:
|
||||
* CN88XX pass 1.x
|
||||
* Fixed in hardware:
|
||||
* CN88XX pass 2.x
|
||||
* CN81XX
|
||||
* CN83XX
|
||||
*
|
||||
* @param node Node to apply errata fix for
|
||||
* @param qlm QLM to apply errata fix to
|
||||
* @param baud_mhz QLM speed in Mhz
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int __bdk_qlm_errata_gser_26636(bdk_node_t node, int qlm, int baud_mhz)
|
||||
{
|
||||
if (!CAVIUM_IS_MODEL(CAVIUM_CN88XX_PASS1_X))
|
||||
return 0;
|
||||
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_RX_TXDIR_CTRL_1(qlm),
|
||||
c.s.rx_precorr_chg_dir = 1;
|
||||
c.s.rx_tap1_chg_dir = 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* (GSER-27140) SERDES has temperature drift sensitivity in the RX EQ<p>
|
||||
* SERDES temperature drift sensitivity in receiver. Issues have
|
||||
* been found with the Bit Error Rate (BER) reliability of
|
||||
* 10GBASE-KR links over the commercial temperature range (0 to 100C),
|
||||
* especially when subjected to rapid thermal ramp stress testing.
|
||||
* (See HRM for corresponding case temperature requirements for each speed grade.)<p>
|
||||
* Applies to:
|
||||
* CN88XX pass 1.x
|
||||
* CN88XX pass 2.x
|
||||
* CN83XX pass 1.x
|
||||
* CN81XX pass 1.x
|
||||
* Fixed in hardware:
|
||||
* TBD<p>
|
||||
* Only applies to QLMs running 10G
|
||||
*
|
||||
* @param node Note to apply errata fix to
|
||||
* @param qlm QLM to apply errata fix to
|
||||
* @param baud_mhz QLM baud rate in Mhz
|
||||
* @param channel_loss
|
||||
* Insertion loss at Nyquist rate (e.g. 5.125Ghz for XFI/XLAUI) in dB
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int __bdk_qlm_errata_gser_27140(bdk_node_t node, int qlm, int baud_mhz, int channel_loss)
|
||||
{
|
||||
if (baud_mhz != 10312)
|
||||
return 0;
|
||||
|
||||
/* A channel loss of -1 means the loss is unknown. A short channel is
|
||||
considered to have loss between 0 and 10 dB */
|
||||
bool short_channel = (channel_loss >= 0) && (channel_loss <= 10);
|
||||
|
||||
/* I. For each GSER QLM: */
|
||||
/* Workaround GSER-27140: */
|
||||
/* (1) GSER-26150 = Applied by the caller */
|
||||
/* (2) Write GSER()_LANE_VMA_FINE_CTRL_0[RX_SDLL_IQ_MAX_FINE] = 0xE */
|
||||
/* (3) Write GSER()_LANE_VMA_FINE_CTRL_0[RX_SDLL_IQ_MIN_FINE] = 0x8 */
|
||||
/* (4) Write GSER()_LANE_VMA_FINE_CTRL_0[RX_SDLL_IQ_STEP_FINE] = 0x2 */
|
||||
/* (5) Write GSER()_LANE_VMA_FINE_CTRL_0[VMA_WINDOW_WAIT_FINE] = 0x5 */
|
||||
/* (6) Write GSER()_LANE_VMA_FINE_CTRL_0[LMS_WAIT_TIME_FINE] = 0x5 */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANE_VMA_FINE_CTRL_0(qlm),
|
||||
c.s.rx_sdll_iq_max_fine = 0xE;
|
||||
c.s.rx_sdll_iq_min_fine = 0x8;
|
||||
c.s.rx_sdll_iq_step_fine = 0x2;
|
||||
c.s.vma_window_wait_fine = 0x5;
|
||||
c.s.lms_wait_time_fine = 0x5);
|
||||
/* (7) Write GSER()_LANE_VMA_FINE_CTRL_2[RX_PRECTLE_GAIN_MAX_FINE] = 0xB */
|
||||
/* (8) Write GSER()_LANE_VMA_FINE_CTRL_2[RX_PRECTLE_GAIN_MIN_FINE] = 0x6(long) or 0x0(short) */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANE_VMA_FINE_CTRL_2(qlm),
|
||||
c.s.rx_prectle_gain_max_fine = 0xB;
|
||||
c.s.rx_prectle_gain_min_fine = short_channel ? 0x0 : 0x6);
|
||||
/* (9) Write GSER()_RX_TXDIR_CTRL_0[RX_BOOST_LO_THRES] = 0x4 */
|
||||
/* (10) Write GSER()_RX_TXDIR_CTRL_0[RX_BOOST_HI_THRES] = 0xB */
|
||||
/* (11) Write GSER()_RX_TXDIR_CTRL_0[RX_BOOST_HI_VAL] = 0xF */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_RX_TXDIR_CTRL_0(qlm),
|
||||
c.s.rx_boost_lo_thrs = 0x4;
|
||||
c.s.rx_boost_hi_thrs = 0xB;
|
||||
c.s.rx_boost_hi_val = 0xF);
|
||||
/* (12) Write GSER()_RX_TXDIR_CTRL_1[RX_TAP1_LO_THRS] = 0x8 */
|
||||
/* (13) Write GSER()_RX_TXDIR_CTRL_1[RX_TAP1_HI_THRS] = 0x17 */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_RX_TXDIR_CTRL_1(qlm),
|
||||
c.s.rx_tap1_lo_thrs = 0x8;
|
||||
c.s.rx_tap1_hi_thrs = 0x17);
|
||||
|
||||
/* (14) Write GSER()_EQ_WAIT_TIME[RXEQ_WAIT_CNT] = 0x6 */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_EQ_WAIT_TIME(qlm),
|
||||
c.s.rxeq_wait_cnt = 0x6);
|
||||
/* (15) Write GSER()_RX_TXDIR_CTRL_2[RX_PRECORR_HI_THRS] = 0xC0 */
|
||||
/* (16) Write GSER()_RX_TXDIR_CTRL_2[RX_PRECORR_LO_THRS] = 0x40 */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_RX_TXDIR_CTRL_2(qlm),
|
||||
c.s.rx_precorr_hi_thrs = 0xc0;
|
||||
c.s.rx_precorr_lo_thrs = 0x40);
|
||||
|
||||
/* We can't call the normal bdk-qlm function as it uses pointers that
|
||||
don't work when running in secondary nodes before CCPI is up */
|
||||
int num_lanes = 4;
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN81XX) || (CAVIUM_IS_MODEL(CAVIUM_CN83XX) && (qlm >= 4)))
|
||||
num_lanes = 2;
|
||||
|
||||
/* II. For each GSER QLM SerDes lane: */
|
||||
/* Establish typical values, which are already reset values in pass 2: */
|
||||
for (int lane = 0; lane < num_lanes; lane++)
|
||||
{
|
||||
/* (17) For each GSER lane in the 10GBASE-KR link: */
|
||||
/* (a) Write GSER()_LANE()_RX_VALBBD_CTRL_0[AGC_GAIN] = 0x3 */
|
||||
/* (b) Write GSER()_LANE()_RX_VALBBD_CTRL_0[DFE_GAIN] = 0x2 */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_RX_VALBBD_CTRL_0(qlm, lane),
|
||||
c.s.agc_gain = 0x3;
|
||||
c.s.dfe_gain = 0x2);
|
||||
}
|
||||
|
||||
/* III. The GSER QLM SerDes Lanes are now ready. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Errata GSER-27882 -GSER 10GBASE-KR Transmit Equalizer
|
||||
* Training may not update PHY Tx Taps. This function is not static
|
||||
* so we can share it with BGX KR
|
||||
* Applies to:
|
||||
* CN88XX pass 1.x, 2.0, 2.1
|
||||
* Fixed in hardware:
|
||||
* CN88XX pass 2.2 and higher
|
||||
* CN81XX
|
||||
* CN83XX
|
||||
*
|
||||
* @param node Node to apply errata fix for
|
||||
* @param qlm QLM to apply errata fix to
|
||||
* @param lane
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int __bdk_qlm_errata_gser_27882(bdk_node_t node, int qlm, int lane)
|
||||
{
|
||||
/* Toggle Toggle Tx Coeff Req override to force an update */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_0(qlm, lane),
|
||||
c.s.cfg_tx_coeff_req_ovrrd_val = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, lane),
|
||||
c.s.cfg_tx_coeff_req_ovrrd_en = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, lane),
|
||||
c.s.ctlifc_ovrrd_req = 1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, lane),
|
||||
c.s.cfg_tx_coeff_req_ovrrd_en = 0);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PCS_CTLIFC_2(qlm, lane),
|
||||
c.s.ctlifc_ovrrd_req = 1);
|
||||
return 0;
|
||||
}
|
||||
|
271
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-margin-cn8xxx.c
Normal file
271
src/vendorcode/cavium/bdk/libbdk-hal/qlm/bdk-qlm-margin-cn8xxx.c
Normal file
@ -0,0 +1,271 @@
|
||||
/***********************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-gser.h"
|
||||
#include "libbdk-hal/if/bdk-if.h"
|
||||
#include "libbdk-hal/bdk-qlm.h"
|
||||
#include "libbdk-hal/bdk-utils.h"
|
||||
|
||||
/* This code is an optional part of the BDK. It is only linked in
|
||||
if BDK_REQUIRE() needs it */
|
||||
BDK_REQUIRE_DEFINE(QLM_MARGIN);
|
||||
|
||||
typedef union
|
||||
{
|
||||
struct
|
||||
{
|
||||
uint64_t rx_os_mvalbbd_2 :16;
|
||||
uint64_t rx_os_mvalbbd_1 :16;
|
||||
uint64_t reserved_63_32 :32;
|
||||
|
||||
} s;
|
||||
struct
|
||||
{
|
||||
uint64_t Qb :6;
|
||||
uint64_t Q :6;
|
||||
uint64_t Lb :6; // Spans the two registers
|
||||
uint64_t L :6;
|
||||
uint64_t qerr0 :6;
|
||||
int64_t reserved_63_30 :34;
|
||||
} f;
|
||||
uint64_t u;
|
||||
} rx_os_mvalbbd_t;
|
||||
|
||||
int __bdk_disable_ccpi_error_report = 0;
|
||||
|
||||
static int convert_to_signed_mag(int source)
|
||||
{
|
||||
/* Synopsis encoded sign in an unexpected way. 0=negative and 1=positive
|
||||
So bit 5 should be 0 for negative numbers, 1 for positive numbers */
|
||||
if (source < 0)
|
||||
source = -source;
|
||||
else
|
||||
source |= 0x20;
|
||||
return source;
|
||||
}
|
||||
|
||||
static rx_os_mvalbbd_t get_current_settings(bdk_node_t node, int qlm, int qlm_lane)
|
||||
{
|
||||
rx_os_mvalbbd_t mvalbbd;
|
||||
mvalbbd.u = 0;
|
||||
|
||||
BDK_CSR_INIT(rx_cfg_1, node, BDK_GSERX_LANEX_RX_CFG_1(qlm, qlm_lane));
|
||||
if (!rx_cfg_1.s.pcs_sds_rx_os_men)
|
||||
{
|
||||
/* Get the current settings */
|
||||
BDK_CSR_INIT(rx_os_out_1, node, BDK_GSERX_LANEX_RX_OS_OUT_1(qlm, qlm_lane));
|
||||
BDK_CSR_INIT(rx_os_out_2, node, BDK_GSERX_LANEX_RX_OS_OUT_2(qlm, qlm_lane));
|
||||
BDK_CSR_INIT(rx_os_out_3, node, BDK_GSERX_LANEX_RX_OS_OUT_3(qlm, qlm_lane));
|
||||
int qerr0 = bdk_extracts(rx_os_out_1.u, 0, 6);
|
||||
int lb = bdk_extracts(rx_os_out_2.u, 0, 6);
|
||||
int l = bdk_extracts(rx_os_out_2.u, 6, 6);
|
||||
int qb = bdk_extracts(rx_os_out_3.u, 0, 6);
|
||||
int q = bdk_extracts(rx_os_out_3.u, 6, 6);
|
||||
/* Enable the override with the current values */
|
||||
mvalbbd.f.Qb = convert_to_signed_mag(qb);
|
||||
mvalbbd.f.Q = convert_to_signed_mag(q);
|
||||
mvalbbd.f.Lb = convert_to_signed_mag(lb);
|
||||
mvalbbd.f.L = convert_to_signed_mag(l);
|
||||
mvalbbd.f.qerr0 = convert_to_signed_mag(qerr0);
|
||||
}
|
||||
else
|
||||
{
|
||||
BDK_CSR_INIT(mvalbbd_1, node, BDK_GSERX_LANEX_RX_OS_MVALBBD_1(qlm, qlm_lane));
|
||||
mvalbbd.s.rx_os_mvalbbd_1 = mvalbbd_1.s.pcs_sds_rx_os_mval;
|
||||
BDK_CSR_INIT(mvalbbd_2, node, BDK_GSERX_LANEX_RX_OS_MVALBBD_2(qlm, qlm_lane));
|
||||
mvalbbd.s.rx_os_mvalbbd_2 = mvalbbd_2.s.pcs_sds_rx_os_mval;
|
||||
}
|
||||
//printf("qerr0=%d, lb=%d, l=%d, qb=%d, q=%d\n",
|
||||
// mvalbbd.f.qerr0, mvalbbd.f.Lb, mvalbbd.f.L, mvalbbd.f.Qb, mvalbbd.f.Q);
|
||||
return mvalbbd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current RX margining parameter
|
||||
*
|
||||
* @param node Node to read margin value from
|
||||
* @param qlm QLM to read from
|
||||
* @param qlm_lane Lane to read
|
||||
* @param margin_type
|
||||
* Type of margining parameter to read
|
||||
*
|
||||
* @return Current margining parameter value
|
||||
*/
|
||||
int64_t bdk_qlm_margin_rx_get(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type)
|
||||
{
|
||||
rx_os_mvalbbd_t mvalbbd = get_current_settings(node, qlm, qlm_lane);
|
||||
|
||||
switch (margin_type)
|
||||
{
|
||||
case BDK_QLM_MARGIN_VERTICAL:
|
||||
if (mvalbbd.f.Q & 0x20) /* Check if sign bit says positive */
|
||||
return mvalbbd.f.Q & 0x1f; /* positive, strip off sign */
|
||||
else
|
||||
return -mvalbbd.f.Q; /* negative */
|
||||
case BDK_QLM_MARGIN_HORIZONTAL:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current RX margining parameter minimum value
|
||||
*
|
||||
* @param node Node to read margin value from
|
||||
* @param qlm QLM to read from
|
||||
* @param qlm_lane Lane to read
|
||||
* @param margin_type
|
||||
* Type of margining parameter to read
|
||||
*
|
||||
* @return Current margining parameter minimum value
|
||||
*/
|
||||
int64_t bdk_qlm_margin_rx_get_min(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type)
|
||||
{
|
||||
switch (margin_type)
|
||||
{
|
||||
case BDK_QLM_MARGIN_VERTICAL:
|
||||
return -31;
|
||||
case BDK_QLM_MARGIN_HORIZONTAL:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current RX margining parameter maximum value
|
||||
*
|
||||
* @param node Node to read margin value from
|
||||
* @param qlm QLM to read from
|
||||
* @param qlm_lane Lane to read
|
||||
* @param margin_type
|
||||
* Type of margining parameter to read
|
||||
*
|
||||
* @return Current margining parameter maximum value
|
||||
*/
|
||||
int64_t bdk_qlm_margin_rx_get_max(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type)
|
||||
{
|
||||
switch (margin_type)
|
||||
{
|
||||
case BDK_QLM_MARGIN_VERTICAL:
|
||||
return 31;
|
||||
case BDK_QLM_MARGIN_HORIZONTAL:
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the current RX margining parameter value
|
||||
*
|
||||
* @param node Node to set margin value on
|
||||
* @param qlm QLM to set
|
||||
* @param qlm_lane Lane to set
|
||||
* @param margin_type
|
||||
* Type of margining parameter to set
|
||||
* @param value Value of margining parameter
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_qlm_margin_rx_set(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type, int value)
|
||||
{
|
||||
rx_os_mvalbbd_t mvalbbd = get_current_settings(node, qlm, qlm_lane);
|
||||
|
||||
switch (margin_type)
|
||||
{
|
||||
case BDK_QLM_MARGIN_VERTICAL:
|
||||
if (value < 0)
|
||||
mvalbbd.f.Q = -value; /* Sign bit is zero, weird Synopsys */
|
||||
else
|
||||
mvalbbd.f.Q = value | 0x20; /* Sign bit is one, weird Synopsys */
|
||||
break;
|
||||
case BDK_QLM_MARGIN_HORIZONTAL:
|
||||
return -1;
|
||||
}
|
||||
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_RX_OS_MVALBBD_1(qlm, qlm_lane),
|
||||
c.s.pcs_sds_rx_os_mval = mvalbbd.s.rx_os_mvalbbd_1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_RX_OS_MVALBBD_2(qlm, qlm_lane),
|
||||
c.s.pcs_sds_rx_os_mval = mvalbbd.s.rx_os_mvalbbd_2);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_RX_CFG_1(qlm, qlm_lane),
|
||||
c.s.pcs_sds_rx_os_men = 1);
|
||||
|
||||
/* Disable the DFE(s), gives a better eye measurement */
|
||||
BDK_CSR_INIT(pwr_ctrl, node, BDK_GSERX_LANEX_PWR_CTRL(qlm, qlm_lane));
|
||||
if (!pwr_ctrl.s.rx_lctrl_ovrrd_en)
|
||||
{
|
||||
BDK_CSR_WRITE(node, BDK_GSERX_LANEX_RX_LOOP_CTRL(qlm, qlm_lane), 0xF1);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PWR_CTRL(qlm, qlm_lane),
|
||||
c.s.rx_lctrl_ovrrd_en = 1);
|
||||
}
|
||||
|
||||
if (qlm >= 8)
|
||||
__bdk_disable_ccpi_error_report = 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the supplied RX margining parameter value as if it was never set. This
|
||||
* disables any overrides in the SERDES need to perform margining
|
||||
*
|
||||
* @param node Node to restore margin value on
|
||||
* @param qlm QLM to restore
|
||||
* @param qlm_lane Lane to restore
|
||||
* @param margin_type
|
||||
* Type of margining parameter to restore
|
||||
* @param value Value of margining parameter
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
int bdk_qlm_margin_rx_restore(bdk_node_t node, int qlm, int qlm_lane, bdk_qlm_margin_t margin_type, int value)
|
||||
{
|
||||
BDK_CSR_INIT(rx_cfg_1, node, BDK_GSERX_LANEX_RX_CFG_1(qlm, qlm_lane));
|
||||
/* Return if no overrides have been applied */
|
||||
if (!rx_cfg_1.s.pcs_sds_rx_os_men)
|
||||
return 0;
|
||||
bdk_qlm_margin_rx_set(node, qlm, qlm_lane, margin_type, value);
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_RX_CFG_1(qlm, qlm_lane),
|
||||
c.s.pcs_sds_rx_os_men = 0);
|
||||
/* Enable the DFE(s) */
|
||||
BDK_CSR_MODIFY(c, node, BDK_GSERX_LANEX_PWR_CTRL(qlm, qlm_lane),
|
||||
c.s.rx_lctrl_ovrrd_en = 0);
|
||||
__bdk_disable_ccpi_error_report = 0;
|
||||
return 0;
|
||||
}
|
||||
|
@ -37,501 +37,7 @@
|
||||
* 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;
|
||||
}
|
||||
#include <libbdk-os/bdk-init.h>
|
||||
|
||||
/**
|
||||
* Get the coremask of the cores actively running the BDK. Doesn't count cores
|
||||
@ -543,7 +49,7 @@ int bdk_init_nodes(int skip_cores, int ccpi_sw_gbaud)
|
||||
*/
|
||||
uint64_t bdk_get_running_coremask(bdk_node_t node)
|
||||
{
|
||||
return __bdk_alive_coremask[node];
|
||||
return 0x1;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -556,6 +62,6 @@ uint64_t bdk_get_running_coremask(bdk_node_t node)
|
||||
*/
|
||||
int bdk_get_num_running_cores(bdk_node_t node)
|
||||
{
|
||||
return __builtin_popcountl(bdk_get_running_coremask(node));
|
||||
return bdk_pop(bdk_get_running_coremask(node));
|
||||
}
|
||||
|
||||
|
@ -1,384 +0,0 @@
|
||||
/***********************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 ¤t->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);
|
||||
}
|
||||
}
|
@ -37,225 +37,8 @@
|
||||
* 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);
|
||||
}
|
||||
#include <libbdk-trust/bdk-trust.h>
|
||||
|
||||
/**
|
||||
* Returns the current level of trust. Must be called after
|
||||
@ -265,22 +48,7 @@ skip_trust:
|
||||
*/
|
||||
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;
|
||||
// FIXME
|
||||
return BDK_TRUST_LEVEL_NONE;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,9 @@
|
||||
#include <bdk.h>
|
||||
#include "dram-internal.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <lame_string.h>
|
||||
|
||||
const char* lookup_env_parameter(const char *format, ...)
|
||||
{
|
||||
const char *s;
|
||||
@ -55,7 +58,7 @@ const char* lookup_env_parameter(const char *format, ...)
|
||||
{
|
||||
value = strtoul(s, NULL, 0);
|
||||
error_print("Parameter found in environment: %s = \"%s\" 0x%lx (%ld)\n",
|
||||
buffer, s, value, value);
|
||||
buffer, s, value, value);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@ -76,7 +79,7 @@ const char* lookup_env_parameter_ull(const char *format, ...)
|
||||
{
|
||||
value = strtoull(s, NULL, 0);
|
||||
error_print("Parameter found in environment: %s = 0x%016llx\n",
|
||||
buffer, value);
|
||||
buffer, value);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
@ -42,7 +42,9 @@
|
||||
* Intenral use only.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __DRAM_ENV_H_
|
||||
#define __DRAM_ENV_H_
|
||||
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)));
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -82,7 +82,7 @@ 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);
|
||||
int ecc_ena, int *settings, const char *title);
|
||||
|
||||
#define RODT_OHMS_COUNT 8
|
||||
#define RTT_NOM_OHMS_COUNT 8
|
||||
@ -94,4 +94,5 @@ display_DAC_DBI_settings(int node, int ddr_interface_num, int dac_or_dbi,
|
||||
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);
|
||||
//extern uint64_t pretty_psecs_to_mts(uint64_t psecs);
|
||||
extern unsigned long pretty_psecs_to_mts(uint64_t psecs); /* FIXME(dhendrix) */
|
||||
|
@ -46,7 +46,9 @@
|
||||
* from the libdram directory
|
||||
*/
|
||||
|
||||
#include "libdram.h"
|
||||
/* FIXME(dhendrix): include path */
|
||||
//#include "libdram.h"
|
||||
#include <libdram/libdram.h>
|
||||
#include "lib_octeon_shared.h"
|
||||
#include "dram-print.h"
|
||||
#include "dram-util.h"
|
||||
|
@ -39,6 +39,10 @@
|
||||
#include <bdk.h>
|
||||
#include "dram-internal.h"
|
||||
|
||||
/* FIXME(dhendrix): added */
|
||||
#include <libbdk-hal/bdk-l2c.h>
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
|
||||
int limit_l2_ways(bdk_node_t node, int ways, int verbose)
|
||||
{
|
||||
int ways_max = bdk_l2c_get_num_assoc(node);
|
||||
|
@ -69,6 +69,8 @@ extern dram_verbosity_t dram_verbosity;
|
||||
#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))
|
||||
|
||||
/* FIXME(dhendrix): printf... */
|
||||
#if 0
|
||||
#define VB_PRT(level, format, ...) \
|
||||
do { \
|
||||
if (dram_is_verbose(level)) \
|
||||
@ -84,3 +86,20 @@ extern dram_verbosity_t dram_verbosity;
|
||||
#else
|
||||
#define debug_print(format, ...) do {} while (0)
|
||||
#endif
|
||||
#endif
|
||||
#include <console/console.h>
|
||||
#define VB_PRT(level, format, ...) \
|
||||
do { \
|
||||
if (dram_is_verbose(level)) \
|
||||
printk(BIOS_DEBUG, format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
#define ddr_print(format, ...) VB_PRT(VBL_NORM, format, ##__VA_ARGS__)
|
||||
|
||||
#define error_print(format, ...) printk(BIOS_ERR, format, ##__VA_ARGS__)
|
||||
|
||||
#ifdef DEBUG_DEBUG_PRINT
|
||||
#define debug_print(format, ...) printk(BIOS_DEBUG, format, ##__VA_ARGS__)
|
||||
#else
|
||||
#define debug_print(format, ...) do {} while (0)
|
||||
#endif
|
||||
|
@ -37,9 +37,16 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
#include <ctype.h>
|
||||
#include "dram-internal.h"
|
||||
|
||||
#include <bdk-minimal.h>
|
||||
#include <libbdk-arch/bdk-warn.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-hal/bdk-twsi.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.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
|
||||
@ -52,8 +59,12 @@
|
||||
*
|
||||
* @return Zero on success, negative on failure
|
||||
*/
|
||||
static uint8_t spd_bufs[4 * 256]; /* FIXME(dhendrix): storage for SPD buffers, assume DDR4 */
|
||||
int read_entire_spd(bdk_node_t node, dram_config_t *cfg, int lmc, int dimm)
|
||||
{
|
||||
/* FIXME(dhendrix): hack to get around using allocated mem */
|
||||
assert(dimm < 4);
|
||||
|
||||
/* 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;
|
||||
@ -69,13 +80,18 @@ int read_entire_spd(bdk_node_t node, dram_config_t *cfg, int lmc, int dimm)
|
||||
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;
|
||||
// FIXME: prudolph: Nobody needs 512 byte SPDs...
|
||||
//int spd_size = (dev_type == 0x0c) ? 512 : 256;
|
||||
int spd_size = 256;
|
||||
|
||||
/* Allocate storage */
|
||||
uint32_t *spd_buf = malloc(spd_size);
|
||||
if (!spd_buf)
|
||||
return -1;
|
||||
uint32_t *ptr = spd_buf;
|
||||
/*
|
||||
* FIXME: Assume DIMM doesn't support
|
||||
* 'Hybrid Module Extended Function Parameters' aka only 256 Byte SPD,
|
||||
* as the code below is broken ...
|
||||
*/
|
||||
assert(spd_size == 256);
|
||||
uint8_t *spd_buf = &spd_bufs[dimm * 256];
|
||||
uint32_t *ptr = (uint32_t *)spd_buf;
|
||||
|
||||
for (int bank = 0; bank < (spd_size >> 8); bank++)
|
||||
{
|
||||
@ -104,7 +120,9 @@ int read_entire_spd(bdk_node_t node, dram_config_t *cfg, int lmc, int dimm)
|
||||
}
|
||||
|
||||
/* Store the SPD in the device tree */
|
||||
bdk_config_set_blob(spd_size, spd_buf, BDK_CONFIG_DDR_SPD_DATA, dimm, lmc, node);
|
||||
/* FIXME(dhendrix): No need for this? cfg gets updated, so the caller
|
||||
* (libdram_config()) has what it needs. */
|
||||
// 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;
|
||||
@ -350,14 +368,14 @@ static uint32_t get_dimm_checksum(bdk_node_t node, const dimm_config_t *dimm_con
|
||||
|
||||
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,
|
||||
const char **dimm_types, int ddr_type, const 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;
|
||||
const 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);
|
||||
@ -405,7 +423,7 @@ void report_ddr3_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
|
||||
int dram_width, int dimm_size_mb)
|
||||
{
|
||||
int spd_voltage;
|
||||
char *volt_str;
|
||||
const char *volt_str;
|
||||
|
||||
spd_voltage = read_spd(node, dimm_config, DDR3_SPD_NOMINAL_VOLTAGE);
|
||||
if ((spd_voltage == 0) || (spd_voltage & 3))
|
||||
@ -445,7 +463,7 @@ void report_ddr4_dimm(bdk_node_t node, const dimm_config_t *dimm_config,
|
||||
int dram_width, int dimm_size_mb)
|
||||
{
|
||||
int spd_voltage;
|
||||
char *volt_str;
|
||||
const char *volt_str;
|
||||
|
||||
spd_voltage = read_spd(node, dimm_config, DDR4_SPD_MODULE_NOMINAL_VOLTAGE);
|
||||
if ((spd_voltage == 0x01) || (spd_voltage & 0x02))
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -42,6 +42,8 @@
|
||||
* are not meant for users's of the libdram API.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
/* FIXME(dhendrix): min/max are defined in stdlib.h */
|
||||
/**
|
||||
* Standard min(a,b) macro
|
||||
*/
|
||||
@ -56,6 +58,7 @@
|
||||
#define max(X, Y) \
|
||||
({ typeof (X) __x = (X); typeof(Y) __y = (Y); \
|
||||
(__x > __y) ? __x : __y; })
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Absolute value of an integer
|
||||
|
@ -43,6 +43,10 @@
|
||||
#include "libbdk-arch/bdk-csrs-l2c.h"
|
||||
#include "dram-internal.h"
|
||||
|
||||
#include "dram-env.h"
|
||||
#include <libbdk-hal/bdk-rng.h>
|
||||
#include <lame_string.h>
|
||||
|
||||
/* Define DDR_DEBUG to debug the DDR interface. This also enables the
|
||||
** output necessary for review by Cavium Inc., Inc. */
|
||||
/* #define DDR_DEBUG */
|
||||
@ -166,8 +170,8 @@ static int init_octeon_dram_interface(bdk_node_t node,
|
||||
}
|
||||
}
|
||||
|
||||
error_print("N%d.LMC%d Configuration Completed: %d MB\n",
|
||||
node, ddr_interface_num, mem_size_mbytes);
|
||||
printf("N%d.LMC%d Configuration Completed: %d MB\n",
|
||||
node, ddr_interface_num, mem_size_mbytes);
|
||||
return mem_size_mbytes;
|
||||
}
|
||||
|
||||
@ -503,7 +507,7 @@ int test_dram_byte_hw(bdk_node_t node, int ddr_interface_num,
|
||||
errors = 0;
|
||||
|
||||
bdk_dram_address_extract_info(p, &node_address, &lmc, &dimm, &prank, &lrank, &bank, &row, &col);
|
||||
VB_PRT(VBL_DEV2, "test_dram_byte_hw: START at A:0x%012lx, N%d L%d D%d R%d/%d B%1x Row:%05x Col:%05x\n",
|
||||
VB_PRT(VBL_DEV2, "test_dram_byte_hw: START at A:0x%012llx, N%d L%d D%d R%d/%d B%1x Row:%05x Col:%05x\n",
|
||||
p, node_address, lmc, dimm, prank, lrank, bank, row, col);
|
||||
|
||||
// only check once per call, and ignore if no match...
|
||||
@ -540,7 +544,7 @@ int test_dram_byte_hw(bdk_node_t node, int ddr_interface_num,
|
||||
p1 = p + k;
|
||||
|
||||
bdk_dram_address_extract_info(p1, &node_address, &lmc, &dimm, &prank, &lrank, &bank, &row, &col);
|
||||
VB_PRT(VBL_DEV3, "test_dram_byte_hw: NEXT interation at A:0x%012lx, N%d L%d D%d R%d/%d B%1x Row:%05x Col:%05x\n",
|
||||
VB_PRT(VBL_DEV3, "test_dram_byte_hw: NEXT interation at A:0x%012llx, N%d L%d D%d R%d/%d B%1x Row:%05x Col:%05x\n",
|
||||
p1, node_address, lmc, dimm, prank, lrank, bank, row, col);
|
||||
|
||||
/*
|
||||
@ -1013,7 +1017,7 @@ int initialize_ddr_clock(bdk_node_t node,
|
||||
|
||||
// always write LMC0 CSR, it must be active
|
||||
DRAM_CSR_WRITE(node, BDK_LMCX_DDR_PLL_CTL(0), ddr_pll_ctl.u);
|
||||
ddr_print("%-45s : 0x%016lx\n", "LMC0: DDR_PLL_CTL", ddr_pll_ctl.u);
|
||||
ddr_print("%-45s : 0x%016llx\n", "LMC0: DDR_PLL_CTL", ddr_pll_ctl.u);
|
||||
|
||||
// only when LMC1 is active
|
||||
// NOTE: 81xx has only 1 LMC, and 83xx can operate in 1-LMC mode
|
||||
@ -1030,7 +1034,7 @@ int initialize_ddr_clock(bdk_node_t node,
|
||||
|
||||
// always write LMC1 CSR when it is active
|
||||
DRAM_CSR_WRITE(node, BDK_LMCX_DDR_PLL_CTL(1), ddr_pll_ctl.u);
|
||||
ddr_print("%-45s : 0x%016lx\n", "LMC1: DDR_PLL_CTL", ddr_pll_ctl.u);
|
||||
ddr_print("%-45s : 0x%016llx\n", "LMC1: DDR_PLL_CTL", ddr_pll_ctl.u);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1107,7 +1111,7 @@ int initialize_ddr_clock(bdk_node_t node,
|
||||
if (clkf > max_clkf) continue; /* PLL requires clkf to be limited */
|
||||
if (_abs(error) > _abs(best_error)) continue;
|
||||
|
||||
VB_PRT(VBL_TME, "clkr: %2lu, en[%d]: %2d, clkf: %4lu, pll_MHz: %4lu, ddr_hertz: %8lu, error: %8ld\n",
|
||||
VB_PRT(VBL_TME, "clkr: %2llu, en[%d]: %2d, clkf: %4llu, pll_MHz: %4llu, ddr_hertz: %8llu, error: %8lld\n",
|
||||
clkr, save_en_idx, _en[save_en_idx], clkf, pll_MHz, calculated_ddr_hertz, error);
|
||||
|
||||
/* Favor the highest PLL frequency. */
|
||||
@ -1143,7 +1147,7 @@ int initialize_ddr_clock(bdk_node_t node,
|
||||
best_error = ddr_hertz - best_calculated_ddr_hertz;
|
||||
}
|
||||
|
||||
ddr_print("clkr: %2lu, en[%d]: %2d, clkf: %4lu, pll_MHz: %4lu, ddr_hertz: %8lu, error: %8ld <==\n",
|
||||
ddr_print("clkr: %2llu, en[%d]: %2d, clkf: %4llu, pll_MHz: %4llu, ddr_hertz: %8llu, error: %8lld <==\n",
|
||||
best_clkr, best_en_idx, _en[best_en_idx], best_clkf, best_pll_MHz,
|
||||
best_calculated_ddr_hertz, best_error);
|
||||
|
||||
@ -1177,7 +1181,7 @@ int initialize_ddr_clock(bdk_node_t node,
|
||||
|
||||
// make sure we preserve any settings already there
|
||||
ddr_pll_ctl.u = BDK_CSR_READ(node, BDK_LMCX_DDR_PLL_CTL(loop_interface_num));
|
||||
ddr_print("LMC%d: DDR_PLL_CTL : 0x%016lx\n",
|
||||
ddr_print("LMC%d: DDR_PLL_CTL : 0x%016llx\n",
|
||||
loop_interface_num, ddr_pll_ctl.u);
|
||||
|
||||
ddr_pll_ctl.cn83xx.ddr_ps_en = best_en_idx;
|
||||
@ -1187,7 +1191,7 @@ int initialize_ddr_clock(bdk_node_t node,
|
||||
ddr_pll_ctl.cn83xx.bwadj = new_bwadj;
|
||||
|
||||
DRAM_CSR_WRITE(node, BDK_LMCX_DDR_PLL_CTL(loop_interface_num), ddr_pll_ctl.u);
|
||||
ddr_print("LMC%d: DDR_PLL_CTL : 0x%016lx\n",
|
||||
ddr_print("LMC%d: DDR_PLL_CTL : 0x%016llx\n",
|
||||
loop_interface_num, ddr_pll_ctl.u);
|
||||
}
|
||||
}
|
||||
@ -1579,7 +1583,7 @@ int initialize_ddr_clock(bdk_node_t node,
|
||||
lmc_phy_ctl.u = BDK_CSR_READ(node, BDK_LMCX_PHY_CTL(loop_interface_num));
|
||||
lmc_phy_ctl.cn83xx.lv_mode = (~loop_interface_num) & 1; /* Odd LMCs = 0, Even LMCs = 1 */
|
||||
|
||||
ddr_print("LMC%d: PHY_CTL : 0x%016lx\n",
|
||||
ddr_print("LMC%d: PHY_CTL : 0x%016llx\n",
|
||||
loop_interface_num, lmc_phy_ctl.u);
|
||||
DRAM_CSR_WRITE(node, BDK_LMCX_PHY_CTL(loop_interface_num), lmc_phy_ctl.u);
|
||||
}
|
||||
@ -1860,7 +1864,7 @@ restart_training:
|
||||
// NOTE: return is a bitmask of the erroring bytelanes - we only print it
|
||||
errors = test_dram_byte_hw(node, lmc, phys_addr, DBTRAIN_DBI, NULL);
|
||||
|
||||
ddr_print("N%d.LMC%d: DBI switchover: TEST: rank %d, phys_addr 0x%lx, errors 0x%x.\n",
|
||||
ddr_print("N%d.LMC%d: DBI switchover: TEST: rank %d, phys_addr 0x%llx, errors 0x%x.\n",
|
||||
node, lmc, rankx, phys_addr, errors);
|
||||
|
||||
// NEXT - check for locking
|
||||
@ -1895,7 +1899,7 @@ restart_training:
|
||||
// end of DBI switchover
|
||||
///////////////////////////////////////////////////////////
|
||||
|
||||
uint32_t measure_octeon_ddr_clock(bdk_node_t node,
|
||||
static uint32_t measure_octeon_ddr_clock(bdk_node_t node,
|
||||
const ddr_configuration_t *ddr_configuration,
|
||||
uint32_t cpu_hertz,
|
||||
uint32_t ddr_hertz,
|
||||
@ -1926,17 +1930,14 @@ uint32_t measure_octeon_ddr_clock(bdk_node_t node,
|
||||
core_clocks = bdk_clock_get_count(BDK_CLOCK_TIME) - core_clocks;
|
||||
calc_ddr_hertz = ddr_clocks * bdk_clock_get_rate(bdk_numa_local(), BDK_CLOCK_TIME) / core_clocks;
|
||||
|
||||
/* Asim doesn't have a DDR clock, force the measurement to be correct */
|
||||
if (bdk_is_platform(BDK_PLATFORM_ASIM))
|
||||
calc_ddr_hertz = ddr_hertz;
|
||||
|
||||
ddr_print("LMC%d: Measured DDR clock: %lu, cpu clock: %u, ddr clocks: %lu\n",
|
||||
ddr_print("LMC%d: Measured DDR clock: %llu, cpu clock: %u, ddr clocks: %llu\n",
|
||||
ddr_interface_num, calc_ddr_hertz, cpu_hertz, ddr_clocks);
|
||||
|
||||
/* Check for unreasonable settings. */
|
||||
if (calc_ddr_hertz == 0) {
|
||||
error_print("DDR clock misconfigured. Exiting.\n");
|
||||
exit(1);
|
||||
/* FIXME(dhendrix): We don't exit() in coreboot */
|
||||
// exit(1);
|
||||
}
|
||||
return calc_ddr_hertz;
|
||||
}
|
||||
|
@ -38,6 +38,14 @@
|
||||
***********************license end**************************************/
|
||||
#include <bdk.h>
|
||||
|
||||
/* FIXME(dhendrix): added */
|
||||
#include <console/console.h> /* for die() */
|
||||
#include <string.h>
|
||||
#include <libbdk-arch/bdk-model.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <soc/twsi.h>
|
||||
#include <device/i2c_simple.h>
|
||||
|
||||
/**
|
||||
* Load a "odt_*rank_config" structure
|
||||
*
|
||||
@ -157,10 +165,12 @@ const dram_config_t *libdram_config_load(bdk_node_t node)
|
||||
}
|
||||
else
|
||||
{
|
||||
#if 0
|
||||
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;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,9 +36,20 @@
|
||||
* 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 <libbdk-arch/bdk-csrs-mio_fus.h>
|
||||
#include <libbdk-dram/bdk-dram-config.h>
|
||||
#include <libbdk-hal/bdk-config.h>
|
||||
#include <libbdk-hal/bdk-gpio.h>
|
||||
#include <libbdk-hal/bdk-l2c.h>
|
||||
#include <libbdk-hal/bdk-utils.h>
|
||||
#include <libbdk-os/bdk-init.h>
|
||||
#include <libdram/libdram-config.h>
|
||||
#include "dram-internal.h"
|
||||
#include <stddef.h> /* for NULL */
|
||||
#include <lame_string.h> /* for strtol() and friends */
|
||||
|
||||
|
||||
/* This global variable is accessed through dram_is_verbose() to determine
|
||||
the verbosity level. Use that function instead of setting it directly */
|
||||
@ -55,35 +66,33 @@ 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;
|
||||
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);
|
||||
}
|
||||
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%llx\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%llx length 0x%llx\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)
|
||||
@ -110,7 +119,7 @@ static void bdk_dram_enable_ecc_reporting(bdk_node_t node)
|
||||
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",
|
||||
ddr_print("N%d.LMC%d: %-36s : 0x%08llx\n",
|
||||
node, lmc, "LMC_INT_ENA_W1S", lmc_int_ena_w1s.u);
|
||||
}
|
||||
}
|
||||
@ -130,7 +139,7 @@ static void bdk_dram_disable_ecc_reporting(bdk_node_t node)
|
||||
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",
|
||||
ddr_print("N%d.LMC%d: %-36s : 0x%08llx\n",
|
||||
node, lmc, "LMC_INT_ENA_W1C", lmc_int_ena_w1c.u);
|
||||
}
|
||||
}
|
||||
@ -171,14 +180,15 @@ static int bdk_libdram_tune_node(int node)
|
||||
// Automatically tune the data byte DLL write offsets
|
||||
// allow override of default setting
|
||||
str = getenv("ddr_tune_write_offsets");
|
||||
str = NULL;
|
||||
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;
|
||||
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?
|
||||
@ -287,9 +297,6 @@ static int bdk_libdram_maybe_tune_node(int node)
|
||||
*/
|
||||
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);
|
||||
@ -446,7 +453,7 @@ int libdram_tune(int node)
|
||||
// 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",
|
||||
ddr_print("N%d: %s: Starting cores (mask was 0x%llx)\n",
|
||||
node, __FUNCTION__, bdk_get_running_coremask(node));
|
||||
bdk_init_cores(node, ~0ULL);
|
||||
|
||||
@ -600,7 +607,7 @@ int libdram_margin_read_timing(int node)
|
||||
int libdram_margin(int node)
|
||||
{
|
||||
int ret_rt, ret_wt, ret_rv, ret_wv;
|
||||
char *risk[2] = { "Low Risk", "Needs Review" };
|
||||
const 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...
|
||||
@ -614,7 +621,7 @@ int libdram_margin(int node)
|
||||
// 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",
|
||||
ddr_print("N%d: %s: Starting cores (mask was 0x%llx)\n",
|
||||
node, __FUNCTION__, bdk_get_running_coremask(node));
|
||||
bdk_init_cores(node, ~0ULL);
|
||||
|
||||
@ -712,7 +719,7 @@ uint32_t libdram_get_freq_from_pll(int node, int lmc)
|
||||
#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);
|
||||
VB_PRT(VBL_CSRS, "N%d: DDR Config %s[%016llx] => %016llx\n", node, csr_name, address, value);
|
||||
bdk_csr_write(node, type, busnum, size, address, value);
|
||||
}
|
||||
#endif
|
||||
|
20
src/vendorcode/cavium/include/bdk/bdk-devicetree.h
Normal file
20
src/vendorcode/cavium/include/bdk/bdk-devicetree.h
Normal file
@ -0,0 +1,20 @@
|
||||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; version 2 of the License.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
*/
|
||||
|
||||
struct bdk_devicetree_key_value {
|
||||
const char *key;
|
||||
const char *value;
|
||||
};
|
60
src/vendorcode/cavium/include/bdk/bdk-minimal.h
Normal file
60
src/vendorcode/cavium/include/bdk/bdk-minimal.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* bdk-minimal.h: Subset of bdk.h used by coreboot
|
||||
*/
|
||||
|
||||
#ifndef __SOC_CAVIUM_COMMON_BDK_MINIMAL_H__
|
||||
#define __SOC_CAVIUM_COMMON_BDK_MINIMAL_H__
|
||||
|
||||
#include <console/console.h> /* for printk */
|
||||
#include <endian.h>
|
||||
#include <stddef.h> /* for NULL */
|
||||
#include <libbdk-hal/bdk-access.h>
|
||||
|
||||
#define bdk_le16_to_cpu(x) le16_to_cpu(x)
|
||||
#define bdk_le32_to_cpu(x) le32_to_cpu(x)
|
||||
#define bdk_le64_to_cpu(x) le64_to_cpu(x)
|
||||
#define bdk_be16_to_cpu(x) be16_to_cpu(x)
|
||||
#define bdk_be32_to_cpu(x) be32_to_cpu(x)
|
||||
#define bdk_be64_to_cpu(x) be64_to_cpu(x)
|
||||
#define bdk_cpu_to_le16(x) cpu_to_le16(x)
|
||||
#define bdk_cpu_to_le32(x) cpu_to_le32(x)
|
||||
#define bdk_cpu_to_le64(x) cpu_to_le64(x)
|
||||
|
||||
#define __BYTE_ORDER __BYTE_ORDER__
|
||||
/* Watch out for __BIG_ENDIAN. coreboot usually checks if it's defined at all
|
||||
* but the Cavium BDK checks its value. */
|
||||
#define __BIG_ENDIAN 4321
|
||||
|
||||
#define printf(format, ...) printk(BIOS_DEBUG, format, ##__VA_ARGS__)
|
||||
#define puts(str) printk(BIOS_INFO, str)
|
||||
#define fflush(x) /* output gets flushed automatically */
|
||||
|
||||
/* careful, the ordering matters for some headers */
|
||||
#include <libbdk-arch/bdk-warn.h>
|
||||
#include <libbdk-arch/bdk-asm.h>
|
||||
#include <libbdk-arch/bdk-model.h>
|
||||
#include <libbdk-arch/bdk-numa.h>
|
||||
|
||||
#include <libbdk-arch/bdk-require.h>
|
||||
#include <libbdk-arch/bdk-csr.h>
|
||||
|
||||
#include <libbdk-os/bdk-thread.h>
|
||||
|
||||
/* FIXME: experiment to see if including the universe here will solve some
|
||||
* current build issues... */
|
||||
#include <libbdk-arch/bdk-arch.h>
|
||||
#include <libbdk-boot/bdk-boot.h>
|
||||
#include <libbdk-dram/bdk-dram.h>
|
||||
#include <libdram/libdram.h>
|
||||
|
||||
static inline char *getenv(const char *name) { return NULL; }
|
||||
|
||||
#endif /* !__SOC_CAVIUM_COMMON_BDK_MINIMAL_H__ */
|
@ -1,80 +1,18 @@
|
||||
#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
|
||||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Master include file for all BDK function.
|
||||
* Copyright 2017-present Facebook, Inc.
|
||||
*
|
||||
* <hr>$Revision: 49448 $<hr>
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*
|
||||
* bdk.h: This is a stub for BDK compatibility. The real bdk.h is an uber-
|
||||
* header that pulls in everything. For our purposes we'll create a minimal
|
||||
* version that includes only the stuff we need.
|
||||
*/
|
||||
|
||||
#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"
|
||||
#ifndef __SOC_CAVIUM_COMMON_BDK_H__
|
||||
#define __SOC_CAVIUM_COMMON_BDK_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.
|
||||
*/
|
||||
#include "bdk-minimal.h"
|
||||
|
||||
#endif
|
||||
#endif /* !__SOC_CAVIUM_COMMON_BDK_H__ */
|
||||
|
19
src/vendorcode/cavium/include/bdk/lame_string.h
Normal file
19
src/vendorcode/cavium/include/bdk/lame_string.h
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
* This file is part of the coreboot project.
|
||||
*
|
||||
* Copyright 2018-present Facebook, Inc.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifndef __LAME_STRING_H__
|
||||
#define __LAME_STRING_H__
|
||||
|
||||
long int strtol(const char *nptr, char **endptr, int base);
|
||||
long long int strtoll(const char *nptr, char **endptr, int base);
|
||||
unsigned long int strtoul(const char *nptr, char **endptr, int base);
|
||||
unsigned long long int strtoull(const char *nptr, char **endptr, int base);
|
||||
int str_to_hex(const char *str, int64_t *val);
|
||||
int str_to_int(const char *str, int64_t *val);
|
||||
|
||||
#endif
|
@ -48,24 +48,24 @@
|
||||
* <hr>$Revision: 49448 $<hr>
|
||||
*/
|
||||
|
||||
#include <arch/byteorder.h>
|
||||
|
||||
#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__
|
||||
#if (__LITTLE_ENDIAN)
|
||||
#define __BYTE_ORDER __LITTLE_ENDIAN
|
||||
#elif defined(__BIG_ENDIAN)
|
||||
#define __BYTE_ORDER __BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __LITTLE_ENDIAN
|
||||
#define __LITTLE_ENDIAN 1234
|
||||
#endif
|
||||
#ifndef __BIG_ENDIAN
|
||||
#define __BIG_ENDIAN 4321
|
||||
#endif
|
||||
|
||||
#include "bdk-require.h"
|
||||
#include "bdk-swap.h"
|
||||
#ifndef BDK_BUILD_HOST
|
||||
#include "bdk-asm.h"
|
||||
#endif
|
||||
@ -76,10 +76,8 @@
|
||||
#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
|
||||
|
@ -1,3 +1,5 @@
|
||||
#ifndef __CB_BDK_CSR_H__
|
||||
#define __CB_BDK_CSR_H__
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
@ -37,6 +39,9 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
|
||||
//#include <libbdk-arch/bdk-csrs-rst.h> /* FIXME: circular dependency with this header */
|
||||
#include <libbdk-hal/bdk-clock.h> /* FIXME(dhendrix): added */
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
@ -106,7 +111,7 @@ extern int bdk_csr_write_by_name(bdk_node_t node, const char *name, uint64_t val
|
||||
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 struct bdk_readline_tab *__bdk_csr_get_tab_complete(void) 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);
|
||||
|
||||
@ -125,10 +130,11 @@ extern void bdk_sysreg_write(int node, int core, uint64_t regnum, uint64_t value
|
||||
*
|
||||
* @return The value of the CSR
|
||||
*/
|
||||
/* FIXME(dhendrix): Moved __bdk_csr_read_slow out of the function body... */
|
||||
extern uint64_t __bdk_csr_read_slow(bdk_node_t node, bdk_csr_type_t type, int busnum, int size, uint64_t address);
|
||||
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:
|
||||
@ -174,10 +180,11 @@ static inline uint64_t bdk_csr_read(bdk_node_t node, bdk_csr_type_t type, int bu
|
||||
* @param address The address of the CSR
|
||||
* @param value Value to write to the CSR
|
||||
*/
|
||||
/* FIXME(dhendrix): Moved __bdk_csr_write_slow out of the function body... */
|
||||
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);
|
||||
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:
|
||||
@ -264,6 +271,8 @@ static inline void bdk_csr_write(bdk_node_t node, bdk_csr_type_t type, int busnu
|
||||
* 2) Check if ("type".s."field" "op" "value")
|
||||
* 3) If #2 isn't true loop to #1 unless too much time has passed.
|
||||
*/
|
||||
/* FIXME(dhendrix): removed bdk_thread_yield() */
|
||||
#if 0
|
||||
#define BDK_CSR_WAIT_FOR_FIELD(node, csr, field, op, value, timeout_usec) \
|
||||
({int result; \
|
||||
do { \
|
||||
@ -285,6 +294,27 @@ static inline void bdk_csr_write(bdk_node_t node, bdk_csr_type_t type, int busnu
|
||||
} \
|
||||
} while (0); \
|
||||
result;})
|
||||
#endif
|
||||
#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; \
|
||||
} \
|
||||
} \
|
||||
} while (0); \
|
||||
result;})
|
||||
|
||||
/**
|
||||
* This macro spins on a field waiting for it to reach a value. It
|
||||
@ -299,6 +329,8 @@ static inline void bdk_csr_write(bdk_node_t node, bdk_csr_type_t type, int busnu
|
||||
* change bit locations, the compiler will not catch those changes
|
||||
* with this macro. Changes silently do the wrong thing at runtime.
|
||||
*/
|
||||
/* FIXME(dhendrix): removed bdk_thread_yield() */
|
||||
#if 0
|
||||
#define BDK_CSR_WAIT_FOR_CHIP_FIELD(node, csr, chip, field, op, value, timeout_usec) \
|
||||
({int result; \
|
||||
do { \
|
||||
@ -320,5 +352,27 @@ static inline void bdk_csr_write(bdk_node_t node, bdk_csr_type_t type, int busnu
|
||||
} \
|
||||
} while (0); \
|
||||
result;})
|
||||
#endif
|
||||
#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; \
|
||||
} \
|
||||
} \
|
||||
} while (0); \
|
||||
result;})
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
17565
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-bgx.h
Normal file
17565
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-bgx.h
Normal file
File diff suppressed because it is too large
Load Diff
1010
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-dap.h
Normal file
1010
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-dap.h
Normal file
File diff suppressed because it is too large
Load Diff
12470
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-dtx.h
Normal file
12470
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-dtx.h
Normal file
File diff suppressed because it is too large
Load Diff
1245
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-ecam.h
Normal file
1245
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-ecam.h
Normal file
File diff suppressed because it is too large
Load Diff
8178
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-gic.h
Normal file
8178
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-gic.h
Normal file
File diff suppressed because it is too large
Load Diff
12340
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-gser.h
Normal file
12340
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-gser.h
Normal file
File diff suppressed because it is too large
Load Diff
20807
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-gsern.h
Normal file
20807
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-gsern.h
Normal file
File diff suppressed because it is too large
Load Diff
7054
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-iobn.h
Normal file
7054
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-iobn.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,12 @@
|
||||
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
|
||||
/* FIXME(dhendrix) added to make compiler happy. However this introduces a
|
||||
* circular dependency and the typdef'd bdk_lmcx_modereg_params2_t makes
|
||||
* forward declaration impossible. */
|
||||
//#include <libdram/libdram-config.h>
|
||||
#include <bdk-minimal.h>
|
||||
#include <libbdk-arch/bdk-model.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
|
@ -41,6 +41,7 @@
|
||||
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
|
||||
#include <bdk-minimal.h> /* FIXME: added by dhendrix */
|
||||
|
||||
/**
|
||||
* @file
|
||||
|
1000
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-pccbr.h
Normal file
1000
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-pccbr.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,7 @@
|
||||
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
|
||||
#include <bdk.h> /* FIXME(dhendrix): added to satisfy compiler... */
|
||||
|
||||
/**
|
||||
* @file
|
||||
|
29162
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-pcierc.h
Normal file
29162
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-pcierc.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -41,6 +41,8 @@
|
||||
* PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
|
||||
#include <bdk-minimal.h>
|
||||
#include <libbdk-arch/bdk-csr.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
|
4167
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-rvu.h
Normal file
4167
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-rvu.h
Normal file
File diff suppressed because it is too large
Load Diff
4896
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-sata.h
Normal file
4896
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-sata.h
Normal file
File diff suppressed because it is too large
Load Diff
7573
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-sli.h
Normal file
7573
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-sli.h
Normal file
File diff suppressed because it is too large
Load Diff
551
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-smi.h
Normal file
551
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-smi.h
Normal file
@ -0,0 +1,551 @@
|
||||
#ifndef __BDK_CSRS_SMI_H__
|
||||
#define __BDK_CSRS_SMI_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 SMI.
|
||||
*
|
||||
* This file is auto generated. Do not edit.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enumeration smi_bar_e
|
||||
*
|
||||
* SMI Base Address Register Enumeration
|
||||
* Enumerates the base address registers.
|
||||
*/
|
||||
#define BDK_SMI_BAR_E_SMI_PF_BAR0_CN8 (0x87e005000000ll)
|
||||
#define BDK_SMI_BAR_E_SMI_PF_BAR0_CN8_SIZE 0x800000ull
|
||||
#define BDK_SMI_BAR_E_SMI_PF_BAR0_CN9 (0x87e005000000ll)
|
||||
#define BDK_SMI_BAR_E_SMI_PF_BAR0_CN9_SIZE 0x100000ull
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_#_clk
|
||||
*
|
||||
* SMI Clock Control Register
|
||||
* This register determines the SMI timing characteristics.
|
||||
* If software wants to change SMI CLK timing parameters ([SAMPLE]/[SAMPLE_HI]), software
|
||||
* must delay the SMI_()_CLK CSR write by at least 512 coprocessor-clock cycles after the
|
||||
* previous SMI operation is finished.
|
||||
*/
|
||||
union bdk_smi_x_clk
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_x_clk_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_25_63 : 39;
|
||||
uint64_t mode : 1; /**< [ 24: 24](R/W) IEEE operating mode; 0 = Clause 22 compliant, 1 = Clause 45 compliant. */
|
||||
uint64_t reserved_21_23 : 3;
|
||||
uint64_t sample_hi : 5; /**< [ 20: 16](R/W) Sample (extended bits). Specifies in coprocessor clock cycles when to sample read data. */
|
||||
uint64_t sample_mode : 1; /**< [ 15: 15](R/W) Read data sampling mode.
|
||||
According to the 802.3 specification, on read operations, the STA transitions SMIn_MDC and
|
||||
the PHY drives SMIn_MDIO with some delay relative to that edge. This is Edge1.
|
||||
The STA then samples SMIn_MDIO on the next rising edge of SMIn_MDC. This is Edge2. The
|
||||
read data can be sampled relative to either edge.
|
||||
0 = Sample time is relative to Edge2.
|
||||
1 = Sample time is relative to Edge1. */
|
||||
uint64_t reserved_14 : 1;
|
||||
uint64_t clk_idle : 1; /**< [ 13: 13](R/W) SMIn_MDC toggle. When set, this bit causes SMIn_MDC not to toggle on idle cycles. */
|
||||
uint64_t preamble : 1; /**< [ 12: 12](R/W) Preamble. When this bit is set, the 32-bit preamble is sent first on SMI transactions.
|
||||
This field must be set to 1 when [MODE] = 1 in order for the receiving PHY to correctly
|
||||
frame the transaction. */
|
||||
uint64_t sample : 4; /**< [ 11: 8](R/W) Sample read data. Specifies the number of coprocessor clock cycles after the rising edge
|
||||
of SMIn_MDC to wait before sampling read data.
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) \> 1
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) + 3 \<= 2 * [PHASE] */
|
||||
uint64_t phase : 8; /**< [ 7: 0](R/W) MDC clock phase. Specifies the number of coprocessor clock cycles that make up an SMIn_MDC
|
||||
phase.
|
||||
|
||||
_ [PHASE] \> 2 */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t phase : 8; /**< [ 7: 0](R/W) MDC clock phase. Specifies the number of coprocessor clock cycles that make up an SMIn_MDC
|
||||
phase.
|
||||
|
||||
_ [PHASE] \> 2 */
|
||||
uint64_t sample : 4; /**< [ 11: 8](R/W) Sample read data. Specifies the number of coprocessor clock cycles after the rising edge
|
||||
of SMIn_MDC to wait before sampling read data.
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) \> 1
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) + 3 \<= 2 * [PHASE] */
|
||||
uint64_t preamble : 1; /**< [ 12: 12](R/W) Preamble. When this bit is set, the 32-bit preamble is sent first on SMI transactions.
|
||||
This field must be set to 1 when [MODE] = 1 in order for the receiving PHY to correctly
|
||||
frame the transaction. */
|
||||
uint64_t clk_idle : 1; /**< [ 13: 13](R/W) SMIn_MDC toggle. When set, this bit causes SMIn_MDC not to toggle on idle cycles. */
|
||||
uint64_t reserved_14 : 1;
|
||||
uint64_t sample_mode : 1; /**< [ 15: 15](R/W) Read data sampling mode.
|
||||
According to the 802.3 specification, on read operations, the STA transitions SMIn_MDC and
|
||||
the PHY drives SMIn_MDIO with some delay relative to that edge. This is Edge1.
|
||||
The STA then samples SMIn_MDIO on the next rising edge of SMIn_MDC. This is Edge2. The
|
||||
read data can be sampled relative to either edge.
|
||||
0 = Sample time is relative to Edge2.
|
||||
1 = Sample time is relative to Edge1. */
|
||||
uint64_t sample_hi : 5; /**< [ 20: 16](R/W) Sample (extended bits). Specifies in coprocessor clock cycles when to sample read data. */
|
||||
uint64_t reserved_21_23 : 3;
|
||||
uint64_t mode : 1; /**< [ 24: 24](R/W) IEEE operating mode; 0 = Clause 22 compliant, 1 = Clause 45 compliant. */
|
||||
uint64_t reserved_25_63 : 39;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_x_clk_s cn8; */
|
||||
struct bdk_smi_x_clk_cn9
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_25_63 : 39;
|
||||
uint64_t mode : 1; /**< [ 24: 24](R/W) IEEE operating mode; 0 = Clause 22 compliant, 1 = Clause 45 compliant. */
|
||||
uint64_t reserved_21_23 : 3;
|
||||
uint64_t sample_hi : 5; /**< [ 20: 16](R/W) Sample (extended bits). Specifies in coprocessor clock cycles when to sample read data. */
|
||||
uint64_t sample_mode : 1; /**< [ 15: 15](R/W) Read data sampling mode.
|
||||
According to the 802.3 specification, on read operations, the STA transitions SMIn_MDC and
|
||||
the PHY drives SMIn_MDIO with some delay relative to that edge. This is Edge1.
|
||||
The STA then samples SMIn_MDIO on the next rising edge of SMIn_MDC. This is Edge2. The
|
||||
read data can be sampled relative to either edge.
|
||||
0 = Sample time is relative to Edge2.
|
||||
1 = Sample time is relative to Edge1. */
|
||||
uint64_t reserved_14 : 1;
|
||||
uint64_t clk_idle : 1; /**< [ 13: 13](R/W) SMIn_MDC toggle. When set, this bit causes SMIn_MDC not to toggle on idle cycles. */
|
||||
uint64_t preamble : 1; /**< [ 12: 12](R/W) Preamble. When this bit is set, the 32-bit preamble is sent first on SMI transactions.
|
||||
This field must be set to 1 when [MODE] = 1 in order for the receiving PHY to correctly
|
||||
frame the transaction. */
|
||||
uint64_t sample : 4; /**< [ 11: 8](R/W) Sample read data. Specifies the number of coprocessor clock cycles after the rising edge
|
||||
of SMIn_MDC to wait before sampling read data.
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) \> 1
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) + 3 \<= 2 * [PHASE] */
|
||||
uint64_t phase : 8; /**< [ 7: 0](R/W) MDC clock phase. Specifies the number of coprocessor clock cycles that make up an SMIn_MDC
|
||||
phase.
|
||||
|
||||
_ [PHASE] \> 2
|
||||
|
||||
Internal:
|
||||
FIXME number of 100MHz clocks or coproc clocks based on CSR that defaults to 100MHz. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t phase : 8; /**< [ 7: 0](R/W) MDC clock phase. Specifies the number of coprocessor clock cycles that make up an SMIn_MDC
|
||||
phase.
|
||||
|
||||
_ [PHASE] \> 2
|
||||
|
||||
Internal:
|
||||
FIXME number of 100MHz clocks or coproc clocks based on CSR that defaults to 100MHz. */
|
||||
uint64_t sample : 4; /**< [ 11: 8](R/W) Sample read data. Specifies the number of coprocessor clock cycles after the rising edge
|
||||
of SMIn_MDC to wait before sampling read data.
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) \> 1
|
||||
|
||||
_ ([SAMPLE_HI],[SAMPLE]) + 3 \<= 2 * [PHASE] */
|
||||
uint64_t preamble : 1; /**< [ 12: 12](R/W) Preamble. When this bit is set, the 32-bit preamble is sent first on SMI transactions.
|
||||
This field must be set to 1 when [MODE] = 1 in order for the receiving PHY to correctly
|
||||
frame the transaction. */
|
||||
uint64_t clk_idle : 1; /**< [ 13: 13](R/W) SMIn_MDC toggle. When set, this bit causes SMIn_MDC not to toggle on idle cycles. */
|
||||
uint64_t reserved_14 : 1;
|
||||
uint64_t sample_mode : 1; /**< [ 15: 15](R/W) Read data sampling mode.
|
||||
According to the 802.3 specification, on read operations, the STA transitions SMIn_MDC and
|
||||
the PHY drives SMIn_MDIO with some delay relative to that edge. This is Edge1.
|
||||
The STA then samples SMIn_MDIO on the next rising edge of SMIn_MDC. This is Edge2. The
|
||||
read data can be sampled relative to either edge.
|
||||
0 = Sample time is relative to Edge2.
|
||||
1 = Sample time is relative to Edge1. */
|
||||
uint64_t sample_hi : 5; /**< [ 20: 16](R/W) Sample (extended bits). Specifies in coprocessor clock cycles when to sample read data. */
|
||||
uint64_t reserved_21_23 : 3;
|
||||
uint64_t mode : 1; /**< [ 24: 24](R/W) IEEE operating mode; 0 = Clause 22 compliant, 1 = Clause 45 compliant. */
|
||||
uint64_t reserved_25_63 : 39;
|
||||
#endif /* Word 0 - End */
|
||||
} cn9;
|
||||
};
|
||||
typedef union bdk_smi_x_clk bdk_smi_x_clk_t;
|
||||
|
||||
static inline uint64_t BDK_SMI_X_CLK(unsigned long a) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_X_CLK(unsigned long a)
|
||||
{
|
||||
if (a<=1)
|
||||
return 0x87e005003818ll + 0x80ll * ((a) & 0x1);
|
||||
__bdk_csr_fatal("SMI_X_CLK", 1, a, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_X_CLK(a) bdk_smi_x_clk_t
|
||||
#define bustype_BDK_SMI_X_CLK(a) BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_X_CLK(a) "SMI_X_CLK"
|
||||
#define device_bar_BDK_SMI_X_CLK(a) 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_X_CLK(a) (a)
|
||||
#define arguments_BDK_SMI_X_CLK(a) (a),-1,-1,-1
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_#_clken
|
||||
*
|
||||
* SMI Clock Enable Register
|
||||
* This register is to force conditional clock enable.
|
||||
*/
|
||||
union bdk_smi_x_clken
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_x_clken_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_1_63 : 63;
|
||||
uint64_t clken : 1; /**< [ 0: 0](R/W) Force the conditional clocking within SMI to be always on. For diagnostic use only. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t clken : 1; /**< [ 0: 0](R/W) Force the conditional clocking within SMI to be always on. For diagnostic use only. */
|
||||
uint64_t reserved_1_63 : 63;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_x_clken_s cn; */
|
||||
};
|
||||
typedef union bdk_smi_x_clken bdk_smi_x_clken_t;
|
||||
|
||||
static inline uint64_t BDK_SMI_X_CLKEN(unsigned long a) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_X_CLKEN(unsigned long a)
|
||||
{
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX) && (a<=1))
|
||||
return 0x87e005003830ll + 0x80ll * ((a) & 0x1);
|
||||
__bdk_csr_fatal("SMI_X_CLKEN", 1, a, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_X_CLKEN(a) bdk_smi_x_clken_t
|
||||
#define bustype_BDK_SMI_X_CLKEN(a) BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_X_CLKEN(a) "SMI_X_CLKEN"
|
||||
#define device_bar_BDK_SMI_X_CLKEN(a) 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_X_CLKEN(a) (a)
|
||||
#define arguments_BDK_SMI_X_CLKEN(a) (a),-1,-1,-1
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_#_cmd
|
||||
*
|
||||
* SMI Command Control Register
|
||||
* This register forces a read or write command to the PHY. Write operations to this register
|
||||
* create SMI transactions. Software will poll (depending on the transaction type).
|
||||
*/
|
||||
union bdk_smi_x_cmd
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_x_cmd_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_18_63 : 46;
|
||||
uint64_t phy_op : 2; /**< [ 17: 16](R/W) PHY opcode, depending on SMI_()_CLK[MODE] setting.
|
||||
* If SMI_()_CLK[MODE] = 0 (\<=1Gbs / Clause 22):
|
||||
0 = Write operation, encoded in the frame as 01.
|
||||
1 = Read operation, encoded in the frame as 10.
|
||||
|
||||
* If SMI_()_CLK[MODE] = 1 (\>1Gbs / Clause 45):
|
||||
0x0 = Address.
|
||||
0x1 = Write.
|
||||
0x2 = Post-read-increment-address.
|
||||
0x3 = Read. */
|
||||
uint64_t reserved_13_15 : 3;
|
||||
uint64_t phy_adr : 5; /**< [ 12: 8](R/W) PHY address. */
|
||||
uint64_t reserved_5_7 : 3;
|
||||
uint64_t reg_adr : 5; /**< [ 4: 0](R/W) PHY register offset. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t reg_adr : 5; /**< [ 4: 0](R/W) PHY register offset. */
|
||||
uint64_t reserved_5_7 : 3;
|
||||
uint64_t phy_adr : 5; /**< [ 12: 8](R/W) PHY address. */
|
||||
uint64_t reserved_13_15 : 3;
|
||||
uint64_t phy_op : 2; /**< [ 17: 16](R/W) PHY opcode, depending on SMI_()_CLK[MODE] setting.
|
||||
* If SMI_()_CLK[MODE] = 0 (\<=1Gbs / Clause 22):
|
||||
0 = Write operation, encoded in the frame as 01.
|
||||
1 = Read operation, encoded in the frame as 10.
|
||||
|
||||
* If SMI_()_CLK[MODE] = 1 (\>1Gbs / Clause 45):
|
||||
0x0 = Address.
|
||||
0x1 = Write.
|
||||
0x2 = Post-read-increment-address.
|
||||
0x3 = Read. */
|
||||
uint64_t reserved_18_63 : 46;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_x_cmd_s cn; */
|
||||
};
|
||||
typedef union bdk_smi_x_cmd bdk_smi_x_cmd_t;
|
||||
|
||||
static inline uint64_t BDK_SMI_X_CMD(unsigned long a) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_X_CMD(unsigned long a)
|
||||
{
|
||||
if (a<=1)
|
||||
return 0x87e005003800ll + 0x80ll * ((a) & 0x1);
|
||||
__bdk_csr_fatal("SMI_X_CMD", 1, a, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_X_CMD(a) bdk_smi_x_cmd_t
|
||||
#define bustype_BDK_SMI_X_CMD(a) BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_X_CMD(a) "SMI_X_CMD"
|
||||
#define device_bar_BDK_SMI_X_CMD(a) 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_X_CMD(a) (a)
|
||||
#define arguments_BDK_SMI_X_CMD(a) (a),-1,-1,-1
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_#_en
|
||||
*
|
||||
* SMI Enable Register
|
||||
* Enables the SMI interface.
|
||||
*/
|
||||
union bdk_smi_x_en
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_x_en_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_1_63 : 63;
|
||||
uint64_t en : 1; /**< [ 0: 0](R/W) SMI/MDIO interface enable:
|
||||
1 = Enable interface.
|
||||
0 = Disable interface: no transactions, no SMIn_MDC transitions. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t en : 1; /**< [ 0: 0](R/W) SMI/MDIO interface enable:
|
||||
1 = Enable interface.
|
||||
0 = Disable interface: no transactions, no SMIn_MDC transitions. */
|
||||
uint64_t reserved_1_63 : 63;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_x_en_s cn; */
|
||||
};
|
||||
typedef union bdk_smi_x_en bdk_smi_x_en_t;
|
||||
|
||||
static inline uint64_t BDK_SMI_X_EN(unsigned long a) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_X_EN(unsigned long a)
|
||||
{
|
||||
if (a<=1)
|
||||
return 0x87e005003820ll + 0x80ll * ((a) & 0x1);
|
||||
__bdk_csr_fatal("SMI_X_EN", 1, a, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_X_EN(a) bdk_smi_x_en_t
|
||||
#define bustype_BDK_SMI_X_EN(a) BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_X_EN(a) "SMI_X_EN"
|
||||
#define device_bar_BDK_SMI_X_EN(a) 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_X_EN(a) (a)
|
||||
#define arguments_BDK_SMI_X_EN(a) (a),-1,-1,-1
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_#_rd_dat
|
||||
*
|
||||
* SMI Read Data Register
|
||||
* This register contains the data in a read operation.
|
||||
*/
|
||||
union bdk_smi_x_rd_dat
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_x_rd_dat_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_18_63 : 46;
|
||||
uint64_t pending : 1; /**< [ 17: 17](RO/H) Read transaction pending. Indicates that an SMI read transaction is in flight. */
|
||||
uint64_t val : 1; /**< [ 16: 16](RO/H) Read data valid. Asserts when the read transaction completes. A read to this register clears [VAL]. */
|
||||
uint64_t dat : 16; /**< [ 15: 0](RO/H) Read data. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t dat : 16; /**< [ 15: 0](RO/H) Read data. */
|
||||
uint64_t val : 1; /**< [ 16: 16](RO/H) Read data valid. Asserts when the read transaction completes. A read to this register clears [VAL]. */
|
||||
uint64_t pending : 1; /**< [ 17: 17](RO/H) Read transaction pending. Indicates that an SMI read transaction is in flight. */
|
||||
uint64_t reserved_18_63 : 46;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_x_rd_dat_s cn; */
|
||||
};
|
||||
typedef union bdk_smi_x_rd_dat bdk_smi_x_rd_dat_t;
|
||||
|
||||
static inline uint64_t BDK_SMI_X_RD_DAT(unsigned long a) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_X_RD_DAT(unsigned long a)
|
||||
{
|
||||
if (a<=1)
|
||||
return 0x87e005003810ll + 0x80ll * ((a) & 0x1);
|
||||
__bdk_csr_fatal("SMI_X_RD_DAT", 1, a, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_X_RD_DAT(a) bdk_smi_x_rd_dat_t
|
||||
#define bustype_BDK_SMI_X_RD_DAT(a) BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_X_RD_DAT(a) "SMI_X_RD_DAT"
|
||||
#define device_bar_BDK_SMI_X_RD_DAT(a) 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_X_RD_DAT(a) (a)
|
||||
#define arguments_BDK_SMI_X_RD_DAT(a) (a),-1,-1,-1
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_#_wr_dat
|
||||
*
|
||||
* SMI Write Data Register
|
||||
* This register provides the data for a write operation.
|
||||
*/
|
||||
union bdk_smi_x_wr_dat
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_x_wr_dat_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_18_63 : 46;
|
||||
uint64_t pending : 1; /**< [ 17: 17](RO/H) Write transaction pending. Indicates that an SMI write transaction is in flight. */
|
||||
uint64_t val : 1; /**< [ 16: 16](RO/H) Write data valid. Asserts when the write transaction completes. A read to this
|
||||
register clears [VAL]. */
|
||||
uint64_t dat : 16; /**< [ 15: 0](R/W/H) Write data. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t dat : 16; /**< [ 15: 0](R/W/H) Write data. */
|
||||
uint64_t val : 1; /**< [ 16: 16](RO/H) Write data valid. Asserts when the write transaction completes. A read to this
|
||||
register clears [VAL]. */
|
||||
uint64_t pending : 1; /**< [ 17: 17](RO/H) Write transaction pending. Indicates that an SMI write transaction is in flight. */
|
||||
uint64_t reserved_18_63 : 46;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_x_wr_dat_s cn; */
|
||||
};
|
||||
typedef union bdk_smi_x_wr_dat bdk_smi_x_wr_dat_t;
|
||||
|
||||
static inline uint64_t BDK_SMI_X_WR_DAT(unsigned long a) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_X_WR_DAT(unsigned long a)
|
||||
{
|
||||
if (a<=1)
|
||||
return 0x87e005003808ll + 0x80ll * ((a) & 0x1);
|
||||
__bdk_csr_fatal("SMI_X_WR_DAT", 1, a, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_X_WR_DAT(a) bdk_smi_x_wr_dat_t
|
||||
#define bustype_BDK_SMI_X_WR_DAT(a) BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_X_WR_DAT(a) "SMI_X_WR_DAT"
|
||||
#define device_bar_BDK_SMI_X_WR_DAT(a) 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_X_WR_DAT(a) (a)
|
||||
#define arguments_BDK_SMI_X_WR_DAT(a) (a),-1,-1,-1
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_drv_ctl
|
||||
*
|
||||
* SMI Drive Strength Control Register
|
||||
* Enables the SMI interface.
|
||||
*/
|
||||
union bdk_smi_drv_ctl
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_drv_ctl_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_11_63 : 53;
|
||||
uint64_t pctl : 3; /**< [ 10: 8](R/W) PCTL drive strength control bits. Suggested values:
|
||||
0x4 = 60 ohm.
|
||||
0x6 = 40 ohm.
|
||||
0x7 = 30 ohm. */
|
||||
uint64_t reserved_3_7 : 5;
|
||||
uint64_t nctl : 3; /**< [ 2: 0](R/W) NCTL drive strength control bits. Suggested values:
|
||||
0x4 = 60 ohm.
|
||||
0x6 = 40 ohm.
|
||||
0x7 = 30 ohm. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t nctl : 3; /**< [ 2: 0](R/W) NCTL drive strength control bits. Suggested values:
|
||||
0x4 = 60 ohm.
|
||||
0x6 = 40 ohm.
|
||||
0x7 = 30 ohm. */
|
||||
uint64_t reserved_3_7 : 5;
|
||||
uint64_t pctl : 3; /**< [ 10: 8](R/W) PCTL drive strength control bits. Suggested values:
|
||||
0x4 = 60 ohm.
|
||||
0x6 = 40 ohm.
|
||||
0x7 = 30 ohm. */
|
||||
uint64_t reserved_11_63 : 53;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_drv_ctl_s cn; */
|
||||
};
|
||||
typedef union bdk_smi_drv_ctl bdk_smi_drv_ctl_t;
|
||||
|
||||
#define BDK_SMI_DRV_CTL BDK_SMI_DRV_CTL_FUNC()
|
||||
static inline uint64_t BDK_SMI_DRV_CTL_FUNC(void) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_DRV_CTL_FUNC(void)
|
||||
{
|
||||
return 0x87e005003828ll;
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_DRV_CTL bdk_smi_drv_ctl_t
|
||||
#define bustype_BDK_SMI_DRV_CTL BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_DRV_CTL "SMI_DRV_CTL"
|
||||
#define device_bar_BDK_SMI_DRV_CTL 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_DRV_CTL 0
|
||||
#define arguments_BDK_SMI_DRV_CTL -1,-1,-1,-1
|
||||
|
||||
/**
|
||||
* Register (RSL) smi_drv_rsvd
|
||||
*
|
||||
* INTERNAL: SMI Drive Reserve Register
|
||||
*
|
||||
* Enables the SMI1 interface.
|
||||
*/
|
||||
union bdk_smi_drv_rsvd
|
||||
{
|
||||
uint64_t u;
|
||||
struct bdk_smi_drv_rsvd_s
|
||||
{
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN /* Word 0 - Big Endian */
|
||||
uint64_t reserved_11_63 : 53;
|
||||
uint64_t pctl : 3; /**< [ 10: 8](R/W) Reserved. */
|
||||
uint64_t reserved_3_7 : 5;
|
||||
uint64_t nctl : 3; /**< [ 2: 0](R/W) Reserved. */
|
||||
#else /* Word 0 - Little Endian */
|
||||
uint64_t nctl : 3; /**< [ 2: 0](R/W) Reserved. */
|
||||
uint64_t reserved_3_7 : 5;
|
||||
uint64_t pctl : 3; /**< [ 10: 8](R/W) Reserved. */
|
||||
uint64_t reserved_11_63 : 53;
|
||||
#endif /* Word 0 - End */
|
||||
} s;
|
||||
/* struct bdk_smi_drv_rsvd_s cn; */
|
||||
};
|
||||
typedef union bdk_smi_drv_rsvd bdk_smi_drv_rsvd_t;
|
||||
|
||||
#define BDK_SMI_DRV_RSVD BDK_SMI_DRV_RSVD_FUNC()
|
||||
static inline uint64_t BDK_SMI_DRV_RSVD_FUNC(void) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t BDK_SMI_DRV_RSVD_FUNC(void)
|
||||
{
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN81XX))
|
||||
return 0x87e0050038a8ll;
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN83XX))
|
||||
return 0x87e0050038a8ll;
|
||||
if (CAVIUM_IS_MODEL(CAVIUM_CN9XXX))
|
||||
return 0x87e0050038a8ll;
|
||||
__bdk_csr_fatal("SMI_DRV_RSVD", 0, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#define typedef_BDK_SMI_DRV_RSVD bdk_smi_drv_rsvd_t
|
||||
#define bustype_BDK_SMI_DRV_RSVD BDK_CSR_TYPE_RSL
|
||||
#define basename_BDK_SMI_DRV_RSVD "SMI_DRV_RSVD"
|
||||
#define device_bar_BDK_SMI_DRV_RSVD 0x0 /* PF_BAR0 */
|
||||
#define busnum_BDK_SMI_DRV_RSVD 0
|
||||
#define arguments_BDK_SMI_DRV_RSVD -1,-1,-1,-1
|
||||
|
||||
#endif /* __BDK_CSRS_SMI_H__ */
|
14020
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-usbdrd.h
Normal file
14020
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-usbdrd.h
Normal file
File diff suppressed because it is too large
Load Diff
7606
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-usbh.h
Normal file
7606
src/vendorcode/cavium/include/bdk/libbdk-arch/bdk-csrs-usbh.h
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,3 +1,6 @@
|
||||
#ifndef __CB_BDK_FUSE_H__
|
||||
#define __CB_BDK_FUSE_H__
|
||||
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
@ -115,3 +118,4 @@ extern int bdk_fuse_field_soft_blow(bdk_node_t node, int fuse);
|
||||
*/
|
||||
extern int bdk_fuse_field_hard_blow(bdk_node_t node, int start_fuse, uint64_t fuses0, uint64_t fuses1);
|
||||
|
||||
#endif
|
||||
|
@ -1,3 +1,5 @@
|
||||
#ifndef __CB_BDK_LMT_H__
|
||||
#define __CB_BDK_LMT_H__
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
@ -98,3 +100,4 @@ static inline int bdk_lmt_submit(uint64_t io_address)
|
||||
}
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef __CB_BDK_MODEL_H__
|
||||
#define __CB_BDK_MODEL_H__
|
||||
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
@ -88,8 +91,8 @@
|
||||
#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()
|
||||
static inline uint64_t cavium_get_model(void) __attribute__ ((pure, always_inline));
|
||||
static inline uint64_t cavium_get_model(void)
|
||||
{
|
||||
#ifdef BDK_BUILD_HOST
|
||||
extern uint32_t thunder_remote_get_model(void) __attribute__ ((pure));
|
||||
@ -158,13 +161,5 @@ static inline int CAVIUM_IS_MODEL(uint32_t arg_model)
|
||||
*/
|
||||
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);
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
@ -1,3 +1,6 @@
|
||||
#ifndef __CB_BDK_NUMA_H__
|
||||
#define __CB_BDK_NUMA_H__
|
||||
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
@ -37,6 +40,10 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
|
||||
/* FIXME(dhendricks): added */
|
||||
#include <libbdk-arch/bdk-asm.h>
|
||||
#include <libbdk-arch/bdk-model.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
@ -113,7 +120,7 @@ extern int bdk_numa_exists(bdk_node_t node);
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
extern int bdk_numa_is_only_one();
|
||||
extern int bdk_numa_is_only_one(void);
|
||||
|
||||
/**
|
||||
* Given a physical address without a node, return the proper physical address
|
||||
@ -136,4 +143,4 @@ static inline uint64_t bdk_numa_get_address(bdk_node_t node, uint64_t pa)
|
||||
return pa;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
@ -1,3 +1,5 @@
|
||||
#ifndef __CB_BDK_REQUIRE_H__
|
||||
#define __CB_BDK_REQIORE_H__
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
@ -102,6 +104,8 @@
|
||||
* reference to bdk_requires_depends() which then contains strong
|
||||
* references to all needed components.
|
||||
*/
|
||||
extern void __bdk_require_depends(void);
|
||||
// FIXME(dhendrix): leave it out if possible */
|
||||
//extern void __bdk_require_depends(void);
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
@ -1,130 +0,0 @@
|
||||
/***********************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)
|
||||
|
||||
/** @} */
|
@ -1,3 +1,6 @@
|
||||
#ifndef __CB_BDK_WARN_H__
|
||||
#define __CB_BDK_WARN_H__
|
||||
|
||||
/***********************license start***********************************
|
||||
* Copyright (c) 2003-2017 Cavium Inc. (support@cavium.com). All rights
|
||||
* reserved.
|
||||
@ -37,6 +40,8 @@
|
||||
* ARISING OUT OF USE OR PERFORMANCE OF THE SOFTWARE LIES WITH YOU.
|
||||
***********************license end**************************************/
|
||||
|
||||
#include <console/console.h>
|
||||
|
||||
/**
|
||||
* @file
|
||||
*
|
||||
@ -48,11 +53,14 @@
|
||||
* @{
|
||||
*/
|
||||
|
||||
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__)
|
||||
#define bdk_warn(format, ...) printk(BIOS_WARNING, format, ##__VA_ARGS__)
|
||||
#define bdk_error(format, ...) printk(BIOS_ERR, format, ##__VA_ARGS__)
|
||||
#define bdk_fatal(format, ...) \
|
||||
do { \
|
||||
printk(BIOS_CRIT, format, ##__VA_ARGS__); \
|
||||
while (1) \
|
||||
; \
|
||||
} while (0)
|
||||
|
||||
/* The following defines control detailed tracing of various parts of the
|
||||
BDK. Each one can be enabled(1) or disabled(0) independently. These
|
||||
@ -87,18 +95,29 @@ typedef enum
|
||||
__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)
|
||||
#define BDK_TRACE(area, format, ...) do { \
|
||||
if ((BDK_TRACE_ENABLE_INIT == BDK_TRACE_ENABLE_##area && \
|
||||
IS_ENABLED(CONFIG_CAVIUM_BDK_VERBOSE_INIT)) || \
|
||||
(BDK_TRACE_ENABLE_DRAM == BDK_TRACE_ENABLE_##area && \
|
||||
IS_ENABLED(CONFIG_CAVIUM_BDK_VERBOSE_DRAM)) || \
|
||||
(BDK_TRACE_ENABLE_DRAM_TEST == BDK_TRACE_ENABLE_##area && \
|
||||
IS_ENABLED(CONFIG_CAVIUM_BDK_VERBOSE_DRAM_TEST)) || \
|
||||
(BDK_TRACE_ENABLE_QLM == BDK_TRACE_ENABLE_##area && \
|
||||
IS_ENABLED(CONFIG_CAVIUM_BDK_VERBOSE_QLM)) || \
|
||||
(BDK_TRACE_ENABLE_PCIE_CONFIG == BDK_TRACE_ENABLE_##area && \
|
||||
IS_ENABLED(CONFIG_CAVIUM_BDK_VERBOSE_PCIE_CONFIG)) || \
|
||||
(BDK_TRACE_ENABLE_PCIE == BDK_TRACE_ENABLE_##area && \
|
||||
IS_ENABLED(CONFIG_CAVIUM_BDK_VERBOSE_PCIE)) || \
|
||||
(BDK_TRACE_ENABLE_PHY == BDK_TRACE_ENABLE_##area && \
|
||||
IS_ENABLED(CONFIG_CAVIUM_BDK_VERBOSE_PHY))) \
|
||||
printk(BIOS_DEBUG, #area ": " format, ##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
/** @} */
|
||||
#endif
|
||||
|
@ -1,43 +0,0 @@
|
||||
#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
|
||||
|
@ -1,41 +0,0 @@
|
||||
/***********************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);
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user