From patchwork Wed Mar 11 05:08:50 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Igal.Liberman" X-Patchwork-Id: 448873 X-Patchwork-Delegate: scottwood@freescale.com Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id C20271400DD for ; Wed, 11 Mar 2015 20:29:25 +1100 (AEDT) Received: from lists.ozlabs.org (lists.ozlabs.org [IPv6:2401:3900:2:1::3]) by lists.ozlabs.org (Postfix) with ESMTP id A29111A2359 for ; Wed, 11 Mar 2015 20:29:25 +1100 (AEDT) X-Original-To: linuxppc-dev@lists.ozlabs.org Delivered-To: linuxppc-dev@lists.ozlabs.org Received: from na01-bn1-obe.outbound.protection.outlook.com (mail-bn1bbn0106.outbound.protection.outlook.com [157.56.111.106]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-SHA384 (256/256 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id C19D71A117A for ; Wed, 11 Mar 2015 20:13:27 +1100 (AEDT) Received: from BN3PR0301CA0067.namprd03.prod.outlook.com (25.160.152.163) by BN1PR0301MB0721.namprd03.prod.outlook.com (25.160.78.140) with Microsoft SMTP Server (TLS) id 15.1.106.15; Wed, 11 Mar 2015 09:13:20 +0000 Received: from BL2FFO11FD016.protection.gbl (2a01:111:f400:7c09::128) by BN3PR0301CA0067.outlook.office365.com (2a01:111:e400:401e::35) with Microsoft SMTP Server (TLS) id 15.1.106.15 via Frontend Transport; Wed, 11 Mar 2015 09:13:19 +0000 Received: from az84smr01.freescale.net (192.88.158.2) by BL2FFO11FD016.mail.protection.outlook.com (10.173.160.224) with Microsoft SMTP Server (TLS) id 15.1.112.13 via Frontend Transport; Wed, 11 Mar 2015 09:13:19 +0000 Received: from b31950-Sun-Ultra-20-Workstation.fil.ea.freescale.net ([10.96.120.118]) by az84smr01.freescale.net (8.14.3/8.14.0) with ESMTP id t2B9DGb3028310; Wed, 11 Mar 2015 02:13:16 -0700 From: Igal.Liberman To: , , Subject: [RFC,6/8] soc/fman: Add FMan SP support Date: Wed, 11 Mar 2015 07:08:50 +0200 Message-ID: <1426050530-12673-1-git-send-email-igal.liberman@freescale.com> X-Mailer: git-send-email 1.7.9.5 X-EOPAttributedMessage: 0 Received-SPF: Fail (protection.outlook.com: domain of freescale.com does not designate 192.88.158.2 as permitted sender) receiver=protection.outlook.com; client-ip=192.88.158.2; helo=az84smr01.freescale.net; Authentication-Results: spf=fail (sender IP is 192.88.158.2) smtp.mailfrom=igal.liberman@freescale.com; freescale.mail.onmicrosoft.com; dkim=none (message not signed) header.d=none; X-Forefront-Antispam-Report: CIP:192.88.158.2; CTRY:US; IPV:NLI; EFV:NLI; BMV:1; SFV:NSPM; SFS:(10019020)(6009001)(339900001)(189002)(199003)(46102003)(105606002)(92566002)(33646002)(104016003)(106466001)(36756003)(47776003)(86362001)(2201001)(50466002)(48376002)(19580405001)(87936001)(50226001)(6806004)(229853001)(85426001)(77096005)(50986999)(77156002)(19580395003)(2004002); DIR:OUT; SFP:1102; SCL:1; SRVR:BN1PR0301MB0721; H:az84smr01.freescale.net; FPR:; SPF:Fail; MLV:sfv; MX:1; A:1; LANG:en; MIME-Version: 1.0 X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BN1PR0301MB0721; X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(5002009)(5005006); SRVR:BN1PR0301MB0721; BCL:0; PCL:0; RULEID:; SRVR:BN1PR0301MB0721; X-Forefront-PRVS: 0512CC5201 X-OriginatorOrg: freescale.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Mar 2015 09:13:19.3945 (UTC) X-MS-Exchange-CrossTenant-Id: 710a03f5-10f6-4d38-9ff4-a80b81da590d X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=710a03f5-10f6-4d38-9ff4-a80b81da590d; Ip=[192.88.158.2]; Helo=[az84smr01.freescale.net] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: BN1PR0301MB0721 Cc: scottwood@freescale.com, Igal Liberman X-BeenThere: linuxppc-dev@lists.ozlabs.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: linuxppc-dev-bounces+patchwork-incoming=ozlabs.org@lists.ozlabs.org Sender: "Linuxppc-dev" From: Igal Liberman Signed-off-by: Igal Liberman --- drivers/soc/fsl/fman/fm_sp_common.h | 112 +++++++++ drivers/soc/fsl/fman/sp/Makefile | 2 +- drivers/soc/fsl/fman/sp/fm_sp.c | 429 +++++++++++++++++++++++++++++++++++ 3 files changed, 542 insertions(+), 1 deletion(-) create mode 100644 drivers/soc/fsl/fman/fm_sp_common.h create mode 100644 drivers/soc/fsl/fman/sp/fm_sp.c diff --git a/drivers/soc/fsl/fman/fm_sp_common.h b/drivers/soc/fsl/fman/fm_sp_common.h new file mode 100644 index 0000000..3809c24 --- /dev/null +++ b/drivers/soc/fsl/fman/fm_sp_common.h @@ -0,0 +1,112 @@ +/* + * Copyright 2008-2015 Freescale Semiconductor Inc. + * + * 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 Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* FM SP ... */ +#ifndef __FM_SP_COMMON_H +#define __FM_SP_COMMON_H + +#include "service.h" +#include "fm_ext.h" +#include "fm_pcd_ext.h" +#include "fsl_fman.h" + +/* defaults */ +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_DATA_SIZE 0 +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTENT_PRIV_PASS_PRS_RESULT false +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_PASS_TIME_STAMP false +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_ALL_OTHER_PCD_INFO false +#define DEFAULT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN 64 + +/* structure for defining internal context copying */ +struct fm_sp_int_context_data_copy_t { + /* < Offset in External buffer to which internal + * context is copied to (Rx) or taken from (Tx, Op). + */ + uint16_t ext_buf_offset; + /* Offset within internal context to copy from + * (Rx) or to copy to (Tx, Op). + */ + uint8_t int_context_offset; + /* Internal offset size to be copied */ + uint16_t size; +}; + +/* struct for defining external buffer margins */ +struct fm_sp_buf_margins_t { + /* Number of bytes to be left at the beginning + * of the external buffer (must be divisible by 16) + */ + uint16_t start_margins; + /* number of bytes to be left at the end + * of the external buffer(must be divisible by 16) + */ + uint16_t end_margins; +}; + +struct fm_sp_buffer_offsets_t { + uint32_t data_offset; + uint32_t prs_result_offset; + uint32_t time_stamp_offset; + uint32_t hash_result_offset; + uint32_t pcd_info_offset; +}; + +int fm_sp_build_buffer_structure(struct fm_sp_int_context_data_copy_t + *p_fm_port_int_context_data_copy, + struct fm_buffer_prefix_content_t + *p_buffer_prefix_content, + struct fm_sp_buf_margins_t + *p_fm_port_buf_margins, + struct fm_sp_buffer_offsets_t + *p_fm_port_buffer_offsets, + uint8_t *internal_buf_offset); + +int fm_sp_check_int_context_params(struct fm_sp_int_context_data_copy_t * + p_fm_sp_int_context_data_copy); +int fm_sp_check_buf_pools_params(struct fm_ext_pools_t *p_fm_ext_pools, + struct fm_backup_bm_pools_t + *p_fm_backup_bm_pools, + struct fm_buf_pool_depletion_t + *p_fm_buf_pool_depletion, + uint32_t max_num_of_ext_pools, + uint32_t bm_max_num_of_pools); +int fm_sp_check_buf_margins(struct fm_sp_buf_margins_t *p_fm_sp_buf_margins); +void fm_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fm_ext_pools_t + *p_fm_ext_pools, + uint8_t *ordered_array, + uint16_t *sizes_array); + +int fm_pcd_sp_alloc_profiles(void *h_fm_pcd, + uint8_t port_id, + uint16_t num_of_storage_profiles, + uint16_t *base, uint8_t *log2_num); +#endif /* __FM_SP_COMMON_H */ diff --git a/drivers/soc/fsl/fman/sp/Makefile b/drivers/soc/fsl/fman/sp/Makefile index 97e89c9..2a324ae 100644 --- a/drivers/soc/fsl/fman/sp/Makefile +++ b/drivers/soc/fsl/fman/sp/Makefile @@ -1,3 +1,3 @@ obj-$(CONFIG_FSL_FMAN) += fsl_fman_sp.o -fsl_fman_sp-objs := fman_sp.o +fsl_fman_sp-objs := fman_sp.o fm_sp.o diff --git a/drivers/soc/fsl/fman/sp/fm_sp.c b/drivers/soc/fsl/fman/sp/fm_sp.c new file mode 100644 index 0000000..5bba23c --- /dev/null +++ b/drivers/soc/fsl/fman/sp/fm_sp.c @@ -0,0 +1,429 @@ +/* + * Copyright 2008 - 2015 Freescale Semiconductor Inc. + * + * 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 Freescale Semiconductor nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * + * ALTERNATIVELY, this software may be distributed under the terms of the + * GNU General Public License ("GPL") as published by the Free Software + * Foundation, either version 2 of that License or (at your option) any + * later version. + * + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* FM PCD Storage profile ... */ + +#include "service.h" +#include "net_ext.h" + +#include "fm_sp_common.h" +#include "fm_common.h" +#include "fsl_fman_sp.h" + +#include + +/* Inter-module API routines */ + +void fm_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fm_ext_pools_t + *p_fm_ext_pools, + uint8_t *ordered_array, + uint16_t *sizes_array) +{ + uint16_t buf_size = 0; + int i = 0, j = 0, k = 0; + + /* First we copy the external buffers pools information + * to an ordered local array + */ + for (i = 0; i < p_fm_ext_pools->num_of_pools_used; i++) { + /* get pool size */ + buf_size = p_fm_ext_pools->ext_buf_pool[i].size; + + /* keep sizes in an array according to poolId + * for direct access + */ + sizes_array[p_fm_ext_pools->ext_buf_pool[i].id] = buf_size; + + /* save poolId in an ordered array according to size */ + for (j = 0; j <= i; j++) { + /* this is the next free place in the array */ + if (j == i) + ordered_array[i] = + p_fm_ext_pools->ext_buf_pool[i].id; + else { + /* find the right place for this poolId */ + if (buf_size < sizes_array[ordered_array[j]]) { + /* move the pool_ids one place ahead + * to make room for this poolId + */ + for (k = i; k > j; k--) + ordered_array[k] = + ordered_array[k - 1]; + + /* now k==j, this is the place for + * the new size + */ + ordered_array[k] = + p_fm_ext_pools->ext_buf_pool[i].id; + break; + } + } + } + } +} + +int fm_sp_check_buf_pools_params(struct fm_ext_pools_t *p_fm_ext_pools, + struct fm_backup_bm_pools_t + *p_fm_backup_bm_pools, + struct fm_buf_pool_depletion_t + *p_fm_buf_pool_depletion, + uint32_t max_num_of_ext_pools, + uint32_t bm_max_num_of_pools) +{ + int i = 0, j = 0; + bool found; + uint8_t count = 0; + + if (p_fm_ext_pools) { + if (p_fm_ext_pools->num_of_pools_used > max_num_of_ext_pools) { + pr_err("num_of_pools_used can't be larger than %d\n", + max_num_of_ext_pools); + return -EDOM; + } + for (i = 0; i < p_fm_ext_pools->num_of_pools_used; i++) { + if (p_fm_ext_pools->ext_buf_pool[i].id >= + bm_max_num_of_pools) { + pr_err("ext_buf_pools.ext_buf_pool[%d].id can't be larger than %d\n", + i, bm_max_num_of_pools); + return -EDOM; + } + if (!p_fm_ext_pools->ext_buf_pool[i].size) { + pr_err("ext_buf_pools.ext_buf_pool[%d].size is 0\n", + i); + return -EDOM; + } + } + } + if (!p_fm_ext_pools && (p_fm_backup_bm_pools || + p_fm_buf_pool_depletion)) { + pr_err("backupBmPools ot buf_pool_depletion can not be defined without external pools\n"); + return -EDOM; + } + /* backup BM pools indication is valid only for some chip derivatives + * (limited by the config routine) + */ + if (p_fm_backup_bm_pools) { + if (p_fm_backup_bm_pools->num_of_backup_pools >= + p_fm_ext_pools->num_of_pools_used) { + pr_err("p_backup_bm_pools must be smaller than ext_buf_pools.num_of_pools_used\n"); + return -EDOM; + } + found = false; + for (i = 0; i < p_fm_backup_bm_pools-> + num_of_backup_pools; i++) { + for (j = 0; j < p_fm_ext_pools-> + num_of_pools_used; j++) { + if (p_fm_backup_bm_pools->pool_ids[i] == + p_fm_ext_pools->ext_buf_pool[j].id) { + found = true; + break; + } + } + if (!found) { + pr_err("All p_backup_bm_pools.pool_ids must be included in ext_buf_pools.ext_buf_pool[n].id\n"); + return -EDOM; + } + found = false; + } + } + + /* up to ext_buf_pools.num_of_pools_used pools may be defined */ + if (p_fm_buf_pool_depletion && p_fm_buf_pool_depletion-> + pools_grp_mode_enable) { + if ((p_fm_buf_pool_depletion->num_of_pools > + p_fm_ext_pools->num_of_pools_used)) { + pr_err("buf_pool_depletion.num_of_pools can't be larger than %d and can't be larger than num_of_pools_used\n", + max_num_of_ext_pools); + return -EDOM; + } + if (!p_fm_buf_pool_depletion->num_of_pools) { + pr_err("buf_pool_depletion.num_of_pools_to_consider can not be 0 when pools_grp_mode_enable=true\n"); + return -EDOM; + } + found = false; + count = 0; + /* for each pool that is in pools_to_consider, check if it + * is defined in ext_buf_pool + */ + for (i = 0; i < bm_max_num_of_pools; i++) { + if (p_fm_buf_pool_depletion->pools_to_consider[i]) { + for (j = 0; j < p_fm_ext_pools-> + num_of_pools_used; j++) { + if (i == p_fm_ext_pools-> + ext_buf_pool[j].id) { + found = true; + count++; + break; + } + } + if (!found) { + pr_err("Pools selected for depletion are not used.\n"); + return -ENOSYS; + } + found = false; + } + } + /* check that the number of pools that we have checked is + * equal to the number announced by the user + */ + if (count != p_fm_buf_pool_depletion->num_of_pools) { + pr_err("buf_pool_depletion.num_of_pools is larger than the number of pools defined.\n"); + return -EDOM; + } + } + + if (p_fm_buf_pool_depletion && p_fm_buf_pool_depletion-> + single_pool_mode_enable) { + /* calculate vector for number of pools depletion */ + found = false; + count = 0; + for (i = 0; i < bm_max_num_of_pools; i++) { + if (p_fm_buf_pool_depletion-> + pools_to_consider_for_single_mode[i]) { + for (j = 0; j < p_fm_ext_pools-> + num_of_pools_used; + j++) { + if (i == p_fm_ext_pools-> + ext_buf_pool[j].id) { + found = true; + count++; + break; + } + } + if (!found) { + pr_err("Pools selected for depletion are not used.\n"); + return -ENOSYS; + } + found = false; + } + } + if (!count) { + pr_err("No pools defined for single buffer mode pool depletion.\n"); + return -EDOM; + } + } + + return 0; +} + +int fm_sp_check_int_context_params(struct fm_sp_int_context_data_copy_t * + p_fm_sp_int_context_data_copy) +{ + /* Check that divisible by 16 and not larger than 240 */ + if (p_fm_sp_int_context_data_copy->int_context_offset > + MAX_INT_OFFSET) { + pr_err("int_context.int_context_offset can't be larger than %d\n", + MAX_INT_OFFSET); + return -EDOM; + } + if (p_fm_sp_int_context_data_copy->int_context_offset % + OFFSET_UNITS) { + pr_err("int_context.int_context_offset has to be divisible by %d\n", + OFFSET_UNITS); + return -EDOM; + + /* check that ic size+ic internal offset, does not exceed + * ic block size + */ + } + if (p_fm_sp_int_context_data_copy->size + + p_fm_sp_int_context_data_copy->int_context_offset > + MAX_IC_SIZE) { + pr_err("int_context.size + int_context.int_context_offset has to be smaller than %d\n", + MAX_IC_SIZE); + return -EDOM; + /* Check that divisible by 16 and not larger than 256 */ + } + if (p_fm_sp_int_context_data_copy->size % OFFSET_UNITS) { + pr_err("int_context.size has to be divisible by %d\n", + OFFSET_UNITS); + return -EDOM; + + /* Check that divisible by 16 and not larger than 4K */ + } + if (p_fm_sp_int_context_data_copy->ext_buf_offset > MAX_EXT_OFFSET) { + pr_err("int_context.ext_buf_offset can't be larger than %d\n", + MAX_EXT_OFFSET); + return -EDOM; + } + if (p_fm_sp_int_context_data_copy->ext_buf_offset % OFFSET_UNITS) { + pr_err("int_context.ext_buf_offset has to be divisible by %d\n", + OFFSET_UNITS); + return -EDOM; + } + return 0; +} + +int fm_sp_check_buf_margins(struct fm_sp_buf_margins_t + *p_fm_sp_buf_margins) +{ + /* Check the margin definition */ + if (p_fm_sp_buf_margins->start_margins > MAX_EXT_BUFFER_OFFSET) { + pr_err("buf_margins.start_margins can't be larger than %d\n", + MAX_EXT_BUFFER_OFFSET); + return -EDOM; + } + if (p_fm_sp_buf_margins->end_margins > MAX_EXT_BUFFER_OFFSET) { + pr_err("buf_margins.end_margins can't be larger than %d\n", + MAX_EXT_BUFFER_OFFSET); + return -EDOM; + } + return 0; +} + +int fm_sp_build_buffer_structure(struct fm_sp_int_context_data_copy_t * + p_fm_sp_int_context_data_copy, + struct fm_buffer_prefix_content_t * + p_buffer_prefix_content, + struct fm_sp_buf_margins_t + *p_fm_sp_buf_margins, + struct fm_sp_buffer_offsets_t + *p_fm_sp_buffer_offsets, + uint8_t *internal_buf_offset) +{ + uint32_t tmp; + + /* Align start of internal context data to 16 byte */ + p_fm_sp_int_context_data_copy->ext_buf_offset = (uint16_t) + ((p_buffer_prefix_content->priv_data_size & + (OFFSET_UNITS - 1)) ? + ((p_buffer_prefix_content->priv_data_size + OFFSET_UNITS) & + ~(uint16_t)(OFFSET_UNITS - 1)) : + p_buffer_prefix_content->priv_data_size); + + /* Translate margin and int_context params to FM parameters */ + /* Initialize with illegal value. Later we'll set legal values. */ + p_fm_sp_buffer_offsets->prs_result_offset = (uint32_t)ILLEGAL_BASE; + p_fm_sp_buffer_offsets->time_stamp_offset = (uint32_t)ILLEGAL_BASE; + p_fm_sp_buffer_offsets->hash_result_offset = (uint32_t)ILLEGAL_BASE; + p_fm_sp_buffer_offsets->pcd_info_offset = (uint32_t)ILLEGAL_BASE; + + /* Internally the driver supports 4 options + * 1. prsResult/timestamp/hashResult selection (in fact 8 options, + * but for simplicity we'll + * relate to it as 1). + * 2. All IC context (from AD) not including debug. + */ + + /* This 'if' covers option 2. We copy from beginning of context. */ + if (p_buffer_prefix_content->pass_all_other_pcd_info) { + /* must be aligned to 16 */ + p_fm_sp_int_context_data_copy->size = 128; + /* Start copying data after 16 bytes (FD) from + * the beginning of the internal context + */ + p_fm_sp_int_context_data_copy->int_context_offset = 16; + + if (p_buffer_prefix_content->pass_all_other_pcd_info) + p_fm_sp_buffer_offsets->pcd_info_offset = + p_fm_sp_int_context_data_copy->ext_buf_offset; + if (p_buffer_prefix_content->pass_prs_result) + p_fm_sp_buffer_offsets->prs_result_offset = + (uint32_t) + (p_fm_sp_int_context_data_copy->ext_buf_offset + + 16); + if (p_buffer_prefix_content->pass_time_stamp) + p_fm_sp_buffer_offsets->time_stamp_offset = + (uint32_t) + (p_fm_sp_int_context_data_copy->ext_buf_offset + + 48); + if (p_buffer_prefix_content->pass_hash_result) + p_fm_sp_buffer_offsets->hash_result_offset = + (uint32_t) + (p_fm_sp_int_context_data_copy->ext_buf_offset + + 56); + } else { + /* This case covers the options under 1 */ + /* Copy size must be in 16-byte granularity. */ + p_fm_sp_int_context_data_copy->size = + (uint16_t)((p_buffer_prefix_content-> + pass_prs_result ? 32 : 0) + + ((p_buffer_prefix_content->pass_time_stamp || + p_buffer_prefix_content-> + pass_hash_result) ? 16 : 0)); + + /* Align start of internal context data to 16 byte */ + p_fm_sp_int_context_data_copy->int_context_offset = + (uint8_t)(p_buffer_prefix_content->pass_prs_result ? 32 : + ((p_buffer_prefix_content->pass_time_stamp || + p_buffer_prefix_content-> + pass_hash_result) ? 64 : 0)); + + if (p_buffer_prefix_content->pass_prs_result) + p_fm_sp_buffer_offsets->prs_result_offset = + p_fm_sp_int_context_data_copy->ext_buf_offset; + if (p_buffer_prefix_content->pass_time_stamp) + p_fm_sp_buffer_offsets->time_stamp_offset = + p_buffer_prefix_content-> + pass_prs_result ? (p_fm_sp_int_context_data_copy-> + ext_buf_offset + + sizeof(struct fm_prs_result_t)) : + p_fm_sp_int_context_data_copy->ext_buf_offset; + if (p_buffer_prefix_content->pass_hash_result) + /* If PR is not requested, whether TS is + * requested or not, IC will be copied from TS + */ + p_fm_sp_buffer_offsets->hash_result_offset = + p_buffer_prefix_content-> + pass_prs_result ? (p_fm_sp_int_context_data_copy-> + ext_buf_offset + + sizeof(struct fm_prs_result_t) + + 8) : + p_fm_sp_int_context_data_copy-> + ext_buf_offset + 8; + } + + if (p_fm_sp_int_context_data_copy->size) + p_fm_sp_buf_margins->start_margins = + (uint16_t)(p_fm_sp_int_context_data_copy->ext_buf_offset + + p_fm_sp_int_context_data_copy->size); + else + /* No Internal Context passing, STartMargin is + * immediately after private_info + */ + p_fm_sp_buf_margins->start_margins = + p_buffer_prefix_content->priv_data_size; + + /* align data start */ + tmp = + (uint32_t)(p_fm_sp_buf_margins->start_margins % + p_buffer_prefix_content->data_align); + if (tmp) + p_fm_sp_buf_margins->start_margins += + (p_buffer_prefix_content->data_align - tmp); + p_fm_sp_buffer_offsets->data_offset = p_fm_sp_buf_margins-> + start_margins; + + return 0; +} + +/* End of inter-module routines */