fsl/fman: Add FMan SP support
authorIgal Liberman <igal.liberman@freescale.com>
Mon, 21 Dec 2015 00:21:28 +0000 (02:21 +0200)
committerDavid S. Miller <davem@davemloft.net>
Mon, 28 Dec 2015 01:51:40 +0000 (20:51 -0500)
The Storage Profiles contain parameters that are used
by the FMan for frame reception and transmission.

Signed-off-by: Igal Liberman <igal.liberman@freescale.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/fman/Makefile
drivers/net/ethernet/freescale/fman/fman_sp.c [new file with mode: 0644]
drivers/net/ethernet/freescale/fman/fman_sp.h [new file with mode: 0644]

index 43360d701e1d5d8f1d87afffb0c2c696c7cb4269..5141532bbeb38f259abd68dbf3ff243f793a1afc 100644 (file)
@@ -2,5 +2,5 @@ subdir-ccflags-y +=  -I$(srctree)/drivers/net/ethernet/freescale/fman
 
 obj-y          += fsl_fman.o fsl_fman_mac.o
 
-fsl_fman-objs  := fman_muram.o fman.o
+fsl_fman-objs  := fman_muram.o fman.o fman_sp.o
 fsl_fman_mac-objs := fman_dtsec.o fman_memac.o fman_tgec.o
