[RFC,4/8] soc/fman: Add FMan Parser and Keygen support
Igal.Liberman
igal.liberman at freescale.com
Wed Mar 11 16:08:29 AEDT 2015
From: Igal Liberman <Igal.Liberman at freescale.com>
Signed-off-by: Igal Liberman <Igal.Liberman at freescale.com>
---
drivers/soc/fsl/fman/fm.c | 38 +++
drivers/soc/fsl/fman/fm.h | 1 +
drivers/soc/fsl/fman/fm_common.h | 32 +++
drivers/soc/fsl/fman/fm_drv.c | 89 ++++++-
drivers/soc/fsl/fman/fm_drv.h | 18 ++
drivers/soc/fsl/fman/inc/fm_pcd_ext.h | 167 +++++++++++++
drivers/soc/fsl/fman/pcd/Makefile | 2 +-
drivers/soc/fsl/fman/pcd/fm_pcd.c | 428 +++++++++++++++++++++++++++++++++
drivers/soc/fsl/fman/pcd/fm_pcd.h | 145 +++++++++++
drivers/soc/fsl/fman/pcd/fm_prs.c | 276 +++++++++++++++++++++
drivers/soc/fsl/fman/pcd/fm_prs.h | 163 +++++++++++++
11 files changed, 1357 insertions(+), 2 deletions(-)
create mode 100644 drivers/soc/fsl/fman/inc/fm_pcd_ext.h
create mode 100644 drivers/soc/fsl/fman/pcd/fm_pcd.c
create mode 100644 drivers/soc/fsl/fman/pcd/fm_pcd.h
create mode 100644 drivers/soc/fsl/fman/pcd/fm_prs.c
create mode 100644 drivers/soc/fsl/fman/pcd/fm_prs.h
diff --git a/drivers/soc/fsl/fman/fm.c b/drivers/soc/fsl/fman/fm.c
index 56711cb..1d32d446 100644
--- a/drivers/soc/fsl/fman/fm.c
+++ b/drivers/soc/fsl/fman/fm.c
@@ -721,6 +721,17 @@ uint16_t fm_get_tnum_aging_period(void *h_fm)
return p_fm->tnum_aging_period;
}
+uintptr_t fm_get_pcd_prs_base_addr(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ if (!p_fm->base_addr) {
+ pr_err("No base-addr!\n");
+ return 0;
+ }
+ return p_fm->base_addr + FM_MM_PRS;
+}
+
struct muram_info *fm_get_muram_pointer(void *h_fm)
{
struct fm_t *p_fm = (struct fm_t *)h_fm;
@@ -847,6 +858,33 @@ void fm_unregister_fman_ctrl_intr(void *h_fm, uint8_t event_reg_id)
p_fm->fman_ctrl_intr[event_reg_id].h_src_handle = NULL;
}
+void fm_register_pcd(void *h_fm, void *h_fm_pcd)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ if (p_fm->h_pcd)
+ pr_err("PCD already set\n");
+
+ p_fm->h_pcd = h_fm_pcd;
+}
+
+void fm_unregister_pcd(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ if (!p_fm->h_pcd)
+ pr_err("PCD handle!\n");
+
+ p_fm->h_pcd = NULL;
+}
+
+void *fm_get_pcd_handle(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ return p_fm->h_pcd;
+}
+
uint8_t fm_get_id(void *h_fm)
{
struct fm_t *p_fm = (struct fm_t *)h_fm;
diff --git a/drivers/soc/fsl/fman/fm.h b/drivers/soc/fsl/fman/fm.h
index 332f2e6..eb71103 100644
--- a/drivers/soc/fsl/fman/fm.h
+++ b/drivers/soc/fsl/fman/fm.h
@@ -452,6 +452,7 @@ struct fm_t {
uintptr_t base_addr;
/* un-needed for recovery */
+ void *h_pcd;
char fm_module_name[MODULE_NAME_SIZE];
/* FM exceptions user callback */
struct fm_intr_src_t intr_mng[FM_EV_DUMMY_LAST];
diff --git a/drivers/soc/fsl/fman/fm_common.h b/drivers/soc/fsl/fman/fm_common.h
index f380133..1e3422c 100644
--- a/drivers/soc/fsl/fman/fm_common.h
+++ b/drivers/soc/fsl/fman/fm_common.h
@@ -38,6 +38,7 @@
#include "service.h"
#include "fm_ext.h"
+#include "fm_pcd_ext.h"
#define CLS_PLAN_NUM_PER_GRP 8
@@ -238,6 +239,27 @@ default: \
((cls_plan_entries == 256) ? 8 : ((cls_plan_entries == 128) ? 7 : \
((cls_plan_entries == 64) ? 6 : ((cls_plan_entries == 32) ? 5 : 0))))
+struct fm_pcd_lock_t {
+ spinlock_t *spinlock;
+ volatile bool flag;
+ struct list_head node;
+};
+
+#define FM_PCD_LOCK_OBJ(ptr) list_object(ptr, struct fm_pcd_lock_t, node)
+
+/* Common API for FM-PCD module */
+uint32_t fm_pcd_get_sw_prs_offset(void *h_fm_pcd, enum net_header_type hdr,
+ uint8_t index_per_hdr);
+uint32_t fm_pcd_lock(void *h_fm_pcd);
+void fm_pcd_unlock(void *h_fm_pcd, unsigned long int_flags);
+bool fm_pcd_lock_try_lock_all(void *h_fm_pcd);
+void fm_pcd_lock_unlock_all(void *h_fm_pcd);
+
+/* Common API for FM-PCD parser module */
+int fm_pcd_prs_include_port_in_statistics(void *p_fm_pcd,
+ uint8_t port_id,
+ bool include);
+
/* Function fm_register_intr
* Description Used to register
* an inter-module event handler to be processed by FM
@@ -276,6 +298,13 @@ enum fm_mac_type {
FM_MAC_1G /* 1G MAC */
};
+/* Function fm_get_pcd_prs_base_addr
+ * Description Get the base address of the Parser from the FM module
+ * Param[in] h_fm A handle to an FM Module.
+ * Return Base address.
+ */
+uintptr_t fm_get_pcd_prs_base_addr(void *h_fm);
+
/* Function fm_get_muram_pointer
* Description Get the pointer of the MURAM from the FM module
* Param[in] h_fm A handle to an FM Module.
@@ -335,6 +364,9 @@ int fm_set_num_of_riscs_per_port(void *h_fm, uint8_t port_id,
uint8_t num_of_fman_ctrls,
fm_fman_ctrl_t or_fman_ctrl);
+void fm_register_pcd(void *h_fm, void *h_fm_pcd);
+void fm_unregister_pcd(void *h_fm);
+void *fm_get_pcd_handle(void *h_fm);
int _fm_enable_rams_ecc(void *h_fm);
int _fm_disable_rams_ecc(void *h_fm);
int fm_alloc_fman_ctrl_event_reg(void *h_fm, uint8_t *p_event_id);
diff --git a/drivers/soc/fsl/fman/fm_drv.c b/drivers/soc/fsl/fman/fm_drv.c
index ffeb223..cacd318 100644
--- a/drivers/soc/fsl/fman/fm_drv.c
+++ b/drivers/soc/fsl/fman/fm_drv.c
@@ -55,7 +55,7 @@
/* Internal services */
#include "service.h"
-#include "fm_ext.h"
+#include "fm_common.h"
#include "fm_drv.h"
#include "fm_muram_ext.h"
@@ -219,6 +219,58 @@ static void destroy_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
kfree(p_lnx_wrp_fm_dev);
}
+#ifdef CONFIG_FSL_FMAN_PCD
+static void lnxwrp_fm_pcd_dev_exceptions_cb(void *h_app,
+ enum fm_pcd_exceptions
+ __maybe_unused exception)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+ (struct lnx_wrp_fm_dev_t *)h_app;
+
+ ASSERT(p_lnx_wrp_fm_dev);
+
+ pr_debug("got fm-pcd exception %d\n", exception);
+
+ /* do nothing */
+}
+
+static int init_fm_pcd_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+ if (p_lnx_wrp_fm_dev->pcd_active) {
+ struct fm_pcd_params_t fm_pcd_params;
+ int err;
+
+ memset(&fm_pcd_params, 0, sizeof(fm_pcd_params));
+ fm_pcd_params.h_fm = p_lnx_wrp_fm_dev->h_dev;
+ fm_pcd_params.prs_support = p_lnx_wrp_fm_dev->prs_active;
+
+ fm_pcd_params.f_exception = lnxwrp_fm_pcd_dev_exceptions_cb;
+ fm_pcd_params.h_app = p_lnx_wrp_fm_dev;
+
+ p_lnx_wrp_fm_dev->h_pcd_dev = fm_pcd_config(&fm_pcd_params);
+ if (!p_lnx_wrp_fm_dev->h_pcd_dev) {
+ pr_err("FM PCD!\n");
+ return -ENOSYS;
+ }
+
+ err = fm_pcd_init(p_lnx_wrp_fm_dev->h_pcd_dev);
+ if (err != 0)
+ return err;
+
+ if (p_lnx_wrp_fm_dev->err_irq == 0) {
+ fm_pcd_set_exception(p_lnx_wrp_fm_dev->h_pcd_dev,
+ FM_PCD_PRS_EXCEPTION_DOUBLE_ECC,
+ false);
+ fm_pcd_set_exception(p_lnx_wrp_fm_dev->h_pcd_dev,
+ FM_PCD_PRS_EXCEPTION_SINGLE_ECC,
+ false);
+ }
+ }
+
+ return 0;
+}
+#endif
+
/**
*find_fman_microcode - find the Fman microcode
*
@@ -449,6 +501,23 @@ static struct lnx_wrp_fm_dev_t *read_fm_dev_tree_node(struct platform_device
}
#endif
+#ifdef CONFIG_FSL_FMAN_PCD
+ /* Enable relevant PCD nodes - Parser */
+ p_lnx_wrp_fm_dev->prs_active = true;
+ p_lnx_wrp_fm_dev->pcd_active = true;
+
+ if (p_lnx_wrp_fm_dev->pcd_active) {
+ const char *str_prop =
+ (char *)of_get_property(fm_node, "fsl,default-pcd", &lenp);
+ if (str_prop) {
+ if (strncmp(str_prop, "3-tuple", strlen("3-tuple")) ==
+ 0)
+ p_lnx_wrp_fm_dev->def_pcd = FM_PCD_3_TUPLE;
+ } else
+ p_lnx_wrp_fm_dev->def_pcd = e_NO_PCD;
+ }
+#endif
+
of_node_put(fm_node);
p_lnx_wrp_fm_dev->active = true;
@@ -684,6 +753,12 @@ static int init_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
return -ENOSYS;
}
+#ifdef CONFIG_FSL_FMAN_PCD
+ if (init_fm_pcd_dev(p_lnx_wrp_fm_dev) != 0) {
+ pr_err("FM-PCD\n");
+ return -ENOSYS;
+ }
+#endif
/* TODO: Why we mask these interrupts? */
if (p_lnx_wrp_fm_dev->err_irq == 0) {
fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
@@ -760,11 +835,23 @@ static int init_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
return 0;
}
+#ifdef CONFIG_FSL_FMAN_PCD
+void free_fm_pcd_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+ if (p_lnx_wrp_fm_dev->h_pcd_dev)
+ fm_pcd_free(p_lnx_wrp_fm_dev->h_pcd_dev);
+}
+#endif
+
static void free_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
{
if (!p_lnx_wrp_fm_dev->active)
return;
+#ifdef CONFIG_FSL_FMAN_PCD
+ free_fm_pcd_dev(p_lnx_wrp_fm_dev);
+#endif
+
#ifdef CONFIG_FSL_FMAN_RTC
if (p_lnx_wrp_fm_dev->h_rtc_dev)
fm_rtc_free((struct fm *)p_lnx_wrp_fm_dev);
diff --git a/drivers/soc/fsl/fman/fm_drv.h b/drivers/soc/fsl/fman/fm_drv.h
index c2831a7..3905795 100644
--- a/drivers/soc/fsl/fman/fm_drv.h
+++ b/drivers/soc/fsl/fman/fm_drv.h
@@ -61,6 +61,13 @@
#define TX_10G_PORT_BASE 0x30
#define RX_10G_PORT_BASE 0x10
+#ifdef CONFIG_FSL_FMAN_PCD
+enum lnx_wrp_fm_port_pcd_def_use_case {
+ e_NO_PCD = 0,
+ FM_PCD_3_TUPLE
+};
+#endif
+
struct lnx_wrp_fm_port_dev_t {
uint8_t id;
char name[20];
@@ -68,6 +75,9 @@ struct lnx_wrp_fm_port_dev_t {
uint64_t phys_base_addr;
uint64_t base_addr; /* Port's *virtual* address */
resource_size_t mem_size;
+#ifdef CONFIG_FSL_FMAN_PCD
+ enum lnx_wrp_fm_port_pcd_def_use_case def_pcd;
+#endif
struct fm_buffer_prefix_content_t buff_prefix_content;
void *h_dev;
void *h_lnx_wrp_fm_dev;
@@ -86,6 +96,11 @@ struct lnx_wrp_fm_dev_t {
uint8_t id;
char name[10];
bool active;
+#ifdef CONFIG_FSL_FMAN_PCD
+ bool pcd_active;
+ bool prs_active;
+ enum lnx_wrp_fm_port_pcd_def_use_case def_pcd;
+#endif
uint64_t fm_phys_base_addr;
uint64_t fm_base_addr;
resource_size_t fm_mem_size;
@@ -101,6 +116,9 @@ struct lnx_wrp_fm_dev_t {
int err_irq;
struct fm_params_t params;
void *h_dev;
+#ifdef CONFIG_FSL_FMAN_PCD
+ void *h_pcd_dev;
+#endif
#ifdef CONFIG_FSL_FMAN_RTC
void *h_rtc_dev;
#endif
diff --git a/drivers/soc/fsl/fman/inc/fm_pcd_ext.h b/drivers/soc/fsl/fman/inc/fm_pcd_ext.h
new file mode 100644
index 0000000..c716532
--- /dev/null
+++ b/drivers/soc/fsl/fman/inc/fm_pcd_ext.h
@@ -0,0 +1,167 @@
+/*
+ * 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.
+ */
+
+/*File fm_pcd_ext.h
+ * FM PCD API definitions
+ */
+#ifndef __FM_PCD_EXT
+#define __FM_PCD_EXT
+
+#include "service.h"
+#include "net_ext.h"
+#include "fm_ext.h"
+
+/* Frame Manager PCD (Parse-Classify-Distribute) API.
+ * The FM PCD module is responsible for the initialization of all global
+ * classifying FM modules. This includes the parser general and common
+ * registers.
+ */
+
+/* General PCD defines */
+
+/* Number of headers supported by HW parser
+ * Number of distinction units is limited by register size (32 bits) minus
+ * reserved bits for private headers.
+ */
+#define FM_PCD_PRS_NUM_OF_HDRS 16
+/* Maximum number of SW parser labels */
+#define FM_PCD_PRS_NUM_OF_LABELS 32
+/* Total size of SW parser area */
+#define FM_PCD_SW_PRS_SIZE 0x00000800
+
+/* Frame Manager PCD Initialization Unit API */
+
+/* PCD interrupts */
+enum fm_pcd_exceptions {
+ /* Parser double-bit ECC error */
+ FM_PCD_PRS_EXCEPTION_DOUBLE_ECC,
+ /* Parser single-bit ECC error */
+ FM_PCD_PRS_EXCEPTION_SINGLE_ECC
+};
+
+/*Description Exceptions user callback routine, will be called upon an
+ * exception passing the exception identification.
+ *Param[in] h_app - User's application descriptor.
+ *Param[in] exception - The exception.
+ */
+typedef void (fm_pcd_exception_cb) (void *h_app,
+ enum fm_pcd_exceptions exception);
+
+/* The main structure for PCD initialization */
+struct fm_pcd_params_t {
+ /* true if Parser will be used for any of the FM ports. */
+ bool prs_support;
+ /* A handle to the FM module. */
+ void *h_fm;
+ /* Callback routine for general PCD exceptions;
+ * Relevant when FM not runs in "guest-mode".
+ **/
+ fm_pcd_exception_cb *f_exception;
+ /* A handle to an application layer object;
+ * This handle will be passed by the driver upon calling
+ * the above callbacks; Relevant when FM not runs in "guest-mode".
+ */
+ void *h_app;
+};
+
+/*Function fm_pcd_config
+ *Description Basic configuration of the PCD module.
+ * Creates descriptor for the FM PCD module.
+ *Param[in] p_fm_pcd_params A structure of parameters for the
+ * initialization of PCD.
+ *Return A handle to the initialized module.
+ */
+void *fm_pcd_config(struct fm_pcd_params_t *p_fm_pcd_params);
+
+/*Function fm_pcd_init
+ *Description Initialization of the PCD module.
+ *Param[in] h_fm_pcd - FM PCD module descriptor.
+ *Return 0 on success; Error code otherwise.
+ */
+int fm_pcd_init(void *h_fm_pcd);
+
+/*Function fm_pcd_free
+ *Description Frees all resources that were assigned to FM module.
+ * Calling this routine invalidates the descriptor.
+ *Param[in] h_fm_pcd - FM PCD module descriptor.
+ *Return 0 on success; Error code otherwise.
+ */
+int fm_pcd_free(void *h_fm_pcd);
+
+/* Frame Manager PCD Runtime Unit API */
+
+/* A structure for SW parser labels*/
+struct fm_pcd_prs_label_params_t {
+ /* SW parser label instruction offset (2 bytes resolution),
+ * relative to Parser RAM.
+ */
+ uint32_t instruction_offset;
+ /* The existence of this header will invoke the SW parser code. */
+ enum net_header_type hdr;
+ /* Normally 0, if more than one SW parser attachments for the
+ * same header, use this index to distinguish between them.
+ */
+ uint8_t index_per_hdr;
+};
+
+/*Function fm_pcd_enable
+ *Description This routine should be called after PCD is initialized for
+ * enabling all
+ * PCD engines according to their existing configuration.
+ *Param[in] h_fm_pcd FM PCD module descriptor.
+ *Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_pcd_init() and when PCD is disabled.
+ */
+int fm_pcd_enable(void *h_fm_pcd);
+
+/*Function fm_pcd_disable
+ *Description This routine may be called when PCD is enabled in order to
+ * disable all PCD engines. It may be called
+ * only when none of the ports in the system are using the PCD.
+ *Param[in] h_fm_pcd FM PCD module descriptor.
+ *Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_pcd_init() and when PCD is enabled.
+ */
+int fm_pcd_disable(void *h_fm_pcd);
+
+/*Function fm_pcd_set_exception
+ *Description Calling this routine enables/disables PCD interrupts.
+ *Param[in] h_fm_pcd FM PCD module descriptor.
+ *Param[in] exception The exception to be selected.
+ *Param[in] enable true to enable interrupt, false to mask it.
+ *Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_pcd_init().
+ */
+int fm_pcd_set_exception(void *h_fm_pcd, enum fm_pcd_exceptions
+ exception, bool enable);
+
+#endif /* __FM_PCD_EXT */
diff --git a/drivers/soc/fsl/fman/pcd/Makefile b/drivers/soc/fsl/fman/pcd/Makefile
index b50aeac..e3ca6ff 100644
--- a/drivers/soc/fsl/fman/pcd/Makefile
+++ b/drivers/soc/fsl/fman/pcd/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_FSL_FMAN_PCD) += fsl_fman_pcd.o
-fsl_fman_pcd-objs := fman_kg.o fman_prs.o
+fsl_fman_pcd-objs := fman_kg.o fman_prs.o fm_pcd.o fm_prs.o
diff --git a/drivers/soc/fsl/fman/pcd/fm_pcd.c b/drivers/soc/fsl/fman/pcd/fm_pcd.c
new file mode 100644
index 0000000..df490ce
--- /dev/null
+++ b/drivers/soc/fsl/fman/pcd/fm_pcd.c
@@ -0,0 +1,428 @@
+/*
+ * 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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "net_ext.h"
+#include "fm_ext.h"
+#include "fm_pcd_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_muram_ext.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* static functions */
+
+static int check_fm_pcd_parameters(struct fm_pcd_t *p_fm_pcd)
+{
+ if (!p_fm_pcd->h_fm) {
+ pr_err("h_fm has to be initialized\n");
+ return -EDOM;
+ }
+ if (!p_fm_pcd->f_exception) {
+ pr_err("f_FmPcdExceptions has to be initialized\n");
+ return -EDOM;
+ }
+ if (p_fm_pcd->p_fm_pcd_drv_param->prs_max_parse_cycle_limit >
+ PRS_MAX_CYCLE_LIMIT) {
+ pr_err("prs_max_parse_cycle_limit has to be < 8191\n");
+ return -EDOM;
+ }
+ return 0;
+}
+
+static struct fm_pcd_lock_t *dequeue_lock_from_free_lst(struct fm_pcd_t
+ *p_fm_pcd)
+{
+ struct fm_pcd_lock_t *p_lock = NULL;
+ unsigned long int_flags;
+
+ spin_lock_irqsave(p_fm_pcd->spinlock, int_flags);
+ if (!list_empty(&p_fm_pcd->free_locks_lst)) {
+ p_lock = FM_PCD_LOCK_OBJ(p_fm_pcd->free_locks_lst.next);
+ list_del_init(&p_lock->node);
+ }
+ spin_unlock_irqrestore(p_fm_pcd->spinlock, int_flags);
+
+ return p_lock;
+}
+
+static void release_free_locks_lst(struct fm_pcd_t *p_fm_pcd)
+{
+ struct fm_pcd_lock_t *p_lock;
+
+ p_lock = dequeue_lock_from_free_lst(p_fm_pcd);
+ while (p_lock) {
+ kfree(p_lock->spinlock);
+ kfree(p_lock);
+ p_lock = dequeue_lock_from_free_lst(p_fm_pcd);
+ }
+}
+
+static struct fm_pcd_intg_t *set_pcd_intg_params(struct fm_pcd_t *p_fm_pcd)
+{
+ struct fm_pcd_intg_t *intg;
+
+ intg = kzalloc(sizeof(*intg), GFP_KERNEL);
+ if (!intg)
+ return NULL;
+
+ switch (p_fm_pcd->fm_rev_info.major_rev) {
+ case FM_IP_BLOCK_P2_P3_P5:
+ case FM_IP_BLOCK_P4:
+ intg->prs_sw_patches_size = 0x00000200;
+ break;
+
+ case FM_IP_BLOCK_P1:
+ intg->prs_sw_patches_size = 0x00000240;
+ break;
+
+ case FM_IP_BLOCK_B_T:
+ intg->prs_sw_patches_size = 0x00000240;
+ break;
+
+ default:
+ pr_err("Unsupported FMan version\n");
+ kfree(intg);
+ return NULL;
+ }
+
+ return intg;
+}
+
+/* Checks if p_fm_pcd driver parameters were initialized
+ * returns 0 if success else returns error
+ */
+static int is_init_done(struct fm_pcd_drv_param_t *p_fm_pcd_drv_param)
+{
+ if (p_fm_pcd_drv_param == NULL)
+ return 0;
+ return -ENOSYS;
+}
+
+/* Inter-module API routines */
+
+uint32_t fm_pcd_lock(void *h_fm_pcd)
+{
+ unsigned long int_flags;
+
+ spin_lock_irqsave(((struct fm_pcd_t *)h_fm_pcd)->spinlock, int_flags);
+ return int_flags;
+}
+
+void fm_pcd_unlock(void *h_fm_pcd, unsigned long int_flags)
+{
+ spin_unlock_irqrestore(((struct fm_pcd_t *)h_fm_pcd)->spinlock,
+ int_flags);
+}
+
+bool fm_pcd_lock_try_lock_all(void *h_fm_pcd)
+{
+ uint32_t int_flags;
+ struct list_head *p_pos, *p_saved_pos = NULL;
+
+ int_flags = fm_pcd_lock(h_fm_pcd);
+ list_for_each(p_pos, &((struct fm_pcd_t *)h_fm_pcd)->
+ acquired_locks_lst) {
+ struct fm_pcd_lock_t *p_lock = FM_PCD_LOCK_OBJ(p_pos);
+
+ if (!fm_pcd_lock_try_lock(p_lock)) {
+ p_saved_pos = p_pos;
+ break;
+ }
+ }
+ if (p_saved_pos) {
+ list_for_each(p_pos, &((struct fm_pcd_t *)h_fm_pcd)->
+ acquired_locks_lst) {
+ struct fm_pcd_lock_t *p_lock = FM_PCD_LOCK_OBJ(p_pos);
+
+ if (p_pos == p_saved_pos)
+ break;
+ fm_pcd_lock_unlock(p_lock);
+ }
+ }
+ fm_pcd_unlock(h_fm_pcd, int_flags);
+
+ /* Memory barrier */
+ mb();
+
+ if (p_saved_pos)
+ return false;
+
+ return true;
+}
+
+void fm_pcd_lock_unlock_all(void *h_fm_pcd)
+{
+ uint32_t int_flags;
+ struct list_head *p_pos;
+
+ int_flags = fm_pcd_lock(h_fm_pcd);
+ list_for_each(p_pos, &((struct fm_pcd_t *)h_fm_pcd)->
+ acquired_locks_lst) {
+ struct fm_pcd_lock_t *p_lock = FM_PCD_LOCK_OBJ(p_pos);
+
+ p_lock->flag = false;
+ }
+ fm_pcd_unlock(h_fm_pcd, int_flags);
+
+ /* Memory barrier */
+ mb();
+}
+
+/* End of inter-module routines */
+
+/* API Init unit functions */
+
+void *fm_pcd_config(struct fm_pcd_params_t *p_fm_pcd_params)
+{
+ struct fm_pcd_t *p_fm_pcd = NULL;
+
+ p_fm_pcd = kzalloc(sizeof(*p_fm_pcd), GFP_KERNEL);
+ if (!p_fm_pcd)
+ return NULL;
+
+ p_fm_pcd->p_fm_pcd_drv_param =
+ kzalloc(sizeof(*p_fm_pcd->p_fm_pcd_drv_param),
+ GFP_KERNEL);
+ if (!p_fm_pcd->p_fm_pcd_drv_param) {
+ kfree(p_fm_pcd);
+ pr_err("FM PCD Driver Param\n");
+ return NULL;
+ }
+
+ p_fm_pcd->h_fm = p_fm_pcd_params->h_fm;
+ fm_get_revision(p_fm_pcd->h_fm, &p_fm_pcd->fm_rev_info);
+ p_fm_pcd->pcd_intg = set_pcd_intg_params(p_fm_pcd);
+ if (!p_fm_pcd->pcd_intg) {
+ kfree(p_fm_pcd->p_fm_pcd_drv_param);
+ kfree(p_fm_pcd);
+ return NULL;
+ }
+
+ if (p_fm_pcd_params->prs_support) {
+ p_fm_pcd->p_fm_pcd_prs =
+ (struct fm_pcd_prs_t *)prs_config(p_fm_pcd, p_fm_pcd_params);
+
+ if (!p_fm_pcd->p_fm_pcd_prs) {
+ pr_err("FM PCD Parser\n");
+ fm_pcd_free(p_fm_pcd);
+ return NULL;
+ }
+ }
+
+ p_fm_pcd->spinlock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+ if (!p_fm_pcd->spinlock) {
+ fm_pcd_free(p_fm_pcd);
+ return NULL;
+ }
+
+ spin_lock_init(p_fm_pcd->spinlock);
+
+ INIT_LIST_HEAD(&p_fm_pcd->free_locks_lst);
+ INIT_LIST_HEAD(&p_fm_pcd->acquired_locks_lst);
+
+ p_fm_pcd->f_exception = p_fm_pcd_params->f_exception;
+ p_fm_pcd->h_app = p_fm_pcd_params->h_app;
+
+ return p_fm_pcd;
+}
+
+int fm_pcd_init(void *h_fm_pcd)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+ int err = 0;
+ int ret, ret_err;
+
+ ret = is_init_done(p_fm_pcd->p_fm_pcd_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ fm_get_revision(p_fm_pcd->h_fm, &p_fm_pcd->fm_rev_info);
+
+ ret_err = check_fm_pcd_parameters(p_fm_pcd);
+ if (ret_err)
+ return ret_err;
+
+ if (p_fm_pcd->p_fm_pcd_prs) {
+ err = prs_init(p_fm_pcd);
+ if (err)
+ return err;
+ }
+
+ kfree(p_fm_pcd->p_fm_pcd_drv_param);
+ p_fm_pcd->p_fm_pcd_drv_param = NULL;
+
+ fm_register_pcd(p_fm_pcd->h_fm, p_fm_pcd);
+
+ return 0;
+}
+
+int fm_pcd_free(void *h_fm_pcd)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+
+ if (p_fm_pcd->enabled)
+ fm_pcd_disable(p_fm_pcd);
+
+ kfree(p_fm_pcd->p_fm_pcd_drv_param);
+ p_fm_pcd->p_fm_pcd_drv_param = NULL;
+
+ kfree(p_fm_pcd->p_fm_pcd_prs);
+ p_fm_pcd->p_fm_pcd_prs = NULL;
+
+ fm_unregister_pcd(p_fm_pcd->h_fm);
+
+ release_free_locks_lst(p_fm_pcd);
+
+ kfree(p_fm_pcd->pcd_intg);
+
+ kfree(p_fm_pcd->spinlock);
+
+ kfree(p_fm_pcd);
+
+ return 0;
+}
+
+int fm_pcd_enable(void *h_fm_pcd)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+
+ if (p_fm_pcd->enabled)
+ return 0;
+
+ if (p_fm_pcd->p_fm_pcd_prs)
+ prs_enable(p_fm_pcd);
+
+ p_fm_pcd->enabled = true;
+
+ return 0;
+}
+
+int fm_pcd_disable(void *h_fm_pcd)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+
+ if (!p_fm_pcd->enabled)
+ return 0;
+
+ if (p_fm_pcd->p_fm_pcd_prs)
+ prs_disable(p_fm_pcd);
+
+ p_fm_pcd->enabled = false;
+
+ return 0;
+}
+
+int fm_pcd_set_exception(void *h_fm_pcd,
+ enum fm_pcd_exceptions exception,
+ bool enable)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+ uint32_t bit_mask = 0, tmp_reg;
+ int ret;
+
+ ret = is_init_done(p_fm_pcd->p_fm_pcd_drv_param);
+ if (ret)
+ return ret;
+
+ GET_FM_PCD_EXCEPTION_FLAG(bit_mask, exception);
+
+ if (bit_mask) {
+ if (enable)
+ p_fm_pcd->exceptions |= bit_mask;
+ else
+ p_fm_pcd->exceptions &= ~bit_mask;
+
+ switch (exception) {
+ case (FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ case (FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ if (!p_fm_pcd->p_fm_pcd_prs) {
+ pr_warn("Parser is not working\n");
+ return -ENOSYS;
+ }
+ break;
+ default:
+ pr_warn("Unsupported exception\n");
+ return -ENOSYS;
+ }
+
+ switch (exception) {
+ case (FM_PCD_PRS_EXCEPTION_DOUBLE_ECC):
+ tmp_reg =
+ GET_UINT32(p_fm_pcd->p_fm_pcd_prs->
+ p_fm_pcd_prs_regs->
+ fmpr_perer);
+ if (enable)
+ tmp_reg |= FM_PCD_PRS_DOUBLE_ECC;
+ else
+ tmp_reg &= ~FM_PCD_PRS_DOUBLE_ECC;
+ WRITE_UINT32(p_fm_pcd->p_fm_pcd_prs->p_fm_pcd_prs_regs->
+ fmpr_perer, tmp_reg);
+ break;
+ case (FM_PCD_PRS_EXCEPTION_SINGLE_ECC):
+ tmp_reg =
+ GET_UINT32(p_fm_pcd->p_fm_pcd_prs->
+ p_fm_pcd_prs_regs->
+ fmpr_pever);
+ if (enable)
+ tmp_reg |= FM_PCD_PRS_SINGLE_ECC;
+ else
+ tmp_reg &= ~FM_PCD_PRS_SINGLE_ECC;
+ WRITE_UINT32(p_fm_pcd->p_fm_pcd_prs->p_fm_pcd_prs_regs->
+ fmpr_pever, tmp_reg);
+ break;
+ default:
+ pr_warn("Unsupported exception\n");
+ return -ENOSYS;
+ }
+ /* for ECC exceptions driver automatically enables
+ * ECC mechanism, if disabled. Driver may disable them
+ * automatically, depending on driver's status
+ */
+ if ((enable) &&
+ ((exception == FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) |
+ (exception == FM_PCD_PRS_EXCEPTION_SINGLE_ECC)))
+ _fm_enable_rams_ecc(p_fm_pcd->h_fm);
+ if ((!enable) &&
+ ((exception == FM_PCD_PRS_EXCEPTION_DOUBLE_ECC) |
+ (exception == FM_PCD_PRS_EXCEPTION_SINGLE_ECC)))
+ _fm_disable_rams_ecc(p_fm_pcd->h_fm);
+ } else {
+ pr_err("Undefined exceptioni\n");
+ return -EDOM;
+ }
+ return 0;
+}
diff --git a/drivers/soc/fsl/fman/pcd/fm_pcd.h b/drivers/soc/fsl/fman/pcd/fm_pcd.h
new file mode 100644
index 0000000..7a1926a
--- /dev/null
+++ b/drivers/soc/fsl/fman/pcd/fm_pcd.h
@@ -0,0 +1,145 @@
+/*
+ * 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.
+ */
+
+#ifndef __FM_PCD_H
+#define __FM_PCD_H
+
+#include "service.h"
+#include "fm_pcd_ext.h"
+#include "fm_common.h"
+#include "fsl_fman_prs.h"
+
+/* Network defines */
+
+#define UDP_HEADER_SIZE 8
+
+#define ESP_SPI_OFFSET 0
+#define ESP_SPI_SIZE 4
+#define ESP_SEQ_NUM_OFFSET ESP_SPI_SIZE
+#define ESP_SEQ_NUM_SIZE 4
+
+/* General defines */
+
+#define ILLEGAL_CLS_PLAN 0xff
+
+#define FM_PCD_MAX_NUM_OF_ALIAS_HDRS 3
+
+/* Error defines */
+
+#define GET_FM_PCD_EXCEPTION_FLAG(bit_mask, exception) do {\
+switch (exception) {\
+case FM_PCD_PRS_EXCEPTION_DOUBLE_ECC:\
+ bit_mask = FM_PCD_EX_PRS_DOUBLE_ECC;\
+ break;\
+case FM_PCD_PRS_EXCEPTION_SINGLE_ECC:\
+ bit_mask = FM_PCD_EX_PRS_SINGLE_ECC;\
+ break;\
+default:\
+ bit_mask = 0; break; } \
+} while (0)
+
+/* Driver's internal structures */
+
+struct fm_pcd_prs_t {
+ uint32_t *p_sw_prs_code;
+ uint32_t *p_curr_sw_prs;
+ uint8_t curr_label;
+ struct fman_prs_regs __iomem *p_fm_pcd_prs_regs;
+ struct fm_pcd_prs_label_params_t labels_table[FM_PCD_PRS_NUM_OF_LABELS];
+ uint32_t fm_pcd_prs_port_id_statistics;
+};
+
+struct fm_pcd_drv_param_t {
+ struct fman_prs_cfg dflt_cfg;
+ uint16_t prs_max_parse_cycle_limit;
+};
+
+struct fm_pcd_intg_t {
+ uint32_t prs_sw_patches_size;
+};
+
+struct fm_pcd_t {
+ void *h_fm;
+ struct fm_revision_info_t fm_rev_info;
+
+ spinlock_t *spinlock;
+ struct list_head free_locks_lst;
+ struct list_head acquired_locks_lst;
+
+ bool enabled;
+ char fm_pcd_module_name[MODULE_NAME_SIZE];
+ struct fm_pcd_prs_t *p_fm_pcd_prs;
+
+ uint32_t exceptions;
+ fm_pcd_exception_cb *f_exception;
+ void *h_app;
+ uintptr_t ipv6_frame_id_addr;
+
+ struct fm_pcd_drv_param_t *p_fm_pcd_drv_param;
+
+ struct fm_pcd_intg_t *pcd_intg;
+
+};
+
+/* PCD internal routines */
+
+/* only for SINGLE partittion */
+
+void *prs_config(struct fm_pcd_t *p_fm_pcd, struct fm_pcd_params_t
+ *p_fm_pcd_params);
+int prs_init(struct fm_pcd_t *p_fm_pcd);
+void prs_enable(struct fm_pcd_t *p_fm_pcd);
+void prs_disable(struct fm_pcd_t *p_fm_pcd);
+void prs_free(struct fm_pcd_t *p_fm_pcd);
+int prs_include_port_in_statistics(struct fm_pcd_t *p_fm_pcd,
+ uint8_t port_id,
+ bool include);
+
+static inline bool fm_pcd_lock_try_lock(struct fm_pcd_lock_t *p_lock)
+{
+ unsigned long int_flags;
+
+ spin_lock_irqsave(p_lock->spinlock, int_flags);
+ if (p_lock->flag) {
+ spin_unlock_irqrestore(p_lock->spinlock, int_flags);
+ return false;
+ }
+ p_lock->flag = true;
+ spin_unlock_irqrestore(p_lock->spinlock, int_flags);
+ return true;
+}
+
+static inline void fm_pcd_lock_unlock(struct fm_pcd_lock_t *p_lock)
+{
+ p_lock->flag = false;
+}
+
+#endif /* __FM_PCD_H */
diff --git a/drivers/soc/fsl/fman/pcd/fm_prs.c b/drivers/soc/fsl/fman/pcd/fm_prs.c
new file mode 100644
index 0000000..5691ba5
--- /dev/null
+++ b/drivers/soc/fsl/fman/pcd/fm_prs.c
@@ -0,0 +1,276 @@
+/*
+ * 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.
+ */
+
+#include "service.h"
+#include "net_ext.h"
+
+#include "fm_common.h"
+#include "fm_pcd.h"
+#include "fm_prs.h"
+#include "fsl_fman_prs.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+static void pcd_prs_error_exception(void *h_fm_pcd)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+ uint32_t event, ev_mask;
+ struct fman_prs_regs __iomem *prs_regs =
+ (struct fman_prs_regs __iomem *)
+ p_fm_pcd->p_fm_pcd_prs->p_fm_pcd_prs_regs;
+
+ ev_mask = fman_prs_get_err_ev_mask(prs_regs);
+
+ event = fman_prs_get_err_event(prs_regs, ev_mask);
+
+ fman_prs_ack_err_event(prs_regs, event);
+
+ pr_debug("parser error - 0x%08x\n", event);
+
+ if (event&FM_PCD_PRS_DOUBLE_ECC)
+ p_fm_pcd->f_exception(p_fm_pcd->h_app,
+ FM_PCD_PRS_EXCEPTION_DOUBLE_ECC);
+}
+
+/* Checks if p_dtsec driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct fm_pcd_drv_param_t *p_fm_pcd_drv_parameters)
+{
+ if (!p_fm_pcd_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+static void pcd_prs_exception(void *h_fm_pcd)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+ uint32_t event, ev_mask;
+ struct fman_prs_regs __iomem *prs_regs =
+ (struct fman_prs_regs __iomem *)
+ p_fm_pcd->p_fm_pcd_prs->p_fm_pcd_prs_regs;
+
+ ev_mask = fman_prs_get_expt_ev_mask(prs_regs);
+ event = fman_prs_get_expt_event(prs_regs, ev_mask);
+
+ ASSERT(event&FM_PCD_PRS_SINGLE_ECC);
+
+ pr_debug("parser event - 0x%08x\n", event);
+
+ fman_prs_ack_expt_event(prs_regs, event);
+
+ p_fm_pcd->f_exception(p_fm_pcd->h_app, FM_PCD_PRS_EXCEPTION_SINGLE_ECC);
+}
+
+void *prs_config(struct fm_pcd_t __maybe_unused *p_fm_pcd,
+ struct fm_pcd_params_t __maybe_unused *p_fm_pcd_params)
+{
+ struct fm_pcd_prs_t *p_fm_pcd_prs;
+ uintptr_t base_addr;
+
+ p_fm_pcd_prs = kzalloc(sizeof(*p_fm_pcd_prs), GFP_KERNEL);
+ if (!p_fm_pcd_prs)
+ return NULL;
+ fman_prs_defconfig(&p_fm_pcd->p_fm_pcd_drv_param->dflt_cfg);
+
+ base_addr = fm_get_pcd_prs_base_addr(p_fm_pcd_params->h_fm);
+ p_fm_pcd_prs->p_sw_prs_code = (uint32_t *)UINT_TO_PTR(base_addr);
+ p_fm_pcd_prs->p_fm_pcd_prs_regs =
+ (struct fman_prs_regs __iomem *)UINT_TO_PTR(base_addr +
+ PRS_REGS_OFFSET);
+
+ p_fm_pcd_prs->fm_pcd_prs_port_id_statistics =
+ p_fm_pcd->p_fm_pcd_drv_param->dflt_cfg.port_id_stat;
+ p_fm_pcd->p_fm_pcd_drv_param->prs_max_parse_cycle_limit =
+ p_fm_pcd->p_fm_pcd_drv_param->dflt_cfg.max_prs_cyc_lim;
+ p_fm_pcd->exceptions |=
+ p_fm_pcd->p_fm_pcd_drv_param->dflt_cfg.prs_exceptions;
+
+ return p_fm_pcd_prs;
+}
+
+int prs_init(struct fm_pcd_t *p_fm_pcd)
+{
+ struct fm_pcd_drv_param_t *p_param = p_fm_pcd->p_fm_pcd_drv_param;
+ uint32_t *p_tmp_code;
+ uint32_t *p_load_target =
+ (uint32_t *)PTR_MOVE(p_fm_pcd->p_fm_pcd_prs->p_sw_prs_code,
+ FM_PCD_SW_PRS_SIZE -
+ p_fm_pcd->pcd_intg->prs_sw_patches_size);
+ struct fman_prs_regs __iomem *prs_regs =
+ (struct fman_prs_regs __iomem *)
+ p_fm_pcd->p_fm_pcd_prs->p_fm_pcd_prs_regs;
+ uint32_t i;
+ uint32_t size_of_sw_prs_code;
+
+ if (p_fm_pcd->fm_rev_info.major_rev >= 6)
+ size_of_sw_prs_code =
+ sizeof(sw_prs_ip_frag_patch_ver_106_3_13);
+ else
+ size_of_sw_prs_code =
+ sizeof(sw_prs_ip_frag_patch_ver_106_1_9);
+
+ ASSERT((size_of_sw_prs_code) <=
+ (p_fm_pcd->pcd_intg->prs_sw_patches_size -
+ FM_PCD_PRS_SW_TAIL_SIZE));
+
+ p_tmp_code = kzalloc(ROUND_UP(size_of_sw_prs_code, 4), GFP_KERNEL);
+ if (!p_tmp_code)
+ return -ENOMEM;
+
+ if (p_fm_pcd->fm_rev_info.major_rev >= 6)
+ memcpy((uint8_t *)p_tmp_code,
+ (uint8_t *)sw_prs_ip_frag_patch_ver_106_3_13,
+ size_of_sw_prs_code);
+ else
+ memcpy((uint8_t *)p_tmp_code,
+ (uint8_t *)sw_prs_ip_frag_patch_ver_106_1_9,
+ size_of_sw_prs_code);
+
+ fman_prs_init(prs_regs, &p_param->dflt_cfg);
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ fm_register_intr(p_fm_pcd->h_fm, FM_MOD_PRS, 0, FM_INTR_TYPE_ERR,
+ pcd_prs_error_exception, p_fm_pcd);
+
+ /* register even if no interrupts enabled, to allow future enablement */
+ fm_register_intr(p_fm_pcd->h_fm, FM_MOD_PRS, 0, FM_INTR_TYPE_NORMAL,
+ pcd_prs_exception, p_fm_pcd);
+
+ if (p_fm_pcd->exceptions&FM_PCD_EX_PRS_SINGLE_ECC)
+ _fm_enable_rams_ecc(p_fm_pcd->h_fm);
+
+ if (p_fm_pcd->exceptions&FM_PCD_EX_PRS_DOUBLE_ECC)
+ _fm_enable_rams_ecc(p_fm_pcd->h_fm);
+
+ for (i = 0; i < DIV_CEIL(size_of_sw_prs_code, 4); i++)
+ WRITE_UINT32(p_load_target[i], p_tmp_code[i]);
+
+ kfree(p_tmp_code);
+
+ return 0;
+}
+
+void prs_free(struct fm_pcd_t *p_fm_pcd)
+{
+ fm_unregister_intr(p_fm_pcd->h_fm, FM_MOD_PRS, 0, FM_INTR_TYPE_ERR);
+ /* register even if no interrupts enabled, to allow future enablement */
+ fm_unregister_intr(p_fm_pcd->h_fm, FM_MOD_PRS, 0, FM_INTR_TYPE_NORMAL);
+}
+
+void prs_enable(struct fm_pcd_t *p_fm_pcd)
+{
+ struct fman_prs_regs __iomem *prs_regs =
+ (struct fman_prs_regs __iomem *)
+ p_fm_pcd->p_fm_pcd_prs->p_fm_pcd_prs_regs;
+
+ fman_prs_enable(prs_regs);
+}
+
+void prs_disable(struct fm_pcd_t *p_fm_pcd)
+{
+ struct fman_prs_regs __iomem *prs_regs =
+ (struct fman_prs_regs __iomem *)
+ p_fm_pcd->p_fm_pcd_prs->p_fm_pcd_prs_regs;
+
+ fman_prs_disable(prs_regs);
+}
+
+int prs_include_port_in_statistics(struct fm_pcd_t *p_fm_pcd,
+ uint8_t port_id,
+ bool include)
+{
+ struct fman_prs_regs __iomem *prs_regs;
+ uint32_t bit_mask = 0;
+ uint8_t prs_port_id;
+
+ if ((port_id < 1 || port_id > 16))
+ return -ENOSYS;
+
+ prs_regs = (struct fman_prs_regs __iomem *)p_fm_pcd->p_fm_pcd_prs->
+ p_fm_pcd_prs_regs;
+
+ GET_FM_PCD_PRS_PORT_ID(prs_port_id, port_id);
+ GET_FM_PCD_INDEX_FLAG(bit_mask, prs_port_id);
+
+ if (include)
+ p_fm_pcd->p_fm_pcd_prs->fm_pcd_prs_port_id_statistics |=
+ bit_mask;
+ else
+ p_fm_pcd->p_fm_pcd_prs->fm_pcd_prs_port_id_statistics &=
+ ~bit_mask;
+
+ fman_prs_set_stst_port_msk(prs_regs,
+ p_fm_pcd->p_fm_pcd_prs->
+ fm_pcd_prs_port_id_statistics);
+
+ return 0;
+}
+
+int fm_pcd_prs_include_port_in_statistics(void *h_fm_pcd,
+ uint8_t port_id,
+ bool include)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+
+ if ((port_id < 1 || port_id > 16))
+ return -ENOSYS;
+
+ return prs_include_port_in_statistics(p_fm_pcd, port_id,
+ include);
+}
+
+uint32_t fm_pcd_get_sw_prs_offset(void *h_fm_pcd, enum net_header_type hdr,
+ uint8_t index_per_hdr)
+{
+ struct fm_pcd_t *p_fm_pcd = (struct fm_pcd_t *)h_fm_pcd;
+ struct fm_pcd_prs_label_params_t *p_label;
+ int i, ret;
+
+ ret = is_init_done(p_fm_pcd->p_fm_pcd_drv_param);
+ if (ret)
+ return 0;
+
+ ASSERT(p_fm_pcd->p_fm_pcd_prs->curr_label <
+ FM_PCD_PRS_NUM_OF_LABELS);
+
+ for (i = 0; i < p_fm_pcd->p_fm_pcd_prs->curr_label; i++) {
+ p_label = &p_fm_pcd->p_fm_pcd_prs->labels_table[i];
+
+ if ((hdr == p_label->hdr) &&
+ (index_per_hdr == p_label->index_per_hdr))
+ return p_label->instruction_offset;
+ }
+
+ pr_err("Sw Parser attachment Not found\n");
+ return (uint32_t)ILLEGAL_BASE;
+}
diff --git a/drivers/soc/fsl/fman/pcd/fm_prs.h b/drivers/soc/fsl/fman/pcd/fm_prs.h
new file mode 100644
index 0000000..f3cbd2f
--- /dev/null
+++ b/drivers/soc/fsl/fman/pcd/fm_prs.h
@@ -0,0 +1,163 @@
+/*
+ * 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.
+ */
+
+#ifndef __FM_PRS_H
+#define __FM_PRS_H
+
+#include "service.h"
+
+/* SW parser IP_FRAG patch */
+/* version: 106.1.9 */
+static uint8_t sw_prs_ip_frag_patch_ver_106_1_9[] = {
+ 0x31, 0x52, 0x00, 0xDA, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x43, 0x0A, 0x00, 0x00, 0x00, 0x01, 0x1B, 0xFE,
+ 0x00, 0x00, 0x99, 0x00, 0x53, 0x13, 0x00, 0x00, 0x00, 0x00,
+ 0x9F, 0x98, 0x53, 0x13, 0x00, 0x00, 0x1B, 0x23, 0x33, 0xF1,
+ 0x00, 0xF9, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x7F, 0x00, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01,
+ 0x32, 0xC1, 0x32, 0xF0, 0x00, 0x4A, 0x00, 0x80, 0x1F, 0xFF,
+ 0x00, 0x01, 0x1B, 0xFE, 0x31, 0x52, 0x00, 0xDA, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x2F, 0x00, 0x00,
+ 0x00, 0x01, 0x1B, 0xFE, 0x31, 0x52, 0x00, 0xDA, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0x95, 0x00, 0x00,
+ 0x00, 0x00, 0x9B, 0x8F, 0x2F, 0x0F, 0x32, 0xC1, 0x00, 0x55,
+ 0x00, 0x28, 0x28, 0x43, 0x30, 0x7E, 0x43, 0x45, 0x00, 0x00,
+ 0x30, 0x7E, 0x43, 0x45, 0x00, 0x3C, 0x1B, 0x5D, 0x32, 0x11,
+ 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x81, 0x00, 0x00, 0x83, 0x8F,
+ 0x2F, 0x0F, 0x06, 0x00, 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F,
+ 0x00, 0x55, 0x00, 0x01, 0x00, 0x81, 0x32, 0x11, 0x00, 0x00,
+ 0x83, 0x8E, 0x00, 0x50, 0x00, 0x01, 0x01, 0x04, 0x00, 0x4D,
+ 0x28, 0x43, 0x06, 0x00, 0x1B, 0x3E, 0x30, 0x7E, 0x53, 0x79,
+ 0x00, 0x2B, 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x81,
+ 0x00, 0x00, 0x87, 0x8F, 0x28, 0x23, 0x06, 0x00, 0x32, 0x11,
+ 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x55, 0x00, 0x01, 0x00, 0x81,
+ 0x32, 0x11, 0x00, 0x00, 0x83, 0x8E, 0x00, 0x50, 0x00, 0x01,
+ 0x01, 0x04, 0x00, 0x4D, 0x28, 0x43, 0x06, 0x00, 0x00, 0x01,
+ 0x1B, 0xFE, 0x00, 0x00, 0x9B, 0x8E, 0x53, 0x90, 0x00, 0x00,
+ 0x06, 0x29, 0x00, 0x00, 0x83, 0x8F, 0x28, 0x23, 0x06, 0x00,
+ 0x06, 0x29, 0x32, 0xC1, 0x00, 0x55, 0x00, 0x28, 0x00, 0x00,
+ 0x83, 0x8E, 0x00, 0x50, 0x00, 0x01, 0x01, 0x04, 0x00, 0x4D,
+ 0x28, 0x43, 0x06, 0x00, 0x00, 0x01, 0x1B, 0xFE, 0x32, 0xC1,
+ 0x00, 0x55, 0x00, 0x28, 0x28, 0x43, 0x1B, 0xCF, 0x00, 0x00,
+ 0x9B, 0x8F, 0x2F, 0x0F, 0x32, 0xC1, 0x00, 0x55, 0x00, 0x28,
+ 0x28, 0x43, 0x30, 0x7E, 0x43, 0xBF, 0x00, 0x2C, 0x32, 0x11,
+ 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x81, 0x00, 0x00, 0x87, 0x8F,
+ 0x28, 0x23, 0x06, 0x00, 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F,
+ 0x00, 0x81, 0x00, 0x00, 0x83, 0x8F, 0x2F, 0x0F, 0x06, 0x00,
+ 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x55, 0x00, 0x01,
+ 0x00, 0x81, 0x32, 0x11, 0x00, 0x00, 0x83, 0x8E, 0x00, 0x50,
+ 0x00, 0x01, 0x01, 0x04, 0x00, 0x4D, 0x28, 0x43, 0x06, 0x00,
+ 0x1B, 0x9C, 0x33, 0xF1, 0x00, 0xF9, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x28, 0x7F, 0x00, 0x03, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01, 0x32, 0xC1, 0x32, 0xF0, 0x00, 0x4A,
+ 0x00, 0x80, 0x1F, 0xFF, 0x00, 0x01, 0x1B, 0xFE};
+
+/* version: 106.3.13 */
+static uint8_t sw_prs_ip_frag_patch_ver_106_3_13[] = {
+ 0x31, 0x52, 0x00, 0xDA, 0x0E, 0x4F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x52, 0xF6, 0x08, 0x4B, 0x31, 0x53, 0x00, 0xFB,
+ 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x2B,
+ 0x33, 0xF1, 0x00, 0xFB, 0x00, 0xDF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x28, 0x7F, 0x31, 0x52, 0x00, 0xDA, 0x0A, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x1B, 0xFE, 0x00, 0x00, 0x99, 0x00, 0x53, 0x09,
+ 0x00, 0x00, 0x00, 0x00, 0x9F, 0x98, 0x53, 0x09, 0x00, 0x00,
+ 0x1B, 0x24, 0x09, 0x5F, 0x00, 0x20, 0x00, 0x00, 0x09, 0x4F,
+ 0x00, 0x20, 0x00, 0x00, 0x34, 0xB7, 0x00, 0xF9, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x97, 0x31, 0xB3,
+ 0x29, 0x8F, 0x33, 0xF1, 0x00, 0xF9, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x28, 0x7F, 0x00, 0x03, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01, 0x1B, 0xFE, 0x00, 0x01, 0x1B, 0xFE,
+ 0x31, 0x52, 0x00, 0xDA, 0x0E, 0x4F, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x53, 0x3C, 0x04, 0x4B, 0x31, 0x53, 0x00, 0xFB,
+ 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x29, 0x2B,
+ 0x33, 0xF1, 0x00, 0xFB, 0x00, 0xDF, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x28, 0x7F, 0x31, 0x52, 0x00, 0xDA, 0x06, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43, 0x46, 0x00, 0x00,
+ 0x00, 0x01, 0x1B, 0xFE, 0x31, 0x52, 0x00, 0xDA, 0x00, 0x40,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x53, 0xAC, 0x00, 0x00,
+ 0x00, 0x00, 0x9B, 0x8F, 0x2F, 0x0F, 0x32, 0xC1, 0x00, 0x55,
+ 0x00, 0x28, 0x28, 0x43, 0x30, 0x7E, 0x43, 0x5C, 0x00, 0x00,
+ 0x30, 0x7E, 0x43, 0x5C, 0x00, 0x3C, 0x1B, 0x74, 0x32, 0x11,
+ 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x81, 0x00, 0x00, 0x83, 0x8F,
+ 0x2F, 0x0F, 0x06, 0x00, 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F,
+ 0x00, 0x55, 0x00, 0x01, 0x00, 0x81, 0x32, 0x11, 0x00, 0x00,
+ 0x83, 0x8E, 0x00, 0x50, 0x00, 0x01, 0x01, 0x04, 0x00, 0x4D,
+ 0x28, 0x43, 0x06, 0x00, 0x1B, 0x55, 0x30, 0x7E, 0x53, 0x90,
+ 0x00, 0x2B, 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x81,
+ 0x00, 0x00, 0x87, 0x8F, 0x28, 0x23, 0x06, 0x00, 0x32, 0x11,
+ 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x55, 0x00, 0x01, 0x00, 0x81,
+ 0x32, 0x11, 0x00, 0x00, 0x83, 0x8E, 0x00, 0x50, 0x00, 0x01,
+ 0x01, 0x04, 0x00, 0x4D, 0x28, 0x43, 0x06, 0x00, 0x00, 0x01,
+ 0x1B, 0xFE, 0x00, 0x00, 0x9B, 0x8E, 0x53, 0xA7, 0x00, 0x00,
+ 0x06, 0x29, 0x00, 0x00, 0x83, 0x8F, 0x28, 0x23, 0x06, 0x00,
+ 0x06, 0x29, 0x32, 0xC1, 0x00, 0x55, 0x00, 0x28, 0x00, 0x00,
+ 0x83, 0x8E, 0x00, 0x50, 0x00, 0x01, 0x01, 0x04, 0x00, 0x4D,
+ 0x28, 0x43, 0x06, 0x00, 0x00, 0x01, 0x1B, 0xFE, 0x32, 0xC1,
+ 0x00, 0x55, 0x00, 0x28, 0x28, 0x43, 0x1B, 0xF1, 0x00, 0x00,
+ 0x9B, 0x8F, 0x2F, 0x0F, 0x32, 0xC1, 0x00, 0x55, 0x00, 0x28,
+ 0x28, 0x43, 0x30, 0x7E, 0x43, 0xD6, 0x00, 0x2C, 0x32, 0x11,
+ 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x81, 0x00, 0x00, 0x87, 0x8F,
+ 0x28, 0x23, 0x06, 0x00, 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F,
+ 0x00, 0x81, 0x00, 0x00, 0x83, 0x8F, 0x2F, 0x0F, 0x06, 0x00,
+ 0x32, 0x11, 0x32, 0xC0, 0x00, 0x4F, 0x00, 0x55, 0x00, 0x01,
+ 0x00, 0x81, 0x32, 0x11, 0x00, 0x00, 0x83, 0x8E, 0x00, 0x50,
+ 0x00, 0x01, 0x01, 0x04, 0x00, 0x4D, 0x28, 0x43, 0x06, 0x00,
+ 0x1B, 0xB3, 0x09, 0x5F, 0x00, 0x20, 0x00, 0x00, 0x09, 0x4F,
+ 0x00, 0x20, 0x00, 0x00, 0x34, 0xB7, 0x00, 0xF9, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2B, 0x97, 0x31, 0xB3,
+ 0x29, 0x8F, 0x33, 0xF1, 0x00, 0xF9, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x28, 0x7F, 0x00, 0x03, 0x00, 0x02,
+ 0x00, 0x00, 0x00, 0x01, 0x1B, 0xFE, 0x00, 0x01, 0x1B, 0xFE};
+
+/* Parser defines */
+
+/* Number of bytes that must be cleared atthe end of the SW parser area */
+#define FM_PCD_PRS_SW_TAIL_SIZE 4
+
+/* masks */
+#define PRS_ERR_CAP 0x80000000
+#define PRS_ERR_TYPE_DOUBLE 0x40000000
+#define PRS_ERR_SINGLE_ECC_CNT_MASK 0x00FF0000
+#define PRS_ERR_ADDR_MASK 0x000001FF
+
+/* others */
+#define PRS_MAX_CYCLE_LIMIT 8191
+#define PRS_SW_DATA 0x00000800
+#define PRS_REGS_OFFSET 0x00000840
+
+#define GET_FM_PCD_PRS_PORT_ID(prs_port_id, port_id) \
+(prs_port_id = (uint8_t)(port_id&0x0f))
+
+#define GET_FM_PCD_INDEX_FLAG(bit_mask, prs_port_id) \
+(bit_mask = 0x80000000>>prs_port_id)
+
+#endif /* __FM_PRS_H */
--
1.7.9.5
More information about the Linuxppc-dev
mailing list