mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-12-17 16:53:06 +00:00
286 lines
8.3 KiB
C
286 lines
8.3 KiB
C
|
// SPDX-License-Identifier: GPL-2.0
|
||
|
/*
|
||
|
* Copyright (C) 2018-2022 Marvell International Ltd.
|
||
|
*
|
||
|
* PKI Support.
|
||
|
*/
|
||
|
|
||
|
#include <time.h>
|
||
|
#include <log.h>
|
||
|
#include <linux/delay.h>
|
||
|
|
||
|
#include <mach/cvmx-regs.h>
|
||
|
#include <mach/cvmx-csr.h>
|
||
|
#include <mach/cvmx-bootmem.h>
|
||
|
#include <mach/octeon-model.h>
|
||
|
#include <mach/cvmx-fuse.h>
|
||
|
#include <mach/octeon-feature.h>
|
||
|
#include <mach/cvmx-qlm.h>
|
||
|
#include <mach/octeon_qlm.h>
|
||
|
#include <mach/cvmx-pcie.h>
|
||
|
#include <mach/cvmx-coremask.h>
|
||
|
|
||
|
#include <mach/cvmx-global-resources.h>
|
||
|
|
||
|
#include <mach/cvmx-pki-defs.h>
|
||
|
#include <mach/cvmx-pko-defs.h>
|
||
|
|
||
|
#include <mach/cvmx-pki.h>
|
||
|
#include <mach/cvmx-helper.h>
|
||
|
#include <mach/cvmx-helper-board.h>
|
||
|
#include <mach/cvmx-helper-cfg.h>
|
||
|
|
||
|
static s32 cvmx_pki_style_refcnt[CVMX_MAX_NODES][CVMX_PKI_NUM_INTERNAL_STYLE];
|
||
|
|
||
|
/**
|
||
|
* This function allocates/reserves a style from pool of global styles per node.
|
||
|
* @param node node to allocate style from.
|
||
|
* @param style style to allocate, if -1 it will be allocated
|
||
|
* first available style from style resource. If index is positive
|
||
|
* number and in range, it will try to allocate specified style.
|
||
|
* @return style number on success,
|
||
|
* -1 on alloc failure.
|
||
|
* -2 on resource already reserved.
|
||
|
*/
|
||
|
int cvmx_pki_style_alloc(int node, int style)
|
||
|
{
|
||
|
int rs;
|
||
|
|
||
|
if (cvmx_create_global_resource_range(CVMX_GR_TAG_STYLE(node),
|
||
|
CVMX_PKI_NUM_INTERNAL_STYLE)) {
|
||
|
printf("ERROR: Failed to create styles global resource\n");
|
||
|
return -1;
|
||
|
}
|
||
|
if (style >= 0) {
|
||
|
/* Reserving specific style, use refcnt for sharing */
|
||
|
rs = cvmx_atomic_fetch_and_add32(
|
||
|
&cvmx_pki_style_refcnt[node][style], 1);
|
||
|
if (rs > 0)
|
||
|
return CVMX_RESOURCE_ALREADY_RESERVED;
|
||
|
|
||
|
rs = cvmx_reserve_global_resource_range(CVMX_GR_TAG_STYLE(node),
|
||
|
style, style, 1);
|
||
|
if (rs == -1) {
|
||
|
/* This means the style is taken by another app */
|
||
|
printf("ERROR: style %d is reserved by another app\n",
|
||
|
style);
|
||
|
cvmx_atomic_fetch_and_add32(
|
||
|
&cvmx_pki_style_refcnt[node][style], -1);
|
||
|
return CVMX_RESOURCE_ALLOC_FAILED;
|
||
|
}
|
||
|
} else {
|
||
|
/* Allocate first available style */
|
||
|
rs = cvmx_allocate_global_resource_range(
|
||
|
CVMX_GR_TAG_STYLE(node), style, 1, 1);
|
||
|
if (rs < 0) {
|
||
|
printf("ERROR: Failed to allocate style, none available\n");
|
||
|
return CVMX_RESOURCE_ALLOC_FAILED;
|
||
|
}
|
||
|
style = rs;
|
||
|
/* Increment refcnt for newly created style */
|
||
|
cvmx_atomic_fetch_and_add32(&cvmx_pki_style_refcnt[node][style],
|
||
|
1);
|
||
|
}
|
||
|
return style;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function frees a style from pool of global styles per node.
|
||
|
* @param node node to free style from.
|
||
|
* @param style style to free
|
||
|
* @return 0 on success, -1 on failure or
|
||
|
* if the style is shared a positive count of remaining users for this style.
|
||
|
*/
|
||
|
int cvmx_pki_style_free(int node, int style)
|
||
|
{
|
||
|
int rs;
|
||
|
|
||
|
rs = cvmx_atomic_fetch_and_add32(&cvmx_pki_style_refcnt[node][style],
|
||
|
-1);
|
||
|
if (rs > 1)
|
||
|
return rs - 1;
|
||
|
|
||
|
if (cvmx_free_global_resource_range_with_base(CVMX_GR_TAG_STYLE(node),
|
||
|
style, 1) == -1) {
|
||
|
printf("ERROR Failed to release style %d\n", (int)style);
|
||
|
return -1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function allocates/reserves a cluster group from per node
|
||
|
cluster group resources.
|
||
|
* @param node node to allocate cluster group from.
|
||
|
@param cl_grp cluster group to allocate/reserve, if -1 ,
|
||
|
* allocate any available cluster group.
|
||
|
* @return cluster group number
|
||
|
* -1 on alloc failure.
|
||
|
* -2 on resource already reserved.
|
||
|
*/
|
||
|
int cvmx_pki_cluster_grp_alloc(int node, int cl_grp)
|
||
|
{
|
||
|
int rs;
|
||
|
|
||
|
if (node >= CVMX_MAX_NODES) {
|
||
|
printf("ERROR: Invalid node number %d\n", node);
|
||
|
return -1;
|
||
|
}
|
||
|
if (cvmx_create_global_resource_range(CVMX_GR_TAG_CLUSTER_GRP(node),
|
||
|
CVMX_PKI_NUM_CLUSTER_GROUP)) {
|
||
|
printf("ERROR: Failed to create Cluster group global resource\n");
|
||
|
return -1;
|
||
|
}
|
||
|
if (cl_grp >= 0) {
|
||
|
rs = cvmx_reserve_global_resource_range(
|
||
|
CVMX_GR_TAG_CLUSTER_GRP(node), 0, cl_grp, 1);
|
||
|
if (rs == -1) {
|
||
|
debug("INFO: cl_grp %d is already reserved\n",
|
||
|
(int)cl_grp);
|
||
|
return CVMX_RESOURCE_ALREADY_RESERVED;
|
||
|
}
|
||
|
} else {
|
||
|
rs = cvmx_allocate_global_resource_range(
|
||
|
CVMX_GR_TAG_CLUSTER_GRP(node), 0, 1, 1);
|
||
|
if (rs == -1) {
|
||
|
debug("Warning: Failed to alloc cluster grp\n");
|
||
|
return CVMX_RESOURCE_ALLOC_FAILED;
|
||
|
}
|
||
|
}
|
||
|
cl_grp = rs;
|
||
|
return cl_grp;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function allocates/reserves a pcam entry from node
|
||
|
* @param node node to allocate pcam entry from.
|
||
|
* @param index index of pacm entry (0-191), if -1 ,
|
||
|
* allocate any available pcam entry.
|
||
|
* @param bank pcam bank where to allocate/reserve pcan entry from
|
||
|
* @param cluster_mask mask of clusters from which pcam entry is needed.
|
||
|
* @return pcam entry of -1 on failure
|
||
|
*/
|
||
|
int cvmx_pki_pcam_entry_alloc(int node, int index, int bank, u64 cluster_mask)
|
||
|
{
|
||
|
int rs = 0;
|
||
|
unsigned int cluster;
|
||
|
|
||
|
for (cluster = 0; cluster < CVMX_PKI_NUM_CLUSTER; cluster++) {
|
||
|
if ((cluster_mask & (1 << cluster)) == 0)
|
||
|
continue;
|
||
|
rs = cvmx_create_global_resource_range(
|
||
|
CVMX_GR_TAG_PCAM(node, cluster, bank),
|
||
|
CVMX_PKI_TOTAL_PCAM_ENTRY);
|
||
|
if (rs != 0) {
|
||
|
printf("ERROR: Failed to create pki pcam global resource\n");
|
||
|
return -1;
|
||
|
}
|
||
|
if (index >= 0)
|
||
|
rs = cvmx_reserve_global_resource_range(
|
||
|
CVMX_GR_TAG_PCAM(node, cluster, bank), cluster,
|
||
|
index, 1);
|
||
|
else
|
||
|
rs = cvmx_allocate_global_resource_range(
|
||
|
CVMX_GR_TAG_PCAM(node, cluster, bank), cluster,
|
||
|
1, 1);
|
||
|
if (rs == -1) {
|
||
|
printf("ERROR: PCAM :index %d not available in cluster %d bank %d",
|
||
|
(int)index, (int)cluster, bank);
|
||
|
return -1;
|
||
|
}
|
||
|
} /* for cluster */
|
||
|
index = rs;
|
||
|
/* implement cluster handle for pass2, for now assume
|
||
|
all clusters will have same base index*/
|
||
|
return index;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function allocates/reserves QPG table entries per node.
|
||
|
* @param node node number.
|
||
|
* @param base_offset base_offset in qpg table. If -1, first available
|
||
|
* qpg base_offset will be allocated. If base_offset is positive
|
||
|
* number and in range, it will try to allocate specified base_offset.
|
||
|
* @param count number of consecutive qpg entries to allocate. They will be consecutive
|
||
|
* from base offset.
|
||
|
* @return qpg table base offset number on success
|
||
|
* -1 on alloc failure.
|
||
|
* -2 on resource already reserved.
|
||
|
*/
|
||
|
int cvmx_pki_qpg_entry_alloc(int node, int base_offset, int count)
|
||
|
{
|
||
|
int rs;
|
||
|
|
||
|
if (cvmx_create_global_resource_range(CVMX_GR_TAG_QPG_ENTRY(node),
|
||
|
CVMX_PKI_NUM_QPG_ENTRY)) {
|
||
|
printf("ERROR: Failed to create qpg_entry global resource\n");
|
||
|
return -1;
|
||
|
}
|
||
|
if (base_offset >= 0) {
|
||
|
rs = cvmx_reserve_global_resource_range(
|
||
|
CVMX_GR_TAG_QPG_ENTRY(node), base_offset, base_offset,
|
||
|
count);
|
||
|
if (rs == -1) {
|
||
|
debug("INFO: qpg entry %d is already reserved\n",
|
||
|
(int)base_offset);
|
||
|
return CVMX_RESOURCE_ALREADY_RESERVED;
|
||
|
}
|
||
|
} else {
|
||
|
rs = cvmx_allocate_global_resource_range(
|
||
|
CVMX_GR_TAG_QPG_ENTRY(node), base_offset, count, 1);
|
||
|
if (rs == -1) {
|
||
|
printf("ERROR: Failed to allocate qpg entry\n");
|
||
|
return CVMX_RESOURCE_ALLOC_FAILED;
|
||
|
}
|
||
|
}
|
||
|
base_offset = rs;
|
||
|
return base_offset;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* This function frees QPG table entries per node.
|
||
|
* @param node node number.
|
||
|
* @param base_offset base_offset in qpg table. If -1, first available
|
||
|
* qpg base_offset will be allocated. If base_offset is positive
|
||
|
* number and in range, it will try to allocate specified base_offset.
|
||
|
* @param count number of consecutive qpg entries to allocate. They will be consecutive
|
||
|
* from base offset.
|
||
|
* @return qpg table base offset number on success, -1 on failure.
|
||
|
*/
|
||
|
int cvmx_pki_qpg_entry_free(int node, int base_offset, int count)
|
||
|
{
|
||
|
if (cvmx_free_global_resource_range_with_base(
|
||
|
CVMX_GR_TAG_QPG_ENTRY(node), base_offset, count) == -1) {
|
||
|
printf("ERROR Failed to release qpg offset %d",
|
||
|
(int)base_offset);
|
||
|
return -1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int cvmx_pki_mtag_idx_alloc(int node, int idx)
|
||
|
{
|
||
|
if (cvmx_create_global_resource_range(CVMX_GR_TAG_MTAG_IDX(node),
|
||
|
CVMX_PKI_NUM_MTAG_IDX)) {
|
||
|
printf("ERROR: Failed to create MTAG-IDX global resource\n");
|
||
|
return -1;
|
||
|
}
|
||
|
if (idx >= 0) {
|
||
|
idx = cvmx_reserve_global_resource_range(
|
||
|
CVMX_GR_TAG_MTAG_IDX(node), idx, idx, 1);
|
||
|
if (idx == -1) {
|
||
|
debug("INFO: MTAG index %d is already reserved\n",
|
||
|
(int)idx);
|
||
|
return CVMX_RESOURCE_ALREADY_RESERVED;
|
||
|
}
|
||
|
} else {
|
||
|
idx = cvmx_allocate_global_resource_range(
|
||
|
CVMX_GR_TAG_MTAG_IDX(node), idx, 1, 1);
|
||
|
if (idx == -1) {
|
||
|
printf("ERROR: Failed to allocate MTAG index\n");
|
||
|
return CVMX_RESOURCE_ALLOC_FAILED;
|
||
|
}
|
||
|
}
|
||
|
return idx;
|
||
|
}
|