diff --git a/drivers/net/ethernet/freescale/fman/fman_sp.c b/drivers/net/ethernet/freescale/fman/fman_sp.c
new file mode 100644 (file)
index 0000000..f9e7aa3
--- /dev/null
@@ -0,0 +1,166 @@
+/*
+ * 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 "fman_sp.h"
+#include "fman.h"
+
+void fman_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fman_ext_pools
+                                                    *fm_ext_pools,
+                                                    u8 *ordered_array,
+                                                    u16 *sizes_array)
+{
+       u16 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 < fm_ext_pools->num_of_pools_used; i++) {
+               /* get pool size */
+               buf_size = fm_ext_pools->ext_buf_pool[i].size;
+
+               /* keep sizes in an array according to poolId
+                * for direct access
+                */
+               sizes_array[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] =
+                                   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] =
+                                           fm_ext_pools->ext_buf_pool[i].id;
+                                       break;
+                               }
+                       }
+               }
+       }
+}
+
+int fman_sp_build_buffer_struct(struct fman_sp_int_context_data_copy *
+                               int_context_data_copy,
+                               struct fman_buffer_prefix_content *
+                               buffer_prefix_content,
+                               struct fman_sp_buf_margins *buf_margins,
+                               struct fman_sp_buffer_offsets *buffer_offsets,
+                               u8 *internal_buf_offset)
+{
+       u32 tmp;
+
+       /* Align start of internal context data to 16 byte */
+       int_context_data_copy->ext_buf_offset = (u16)
+               ((buffer_prefix_content->priv_data_size & (OFFSET_UNITS - 1)) ?
+               ((buffer_prefix_content->priv_data_size + OFFSET_UNITS) &
+                       ~(u16)(OFFSET_UNITS - 1)) :
+               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. */
+       buffer_offsets->prs_result_offset = (u32)ILLEGAL_BASE;
+       buffer_offsets->time_stamp_offset = (u32)ILLEGAL_BASE;
+       buffer_offsets->hash_result_offset = (u32)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 case covers the options under 1 */
+       /* Copy size must be in 16-byte granularity. */
+       int_context_data_copy->size =
+           (u16)((buffer_prefix_content->pass_prs_result ? 32 : 0) +
+                 ((buffer_prefix_content->pass_time_stamp ||
+                 buffer_prefix_content->pass_hash_result) ? 16 : 0));
+
+       /* Align start of internal context data to 16 byte */
+       int_context_data_copy->int_context_offset =
+           (u8)(buffer_prefix_content->pass_prs_result ? 32 :
+                ((buffer_prefix_content->pass_time_stamp ||
+                buffer_prefix_content->pass_hash_result) ? 64 : 0));
+
+       if (buffer_prefix_content->pass_prs_result)
+               buffer_offsets->prs_result_offset =
+                   int_context_data_copy->ext_buf_offset;
+       if (buffer_prefix_content->pass_time_stamp)
+               buffer_offsets->time_stamp_offset =
+                   buffer_prefix_content->pass_prs_result ?
+                   (int_context_data_copy->ext_buf_offset +
+                       sizeof(struct fman_prs_result)) :
+                   int_context_data_copy->ext_buf_offset;
+       if (buffer_prefix_content->pass_hash_result)
+               /* If PR is not requested, whether TS is
+                * requested or not, IC will be copied from TS
+                        */
+               buffer_offsets->hash_result_offset =
+               buffer_prefix_content->pass_prs_result ?
+                       (int_context_data_copy->ext_buf_offset +
+                               sizeof(struct fman_prs_result) + 8) :
+                       int_context_data_copy->ext_buf_offset + 8;
+
+       if (int_context_data_copy->size)
+               buf_margins->start_margins =
+                   (u16)(int_context_data_copy->ext_buf_offset +
+                         int_context_data_copy->size);
+       else
+               /* No Internal Context passing, STartMargin is
+                * immediately after private_info
+                */
+               buf_margins->start_margins =
+                   buffer_prefix_content->priv_data_size;
+
+       /* align data start */
+       tmp = (u32)(buf_margins->start_margins %
+                   buffer_prefix_content->data_align);
+       if (tmp)
+               buf_margins->start_margins +=
+                   (buffer_prefix_content->data_align - tmp);
+       buffer_offsets->data_offset = buf_margins->start_margins;
+
+       return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/fman_sp.h b/drivers/net/ethernet/freescale/fman/fman_sp.h
new file mode 100644 (file)
index 0000000..820b7f6
--- /dev/null
@@ -0,0 +1,103 @@
+/*
+ * 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_SP_H
+#define __FM_SP_H
+
+#include "fman.h"
+#include <linux/types.h>
+
+#define ILLEGAL_BASE    (~0)
+
+/* defaults */
+#define DFLT_FM_SP_BUFFER_PREFIX_CONTEXT_DATA_ALIGN    64
+
+/* Registers bit fields */
+#define FMAN_SP_EXT_BUF_POOL_EN_COUNTER                0x40000000
+#define FMAN_SP_EXT_BUF_POOL_VALID                     0x80000000
+#define FMAN_SP_EXT_BUF_POOL_BACKUP                    0x20000000
+#define FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE                0x00100000
+#define FMAN_SP_SG_DISABLE                             0x80000000
+
+/* shifts */
+#define FMAN_SP_EXT_BUF_MARG_START_SHIFT               16
+#define FMAN_SP_DMA_ATTR_SWP_SHIFT                     30
+#define FMAN_SP_IC_TO_EXT_SHIFT                        16
+#define FMAN_SP_IC_FROM_INT_SHIFT                      8
+
+/* structure for defining internal context copying */
+struct fman_sp_int_context_data_copy {
+       /* < Offset in External buffer to which internal
+        *  context is copied to (Rx) or taken from (Tx, Op).
+        */
+       u16 ext_buf_offset;
+       /* Offset within internal context to copy from
+        * (Rx) or to copy to (Tx, Op).
+        */
+       u8 int_context_offset;
+       /* Internal offset size to be copied */
+       u16 size;
+};
+
+/*  struct for defining external buffer margins */
+struct fman_sp_buf_margins {
+       /* Number of bytes to be left at the beginning
+        * of the external buffer (must be divisible by 16)
+        */
+       u16 start_margins;
+       /* number of bytes to be left at the end
+        * of the external buffer(must be divisible by 16)
+        */
+       u16 end_margins;
+};
+
+struct fman_sp_buffer_offsets {
+       u32 data_offset;
+       u32 prs_result_offset;
+       u32 time_stamp_offset;
+       u32 hash_result_offset;
+};
+
+int fman_sp_build_buffer_struct(struct fman_sp_int_context_data_copy
+                               *int_context_data_copy,
+                               struct fman_buffer_prefix_content
+                               *buffer_prefix_content,
+                               struct fman_sp_buf_margins *buf_margins,
+                               struct fman_sp_buffer_offsets
+                               *buffer_offsets,
+                               u8 *internal_buf_offset);
+
+void fman_sp_set_buf_pools_in_asc_order_of_buf_sizes(struct fman_ext_pools
+                                                    *fm_ext_pools,
+                                                    u8 *ordered_array,
+                                                    u16 *sizes_array);
+
+#endif /* __FM_SP_H */