* [RFC,v3,09/12] fsl/fman: Add FMan MAC support
@ 2015-04-29 9:28 Igal.Liberman
0 siblings, 0 replies; 2+ messages in thread
From: Igal.Liberman @ 2015-04-29 9:28 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman, linuxppc-dev, linux-kernel, madalin.bucur
From: Igal Liberman <Igal.Liberman@freescale.com>
Add Frame Manger MAC Driver support.
This patch adds The FMan MAC configuration, initialization and
runtime control routines.
This patch contains support for these types of MACs:
tGEC, dTSEC and mEMAC
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
drivers/net/ethernet/freescale/fman/fm.c | 77 ++
drivers/net/ethernet/freescale/fman/fm.h | 4 +-
drivers/net/ethernet/freescale/fman/fm_common.h | 41 +
.../ethernet/freescale/fman/inc/crc_mac_addr_ext.h | 343 ++++++
.../net/ethernet/freescale/fman/inc/fm_mac_ext.h | 452 ++++++++
drivers/net/ethernet/freescale/fman/mac/Makefile | 7 +-
drivers/net/ethernet/freescale/fman/mac/dtsec.c | 1226 ++++++++++++++++++++
drivers/net/ethernet/freescale/fman/mac/dtsec.h | 185 +++
.../ethernet/freescale/fman/mac/dtsec_mii_acc.c | 82 ++
.../ethernet/freescale/fman/mac/dtsec_mii_acc.h | 43 +
drivers/net/ethernet/freescale/fman/mac/fm_mac.c | 510 ++++++++
drivers/net/ethernet/freescale/fman/mac/fm_mac.h | 183 +++
drivers/net/ethernet/freescale/fman/mac/memac.c | 837 +++++++++++++
drivers/net/ethernet/freescale/fman/mac/memac.h | 103 ++
.../ethernet/freescale/fman/mac/memac_mii_acc.c | 66 ++
.../ethernet/freescale/fman/mac/memac_mii_acc.h | 50 +
drivers/net/ethernet/freescale/fman/mac/tgec.c | 797 +++++++++++++
drivers/net/ethernet/freescale/fman/mac/tgec.h | 112 ++
.../net/ethernet/freescale/fman/mac/tgec_mii_acc.h | 66 ++
19 files changed, 5181 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_mac.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_mac.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c
index fbe4c16..c8889bd 100644
--- a/drivers/net/ethernet/freescale/fman/fm.c
+++ b/drivers/net/ethernet/freescale/fman/fm.c
@@ -703,6 +703,36 @@ static int fw_not_reset_erratum_bugzilla6173wa(struct fm_t *p_fm)
#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
/* Inter-Module functions */
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_10g_tx_ecc_workaround(void *h_fm, uint8_t mac_id)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ uint8_t rx_port_id, tx_port_id;
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ if (!(is_fman_ctrl_code_loaded(p_fm)))
+ return -ENOSYS;
+
+ SW_PORT_ID_TO_HW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+ rx_port_id,
+ FM_PORT_TYPE_RX,
+ mac_id);
+ SW_PORT_ID_TO_HW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+ tx_port_id,
+ FM_PORT_TYPE_TX,
+ mac_id);
+
+ if ((p_fm->p_fm_state_struct->ports_types[rx_port_id] !=
+ FM_PORT_TYPE_DUMMY) ||
+ (p_fm->p_fm_state_struct->ports_types[tx_port_id] !=
+ FM_PORT_TYPE_DUMMY)) {
+ pr_err("Initialize MAC prior to Rx & Tx ports!\n");
+ return -ENOSYS;
+ }
+
+ return fman_set_erratum_10gmac_a004_wa(fpm_rg);
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
void fm_register_intr(void *h_fm, enum fm_event_modules module,
uint8_t mod_id, enum fm_intr_type intr_type,
@@ -739,6 +769,53 @@ uint8_t fm_get_id(void *h_fm)
return p_fm->p_fm_state_struct->fm_id;
}
+int fm_reset_mac(void *h_fm, enum fm_mac_type type, uint8_t mac_id)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ int err;
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6) {
+ pr_warn("FMan MAC reset!\n");
+ return -ENOSYS;
+ }
+ if (!p_fm->base_addr) {
+ pr_warn("'base_address' is required!\n");
+ return -ENOSYS;
+ }
+ err =
+ (int)fman_reset_mac(fpm_rg, mac_id);
+
+ if (err == -EINVAL) {
+ pr_warn("Illegal MAC Id\n");
+ return -EINVAL;
+ } else if (err == EINVAL) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int fm_set_mac_max_frame(void *h_fm, enum fm_mac_type type,
+ uint8_t mac_id,
+ uint16_t mtu)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ /* if port is already initialized, check that MaxFrameLength is smaller
+ * or equal to the port's max
+ */
+ if ((!p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id]) ||
+ (p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id] &&
+ (mtu <=
+ p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id]))) {
+ p_fm->p_fm_state_struct->mac_max_frame_lengths[mac_id] = mtu;
+ } else {
+ pr_warn("MAC max_frame_length is larger than Port max_frame_length\n");
+ return -EDOM;
+ }
+ return 0;
+}
+
uint16_t fm_get_clock_freq(void *h_fm)
{
struct fm_t *p_fm = (struct fm_t *)h_fm;
diff --git a/drivers/net/ethernet/freescale/fman/fm.h b/drivers/net/ethernet/freescale/fman/fm.h
index ba5bb16..0f8d028 100644
--- a/drivers/net/ethernet/freescale/fman/fm.h
+++ b/drivers/net/ethernet/freescale/fman/fm.h
@@ -391,6 +391,7 @@ struct fm_state_struct_t {
/* Master/Guest parameters */
uint8_t fm_id;
+ enum fm_port_type ports_types[FM_MAX_NUM_OF_HW_PORT_IDS];
uint16_t fm_clk_freq;
struct fm_revision_info_t rev_info;
@@ -416,6 +417,8 @@ struct fm_state_struct_t {
uint32_t extra_fifo_pool_size;
uint8_t extra_tasks_pool_size;
uint8_t extra_open_dmas_pool_size;
+ uint16_t port_max_frame_lengths[FM_MAX_NUM_OF_MACS];
+ uint16_t mac_max_frame_lengths[FM_MAX_NUM_OF_MACS];
};
struct fm_intg_t {
@@ -466,7 +469,6 @@ struct fm_t {
struct fm_state_struct_t *p_fm_state_struct;
uint16_t tnum_aging_period;
-/* un-needed for recovery */
struct fman_cfg *p_fm_drv_param;
struct muram_info *p_muram;
phys_addr_t fm_muram_phys_base_addr;
diff --git a/drivers/net/ethernet/freescale/fman/fm_common.h b/drivers/net/ethernet/freescale/fman/fm_common.h
index f9d6575..4fe12c6 100644
--- a/drivers/net/ethernet/freescale/fman/fm_common.h
+++ b/drivers/net/ethernet/freescale/fman/fm_common.h
@@ -174,6 +174,30 @@ static inline bool TRY_LOCK(spinlock_t *spinlock, volatile bool *p_flag)
#define FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK 0x0000003f
+/* Description Port Id defines */
+#define BASE_OH_PORTID(major) (major >= 6 ? 2 : 1)
+#define BASE_RX_PORTID 0x08
+#define BASE_TX_PORTID 0x28
+
+#define SW_PORT_ID_TO_HW_PORT_ID(major, _port, type, mac_id) \
+do { \
+ switch (type) { \
+ case (FM_PORT_TYPE_OP): \
+ _port = (uint8_t)(BASE_OH_PORTID(major) + mac_id); \
+ break; \
+ case (FM_PORT_TYPE_RX): \
+ _port = (uint8_t)(BASE_RX_PORTID + mac_id); \
+ break; \
+ case (FM_PORT_TYPE_TX): \
+ _port = (uint8_t)(BASE_TX_PORTID + mac_id); \
+ break; \
+ default: \
+ pr_err("Illegal port type\n"); \
+ _port = 0; \
+ break; \
+ } \
+} while (0)
+
#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE)
#define BMI_FIFO_UNITS 0x100
@@ -292,6 +316,16 @@ struct muram_info *fm_get_muram_pointer(void *h_fm);
void fm_get_physical_muram_base(void *h_fm,
struct fm_phys_addr_t *fm_phys_addr);
+/* Function fm_reset_mac
+ * Description Used by MAC driver to reset the MAC registers
+ * Param[in] h_fm A handle to an FM Module.
+ * Param[in] type MAC type.
+ * Param[in] mac_id MAC id - according to type.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_init().
+ */
+int fm_reset_mac(void *h_fm, enum fm_mac_type type, uint8_t mac_id);
+
/* Function fm_get_clock_freq
* Description Used by MAC driver to get the FM clock frequency
* Param[in] h_fm A handle to an FM Module.
@@ -308,6 +342,10 @@ uint16_t fm_get_clock_freq(void *h_fm);
*/
uint8_t fm_get_id(void *h_fm);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_10g_tx_ecc_workaround(void *h_fm, uint8_t mac_id);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
void fm_muram_clear(struct muram_info *p_muram);
int fm_set_num_of_open_dmas(void *h_fm,
uint8_t port_id,
@@ -328,4 +366,7 @@ int fm_set_size_of_fifo(void *h_fm,
uint32_t fm_get_bmi_max_fifo_size(void *h_fm);
struct num_of_ports_info_t *fm_get_num_of_ports(void *h_fm);
+int fm_set_mac_max_frame(void *h_fm, enum fm_mac_type type,
+ uint8_t mac_id, uint16_t mtu);
+
#endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h b/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
new file mode 100644
index 0000000..12468cb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
@@ -0,0 +1,343 @@
+/*
+ * 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 a macro that calculate the crc value of an Ethernet MAC address
+ * (48 bitd address)
+ */
+
+#ifndef __crc_mac_addr_ext_h
+#define __crc_mac_addr_ext_h
+
+#include <linux/bitrev.h>
+
+static uint32_t crc_table[256] = {
+ 0x00000000,
+ 0x77073096,
+ 0xee0e612c,
+ 0x990951ba,
+ 0x076dc419,
+ 0x706af48f,
+ 0xe963a535,
+ 0x9e6495a3,
+ 0x0edb8832,
+ 0x79dcb8a4,
+ 0xe0d5e91e,
+ 0x97d2d988,
+ 0x09b64c2b,
+ 0x7eb17cbd,
+ 0xe7b82d07,
+ 0x90bf1d91,
+ 0x1db71064,
+ 0x6ab020f2,
+ 0xf3b97148,
+ 0x84be41de,
+ 0x1adad47d,
+ 0x6ddde4eb,
+ 0xf4d4b551,
+ 0x83d385c7,
+ 0x136c9856,
+ 0x646ba8c0,
+ 0xfd62f97a,
+ 0x8a65c9ec,
+ 0x14015c4f,
+ 0x63066cd9,
+ 0xfa0f3d63,
+ 0x8d080df5,
+ 0x3b6e20c8,
+ 0x4c69105e,
+ 0xd56041e4,
+ 0xa2677172,
+ 0x3c03e4d1,
+ 0x4b04d447,
+ 0xd20d85fd,
+ 0xa50ab56b,
+ 0x35b5a8fa,
+ 0x42b2986c,
+ 0xdbbbc9d6,
+ 0xacbcf940,
+ 0x32d86ce3,
+ 0x45df5c75,
+ 0xdcd60dcf,
+ 0xabd13d59,
+ 0x26d930ac,
+ 0x51de003a,
+ 0xc8d75180,
+ 0xbfd06116,
+ 0x21b4f4b5,
+ 0x56b3c423,
+ 0xcfba9599,
+ 0xb8bda50f,
+ 0x2802b89e,
+ 0x5f058808,
+ 0xc60cd9b2,
+ 0xb10be924,
+ 0x2f6f7c87,
+ 0x58684c11,
+ 0xc1611dab,
+ 0xb6662d3d,
+ 0x76dc4190,
+ 0x01db7106,
+ 0x98d220bc,
+ 0xefd5102a,
+ 0x71b18589,
+ 0x06b6b51f,
+ 0x9fbfe4a5,
+ 0xe8b8d433,
+ 0x7807c9a2,
+ 0x0f00f934,
+ 0x9609a88e,
+ 0xe10e9818,
+ 0x7f6a0dbb,
+ 0x086d3d2d,
+ 0x91646c97,
+ 0xe6635c01,
+ 0x6b6b51f4,
+ 0x1c6c6162,
+ 0x856530d8,
+ 0xf262004e,
+ 0x6c0695ed,
+ 0x1b01a57b,
+ 0x8208f4c1,
+ 0xf50fc457,
+ 0x65b0d9c6,
+ 0x12b7e950,
+ 0x8bbeb8ea,
+ 0xfcb9887c,
+ 0x62dd1ddf,
+ 0x15da2d49,
+ 0x8cd37cf3,
+ 0xfbd44c65,
+ 0x4db26158,
+ 0x3ab551ce,
+ 0xa3bc0074,
+ 0xd4bb30e2,
+ 0x4adfa541,
+ 0x3dd895d7,
+ 0xa4d1c46d,
+ 0xd3d6f4fb,
+ 0x4369e96a,
+ 0x346ed9fc,
+ 0xad678846,
+ 0xda60b8d0,
+ 0x44042d73,
+ 0x33031de5,
+ 0xaa0a4c5f,
+ 0xdd0d7cc9,
+ 0x5005713c,
+ 0x270241aa,
+ 0xbe0b1010,
+ 0xc90c2086,
+ 0x5768b525,
+ 0x206f85b3,
+ 0xb966d409,
+ 0xce61e49f,
+ 0x5edef90e,
+ 0x29d9c998,
+ 0xb0d09822,
+ 0xc7d7a8b4,
+ 0x59b33d17,
+ 0x2eb40d81,
+ 0xb7bd5c3b,
+ 0xc0ba6cad,
+ 0xedb88320,
+ 0x9abfb3b6,
+ 0x03b6e20c,
+ 0x74b1d29a,
+ 0xead54739,
+ 0x9dd277af,
+ 0x04db2615,
+ 0x73dc1683,
+ 0xe3630b12,
+ 0x94643b84,
+ 0x0d6d6a3e,
+ 0x7a6a5aa8,
+ 0xe40ecf0b,
+ 0x9309ff9d,
+ 0x0a00ae27,
+ 0x7d079eb1,
+ 0xf00f9344,
+ 0x8708a3d2,
+ 0x1e01f268,
+ 0x6906c2fe,
+ 0xf762575d,
+ 0x806567cb,
+ 0x196c3671,
+ 0x6e6b06e7,
+ 0xfed41b76,
+ 0x89d32be0,
+ 0x10da7a5a,
+ 0x67dd4acc,
+ 0xf9b9df6f,
+ 0x8ebeeff9,
+ 0x17b7be43,
+ 0x60b08ed5,
+ 0xd6d6a3e8,
+ 0xa1d1937e,
+ 0x38d8c2c4,
+ 0x4fdff252,
+ 0xd1bb67f1,
+ 0xa6bc5767,
+ 0x3fb506dd,
+ 0x48b2364b,
+ 0xd80d2bda,
+ 0xaf0a1b4c,
+ 0x36034af6,
+ 0x41047a60,
+ 0xdf60efc3,
+ 0xa867df55,
+ 0x316e8eef,
+ 0x4669be79,
+ 0xcb61b38c,
+ 0xbc66831a,
+ 0x256fd2a0,
+ 0x5268e236,
+ 0xcc0c7795,
+ 0xbb0b4703,
+ 0x220216b9,
+ 0x5505262f,
+ 0xc5ba3bbe,
+ 0xb2bd0b28,
+ 0x2bb45a92,
+ 0x5cb36a04,
+ 0xc2d7ffa7,
+ 0xb5d0cf31,
+ 0x2cd99e8b,
+ 0x5bdeae1d,
+ 0x9b64c2b0,
+ 0xec63f226,
+ 0x756aa39c,
+ 0x026d930a,
+ 0x9c0906a9,
+ 0xeb0e363f,
+ 0x72076785,
+ 0x05005713,
+ 0x95bf4a82,
+ 0xe2b87a14,
+ 0x7bb12bae,
+ 0x0cb61b38,
+ 0x92d28e9b,
+ 0xe5d5be0d,
+ 0x7cdcefb7,
+ 0x0bdbdf21,
+ 0x86d3d2d4,
+ 0xf1d4e242,
+ 0x68ddb3f8,
+ 0x1fda836e,
+ 0x81be16cd,
+ 0xf6b9265b,
+ 0x6fb077e1,
+ 0x18b74777,
+ 0x88085ae6,
+ 0xff0f6a70,
+ 0x66063bca,
+ 0x11010b5c,
+ 0x8f659eff,
+ 0xf862ae69,
+ 0x616bffd3,
+ 0x166ccf45,
+ 0xa00ae278,
+ 0xd70dd2ee,
+ 0x4e048354,
+ 0x3903b3c2,
+ 0xa7672661,
+ 0xd06016f7,
+ 0x4969474d,
+ 0x3e6e77db,
+ 0xaed16a4a,
+ 0xd9d65adc,
+ 0x40df0b66,
+ 0x37d83bf0,
+ 0xa9bcae53,
+ 0xdebb9ec5,
+ 0x47b2cf7f,
+ 0x30b5ffe9,
+ 0xbdbdf21c,
+ 0xcabac28a,
+ 0x53b39330,
+ 0x24b4a3a6,
+ 0xbad03605,
+ 0xcdd70693,
+ 0x54de5729,
+ 0x23d967bf,
+ 0xb3667a2e,
+ 0xc4614ab8,
+ 0x5d681b02,
+ 0x2a6f2b94,
+ 0xb40bbe37,
+ 0xc30c8ea1,
+ 0x5a05df1b,
+ 0x2d02ef8d
+};
+
+/* CRC calculation */
+#define GET_MAC_ADDR_CRC(addr, crc) \
+{ \
+ uint32_t i; \
+ uint8_t data; \
+ crc = 0xffffffff; \
+ for (i = 0; i < 6; i++) { \
+ data = (uint8_t)(addr >> ((5 - i) * 8)); \
+ crc = crc ^ data; \
+ crc = crc_table[crc & 0xff] ^ (crc >> 8); \
+ } \
+} \
+
+/* Define a macro for getting the mirrored value of */
+/* a byte size number. (0x11010011 --> 0x11001011) */
+/* Sometimes the mirrored value of the CRC is required */
+static inline uint8_t swab(uint8_t n)
+{
+ uint8_t mirror[16] = {
+ 0x00,
+ 0x08,
+ 0x04,
+ 0x0c,
+ 0x02,
+ 0x0a,
+ 0x06,
+ 0x0e,
+ 0x01,
+ 0x09,
+ 0x05,
+ 0x0d,
+ 0x03,
+ 0x0b,
+ 0x07,
+ 0x0f
+ };
+ return ((uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4]))));
+}
+
+#define MIRROR bitrev
+#define MIRROR_32 bitrev32
+
+#endif /* __crc_mac_addr_ext_h */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
new file mode 100644
index 0000000..4d4b211
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
@@ -0,0 +1,452 @@
+/*
+ * 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_mac_ext.h
+ * Description FM MAC ...
+ */
+#ifndef __FM_MAC_EXT_H
+#define __FM_MAC_EXT_H
+
+#include "service.h"
+#include "enet_ext.h"
+#include "dpaa_integration_ext.h"
+
+struct fm_mac_dev;
+
+/* Description FM MAC API functions, definitions and enums */
+
+#define FM_MAC_NO_PFC 0xff
+
+/* FM MAC Exceptions */
+enum fm_mac_exceptions {
+ FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
+ /* 10GEC MDIO scan event interrupt */
+ , FM_MAC_EX_10G_MDIO_CMD_CMPL
+ /* 10GEC MDIO command completion interrupt */
+ , FM_MAC_EX_10G_REM_FAULT
+ /* 10GEC, mEMAC Remote fault interrupt */
+ , FM_MAC_EX_10G_LOC_FAULT
+ /* 10GEC, mEMAC Local fault interrupt */
+ , FM_MAC_EX_10G_1TX_ECC_ER
+ /* 10GEC, mEMAC Transmit frame ECC error interrupt */
+ , FM_MAC_EX_10G_TX_FIFO_UNFL
+ /* 10GEC, mEMAC Transmit FIFO underflow interrupt */
+ , FM_MAC_EX_10G_TX_FIFO_OVFL
+ /* 10GEC, mEMAC Transmit FIFO overflow interrupt */
+ , FM_MAC_EX_10G_TX_ER
+ /* 10GEC Transmit frame error interrupt */
+ , FM_MAC_EX_10G_RX_FIFO_OVFL
+ /* 10GEC, mEMAC Receive FIFO overflow interrupt */
+ , FM_MAC_EX_10G_RX_ECC_ER
+ /* 10GEC, mEMAC Receive frame ECC error interrupt */
+ , FM_MAC_EX_10G_RX_JAB_FRM
+ /* 10GEC Receive jabber frame interrupt */
+ , FM_MAC_EX_10G_RX_OVRSZ_FRM
+ /* 10GEC Receive oversized frame interrupt */
+ , FM_MAC_EX_10G_RX_RUNT_FRM
+ /* 10GEC Receive runt frame interrupt */
+ , FM_MAC_EX_10G_RX_FRAG_FRM
+ /* 10GEC Receive fragment frame interrupt */
+ , FM_MAC_EX_10G_RX_LEN_ER
+ /* 10GEC Receive payload length error interrupt */
+ , FM_MAC_EX_10G_RX_CRC_ER
+ /* 10GEC Receive CRC error interrupt */
+ , FM_MAC_EX_10G_RX_ALIGN_ER
+ /* 10GEC Receive alignment error interrupt */
+ , FM_MAC_EX_1G_BAB_RX
+ /* dTSEC Babbling receive error */
+ , FM_MAC_EX_1G_RX_CTL
+ /* dTSEC Receive control (pause frame) interrupt */
+ , FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET
+ /* dTSEC Graceful transmit stop complete */
+ , FM_MAC_EX_1G_BAB_TX
+ /* dTSEC Babbling transmit error */
+ , FM_MAC_EX_1G_TX_CTL
+ /* dTSEC Transmit control (pause frame) interrupt */
+ , FM_MAC_EX_1G_TX_ERR
+ /* dTSEC Transmit error */
+ , FM_MAC_EX_1G_LATE_COL
+ /* dTSEC Late collision */
+ , FM_MAC_EX_1G_COL_RET_LMT
+ /* dTSEC Collision retry limit */
+ , FM_MAC_EX_1G_TX_FIFO_UNDRN
+ /* dTSEC Transmit FIFO underrun */
+ , FM_MAC_EX_1G_MAG_PCKT
+ /* dTSEC Magic Packet detection */
+ , FM_MAC_EX_1G_MII_MNG_RD_COMPLET
+ /* dTSEC MII management read completion */
+ , FM_MAC_EX_1G_MII_MNG_WR_COMPLET
+ /* dTSEC MII management write completion */
+ , FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET
+ /* dTSEC Graceful receive stop complete */
+ , FM_MAC_EX_1G_DATA_ERR
+ /* dTSEC Internal data error on transmit */
+ , FM_MAC_1G_RX_DATA_ERR
+ /* dTSEC Internal data error on receive */
+ , FM_MAC_EX_1G_1588_TS_RX_ERR
+ /* dTSEC Time-Stamp Receive Error */
+ , FM_MAC_EX_1G_RX_MIB_CNT_OVFL
+ /* dTSEC MIB counter overflow */
+ , FM_MAC_EX_TS_FIFO_ECC_ERR
+ /* mEMAC Time-stamp FIFO ECC error interrupt;
+ * not supported on T4240/B4860 rev1 chips
+ */
+ , FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT
+ /* mEMAC Magic Packet Indication Interrupt */
+};
+
+/* Function fm_mac_exception_cb
+ * Description Fm Mac Exception Callback from FM MAC to the user
+ * Param[in] h_app - Handle to the upper layer handler
+ * Param[in] exceptions - The exception that occurred
+ * Return void.
+ */
+typedef void (fm_mac_exception_cb) (void *h_app,
+ enum fm_mac_exceptions exceptions);
+
+/* FM MAC Initialization Unit */
+
+/* FM MAC config input */
+struct fm_mac_params_t {
+ /* Base of memory mapped FM MAC registers */
+ uintptr_t base_addr;
+ /* MAC address of device; First octet is sent first */
+ enet_addr_t addr;
+ /* MAC ID; numbering of dTSEC and 1G-mEMAC:
+ * 0 - FM_MAX_NUM_OF_1G_MACS;
+ * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
+ * 0 - FM_MAX_NUM_OF_10G_MACS
+ */
+ uint8_t mac_id;
+ /* Ethernet operation mode (MAC-PHY interface and speed);
+ * Note that the speed should indicate the maximum rate that
+ * this MAC should support rather than the actual speed;
+ * i.e. user should use the FM_MAC_AdjustLink() routine to
+ * provide accurate speed;
+ * In case of mEMAC RGMII mode, the MAC is configured to RGMII
+ * automatic mode, where actual speed/duplex mode information
+ * is provided by PHY automatically in-band; FM_MAC_AdjustLink()
+ * function should be used to switch to manual RGMII speed/duplex mode
+ * configuration if RGMII PHY doesn't support in-band status signaling;
+ * In addition, in mEMAC, in case where user is using the higher MACs
+ * (i.e. the MACs that should support 10G), user should pass here
+ * speed=10000 even if the interface is not allowing that (e.g. SGMII).
+ */
+ enum e_enet_mode enet_mode;
+ /* A handle to the FM object this port related to */
+ void *h_fm;
+ /* MDIO exceptions interrupt source - not valid for all
+ * MACs; MUST be set to 'NO_IRQ' for MACs that don't have
+ * mdio-irq, or for polling
+ */
+ int mdio_irq;
+ fm_mac_exception_cb *f_event; /* MDIO Events Callback Routine */
+ fm_mac_exception_cb *f_exception; /* Exception Callback Routine */
+ void *h_app; /* A handle to an application layer object;
+ * This handle will be passed by the driver
+ * upon calling the above callbacks
+ */
+};
+
+struct fm_mac_dev;
+
+/* Function fm_mac_config
+ * Description Creates descriptor for the FM MAC module.
+ * The routine returns a pointer to the FM MAC object.
+ * This pointer must be passed as first parameter to all other
+ * FM MAC function calls.
+ * No actual initialization or configuration of FM MAC hardware
+ * is done by this routine.
+ * Param[in] p_fm_mac_param - Pointer to data structure of parameters
+ * Retval Pointer to FM MAC object, or NULL for Failure.
+ */
+struct fm_mac_dev *fm_mac_config(struct fm_mac_params_t *p_fm_mac_param);
+
+/* Function fm_mac_init
+ * Description Initializes the FM MAC module
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev);
+
+/* Function fm_free
+ * Description Frees all resources that were assigned to FM MAC module.
+ * Calling this routine invalidates the descriptor.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev);
+
+/* Description Configuration functions used to change default values. */
+
+/* Function fm_mac_cfg_reset_on_init
+ * Description Tell the driver whether to reset the FM MAC before
+ * initialization or not. It changes the default configuration
+ * [DEFAULT_RESET_ON_INIT].
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable - When true, FM will be reset before initialization.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_cfg_max_frame_len
+ * Description Setup maximum Rx Frame Length (in 1G MAC, effects also Tx)
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] new_val - MAX Frame length
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_max_frame_len(struct fm_mac_dev *fm_mac_dev, uint16_t new_val);
+
+/* Function fm_mac_cfg_pad_and_crc
+ * Description Config PAD and CRC mode
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable - true to enable or false to disable.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ * Not supported on 10G-MAC (i.e. CRC&PAD are added
+ * automatically by HW); on mEMAC, this routine supports only
+ * PAD (i.e. CRC is added automatically by HW).
+ */
+int fm_mac_cfg_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_cfg_tbi_phy_addr
+ * Description Configures the address of internal TBI PHY.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] new_val - TBI PHY address (1-31).
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_tbi_phy_addr(struct fm_mac_dev *fm_mac_dev, uint8_t new_val);
+
+/* Function fm_mac_cfg_len_check
+ * Description Configure the frame length checking.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable - true to enable or false to disable.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_len_check(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_cfg_exception
+ * Description Change Exception selection from default
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] ex - Type of the desired exceptions
+ * Param[in] enable - true to enable the specified exception,
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable);
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_mac_cfg_skip_fman11_wa(struct fm_mac_dev *fm_mac_dev);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* FM MAC Runtime control unit API functions, definitions and enums. */
+
+/* Function fm_mac_enable
+ * Description Enable the MAC
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] mode - Mode of operation (RX, TX, Both)
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_enable(struct fm_mac_dev*, enum comm_mode mode);
+
+/* Function fm_mac_disable
+ * Description Disavle the MAC
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] mode - Mode of operation (RX, TX, Both)
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode);
+
+#define FSL_FM_PAUSE_TIME_ENABLE 0xf000
+#define FSL_FM_PAUSE_TIME_DISABLE 0
+#define FSL_FM_PAUSE_THRESH_DEFAULT 0
+
+/* Function fm_mac_set_tx_pause_frames
+ * Description Enable/Disable transmission of Pause-Frames.
+ * The routine changes the default configuration:
+ * pause-time - [DEFAULT_TX_PAUSE_TIME]
+ * threshold-time - [0]
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] priority - the PFC class of service; use 'FM_MAC_NO_PFC'
+ * to indicate legacy pause support (i.e. no PFC).
+ * Param[in] pause_time - Pause quanta value used with transmitted pause
+ * frames. Each quanta represents a 512 bit-times;
+ * Note that '0' as an input here will be used as disabling the
+ * transmission of the pause-frames.
+ * Param[in] For legacy pause support (i.e. no PFC), thus
+ * value should be '0'.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time);
+
+/* Function fm_mac_set_rx_pause_frames
+ * Description Enable/Disable rx Pause-Frames.
+ * Param[in] fm_mac_dev - A Pointer to MAC object
+ * Param[in] en - boolean indicates whether to ignore the incoming pause
+ * frames or not.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_set_rx_pause_frames(struct fm_mac_dev *fm_mac_dev, bool en);
+
+/* Function fm_mac_set_exception
+ * Description Enable/Disable a specific Exception
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] ex - Type of the desired exceptions
+ * Param[in] enable - true to enable the specified exception,
+ * false to disable it.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable);
+
+/* Function fm_mac_modify_mac_addr
+ * Description Replace the main MAC Address
+ * Param[in] fm_mac_dev - A pointer to MAC object
+ * Param[in] p_enet_addr - Ethernet Mac address
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr);
+
+/* Function fm_mac_add_hash_mac_addr
+ * Description Add an Address to the hash table. This is for filter purpose
+ * only.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] p_enet_addr - Ethernet Mac address
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ * It is a filter only address.
+ * Cautions Some address need to be filterd out in upper FM blocks.
+ */
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr);
+
+/* Function fm_mac_remove_hash_mac_addr
+ * Description Delete an Address to the hash table. This is for filter
+ * purpose only.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] p_enet_addr - Ethernet Mac address
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr);
+
+/* Function fm_mac_set_promiscuous
+ * Description Enable/Disable MAC Promiscuous mode for ALL mac addresses.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable -true to enable or false to disable.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_adjust_link
+ * Description Adjusts the Ethernet link with new speed/duplex setup.
+ * This routine is relevant for dTSEC and mEMAC.
+ * In case of mEMAC, this routine is also used for manual
+ * re-configuration of RGMII speed and duplex mode for
+ * RGMII PHYs not supporting in-band status information to MAC.
+ * Param[in] fm_mac_dev - A pointer to MAC object
+ * Param[in] speed - Ethernet speed.
+ * false for half-duplex mode.
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, int link,
+ enum ethernet_speed speed);
+
+/* Function fm_mac_restart_autoneg
+ * Description Restarts the auto-negotiation process.
+ * When auto-negotiation process is invoked under traffic the
+ * auto-negotiation process between the internal SGMII PHY and
+ * the external PHY does not always complete successfully.
+ * Calling this function will restart the auto-negotiation
+ * process that will end successfully. It is recommended to
+ * call this function after issuing auto-negotiation restart
+ * command to the Eth Phy.
+ * This routine is relevant only for dTSEC.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_restart_autoneg(struct fm_mac_dev *fm_mac_dev);
+
+/* Function fm_mac_get_max_frame_length
+ * Description Return the max frame length value
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[out] p_mac_id - MAC ID of device.
+ * Return the maximum frame length value
+ * Cautions Allowed only after fm_mac_init().
+ */
+uint16_t fm_mac_get_max_frame_length(struct fm_mac_dev *fm_mac_dev);
+
+/* Function fm_mac_get_id
+ * Description Return the MAC ID
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[out] p_mac_id - MAC ID of device.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_get_id(struct fm_mac_dev *fm_mac_dev, uint32_t *p_mac_id);
+
+/* Function fm_mac_get_version
+ * Description Return Mac HW chip version
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[out] p_mac_version - Mac version as defined by the chip
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev,
+ uint32_t *p_mac_version);
+
+#endif /* __FM_MAC_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/Makefile b/drivers/net/ethernet/freescale/fman/mac/Makefile
index 80b7048..042a1f7 100644
--- a/drivers/net/ethernet/freescale/fman/mac/Makefile
+++ b/drivers/net/ethernet/freescale/fman/mac/Makefile
@@ -1,5 +1,8 @@
obj-$(CONFIG_FSL_FMAN_MAC) += fsl_fman_mac.o
fsl_fman_mac-objs := fman_dtsec.o fman_dtsec_mii_acc.o \
- fman_memac.o fman_tgec.o \
- fman_crc32.o fman_memac_mii_acc.o
+ dtsec.o dtsec_mii_acc.o \
+ fman_memac.o fman_memac_mii_acc.o \
+ memac.o memac_mii_acc.o \
+ fman_tgec.o tgec.o \
+ fman_crc32.o fm_mac.o
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec.c b/drivers/net/ethernet/freescale/fman/mac/dtsec.c
new file mode 100644
index 0000000..e5c830b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec.c
@@ -0,0 +1,1226 @@
+/*
+ * 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.
+ */
+
+/* FMan dTSEC driver */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/bitrev.h>
+
+/* Internal routines */
+
+static int check_init_parameters(struct dtsec_t *p_dtsec)
+{
+ if (ENET_SPEED_FROM_MODE(p_dtsec->enet_mode) >= ENET_SPEED_10000) {
+ pr_err("1G MAC driver supports 1G or lower speeds\n");
+ return -EDOM;
+ }
+ if (p_dtsec->addr == 0) {
+ pr_err("Ethernet MAC Must have a valid MAC Address\n");
+ return -EDOM;
+ }
+ if ((ENET_SPEED_FROM_MODE(p_dtsec->enet_mode) >= ENET_SPEED_1000) &&
+ p_dtsec->p_dtsec_drv_param->halfdup_on) {
+ pr_err("Ethernet MAC 1G can't work in half duplex\n");
+ return -EDOM;
+ }
+#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001
+ /* fixed for rev3 */
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev <= 6)
+ if (p_dtsec->p_dtsec_drv_param->rx_preamble) {
+ pr_err("preambleRxEn\n");
+ return -ENOSYS;
+ }
+#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */
+ if (((p_dtsec->p_dtsec_drv_param)->tx_preamble ||
+ (p_dtsec->p_dtsec_drv_param)->rx_preamble) &&
+ ((p_dtsec->p_dtsec_drv_param)->preamble_len != 0x7)) {
+ pr_err("Preamble length should be 0x7 bytes\n");
+ return -EDOM;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_on &&
+ (p_dtsec->p_dtsec_drv_param->tx_time_stamp_en ||
+ p_dtsec->p_dtsec_drv_param->rx_time_stamp_en)) {
+ pr_err("1588 timeStamp disabled in half duplex mode\n");
+ return -EDOM;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->rx_flow &&
+ (p_dtsec->p_dtsec_drv_param)->rx_ctrl_acc) {
+ pr_err("Receive control frame can not be accepted\n");
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->rx_prepend >
+ MAX_PACKET_ALIGNMENT) {
+ pr_err("packetAlignmentPadding can't be > than %d\n",
+ MAX_PACKET_ALIGNMENT);
+ return -ENOSYS;
+ }
+ if (((p_dtsec->p_dtsec_drv_param)->non_back_to_back_ipg1 >
+ MAX_INTER_PACKET_GAP) ||
+ ((p_dtsec->p_dtsec_drv_param)->non_back_to_back_ipg2 >
+ MAX_INTER_PACKET_GAP) ||
+ ((p_dtsec->p_dtsec_drv_param)->back_to_back_ipg >
+ MAX_INTER_PACKET_GAP)) {
+ pr_err("Inter packet gap can't be greater than %d\n",
+ MAX_INTER_PACKET_GAP);
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_alt_backoff_val >
+ MAX_INTER_PALTERNATE_BEB) {
+ pr_err("alternateBackoffVal can't be greater than %d\n",
+ MAX_INTER_PALTERNATE_BEB);
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_retransmit >
+ MAX_RETRANSMISSION) {
+ pr_err("maxRetransmission can't be greater than %d\n",
+ MAX_RETRANSMISSION);
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_coll_window >
+ MAX_COLLISION_WINDOW) {
+ pr_err("collisionWindow can't be greater than %d\n",
+ MAX_COLLISION_WINDOW);
+ return -ENOSYS;
+ /* If Auto negotiation process is disabled, need to */
+ /* Set up the PHY using the MII Management Interface */
+ }
+ if (p_dtsec->p_dtsec_drv_param->tbipa > MAX_PHYS) {
+ pr_err("PHY address (should be 0-%d)\n", MAX_PHYS);
+ return -ERANGE;
+ }
+ if (!p_dtsec->f_exception) {
+ pr_err("uninitialized f_exception\n");
+ return -EINVAL;
+ }
+ if (!p_dtsec->f_event) {
+ pr_err("uninitialized f_event\n");
+ return -EINVAL;
+ }
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev != 4 &&
+ p_dtsec->p_dtsec_drv_param->rx_len_check) {
+ pr_warn("LengthCheck!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+ uint32_t bit_mask;
+
+ switch (exception) {
+ case FM_MAC_EX_1G_BAB_RX:
+ bit_mask = DTSEC_IMASK_BREN;
+ break;
+ case FM_MAC_EX_1G_RX_CTL:
+ bit_mask = DTSEC_IMASK_RXCEN;
+ break;
+ case FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET:
+ bit_mask = DTSEC_IMASK_GTSCEN;
+ break;
+ case FM_MAC_EX_1G_BAB_TX:
+ bit_mask = DTSEC_IMASK_BTEN;
+ break;
+ case FM_MAC_EX_1G_TX_CTL:
+ bit_mask = DTSEC_IMASK_TXCEN;
+ break;
+ case FM_MAC_EX_1G_TX_ERR:
+ bit_mask = DTSEC_IMASK_TXEEN;
+ break;
+ case FM_MAC_EX_1G_LATE_COL:
+ bit_mask = DTSEC_IMASK_LCEN;
+ break;
+ case FM_MAC_EX_1G_COL_RET_LMT:
+ bit_mask = DTSEC_IMASK_CRLEN;
+ break;
+ case FM_MAC_EX_1G_TX_FIFO_UNDRN:
+ bit_mask = DTSEC_IMASK_XFUNEN;
+ break;
+ case FM_MAC_EX_1G_MAG_PCKT:
+ bit_mask = DTSEC_IMASK_MAGEN;
+ break;
+ case FM_MAC_EX_1G_MII_MNG_RD_COMPLET:
+ bit_mask = DTSEC_IMASK_MMRDEN;
+ break;
+ case FM_MAC_EX_1G_MII_MNG_WR_COMPLET:
+ bit_mask = DTSEC_IMASK_MMWREN;
+ break;
+ case FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET:
+ bit_mask = DTSEC_IMASK_GRSCEN;
+ break;
+ case FM_MAC_EX_1G_DATA_ERR:
+ bit_mask = DTSEC_IMASK_TDPEEN;
+ break;
+ case FM_MAC_EX_1G_RX_MIB_CNT_OVFL:
+ bit_mask = DTSEC_IMASK_MSROEN;
+ break;
+ default:
+ bit_mask = 0;
+ break;
+ }
+
+ return bit_mask;
+}
+
+/* Checks if p_dtsec driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct dtsec_cfg *p_dtsec_drv_parameters)
+{
+ if (!p_dtsec_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(eth_addr, crc);
+
+ crc = bitrev32(crc);
+
+ return crc;
+}
+
+static uint16_t dtsec_get_max_frame_length(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return 0;
+
+ return fman_dtsec_get_max_frame_len(p_dtsec->p_mem_map);
+}
+
+static void dtsec_isr(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t event;
+ struct dtsec_regs __iomem *p_dtsec_mem_map = p_dtsec->p_mem_map;
+
+ /* do not handle MDIO events */
+ event =
+ fman_dtsec_get_event(p_dtsec_mem_map,
+ (uint32_t)(~
+ (DTSEC_IMASK_MMRDEN |
+ DTSEC_IMASK_MMWREN)));
+
+ event &= fman_dtsec_get_interrupt_mask(p_dtsec_mem_map);
+
+ fman_dtsec_ack_event(p_dtsec_mem_map, event);
+
+ if (event & DTSEC_IMASK_BREN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_BAB_RX);
+ if (event & DTSEC_IMASK_RXCEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_RX_CTL);
+ if (event & DTSEC_IMASK_GTSCEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET);
+ if (event & DTSEC_IMASK_BTEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_BAB_TX);
+ if (event & DTSEC_IMASK_TXCEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_TX_CTL);
+ if (event & DTSEC_IMASK_TXEEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_TX_ERR);
+ if (event & DTSEC_IMASK_LCEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_LATE_COL);
+ if (event & DTSEC_IMASK_CRLEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_COL_RET_LMT);
+ if (event & DTSEC_IMASK_XFUNEN) {
+#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2) {
+ uint32_t tpkt1, tmp_reg1, tpkt2, tmp_reg2, i;
+ /* a. Write 0x00E0_0C00 to DTSEC_ID */
+ /* This is a read only regidter
+ */
+
+ /* b. Read and save the value of TPKT */
+ tpkt1 = GET_UINT32(p_dtsec_mem_map->tpkt);
+
+ /* c. Read the register at dTSEC address offset 0x32C */
+ tmp_reg1 =
+ GET_UINT32(*(uint32_t *)
+ ((uint8_t *)p_dtsec_mem_map + 0x32c));
+
+ /* d. Compare bits [9:15] to bits [25:31] of the
+ * register at address offset 0x32C.
+ */
+ if ((tmp_reg1 & 0x007F0000) !=
+ (tmp_reg1 & 0x0000007F)) {
+ /* If they are not equal, save the value of
+ * this register and wait for at least
+ * MAXFRM*16 ns
+ */
+ usleep_range((uint32_t)(min
+ (dtsec_get_max_frame_length(p_dtsec) *
+ 16 / 1000, 1)), (uint32_t)
+ (min(dtsec_get_max_frame_length
+ (p_dtsec) * 16 / 1000, 1) + 1));
+ }
+
+ /* e. Read and save TPKT again and read the register
+ * at dTSEC address offset 0x32C again
+ */
+ tpkt2 = GET_UINT32(p_dtsec_mem_map->tpkt);
+ tmp_reg2 =
+ GET_UINT32(*(uint32_t __iomem *)
+ ((uint8_t *)p_dtsec_mem_map + 0x32c));
+
+ /* f. Compare the value of TPKT saved in step b to
+ * value read in step e. Also compare bits [9:15] of
+ * the register at offset 0x32C saved in step d to the
+ * value of bits [9:15] saved in step e. If the two
+ * registers values are unchanged, then the transmit
+ * portion of the dTSEC controller is locked up and
+ * the user should proceed to the recover sequence.
+ */
+ if ((tpkt1 == tpkt2) && ((tmp_reg1 & 0x007F0000) ==
+ (tmp_reg2 & 0x007F0000))) {
+ /* recover sequence */
+
+ /* a.Write a 1 to RCTRL[GRS] */
+
+ WRITE_UINT32(p_dtsec_mem_map->rctrl,
+ GET_UINT32(p_dtsec_mem_map->
+ rctrl) | RCTRL_GRS);
+
+ /* b.Wait until IEVENT[GRSC]=1, or at least
+ * 100 us has elapsed.
+ */
+ for (i = 0; i < 100; i++) {
+ if (GET_UINT32(p_dtsec_mem_map->
+ ievent) &
+ DTSEC_IMASK_GRSCEN)
+ break;
+ udelay(1);
+ }
+ if (GET_UINT32(p_dtsec_mem_map->ievent) &
+ DTSEC_IMASK_GRSCEN)
+ WRITE_UINT32(p_dtsec_mem_map->ievent,
+ DTSEC_IMASK_GRSCEN);
+ else
+ pr_debug("Rx lockup due to Tx lockup\n");
+
+ /* c.Write a 1 to bit n of FM_RSTC
+ * (offset 0x0CC of FPM)
+ */
+ fm_reset_mac(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MAC_1G,
+ p_dtsec->fm_mac_ctrl_drv.mac_id);
+
+ /* d.Wait 4 Tx clocks (32 ns) */
+ udelay(1);
+
+ /* e.Write a 0 to bit n of FM_RSTC. */
+ /* cleared by FMAN
+ */
+ }
+ }
+#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */
+
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_TX_FIFO_UNDRN);
+ }
+ if (event & DTSEC_IMASK_MAGEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_MAG_PCKT);
+ if (event & DTSEC_IMASK_GRSCEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET);
+ if (event & DTSEC_IMASK_TDPEEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_DATA_ERR);
+ if (event & DTSEC_IMASK_RDPEEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_1G_RX_DATA_ERR);
+
+ /* - masked interrupts */
+ ASSERT(!(event & DTSEC_IMASK_ABRTEN));
+ ASSERT(!(event & DTSEC_IMASK_IFERREN));
+}
+
+static void dtsec_1588_isr(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t event;
+ struct dtsec_regs __iomem *p_dtsec_mem_map = p_dtsec->p_mem_map;
+
+ if (p_dtsec->ptp_tsu_enabled) {
+ event = fman_dtsec_check_and_clear_tmr_event(p_dtsec_mem_map);
+
+ if (event) {
+ ASSERT(event & TMR_PEVENT_TSRE);
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_1588_TS_RX_ERR);
+ }
+ }
+}
+
+static void free_init_resources(struct dtsec_t *p_dtsec)
+{
+ fm_unregister_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC, p_dtsec->mac_id, FM_INTR_TYPE_ERR);
+ fm_unregister_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC, p_dtsec->mac_id,
+ FM_INTR_TYPE_NORMAL);
+
+ /* release the driver's group hash table */
+ free_hash_table(p_dtsec->p_multicast_addr_hash);
+ p_dtsec->p_multicast_addr_hash = NULL;
+
+ /* release the driver's individual hash table */
+ free_hash_table(p_dtsec->p_unicast_addr_hash);
+ p_dtsec->p_unicast_addr_hash = NULL;
+}
+
+static int graceful_stop(struct dtsec_t *p_dtsec, enum comm_mode mode)
+{
+ struct dtsec_regs __iomem *p_mem_map;
+
+ p_mem_map = p_dtsec->p_mem_map;
+
+ /* Assert the graceful transmit stop bit */
+ if (mode & COMM_MODE_RX) {
+ fman_dtsec_stop_rx(p_mem_map);
+
+#ifdef FM_GRS_ERRATA_DTSEC_A002
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ usleep_range(100, 101);
+#else /* FM_GRS_ERRATA_DTSEC_A002 */
+#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
+ usleep_range(10, 11);
+#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */
+#endif /* FM_GRS_ERRATA_DTSEC_A002 */
+ }
+
+ if (mode & COMM_MODE_TX) {
+#if defined(FM_GTS_ERRATA_DTSEC_A004) || \
+defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012)
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ pr_debug("GTS not supported due to DTSEC_A004 errata.\n");
+#else /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||..*/
+#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev != 4)
+ pr_debug("GTS not supported due to DTSEC_A0014 errata.\n");
+#else /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+ fman_dtsec_stop_tx(p_mem_map);
+#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */
+ }
+ return 0;
+}
+
+static int graceful_restart(struct dtsec_t *p_dtsec, enum comm_mode mode)
+{
+ struct dtsec_regs __iomem *p_mem_map;
+
+ p_mem_map = p_dtsec->p_mem_map;
+ /* clear the graceful receive stop bit */
+ if (mode & COMM_MODE_TX)
+ fman_dtsec_start_tx(p_mem_map);
+
+ if (mode & COMM_MODE_RX)
+ fman_dtsec_start_rx(p_mem_map);
+
+ return 0;
+}
+
+/* dTSEC Configs modification functions */
+
+static int dtsec_cfg_lb(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->loopback = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_max_frame_len(void *h_dtsec, uint16_t new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->maximum_frame = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_pad_and_crc(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->tx_pad_crc = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_tbi_phy_addr(void *h_dtsec, uint8_t new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->tbi_phy_addr = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_len_check(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->rx_len_check = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_exception(void *h_dtsec, enum fm_mac_exceptions
+ exception, bool enable)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) {
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_dtsec->exceptions |= bit_mask;
+ else
+ p_dtsec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ } else {
+ if (!p_dtsec->ptp_tsu_enabled) {
+ pr_err("Exception valid for 1588 only\n");
+ return -EDOM;
+ }
+ switch (exception) {
+ case (FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable)
+ p_dtsec->en_tsu_err_exeption = true;
+ else
+ p_dtsec->en_tsu_err_exeption = false;
+ break;
+ default:
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ }
+ return 0;
+}
+
+/* dTSEC Run Time API functions */
+
+static int dtsec_enable(void *h_dtsec, enum comm_mode mode)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_dtsec_enable(p_dtsec->p_mem_map,
+ (bool)!!(mode & COMM_MODE_RX),
+ (bool)!!(mode & COMM_MODE_TX));
+
+ graceful_restart(p_dtsec, mode);
+
+ return 0;
+}
+
+static int dtsec_disable(void *h_dtsec, enum comm_mode mode)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ graceful_stop(p_dtsec, mode);
+
+ fman_dtsec_disable(p_dtsec->p_mem_map,
+ (bool)!!(mode & COMM_MODE_RX),
+ (bool)!!(mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int dtsec_set_tx_pause_frames(void *h_dtsec,
+ uint8_t __maybe_unused priority,
+ uint16_t pause_time,
+ uint16_t __maybe_unused thresh_time)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ if (0 < pause_time && pause_time <= 320) {
+ pr_warn("pause-time:%d illegal.Should be >320\n",
+ pause_time);
+ return -EDOM;
+ }
+#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */
+
+ fman_dtsec_set_tx_pause_frames(p_dtsec->p_mem_map, pause_time);
+ return 0;
+}
+
+/* backward compatibility. will be removed in the future. */
+static int dtsec_tx_mac_pause(void *h_dtsec, uint16_t pause_time)
+{
+ return dtsec_set_tx_pause_frames(h_dtsec, 0, pause_time, 0);
+}
+
+static int dtsec_rx_ignore_mac_pause(void *h_dtsec, bool en)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+ bool accept_pause = !en;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_dtsec_handle_rx_pause(p_dtsec->p_mem_map, accept_pause);
+
+ return 0;
+}
+
+static int dtsec_modify_mac_address(void *h_dtsec, enet_addr_t
+ *p_enet_addr)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ /* Initialize MAC Station Address registers (1&2) */
+ /* Station address have to be swapped (big endian to little endian */
+ p_dtsec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
+ fman_dtsec_set_mac_address(p_dtsec->p_mem_map,
+ (uint8_t *)(*p_enet_addr));
+
+ return 0;
+}
+
+static int dtsec_add_hash_mac_address(void *h_dtsec,
+ enet_addr_t *p_eth_addr)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct eth_hash_entry_t *p_hash_entry;
+ uint64_t eth_addr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ ghtx = (bool)((fman_dtsec_get_rctrl(p_dtsec->p_mem_map) &
+ RCTRL_GHTX) ? true : false);
+ mcast = (bool)((eth_addr & MAC_GROUP_ADDRESS) ? true : false);
+
+ /* Cannot handle unicast mac addr when GHTX is on */
+ if (ghtx && !mcast) {
+ pr_err("Could not compute hash bucket\n");
+ return -ENOSYS;
+ }
+ crc = get_mac_addr_hash_code(eth_addr);
+
+ /* considering the 9 highest order bits in crc H[8:0]:
+ *if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register
+ *and H[5:1] (next 5 bits) identify the hash bit
+ *if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register
+ *and H[4:0] (next 5 bits) identify the hash bit.
+ *
+ *In bucket index output the low 5 bits identify the hash register
+ *bit, while the higher 4 bits identify the hash register
+ */
+
+ if (ghtx) {
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ } else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set in gaddr instead of
+ *igaddr.
+ */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket, true);
+
+ /* Create element to be added to the driver hash table */
+ p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+ if (!p_hash_entry)
+ return -ENOMEM;
+ p_hash_entry->addr = eth_addr;
+ INIT_LIST_HEAD(&p_hash_entry->node);
+
+ if (eth_addr & MAC_GROUP_ADDRESS)
+ /* Group Address */
+ list_add_tail(&p_hash_entry->node,
+ &(p_dtsec->p_multicast_addr_hash->p_lsts[bucket]
+ ));
+ else
+ list_add_tail(&p_hash_entry->node,
+ &p_dtsec->p_unicast_addr_hash->p_lsts[bucket]);
+
+ return 0;
+}
+
+static int dtsec_del_hash_mac_address(void *h_dtsec, enet_addr_t
+ *p_eth_addr)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct list_head *p_pos;
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+ uint64_t eth_addr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ ghtx =
+ (bool)((fman_dtsec_get_rctrl(p_dtsec->p_mem_map) & RCTRL_GHTX) ?
+ true : false);
+ mcast = (bool)((eth_addr & MAC_GROUP_ADDRESS) ? true : false);
+
+ /* Cannot handle unicast mac addr when GHTX is on */
+ if (ghtx && !mcast) {
+ pr_err("Could not compute hash bucket\n");
+ return -ENOSYS;
+ }
+ crc = get_mac_addr_hash_code(eth_addr);
+
+ if (ghtx) {
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ } else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set
+ * in gaddr instead of igaddr.
+ */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ if (eth_addr & MAC_GROUP_ADDRESS) {
+ /* Group Address */
+ list_for_each(p_pos,
+ &(p_dtsec->p_multicast_addr_hash->
+ p_lsts[bucket])) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_dtsec->p_multicast_addr_hash->p_lsts[bucket]))
+ fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket,
+ false);
+ } else {
+ /* Individual Address */
+ list_for_each(p_pos,
+ &p_dtsec->p_unicast_addr_hash->p_lsts[bucket]) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_dtsec->p_unicast_addr_hash->p_lsts[bucket]))
+ fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket,
+ false);
+ }
+
+ /* address does not exist */
+ ASSERT(p_hash_entry);
+
+ return 0;
+}
+
+static int dtsec_set_promiscuous(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_dtsec_set_uc_promisc(p_dtsec->p_mem_map, new_val);
+ fman_dtsec_set_mc_promisc(p_dtsec->p_mem_map, new_val);
+
+ return 0;
+}
+
+static int dtsec_adjust_link(void *h_dtsec, enum ethernet_speed speed)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int err;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ int ret, full_duplex = true;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ p_dtsec->enet_mode =
+ MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode), speed);
+ enet_interface =
+ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_dtsec->enet_mode);
+
+ err =
+ (int)fman_dtsec_adjust_link(p_dtsec->p_mem_map, enet_interface,
+ enet_speed, full_duplex);
+
+ if (err == -EINVAL) {
+ pr_err("Ethernet doesn't support Half Duplex mode\n");
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static int dtsec_restart_autoneg(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint16_t tmp_reg16;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ dtsec_mii_read_phy_reg(p_dtsec, p_dtsec->tbi_phy_addr, 0, &tmp_reg16);
+
+ tmp_reg16 &= ~(PHY_CR_SPEED0 | PHY_CR_SPEED1);
+ tmp_reg16 |=
+ (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+
+ dtsec_mii_write_phy_reg(p_dtsec, p_dtsec->tbi_phy_addr, 0, tmp_reg16);
+
+ return 0;
+}
+
+static int dtsec_get_id(void *h_dtsec, uint32_t *mac_id)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ *mac_id = p_dtsec->mac_id;
+
+ return 0;
+}
+
+static int dtsec_get_version(void *h_dtsec, uint32_t *mac_version)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ *mac_version = fman_dtsec_get_revision(p_dtsec->p_mem_map);
+
+ return 0;
+}
+
+static int dtsec_set_exception(void *h_dtsec,
+ enum fm_mac_exceptions exception,
+ bool enable)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) {
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_dtsec->exceptions |= bit_mask;
+ else
+ p_dtsec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ if (enable)
+ fman_dtsec_enable_interrupt(p_dtsec->p_mem_map,
+ bit_mask);
+ else
+ fman_dtsec_disable_interrupt(p_dtsec->p_mem_map,
+ bit_mask);
+ } else {
+ if (!p_dtsec->ptp_tsu_enabled) {
+ pr_err("Exception valid for 1588 only\n");
+ return -EDOM;
+ }
+ switch (exception) {
+ case (FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable) {
+ p_dtsec->en_tsu_err_exeption = true;
+ fman_dtsec_enable_tmr_interrupt(p_dtsec->
+ p_mem_map);
+ } else {
+ p_dtsec->en_tsu_err_exeption = false;
+ fman_dtsec_disable_tmr_interrupt(p_dtsec->
+ p_mem_map);
+ }
+ break;
+ default:
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ }
+
+ return 0;
+}
+
+/* dTSEC Init&Free API */
+
+static int dtsec_init(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct dtsec_cfg *p_dtsec_drv_param;
+ int err;
+ uint16_t max_frm_ln;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ enet_addr_t eth_addr;
+ int ret, ret_err;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return ret;
+
+ fm_get_revision(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ &p_dtsec->fm_mac_ctrl_drv.fm_rev_info);
+ ret_err = check_init_parameters(p_dtsec);
+ if (ret_err)
+ return -ret_err;
+
+ p_dtsec_drv_param = p_dtsec->p_dtsec_drv_param;
+
+ enet_interface =
+ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_dtsec->enet_mode);
+ MAKE_ENET_ADDR_FROM_UINT64(p_dtsec->addr, eth_addr);
+
+ err = (int)fman_dtsec_init(p_dtsec->p_mem_map,
+ p_dtsec_drv_param,
+ enet_interface,
+ enet_speed,
+ (uint8_t *)eth_addr,
+ p_dtsec->fm_mac_ctrl_drv.
+ fm_rev_info.major_rev,
+ p_dtsec->fm_mac_ctrl_drv.
+ fm_rev_info.minor_rev,
+ p_dtsec->exceptions);
+ if (err) {
+ free_init_resources(p_dtsec);
+ pr_err("DTSEC version doesn't support this i/f mode\n");
+ return err;
+ }
+
+ if (ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode) == ENET_IF_SGMII) {
+ uint16_t tmp_reg16;
+
+ /* Configure the TBI PHY Control Register */
+ tmp_reg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET;
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 17, tmp_reg16);
+
+ tmp_reg16 = PHY_TBICON_CLK_SEL;
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 17, tmp_reg16);
+
+ tmp_reg16 =
+ (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX |
+ PHY_CR_SPEED1);
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 0, tmp_reg16);
+
+ if (p_dtsec->enet_mode & ENET_IF_SGMII_BASEX)
+ tmp_reg16 = PHY_TBIANA_1000X;
+ else
+ tmp_reg16 = PHY_TBIANA_SGMII;
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 4, tmp_reg16);
+
+ tmp_reg16 =
+ (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX |
+ PHY_CR_SPEED1);
+
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 0, tmp_reg16);
+ }
+
+ /* Max Frame Length */
+ max_frm_ln = fman_dtsec_get_max_frame_len(p_dtsec->p_mem_map);
+ err = fm_set_mac_max_frame(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MAC_1G,
+ p_dtsec->fm_mac_ctrl_drv.mac_id,
+ max_frm_ln);
+ if (err) {
+ pr_err("Setting max frame length FAILED\n");
+ free_init_resources(p_dtsec);
+ return -EINVAL;
+ }
+
+ p_dtsec->p_multicast_addr_hash =
+ alloc_hash_table(EXTENDED_HASH_TABLE_SIZE);
+ if (!p_dtsec->p_multicast_addr_hash) {
+ free_init_resources(p_dtsec);
+ pr_err("MC hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ p_dtsec->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_dtsec->p_unicast_addr_hash) {
+ free_init_resources(p_dtsec);
+ pr_err("UC hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ /* register err intr handler for dtsec to FPM (err) */
+ fm_register_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_dtsec->mac_id,
+ FM_INTR_TYPE_ERR,
+ dtsec_isr,
+ p_dtsec);
+ /* register 1588 intr handler for TMR to FPM (normal) */
+ fm_register_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_dtsec->mac_id,
+ FM_INTR_TYPE_NORMAL,
+ dtsec_1588_isr,
+ p_dtsec);
+
+ kfree(p_dtsec_drv_param);
+ p_dtsec->p_dtsec_drv_param = NULL;
+
+ return 0;
+}
+
+static int dtsec_free(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+
+ free_init_resources(p_dtsec);
+
+ kfree(p_dtsec->p_dtsec_drv_param);
+ p_dtsec->p_dtsec_drv_param = NULL;
+ kfree(h_dtsec);
+
+ return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+ p_fm_mac_ctrl_drv)
+{
+ p_fm_mac_ctrl_drv->f_fm_mac_init = dtsec_init;
+ p_fm_mac_ctrl_drv->f_fm_mac_free = dtsec_free;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = dtsec_cfg_lb;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len =
+ dtsec_cfg_max_frame_len;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc =
+ dtsec_cfg_pad_and_crc;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = dtsec_cfg_len_check;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr = dtsec_cfg_tbi_phy_addr;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = dtsec_cfg_exception;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init = NULL;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_enable = dtsec_enable;
+ p_fm_mac_ctrl_drv->f_fm_mac_disable = dtsec_disable;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_exception = dtsec_set_exception;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = dtsec_set_promiscuous;
+ p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = dtsec_adjust_link;
+ p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = dtsec_restart_autoneg;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+ dtsec_tx_mac_pause;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames =
+ dtsec_set_tx_pause_frames;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+ dtsec_rx_ignore_mac_pause;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr =
+ dtsec_modify_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+ dtsec_add_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+ dtsec_del_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_id = dtsec_get_id;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_version = dtsec_get_version;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+ dtsec_get_max_frame_length;
+}
+
+/* d_tsec config main entry */
+
+void *dtsec_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct dtsec_t *p_dtsec;
+ struct dtsec_cfg *p_dtsec_drv_param;
+ uintptr_t base_addr;
+
+ base_addr = p_fm_mac_param->base_addr;
+
+ /* allocate memory for the UCC GETH data structure. */
+ p_dtsec = kzalloc(sizeof(*p_dtsec), GFP_KERNEL);
+ if (!p_dtsec)
+ return ERR_PTR(-ENOMEM);
+ init_fm_mac_ctrl_drv(&p_dtsec->fm_mac_ctrl_drv);
+
+ /* allocate memory for the d_tsec driver parameters data structure. */
+ p_dtsec_drv_param = kzalloc(sizeof(*p_dtsec_drv_param),
+ GFP_KERNEL);
+ if (!p_dtsec_drv_param) {
+ kfree(p_dtsec);
+ pr_err("dTSEC driver parameters");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Plant parameter structure pointer */
+ p_dtsec->p_dtsec_drv_param = p_dtsec_drv_param;
+
+ fman_dtsec_defconfig(p_dtsec_drv_param);
+
+ p_dtsec->p_mem_map = (struct dtsec_regs __iomem *)
+ UINT_TO_PTR(base_addr);
+ p_dtsec->p_mii_mem_map = (struct dtsec_mii_reg __iomem *)
+ UINT_TO_PTR(base_addr + DTSEC_TO_MII_OFFSET);
+ p_dtsec->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+ p_dtsec->enet_mode = p_fm_mac_param->enet_mode;
+ p_dtsec->mac_id = p_fm_mac_param->mac_id;
+ p_dtsec->exceptions = DEFAULT_exceptions;
+ p_dtsec->f_exception = p_fm_mac_param->f_exception;
+ p_dtsec->f_event = p_fm_mac_param->f_event;
+ p_dtsec->h_app = p_fm_mac_param->h_app;
+ p_dtsec->ptp_tsu_enabled = p_dtsec->p_dtsec_drv_param->ptp_tsu_en;
+ p_dtsec->en_tsu_err_exeption =
+ p_dtsec->p_dtsec_drv_param->ptp_exception_en;
+ p_dtsec->tbi_phy_addr = p_dtsec->p_dtsec_drv_param->tbi_phy_addr;
+
+ return p_dtsec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec.h b/drivers/net/ethernet/freescale/fman/mac/dtsec.h
new file mode 100644
index 0000000..723a7d2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec.h
@@ -0,0 +1,185 @@
+/*
+ * 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 dTSEC ... */
+#ifndef __DTSEC_H
+#define __DTSEC_
+
+#include "service.h"
+#include "enet_ext.h"
+
+#include "dtsec_mii_acc.h"
+#include "fm_mac.h"
+
+#define DEFAULT_exceptions \
+((uint32_t)(DTSEC_IMASK_BREN | \
+ DTSEC_IMASK_RXCEN | \
+ DTSEC_IMASK_BTEN | \
+ DTSEC_IMASK_TXCEN | \
+ DTSEC_IMASK_TXEEN | \
+ DTSEC_IMASK_ABRTEN | \
+ DTSEC_IMASK_LCEN | \
+ DTSEC_IMASK_CRLEN | \
+ DTSEC_IMASK_XFUNEN | \
+ DTSEC_IMASK_IFERREN | \
+ DTSEC_IMASK_MAGEN | \
+ DTSEC_IMASK_TDPEEN | \
+ DTSEC_IMASK_RDPEEN))
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+/*number of pattern match registers (entries) */
+#define DTSEC_NUM_OF_PADDRS 15
+
+/* Group address bit indication */
+#define GROUP_ADDRESS 0x0000010000000000LL
+
+/* Hash table size (32 bits*8 regs) */
+#define HASH_TABLE_SIZE 256
+/* Extended Hash table size (32 bits*16 regs) */
+#define EXTENDED_HASH_TABLE_SIZE 512
+
+/* number of pattern match registers (entries) */
+#define DTSEC_TO_MII_OFFSET 0x1000
+/* maximum number of phys */
+#define MAX_PHYS 32
+
+#define VAL32BIT 0x100000000LL
+#define VAL22BIT 0x00400000
+#define VAL16BIT 0x00010000
+#define VAL12BIT 0x00001000
+
+/* CAR1/2 bits */
+#define CAR1_TR64 0x80000000
+#define CAR1_TR127 0x40000000
+#define CAR1_TR255 0x20000000
+#define CAR1_TR511 0x10000000
+#define CAR1_TRK1 0x08000000
+#define CAR1_TRMAX 0x04000000
+#define CAR1_TRMGV 0x02000000
+
+#define CAR1_RBYT 0x00010000
+#define CAR1_RPKT 0x00008000
+#define CAR1_RMCA 0x00002000
+#define CAR1_RBCA 0x00001000
+#define CAR1_RXPF 0x00000400
+#define CAR1_RALN 0x00000100
+#define CAR1_RFLR 0x00000080
+#define CAR1_RCDE 0x00000040
+#define CAR1_RCSE 0x00000020
+#define CAR1_RUND 0x00000010
+#define CAR1_ROVR 0x00000008
+#define CAR1_RFRG 0x00000004
+#define CAR1_RJBR 0x00000002
+#define CAR1_RDRP 0x00000001
+
+#define CAR2_TFCS 0x00040000
+#define CAR2_TBYT 0x00002000
+#define CAR2_TPKT 0x00001000
+#define CAR2_TMCA 0x00000800
+#define CAR2_TBCA 0x00000400
+#define CAR2_TXPF 0x00000200
+#define CAR2_TDRP 0x00000001
+
+struct internal_statistics_t {
+ uint64_t tr64;
+ uint64_t tr127;
+ uint64_t tr255;
+ uint64_t tr511;
+ uint64_t tr1k;
+ uint64_t trmax;
+ uint64_t trmgv;
+ uint64_t rfrg;
+ uint64_t rjbr;
+ uint64_t rdrp;
+ uint64_t raln;
+ uint64_t rund;
+ uint64_t rovr;
+ uint64_t rxpf;
+ uint64_t txpf;
+ uint64_t rbyt;
+ uint64_t rpkt;
+ uint64_t rmca;
+ uint64_t rbca;
+ uint64_t rflr;
+ uint64_t rcde;
+ uint64_t rcse;
+ uint64_t tbyt;
+ uint64_t tpkt;
+ uint64_t tmca;
+ uint64_t tbca;
+ uint64_t tdrp;
+ uint64_t tfcs;
+};
+
+struct dtsec_t {
+ struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+ /* Handle to the upper layer application */
+ void *h_app;
+ /* pointer to dTSEC memory mapped registers. */
+ struct dtsec_regs __iomem *p_mem_map;
+ /* pointer to dTSEC MII memory mapped registers. */
+ struct dtsec_mii_reg __iomem *p_mii_mem_map;
+ /* MAC address of device; */
+ uint64_t addr;
+ /* Ethernet physical interface */
+ enum e_enet_mode enet_mode;
+ fm_mac_exception_cb *f_exception;
+ fm_mac_exception_cb *f_event;
+ /* Whether a particular individual address recognition
+ * register is being used
+ */
+ bool ind_addr_reg_used[DTSEC_NUM_OF_PADDRS];
+ /* MAC address for particular individual
+ * address recognition register
+ */
+ uint64_t paddr[DTSEC_NUM_OF_PADDRS];
+ /* Number of individual addresses in registers for this station. */
+ uint8_t num_of_ind_addr_in_regs;
+ struct internal_statistics_t internal_statistics;
+ /* pointer to driver's global address hash table */
+ struct eth_hash_t *p_multicast_addr_hash;
+ /* pointer to driver's individual address hash table */
+ struct eth_hash_t *p_unicast_addr_hash;
+ uint8_t mac_id;
+ uint8_t tbi_phy_addr;
+ uint32_t exceptions;
+ bool ptp_tsu_enabled;
+ bool en_tsu_err_exeption;
+ struct dtsec_cfg *p_dtsec_drv_param;
+};
+
+#endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
new file mode 100644
index 0000000..0b2ef14
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
@@ -0,0 +1,82 @@
+/*
+ * 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 dtsec MII register access MAC ... */
+
+#include "service.h"
+#include "fm_mac.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+int dtsec_mii_write_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t data)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct dtsec_mii_reg __iomem *miiregs;
+ uint16_t dtsec_freq;
+ int err;
+
+ dtsec_freq = (uint16_t)(p_dtsec->fm_mac_ctrl_drv.clk_freq >> 1);
+ miiregs = p_dtsec->p_mii_mem_map;
+
+ err =
+ (int)fman_dtsec_mii_write_reg(miiregs, phy_addr, reg, data,
+ dtsec_freq);
+
+ return err;
+}
+
+int dtsec_mii_read_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t *p_data)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct dtsec_mii_reg __iomem *miiregs;
+ uint16_t dtsec_freq;
+ int err;
+
+ dtsec_freq = (uint16_t)(p_dtsec->fm_mac_ctrl_drv.clk_freq >> 1);
+ miiregs = p_dtsec->p_mii_mem_map;
+
+ err =
+ (int)fman_dtsec_mii_read_reg(miiregs, phy_addr, reg, p_data,
+ dtsec_freq);
+
+ if (*p_data == 0xffff) {
+ pr_warn("Read wrong data(0xffff):phy_addr 0x%x,reg 0x%x",
+ phy_addr, reg);
+ return -ENXIO;
+ }
+ if (err)
+ return err;
+
+ return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
new file mode 100644
index 0000000..e599642
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
@@ -0,0 +1,43 @@
+/*
+ * 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 __DTSEC_MII_ACC_H
+#define __DTSEC_MII_ACC_H
+
+#include "service.h"
+
+int dtsec_mii_write_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t data);
+int dtsec_mii_read_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t *p_data);
+
+#endif /* __DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/fm_mac.c b/drivers/net/ethernet/freescale/fman/mac/fm_mac.c
new file mode 100644
index 0000000..8048446
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fm_mac.c
@@ -0,0 +1,510 @@
+/*
+ * 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 MAC ... */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "fm_ext.h"
+
+#include "fm_common.h"
+#include "fm_mac.h"
+
+#include <linux/string.h>
+
+struct fm_mac_dev *fm_mac_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct fm_mac_dev *fm_mac_dev;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv;
+ struct fm_revision_info_t fm_rev_info;
+
+ fm_get_revision(p_fm_mac_param->h_fm, &fm_rev_info);
+
+ if (fm_rev_info.major_rev >= 6) {
+ p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+ memac_config(p_fm_mac_param);
+ } else {
+ if (ENET_SPEED_FROM_MODE(p_fm_mac_param->enet_mode) <
+ ENET_SPEED_10000)
+ p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+ dtsec_config(p_fm_mac_param);
+ else if (ENET_SPEED_FROM_MODE(p_fm_mac_param->enet_mode) ==
+ ENET_SPEED_10000)
+ p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+ tgec_config(p_fm_mac_param);
+ else
+ p_fm_mac_ctrl_drv = NULL;
+ }
+
+ if (!p_fm_mac_ctrl_drv)
+ return NULL;
+
+ p_fm_mac_ctrl_drv->h_fm = p_fm_mac_param->h_fm;
+ p_fm_mac_ctrl_drv->enet_mode = p_fm_mac_param->enet_mode;
+ p_fm_mac_ctrl_drv->mac_id = p_fm_mac_param->mac_id;
+ p_fm_mac_ctrl_drv->reset_on_init = DEFAULT_RESET_ON_INIT;
+ p_fm_mac_ctrl_drv->fm_rev_info.major_rev = fm_rev_info.major_rev;
+ p_fm_mac_ctrl_drv->fm_rev_info.minor_rev = fm_rev_info.minor_rev;
+ p_fm_mac_ctrl_drv->clk_freq =
+ fm_get_clock_freq(p_fm_mac_ctrl_drv->h_fm);
+
+ if (p_fm_mac_ctrl_drv->clk_freq == 0) {
+ pr_err("Can't get clock for MAC!\n");
+ kfree(p_fm_mac_ctrl_drv);
+ return NULL;
+ }
+
+ fm_mac_dev = (void *)p_fm_mac_ctrl_drv;
+
+ return fm_mac_dev;
+}
+EXPORT_SYMBOL(fm_mac_config);
+
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->reset_on_init &&
+ !p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init &&
+ (fm_reset_mac(p_fm_mac_ctrl_drv->h_fm,
+ ((ENET_INTERFACE_FROM_MODE
+ (p_fm_mac_ctrl_drv->enet_mode) ==
+ ENET_IF_XGMII) ? FM_MAC_10G : FM_MAC_1G),
+ p_fm_mac_ctrl_drv->mac_id) != 0)) {
+ pr_err("Can't reset MAC!\n");
+ return -ENOSYS;
+ }
+ if (p_fm_mac_ctrl_drv->f_fm_mac_init)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_init(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_init() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_init);
+
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_free)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_free(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_free() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_free);
+
+int fm_mac_cfg_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init(fm_mac_dev,
+ enable);
+ else
+ err = 0;
+
+ p_fm_mac_ctrl_drv->reset_on_init = enable;
+ if (unlikely(err < 0))
+ pr_err("fm_mac_reset_on_init() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_reset_on_init);
+
+int fm_mac_cfg_max_frame_len(struct fm_mac_dev *fm_mac_dev, uint16_t new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_max_frame_len() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_max_frame_len);
+
+int fm_mac_cfg_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_init() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_pad_and_crc);
+
+int fm_mac_cfg_tbi_phy_addr(struct fm_mac_dev *fm_mac_dev, uint8_t new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_tbi_phy_addr() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_tbi_phy_addr);
+
+int fm_mac_cfg_len_check(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_len_check() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_len_check);
+
+int fm_mac_cfg_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception(fm_mac_dev,
+ ex,
+ enable);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_exception() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_exception);
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_mac_cfg_skip_fman11_wa(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_skip_fman11_wa)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_cfg_skip_fman11_wa(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_skip_fman11_wa() = 0x%08x\n",
+ err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_skip_fman11_wa);
+
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* Run Time Control */
+
+int fm_mac_enable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_enable)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_enable(fm_mac_dev, mode);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_enable() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_enable);
+
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_disable)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_disable(fm_mac_dev, mode);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_disable() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_disable);
+
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames)
+ return p_fm_mac_ctrl_drv->
+ f_fm_mac_set_tx_auto_pause_frames(fm_mac_dev, pause_time);
+
+ return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_set_tx_pause_frames);
+
+int fm_mac_set_rx_pause_frames(struct fm_mac_dev *fm_mac_dev, bool en)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_set_rx_ignore_pause_frames(fm_mac_dev, !en);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_set_rx_ignore_pause_frames() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_set_rx_pause_frames);
+
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_exception)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_set_exception(fm_mac_dev,
+ ex,
+ enable);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_set_exception() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_set_exception);
+
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr)
+ return p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr(fm_mac_dev,
+ p_enet_addr);
+
+ return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_modify_mac_addr);
+
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_add_hash_mac_addr(fm_mac_dev, p_enet_addr);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_add_hash_mac_addr() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_add_hash_mac_addr);
+
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_remove_hash_mac_addr(fm_mac_dev, p_enet_addr);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_remove_hash_mac_addr() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_remove_hash_mac_addr);
+
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev, uint32_t *mac_version)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_get_version)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_get_version(fm_mac_dev,
+ mac_version);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_version() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_get_version);
+
+int fm_mac_get_id(struct fm_mac_dev *fm_mac_dev, uint32_t *mac_id)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_get_id)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_get_id(fm_mac_dev, mac_id);
+ else
+ err = -ENOSYS;
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_id() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_get_id);
+
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_set_promiscuous(fm_mac_dev, new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_id() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_set_promiscuous);
+
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, int link,
+ enum ethernet_speed speed)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (!link) {
+ if (p_fm_mac_ctrl_drv->fm_rev_info.major_rev < 6)
+ fm_mac_restart_autoneg(fm_mac_dev);
+
+ return 0;
+ }
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_adjust_link)
+ return p_fm_mac_ctrl_drv->f_fm_mac_adjust_link(fm_mac_dev,
+ speed);
+
+ return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_adjust_link);
+
+int fm_mac_restart_autoneg(struct fm_mac_dev *fm_mac_dev)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg)
+ return p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg(fm_mac_dev);
+
+ return -ENOSYS;
+}
+
+uint16_t fm_mac_get_max_frame_length(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_get_max_frame_length(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_max_frame_length() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_get_max_frame_length);
diff --git a/drivers/net/ethernet/freescale/fman/mac/fm_mac.h b/drivers/net/ethernet/freescale/fman/mac/fm_mac.h
new file mode 100644
index 0000000..81fd563
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fm_mac.h
@@ -0,0 +1,183 @@
+/*
+ * 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 MAC ... */
+#ifndef __FM_MAC_H
+#define __FM_MAC_H
+
+#include "service.h"
+#include "fm_mac_ext.h"
+#include "fm_common.h"
+
+#include <linux/slab.h>
+
+/* defaults */
+
+#define DEFAULT_RESET_ON_INIT false
+
+struct eth_hash_entry_t {
+ uint64_t addr; /* Ethernet Address */
+ struct list_head node;
+};
+
+#define ETH_HASH_ENTRY_OBJ(ptr) list_object(ptr, struct eth_hash_entry_t, node)
+
+struct eth_hash_t {
+ uint16_t size;
+ struct list_head *p_lsts;
+};
+
+struct fm_mac_ctrl_drv_t {
+ int (*f_fm_mac_init)(void *h_fm_mac);
+ int (*f_fm_mac_free)(void *h_fm_mac);
+
+ int (*f_fm_mac_cfg_lb)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_cfg_max_frame_len)(void *h_fm_mac, uint16_t new_val);
+ int (*f_fm_mac_cfg_pad_and_crc)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_cfg_len_check)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_cfg_tbi_phy_addr)(void *h_fm_mac, uint8_t new_val);
+ int (*f_fm_mac_cfg_exception)(void *h_fm_mac,
+ enum fm_mac_exceptions, bool enable);
+ int (*f_fm_mac_cfg_reset_on_init)(void *h_fm_mac, bool enable);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ int (*f_fm_mac_cfg_skip_fman11_wa)(void *h_fm_mac);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ int (*f_fm_mac_set_exception)(void *h_fm_mac,
+ enum fm_mac_exceptions ex,
+ bool enable);
+
+ int (*f_fm_mac_enable)(void *h_fm_mac, enum comm_mode mode);
+ int (*f_fm_mac_disable)(void *h_fm_mac, enum comm_mode mode);
+ int (*f_fm_mac_reset)(void *h_fm_mac, bool wait);
+
+ int (*f_fm_mac_set_tx_auto_pause_frames)(void *h_fm_mac,
+ uint16_t pause_time);
+ int (*f_fm_mac_set_tx_pause_frames)(void *h_fm_mac,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time);
+ int (*f_fm_mac_set_rx_ignore_pause_frames)(void *h_fm_mac, bool en);
+
+ int (*f_fm_mac_modify_mac_addr)(void *h_fm_mac,
+ enet_addr_t *p_enet_addr);
+ int (*f_fm_mac_add_hash_mac_addr)(void *h_fm_mac,
+ enet_addr_t *p_enet_addr);
+ int (*f_fm_mac_remove_hash_mac_addr)(void *h_fm_mac,
+ enet_addr_t *p_enet_addr);
+ int (*f_fm_mac_set_promiscuous)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_adjust_link)(void *h_fm_mac,
+ enum ethernet_speed speed);
+ int (*f_fm_mac_restart_autoneg)(void *h_fm_mac);
+
+ int (*f_fm_mac_get_id)(void *h_fm_mac, uint32_t *mac_id);
+
+ int (*f_fm_mac_get_version)(void *h_fm_mac, uint32_t *mac_version);
+
+ uint16_t (*f_fm_mac_get_max_frame_length)(void *h_fm_mac);
+
+ void *h_fm;
+ struct fm_revision_info_t fm_rev_info;
+ enum e_enet_mode enet_mode;
+ uint8_t mac_id;
+ bool reset_on_init;
+ uint16_t clk_freq;
+};
+
+void *dtsec_config(struct fm_mac_params_t *p_fm_mac_param);
+void *tgec_config(struct fm_mac_params_t *p_fm_mac_params);
+void *memac_config(struct fm_mac_params_t *p_fm_mac_param);
+
+static inline struct eth_hash_entry_t
+*dequeue_addr_from_hash_entry(struct list_head *p_addr_lst)
+{
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+
+ if (!list_empty(p_addr_lst)) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_addr_lst->next);
+ list_del_init(&p_hash_entry->node);
+ }
+ return p_hash_entry;
+}
+
+static inline void free_hash_table(struct eth_hash_t *p_hash)
+{
+ struct eth_hash_entry_t *p_hash_entry;
+ int i = 0;
+
+ if (p_hash) {
+ if (p_hash->p_lsts) {
+ for (i = 0; i < p_hash->size; i++) {
+ p_hash_entry =
+ dequeue_addr_from_hash_entry(&p_hash->
+ p_lsts[i]);
+ while (p_hash_entry) {
+ kfree(p_hash_entry);
+ p_hash_entry =
+ dequeue_addr_from_hash_entry
+ (&p_hash->p_lsts[i]);
+ }
+ }
+
+ kfree(p_hash->p_lsts);
+ }
+
+ kfree(p_hash);
+ }
+}
+
+static inline struct eth_hash_t *alloc_hash_table(uint16_t size)
+{
+ uint32_t i;
+ struct eth_hash_t *p_hash;
+
+ /* Allocate address hash table */
+ p_hash = kmalloc_array(size, sizeof(struct eth_hash_t *), GFP_KERNEL);
+ if (!p_hash)
+ return NULL;
+
+ p_hash->size = size;
+
+ p_hash->p_lsts = kmalloc_array(p_hash->size, sizeof(struct list_head),
+ GFP_KERNEL);
+ if (!p_hash->p_lsts) {
+ kfree(p_hash);
+ return NULL;
+ }
+
+ for (i = 0; i < p_hash->size; i++)
+ INIT_LIST_HEAD(&p_hash->p_lsts[i]);
+
+ return p_hash;
+}
+
+#endif /* __FM_MAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac.c b/drivers/net/ethernet/freescale/fman/mac/memac.c
new file mode 100644
index 0000000..0f6c615
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac.c
@@ -0,0 +1,837 @@
+/*
+ * 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 mEMAC driver */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+
+#include "fm_common.h"
+#include "memac.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* Internal routine */
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+ uint64_t mask1, mask2;
+ uint32_t xor_val = 0;
+ uint8_t i, j;
+
+ for (i = 0; i < 6; i++) {
+ mask1 = eth_addr & (uint64_t)0x01;
+ eth_addr >>= 1;
+
+ for (j = 0; j < 7; j++) {
+ mask2 = eth_addr & (uint64_t)0x01;
+ mask1 ^= mask2;
+ eth_addr >>= 1;
+ }
+
+ xor_val |= (mask1 << (5 - i));
+ }
+
+ return xor_val;
+}
+
+static void setup_sgmii_internal_phy(struct memac_t *p_memac, uint8_t phy_addr)
+{
+ uint16_t tmp_reg16;
+ enum e_enet_mode enet_mode;
+
+ /* In case the higher MACs are used (i.e. the MACs that should
+ * support 10G), speed=10000 is provided for SGMII ports.
+ * Temporary modify enet mode to 1G one, so MII functions can
+ * work correctly.
+ */
+ enet_mode = p_memac->enet_mode;
+ p_memac->enet_mode =
+ MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+ ENET_SPEED_1000);
+
+ /* SGMII mode + AN enable */
+ tmp_reg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x14, tmp_reg16);
+
+ /* Device ability according to SGMII specification */
+ tmp_reg16 = PHY_SGMII_DEV_ABILITY_SGMII;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x4, tmp_reg16);
+
+ /* Adjust link timer for SGMII -
+ * According to Cisco SGMII specification the timer should be 1.6 ms.
+ * The link_timer register is configured in units of the clock.
+ * - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ * unit = 1 / (125*10^6 Hz) = 8 ns.
+ * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40
+ * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120.
+ * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ * we always set up here a value of 2.5 SGMII.
+ */
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x13, 0x0007);
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x12, 0xa120);
+
+ /* Restart AN */
+ tmp_reg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x0, tmp_reg16);
+
+ /* Restore original enet mode */
+ p_memac->enet_mode = enet_mode;
+}
+
+static void setup_sgmii_internal_phy_base_x(struct memac_t *p_memac,
+ uint8_t phy_addr)
+{
+ uint16_t tmp_reg16;
+ enum e_enet_mode enet_mode;
+
+ /* In case the higher MACs are used (i.e. the MACs that
+ * should support 10G), speed=10000 is provided for SGMII ports.
+ * Temporary modify enet mode to 1G one, so MII functions can
+ * work correctly.
+ */
+ enet_mode = p_memac->enet_mode;
+ p_memac->enet_mode =
+ MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+ ENET_SPEED_1000);
+
+ /* 1000BaseX mode */
+ tmp_reg16 = PHY_SGMII_IF_MODE_1000X;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x14, tmp_reg16);
+
+ /* AN Device capability */
+ tmp_reg16 = PHY_SGMII_DEV_ABILITY_1000X;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x4, tmp_reg16);
+
+ /* Adjust link timer for SGMII -
+ * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
+ * The link_timer register is configured in units of the clock.
+ * - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ * unit = 1 / (125*10^6 Hz) = 8 ns.
+ * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
+ * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
+ * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ * we always set up here a value of 2.5 SGMII.
+ */
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x13, 0x002f);
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x12, 0xaf08);
+
+ /* Restart AN */
+ tmp_reg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x0, tmp_reg16);
+
+ /* Restore original enet mode */
+ p_memac->enet_mode = enet_mode;
+}
+
+static int check_init_parameters(struct memac_t *p_memac)
+{
+ if (p_memac->addr == 0) {
+ pr_err("Ethernet MAC must have a valid MAC address\n");
+ return -EDOM;
+ }
+ if (!p_memac->f_exception) {
+ pr_err("Uninitialized f_exception\n");
+ return -EDOM;
+ }
+ if (!p_memac->f_event) {
+ pr_warn("Uninitialize f_event\n");
+ return -EDOM;
+ }
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_memac->p_memac_drv_param->no_length_check_enable) {
+ pr_err("LengthCheck!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+ uint32_t bit_mask;
+
+ switch (exception) {
+ case FM_MAC_EX_10G_1TX_ECC_ER:
+ bit_mask = MEMAC_IMASK_TECC_ER;
+ break;
+ case FM_MAC_EX_10G_RX_ECC_ER:
+ bit_mask = MEMAC_IMASK_RECC_ER;
+ break;
+ case FM_MAC_EX_TS_FIFO_ECC_ERR:
+ bit_mask = MEMAC_IMASK_TSECC_ER;
+ break;
+ case FM_MAC_EX_MAGIC_PACKET_INDICATION:
+ bit_mask = MEMAC_IMASK_MGI;
+ break;
+ default:
+ bit_mask = 0;
+ break;
+ }
+
+ return bit_mask;
+}
+
+static void memac_err_exception(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t event, imask;
+
+ event = fman_memac_get_event(p_memac->p_mem_map, 0xffffffff);
+ imask = fman_memac_get_interrupt_mask(p_memac->p_mem_map);
+
+ /* Imask include both error and notification/event bits.
+ * Leaving only error bits enabled by imask.
+ * The imask error bits are shifted by 16 bits offset from
+ * their corresponding location in the ievent - hence the >> 16
+ */
+ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+ fman_memac_ack_event(p_memac->p_mem_map, event);
+
+ if (event & MEMAC_IEVNT_TS_ECC_ER)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_TS_FIFO_ECC_ERR);
+ if (event & MEMAC_IEVNT_TX_ECC_ER)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & MEMAC_IEVNT_RX_ECC_ER)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_10G_RX_ECC_ER);
+}
+
+static void memac_exception(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t event, imask;
+
+ event = fman_memac_get_event(p_memac->p_mem_map, 0xffffffff);
+ imask = fman_memac_get_interrupt_mask(p_memac->p_mem_map);
+
+ /* Imask include both error and notification/event bits.
+ * Leaving only error bits enabled by imask.
+ * The imask error bits are shifted by 16 bits offset from
+ * their corresponding location in the ievent - hence the >> 16
+ */
+ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+ fman_memac_ack_event(p_memac->p_mem_map, event);
+
+ if (event & MEMAC_IEVNT_MGI)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_MAGIC_PACKET_INDICATION);
+}
+
+static void free_init_resources(struct memac_t *p_memac)
+{
+ fm_unregister_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_memac->mac_id,
+ FM_INTR_TYPE_ERR);
+
+ /* release the driver's group hash table */
+ free_hash_table(p_memac->p_multicast_addr_hash);
+ p_memac->p_multicast_addr_hash = NULL;
+
+ /* release the driver's individual hash table */
+ free_hash_table(p_memac->p_unicast_addr_hash);
+ p_memac->p_unicast_addr_hash = NULL;
+}
+
+/* Checks if p_memac driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct memac_cfg *p_memac_drv_parameters)
+{
+ if (!p_memac_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+/* mEMAC API routine */
+
+static int memac_enable(void *h_memac, enum comm_mode mode)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_enable(p_memac->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int memac_disable(void *h_memac, enum comm_mode mode)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_disable(p_memac->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int memac_set_promiscuous(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_set_promiscuous(p_memac->p_mem_map, new_val);
+
+ return 0;
+}
+
+static int memac_adjust_link(void *h_memac, enum ethernet_speed speed)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret, full_duplex = true;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_adjust_link(p_memac->p_mem_map,
+ (enum enet_interface)
+ ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+ (enum enet_speed)speed, full_duplex);
+ return 0;
+}
+
+/* memac configs modification function */
+
+static int memac_cfg_lb(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->loopback_enable = new_val;
+
+ return 0;
+}
+
+static int memac_cfg_max_frame_len(void *h_memac, uint16_t new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->max_frame_length = new_val;
+
+ return 0;
+}
+
+static int memac_cfg_pad(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->pad_enable = new_val;
+
+ return 0;
+}
+
+static int memac_cfg_len_check(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->no_length_check_enable = !new_val;
+
+ return 0;
+}
+
+static int memac_cfg_exception(void *h_memac,
+ enum fm_mac_exceptions exception, bool enable)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_memac->exceptions |= bit_mask;
+ else
+ p_memac->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ return 0;
+}
+
+static int memac_cfg_reset_on_init(void *h_memac, bool enable)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->reset_on_init = enable;
+
+ return 0;
+}
+
+/* memac run time api functions */
+
+static int memac_set_tx_auto_pause_frames(void *h_memac,
+ uint16_t pause_time)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ fman_memac_set_tx_pause_frames(p_memac->p_mem_map, FM_MAC_NO_PFC,
+ pause_time, 0);
+
+ return 0;
+}
+
+static int memac_set_rx_ignore_pause_frames(void *h_memac, bool en)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_set_rx_ignore_pause_frames(p_memac->p_mem_map, en);
+
+ return 0;
+}
+
+static int memac_modify_mac_address(void *h_memac,
+ enet_addr_t *p_enet_addr)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_add_addr_in_paddr(p_memac->p_mem_map,
+ (uint8_t *)(*p_enet_addr), 0);
+
+ return 0;
+}
+
+static int memac_add_hash_mac_address(void *h_memac,
+ enet_addr_t *p_eth_addr)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ struct eth_hash_entry_t *p_hash_entry;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ if (!(eth_addr & GROUP_ADDRESS)) {
+ /* Unicast addresses not supported in hash */
+ pr_err("Unicast Address\n");
+ return -ENOSYS;
+ }
+ hash = get_mac_addr_hash_code(eth_addr) & HASH_CTRL_ADDR_MASK;
+
+ /* Create element to be added to the driver hash table */
+ p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+ if (!p_hash_entry)
+ return -ENOMEM;
+ p_hash_entry->addr = eth_addr;
+ INIT_LIST_HEAD(&p_hash_entry->node);
+
+ list_add_tail(&p_hash_entry->node,
+ &p_memac->p_multicast_addr_hash->p_lsts[hash]);
+ fman_memac_set_hash_table(p_memac->p_mem_map,
+ (hash | HASH_CTRL_MCAST_EN));
+
+ return 0;
+}
+
+static int memac_del_hash_mac_address(void *h_memac,
+ enet_addr_t *p_eth_addr)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+ struct list_head *p_pos;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ hash = get_mac_addr_hash_code(eth_addr) & HASH_CTRL_ADDR_MASK;
+
+ list_for_each(p_pos, &p_memac->p_multicast_addr_hash->p_lsts[hash]) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_memac->p_multicast_addr_hash->p_lsts[hash]))
+ fman_memac_set_hash_table(p_memac->p_mem_map,
+ (hash & ~HASH_CTRL_MCAST_EN));
+
+ return 0;
+}
+
+static int memac_set_exception(void *h_memac,
+ enum fm_mac_exceptions exception,
+ bool enable)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_memac->exceptions |= bit_mask;
+ else
+ p_memac->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ fman_memac_set_exception(p_memac->p_mem_map, bit_mask, enable);
+
+ return 0;
+}
+
+static uint16_t memac_get_max_frame_length(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return 0;
+
+ return fman_memac_get_max_frame_len(p_memac->p_mem_map);
+}
+
+/* mEMAC Init & Free API */
+static int memac_init(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ struct memac_cfg *p_memac_drv_param;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ uint8_t i, phy_addr;
+ enet_addr_t eth_addr;
+ enum fm_mac_type port_type;
+ bool slow_10g_if = false;
+ int err, ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ err = check_init_parameters(p_memac);
+ if (err)
+ return err;
+
+ p_memac_drv_param = p_memac->p_memac_drv_param;
+
+ if (p_memac->fm_mac_ctrl_drv.fm_rev_info.major_rev == 6 &&
+ p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 4)
+ slow_10g_if = true;
+
+ port_type =
+ ((ENET_SPEED_FROM_MODE(p_memac->enet_mode) <
+ ENET_SPEED_10000) ? FM_MAC_1G : FM_MAC_10G);
+
+ /* First, reset the MAC if desired. */
+ if (p_memac_drv_param->reset_on_init)
+ fman_memac_reset(p_memac->p_mem_map);
+
+ /* MAC Address */
+ MAKE_ENET_ADDR_FROM_UINT64(p_memac->addr, eth_addr);
+ fman_memac_add_addr_in_paddr(p_memac->p_mem_map,
+ (uint8_t *)eth_addr, 0);
+
+ enet_interface =
+ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_memac->enet_mode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_memac->enet_mode);
+
+ fman_memac_init(p_memac->p_mem_map,
+ p_memac->p_memac_drv_param,
+ enet_interface,
+ enet_speed,
+ slow_10g_if,
+ p_memac->exceptions);
+
+#ifdef FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320
+ {
+ uint32_t tmp_reg = 0;
+
+ fm_get_revision(p_memac->fm_mac_ctrl_drv.h_fm,
+ &p_memac->fm_mac_ctrl_drv.fm_rev_info);
+ /* check the FMAN version - the bug exists only in rev1 */
+ if ((p_memac->fm_mac_ctrl_drv.fm_rev_info.major_rev == 6) &&
+ ((p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 0) ||
+ (p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 3))) {
+ /* MAC strips CRC from received frames - this
+ * workaround should decrease the likelihood of bug
+ * appearance
+ */
+ tmp_reg = GET_UINT32(p_memac->p_mem_map->
+ command_config);
+ tmp_reg &= ~CMD_CFG_CRC_FWD;
+ WRITE_UINT32(p_memac->p_mem_map->command_config,
+ tmp_reg);
+ }
+ }
+#endif /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 */
+
+ if (ENET_INTERFACE_FROM_MODE(p_memac->enet_mode) == ENET_IF_SGMII) {
+ /* Configure internal SGMII PHY */
+ if (p_memac->enet_mode & ENET_IF_SGMII_BASEX)
+ setup_sgmii_internal_phy_base_x(p_memac, PHY_MDIO_ADDR);
+ else
+ setup_sgmii_internal_phy(p_memac, PHY_MDIO_ADDR);
+ } else if (ENET_INTERFACE_FROM_MODE(p_memac->enet_mode) ==
+ ENET_IF_QSGMII) {
+ /* Configure 4 internal SGMII PHYs */
+ for (i = 0; i < 4; i++) {
+ /* QSGMII PHY address occupies 3 upper bits of 5-bit
+ * phy_address; the lower 2 bits are used to extend
+ * register address space and access each one of 4
+ * ports inside QSGMII.
+ */
+ phy_addr = (uint8_t)((PHY_MDIO_ADDR << 2) | i);
+ if (p_memac->enet_mode & ENET_IF_SGMII_BASEX)
+ setup_sgmii_internal_phy_base_x(p_memac,
+ phy_addr);
+ else
+ setup_sgmii_internal_phy(p_memac, phy_addr);
+ }
+ }
+
+ /* Max Frame Length */
+ err = fm_set_mac_max_frame(p_memac->fm_mac_ctrl_drv.h_fm,
+ port_type,
+ p_memac->fm_mac_ctrl_drv.mac_id,
+ p_memac_drv_param->max_frame_length);
+ if (err) {
+ pr_err("settings Mac max frame length is FAILED\n");
+ return err;
+ }
+
+ p_memac->p_multicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_memac->p_multicast_addr_hash) {
+ free_init_resources(p_memac);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ p_memac->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_memac->p_unicast_addr_hash) {
+ free_init_resources(p_memac);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ fm_register_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_memac->mac_id,
+ FM_INTR_TYPE_ERR,
+ memac_err_exception,
+ p_memac);
+
+ fm_register_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_memac->mac_id, FM_INTR_TYPE_NORMAL,
+ memac_exception, p_memac);
+
+ kfree(p_memac_drv_param);
+ p_memac->p_memac_drv_param = NULL;
+
+ return 0;
+}
+
+static int memac_free(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ free_init_resources(p_memac);
+
+ kfree(p_memac->p_memac_drv_param);
+ kfree(p_memac);
+
+ return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+ p_fm_mac_ctrl_drv)
+{
+ p_fm_mac_ctrl_drv->f_fm_mac_init = memac_init;
+ p_fm_mac_ctrl_drv->f_fm_mac_free = memac_free;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = memac_cfg_lb;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len =
+ memac_cfg_max_frame_len;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc = memac_cfg_pad;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = memac_cfg_len_check;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = memac_cfg_exception;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init =
+ memac_cfg_reset_on_init;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_exception = memac_set_exception;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = memac_set_promiscuous;
+ p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = memac_adjust_link;
+ p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = NULL;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_enable = memac_enable;
+ p_fm_mac_ctrl_drv->f_fm_mac_disable = memac_disable;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+ memac_set_tx_auto_pause_frames;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+ memac_set_rx_ignore_pause_frames;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr =
+ memac_modify_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+ memac_add_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+ memac_del_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_id = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_version = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+ memac_get_max_frame_length;
+}
+
+/* m_emac config main entry */
+
+void *memac_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct memac_t *p_memac;
+ struct memac_cfg *p_memac_drv_param;
+ uintptr_t base_addr;
+
+ base_addr = p_fm_mac_param->base_addr;
+ /* allocate memory for the m_emac data structure */
+ p_memac = kzalloc(sizeof(*p_memac), GFP_KERNEL);
+ if (!p_memac)
+ return NULL;
+
+ init_fm_mac_ctrl_drv(&p_memac->fm_mac_ctrl_drv);
+
+ /* allocate memory for the m_emac driver parameters data structure */
+ p_memac_drv_param = kzalloc(sizeof(*p_memac_drv_param),
+ GFP_KERNEL);
+ if (!p_memac_drv_param) {
+ memac_free(p_memac);
+ return NULL;
+ }
+
+ /* Plant parameter structure pointer */
+ p_memac->p_memac_drv_param = p_memac_drv_param;
+
+ fman_memac_defconfig(p_memac_drv_param);
+
+ p_memac->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+
+ p_memac->p_mem_map =
+ (struct memac_regs __iomem *)UINT_TO_PTR(base_addr);
+ p_memac->p_mii_mem_map = (struct memac_mii_access_mem_map __iomem *)
+ UINT_TO_PTR(base_addr + MEMAC_TO_MII_OFFSET);
+
+ p_memac->enet_mode = p_fm_mac_param->enet_mode;
+ p_memac->mac_id = p_fm_mac_param->mac_id;
+ p_memac->exceptions = MEMAC_default_exceptions;
+ p_memac->f_exception = p_fm_mac_param->f_exception;
+ p_memac->f_event = p_fm_mac_param->f_event;
+ p_memac->h_app = p_fm_mac_param->h_app;
+
+ return p_memac;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac.h b/drivers/net/ethernet/freescale/fman/mac/memac.h
new file mode 100644
index 0000000..9f0c607
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac.h
@@ -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.
+ */
+
+/* FM Multirate Ethernet MAC (mEMAC) */
+#ifndef __MEMAC_H
+#define __MEMAC_H
+
+#include "service.h"
+
+#include "fsl_fman_memac_mii_acc.h"
+#include "fm_mac.h"
+#include "fsl_fman_memac.h"
+
+#define MEMAC_default_exceptions\
+ ((uint32_t)(MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER |\
+ MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI))
+
+struct memac_t {
+ /* Upper Mac control block */
+ struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+ /* Handle to the upper layer application */
+ void *h_app;
+ /* Pointer to MAC memory mapped registers */
+ struct memac_regs __iomem *p_mem_map;
+ /* Pointer to MII memory mapped registers */
+ struct memac_mii_access_mem_map __iomem *p_mii_mem_map;
+ /* MAC address of device */
+ uint64_t addr;
+ /* Ethernet physical interface */
+ enum e_enet_mode enet_mode;
+ fm_mac_exception_cb *f_exception;
+ int mdio_irq;
+ fm_mac_exception_cb *f_event;
+ /* Whether a particular individual address
+ * recognition register is being used
+ */
+ bool ind_addr_reg_used[MEMAC_NUM_OF_PADDRS];
+ /* MAC address for particular individual address
+ * recognition register
+ */
+ uint64_t paddr[MEMAC_NUM_OF_PADDRS];
+ /* Number of individual addresses in registers for this station. */
+ uint8_t num_of_ind_addr_in_regs;
+ /* Pointer to driver's global address hash table */
+ struct eth_hash_t *p_multicast_addr_hash;
+ /* Pointer to driver's individual address hash table */
+ struct eth_hash_t *p_unicast_addr_hash;
+ bool debug_mode;
+ uint8_t mac_id;
+ uint32_t exceptions;
+ struct memac_cfg *p_memac_drv_param;
+};
+
+/* Internal PHY access */
+#define PHY_MDIO_ADDR 0
+
+/* Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_RESET_AN 0x0200
+#define PHY_SGMII_CR_DEF_VAL 0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0
+#define PHY_SGMII_IF_MODE_AN 0x0002
+#define PHY_SGMII_IF_MODE_SGMII 0x0001
+#define PHY_SGMII_IF_MODE_1000X 0x0000
+
+/* Offset from the MEM map to the MDIO mem map */
+#define MEMAC_TO_MII_OFFSET 0x030
+
+int memac_mii_write_phy_reg(void *h_memac, uint8_t phy_addr, uint8_t reg,
+ uint16_t data);
+int memac_mii_read_phy_reg(void *h_memac, uint8_t phy_addr, uint8_t reg,
+ uint16_t *p_data);
+
+#endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
new file mode 100644
index 0000000..0150e9d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
@@ -0,0 +1,66 @@
+/*
+ * 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 "fm_mac.h"
+#include "memac.h"
+
+#include "fm_common.h"
+#include "memac_mii_acc.h"
+
+int memac_mii_write_phy_reg(void *h_memac,
+ uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ return (int)fman_memac_mii_write_phy_reg(p_memac->p_mii_mem_map,
+ phy_addr,
+ reg,
+ data,
+ (enum enet_speed)
+ ENET_SPEED_FROM_MODE
+ (p_memac->enet_mode));
+}
+
+int memac_mii_read_phy_reg(void *h_memac,
+ uint8_t phy_addr, uint8_t reg, uint16_t *p_data)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ return fman_memac_mii_read_phy_reg(p_memac->p_mii_mem_map,
+ phy_addr,
+ reg,
+ p_data,
+ (enum enet_speed)
+ ENET_SPEED_FROM_MODE(p_memac->
+ enet_mode));
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
new file mode 100644
index 0000000..f38572c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
@@ -0,0 +1,50 @@
+/*
+ * 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 __MEMAC_MII_ACC_H
+#define __MEMAC_MII_ACC_H
+
+#include "service.h"
+
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK 0x0080ff80
+#define MDIO_CFG_HOLD_MASK 0x0000001c
+#define MDIO_CFG_ENC45 0x00000040
+#define MDIO_CFG_READ_ERR 0x00000002
+#define MDIO_CFG_BSY 0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT 5
+#define MDIO_CTL_READ 0x00008000
+
+#define MDIO_DATA_BSY 0x80000000
+
+#endif /* __MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec.c b/drivers/net/ethernet/freescale/fman/mac/tgec.c
new file mode 100644
index 0000000..30b0078
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec.c
@@ -0,0 +1,797 @@
+/*
+ * 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.
+ */
+
+/* TGEC MAC ... */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "fsl_fman_tgec.h"
+#include "tgec.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/bitrev.h>
+
+/* Internal routines */
+
+static int check_init_parameters(struct tgec_t *p_tgec)
+{
+ if (ENET_SPEED_FROM_MODE(p_tgec->enet_mode) < ENET_SPEED_10000) {
+ pr_err("10G MAC driver only support 10G speed\n");
+ return -EDOM;
+ }
+ if (p_tgec->addr == 0) {
+ pr_err("Ethernet 10G MAC Must have valid MAC Address\n");
+ return -EDOM;
+ }
+ if (!p_tgec->f_exception) {
+ pr_err("uninitialized f_exception\n");
+ return -EDOM;
+ }
+ if (!p_tgec->f_event) {
+ pr_err("uninitialized f_event\n");
+ return -EDOM;
+ }
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_tgec->p_tgec_drv_param->no_length_check_enable) {
+ pr_warn("LengthCheck!\n");
+ return -EDOM;
+ }
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+ return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+ uint32_t bit_mask;
+
+ switch (exception) {
+ case FM_MAC_EX_10G_MDIO_SCAN_EVENT:
+ bit_mask = TGEC_IMASK_MDIO_SCAN_EVENT;
+ break;
+ case FM_MAC_EX_10G_MDIO_CMD_CMPL:
+ bit_mask = TGEC_IMASK_MDIO_CMD_CMPL;
+ break;
+ case FM_MAC_EX_10G_REM_FAULT:
+ bit_mask = TGEC_IMASK_REM_FAULT;
+ break;
+ case FM_MAC_EX_10G_LOC_FAULT:
+ bit_mask = TGEC_IMASK_LOC_FAULT;
+ break;
+ case FM_MAC_EX_10G_1TX_ECC_ER:
+ bit_mask = TGEC_IMASK_TX_ECC_ER;
+ break;
+ case FM_MAC_EX_10G_TX_FIFO_UNFL:
+ bit_mask = TGEC_IMASK_TX_FIFO_UNFL;
+ break;
+ case FM_MAC_EX_10G_TX_FIFO_OVFL:
+ bit_mask = TGEC_IMASK_TX_FIFO_OVFL;
+ break;
+ case FM_MAC_EX_10G_TX_ER:
+ bit_mask = TGEC_IMASK_TX_ER;
+ break;
+ case FM_MAC_EX_10G_RX_FIFO_OVFL:
+ bit_mask = TGEC_IMASK_RX_FIFO_OVFL;
+ break;
+ case FM_MAC_EX_10G_RX_ECC_ER:
+ bit_mask = TGEC_IMASK_RX_ECC_ER;
+ break;
+ case FM_MAC_EX_10G_RX_JAB_FRM:
+ bit_mask = TGEC_IMASK_RX_JAB_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_OVRSZ_FRM:
+ bit_mask = TGEC_IMASK_RX_OVRSZ_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_RUNT_FRM:
+ bit_mask = TGEC_IMASK_RX_RUNT_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_FRAG_FRM:
+ bit_mask = TGEC_IMASK_RX_FRAG_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_LEN_ER:
+ bit_mask = TGEC_IMASK_RX_LEN_ER;
+ break;
+ case FM_MAC_EX_10G_RX_CRC_ER:
+ bit_mask = TGEC_IMASK_RX_CRC_ER;
+ break;
+ case FM_MAC_EX_10G_RX_ALIGN_ER:
+ bit_mask = TGEC_IMASK_RX_ALIGN_ER;
+ break;
+ default:
+ bit_mask = 0;
+ break;
+ }
+
+ return bit_mask;
+}
+
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(eth_addr, crc);
+
+ crc = bitrev32(crc);
+
+ return crc;
+}
+
+static void tgec_err_exception(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ uint32_t event;
+ struct tgec_regs __iomem *p_tgec_mem_map = p_tgec->p_mem_map;
+
+ /* do not handle MDIO events */
+ event =
+ fman_tgec_get_event(p_tgec_mem_map,
+ ~(TGEC_IMASK_MDIO_SCAN_EVENT |
+ TGEC_IMASK_MDIO_CMD_CMPL));
+ event &= fman_tgec_get_interrupt_mask(p_tgec_mem_map);
+
+ fman_tgec_ack_event(p_tgec_mem_map, event);
+
+ if (event & TGEC_IMASK_REM_FAULT)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_REM_FAULT);
+ if (event & TGEC_IMASK_LOC_FAULT)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_LOC_FAULT);
+ if (event & TGEC_IMASK_TX_ECC_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & TGEC_IMASK_TX_FIFO_UNFL)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_TX_FIFO_UNFL);
+ if (event & TGEC_IMASK_TX_FIFO_OVFL)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_TX_FIFO_OVFL);
+ if (event & TGEC_IMASK_TX_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_TX_ER);
+ if (event & TGEC_IMASK_RX_FIFO_OVFL)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_RX_FIFO_OVFL);
+ if (event & TGEC_IMASK_RX_ECC_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_ECC_ER);
+ if (event & TGEC_IMASK_RX_JAB_FRM)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_JAB_FRM);
+ if (event & TGEC_IMASK_RX_OVRSZ_FRM)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_RX_OVRSZ_FRM);
+ if (event & TGEC_IMASK_RX_RUNT_FRM)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_RUNT_FRM);
+ if (event & TGEC_IMASK_RX_FRAG_FRM)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_FRAG_FRM);
+ if (event & TGEC_IMASK_RX_LEN_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_LEN_ER);
+ if (event & TGEC_IMASK_RX_CRC_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_CRC_ER);
+ if (event & TGEC_IMASK_RX_ALIGN_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_ALIGN_ER);
+}
+
+static void free_init_resources(struct tgec_t *p_tgec)
+{
+ fm_unregister_intr(p_tgec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC, p_tgec->mac_id, FM_INTR_TYPE_ERR);
+
+ /* release the driver's group hash table */
+ free_hash_table(p_tgec->p_multicast_addr_hash);
+ p_tgec->p_multicast_addr_hash = NULL;
+
+ /* release the driver's individual hash table */
+ free_hash_table(p_tgec->p_unicast_addr_hash);
+ p_tgec->p_unicast_addr_hash = NULL;
+}
+
+/* Checks if p_tgec driver parameters were initialized
+ * returns 0 if success else returns error
+ */
+static int is_init_done(struct tgec_cfg *p_tgec_drv_parameters)
+{
+ if (!p_tgec_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+/* TGEC MAC API routines */
+static int tgec_enable(void *h_tgec, enum comm_mode mode)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_enable(p_tgec->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int tgec_disable(void *h_tgec, enum comm_mode mode)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_disable(p_tgec->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int tgec_set_promiscuous(void *h_tgec, bool new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_promiscuous(p_tgec->p_mem_map, new_val);
+
+ return 0;
+}
+
+/* tgec configs modification functions */
+
+static int tgec_cfg_lb(void *h_tgec, bool new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->loopback_enable = new_val;
+
+ return 0;
+}
+
+static int tgec_cfg_max_frame_len(void *h_tgec, uint16_t new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->max_frame_length = new_val;
+
+ return 0;
+}
+
+static int tgec_cfg_len_check(void *h_tgec, bool __maybe_unused new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->no_length_check_enable = !new_val;
+
+ return 0;
+}
+
+static int tgec_cfg_exception(void *h_tgec,
+ enum fm_mac_exceptions exception, bool enable)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_tgec->exceptions |= bit_mask;
+ else
+ p_tgec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ return 0;
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+
+static int tgec_cfg_skip_fman11_wa(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->skip_fman11_workaround = true;
+
+ return 0;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* tgec run time api functions */
+
+/* backward compatibility. will be removed in the future. */
+static int tgec_tx_mac_pause(void *h_tgec, uint16_t pause_time)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_tx_pause_frames(p_tgec->p_mem_map, pause_time);
+
+ return 0;
+}
+
+static int tgec_set_tx_pause_frames(void *h_tgec,
+ uint8_t __maybe_unused priority,
+ uint16_t pause_time,
+ uint16_t __maybe_unused thresh_time)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_tx_pause_frames(p_tgec->p_mem_map, pause_time);
+
+ return 0;
+}
+
+static int tgec_rx_ignore_mac_pause(void *h_tgec, bool en)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_rx_ignore_pause_frames(p_tgec->p_mem_map, en);
+
+ return 0;
+}
+
+static int tgec_modify_mac_address(void *h_tgec, enet_addr_t
+ *p_enet_addr)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ p_tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
+ fman_tgec_set_mac_address(p_tgec->p_mem_map, (uint8_t *)(*p_enet_addr));
+
+ return 0;
+}
+
+static int tgec_add_hash_mac_address(void *h_tgec, enet_addr_t
+ *p_eth_addr)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ struct eth_hash_entry_t *p_hash_entry;
+ uint32_t crc;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ if (!(eth_addr & GROUP_ADDRESS)) {
+ /* Unicast addresses not supported in hash */
+ pr_err("Unicast Address\n");
+ return -ENOSYS;
+ }
+ /* CRC calculation */
+ crc = get_mac_addr_hash_code(eth_addr);
+
+ /* Take 9 MSB bits */
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;
+
+ /* Create element to be added to the driver hash table */
+ p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+ if (!p_hash_entry)
+ return -ENOMEM;
+ p_hash_entry->addr = eth_addr;
+ INIT_LIST_HEAD(&p_hash_entry->node);
+
+ list_add_tail(&p_hash_entry->node,
+ &p_tgec->p_multicast_addr_hash->p_lsts[hash]);
+ fman_tgec_set_hash_table(p_tgec->p_mem_map,
+ (hash | TGEC_HASH_MCAST_EN));
+
+ return 0;
+}
+
+static int tgec_del_hash_mac_address(void *h_tgec, enet_addr_t
+ *p_eth_addr)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+ struct list_head *p_pos;
+ uint32_t crc;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ((*(uint64_t *)p_eth_addr) >> 16);
+
+ /* CRC calculation */
+ crc = get_mac_addr_hash_code(eth_addr);
+ /* Take 9 MSB bits */
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;
+
+ list_for_each(p_pos, &p_tgec->p_multicast_addr_hash->p_lsts[hash]) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_tgec->p_multicast_addr_hash->p_lsts[hash]))
+ fman_tgec_set_hash_table(p_tgec->p_mem_map,
+ (hash & ~TGEC_HASH_MCAST_EN));
+
+ return 0;
+}
+
+static int tgec_get_id(void *h_tgec,
+ uint32_t __maybe_unused *mac_id)
+{
+ struct tgec_t __maybe_unused *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ pr_warn("tgec_get_id not supported\n");
+ return -ENOSYS;
+}
+
+static int tgec_get_version(void *h_tgec, uint32_t *mac_version)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ *mac_version = fman_tgec_get_revision(p_tgec->p_mem_map);
+
+ return 0;
+}
+
+static int tgec_set_excpetion(void *h_tgec,
+ enum fm_mac_exceptions exception,
+ bool enable)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_tgec->exceptions |= bit_mask;
+ else
+ p_tgec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ if (enable)
+ fman_tgec_enable_interrupt(p_tgec->p_mem_map, bit_mask);
+ else
+ fman_tgec_disable_interrupt(p_tgec->p_mem_map, bit_mask);
+
+ return 0;
+}
+
+static uint16_t tgec_get_max_frame_length(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return 0;
+
+ return fman_tgec_get_max_frame_len(p_tgec->p_mem_map);
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+static int tgec_tx_ecc_workaround(struct tgec_t *p_tgec)
+{
+ int err;
+
+ pr_info("Applying 10G TX ECC workaround (10GMAC-A004) ... ");
+
+ /* enable and set promiscuous */
+ fman_tgec_enable(p_tgec->p_mem_map, true, true);
+ fman_tgec_set_promiscuous(p_tgec->p_mem_map, true);
+ err =
+ fm_10g_tx_ecc_workaround(p_tgec->fm_mac_ctrl_drv.h_fm,
+ p_tgec->mac_id);
+ /* disable */
+ fman_tgec_set_promiscuous(p_tgec->p_mem_map, false);
+ fman_tgec_enable(p_tgec->p_mem_map, false, false);
+ fman_tgec_ack_event(p_tgec->p_mem_map, 0xffffffff);
+
+ if (err)
+ pr_err("FAILED!\n");
+ else
+ pr_info("done.\n");
+
+ return err;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* FM Init&Free API */
+
+static int tgec_init(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ struct tgec_cfg *p_tgec_drv_param;
+ enet_addr_t eth_addr;
+ int err, ret, ret_err;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ fm_get_revision(p_tgec->fm_mac_ctrl_drv.h_fm,
+ &p_tgec->fm_mac_ctrl_drv.fm_rev_info);
+ ret_err = check_init_parameters(p_tgec);
+ if (ret_err)
+ return ret_err;
+
+ p_tgec_drv_param = p_tgec->p_tgec_drv_param;
+
+ MAKE_ENET_ADDR_FROM_UINT64(p_tgec->addr, eth_addr);
+ fman_tgec_set_mac_address(p_tgec->p_mem_map, (uint8_t *)eth_addr);
+
+ /* interrupts */
+#ifdef FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005
+ {
+ if (p_tgec->fm_mac_ctrl_drv.fm_rev_info.major_rev <= 2)
+ p_tgec->exceptions &=
+ ~(TGEC_IMASK_REM_FAULT | TGEC_IMASK_LOC_FAULT);
+ }
+#endif /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 */
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ if (!p_tgec->p_tgec_drv_param->skip_fman11_workaround) {
+ err = tgec_tx_ecc_workaround(p_tgec);
+ if (err != 0) {
+ free_init_resources(p_tgec);
+ pr_warn("tgec_tx_ecc_workaround failed\n");
+ }
+ }
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ err =
+ fman_tgec_init(p_tgec->p_mem_map, p_tgec_drv_param,
+ p_tgec->exceptions);
+ if (err) {
+ free_init_resources(p_tgec);
+ pr_err("TGEC version doesn't support this i/f mode\n");
+ return err;
+ }
+
+ /* Max Frame Length */
+ err = fm_set_mac_max_frame(p_tgec->fm_mac_ctrl_drv.h_fm,
+ FM_MAC_10G,
+ p_tgec->fm_mac_ctrl_drv.mac_id,
+ p_tgec_drv_param->max_frame_length);
+ if (err) {
+ pr_err("Setting max frame length FAILED\n");
+ free_init_resources(p_tgec);
+ return -EINVAL;
+ }
+
+#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007
+ if (p_tgec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(p_tgec->
+ p_mem_map);
+#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */
+
+ p_tgec->p_multicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_tgec->p_multicast_addr_hash) {
+ free_init_resources(p_tgec);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ p_tgec->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_tgec->p_unicast_addr_hash) {
+ free_init_resources(p_tgec);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ fm_register_intr(p_tgec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_tgec->mac_id,
+ FM_INTR_TYPE_ERR, tgec_err_exception, p_tgec);
+
+ kfree(p_tgec_drv_param);
+ p_tgec->p_tgec_drv_param = NULL;
+
+ return 0;
+}
+
+static int tgec_free(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+
+ free_init_resources(p_tgec);
+
+ if (p_tgec->p_tgec_drv_param)
+ p_tgec->p_tgec_drv_param = NULL;
+
+ kfree(p_tgec->p_tgec_drv_param);
+ kfree(p_tgec);
+
+ return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+ p_fm_mac_ctrl_drv)
+{
+ p_fm_mac_ctrl_drv->f_fm_mac_init = tgec_init;
+ p_fm_mac_ctrl_drv->f_fm_mac_free = tgec_free;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = tgec_cfg_lb;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len = tgec_cfg_max_frame_len;
+
+ /* tgec always works with pad+crc */
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc = NULL;
+ /* half-duplex is not supported in xgec */
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = tgec_cfg_len_check;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = tgec_cfg_exception;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init = NULL;
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_skip_fman11_wa =
+ tgec_cfg_skip_fman11_wa;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_exception = tgec_set_excpetion;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = tgec_set_promiscuous;
+ p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = NULL;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_enable = tgec_enable;
+ p_fm_mac_ctrl_drv->f_fm_mac_disable = tgec_disable;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+ tgec_tx_mac_pause;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames =
+ tgec_set_tx_pause_frames;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+ tgec_rx_ignore_mac_pause;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr = tgec_modify_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+ tgec_add_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+ tgec_del_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_id = tgec_get_id;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_version = tgec_get_version;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+ tgec_get_max_frame_length;
+}
+
+/* tgec config main entry */
+
+void *tgec_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct tgec_t *p_tgec;
+ struct tgec_cfg *p_tgec_drv_param;
+ uintptr_t base_addr;
+
+ base_addr = p_fm_mac_param->base_addr;
+ /* allocate memory for the UCC GETH data structure. */
+ p_tgec = kzalloc(sizeof(*p_tgec), GFP_KERNEL);
+ if (!p_tgec)
+ return NULL;
+
+ init_fm_mac_ctrl_drv(&p_tgec->fm_mac_ctrl_drv);
+
+ /* allocate memory for the 10G MAC driver parameters data structure. */
+ p_tgec_drv_param = kzalloc(sizeof(*p_tgec_drv_param), GFP_KERNEL);
+ if (!p_tgec_drv_param) {
+ tgec_free(p_tgec);
+ return NULL;
+ }
+
+ /* Plant parameter structure pointer */
+ p_tgec->p_tgec_drv_param = p_tgec_drv_param;
+
+ fman_tgec_defconfig(p_tgec_drv_param);
+
+ p_tgec->p_mem_map = (struct tgec_regs __iomem *)UINT_TO_PTR(base_addr);
+ p_tgec->p_mii_mem_map = (struct tgec_mii_access_mem_map_t *)
+ UINT_TO_PTR(base_addr + TGEC_TO_MII_OFFSET);
+ p_tgec->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+ p_tgec->enet_mode = p_fm_mac_param->enet_mode;
+ p_tgec->mac_id = p_fm_mac_param->mac_id;
+ p_tgec->exceptions = DEFAULT_exceptions;
+ p_tgec->f_exception = p_fm_mac_param->f_exception;
+ p_tgec->f_event = p_fm_mac_param->f_event;
+ p_tgec->h_app = p_fm_mac_param->h_app;
+
+ return p_tgec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec.h b/drivers/net/ethernet/freescale/fman/mac/tgec.h
new file mode 100644
index 0000000..f839250
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec.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.
+ */
+
+/* TGEC MAC ... */
+#ifndef __TGEC_H
+#define __TGEC_H
+
+#include "service.h"
+#include "enet_ext.h"
+
+#include "tgec_mii_acc.h"
+#include "fm_mac.h"
+
+#define DEFAULT_exceptions\
+ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT |\
+ TGEC_IMASK_REM_FAULT |\
+ TGEC_IMASK_LOC_FAULT |\
+ TGEC_IMASK_TX_ECC_ER |\
+ TGEC_IMASK_TX_FIFO_UNFL |\
+ TGEC_IMASK_TX_FIFO_OVFL |\
+ TGEC_IMASK_TX_ER |\
+ TGEC_IMASK_RX_FIFO_OVFL |\
+ TGEC_IMASK_RX_ECC_ER |\
+ TGEC_IMASK_RX_JAB_FRM |\
+ TGEC_IMASK_RX_OVRSZ_FRM |\
+ TGEC_IMASK_RX_RUNT_FRM |\
+ TGEC_IMASK_RX_FRAG_FRM |\
+ TGEC_IMASK_RX_CRC_ER |\
+ TGEC_IMASK_RX_ALIGN_ER))
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+/* number of pattern match registers (entries) */
+#define TGEC_NUM_OF_PADDRS 1
+
+/* Group address bit indication */
+#define GROUP_ADDRESS 0x0000010000000000LL
+
+#define HASH_TABLE_SIZE 512 /* Hash table size (= 32 bits*8 regs)*/
+
+/* Offset from the MEM map to the MDIO mem map */
+#define TGEC_TO_MII_OFFSET 0x1030
+
+struct tgec_t {
+ /* Upper Mac control block */
+ struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+ /* Handle to the upper layer application */
+ void *h_app;
+ /* pointer to 10G memory mapped registers. */
+ struct tgec_regs __iomem *p_mem_map;
+ /* pointer to MII memory mapped registers. */
+ struct tgec_mii_access_mem_map_t *p_mii_mem_map;
+ /* MAC address of device; */
+ uint64_t addr;
+ /* Ethernet physical interface */
+ enum e_enet_mode enet_mode;
+ fm_mac_exception_cb *f_exception;
+ fm_mac_exception_cb *f_event;
+ /* Whether a particular individual address recognition
+ * register is being used
+ */
+ bool ind_addr_reg_used[TGEC_NUM_OF_PADDRS];
+ /* MAC address for particular individual address
+ * recognition register
+ */
+ uint64_t paddr[TGEC_NUM_OF_PADDRS];
+ /* Number of individual addresses in registers for this station. */
+ uint8_t num_of_ind_addr_in_regs;
+ /* pointer to driver's global address hash table */
+ struct eth_hash_t *p_multicast_addr_hash;
+ /* pointer to driver's individual address hash table */
+ struct eth_hash_t *p_unicast_addr_hash;
+ bool debug_mode;
+ uint8_t mac_id;
+ uint32_t exceptions;
+ struct tgec_cfg *p_tgec_drv_param;
+};
+
+#endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
new file mode 100644
index 0000000..4ea9b35
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
@@ -0,0 +1,66 @@
+/*
+ * 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 __TGEC_MII_ACC_H
+#define __TGEC_MII_ACC_H
+
+#include "service.h"
+
+/* MII Management Command Register */
+#define MIIMCOM_READ_POST_INCREMENT 0x00004000
+#define MIIMCOM_READ_CYCLE 0x00008000
+#define MIIMCOM_SCAN_CYCLE 0x00000800
+#define MIIMCOM_PREAMBLE_DISABLE 0x00000400
+
+#define MIIMCOM_MDIO_HOLD_1_REG_CLK 0
+#define MIIMCOM_MDIO_HOLD_2_REG_CLK 1
+#define MIIMCOM_MDIO_HOLD_3_REG_CLK 2
+#define MIIMCOM_MDIO_HOLD_4_REG_CLK 3
+
+#define MIIMCOM_DIV_MASK 0x0000ff00
+#define MIIMCOM_DIV_SHIFT 8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_READ_ERROR 0x00000002
+
+#define MIIDATA_BUSY 0x80000000
+
+/* MII Configuration Control Memory Map Registers */
+struct tgec_mii_access_mem_map_t {
+ uint32_t mdio_cfg_status; /* 0x030 */
+ uint32_t mdio_command; /* 0x034 */
+ uint32_t mdio_data; /* 0x038 */
+ uint32_t mdio_regaddr; /* 0x03c */
+} __attribute__((__packed__));
+
+#endif /* __TGEC_MII_ACC_H */
--
1.7.9.5
_______________________________________________
Linuxppc-dev mailing list
Linuxppc-dev@lists.ozlabs.org
https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 01/12] fsl/fman: Add the FMan FLIB headers
@ 2015-05-07 13:05 Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 02/12] fsl/fman: Add the FMan FLIB Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
This patch presents the FMan Foundation Libraries (FLIB) headers.
The FMan FLib provides the basic API used by the FMan drivers to
configure and control the FMan hardware.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
.../ethernet/freescale/fman/flib/common/general.h | 41 ++
.../net/ethernet/freescale/fman/flib/fsl_fman.h | 743 +++++++++++++++++++++
2 files changed, 784 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/fman/flib/common/general.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman.h
diff --git a/drivers/net/ethernet/freescale/fman/flib/common/general.h b/drivers/net/ethernet/freescale/fman/flib/common/general.h
new file mode 100644
index 0000000..0501f01
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/common/general.h
@@ -0,0 +1,41 @@
+/*
+ * 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 __GENERAL_H
+#define __GENERAL_H
+
+#include <linux/types.h>
+#include <linux/io.h>
+
+#define iowrite32be(val, addr) out_be32(&(*addr), val)
+#define ioread32be(addr) in_be32(&(*addr))
+
+#endif /* __GENERAL_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h
new file mode 100644
index 0000000..8534550
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman.h
@@ -0,0 +1,743 @@
+/*
+ * 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 __FSL_FMAN_H
+#define __FSL_FMAN_H
+
+#include "common/general.h"
+#include <linux/delay.h>
+
+struct fman_ext_pool_params {
+ uint8_t id; /* External buffer pool id */
+ uint16_t size; /* External buffer pool buffer size */
+};
+
+struct fman_ext_pools {
+ uint8_t num_pools_used; /* Number of pools use by this port */
+ struct fman_ext_pool_params *ext_buf_pool;
+ /* Parameters for each port */
+};
+
+struct fman_backup_bm_pools {
+ uint8_t num_backup_pools; /* Number of BM backup pools -
+ * must be smaller than the total
+ * number of pools defined for the
+ * specified port.
+ */
+ uint8_t *pool_ids; /* num_of_backup_pools pool id's,
+ * specifying which pools should be
+ * used only as backup. Pool id's
+ * specified here must be a subset
+ * of the pools used by the specified
+ * port.
+ */
+};
+
+/* A structure for defining BM pool depletion criteria */
+struct fman_buf_pool_depletion {
+ bool buf_pool_depletion_enabled;
+ bool pools_grp_mode_enable; /* select mode in which pause frames
+ * will be sent after a number of pools
+ * (all together!) are depleted
+ */
+ uint8_t num_pools; /* the number of depleted pools that
+ * will invoke pause frames transmission.
+ */
+ bool *pools_to_consider; /* For each pool, true if it should be
+ * considered for depletion (Note - this
+ * pool must be used by this port!).
+ */
+ bool single_pool_mode_enable; /* select mode in which pause frames
+ * will be sent after a single-pool
+ * is depleted;
+ */
+ bool *pools_to_consider_for_single_mode;
+ /* For each pool, true if it should be
+ * considered for depletion (Note - this
+ * pool must be used by this port!)
+ */
+};
+
+/* Enum for defining port DMA swap mode */
+enum fman_dma_swap_option {
+ FMAN_DMA_NO_SWP, /* No swap, transfer data as is.*/
+ FMAN_DMA_SWP_PPC_LE, /* The transferred data should be swapped
+ * in PowerPc Little Endian mode.
+ */
+ FMAN_DMA_SWP_BE /* The transferred data should be swapped
+ * in Big Endian mode
+ */
+};
+
+/* Enum for defining port DMA cache attributes */
+enum fman_dma_cache_option {
+ FMAN_DMA_NO_STASH = 0, /* Cacheable, no Allocate (No Stashing) */
+ FMAN_DMA_STASH = 1 /* Cacheable and Allocate (Stashing on) */
+};
+
+typedef struct fm_prs_result_t fm_prs_result;
+typedef enum e_enet_mode enet_mode_t;
+
+struct fman_revision_info {
+ uint8_t major_rev; /* Major revision */
+ uint8_t minor_rev; /* Minor revision */
+};
+
+/* sizes */
+#define CAPWAP_FRAG_EXTRA_SPACE 32
+#define OFFSET_UNITS 16
+#define MAX_INT_OFFSET 240
+#define MAX_IC_SIZE 256
+#define MAX_EXT_OFFSET 496
+#define MAX_EXT_BUFFER_OFFSET 511
+
+/* Memory Mapped Registers */
+#define FMAN_LIODN_TBL 64 /* size of LIODN table */
+
+struct fman_fpm_regs {
+ uint32_t fmfp_tnc; /* FPM TNUM Control 0x00 */
+ uint32_t fmfp_prc; /* FPM Port_ID FmCtl Association 0x04 */
+ uint32_t fmfp_brkc; /* FPM Breakpoint Control 0x08 */
+ uint32_t fmfp_mxd; /* FPM Flush Control 0x0c */
+ uint32_t fmfp_dist1; /* FPM Dispatch Thresholds1 0x10 */
+ uint32_t fmfp_dist2; /* FPM Dispatch Thresholds2 0x14 */
+ uint32_t fm_epi; /* FM Error Pending Interrupts 0x18 */
+ uint32_t fm_rie; /* FM Error Interrupt Enable 0x1c */
+ uint32_t fmfp_fcev[4]; /* FPM FMan-Controller Event 1-4 0x20-0x2f */
+ uint32_t res0030[4]; /* res 0x30 - 0x3f */
+ uint32_t fmfp_cee[4]; /* PM FMan-Controller Event 1-4 0x40-0x4f */
+ uint32_t res0050[4]; /* res 0x50-0x5f */
+ uint32_t fmfp_tsc1; /* FPM TimeStamp Control1 0x60 */
+ uint32_t fmfp_tsc2; /* FPM TimeStamp Control2 0x64 */
+ uint32_t fmfp_tsp; /* FPM Time Stamp 0x68 */
+ uint32_t fmfp_tsf; /* FPM Time Stamp Fraction 0x6c */
+ uint32_t fm_rcr; /* FM Rams Control 0x70 */
+ uint32_t fmfp_extc; /* FPM External Requests Control 0x74 */
+ uint32_t fmfp_ext1; /* FPM External Requests Config1 0x78 */
+ uint32_t fmfp_ext2; /* FPM External Requests Config2 0x7c */
+ uint32_t fmfp_drd[16]; /* FPM Data_Ram Data 0-15 0x80 - 0xbf */
+ uint32_t fmfp_dra; /* FPM Data Ram Access 0xc0 */
+ uint32_t fm_ip_rev_1; /* FM IP Block Revision 1 0xc4 */
+ uint32_t fm_ip_rev_2; /* FM IP Block Revision 2 0xc8 */
+ uint32_t fm_rstc; /* FM Reset Command 0xcc */
+ uint32_t fm_cld; /* FM Classifier Debug 0xd0 */
+ uint32_t fm_npi; /* FM Normal Pending Interrupts 0xd4 */
+ uint32_t fmfp_exte; /* FPM External Requests Enable 0xd8 */
+ uint32_t fmfp_ee; /* FPM Event&Mask 0xdc */
+ uint32_t fmfp_cev[4]; /* FPM CPU Event 1-4 0xe0-0xef */
+ uint32_t res00f0[4]; /* res 0xf0-0xff */
+ uint32_t fmfp_ps[50]; /* FPM Port Status 0x100-0x1c7 */
+ uint32_t res01c8[14]; /* res 0x1c8-0x1ff */
+ uint32_t fmfp_clfabc; /* FPM CLFABC 0x200 */
+ uint32_t fmfp_clfcc; /* FPM CLFCC 0x204 */
+ uint32_t fmfp_clfaval; /* FPM CLFAVAL 0x208 */
+ uint32_t fmfp_clfbval; /* FPM CLFBVAL 0x20c */
+ uint32_t fmfp_clfcval; /* FPM CLFCVAL 0x210 */
+ uint32_t fmfp_clfamsk; /* FPM CLFAMSK 0x214 */
+ uint32_t fmfp_clfbmsk; /* FPM CLFBMSK 0x218 */
+ uint32_t fmfp_clfcmsk; /* FPM CLFCMSK 0x21c */
+ uint32_t fmfp_clfamc; /* FPM CLFAMC 0x220 */
+ uint32_t fmfp_clfbmc; /* FPM CLFBMC 0x224 */
+ uint32_t fmfp_clfcmc; /* FPM CLFCMC 0x228 */
+ uint32_t fmfp_decceh; /* FPM DECCEH 0x22c */
+ uint32_t res0230[116]; /* res 0x230 - 0x3ff */
+ uint32_t fmfp_ts[128]; /* 0x400: FPM Task Status 0x400 - 0x5ff */
+ uint32_t res0600[0x400 - 384];
+};
+
+struct fman_bmi_regs {
+ uint32_t fmbm_init; /* BMI Initialization 0x00 */
+ uint32_t fmbm_cfg1; /* BMI Configuration 1 0x04 */
+ uint32_t fmbm_cfg2; /* BMI Configuration 2 0x08 */
+ uint32_t res000c[5]; /* 0x0c - 0x1f */
+ uint32_t fmbm_ievr; /* Interrupt Event Register 0x20 */
+ uint32_t fmbm_ier; /* Interrupt Enable Register 0x24 */
+ uint32_t fmbm_ifr; /* Interrupt Force Register 0x28 */
+ uint32_t res002c[5]; /* 0x2c - 0x3f */
+ uint32_t fmbm_arb[8]; /* BMI Arbitration 0x40 - 0x5f */
+ uint32_t res0060[12]; /*0x60 - 0x8f */
+ uint32_t fmbm_dtc[3]; /* Debug Trap Counter 0x90 - 0x9b */
+ uint32_t res009c; /* 0x9c */
+ uint32_t fmbm_dcv[3][4]; /* Debug Compare val 0xa0-0xcf */
+ uint32_t fmbm_dcm[3][4]; /* Debug Compare Mask 0xd0-0xff */
+ uint32_t fmbm_gde; /* BMI Global Debug Enable 0x100 */
+ uint32_t fmbm_pp[63]; /* BMI Port Parameters 0x104 - 0x1ff */
+ uint32_t res0200; /* 0x200 */
+ uint32_t fmbm_pfs[63]; /* BMI Port FIFO Size 0x204 - 0x2ff */
+ uint32_t res0300; /* 0x300 */
+ uint32_t fmbm_spliodn[63]; /* Port Partition ID 0x304 - 0x3ff */
+};
+
+struct fman_qmi_regs {
+ uint32_t fmqm_gc; /* General Configuration Register 0x00 */
+ uint32_t res0004; /* 0x04 */
+ uint32_t fmqm_eie; /* Error Interrupt Event Register 0x08 */
+ uint32_t fmqm_eien; /* Error Interrupt Enable Register 0x0c */
+ uint32_t fmqm_eif; /* Error Interrupt Force Register 0x10 */
+ uint32_t fmqm_ie; /* Interrupt Event Register 0x14 */
+ uint32_t fmqm_ien; /* Interrupt Enable Register 0x18 */
+ uint32_t fmqm_if; /* Interrupt Force Register 0x1c */
+ uint32_t fmqm_gs; /* Global Status Register 0x20 */
+ uint32_t fmqm_ts; /* Task Status Register 0x24 */
+ uint32_t fmqm_etfc; /* Enqueue Total Frame Counter 0x28 */
+ uint32_t fmqm_dtfc; /* Dequeue Total Frame Counter 0x2c */
+ uint32_t fmqm_dc0; /* Dequeue Counter 0 0x30 */
+ uint32_t fmqm_dc1; /* Dequeue Counter 1 0x34 */
+ uint32_t fmqm_dc2; /* Dequeue Counter 2 0x38 */
+ uint32_t fmqm_dc3; /* Dequeue Counter 3 0x3c */
+ uint32_t fmqm_dfdc; /* Dequeue FQID from Default Counter 0x40 */
+ uint32_t fmqm_dfcc; /* Dequeue FQID from Context Counter 0x44 */
+ uint32_t fmqm_dffc; /* Dequeue FQID from FD Counter 0x48 */
+ uint32_t fmqm_dcc; /* Dequeue Confirm Counter 0x4c */
+ uint32_t res0050[7]; /* 0x50 - 0x6b */
+ uint32_t fmqm_tapc; /* Tnum Aging Period Control 0x6c */
+ uint32_t fmqm_dmcvc; /* Dequeue MAC Command Valid Counter 0x70 */
+ uint32_t fmqm_difdcc; /* Dequeue Invalid FD Command Counter 0x74 */
+ uint32_t fmqm_da1v; /* Dequeue A1 Valid Counter 0x78 */
+ uint32_t res007c; /* 0x7c */
+ uint32_t fmqm_dtc; /* 0x80 Debug Trap Counter 0x80 */
+ uint32_t fmqm_efddd; /* 0x84 Enqueue Frame desc Dynamic dbg 0x84 */
+ uint32_t res0088[2]; /* 0x88 - 0x8f */
+ struct {
+ uint32_t fmqm_dtcfg1; /* 0x90 dbg trap cfg 1 Register 0x00 */
+ uint32_t fmqm_dtval1; /* Debug Trap Value 1 Register 0x04 */
+ uint32_t fmqm_dtm1; /* Debug Trap Mask 1 Register 0x08 */
+ uint32_t fmqm_dtc1; /* Debug Trap Counter 1 Register 0x0c */
+ uint32_t fmqm_dtcfg2; /* dbg Trap cfg 2 Register 0x10 */
+ uint32_t fmqm_dtval2; /* Debug Trap Value 2 Register 0x14 */
+ uint32_t fmqm_dtm2; /* Debug Trap Mask 2 Register 0x18 */
+ uint32_t res001c; /* 0x1c */
+ } dbg_traps[3]; /* 0x90 - 0xef */
+ uint8_t res00f0[0x400 - 0xf0]; /* 0xf0 - 0x3ff */
+};
+
+struct fman_dma_regs {
+ uint32_t fmdmsr; /* FM DMA status register 0x00 */
+ uint32_t fmdmmr; /* FM DMA mode register 0x04 */
+ uint32_t fmdmtr; /* FM DMA bus threshold register 0x08 */
+ uint32_t fmdmhy; /* FM DMA bus hysteresis register 0x0c */
+ uint32_t fmdmsetr; /* FM DMA SOS emergency Threshold Register 0x10 */
+ uint32_t fmdmtah; /* FM DMA transfer bus address high reg 0x14 */
+ uint32_t fmdmtal; /* FM DMA transfer bus address low reg 0x18 */
+ uint32_t fmdmtcid; /* FM DMA transfer bus communication ID reg 0x1c */
+ uint32_t fmdmra; /* FM DMA bus internal ram address register 0x20 */
+ uint32_t fmdmrd; /* FM DMA bus internal ram data register 0x24 */
+ uint32_t fmdmwcr; /* FM DMA CAM watchdog counter value 0x28 */
+ uint32_t fmdmebcr; /* FM DMA CAM base in MURAM register 0x2c */
+ uint32_t fmdmccqdr; /* FM DMA CAM and CMD Queue Debug reg 0x30 */
+ uint32_t fmdmccqvr1; /* FM DMA CAM and CMD Queue Value reg #1 0x34 */
+ uint32_t fmdmccqvr2; /* FM DMA CAM and CMD Queue Value reg #2 0x38 */
+ uint32_t fmdmcqvr3; /* FM DMA CMD Queue Value register #3 0x3c */
+ uint32_t fmdmcqvr4; /* FM DMA CMD Queue Value register #4 0x40 */
+ uint32_t fmdmcqvr5; /* FM DMA CMD Queue Value register #5 0x44 */
+ uint32_t fmdmsefrc; /* FM DMA Semaphore Entry Full Reject Cntr 0x48 */
+ uint32_t fmdmsqfrc; /* FM DMA Semaphore Queue Full Reject Cntr 0x4c */
+ uint32_t fmdmssrc; /* FM DMA Semaphore SYNC Reject Counter 0x50 */
+ uint32_t fmdmdcr; /* FM DMA Debug Counter 0x54 */
+ uint32_t fmdmemsr; /* FM DMA Emergency Smoother Register 0x58 */
+ uint32_t res005c; /* 0x5c */
+ uint32_t fmdmplr[FMAN_LIODN_TBL / 2]; /* DMA LIODN regs 0x60-0xdf */
+ uint32_t res00e0[0x400 - 56];
+};
+
+struct fman_rg {
+ struct fman_fpm_regs __iomem *fpm_rg;
+ struct fman_dma_regs __iomem *dma_rg;
+ struct fman_bmi_regs __iomem *bmi_rg;
+ struct fman_qmi_regs __iomem *qmi_rg;
+};
+
+enum fman_dma_cache_override {
+ E_FMAN_DMA_NO_CACHE_OR = 0, /* No override of the Cache field */
+ E_FMAN_DMA_NO_STASH_DATA, /* No data stashing in system level cache */
+ E_FMAN_DMA_MAY_STASH_DATA, /* Stashing allowed in sys level cache */
+ E_FMAN_DMA_STASH_DATA /* Stashing performed in system level cache */
+};
+
+enum fman_dma_aid_mode {
+ E_FMAN_DMA_AID_OUT_PORT_ID = 0, /* 4 LSB of PORT_ID */
+ E_FMAN_DMA_AID_OUT_TNUM /* 4 LSB of TNUM */
+};
+
+enum fman_dma_dbg_cnt_mode {
+ E_FMAN_DMA_DBG_NO_CNT = 0, /* No counting */
+ E_FMAN_DMA_DBG_CNT_DONE, /* Count DONE commands */
+ E_FMAN_DMA_DBG_CNT_COMM_Q_EM, /* command Q emergency signal */
+ E_FMAN_DMA_DBG_CNT_INT_READ_EM, /* Read buf emergency signal */
+ E_FMAN_DMA_DBG_CNT_INT_WRITE_EM, /* Write buf emergency signal */
+ E_FMAN_DMA_DBG_CNT_FPM_WAIT, /* FPM WAIT signal */
+ E_FMAN_DMA_DBG_CNT_SIGLE_BIT_ECC, /* Single bit ECC errors */
+ E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT /* RAW&WAR protection counter */
+};
+
+enum fman_dma_emergency_level {
+ E_FMAN_DMA_EM_EBS = 0, /* EBS emergency */
+ E_FMAN_DMA_EM_SOS /* SOS emergency */
+};
+
+enum fman_catastrophic_err {
+ E_FMAN_CATAST_ERR_STALL_PORT = 0, /* Port_ID stalled reset required */
+ E_FMAN_CATAST_ERR_STALL_TASK /* Only erroneous task is stalled */
+};
+
+enum fman_dma_err {
+ E_FMAN_DMA_ERR_CATASTROPHIC = 0, /* Catastrophic DMA error */
+ E_FMAN_DMA_ERR_REPORT /* Reported DMA error */
+};
+
+struct fman_cfg {
+ uint16_t liodn_bs_pr_port[FMAN_LIODN_TBL]; /* base per port */
+ uint8_t disp_limit_tsh;
+ uint8_t prs_disp_tsh;
+ uint8_t plcr_disp_tsh;
+ uint8_t kg_disp_tsh;
+ uint8_t bmi_disp_tsh;
+ uint8_t qmi_enq_disp_tsh;
+ uint8_t qmi_deq_disp_tsh;
+ uint8_t fm_ctl1_disp_tsh;
+ uint8_t fm_ctl2_disp_tsh;
+ enum fman_dma_cache_override dma_cache_override;
+ enum fman_dma_aid_mode dma_aid_mode;
+ bool dma_aid_override;
+ uint8_t dma_axi_dbg_num_of_beats;
+ uint8_t dma_cam_num_of_entries;
+ uint32_t dma_watchdog;
+ uint8_t dma_comm_qtsh_asrt_emer;
+ uint8_t dma_write_buf_tsh_asrt_emer;
+ uint8_t dma_read_buf_tsh_asrt_emer;
+ uint8_t dma_comm_qtsh_clr_emer;
+ uint8_t dma_write_buf_tsh_clr_emer;
+ uint8_t dma_read_buf_tsh_clr_emer;
+ uint32_t dma_sos_emergency;
+ enum fman_dma_dbg_cnt_mode dma_dbg_cnt_mode;
+ bool dma_stop_on_bus_error;
+ bool dma_en_emergency;
+ uint32_t dma_emergency_bus_select;
+ enum fman_dma_emergency_level dma_emergency_level;
+ bool dma_en_emergency_smoother;
+ uint32_t dma_emergency_switch_counter;
+ bool halt_on_external_activ;
+ bool halt_on_unrecov_ecc_err;
+ enum fman_catastrophic_err catastrophic_err;
+ enum fman_dma_err dma_err;
+ bool en_muram_test_mode;
+ bool en_iram_test_mode;
+ bool external_ecc_rams_enable;
+ uint16_t tnum_aging_period;
+ uint32_t exceptions;
+ uint16_t clk_freq;
+ bool pedantic_dma;
+ uint32_t cam_base_addr;
+ uint32_t fifo_base_addr;
+ uint32_t total_fifo_size;
+ uint8_t total_num_of_tasks;
+ bool qmi_deq_option_support;
+ uint32_t qmi_def_tnums_thresh;
+ bool fman_partition_array;
+ uint8_t num_of_fman_ctrl_evnt_regs;
+};
+
+/* Exceptions */
+#define FMAN_EX_DMA_BUS_ERROR 0x80000000
+#define FMAN_EX_DMA_READ_ECC 0x40000000
+#define FMAN_EX_DMA_SYSTEM_WRITE_ECC 0x20000000
+#define FMAN_EX_DMA_FM_WRITE_ECC 0x10000000
+#define FMAN_EX_FPM_STALL_ON_TASKS 0x08000000
+#define FMAN_EX_FPM_SINGLE_ECC 0x04000000
+#define FMAN_EX_FPM_DOUBLE_ECC 0x02000000
+#define FMAN_EX_QMI_SINGLE_ECC 0x01000000
+#define FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000
+#define FMAN_EX_QMI_DOUBLE_ECC 0x00400000
+#define FMAN_EX_BMI_LIST_RAM_ECC 0x00200000
+#define FMAN_EX_BMI_PIPELINE_ECC 0x00100000
+#define FMAN_EX_BMI_STATISTICS_RAM_ECC 0x00080000
+#define FMAN_EX_IRAM_ECC 0x00040000
+#define FMAN_EX_NURAM_ECC 0x00020000
+#define FMAN_EX_BMI_DISPATCH_RAM_ECC 0x00010000
+
+enum fman_exceptions {
+ E_FMAN_EX_DMA_BUS_ERROR = 0, /* DMA bus error. */
+ E_FMAN_EX_DMA_READ_ECC, /* Read Buffer ECC error */
+ E_FMAN_EX_DMA_SYSTEM_WRITE_ECC, /* Write Buffer ECC err on sys side */
+ E_FMAN_EX_DMA_FM_WRITE_ECC, /* Write Buffer ECC error on FM side */
+ E_FMAN_EX_FPM_STALL_ON_TASKS, /* Stall of tasks on FPM */
+ E_FMAN_EX_FPM_SINGLE_ECC, /* Single ECC on FPM. */
+ E_FMAN_EX_FPM_DOUBLE_ECC, /* Double ECC error on FPM ram access */
+ E_FMAN_EX_QMI_SINGLE_ECC, /* Single ECC on QMI. */
+ E_FMAN_EX_QMI_DOUBLE_ECC, /* Double bit ECC occurred on QMI */
+ E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,/* DeQ from unknown port id */
+ E_FMAN_EX_BMI_LIST_RAM_ECC, /* Linked List RAM ECC error */
+ E_FMAN_EX_BMI_STORAGE_PROFILE_ECC, /* storage profile */
+ E_FMAN_EX_BMI_STATISTICS_RAM_ECC, /* Statistics RAM ECC Err Enable */
+ E_FMAN_EX_BMI_DISPATCH_RAM_ECC, /* Dispatch RAM ECC Error Enable */
+ E_FMAN_EX_IRAM_ECC, /* Double bit ECC occurred on IRAM*/
+ E_FMAN_EX_MURAM_ECC /* Double bit ECC occurred on MURAM*/
+};
+
+#define FPM_PRT_FM_CTL1 0x00000001
+#define FPM_PRT_FM_CTL2 0x00000002
+
+/* DMA definitions */
+
+/* masks */
+#define DMA_MODE_AID_OR 0x20000000
+#define DMA_MODE_SBER 0x10000000
+#define DMA_MODE_BER 0x00200000
+#define DMA_MODE_EB 0x00100000
+#define DMA_MODE_ECC 0x00000020
+#define DMA_MODE_PRIVILEGE_PROT 0x00001000
+#define DMA_MODE_SECURE_PROT 0x00000800
+#define DMA_MODE_EMER_READ 0x00080000
+#define DMA_MODE_EMER_WRITE 0x00040000
+#define DMA_MODE_CACHE_OR_MASK 0xC0000000
+#define DMA_MODE_CEN_MASK 0x0000E000
+#define DMA_MODE_DBG_MASK 0x00000380
+#define DMA_MODE_AXI_DBG_MASK 0x0F000000
+
+#define DMA_EMSR_EMSTR_MASK 0x0000FFFF
+
+#define DMA_TRANSFER_PORTID_MASK 0xFF000000
+#define DMA_TRANSFER_TNUM_MASK 0x00FF0000
+#define DMA_TRANSFER_LIODN_MASK 0x00000FFF
+
+#define DMA_HIGH_LIODN_MASK 0x0FFF0000
+#define DMA_LOW_LIODN_MASK 0x00000FFF
+
+#define DMA_STATUS_CMD_QUEUE_NOT_EMPTY 0x10000000
+#define DMA_STATUS_BUS_ERR 0x08000000
+#define DMA_STATUS_READ_ECC 0x04000000
+#define DMA_STATUS_SYSTEM_WRITE_ECC 0x02000000
+#define DMA_STATUS_FM_WRITE_ECC 0x01000000
+#define DMA_STATUS_SYSTEM_DPEXT_ECC 0x00800000
+#define DMA_STATUS_FM_DPEXT_ECC 0x00400000
+#define DMA_STATUS_SYSTEM_DPDAT_ECC 0x00200000
+#define DMA_STATUS_FM_DPDAT_ECC 0x00100000
+#define DMA_STATUS_FM_SPDAT_ECC 0x00080000
+
+#define FM_LIODN_BASE_MASK 0x00000FFF
+
+/* shifts */
+#define DMA_MODE_CACHE_OR_SHIFT 30
+#define DMA_MODE_BUS_PRI_SHIFT 16
+#define DMA_MODE_AXI_DBG_SHIFT 24
+#define DMA_MODE_CEN_SHIFT 13
+#define DMA_MODE_BUS_PROT_SHIFT 10
+#define DMA_MODE_DBG_SHIFT 7
+#define DMA_MODE_EMER_LVL_SHIFT 6
+#define DMA_MODE_AID_MODE_SHIFT 4
+#define DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS 16
+#define DMA_MODE_MAX_CAM_NUM_OF_ENTRIES 32
+
+#define DMA_THRESH_COMMQ_SHIFT 24
+#define DMA_THRESH_READ_INT_BUF_SHIFT 16
+
+#define DMA_LIODN_SHIFT 16
+
+#define DMA_TRANSFER_PORTID_SHIFT 24
+#define DMA_TRANSFER_TNUM_SHIFT 16
+
+/* sizes */
+#define DMA_MAX_WATCHDOG 0xffffffff
+
+/* others */
+#define DMA_CAM_SIZEOF_ENTRY 0x40
+#define DMA_CAM_ALIGN 0x40
+#define DMA_CAM_UNITS 8
+
+/* General defines */
+
+#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL
+#define FM_UCODE_DEBUG_INSTRUCTION 0x6ffff805UL
+#define FM_PORT_MAX_BW_WEIGHTS 64
+
+/* FPM defines */
+
+/* masks */
+#define FPM_EV_MASK_DOUBLE_ECC 0x80000000
+#define FPM_EV_MASK_STALL 0x40000000
+#define FPM_EV_MASK_SINGLE_ECC 0x20000000
+#define FPM_EV_MASK_RELEASE_FM 0x00010000
+#define FPM_EV_MASK_DOUBLE_ECC_EN 0x00008000
+#define FPM_EV_MASK_STALL_EN 0x00004000
+#define FPM_EV_MASK_SINGLE_ECC_EN 0x00002000
+#define FPM_EV_MASK_EXTERNAL_HALT 0x00000008
+#define FPM_EV_MASK_ECC_ERR_HALT 0x00000004
+
+#define FPM_RAM_RAMS_ECC_EN 0x80000000
+#define FPM_RAM_IRAM_ECC_EN 0x40000000
+#define FPM_RAM_MURAM_ECC 0x00008000
+#define FPM_RAM_IRAM_ECC 0x00004000
+#define FPM_RAM_MURAM_TEST_ECC 0x20000000
+#define FPM_RAM_IRAM_TEST_ECC 0x10000000
+#define FPM_RAM_RAMS_ECC_EN_SRC_SEL 0x08000000
+
+#define FPM_IRAM_ECC_ERR_EX_EN 0x00020000
+#define FPM_MURAM_ECC_ERR_EX_EN 0x00040000
+
+#define FPM_REV1_MAJOR_MASK 0x0000FF00
+#define FPM_REV1_MINOR_MASK 0x000000FF
+
+#define FPM_REV2_INTEG_MASK 0x00FF0000
+#define FPM_REV2_ERR_MASK 0x0000FF00
+#define FPM_REV2_CFG_MASK 0x000000FF
+
+#define FPM_TS_FRACTION_MASK 0x0000FFFF
+#define FPM_TS_CTL_EN 0x80000000
+
+#define FPM_PRC_REALSE_STALLED 0x00800000
+
+#define FPM_PS_STALLED 0x00800000
+#define FPM_PS_FM_CTL1_SEL 0x80000000
+#define FPM_PS_FM_CTL2_SEL 0x40000000
+#define FPM_PS_FM_CTL_SEL_MASK (FPM_PS_FM_CTL1_SEL | FPM_PS_FM_CTL2_SEL)
+
+#define FPM_RSTC_FM_RESET 0x80000000
+
+#define FPM_DISP_LIMIT_MASK 0x1F000000
+#define FPM_THR1_PRS_MASK 0xFF000000
+#define FPM_THR1_KG_MASK 0x00FF0000
+#define FPM_THR1_PLCR_MASK 0x0000FF00
+#define FPM_THR1_BMI_MASK 0x000000FF
+
+#define FPM_THR2_QMI_ENQ_MASK 0xFF000000
+#define FPM_THR2_QMI_DEQ_MASK 0x000000FF
+#define FPM_THR2_FM_CTL1_MASK 0x00FF0000
+#define FPM_THR2_FM_CTL2_MASK 0x0000FF00
+
+/* shifts */
+#define FPM_DISP_LIMIT_SHIFT 24
+
+#define FPM_THR1_PRS_SHIFT 24
+#define FPM_THR1_KG_SHIFT 16
+#define FPM_THR1_PLCR_SHIFT 8
+#define FPM_THR1_BMI_SHIFT 0
+
+#define FPM_THR2_QMI_ENQ_SHIFT 24
+#define FPM_THR2_QMI_DEQ_SHIFT 0
+#define FPM_THR2_FM_CTL1_SHIFT 16
+#define FPM_THR2_FM_CTL2_SHIFT 8
+
+#define FPM_EV_MASK_CAT_ERR_SHIFT 1
+#define FPM_EV_MASK_DMA_ERR_SHIFT 0
+
+#define FPM_REV1_MAJOR_SHIFT 8
+#define FPM_REV1_MINOR_SHIFT 0
+
+#define FPM_REV2_INTEG_SHIFT 16
+#define FPM_REV2_ERR_SHIFT 8
+#define FPM_REV2_CFG_SHIFT 0
+
+#define FPM_TS_INT_SHIFT 16
+
+#define FPM_PORT_FM_CTL_PORTID_SHIFT 24
+
+#define FPM_PS_FM_CTL_SEL_SHIFT 30
+#define FPM_PRC_ORA_FM_CTL_SEL_SHIFT 16
+
+#define FPM_DISP_LIMIT_SHIFT 24
+
+/* Interrupts defines */
+#define FPM_EVENT_FM_CTL_0 0x00008000
+#define FPM_EVENT_FM_CTL 0x0000FF00
+#define FPM_EVENT_FM_CTL_BRK 0x00000080
+
+/* others */
+#define FPM_MAX_DISP_LIMIT 31
+#define FPM_RSTC_FM_RESET 0x80000000
+#define FPM_RSTC_MAC0_RESET 0x40000000
+#define FPM_RSTC_MAC1_RESET 0x20000000
+#define FPM_RSTC_MAC2_RESET 0x10000000
+#define FPM_RSTC_MAC3_RESET 0x08000000
+#define FPM_RSTC_MAC8_RESET 0x04000000
+#define FPM_RSTC_MAC4_RESET 0x02000000
+#define FPM_RSTC_MAC5_RESET 0x01000000
+#define FPM_RSTC_MAC6_RESET 0x00800000
+#define FPM_RSTC_MAC7_RESET 0x00400000
+#define FPM_RSTC_MAC9_RESET 0x00200000
+/* BMI defines */
+/* masks */
+#define BMI_INIT_START 0x80000000
+#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000
+#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000
+#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000
+#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000
+#define BMI_NUM_OF_TASKS_MASK 0x3F000000
+#define BMI_NUM_OF_EXTRA_TASKS_MASK 0x000F0000
+#define BMI_NUM_OF_DMAS_MASK 0x00000F00
+#define BMI_NUM_OF_EXTRA_DMAS_MASK 0x0000000F
+#define BMI_FIFO_SIZE_MASK 0x000003FF
+#define BMI_EXTRA_FIFO_SIZE_MASK 0x03FF0000
+#define BMI_CFG1_FIFO_SIZE_MASK 0x03FF0000
+#define BMI_CFG2_DMAS_MASK 0x0000003F
+#define BMI_TOTAL_FIFO_SIZE_MASK 0x07FF0000
+#define BMI_TOTAL_NUM_OF_TASKS_MASK 0x007F0000
+
+/* shifts */
+#define BMI_CFG2_TASKS_SHIFT 16
+#define BMI_CFG2_DMAS_SHIFT 0
+#define BMI_CFG1_FIFO_SIZE_SHIFT 16
+#define BMI_FIFO_SIZE_SHIFT 0
+#define BMI_EXTRA_FIFO_SIZE_SHIFT 16
+#define BMI_NUM_OF_TASKS_SHIFT 24
+#define BMI_EXTRA_NUM_OF_TASKS_SHIFT 16
+#define BMI_NUM_OF_DMAS_SHIFT 8
+#define BMI_EXTRA_NUM_OF_DMAS_SHIFT 0
+
+/* others */
+#define BMI_FIFO_ALIGN 0x100
+#define FMAN_BMI_FIFO_UNITS 0x100
+
+/* QMI defines */
+/* masks */
+#define QMI_CFG_ENQ_EN 0x80000000
+#define QMI_CFG_DEQ_EN 0x40000000
+#define QMI_CFG_EN_COUNTERS 0x10000000
+#define QMI_CFG_SOFT_RESET 0x01000000
+#define QMI_CFG_DEQ_MASK 0x0000003F
+#define QMI_CFG_ENQ_MASK 0x00003F00
+
+#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000
+#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000
+#define QMI_INTR_EN_SINGLE_ECC 0x80000000
+
+/* shifts */
+#define QMI_CFG_ENQ_SHIFT 8
+#define QMI_TAPC_TAP 22
+
+#define QMI_GS_HALT_NOT_BUSY 0x00000002
+
+/* IRAM defines */
+/* masks */
+#define IRAM_IADD_AIE 0x80000000
+#define IRAM_READY 0x80000000
+
+uint32_t fman_get_bmi_err_event(struct fman_bmi_regs __iomem *bmi_rg);
+uint32_t fman_get_qmi_err_event(struct fman_qmi_regs __iomem *qmi_rg);
+uint32_t fman_get_dma_com_id(struct fman_dma_regs __iomem *dma_rg);
+uint64_t fman_get_dma_addr(struct fman_dma_regs __iomem *dma_rg);
+uint32_t fman_get_dma_err_event(struct fman_dma_regs __iomem *dma_rg);
+uint32_t fman_get_fpm_err_event(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_muram_err_event(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_iram_err_event(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_qmi_event(struct fman_qmi_regs __iomem *qmi_rg);
+uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs __iomem *fpm_rg);
+uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg);
+uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg);
+uint16_t fman_get_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id);
+uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id);
+uint8_t fman_get_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id);
+uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id);
+uint8_t fman_get_num_of_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id);
+uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id);
+uint32_t fman_get_normal_pending(struct fman_fpm_regs __iomem *fpm_rg);
+uint32_t fman_get_controller_event(struct fman_fpm_regs __iomem *fpm_rg,
+ uint8_t reg_id);
+uint32_t fman_get_error_pending(struct fman_fpm_regs __iomem *fpm_rg);
+void fman_get_revision(struct fman_fpm_regs __iomem *fpm_rg, uint8_t *major,
+ uint8_t *minor);
+
+int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs __iomem *fpm_rg);
+void fman_set_order_restoration_per_port(struct fman_fpm_regs __iomem *fpm_rg,
+ uint8_t port_id, bool is_rx_port);
+void fman_set_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val);
+void fman_set_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val);
+void fman_set_liodn_per_port(struct fman_rg *fman_rg,
+ uint8_t port_id,
+ uint16_t liodn_base, uint16_t liodn_offset);
+void fman_set_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id,
+ uint32_t size_of_fifo, uint32_t extra_size_of_fifo);
+void fman_set_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id,
+ uint8_t num_of_tasks, uint8_t num_of_extra_tasks);
+void fman_set_num_of_open_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id,
+ uint8_t num_of_open_dmas,
+ uint8_t num_of_extra_open_dmas,
+ uint8_t total_num_of_dmas);
+int fman_set_exception(struct fman_rg *fman_rg,
+ enum fman_exceptions exception, bool enable);
+
+void fman_defconfig(struct fman_cfg *cfg);
+int fman_fpm_init(struct fman_fpm_regs __iomem *fpm_rg, struct fman_cfg *cfg);
+int fman_bmi_init(struct fman_bmi_regs __iomem *bmi_rg, struct fman_cfg *cfg);
+int fman_qmi_init(struct fman_qmi_regs __iomem *qmi_rg, struct fman_cfg *cfg);
+int fman_dma_init(struct fman_dma_regs __iomem *dma_rg, struct fman_cfg *cfg);
+void fman_free_resources(struct fman_rg *fman_rg);
+int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg);
+void fman_resume(struct fman_fpm_regs __iomem *fpm_rg);
+
+void fman_enable_time_stamp(struct fman_fpm_regs __iomem *fpm_rg,
+ uint8_t count1ubit, uint16_t fm_clk_freq);
+void fman_enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg);
+void fman_disable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg);
+int fman_reset_mac(struct fman_fpm_regs __iomem *fpm_rg, uint8_t mac_id);
+bool fman_rams_ecc_is_external_ctl(struct fman_fpm_regs __iomem *fpm_rg);
+bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs __iomem *qmi_rg);
+
+/* default values */
+#define DEFAULT_CATASTROPHIC_ERR E_FMAN_CATAST_ERR_STALL_PORT
+#define DEFAULT_DMA_ERR E_FMAN_DMA_ERR_CATASTROPHIC
+/* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_HALT_ON_EXTERNAL_ACTIVATION false
+/* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR false
+#define DEFAULT_EXTERNAL_ECC_RAMS_ENABLE false
+#define DEFAULT_AID_OVERRIDE false
+#define DEFAULT_AID_MODE E_FMAN_DMA_AID_OUT_TNUM
+#define DEFAULT_DMA_COMM_Q_LOW 0x2A
+#define DEFAULT_DMA_COMM_Q_HIGH 0x3F
+#define DEFAULT_CACHE_OVERRIDE E_FMAN_DMA_NO_CACHE_OR
+#define DEFAULT_DMA_CAM_NUM_OF_ENTRIES 64
+#define DEFAULT_DMA_DBG_CNT_MODE E_FMAN_DMA_DBG_NO_CNT
+#define DEFAULT_DMA_EN_EMERGENCY false
+#define DEFAULT_DMA_SOS_EMERGENCY 0
+#define DEFAULT_DMA_WATCHDOG 0 /* disabled */
+#define DEFAULT_DMA_EN_EMERGENCY_SMOOTHER false
+#define DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER 0
+#define DEFAULT_DISP_LIMIT 0
+#define DEFAULT_PRS_DISP_TH 16
+#define DEFAULT_PLCR_DISP_TH 16
+#define DEFAULT_KG_DISP_TH 16
+#define DEFAULT_BMI_DISP_TH 16
+#define DEFAULT_QMI_ENQ_DISP_TH 16
+#define DEFAULT_QMI_DEQ_DISP_TH 16
+#define DEFAULT_FM_CTL1_DISP_TH 16
+#define DEFAULT_FM_CTL2_DISP_TH 16
+#define DEFAULT_TNUM_AGING_PERIOD 4
+
+#endif /* __FSL_FMAN_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 02/12] fsl/fman: Add the FMan FLIB
2015-05-07 13:05 [RFC,v3 01/12] fsl/fman: Add the FMan FLIB headers Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
The FMan FLib provides the basic API used by the FMan drivers to
configure and control the FMan hardware.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
drivers/net/ethernet/freescale/Kconfig | 1 +
drivers/net/ethernet/freescale/Makefile | 2 +
drivers/net/ethernet/freescale/fman/Kconfig | 7 +
drivers/net/ethernet/freescale/fman/Makefile | 5 +
drivers/net/ethernet/freescale/fman/fman.c | 978 +++++++++++++++++++++++++++
5 files changed, 993 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/fman/Kconfig
create mode 100644 drivers/net/ethernet/freescale/fman/Makefile
create mode 100644 drivers/net/ethernet/freescale/fman/fman.c
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index 25e3425..24e938d 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -55,6 +55,7 @@ config FEC_MPC52xx_MDIO
If compiled as module, it will be called fec_mpc52xx_phy.
source "drivers/net/ethernet/freescale/fs_enet/Kconfig"
+source "drivers/net/ethernet/freescale/fman/Kconfig"
config FSL_PQ_MDIO
tristate "Freescale PQ MDIO"
diff --git a/drivers/net/ethernet/freescale/Makefile b/drivers/net/ethernet/freescale/Makefile
index 71debd1..4097c58 100644
--- a/drivers/net/ethernet/freescale/Makefile
+++ b/drivers/net/ethernet/freescale/Makefile
@@ -17,3 +17,5 @@ gianfar_driver-objs := gianfar.o \
gianfar_ethtool.o
obj-$(CONFIG_UCC_GETH) += ucc_geth_driver.o
ucc_geth_driver-objs := ucc_geth.o ucc_geth_ethtool.o
+
+obj-$(CONFIG_FSL_FMAN) += fman/
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
new file mode 100644
index 0000000..8aeae29
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -0,0 +1,7 @@
+config FSL_FMAN
+ bool "FMan support"
+ depends on FSL_SOC || COMPILE_TEST
+ default n
+ help
+ Freescale Data-Path Acceleration Architecture Frame Manager
+ (FMan) support
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
new file mode 100644
index 0000000..a718f7c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -0,0 +1,5 @@
+subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib
+
+obj-y += fsl_fman.o
+
+fsl_fman-objs := fman.o
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
new file mode 100644
index 0000000..d9ea1e8
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -0,0 +1,978 @@
+/*
+ * 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 "fsl_fman.h"
+
+uint32_t fman_get_bmi_err_event(struct fman_bmi_regs __iomem *bmi_rg)
+{
+ uint32_t event, mask, force;
+
+ event = ioread32be(&bmi_rg->fmbm_ievr);
+ mask = ioread32be(&bmi_rg->fmbm_ier);
+ event &= mask;
+ /* clear the forced events */
+ force = ioread32be(&bmi_rg->fmbm_ifr);
+ if (force & event)
+ iowrite32be(force & ~event, &bmi_rg->fmbm_ifr);
+ /* clear the acknowledged events */
+ iowrite32be(event, &bmi_rg->fmbm_ievr);
+ return event;
+}
+
+uint32_t fman_get_qmi_err_event(struct fman_qmi_regs __iomem *qmi_rg)
+{
+ uint32_t event, mask, force;
+
+ event = ioread32be(&qmi_rg->fmqm_eie);
+ mask = ioread32be(&qmi_rg->fmqm_eien);
+ event &= mask;
+
+ /* clear the forced events */
+ force = ioread32be(&qmi_rg->fmqm_eif);
+ if (force & event)
+ iowrite32be(force & ~event, &qmi_rg->fmqm_eif);
+ /* clear the acknowledged events */
+ iowrite32be(event, &qmi_rg->fmqm_eie);
+ return event;
+}
+
+uint32_t fman_get_dma_com_id(struct fman_dma_regs __iomem *dma_rg)
+{
+ return ioread32be(&dma_rg->fmdmtcid);
+}
+
+uint64_t fman_get_dma_addr(struct fman_dma_regs __iomem *dma_rg)
+{
+ uint64_t addr;
+
+ addr = (uint64_t)ioread32be(&dma_rg->fmdmtal);
+ addr |= ((uint64_t)(ioread32be(&dma_rg->fmdmtah)) << 32);
+
+ return addr;
+}
+
+uint32_t fman_get_dma_err_event(struct fman_dma_regs __iomem *dma_rg)
+{
+ uint32_t status, mask;
+
+ status = ioread32be(&dma_rg->fmdmsr);
+ mask = ioread32be(&dma_rg->fmdmmr);
+
+ /* clear DMA_STATUS_BUS_ERR if mask has no DMA_MODE_BER */
+ if ((mask & DMA_MODE_BER) != DMA_MODE_BER)
+ status &= ~DMA_STATUS_BUS_ERR;
+
+ /* clear relevant bits if mask has no DMA_MODE_ECC */
+ if ((mask & DMA_MODE_ECC) != DMA_MODE_ECC)
+ status &= ~(DMA_STATUS_FM_SPDAT_ECC |
+ DMA_STATUS_READ_ECC |
+ DMA_STATUS_SYSTEM_WRITE_ECC |
+ DMA_STATUS_FM_WRITE_ECC);
+
+ /* clear set events */
+ iowrite32be(status, &dma_rg->fmdmsr);
+
+ return status;
+}
+
+uint32_t fman_get_fpm_err_event(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ uint32_t event;
+
+ event = ioread32be(&fpm_rg->fmfp_ee);
+ /* clear the all occurred events */
+ iowrite32be(event, &fpm_rg->fmfp_ee);
+ return event;
+}
+
+uint32_t fman_get_muram_err_event(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ uint32_t event, mask;
+
+ event = ioread32be(&fpm_rg->fm_rcr);
+ mask = ioread32be(&fpm_rg->fm_rie);
+
+ /* clear MURAM event bit (do not clear IRAM event) */
+ iowrite32be(event & ~FPM_RAM_IRAM_ECC, &fpm_rg->fm_rcr);
+
+ if ((mask & FPM_MURAM_ECC_ERR_EX_EN))
+ return event;
+ else
+ return 0;
+}
+
+uint32_t fman_get_iram_err_event(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ uint32_t event, mask;
+
+ event = ioread32be(&fpm_rg->fm_rcr);
+ mask = ioread32be(&fpm_rg->fm_rie);
+ /* clear IRAM event bit (do not clear MURAM event) */
+ iowrite32be(event & ~FPM_RAM_MURAM_ECC, &fpm_rg->fm_rcr);
+
+ if ((mask & FPM_IRAM_ECC_ERR_EX_EN))
+ return event;
+ else
+ return 0;
+}
+
+uint32_t fman_get_qmi_event(struct fman_qmi_regs __iomem *qmi_rg)
+{
+ uint32_t event, mask, force;
+
+ event = ioread32be(&qmi_rg->fmqm_ie);
+ mask = ioread32be(&qmi_rg->fmqm_ien);
+ event &= mask;
+ /* clear the forced events */
+ force = ioread32be(&qmi_rg->fmqm_if);
+ if (force & event)
+ iowrite32be(force & ~event, &qmi_rg->fmqm_if);
+ /* clear the acknowledged events */
+ iowrite32be(event, &qmi_rg->fmqm_ie);
+ return event;
+}
+
+void fman_enable_time_stamp(struct fman_fpm_regs __iomem *fpm_rg,
+ uint8_t count1ubit, uint16_t fm_clk_freq)
+{
+ uint32_t tmp;
+ uint64_t frac;
+ uint32_t intgr;
+ uint32_t ts_freq = (uint32_t)(1 << count1ubit); /* in Mhz */
+
+ /* configure timestamp so that bit 8 will count 1 microsecond
+ * Find effective count rate at TIMESTAMP least significant bits:
+ * Effective_Count_Rate = 1MHz x 2^8 = 256MHz
+ * Find frequency ratio between effective count rate and the clock:
+ * Effective_Count_Rate / CLK e.g. for 600 MHz clock:
+ * 256/600 = 0.4266666...
+ */
+
+ intgr = ts_freq / fm_clk_freq;
+ /* we multiply by 2^16 to keep the fraction of the division
+ * we do not div back, since we write this value as a fraction
+ * see spec
+ */
+
+ frac = ((ts_freq << 16) - (intgr << 16) * fm_clk_freq) / fm_clk_freq;
+ /* we check remainder of the division in order to round up if not int */
+ if (((ts_freq << 16) - (intgr << 16) * fm_clk_freq) % fm_clk_freq)
+ frac++;
+
+ tmp = (intgr << FPM_TS_INT_SHIFT) | (uint16_t)frac;
+ iowrite32be(tmp, &fpm_rg->fmfp_tsc2);
+
+ /* enable timestamp with original clock */
+ iowrite32be(FPM_TS_CTL_EN, &fpm_rg->fmfp_tsc1);
+}
+
+uint32_t fman_get_fpm_error_interrupts(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ return ioread32be(&fpm_rg->fm_epi);
+}
+
+int fman_set_erratum_10gmac_a004_wa(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ int timeout = 100;
+
+ iowrite32be(0x40000000, &fpm_rg->fmfp_extc);
+
+ while ((ioread32be(&fpm_rg->fmfp_extc) & 0x40000000) && --timeout)
+ usleep_range(10, 11);
+
+ if (!timeout)
+ return -EIO;
+ return 0;
+}
+
+void fman_set_order_restoration_per_port(struct fman_fpm_regs __iomem *fpm_rg,
+ uint8_t port_id, bool is_rx_port)
+{
+ uint32_t tmp = 0;
+
+ tmp = (uint32_t)(port_id << FPM_PORT_FM_CTL_PORTID_SHIFT);
+
+ tmp |= (FPM_PRT_FM_CTL2 | FPM_PRT_FM_CTL1);
+
+ /* order restoration */
+ if (port_id % 2)
+ tmp |= (FPM_PRT_FM_CTL1 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+ else
+ tmp |= (FPM_PRT_FM_CTL2 << FPM_PRC_ORA_FM_CTL_SEL_SHIFT);
+
+ iowrite32be(tmp, &fpm_rg->fmfp_prc);
+}
+
+uint8_t fman_get_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg)
+{
+ return (uint8_t)ioread32be(&qmi_rg->fmqm_gc);
+}
+
+uint8_t fman_get_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg)
+{
+ return (uint8_t)(ioread32be(&qmi_rg->fmqm_gc) >> 8);
+}
+
+void fman_set_qmi_enq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&qmi_rg->fmqm_gc);
+ tmp_reg &= ~QMI_CFG_ENQ_MASK;
+ tmp_reg |= ((uint32_t)val << 8);
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_gc);
+}
+
+void fman_set_qmi_deq_th(struct fman_qmi_regs __iomem *qmi_rg, uint8_t val)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&qmi_rg->fmqm_gc);
+ tmp_reg &= ~QMI_CFG_DEQ_MASK;
+ tmp_reg |= (uint32_t)val;
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_gc);
+}
+
+void fman_set_liodn_per_port(struct fman_rg *fman_rg, uint8_t port_id,
+ uint16_t liodn_base, uint16_t liodn_ofst)
+{
+ uint32_t tmp;
+
+ /* set LIODN base for this port */
+ tmp = ioread32be(&fman_rg->dma_rg->fmdmplr[port_id / 2]);
+ if (port_id % 2) {
+ tmp &= ~FM_LIODN_BASE_MASK;
+ tmp |= (uint32_t)liodn_base;
+ } else {
+ tmp &= ~(FM_LIODN_BASE_MASK << DMA_LIODN_SHIFT);
+ tmp |= (uint32_t)liodn_base << DMA_LIODN_SHIFT;
+ }
+ iowrite32be(tmp, &fman_rg->dma_rg->fmdmplr[port_id / 2]);
+ iowrite32be((uint32_t)liodn_ofst,
+ &fman_rg->bmi_rg->fmbm_spliodn[port_id - 1]);
+}
+
+int fman_reset_mac(struct fman_fpm_regs __iomem *fpm_rg, uint8_t mac_id)
+{
+ uint32_t msk, timeout = 100;
+
+ /* Get the relevant bit mask */
+ switch (mac_id) {
+ case 0:
+ msk = FPM_RSTC_MAC0_RESET;
+ break;
+ case 1:
+ msk = FPM_RSTC_MAC1_RESET;
+ break;
+ case 2:
+ msk = FPM_RSTC_MAC2_RESET;
+ break;
+ case 3:
+ msk = FPM_RSTC_MAC3_RESET;
+ break;
+ case 4:
+ msk = FPM_RSTC_MAC4_RESET;
+ break;
+ case 5:
+ msk = FPM_RSTC_MAC5_RESET;
+ break;
+ case 6:
+ msk = FPM_RSTC_MAC6_RESET;
+ break;
+ case 7:
+ msk = FPM_RSTC_MAC7_RESET;
+ break;
+ case 8:
+ msk = FPM_RSTC_MAC8_RESET;
+ break;
+ case 9:
+ msk = FPM_RSTC_MAC9_RESET;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* reset */
+ iowrite32be(msk, &fpm_rg->fm_rstc);
+ while ((ioread32be(&fpm_rg->fm_rstc) & msk) && --timeout)
+ usleep_range(10, 11);
+
+ if (!timeout)
+ return -EIO;
+ return 0;
+}
+
+uint16_t fman_get_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id - 1]);
+ return (uint16_t)((tmp_reg & BMI_FIFO_SIZE_MASK) + 1);
+}
+
+uint16_t fman_get_size_of_extra_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&bmi_rg->fmbm_pfs[port_id - 1]);
+ return (uint16_t)((tmp_reg & BMI_EXTRA_FIFO_SIZE_MASK) >>
+ BMI_EXTRA_FIFO_SIZE_SHIFT);
+}
+
+void fman_set_size_of_fifo(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id, uint32_t sz_fifo,
+ uint32_t extra_sz_fifo)
+{
+ uint32_t tmp;
+
+ /* calculate reg */
+ tmp = (uint32_t)((sz_fifo / FMAN_BMI_FIFO_UNITS - 1) |
+ ((extra_sz_fifo / FMAN_BMI_FIFO_UNITS) <<
+ BMI_EXTRA_FIFO_SIZE_SHIFT));
+ iowrite32be(tmp, &bmi_rg->fmbm_pfs[port_id - 1]);
+}
+
+uint8_t fman_get_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)(((tmp & BMI_NUM_OF_TASKS_MASK) >>
+ BMI_NUM_OF_TASKS_SHIFT) + 1);
+}
+
+uint8_t fman_get_num_extra_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_TASKS_MASK) >>
+ BMI_EXTRA_NUM_OF_TASKS_SHIFT);
+}
+
+void fman_set_num_of_tasks(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id, uint8_t num_tasks,
+ uint8_t num_extra_tasks)
+{
+ uint32_t tmp;
+
+ /* calculate reg */
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) &
+ ~(BMI_NUM_OF_TASKS_MASK | BMI_NUM_OF_EXTRA_TASKS_MASK);
+ tmp |= ((uint32_t)((num_tasks - 1) << BMI_NUM_OF_TASKS_SHIFT) |
+ (uint32_t)(num_extra_tasks << BMI_EXTRA_NUM_OF_TASKS_SHIFT));
+ iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]);
+}
+
+uint8_t fman_get_num_of_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)(((tmp & BMI_NUM_OF_DMAS_MASK) >>
+ BMI_NUM_OF_DMAS_SHIFT) + 1);
+}
+
+uint8_t fman_get_num_extra_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]);
+ return (uint8_t)((tmp & BMI_NUM_OF_EXTRA_DMAS_MASK) >>
+ BMI_EXTRA_NUM_OF_DMAS_SHIFT);
+}
+
+void fman_set_num_of_open_dmas(struct fman_bmi_regs __iomem *bmi_rg,
+ uint8_t port_id, uint8_t num_open_dmas,
+ uint8_t num_extra_open_dmas,
+ uint8_t total_num_dmas)
+{
+ uint32_t tmp = 0;
+
+ /* calculate reg */
+ tmp = ioread32be(&bmi_rg->fmbm_pp[port_id - 1]) &
+ ~(BMI_NUM_OF_DMAS_MASK | BMI_NUM_OF_EXTRA_DMAS_MASK);
+ tmp |= (uint32_t)(((num_open_dmas - 1) << BMI_NUM_OF_DMAS_SHIFT) |
+ (num_extra_open_dmas <<
+ BMI_EXTRA_NUM_OF_DMAS_SHIFT));
+ iowrite32be(tmp, &bmi_rg->fmbm_pp[port_id - 1]);
+
+ /* update total num of DMA's with committed number of open DMAS,
+ * and max uncommitted pool.
+ */
+ if (total_num_dmas) {
+ tmp = ioread32be(&bmi_rg->fmbm_cfg2) & ~BMI_CFG2_DMAS_MASK;
+ tmp |= (uint32_t)(total_num_dmas - 1) << BMI_CFG2_DMAS_SHIFT;
+ iowrite32be(tmp, &bmi_rg->fmbm_cfg2);
+ }
+}
+
+/* API Init unit functions */
+
+void fman_defconfig(struct fman_cfg *cfg)
+{
+ memset(cfg, 0, sizeof(struct fman_cfg));
+
+ cfg->catastrophic_err = DEFAULT_CATASTROPHIC_ERR;
+ cfg->dma_err = DEFAULT_DMA_ERR;
+ cfg->halt_on_external_activ = DEFAULT_HALT_ON_EXTERNAL_ACTIVATION;
+ cfg->halt_on_unrecov_ecc_err = DEFAULT_HALT_ON_UNRECOVERABLE_ECC_ERROR;
+ cfg->en_iram_test_mode = false;
+ cfg->en_muram_test_mode = false;
+ cfg->external_ecc_rams_enable = DEFAULT_EXTERNAL_ECC_RAMS_ENABLE;
+
+ cfg->dma_aid_override = DEFAULT_AID_OVERRIDE;
+ cfg->dma_aid_mode = DEFAULT_AID_MODE;
+ cfg->dma_comm_qtsh_clr_emer = DEFAULT_DMA_COMM_Q_LOW;
+ cfg->dma_comm_qtsh_asrt_emer = DEFAULT_DMA_COMM_Q_HIGH;
+ cfg->dma_cache_override = DEFAULT_CACHE_OVERRIDE;
+ cfg->dma_cam_num_of_entries = DEFAULT_DMA_CAM_NUM_OF_ENTRIES;
+ cfg->dma_dbg_cnt_mode = DEFAULT_DMA_DBG_CNT_MODE;
+ cfg->dma_en_emergency = DEFAULT_DMA_EN_EMERGENCY;
+ cfg->dma_sos_emergency = DEFAULT_DMA_SOS_EMERGENCY;
+ cfg->dma_watchdog = DEFAULT_DMA_WATCHDOG;
+ cfg->dma_en_emergency_smoother = DEFAULT_DMA_EN_EMERGENCY_SMOOTHER;
+ cfg->dma_emergency_switch_counter =
+ DEFAULT_DMA_EMERGENCY_SWITCH_COUNTER;
+ cfg->disp_limit_tsh = DEFAULT_DISP_LIMIT;
+ cfg->prs_disp_tsh = DEFAULT_PRS_DISP_TH;
+ cfg->plcr_disp_tsh = DEFAULT_PLCR_DISP_TH;
+ cfg->kg_disp_tsh = DEFAULT_KG_DISP_TH;
+ cfg->bmi_disp_tsh = DEFAULT_BMI_DISP_TH;
+ cfg->qmi_enq_disp_tsh = DEFAULT_QMI_ENQ_DISP_TH;
+ cfg->qmi_deq_disp_tsh = DEFAULT_QMI_DEQ_DISP_TH;
+ cfg->fm_ctl1_disp_tsh = DEFAULT_FM_CTL1_DISP_TH;
+ cfg->fm_ctl2_disp_tsh = DEFAULT_FM_CTL2_DISP_TH;
+
+ cfg->pedantic_dma = false;
+ cfg->tnum_aging_period = DEFAULT_TNUM_AGING_PERIOD;
+ cfg->dma_stop_on_bus_error = false;
+ cfg->qmi_deq_option_support = false;
+}
+
+/* fm_init
+ * Initializes the FM module
+ * h_fm - FM module descriptor
+ * Return 0 on success; Error code otherwise.
+ */
+int fman_dma_init(struct fman_dma_regs __iomem *dma_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+
+ /* Init DMA Registers */
+
+ /* clear status reg events */
+ tmp_reg = (DMA_STATUS_BUS_ERR | DMA_STATUS_READ_ECC |
+ DMA_STATUS_SYSTEM_WRITE_ECC | DMA_STATUS_FM_WRITE_ECC);
+ iowrite32be(ioread32be(&dma_rg->fmdmsr) | tmp_reg, &dma_rg->fmdmsr);
+
+ /* configure mode register */
+ tmp_reg = 0;
+ tmp_reg |= cfg->dma_cache_override << DMA_MODE_CACHE_OR_SHIFT;
+ if (cfg->dma_aid_override)
+ tmp_reg |= DMA_MODE_AID_OR;
+ if (cfg->exceptions & FMAN_EX_DMA_BUS_ERROR)
+ tmp_reg |= DMA_MODE_BER;
+ if ((cfg->exceptions & FMAN_EX_DMA_SYSTEM_WRITE_ECC) |
+ (cfg->exceptions & FMAN_EX_DMA_READ_ECC) |
+ (cfg->exceptions & FMAN_EX_DMA_FM_WRITE_ECC))
+ tmp_reg |= DMA_MODE_ECC;
+ if (cfg->dma_stop_on_bus_error)
+ tmp_reg |= DMA_MODE_SBER;
+ if (cfg->dma_axi_dbg_num_of_beats)
+ tmp_reg |= (uint32_t)(DMA_MODE_AXI_DBG_MASK &
+ ((cfg->dma_axi_dbg_num_of_beats -
+ 1) << DMA_MODE_AXI_DBG_SHIFT));
+
+ if (cfg->dma_en_emergency) {
+ tmp_reg |= cfg->dma_emergency_bus_select;
+ tmp_reg |= cfg->dma_emergency_level << DMA_MODE_EMER_LVL_SHIFT;
+ if (cfg->dma_en_emergency_smoother)
+ iowrite32be(cfg->dma_emergency_switch_counter,
+ &dma_rg->fmdmemsr);
+ }
+ tmp_reg |= ((cfg->dma_cam_num_of_entries / DMA_CAM_UNITS) - 1) <<
+ DMA_MODE_CEN_SHIFT;
+ tmp_reg |= DMA_MODE_SECURE_PROT;
+ tmp_reg |= cfg->dma_dbg_cnt_mode << DMA_MODE_DBG_SHIFT;
+ tmp_reg |= cfg->dma_aid_mode << DMA_MODE_AID_MODE_SHIFT;
+
+ if (cfg->pedantic_dma)
+ tmp_reg |= DMA_MODE_EMER_READ;
+
+ iowrite32be(tmp_reg, &dma_rg->fmdmmr);
+
+ /* configure thresholds register */
+ tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_asrt_emer <<
+ DMA_THRESH_COMMQ_SHIFT) |
+ ((uint32_t)cfg->dma_read_buf_tsh_asrt_emer <<
+ DMA_THRESH_READ_INT_BUF_SHIFT) |
+ ((uint32_t)cfg->dma_write_buf_tsh_asrt_emer);
+
+ iowrite32be(tmp_reg, &dma_rg->fmdmtr);
+
+ /* configure hysteresis register */
+ tmp_reg = ((uint32_t)cfg->dma_comm_qtsh_clr_emer <<
+ DMA_THRESH_COMMQ_SHIFT) |
+ ((uint32_t)cfg->dma_read_buf_tsh_clr_emer <<
+ DMA_THRESH_READ_INT_BUF_SHIFT) |
+ ((uint32_t)cfg->dma_write_buf_tsh_clr_emer);
+
+ iowrite32be(tmp_reg, &dma_rg->fmdmhy);
+
+ /* configure emergency threshold */
+ iowrite32be(cfg->dma_sos_emergency, &dma_rg->fmdmsetr);
+
+ /* configure Watchdog */
+ iowrite32be((cfg->dma_watchdog * cfg->clk_freq), &dma_rg->fmdmwcr);
+
+ iowrite32be(cfg->cam_base_addr, &dma_rg->fmdmebcr);
+
+ return 0;
+}
+
+int fman_fpm_init(struct fman_fpm_regs __iomem *fpm_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+ int i;
+
+ /* Init FPM Registers */
+
+ tmp_reg = (uint32_t)(cfg->disp_limit_tsh << FPM_DISP_LIMIT_SHIFT);
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_mxd);
+
+ tmp_reg = (((uint32_t)cfg->prs_disp_tsh << FPM_THR1_PRS_SHIFT) |
+ ((uint32_t)cfg->kg_disp_tsh << FPM_THR1_KG_SHIFT) |
+ ((uint32_t)cfg->plcr_disp_tsh << FPM_THR1_PLCR_SHIFT) |
+ ((uint32_t)cfg->bmi_disp_tsh << FPM_THR1_BMI_SHIFT));
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_dist1);
+
+ tmp_reg =
+ (((uint32_t)cfg->qmi_enq_disp_tsh << FPM_THR2_QMI_ENQ_SHIFT) |
+ ((uint32_t)cfg->qmi_deq_disp_tsh << FPM_THR2_QMI_DEQ_SHIFT) |
+ ((uint32_t)cfg->fm_ctl1_disp_tsh << FPM_THR2_FM_CTL1_SHIFT) |
+ ((uint32_t)cfg->fm_ctl2_disp_tsh << FPM_THR2_FM_CTL2_SHIFT));
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_dist2);
+
+ /* define exceptions and error behavior */
+ tmp_reg = 0;
+ /* Clear events */
+ tmp_reg |= (FPM_EV_MASK_STALL | FPM_EV_MASK_DOUBLE_ECC |
+ FPM_EV_MASK_SINGLE_ECC);
+ /* enable interrupts */
+ if (cfg->exceptions & FMAN_EX_FPM_STALL_ON_TASKS)
+ tmp_reg |= FPM_EV_MASK_STALL_EN;
+ if (cfg->exceptions & FMAN_EX_FPM_SINGLE_ECC)
+ tmp_reg |= FPM_EV_MASK_SINGLE_ECC_EN;
+ if (cfg->exceptions & FMAN_EX_FPM_DOUBLE_ECC)
+ tmp_reg |= FPM_EV_MASK_DOUBLE_ECC_EN;
+ tmp_reg |= (cfg->catastrophic_err << FPM_EV_MASK_CAT_ERR_SHIFT);
+ tmp_reg |= (cfg->dma_err << FPM_EV_MASK_DMA_ERR_SHIFT);
+ if (!cfg->halt_on_external_activ)
+ tmp_reg |= FPM_EV_MASK_EXTERNAL_HALT;
+ if (!cfg->halt_on_unrecov_ecc_err)
+ tmp_reg |= FPM_EV_MASK_ECC_ERR_HALT;
+ iowrite32be(tmp_reg, &fpm_rg->fmfp_ee);
+
+ /* clear all fmCtls event registers */
+ for (i = 0; i < cfg->num_of_fman_ctrl_evnt_regs; i++)
+ iowrite32be(0xFFFFFFFF, &fpm_rg->fmfp_cev[i]);
+
+ /* RAM ECC - enable and clear events */
+ /* first we need to clear all parser memory,
+ * as it is uninitialized and may cause ECC errors
+ */
+ /* event bits */
+ tmp_reg = (FPM_RAM_MURAM_ECC | FPM_RAM_IRAM_ECC);
+ /* Rams enable not effected by RCR bit,
+ * but by a COP configuration
+ */
+ if (cfg->external_ecc_rams_enable)
+ tmp_reg |= FPM_RAM_RAMS_ECC_EN_SRC_SEL;
+
+ /* enable test mode */
+ if (cfg->en_muram_test_mode)
+ tmp_reg |= FPM_RAM_MURAM_TEST_ECC;
+ if (cfg->en_iram_test_mode)
+ tmp_reg |= FPM_RAM_IRAM_TEST_ECC;
+ iowrite32be(tmp_reg, &fpm_rg->fm_rcr);
+
+ tmp_reg = 0;
+ if (cfg->exceptions & FMAN_EX_IRAM_ECC) {
+ tmp_reg |= FPM_IRAM_ECC_ERR_EX_EN;
+ fman_enable_rams_ecc(fpm_rg);
+ }
+ if (cfg->exceptions & FMAN_EX_NURAM_ECC) {
+ tmp_reg |= FPM_MURAM_ECC_ERR_EX_EN;
+ fman_enable_rams_ecc(fpm_rg);
+ }
+ iowrite32be(tmp_reg, &fpm_rg->fm_rie);
+
+ return 0;
+}
+
+int fman_bmi_init(struct fman_bmi_regs __iomem *bmi_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+
+ /* Init BMI Registers */
+
+ /* define common resources */
+ tmp_reg = cfg->fifo_base_addr;
+ tmp_reg = tmp_reg / BMI_FIFO_ALIGN;
+
+ tmp_reg |= ((cfg->total_fifo_size / FMAN_BMI_FIFO_UNITS - 1) <<
+ BMI_CFG1_FIFO_SIZE_SHIFT);
+ iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg1);
+
+ tmp_reg = ((uint32_t)(cfg->total_num_of_tasks - 1) <<
+ BMI_CFG2_TASKS_SHIFT);
+ /* num of DMA's will be dynamically updated when each port is set */
+ iowrite32be(tmp_reg, &bmi_rg->fmbm_cfg2);
+
+ /* define unmaskable exceptions, enable and clear events */
+ tmp_reg = 0;
+ iowrite32be(BMI_ERR_INTR_EN_LIST_RAM_ECC |
+ BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC |
+ BMI_ERR_INTR_EN_STATISTICS_RAM_ECC |
+ BMI_ERR_INTR_EN_DISPATCH_RAM_ECC, &bmi_rg->fmbm_ievr);
+
+ if (cfg->exceptions & FMAN_EX_BMI_LIST_RAM_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ if (cfg->exceptions & FMAN_EX_BMI_PIPELINE_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ if (cfg->exceptions & FMAN_EX_BMI_STATISTICS_RAM_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ if (cfg->exceptions & FMAN_EX_BMI_DISPATCH_RAM_ECC)
+ tmp_reg |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ iowrite32be(tmp_reg, &bmi_rg->fmbm_ier);
+
+ return 0;
+}
+
+int fman_qmi_init(struct fman_qmi_regs __iomem *qmi_rg, struct fman_cfg *cfg)
+{
+ uint32_t tmp_reg;
+ uint16_t period_in_fm_clocks;
+ uint8_t remainder;
+
+ /* Init QMI Registers */
+
+ /* Clear error interrupt events */
+
+ iowrite32be(QMI_ERR_INTR_EN_DOUBLE_ECC | QMI_ERR_INTR_EN_DEQ_FROM_DEF,
+ &qmi_rg->fmqm_eie);
+ tmp_reg = 0;
+ if (cfg->exceptions & FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID)
+ tmp_reg |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ if (cfg->exceptions & FMAN_EX_QMI_DOUBLE_ECC)
+ tmp_reg |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+ /* enable events */
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_eien);
+
+ if (cfg->tnum_aging_period) {
+ /* tnum_aging_period is in units of usec,
+ * p_fmClockFreq in Mhz
+ */
+ period_in_fm_clocks = (uint16_t)
+ (cfg->tnum_aging_period * cfg->clk_freq);
+ /* period_in_fm_clocks must be a 64 multiple */
+ remainder = period_in_fm_clocks % 64;
+ if (remainder) {
+ tmp_reg = (uint32_t)((period_in_fm_clocks / 64) + 1);
+ } else {
+ tmp_reg = (uint32_t)(period_in_fm_clocks / 64);
+ if (!tmp_reg)
+ tmp_reg = 1;
+ }
+ tmp_reg <<= QMI_TAPC_TAP;
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_tapc);
+ }
+ tmp_reg = 0;
+ /* Clear interrupt events */
+ iowrite32be(QMI_INTR_EN_SINGLE_ECC, &qmi_rg->fmqm_ie);
+ if (cfg->exceptions & FMAN_EX_QMI_SINGLE_ECC)
+ tmp_reg |= QMI_INTR_EN_SINGLE_ECC;
+ /* enable events */
+ iowrite32be(tmp_reg, &qmi_rg->fmqm_ien);
+
+ return 0;
+}
+
+int fman_enable(struct fman_rg *fman_rg, struct fman_cfg *cfg)
+{
+ uint32_t cfg_reg = 0;
+
+ /* Enable all modules */
+
+ /* clear&enable global counters - calculate reg and save for later,
+ * because it's the same reg for QMI enable
+ */
+ cfg_reg = QMI_CFG_EN_COUNTERS;
+ if (cfg->qmi_deq_option_support)
+ cfg_reg |= (uint32_t)(((cfg->qmi_def_tnums_thresh) << 8) |
+ cfg->qmi_def_tnums_thresh);
+
+ iowrite32be(BMI_INIT_START, &fman_rg->bmi_rg->fmbm_init);
+ iowrite32be(cfg_reg | QMI_CFG_ENQ_EN | QMI_CFG_DEQ_EN,
+ &fman_rg->qmi_rg->fmqm_gc);
+
+ return 0;
+}
+
+void fman_free_resources(struct fman_rg *fman_rg)
+{
+ /* disable BMI and QMI */
+ iowrite32be(0, &fman_rg->bmi_rg->fmbm_init);
+ iowrite32be(0, &fman_rg->qmi_rg->fmqm_gc);
+
+ /* release BMI resources */
+ iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg2);
+ iowrite32be(0, &fman_rg->bmi_rg->fmbm_cfg1);
+
+ /* disable ECC */
+ iowrite32be(0, &fman_rg->fpm_rg->fm_rcr);
+}
+
+/* API Run-time Control uint functions */
+
+uint32_t fman_get_normal_pending(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ return ioread32be(&fpm_rg->fm_npi);
+}
+
+uint32_t fman_get_error_pending(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ return ioread32be(&fpm_rg->fm_epi);
+}
+
+void fman_enable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fm_rcr);
+ if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL)
+ iowrite32be(tmp | FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr);
+ else
+ iowrite32be(tmp | FPM_RAM_RAMS_ECC_EN |
+ FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr);
+}
+
+void fman_disable_rams_ecc(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fm_rcr);
+ if (tmp & FPM_RAM_RAMS_ECC_EN_SRC_SEL)
+ iowrite32be(tmp & ~FPM_RAM_IRAM_ECC_EN, &fpm_rg->fm_rcr);
+ else
+ iowrite32be(tmp & ~(FPM_RAM_RAMS_ECC_EN | FPM_RAM_IRAM_ECC_EN),
+ &fpm_rg->fm_rcr);
+}
+
+int fman_set_exception(struct fman_rg *fman_rg,
+ enum fman_exceptions exception, bool enable)
+{
+ uint32_t tmp;
+
+ switch (exception) {
+ case E_FMAN_EX_DMA_BUS_ERROR:
+ tmp = ioread32be(&fman_rg->dma_rg->fmdmmr);
+ if (enable)
+ tmp |= DMA_MODE_BER;
+ else
+ tmp &= ~DMA_MODE_BER;
+ /* disable bus error */
+ iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr);
+ break;
+ case E_FMAN_EX_DMA_READ_ECC:
+ case E_FMAN_EX_DMA_SYSTEM_WRITE_ECC:
+ case E_FMAN_EX_DMA_FM_WRITE_ECC:
+ tmp = ioread32be(&fman_rg->dma_rg->fmdmmr);
+ if (enable)
+ tmp |= DMA_MODE_ECC;
+ else
+ tmp &= ~DMA_MODE_ECC;
+ iowrite32be(tmp, &fman_rg->dma_rg->fmdmmr);
+ break;
+ case E_FMAN_EX_FPM_STALL_ON_TASKS:
+ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+ if (enable)
+ tmp |= FPM_EV_MASK_STALL_EN;
+ else
+ tmp &= ~FPM_EV_MASK_STALL_EN;
+ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+ break;
+ case E_FMAN_EX_FPM_SINGLE_ECC:
+ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+ if (enable)
+ tmp |= FPM_EV_MASK_SINGLE_ECC_EN;
+ else
+ tmp &= ~FPM_EV_MASK_SINGLE_ECC_EN;
+ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+ break;
+ case E_FMAN_EX_FPM_DOUBLE_ECC:
+ tmp = ioread32be(&fman_rg->fpm_rg->fmfp_ee);
+ if (enable)
+ tmp |= FPM_EV_MASK_DOUBLE_ECC_EN;
+ else
+ tmp &= ~FPM_EV_MASK_DOUBLE_ECC_EN;
+ iowrite32be(tmp, &fman_rg->fpm_rg->fmfp_ee);
+ break;
+ case E_FMAN_EX_QMI_SINGLE_ECC:
+ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_ien);
+ if (enable)
+ tmp |= QMI_INTR_EN_SINGLE_ECC;
+ else
+ tmp &= ~QMI_INTR_EN_SINGLE_ECC;
+ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_ien);
+ break;
+ case E_FMAN_EX_QMI_DOUBLE_ECC:
+ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien);
+ if (enable)
+ tmp |= QMI_ERR_INTR_EN_DOUBLE_ECC;
+ else
+ tmp &= ~QMI_ERR_INTR_EN_DOUBLE_ECC;
+ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien);
+ break;
+ case E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID:
+ tmp = ioread32be(&fman_rg->qmi_rg->fmqm_eien);
+ if (enable)
+ tmp |= QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ else
+ tmp &= ~QMI_ERR_INTR_EN_DEQ_FROM_DEF;
+ iowrite32be(tmp, &fman_rg->qmi_rg->fmqm_eien);
+ break;
+ case E_FMAN_EX_BMI_LIST_RAM_ECC:
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_LIST_RAM_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case E_FMAN_EX_BMI_STORAGE_PROFILE_ECC:
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case E_FMAN_EX_BMI_STATISTICS_RAM_ECC:
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_STATISTICS_RAM_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case E_FMAN_EX_BMI_DISPATCH_RAM_ECC:
+ tmp = ioread32be(&fman_rg->bmi_rg->fmbm_ier);
+ if (enable)
+ tmp |= BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ else
+ tmp &= ~BMI_ERR_INTR_EN_DISPATCH_RAM_ECC;
+ iowrite32be(tmp, &fman_rg->bmi_rg->fmbm_ier);
+ break;
+ case E_FMAN_EX_IRAM_ECC:
+ tmp = ioread32be(&fman_rg->fpm_rg->fm_rie);
+ if (enable) {
+ /* enable ECC if not enabled */
+ fman_enable_rams_ecc(fman_rg->fpm_rg);
+ /* enable ECC interrupts */
+ tmp |= FPM_IRAM_ECC_ERR_EX_EN;
+ } else {
+ /* ECC mechanism may be disabled,
+ * depending on driver status
+ */
+ fman_disable_rams_ecc(fman_rg->fpm_rg);
+ tmp &= ~FPM_IRAM_ECC_ERR_EX_EN;
+ }
+ iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie);
+ break;
+ case E_FMAN_EX_MURAM_ECC:
+ tmp = ioread32be(&fman_rg->fpm_rg->fm_rie);
+ if (enable) {
+ /* enable ECC if not enabled */
+ fman_enable_rams_ecc(fman_rg->fpm_rg);
+ /* enable ECC interrupts */
+ tmp |= FPM_MURAM_ECC_ERR_EX_EN;
+ } else {
+ /* ECC mechanism may be disabled,
+ * depending on driver status
+ */
+ fman_disable_rams_ecc(fman_rg->fpm_rg);
+ tmp &= ~FPM_MURAM_ECC_ERR_EX_EN;
+ }
+ iowrite32be(tmp, &fman_rg->fpm_rg->fm_rie);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+void fman_get_revision(struct fman_fpm_regs __iomem *fpm_rg,
+ uint8_t *major, uint8_t *minor)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fm_ip_rev_1);
+ *major =
+ (uint8_t)((tmp & FPM_REV1_MAJOR_MASK) >> FPM_REV1_MAJOR_SHIFT);
+ *minor =
+ (uint8_t)((tmp & FPM_REV1_MINOR_MASK) >> FPM_REV1_MINOR_SHIFT);
+}
+
+bool fman_is_qmi_halt_not_busy_state(struct fman_qmi_regs __iomem *qmi_rg)
+{
+ return !!(ioread32be(&qmi_rg->fmqm_gs) & QMI_GS_HALT_NOT_BUSY);
+}
+
+void fman_resume(struct fman_fpm_regs __iomem *fpm_rg)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(&fpm_rg->fmfp_ee);
+ /* clear tmp_reg event bits in order not to clear standing events */
+ tmp &= ~(FPM_EV_MASK_DOUBLE_ECC |
+ FPM_EV_MASK_STALL | FPM_EV_MASK_SINGLE_ECC);
+ tmp |= FPM_EV_MASK_RELEASE_FM;
+
+ iowrite32be(tmp, &fpm_rg->fmfp_ee);
+}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers
2015-05-07 13:05 ` [RFC,v3 02/12] fsl/fman: Add the FMan FLIB Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
The FMan Port Flib provides basic API used by the drivers to
configure and control the FMan Port hardware.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
.../net/ethernet/freescale/fman/flib/fman_common.h | 73 ++++
.../ethernet/freescale/fman/flib/fsl_fman_port.h | 462 +++++++++++++++++++++
.../net/ethernet/freescale/fman/flib/fsl_fman_sp.h | 66 +++
3 files changed, 601 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fman_common.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h
diff --git a/drivers/net/ethernet/freescale/fman/flib/fman_common.h b/drivers/net/ethernet/freescale/fman/flib/fman_common.h
new file mode 100644
index 0000000..e186ed9
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fman_common.h
@@ -0,0 +1,73 @@
+/*
+ * 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 __FMAN_COMMON_H
+#define __FMAN_COMMON_H
+
+/* NIA Description */
+#define NIA_ORDER_RESTOR 0x00800000
+#define NIA_ENG_FM_CTL 0x00000000
+#define NIA_ENG_PRS 0x00440000
+#define NIA_ENG_KG 0x00480000
+#define NIA_ENG_PLCR 0x004C0000
+#define NIA_ENG_BMI 0x00500000
+#define NIA_ENG_QMI_ENQ 0x00540000
+#define NIA_ENG_QMI_DEQ 0x00580000
+#define NIA_ENG_MASK 0x007C0000
+
+#define NIA_FM_CTL_AC_CC 0x00000006
+#define NIA_FM_CTL_AC_HC 0x0000000C
+#define NIA_FM_CTL_AC_IND_MODE_TX 0x00000008
+#define NIA_FM_CTL_AC_IND_MODE_RX 0x0000000A
+#define NIA_FM_CTL_AC_FRAG 0x0000000e
+#define NIA_FM_CTL_AC_PRE_FETCH 0x00000010
+#define NIA_FM_CTL_AC_POST_FETCH_PCD 0x00000012
+#define NIA_FM_CTL_AC_POST_FETCH_PCD_UDP_LEN 0x00000018
+#define NIA_FM_CTL_AC_POST_FETCH_NO_PCD 0x00000012
+#define NIA_FM_CTL_AC_FRAG_CHECK 0x00000014
+#define NIA_FM_CTL_AC_PRE_CC 0x00000020
+
+#define NIA_BMI_AC_ENQ_FRAME 0x00000002
+#define NIA_BMI_AC_TX_RELEASE 0x000002C0
+#define NIA_BMI_AC_RELEASE 0x000000C0
+#define NIA_BMI_AC_DISCARD 0x000000C1
+#define NIA_BMI_AC_TX 0x00000274
+#define NIA_BMI_AC_FETCH 0x00000208
+#define NIA_BMI_AC_MASK 0x000003FF
+
+#define NIA_KG_DIRECT 0x00000100
+#define NIA_KG_CC_EN 0x00000200
+#define NIA_PLCR_ABSOLUTE 0x00008000
+
+#define NIA_BMI_AC_ENQ_FRAME_WITHOUT_DMA 0x00000202
+#define NIA_BMI_AC_FETCH_ALL_FRAME 0x0000020c
+
+#endif /* __FMAN_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h
new file mode 100644
index 0000000..8903c99
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_port.h
@@ -0,0 +1,462 @@
+/*
+ * 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 __FSL_FMAN_PORT_H
+#define __FSL_FMAN_PORT_H
+
+#include "fsl_fman_sp.h"
+
+/* Registers bit fields */
+
+/* BMI defines */
+#define BMI_EBD_EN 0x80000000
+
+#define BMI_PORT_CFG_EN 0x80000000
+#define BMI_PORT_CFG_FDOVR 0x02000000
+#define BMI_PORT_CFG_IM 0x01000000
+
+#define BMI_PORT_STATUS_BSY 0x80000000
+
+#define BMI_DMA_ATTR_SWP_SHIFT FMAN_SP_DMA_ATTR_SWP_SHIFT
+#define BMI_DMA_ATTR_IC_STASH_ON 0x10000000
+#define BMI_DMA_ATTR_HDR_STASH_ON 0x04000000
+#define BMI_DMA_ATTR_SG_STASH_ON 0x01000000
+#define BMI_DMA_ATTR_WRITE_OPTIMIZE FMAN_SP_DMA_ATTR_WRITE_OPTIMIZE
+
+#define BMI_RX_FIFO_PRI_ELEVATION_SHIFT 16
+#define BMI_RX_FIFO_THRESHOLD_ETHE 0x80000000
+
+#define BMI_TX_FRAME_END_CS_IGNORE_SHIFT 24
+#define BMI_RX_FRAME_END_CS_IGNORE_SHIFT 24
+#define BMI_RX_FRAME_END_CUT_SHIFT 16
+
+#define BMI_IC_TO_EXT_SHIFT FMAN_SP_IC_TO_EXT_SHIFT
+#define BMI_IC_FROM_INT_SHIFT FMAN_SP_IC_FROM_INT_SHIFT
+
+#define BMI_INT_BUF_MARG_SHIFT 28
+#define BMI_EXT_BUF_MARG_START_SHIFT FMAN_SP_EXT_BUF_MARG_START_SHIFT
+
+#define BMI_CMD_MR_LEAC 0x00200000
+#define BMI_CMD_MR_SLEAC 0x00100000
+#define BMI_CMD_MR_MA 0x00080000
+#define BMI_CMD_MR_DEAS 0x00040000
+#define BMI_CMD_RX_MR_DEF (BMI_CMD_MR_LEAC | \
+ BMI_CMD_MR_SLEAC | \
+ BMI_CMD_MR_MA | \
+ BMI_CMD_MR_DEAS)
+#define BMI_CMD_TX_MR_DEF 0
+#define BMI_CMD_OP_MR_DEF (BMI_CMD_MR_DEAS | \
+ BMI_CMD_MR_MA)
+
+#define BMI_CMD_ATTR_ORDER 0x80000000
+#define BMI_CMD_ATTR_SYNC 0x02000000
+#define BMI_CMD_ATTR_COLOR_SHIFT 26
+
+#define BMI_FIFO_PIPELINE_DEPTH_SHIFT 12
+#define BMI_NEXT_ENG_FD_BITS_SHIFT 24
+#define BMI_FRAME_END_CS_IGNORE_SHIFT 24
+
+#define BMI_COUNTERS_EN 0x80000000
+
+#define BMI_EXT_BUF_POOL_VALID FMAN_SP_EXT_BUF_POOL_VALID
+#define BMI_EXT_BUF_POOL_EN_COUNTER FMAN_SP_EXT_BUF_POOL_EN_COUNTER
+#define BMI_EXT_BUF_POOL_BACKUP FMAN_SP_EXT_BUF_POOL_BACKUP
+#define BMI_EXT_BUF_POOL_ID_SHIFT 16
+#define BMI_EXT_BUF_POOL_ID_MASK 0x003F0000
+#define BMI_POOL_DEP_NUM_OF_POOLS_SHIFT 16
+
+#define BMI_TX_FIFO_MIN_FILL_SHIFT 16
+#define BMI_TX_FIFO_PIPELINE_DEPTH_SHIFT 12
+
+#define MAX_PERFORMANCE_TASK_COMP 64
+#define MAX_PERFORMANCE_RX_QUEUE_COMP 64
+#define MAX_PERFORMANCE_TX_QUEUE_COMP 8
+#define MAX_PERFORMANCE_DMA_COMP 16
+#define MAX_PERFORMANCE_FIFO_COMP 1024
+
+#define BMI_PERFORMANCE_TASK_COMP_SHIFT 24
+#define BMI_PERFORMANCE_QUEUE_COMP_SHIFT 16
+#define BMI_PERFORMANCE_DMA_COMP_SHIFT 12
+
+#define BMI_SG_DISABLE FMAN_SP_SG_DISABLE
+
+/* QMI defines */
+#define QMI_PORT_CFG_EN 0x80000000
+#define QMI_PORT_CFG_EN_COUNTERS 0x10000000
+
+#define QMI_PORT_STATUS_DEQ_TNUM_BSY 0x80000000
+#define QMI_PORT_STATUS_DEQ_FD_BSY 0x20000000
+
+#define QMI_DEQ_CFG_PRI 0x80000000
+#define QMI_DEQ_CFG_TYPE1 0x10000000
+#define QMI_DEQ_CFG_TYPE2 0x20000000
+#define QMI_DEQ_CFG_TYPE3 0x30000000
+#define QMI_DEQ_CFG_PREFETCH_PARTIAL 0x01000000
+#define QMI_DEQ_CFG_PREFETCH_FULL 0x03000000
+#define QMI_DEQ_CFG_SP_MASK 0xf
+#define QMI_DEQ_CFG_SP_SHIFT 20
+
+/* General port defines */
+#define FMAN_PORT_EXT_POOLS_NUM(fm_rev_maj) \
+ (((fm_rev_maj) == 4) ? 4 : 8)
+#define FMAN_PORT_MAX_EXT_POOLS_NUM 8
+#define FMAN_PORT_OBS_EXT_POOLS_NUM 2
+#define FMAN_PORT_CG_MAP_NUM 8
+#define FMAN_PORT_PRS_RESULT_WORDS_NUM 8
+#define FMAN_PORT_BMI_FIFO_UNITS 0x100
+#define FMAN_PORT_IC_OFFSET_UNITS 0x10
+
+/* FM Port Register Map */
+
+/* BMI Rx port register map */
+struct fman_port_rx_bmi_regs {
+ uint32_t fmbm_rcfg; /* Rx Configuration */
+ uint32_t fmbm_rst; /* Rx Status */
+ uint32_t fmbm_rda; /* Rx DMA attributes*/
+ uint32_t fmbm_rfp; /* Rx FIFO Parameters*/
+ uint32_t fmbm_rfed; /* Rx Frame End Data*/
+ uint32_t fmbm_ricp; /* Rx Internal Context Parameters*/
+ uint32_t fmbm_rim; /* Rx Internal Buffer Margins*/
+ uint32_t fmbm_rebm; /* Rx External Buffer Margins*/
+ uint32_t fmbm_rfne; /* Rx Frame Next Engine*/
+ uint32_t fmbm_rfca; /* Rx Frame Command Attributes.*/
+ uint32_t fmbm_rfpne; /* Rx Frame Parser Next Engine*/
+ uint32_t fmbm_rpso; /* Rx Parse Start Offset*/
+ uint32_t fmbm_rpp; /* Rx Policer Profile */
+ uint32_t fmbm_rccb; /* Rx Coarse Classification Base */
+ uint32_t fmbm_reth; /* Rx Excessive Threshold */
+ uint32_t reserved003c[1]; /* (0x03C 0x03F) */
+ uint32_t fmbm_rprai[FMAN_PORT_PRS_RESULT_WORDS_NUM];
+ /* Rx Parse Results Array Init*/
+ uint32_t fmbm_rfqid; /* Rx Frame Queue ID*/
+ uint32_t fmbm_refqid; /* Rx Error Frame Queue ID*/
+ uint32_t fmbm_rfsdm; /* Rx Frame Status Discard Mask*/
+ uint32_t fmbm_rfsem; /* Rx Frame Status Error Mask*/
+ uint32_t fmbm_rfene; /* Rx Frame Enqueue Next Engine */
+ uint32_t reserved0074[0x2]; /* (0x074-0x07C) */
+ uint32_t fmbm_rcmne; /* Rx Frame Continuous Mode Next Engine */
+ uint32_t reserved0080[0x20];/* (0x080 0x0FF) */
+ uint32_t fmbm_ebmpi[FMAN_PORT_MAX_EXT_POOLS_NUM];
+ /* Buffer Manager pool Information-*/
+ uint32_t fmbm_acnt[FMAN_PORT_MAX_EXT_POOLS_NUM];
+ /* Allocate Counter-*/
+ uint32_t reserved0130[8];
+ /* 0x130/0x140 - 0x15F reserved -*/
+ uint32_t fmbm_rcgm[FMAN_PORT_CG_MAP_NUM];
+ /* Congestion Group Map*/
+ uint32_t fmbm_mpd; /* BM Pool Depletion */
+ uint32_t reserved0184[0x1F]; /* (0x184 0x1FF) */
+ uint32_t fmbm_rstc; /* Rx Statistics Counters*/
+ uint32_t fmbm_rfrc; /* Rx Frame Counter*/
+ uint32_t fmbm_rfbc; /* Rx Bad Frames Counter*/
+ uint32_t fmbm_rlfc; /* Rx Large Frames Counter*/
+ uint32_t fmbm_rffc; /* Rx Filter Frames Counter*/
+ uint32_t fmbm_rfdc; /* Rx Frame Discard Counter*/
+ uint32_t fmbm_rfldec; /* Rx Frames List DMA Error Counter*/
+ uint32_t fmbm_rodc; /* Rx Out of Buffers Discard nntr*/
+ uint32_t fmbm_rbdc; /* Rx Buffers Deallocate Counter*/
+ uint32_t reserved0224[0x17]; /* (0x224 0x27F) */
+ uint32_t fmbm_rpc; /* Rx Performance Counters*/
+ uint32_t fmbm_rpcp; /* Rx Performance Count Parameters*/
+ uint32_t fmbm_rccn; /* Rx Cycle Counter*/
+ uint32_t fmbm_rtuc; /* Rx Tasks Utilization Counter*/
+ uint32_t fmbm_rrquc; /* Rx Receive Queue Utilization cntr*/
+ uint32_t fmbm_rduc; /* Rx DMA Utilization Counter*/
+ uint32_t fmbm_rfuc; /* Rx FIFO Utilization Counter*/
+ uint32_t fmbm_rpac; /* Rx Pause Activation Counter*/
+ uint32_t reserved02a0[0x18]; /* (0x2A0 0x2FF) */
+ uint32_t fmbm_rdbg; /* Rx Debug-*/
+};
+
+/* BMI Tx port register map */
+struct fman_port_tx_bmi_regs {
+ uint32_t fmbm_tcfg; /* Tx Configuration */
+ uint32_t fmbm_tst; /* Tx Status */
+ uint32_t fmbm_tda; /* Tx DMA attributes */
+ uint32_t fmbm_tfp; /* Tx FIFO Parameters */
+ uint32_t fmbm_tfed; /* Tx Frame End Data */
+ uint32_t fmbm_ticp; /* Tx Internal Context Parameters */
+ uint32_t fmbm_tfdne; /* Tx Frame Dequeue Next Engine. */
+ uint32_t fmbm_tfca; /* Tx Frame Command attribute. */
+ uint32_t fmbm_tcfqid; /* Tx Confirmation Frame Queue ID. */
+ uint32_t fmbm_tefqid; /* Tx Frame Error Queue ID */
+ uint32_t fmbm_tfene; /* Tx Frame Enqueue Next Engine */
+ uint32_t fmbm_trlmts; /* Tx Rate Limiter Scale */
+ uint32_t fmbm_trlmt; /* Tx Rate Limiter */
+ uint32_t reserved0034[0x0e]; /* (0x034-0x6c) */
+ uint32_t fmbm_tccb; /* Tx Coarse Classification base */
+ uint32_t fmbm_tfne; /* Tx Frame Next Engine */
+ /* Tx Priority based Flow Control (PFC) Mapping */
+ uint32_t fmbm_tpfcm[0x02];
+ /* Tx Frame Continuous Mode Next Engine */
+ uint32_t fmbm_tcmne;
+ uint32_t reserved0080[0x60]; /* (0x080-0x200) */
+ uint32_t fmbm_tstc; /* Tx Statistics Counters */
+ uint32_t fmbm_tfrc; /* Tx Frame Counter */
+ uint32_t fmbm_tfdc; /* Tx Frames Discard Counter */
+ uint32_t fmbm_tfledc; /* Tx Frame len error discard cntr */
+ uint32_t fmbm_tfufdc; /* Tx Frame unsprt frmt discard cntr*/
+ uint32_t fmbm_tbdc; /* Tx Buffers Deallocate Counter */
+ uint32_t reserved0218[0x1A]; /* (0x218-0x280) */
+ uint32_t fmbm_tpc; /* Tx Performance Counters*/
+ uint32_t fmbm_tpcp; /* Tx Performance Count Parameters*/
+ uint32_t fmbm_tccn; /* Tx Cycle Counter*/
+ uint32_t fmbm_ttuc; /* Tx Tasks Utilization Counter*/
+ uint32_t fmbm_ttcquc; /* Tx Transmit conf Q util Counter*/
+ uint32_t fmbm_tduc; /* Tx DMA Utilization Counter*/
+ uint32_t fmbm_tfuc; /* Tx FIFO Utilization Counter*/
+};
+
+/* BMI O/H port register map */
+struct fman_port_oh_bmi_regs {
+ uint32_t fmbm_ocfg; /* O/H Configuration */
+ uint32_t fmbm_ost; /* O/H Status */
+ uint32_t fmbm_oda; /* O/H DMA attributes */
+ uint32_t fmbm_oicp; /* O/H Internal Context Parameters */
+ uint32_t fmbm_ofdne; /* O/H Frame Dequeue Next Engine */
+ uint32_t fmbm_ofne; /* O/H Frame Next Engine */
+ uint32_t fmbm_ofca; /* O/H Frame Command Attributes. */
+ uint32_t fmbm_ofpne; /* O/H Frame Parser Next Engine */
+ uint32_t fmbm_opso; /* O/H Parse Start Offset */
+ uint32_t fmbm_opp; /* O/H Policer Profile */
+ uint32_t fmbm_occb; /* O/H Coarse Classification base */
+ uint32_t fmbm_oim; /* O/H Internal margins*/
+ uint32_t fmbm_ofp; /* O/H Fifo Parameters*/
+ uint32_t fmbm_ofed; /* O/H Frame End Data*/
+ uint32_t reserved0030[2]; /* (0x038 - 0x03F) */
+ uint32_t fmbm_oprai[FMAN_PORT_PRS_RESULT_WORDS_NUM];
+ /* O/H Parse Results Array Initialization */
+ uint32_t fmbm_ofqid; /* O/H Frame Queue ID */
+ uint32_t fmbm_oefqid; /* O/H Error Frame Queue ID */
+ uint32_t fmbm_ofsdm; /* O/H Frame Status Discard Mask */
+ uint32_t fmbm_ofsem; /* O/H Frame Status Error Mask */
+ uint32_t fmbm_ofene; /* O/H Frame Enqueue Next Engine */
+ uint32_t fmbm_orlmts; /* O/H Rate Limiter Scale */
+ uint32_t fmbm_orlmt; /* O/H Rate Limiter */
+ uint32_t fmbm_ocmne; /* O/H Continuous Mode Next Engine */
+ uint32_t reserved0080[0x20]; /* 0x080 - 0x0FF Reserved */
+ uint32_t fmbm_oebmpi[2]; /* Buf Mngr Observed Pool Info */
+ uint32_t reserved0108[0x16]; /* 0x108 - 0x15F Reserved */
+ uint32_t fmbm_ocgm; /* Observed Congestion Group Map */
+ uint32_t reserved0164[0x7]; /* 0x164 - 0x17F Reserved */
+ uint32_t fmbm_ompd; /* Observed BMan Pool Depletion */
+ uint32_t reserved0184[0x1F]; /* 0x184 - 0x1FF Reserved */
+ uint32_t fmbm_ostc; /* O/H Statistics Counters */
+ uint32_t fmbm_ofrc; /* O/H Frame Counter */
+ uint32_t fmbm_ofdc; /* O/H Frames Discard Counter */
+ uint32_t fmbm_ofledc; /* O/H Frames Len Err Discard Cntr */
+ uint32_t fmbm_ofufdc; /* O/H Frames Unsprtd Discard Cutr */
+ uint32_t fmbm_offc; /* O/H Filter Frames Counter */
+ uint32_t fmbm_ofwdc; /* Rx Frames WRED Discard Counter */
+ uint32_t fmbm_ofldec; /* O/H Frames List DMA Error Cntr */
+ uint32_t fmbm_obdc; /* O/H Buffers Deallocate Counter */
+ uint32_t reserved0218[0x17]; /* (0x218 - 0x27F) */
+ uint32_t fmbm_opc; /* O/H Performance Counters */
+ uint32_t fmbm_opcp; /* O/H Performance Count Parameters */
+ uint32_t fmbm_occn; /* O/H Cycle Counter */
+ uint32_t fmbm_otuc; /* O/H Tasks Utilization Counter */
+ uint32_t fmbm_oduc; /* O/H DMA Utilization Counter */
+ uint32_t fmbm_ofuc; /* O/H FIFO Utilization Counter */
+};
+
+/* BMI port register map */
+union fman_port_bmi_regs {
+ struct fman_port_rx_bmi_regs rx;
+ struct fman_port_tx_bmi_regs tx;
+ struct fman_port_oh_bmi_regs oh;
+};
+
+/* QMI port register map */
+struct fman_port_qmi_regs {
+ uint32_t fmqm_pnc; /* PortID n Configuration Register */
+ uint32_t fmqm_pns; /* PortID n Status Register */
+ uint32_t fmqm_pnts; /* PortID n Task Status Register */
+ uint32_t reserved00c[4]; /* 0xn00C - 0xn01B */
+ uint32_t fmqm_pnen; /* PortID n Enqueue NIA Register */
+ uint32_t fmqm_pnetfc; /* PortID n Enq Total Frame Counter */
+ uint32_t reserved024[2]; /* 0xn024 - 0x02B */
+ uint32_t fmqm_pndn; /* PortID n Dequeue NIA Register */
+ uint32_t fmqm_pndc; /* PortID n Dequeue Config Register */
+ uint32_t fmqm_pndtfc; /* PortID n Dequeue tot Frame cntr */
+ uint32_t fmqm_pndfdc; /* PortID n Dequeue FQID Dflt Cntr */
+ uint32_t fmqm_pndcc; /* PortID n Dequeue Confirm Counter */
+};
+
+enum fman_port_dma_swap {
+ E_FMAN_PORT_DMA_NO_SWAP, /* No swap, transfer data as is */
+ E_FMAN_PORT_DMA_SWAP_LE,
+ /* The transferred data should be swapped in PPC Little Endian mode */
+ E_FMAN_PORT_DMA_SWAP_BE
+ /* The transferred data should be swapped in Big Endian mode */
+};
+
+/* Default port color */
+enum fman_port_color {
+ E_FMAN_PORT_COLOR_GREEN, /* Default port color is green */
+ E_FMAN_PORT_COLOR_YELLOW, /* Default port color is yellow */
+ E_FMAN_PORT_COLOR_RED, /* Default port color is red */
+ E_FMAN_PORT_COLOR_OVERRIDE /* Ignore color */
+};
+
+/* QMI dequeue from the SP channel - types */
+enum fman_port_deq_type {
+ E_FMAN_PORT_DEQ_BY_PRI,
+ /* Priority precedence and Intra-Class scheduling */
+ E_FMAN_PORT_DEQ_ACTIVE_FQ,
+ /* Active FQ precedence and Intra-Class scheduling */
+ E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS
+ /* Active FQ precedence and override Intra-Class scheduling */
+};
+
+/* QMI dequeue prefetch modes */
+enum fman_port_deq_prefetch {
+ E_FMAN_PORT_DEQ_NO_PREFETCH, /* No prefetch mode */
+ E_FMAN_PORT_DEQ_PART_PREFETCH, /* Partial prefetch mode */
+ E_FMAN_PORT_DEQ_FULL_PREFETCH /* Full prefetch mode */
+};
+
+/* Parameters for defining performance counters behavior */
+struct fman_port_perf_cnt_params {
+ uint8_t task_val; /* Task compare value */
+ uint8_t queue_val;
+ /* Rx or Tx conf queue compare value (unused for O/H ports) */
+ uint8_t dma_val; /* Dma compare value */
+ uint32_t fifo_val; /* Fifo compare value (in bytes) */
+};
+
+/* FM Port configuration structure, used at init */
+struct fman_port_cfg {
+ struct fman_port_perf_cnt_params perf_cnt_params;
+ /* BMI parameters */
+ enum fman_port_dma_swap dma_swap_data;
+ bool dma_ic_stash_on;
+ bool dma_header_stash_on;
+ bool dma_sg_stash_on;
+ bool dma_write_optimize;
+ uint16_t ic_ext_offset;
+ uint8_t ic_int_offset;
+ uint16_t ic_size;
+ enum fman_port_color color;
+ bool sync_req;
+ bool discard_override;
+ uint8_t checksum_bytes_ignore;
+ uint8_t rx_cut_end_bytes;
+ uint32_t rx_pri_elevation;
+ uint32_t rx_fifo_thr;
+ uint8_t rx_fd_bits;
+ uint8_t int_buf_start_margin;
+ uint16_t ext_buf_start_margin;
+ uint16_t ext_buf_end_margin;
+ uint32_t tx_fifo_min_level;
+ uint32_t tx_fifo_low_comf_level;
+ uint8_t tx_fifo_deq_pipeline_depth;
+ bool stats_counters_enable;
+ bool perf_counters_enable;
+ /* QMI parameters */
+ bool deq_high_pri;
+ enum fman_port_deq_type deq_type;
+ enum fman_port_deq_prefetch deq_prefetch_opt;
+ uint16_t deq_byte_cnt;
+ bool queue_counters_enable;
+ bool no_scatter_gather;
+ int errata_A006675;
+ int errata_A006320;
+ int excessive_threshold_register;
+ int fmbm_rebm_has_sgd;
+ int fmbm_tfne_has_features;
+ int qmi_deq_options_support;
+};
+
+enum fman_port_type {
+ E_FMAN_PORT_TYPE_OP = 0,
+ /* Offline parsing port, shares id-s with
+ * host command, so must have exclusive id-s
+ */
+ E_FMAN_PORT_TYPE_RX, /* 1G Rx port */
+ E_FMAN_PORT_TYPE_RX_10G, /* 10G Rx port */
+ E_FMAN_PORT_TYPE_TX, /* 1G Tx port */
+ E_FMAN_PORT_TYPE_TX_10G, /* 10G Tx port */
+ E_FMAN_PORT_TYPE_DUMMY
+};
+
+struct fman_port_params {
+ uint32_t discard_mask;
+ uint32_t err_mask;
+ uint32_t dflt_fqid;
+ uint32_t err_fqid;
+ uint8_t deq_sp;
+ bool dont_release_buf;
+};
+
+/* Port context - used by most API functions */
+struct fman_port {
+ enum fman_port_type type;
+ uint8_t fm_rev_maj;
+ uint8_t fm_rev_min;
+ union fman_port_bmi_regs __iomem *bmi_regs;
+ struct fman_port_qmi_regs __iomem *qmi_regs;
+ uint8_t ext_pools_num;
+};
+
+/* External buffer pools configuration */
+struct fman_port_bpools {
+ uint8_t count; /* Num of pools to set up */
+ bool counters_enable; /* Enable allocate counters */
+ uint8_t grp_bp_depleted_num;
+ /* Number of depleted pools - if reached the BMI indicates
+ * the MAC to send a pause frame
+ */
+ struct {
+ uint8_t bpid; /* BM pool ID */
+ uint16_t size;
+ /* Pool's size - must be in ascending order */
+ bool is_backup;
+ /* If this is a backup pool */
+ bool grp_bp_depleted;
+ /* Consider this buffer in multiple pools depletion criteria*/
+ bool single_bp_depleted;
+ /* Consider this buffer in single pool depletion criteria */
+ } bpool[FMAN_PORT_MAX_EXT_POOLS_NUM];
+};
+
+
+/* FM Port API */
+void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type);
+int fman_port_init(struct fman_port *port,
+ struct fman_port_cfg *cfg, struct fman_port_params *params);
+int fman_port_enable(struct fman_port *port);
+int fman_port_disable(const struct fman_port *port);
+int fman_port_set_bpools(const struct fman_port *port,
+ const struct fman_port_bpools *bp);
+int fman_port_set_perf_cnt_params(struct fman_port *port,
+ struct fman_port_perf_cnt_params *params);
+
+#endif /* __FSL_FMAN_PORT_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h
new file mode 100644
index 0000000..0f7bce1
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_sp.h
@@ -0,0 +1,66 @@
+/*
+ * 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 __FSL_FMAN_SP_H
+#define __FSL_FMAN_SP_H
+
+#include "common/general.h"
+#include "fsl_fman.h"
+
+/* 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_POOL_ID_SHIFT 16
+#define FMAN_SP_POOL_DEP_NUM_OF_POOLS_SHIFT 16
+#define FMAN_SP_EXT_BUF_MARG_START_SHIFT 16
+#define FMAN_SP_EXT_BUF_MARG_END_SHIFT 0
+#define FMAN_SP_DMA_ATTR_SWP_SHIFT 30
+#define FMAN_SP_DMA_ATTR_IC_CACHE_SHIFT 28
+#define FMAN_SP_DMA_ATTR_HDR_CACHE_SHIFT 26
+#define FMAN_SP_DMA_ATTR_SG_CACHE_SHIFT 24
+#define FMAN_SP_IC_TO_EXT_SHIFT 16
+#define FMAN_SP_IC_FROM_INT_SHIFT 8
+#define FMAN_SP_IC_SIZE_SHIFT 0
+
+/* defaults */
+#define DEFAULT_FMAN_SP_DMA_SWAP_DATA FMAN_DMA_NO_SWP
+#define DEFAULT_FMAN_SP_DMA_INT_CONTEXT_CACHE_ATTR FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_HEADER_CACHE_ATTR FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_SCATTER_GATHER_CACHE_ATTR FMAN_DMA_NO_STASH
+#define DEFAULT_FMAN_SP_DMA_WRITE_OPTIMIZE true
+#define DEFAULT_FMAN_SP_NO_SCATTER_GATHER false
+
+#endif /* __FSL_FMAN_SP_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB
2015-05-07 13:05 ` [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
The FMan Port FLib provides basic API used by the drivers to
configure and control the FMan Port hardware.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
drivers/net/ethernet/freescale/fman/Kconfig | 1 +
drivers/net/ethernet/freescale/fman/Makefile | 2 +
drivers/net/ethernet/freescale/fman/port/Makefile | 3 +
.../net/ethernet/freescale/fman/port/fman_port.c | 728 +++++++++++++++++++++
4 files changed, 734 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/fman/port/Makefile
create mode 100644 drivers/net/ethernet/freescale/fman/port/fman_port.c
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index 8aeae29..af42c3a 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -5,3 +5,4 @@ config FSL_FMAN
help
Freescale Data-Path Acceleration Architecture Frame Manager
(FMan) support
+
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index a718f7c..a9ae0aa 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -3,3 +3,5 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib
obj-y += fsl_fman.o
fsl_fman-objs := fman.o
+
+obj-y += port/
diff --git a/drivers/net/ethernet/freescale/fman/port/Makefile b/drivers/net/ethernet/freescale/fman/port/Makefile
new file mode 100644
index 0000000..54b1fa4
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/Makefile
@@ -0,0 +1,3 @@
+obj-y += fsl_fman_port.o
+
+fsl_fman_port-objs := fman_port.o
diff --git a/drivers/net/ethernet/freescale/fman/port/fman_port.c b/drivers/net/ethernet/freescale/fman/port/fman_port.c
new file mode 100644
index 0000000..7d04084
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/port/fman_port.c
@@ -0,0 +1,728 @@
+/*
+ * 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 "common/general.h"
+
+#include "fman_common.h"
+#include "fsl_fman_port.h"
+
+/* problem Eyal: the following should not be here*/
+#define NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME 0x00000028
+
+static uint32_t get_no_pcd_nia_bmi_ac_enc_frame(struct fman_port_cfg *cfg)
+{
+ if (cfg->errata_A006675)
+ return NIA_ENG_FM_CTL |
+ NIA_FM_CTL_AC_NO_IPACC_PRE_BMI_ENQ_FRAME;
+ else
+ return NIA_ENG_BMI | NIA_BMI_AC_ENQ_FRAME;
+}
+
+static int init_bmi_rx(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ struct fman_port_rx_bmi_regs __iomem *regs = &port->bmi_regs->rx;
+ uint32_t tmp;
+
+ /* Rx Configuration register */
+ tmp = 0;
+ if (cfg->discard_override)
+ tmp |= BMI_PORT_CFG_FDOVR;
+ iowrite32be(tmp, ®s->fmbm_rcfg);
+
+ /* DMA attributes */
+ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+ if (cfg->dma_ic_stash_on)
+ tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+ if (cfg->dma_header_stash_on)
+ tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+ if (cfg->dma_sg_stash_on)
+ tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+ if (cfg->dma_write_optimize)
+ tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+ iowrite32be(tmp, ®s->fmbm_rda);
+
+ /* Rx FIFO parameters */
+ tmp = (cfg->rx_pri_elevation / FMAN_PORT_BMI_FIFO_UNITS - 1) <<
+ BMI_RX_FIFO_PRI_ELEVATION_SHIFT;
+ tmp |= cfg->rx_fifo_thr / FMAN_PORT_BMI_FIFO_UNITS - 1;
+ iowrite32be(tmp, ®s->fmbm_rfp);
+
+ if (cfg->excessive_threshold_register)
+ /* always allow access to the extra resources */
+ iowrite32be(BMI_RX_FIFO_THRESHOLD_ETHE, ®s->fmbm_reth);
+
+ /* Frame end data */
+ tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+ BMI_RX_FRAME_END_CS_IGNORE_SHIFT;
+ tmp |= (uint32_t)cfg->rx_cut_end_bytes << BMI_RX_FRAME_END_CUT_SHIFT;
+ if (cfg->errata_A006320)
+ tmp &= 0xffe0ffff;
+ iowrite32be(tmp, ®s->fmbm_rfed);
+
+ /* Internal context parameters */
+ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_TO_EXT_SHIFT;
+ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_FROM_INT_SHIFT;
+ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+ iowrite32be(tmp, ®s->fmbm_ricp);
+
+ /* Internal buffer offset */
+ tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+ << BMI_INT_BUF_MARG_SHIFT;
+ iowrite32be(tmp, ®s->fmbm_rim);
+
+ /* External buffer margins */
+ tmp = (uint32_t)cfg->ext_buf_start_margin <<
+ BMI_EXT_BUF_MARG_START_SHIFT;
+ tmp |= (uint32_t)cfg->ext_buf_end_margin;
+ if (cfg->fmbm_rebm_has_sgd && cfg->no_scatter_gather)
+ tmp |= BMI_SG_DISABLE;
+ iowrite32be(tmp, ®s->fmbm_rebm);
+
+ /* Frame attributes */
+ tmp = BMI_CMD_RX_MR_DEF;
+ tmp |= BMI_CMD_ATTR_ORDER;
+ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+ if (cfg->sync_req)
+ tmp |= BMI_CMD_ATTR_SYNC;
+
+ iowrite32be(tmp, ®s->fmbm_rfca);
+
+ /* NIA */
+ tmp = (uint32_t)cfg->rx_fd_bits << BMI_NEXT_ENG_FD_BITS_SHIFT;
+ tmp |= get_no_pcd_nia_bmi_ac_enc_frame(cfg);
+
+ iowrite32be(tmp, ®s->fmbm_rfne);
+
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_rfene);
+
+ /* Default/error queues */
+ iowrite32be((params->dflt_fqid & 0x00FFFFFF), ®s->fmbm_rfqid);
+ iowrite32be((params->err_fqid & 0x00FFFFFF), ®s->fmbm_refqid);
+
+ /* Discard/error masks */
+ iowrite32be(params->discard_mask, ®s->fmbm_rfsdm);
+ iowrite32be(params->err_mask, ®s->fmbm_rfsem);
+
+ /* Statistics counters */
+ tmp = 0;
+ if (cfg->stats_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, ®s->fmbm_rstc);
+
+ /* Performance counters */
+ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+ tmp = 0;
+ if (cfg->perf_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, ®s->fmbm_rpc);
+
+ return 0;
+}
+
+static int init_bmi_tx(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ struct fman_port_tx_bmi_regs __iomem *regs = &port->bmi_regs->tx;
+ uint32_t tmp;
+
+ /* Tx Configuration register */
+ tmp = 0;
+ iowrite32be(tmp, ®s->fmbm_tcfg);
+
+ /* DMA attributes */
+ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+ if (cfg->dma_ic_stash_on)
+ tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+ if (cfg->dma_header_stash_on)
+ tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+ if (cfg->dma_sg_stash_on)
+ tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+ iowrite32be(tmp, ®s->fmbm_tda);
+
+ /* Tx FIFO parameters */
+ tmp = (cfg->tx_fifo_min_level / FMAN_PORT_BMI_FIFO_UNITS) <<
+ BMI_TX_FIFO_MIN_FILL_SHIFT;
+ tmp |= ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+ BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+ tmp |= (uint32_t)(cfg->tx_fifo_low_comf_level /
+ FMAN_PORT_BMI_FIFO_UNITS - 1);
+ iowrite32be(tmp, ®s->fmbm_tfp);
+
+ /* Frame end data */
+ tmp = (uint32_t)cfg->checksum_bytes_ignore <<
+ BMI_FRAME_END_CS_IGNORE_SHIFT;
+ iowrite32be(tmp, ®s->fmbm_tfed);
+
+ /* Internal context parameters */
+ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_TO_EXT_SHIFT;
+ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_FROM_INT_SHIFT;
+ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+ iowrite32be(tmp, ®s->fmbm_ticp);
+
+ /* Frame attributes */
+ tmp = BMI_CMD_TX_MR_DEF;
+ tmp |= BMI_CMD_ATTR_ORDER;
+ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+ iowrite32be(tmp, ®s->fmbm_tfca);
+
+ /* Dequeue NIA + enqueue NIA */
+ iowrite32be(NIA_ENG_QMI_DEQ, ®s->fmbm_tfdne);
+ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR, ®s->fmbm_tfene);
+ if (cfg->fmbm_tfne_has_features)
+ iowrite32be(!params->dflt_fqid ?
+ BMI_EBD_EN | NIA_BMI_AC_FETCH_ALL_FRAME :
+ NIA_BMI_AC_FETCH_ALL_FRAME, ®s->fmbm_tfne);
+ if (!params->dflt_fqid && params->dont_release_buf) {
+ iowrite32be(0x00FFFFFF, ®s->fmbm_tcfqid);
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE,
+ ®s->fmbm_tfene);
+ if (cfg->fmbm_tfne_has_features)
+ iowrite32be(ioread32be(®s->fmbm_tfne) & ~BMI_EBD_EN,
+ ®s->fmbm_tfne);
+ }
+
+ /* Confirmation/error queues */
+ if (params->dflt_fqid || !params->dont_release_buf)
+ iowrite32be(params->dflt_fqid & 0x00FFFFFF, ®s->fmbm_tcfqid);
+ iowrite32be((params->err_fqid & 0x00FFFFFF), ®s->fmbm_tefqid);
+
+ /* Statistics counters */
+ tmp = 0;
+ if (cfg->stats_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, ®s->fmbm_tstc);
+
+ /* Performance counters */
+ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+ tmp = 0;
+ if (cfg->perf_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, ®s->fmbm_tpc);
+
+ return 0;
+}
+
+static int init_bmi_oh(struct fman_port *port,
+ struct fman_port_cfg *cfg,
+ struct fman_port_params *params)
+{
+ struct fman_port_oh_bmi_regs __iomem *regs = &port->bmi_regs->oh;
+ uint32_t tmp;
+
+ /* OP Configuration register */
+ tmp = 0;
+ if (cfg->discard_override)
+ tmp |= BMI_PORT_CFG_FDOVR;
+ iowrite32be(tmp, ®s->fmbm_ocfg);
+
+ /* DMA attributes */
+ tmp = (uint32_t)cfg->dma_swap_data << BMI_DMA_ATTR_SWP_SHIFT;
+ if (cfg->dma_ic_stash_on)
+ tmp |= BMI_DMA_ATTR_IC_STASH_ON;
+ if (cfg->dma_header_stash_on)
+ tmp |= BMI_DMA_ATTR_HDR_STASH_ON;
+ if (cfg->dma_sg_stash_on)
+ tmp |= BMI_DMA_ATTR_SG_STASH_ON;
+ if (cfg->dma_write_optimize)
+ tmp |= BMI_DMA_ATTR_WRITE_OPTIMIZE;
+ iowrite32be(tmp, ®s->fmbm_oda);
+
+ /* Tx FIFO parameters */
+ tmp = ((uint32_t)cfg->tx_fifo_deq_pipeline_depth - 1) <<
+ BMI_FIFO_PIPELINE_DEPTH_SHIFT;
+ iowrite32be(tmp, ®s->fmbm_ofp);
+
+ /* Internal context parameters */
+ tmp = ((uint32_t)cfg->ic_ext_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_TO_EXT_SHIFT;
+ tmp |= ((uint32_t)cfg->ic_int_offset / FMAN_PORT_IC_OFFSET_UNITS) <<
+ BMI_IC_FROM_INT_SHIFT;
+ tmp |= cfg->ic_size / FMAN_PORT_IC_OFFSET_UNITS;
+ iowrite32be(tmp, ®s->fmbm_oicp);
+
+ /* Frame attributes */
+ tmp = BMI_CMD_OP_MR_DEF;
+ tmp |= (uint32_t)cfg->color << BMI_CMD_ATTR_COLOR_SHIFT;
+ if (cfg->sync_req)
+ tmp |= BMI_CMD_ATTR_SYNC;
+ if (port->type == E_FMAN_PORT_TYPE_OP)
+ tmp |= BMI_CMD_ATTR_ORDER;
+ iowrite32be(tmp, ®s->fmbm_ofca);
+
+ /* Internal buffer offset */
+ tmp = ((uint32_t)cfg->int_buf_start_margin / FMAN_PORT_IC_OFFSET_UNITS)
+ << BMI_INT_BUF_MARG_SHIFT;
+ iowrite32be(tmp, ®s->fmbm_oim);
+
+ /* Dequeue NIA */
+ iowrite32be(NIA_ENG_QMI_DEQ, ®s->fmbm_ofdne);
+
+ /* NIA and Enqueue NIA */
+ iowrite32be(get_no_pcd_nia_bmi_ac_enc_frame(cfg),
+ ®s->fmbm_ofne);
+ iowrite32be(NIA_ENG_QMI_ENQ | NIA_ORDER_RESTOR,
+ ®s->fmbm_ofene);
+
+ /* Default/error queues */
+ iowrite32be((params->dflt_fqid & 0x00FFFFFF), ®s->fmbm_ofqid);
+ iowrite32be((params->err_fqid & 0x00FFFFFF), ®s->fmbm_oefqid);
+
+ /* Discard/error masks */
+ if (port->type == E_FMAN_PORT_TYPE_OP) {
+ iowrite32be(params->discard_mask, ®s->fmbm_ofsdm);
+ iowrite32be(params->err_mask, ®s->fmbm_ofsem);
+ }
+
+ /* Statistics counters */
+ tmp = 0;
+ if (cfg->stats_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, ®s->fmbm_ostc);
+
+ /* Performance counters */
+ fman_port_set_perf_cnt_params(port, &cfg->perf_cnt_params);
+ tmp = 0;
+ if (cfg->perf_counters_enable)
+ tmp = BMI_COUNTERS_EN;
+ iowrite32be(tmp, ®s->fmbm_opc);
+
+ return 0;
+}
+
+static int init_qmi(struct fman_port *port,
+ struct fman_port_cfg *cfg, struct fman_port_params *params)
+{
+ struct fman_port_qmi_regs __iomem *regs = port->qmi_regs;
+ uint32_t tmp;
+
+ tmp = 0;
+ if (cfg->queue_counters_enable)
+ tmp |= QMI_PORT_CFG_EN_COUNTERS;
+ iowrite32be(tmp, ®s->fmqm_pnc);
+
+ /* Rx port configuration */
+ if ((port->type == E_FMAN_PORT_TYPE_RX) ||
+ (port->type == E_FMAN_PORT_TYPE_RX_10G)) {
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, ®s->fmqm_pnen);
+ return 0;
+ }
+
+ /* Continue with Tx and O/H port configuration */
+ if ((port->type == E_FMAN_PORT_TYPE_TX) ||
+ (port->type == E_FMAN_PORT_TYPE_TX_10G)) {
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX_RELEASE,
+ ®s->fmqm_pnen);
+ /* Dequeue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_TX, ®s->fmqm_pndn);
+ } else {
+ /* Enqueue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_RELEASE, ®s->fmqm_pnen);
+ /* Dequeue NIA */
+ iowrite32be(NIA_ENG_BMI | NIA_BMI_AC_FETCH, ®s->fmqm_pndn);
+ }
+
+ /* Dequeue Configuration register */
+ tmp = 0;
+ if (cfg->deq_high_pri)
+ tmp |= QMI_DEQ_CFG_PRI;
+
+ switch (cfg->deq_type) {
+ case E_FMAN_PORT_DEQ_BY_PRI:
+ tmp |= QMI_DEQ_CFG_TYPE1;
+ break;
+ case E_FMAN_PORT_DEQ_ACTIVE_FQ:
+ tmp |= QMI_DEQ_CFG_TYPE2;
+ break;
+ case E_FMAN_PORT_DEQ_ACTIVE_FQ_NO_ICS:
+ tmp |= QMI_DEQ_CFG_TYPE3;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (cfg->qmi_deq_options_support) {
+ switch (cfg->deq_prefetch_opt) {
+ case E_FMAN_PORT_DEQ_NO_PREFETCH:
+ break;
+ case E_FMAN_PORT_DEQ_PART_PREFETCH:
+ tmp |= QMI_DEQ_CFG_PREFETCH_PARTIAL;
+ break;
+ case E_FMAN_PORT_DEQ_FULL_PREFETCH:
+ tmp |= QMI_DEQ_CFG_PREFETCH_FULL;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+ tmp |= (uint32_t)(params->deq_sp & QMI_DEQ_CFG_SP_MASK) <<
+ QMI_DEQ_CFG_SP_SHIFT;
+ tmp |= cfg->deq_byte_cnt;
+ iowrite32be(tmp, ®s->fmqm_pndc);
+
+ return 0;
+}
+
+void fman_port_defconfig(struct fman_port_cfg *cfg, enum fman_port_type type)
+{
+ cfg->dma_swap_data = E_FMAN_PORT_DMA_NO_SWAP;
+ cfg->dma_ic_stash_on = false;
+ cfg->dma_header_stash_on = false;
+ cfg->dma_sg_stash_on = false;
+ cfg->dma_write_optimize = true;
+ cfg->color = E_FMAN_PORT_COLOR_GREEN;
+ cfg->discard_override = false;
+ cfg->checksum_bytes_ignore = 0;
+ cfg->rx_cut_end_bytes = 4;
+ cfg->rx_pri_elevation = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+ cfg->rx_fifo_thr = ((0x3FF + 1) * FMAN_PORT_BMI_FIFO_UNITS);
+ cfg->rx_fd_bits = 0;
+ cfg->ic_ext_offset = 0;
+ cfg->ic_int_offset = 0;
+ cfg->ic_size = 0;
+ cfg->int_buf_start_margin = 0;
+ cfg->ext_buf_start_margin = 0;
+ cfg->ext_buf_end_margin = 0;
+ cfg->tx_fifo_min_level = 0;
+ cfg->tx_fifo_low_comf_level = (5 * 1024);
+ cfg->stats_counters_enable = true;
+ cfg->perf_counters_enable = true;
+ cfg->deq_type = E_FMAN_PORT_DEQ_BY_PRI;
+
+ cfg->sync_req = true;
+ cfg->deq_prefetch_opt = E_FMAN_PORT_DEQ_FULL_PREFETCH;
+
+ if (type == E_FMAN_PORT_TYPE_TX_10G) {
+ cfg->tx_fifo_deq_pipeline_depth = 4;
+ cfg->deq_high_pri = true;
+ cfg->deq_byte_cnt = 0x1400;
+ } else {
+ if (type == E_FMAN_PORT_TYPE_OP)
+ cfg->tx_fifo_deq_pipeline_depth = 2;
+ else
+ cfg->tx_fifo_deq_pipeline_depth = 1;
+
+ cfg->deq_high_pri = false;
+ cfg->deq_byte_cnt = 0x400;
+ }
+ cfg->no_scatter_gather = DEFAULT_FMAN_SP_NO_SCATTER_GATHER;
+}
+
+int fman_port_init(struct fman_port *port,
+ struct fman_port_cfg *cfg, struct fman_port_params *params)
+{
+ int err;
+
+ /* Init BMI registers */
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ err = init_bmi_rx(port, cfg, params);
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ err = init_bmi_tx(port, cfg, params);
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ err = init_bmi_oh(port, cfg, params);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (err)
+ return err;
+
+ /* Init QMI registers */
+ err = init_qmi(port, cfg, params);
+ return err;
+
+ return 0;
+}
+
+int fman_port_enable(struct fman_port *port)
+{
+ uint32_t __iomem *bmi_cfg_reg;
+ uint32_t tmp;
+ bool rx_port;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+ rx_port = true;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+ rx_port = false;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+ rx_port = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Enable QMI */
+ if (!rx_port) {
+ tmp = ioread32be(&port->qmi_regs->fmqm_pnc) | QMI_PORT_CFG_EN;
+ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+ }
+
+ /* Enable BMI */
+ tmp = ioread32be(bmi_cfg_reg) | BMI_PORT_CFG_EN;
+ iowrite32be(tmp, bmi_cfg_reg);
+
+ return 0;
+}
+
+int fman_port_disable(const struct fman_port *port)
+{
+ uint32_t __iomem *bmi_cfg_reg, *bmi_status_reg;
+ uint32_t tmp;
+ bool rx_port, failure = false;
+ int count;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ bmi_cfg_reg = &port->bmi_regs->rx.fmbm_rcfg;
+ bmi_status_reg = &port->bmi_regs->rx.fmbm_rst;
+ rx_port = true;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ bmi_cfg_reg = &port->bmi_regs->tx.fmbm_tcfg;
+ bmi_status_reg = &port->bmi_regs->tx.fmbm_tst;
+ rx_port = false;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ bmi_cfg_reg = &port->bmi_regs->oh.fmbm_ocfg;
+ bmi_status_reg = &port->bmi_regs->oh.fmbm_ost;
+ rx_port = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Disable QMI */
+ if (!rx_port) {
+ tmp = ioread32be(&port->qmi_regs->fmqm_pnc) & ~QMI_PORT_CFG_EN;
+ iowrite32be(tmp, &port->qmi_regs->fmqm_pnc);
+
+ /* Wait for QMI to finish FD handling */
+ count = 100;
+ do {
+ usleep_range(10, 11);
+ tmp = ioread32be(&port->qmi_regs->fmqm_pns);
+ } while ((tmp & QMI_PORT_STATUS_DEQ_FD_BSY) && --count);
+
+ if (count == 0) {
+ /* Timeout */
+ failure = true;
+ }
+ }
+
+ /* Disable BMI */
+ tmp = ioread32be(bmi_cfg_reg) & ~BMI_PORT_CFG_EN;
+ iowrite32be(tmp, bmi_cfg_reg);
+
+ /* Wait for graceful stop end */
+ count = 500;
+ do {
+ usleep_range(10, 11);
+ tmp = ioread32be(bmi_status_reg);
+ } while ((tmp & BMI_PORT_STATUS_BSY) && --count);
+
+ if (count == 0) {
+ /* Timeout */
+ failure = true;
+ }
+
+ if (failure)
+ return -EBUSY;
+
+ return 0;
+}
+
+int fman_port_set_bpools(const struct fman_port *port,
+ const struct fman_port_bpools *bp)
+{
+ uint32_t __iomem *bp_reg, *bp_depl_reg;
+ uint32_t tmp;
+ uint8_t i, max_bp_num;
+ bool grp_depl_used = false, rx_port;
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ max_bp_num = port->ext_pools_num;
+ rx_port = true;
+ bp_reg = port->bmi_regs->rx.fmbm_ebmpi;
+ bp_depl_reg = &port->bmi_regs->rx.fmbm_mpd;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ if (port->fm_rev_maj != 4)
+ return -EINVAL;
+ max_bp_num = FMAN_PORT_OBS_EXT_POOLS_NUM;
+ rx_port = false;
+ bp_reg = port->bmi_regs->oh.fmbm_oebmpi;
+ bp_depl_reg = &port->bmi_regs->oh.fmbm_ompd;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (rx_port) {
+ /* Check buffers are provided in ascending order */
+ for (i = 0; (i < (bp->count - 1) &&
+ (i < FMAN_PORT_MAX_EXT_POOLS_NUM - 1)); i++) {
+ if (bp->bpool[i].size > bp->bpool[i + 1].size)
+ return -EINVAL;
+ }
+ }
+
+ /* Set up external buffers pools */
+ for (i = 0; i < bp->count; i++) {
+ tmp = BMI_EXT_BUF_POOL_VALID;
+ tmp |= ((uint32_t)bp->bpool[i].bpid <<
+ BMI_EXT_BUF_POOL_ID_SHIFT) & BMI_EXT_BUF_POOL_ID_MASK;
+
+ if (rx_port) {
+ if (bp->counters_enable)
+ tmp |= BMI_EXT_BUF_POOL_EN_COUNTER;
+
+ if (bp->bpool[i].is_backup)
+ tmp |= BMI_EXT_BUF_POOL_BACKUP;
+
+ tmp |= (uint32_t)bp->bpool[i].size;
+ }
+
+ iowrite32be(tmp, &bp_reg[i]);
+ }
+
+ /* Clear unused pools */
+ for (i = bp->count; i < max_bp_num; i++)
+ iowrite32be(0, &bp_reg[i]);
+
+ /* Pools depletion */
+ tmp = 0;
+ for (i = 0; i < FMAN_PORT_MAX_EXT_POOLS_NUM; i++) {
+ if (bp->bpool[i].grp_bp_depleted) {
+ grp_depl_used = true;
+ tmp |= 0x80000000 >> i;
+ }
+
+ if (bp->bpool[i].single_bp_depleted)
+ tmp |= 0x80 >> i;
+ }
+
+ if (grp_depl_used)
+ tmp |= ((uint32_t)bp->grp_bp_depleted_num - 1) <<
+ BMI_POOL_DEP_NUM_OF_POOLS_SHIFT;
+
+ iowrite32be(tmp, bp_depl_reg);
+ return 0;
+}
+
+int fman_port_set_perf_cnt_params(struct fman_port *port,
+ struct fman_port_perf_cnt_params *params)
+{
+ uint32_t __iomem *pcp_reg;
+ uint32_t tmp;
+
+ /* Obtain register address and check parameters are in range */
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ pcp_reg = &port->bmi_regs->rx.fmbm_rpcp;
+ if ((params->queue_val == 0) ||
+ (params->queue_val > MAX_PERFORMANCE_RX_QUEUE_COMP))
+ return -EINVAL;
+ break;
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ pcp_reg = &port->bmi_regs->tx.fmbm_tpcp;
+ if ((params->queue_val == 0) ||
+ (params->queue_val > MAX_PERFORMANCE_TX_QUEUE_COMP))
+ return -EINVAL;
+ break;
+ case E_FMAN_PORT_TYPE_OP:
+ pcp_reg = &port->bmi_regs->oh.fmbm_opcp;
+ if (params->queue_val != 0)
+ return -EINVAL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((params->task_val == 0) ||
+ (params->task_val > MAX_PERFORMANCE_TASK_COMP))
+ return -EINVAL;
+ if ((params->dma_val == 0) ||
+ (params->dma_val > MAX_PERFORMANCE_DMA_COMP))
+ return -EINVAL;
+ if ((params->fifo_val == 0) ||
+ ((params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS) >
+ MAX_PERFORMANCE_FIFO_COMP))
+ return -EINVAL;
+ tmp = (uint32_t)(params->task_val - 1) <<
+ BMI_PERFORMANCE_TASK_COMP_SHIFT;
+ tmp |= (uint32_t)(params->dma_val - 1) <<
+ BMI_PERFORMANCE_DMA_COMP_SHIFT;
+ tmp |= (uint32_t)(params->fifo_val / FMAN_PORT_BMI_FIFO_UNITS - 1);
+
+ switch (port->type) {
+ case E_FMAN_PORT_TYPE_RX:
+ case E_FMAN_PORT_TYPE_RX_10G:
+ case E_FMAN_PORT_TYPE_TX:
+ case E_FMAN_PORT_TYPE_TX_10G:
+ tmp |= (uint32_t)(params->queue_val - 1) <<
+ BMI_PERFORMANCE_QUEUE_COMP_SHIFT;
+ break;
+ default:
+ break;
+ }
+
+ iowrite32be(tmp, pcp_reg);
+ return 0;
+}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers
2015-05-07 13:05 ` [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
The FMan MAC FLib provides basic API used by the drivers to
configure and control the FMan MAC hardware.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
.../net/ethernet/freescale/fman/flib/fsl_enet.h | 275 +++++++
.../ethernet/freescale/fman/flib/fsl_fman_dtsec.h | 791 +++++++++++++++++++++
.../freescale/fman/flib/fsl_fman_dtsec_mii_acc.h | 103 +++
.../ethernet/freescale/fman/flib/fsl_fman_memac.h | 453 ++++++++++++
.../freescale/fman/flib/fsl_fman_memac_mii_acc.h | 76 ++
.../ethernet/freescale/fman/flib/fsl_fman_tgec.h | 409 +++++++++++
6 files changed, 2107 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_enet.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h
create mode 100644 drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_enet.h b/drivers/net/ethernet/freescale/fman/flib/fsl_enet.h
new file mode 100644
index 0000000..78e7d04
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_enet.h
@@ -0,0 +1,275 @@
+/*
+ * 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 __FSL_ENET_H
+#define __FSL_ENET_H
+
+/*Ethernet MAC-PHY Interface */
+
+enum enet_interface {
+ E_ENET_IF_MII = 0x00010000, /* MII interface */
+ E_ENET_IF_RMII = 0x00020000, /* RMII interface */
+ E_ENET_IF_SMII = 0x00030000, /* SMII interface */
+ E_ENET_IF_GMII = 0x00040000, /* GMII interface */
+ E_ENET_IF_RGMII = 0x00050000, /* RGMII interface */
+ E_ENET_IF_TBI = 0x00060000, /* TBI interface */
+ E_ENET_IF_RTBI = 0x00070000, /* RTBI interface */
+ E_ENET_IF_SGMII = 0x00080000, /* SGMII interface */
+ E_ENET_IF_XGMII = 0x00090000, /* XGMII interface */
+ E_ENET_IF_QSGMII = 0x000a0000, /* QSGMII interface */
+ E_ENET_IF_XFI = 0x000b0000 /* XFI interface */
+};
+
+/* Ethernet Speed (nominal data rate) */
+enum enet_speed {
+ E_ENET_SPEED_10 = 10, /* 10 Mbps */
+ E_ENET_SPEED_100 = 100, /* 100 Mbps */
+ E_ENET_SPEED_1000 = 1000, /* 1000 Mbps = 1 Gbps */
+ E_ENET_SPEED_10000 = 10000 /* 10000 Mbps = 10 Gbps */
+};
+
+enum mac_type {
+ E_MAC_DTSEC,
+ E_MAC_TGEC,
+ E_MAC_MEMAC
+};
+
+/* Enum for inter-module interrupts registration */
+enum fman_event_modules {
+ E_FMAN_MOD_PRS, /* Parser event */
+ E_FMAN_MOD_KG, /* Keygen event */
+ E_FMAN_MOD_PLCR, /* Policer event */
+ E_FMAN_MOD_10G_MAC, /* 10G MAC event */
+ E_FMAN_MOD_1G_MAC, /* 1G MAC event */
+ E_FMAN_MOD_TMR, /* Timer event */
+ E_FMAN_MOD_FMAN_CTRL, /* FMAN Controller Timer event */
+ E_FMAN_MOD_MACSEC,
+ E_FMAN_MOD_DUMMY_LAST
+};
+
+/* Enum for interrupts types */
+enum fman_intr_type {
+ E_FMAN_INTR_TYPE_ERR,
+ E_FMAN_INTR_TYPE_NORMAL
+};
+
+/* enum for defining MAC types */
+enum fman_mac_type {
+ E_FMAN_MAC_10G = 0, /* 10G MAC */
+ E_FMAN_MAC_1G /* 1G MAC */
+};
+
+enum fman_mac_exceptions {
+ E_FMAN_MAC_EX_10G_MDIO_SCAN_EVENTMDIO = 0,
+ /* 10GEC MDIO scan event interrupt */
+ E_FMAN_MAC_EX_10G_MDIO_CMD_CMPL,
+ /* 10GEC MDIO command completion interrupt */
+ E_FMAN_MAC_EX_10G_REM_FAULT,
+ /* 10GEC, mEMAC Remote fault interrupt */
+ E_FMAN_MAC_EX_10G_LOC_FAULT,
+ /* 10GEC, mEMAC Local fault interrupt */
+ E_FMAN_MAC_EX_10G_1TX_ECC_ER,
+ /* 10GEC, mEMAC Transmit frame ECC error interrupt */
+ E_FMAN_MAC_EX_10G_TX_FIFO_UNFL,
+ /* 10GEC, mEMAC Transmit FIFO underflow interrupt */
+ E_FMAN_MAC_EX_10G_TX_FIFO_OVFL,
+ /* 10GEC, mEMAC Transmit FIFO overflow interrupt */
+ E_FMAN_MAC_EX_10G_TX_ER,
+ /* 10GEC Transmit frame error interrupt */
+ E_FMAN_MAC_EX_10G_RX_FIFO_OVFL,
+ /* 10GEC, mEMAC Receive FIFO overflow interrupt */
+ E_FMAN_MAC_EX_10G_RX_ECC_ER,
+ /* 10GEC, mEMAC Receive frame ECC error interrupt */
+ E_FMAN_MAC_EX_10G_RX_JAB_FRM,
+ /* 10GEC Receive jabber frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_OVRSZ_FRM,
+ /* 10GEC Receive oversized frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_RUNT_FRM,
+ /* 10GEC Receive runt frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_FRAG_FRM,
+ /* 10GEC Receive fragment frame interrupt */
+ E_FMAN_MAC_EX_10G_RX_LEN_ER,
+ /* 10GEC Receive payload length error interrupt */
+ E_FMAN_MAC_EX_10G_RX_CRC_ER,
+ /* 10GEC Receive CRC error interrupt */
+ E_FMAN_MAC_EX_10G_RX_ALIGN_ER,
+ /* 10GEC Receive alignment error interrupt */
+ E_FMAN_MAC_EX_1G_BAB_RX,
+ /* dTSEC Babbling receive error */
+ E_FMAN_MAC_EX_1G_RX_CTL,
+ /* dTSEC Receive control (pause frame) interrupt */
+ E_FMAN_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET,
+ /* dTSEC Graceful transmit stop complete */
+ E_FMAN_MAC_EX_1G_BAB_TX,
+ /* dTSEC Babbling transmit error */
+ E_FMAN_MAC_EX_1G_TX_CTL,
+ /* dTSEC Transmit control (pause frame) interrupt */
+ E_FMAN_MAC_EX_1G_TX_ERR,
+ /* dTSEC Transmit error */
+ E_FMAN_MAC_EX_1G_LATE_COL,
+ /* dTSEC Late collision */
+ E_FMAN_MAC_EX_1G_COL_RET_LMT,
+ /* dTSEC Collision retry limit */
+ E_FMAN_MAC_EX_1G_TX_FIFO_UNDRN,
+ /* dTSEC Transmit FIFO underrun */
+ E_FMAN_MAC_EX_1G_MAG_PCKT,
+ /* dTSEC Magic Packet detection */
+ E_FMAN_MAC_EX_1G_MII_MNG_RD_COMPLET,
+ /* dTSEC MII management read completion */
+ E_FMAN_MAC_EX_1G_MII_MNG_WR_COMPLET,
+ /* dTSEC MII management write completion */
+ E_FMAN_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET,
+ /* dTSEC Graceful receive stop complete */
+ E_FMAN_MAC_EX_1G_TX_DATA_ERR,
+ /* dTSEC Internal data error on transmit */
+ E_FMAN_MAC_EX_1G_RX_DATA_ERR,
+ /* dTSEC Internal data error on receive */
+ E_FMAN_MAC_EX_1G_1588_TS_RX_ERR,
+ /* dTSEC Time-Stamp Receive Error */
+ E_FMAN_MAC_EX_1G_RX_MIB_CNT_OVFL,
+ /* dTSEC MIB counter overflow */
+ E_FMAN_MAC_EX_TS_FIFO_ECC_ERR,
+ /* < mEMAC Time-stamp FIFO ECC error interrupt;
+ * not supported on T4240/B4860 rev1 chips
+ */
+};
+
+/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC
+ * and phy or backplane;
+ * Note: 1000BaseX auto-negotiation relates only to interface between MAC
+ * and phy/backplane, SGMII phy can still synchronize with far-end phy at
+ * 10Mbps, 100Mbps or 1000Mbps
+ */
+#define ENET_IF_SGMII_BASEX 0x80000000
+
+enum enet_mode {
+ E_ENET_MODE_INVALID = 0,
+ /* Invalid Ethernet mode */
+ E_ENET_MODE_MII_10 = (E_ENET_IF_MII | E_ENET_SPEED_10),
+ /* 10 Mbps MII */
+ E_ENET_MODE_MII_100 = (E_ENET_IF_MII | E_ENET_SPEED_100),
+ /* 100 Mbps MII */
+ E_ENET_MODE_RMII_10 = (E_ENET_IF_RMII | E_ENET_SPEED_10),
+ /* 10 Mbps RMII */
+ E_ENET_MODE_RMII_100 = (E_ENET_IF_RMII | E_ENET_SPEED_100),
+ /* 100 Mbps RMII */
+ E_ENET_MODE_SMII_10 = (E_ENET_IF_SMII | E_ENET_SPEED_10),
+ /* 10 Mbps SMII */
+ E_ENET_MODE_SMII_100 = (E_ENET_IF_SMII | E_ENET_SPEED_100),
+ /* 100 Mbps SMII */
+ E_ENET_MODE_GMII_1000 = (E_ENET_IF_GMII | E_ENET_SPEED_1000),
+ /* 1000 Mbps GMII */
+ E_ENET_MODE_RGMII_10 = (E_ENET_IF_RGMII | E_ENET_SPEED_10),
+ /* 10 Mbps RGMII */
+ E_ENET_MODE_RGMII_100 = (E_ENET_IF_RGMII | E_ENET_SPEED_100),
+ /* 100 Mbps RGMII */
+ E_ENET_MODE_RGMII_1000 = (E_ENET_IF_RGMII | E_ENET_SPEED_1000),
+ /* 1000 Mbps RGMII */
+ E_ENET_MODE_TBI_1000 = (E_ENET_IF_TBI | E_ENET_SPEED_1000),
+ /* 1000 Mbps TBI */
+ E_ENET_MODE_RTBI_1000 = (E_ENET_IF_RTBI | E_ENET_SPEED_1000),
+ /* 1000 Mbps RTBI */
+ E_ENET_MODE_SGMII_10 = (E_ENET_IF_SGMII | E_ENET_SPEED_10),
+ /* 10 Mbps SGMII with auto-negotiation between MAC and
+ * SGMII phy according to Cisco SGMII specification
+ */
+ E_ENET_MODE_SGMII_100 = (E_ENET_IF_SGMII | E_ENET_SPEED_100),
+ /* 100 Mbps SGMII with auto-negotiation between MAC and
+ * SGMII phy according to Cisco SGMII specification
+ */
+ E_ENET_MODE_SGMII_1000 = (E_ENET_IF_SGMII | E_ENET_SPEED_1000),
+ /* 1000 Mbps SGMII with auto-negotiation between MAC and
+ * SGMII phy according to Cisco SGMII specification
+ */
+ E_ENET_MODE_SGMII_BASEX_10 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+ | E_ENET_SPEED_10),
+ /* 10 Mbps SGMII with 1000BaseX auto-negotiation between
+ * MAC and SGMII phy or backplane
+ */
+ E_ENET_MODE_SGMII_BASEX_100 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+ | E_ENET_SPEED_100),
+ /* 100 Mbps SGMII with 1000BaseX auto-negotiation between
+ * MAC and SGMII phy or backplane
+ */
+ E_ENET_MODE_SGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_SGMII
+ | E_ENET_SPEED_1000),
+ /* 1000 Mbps SGMII with 1000BaseX auto-negotiation between
+ * MAC and SGMII phy or backplane
+ */
+ E_ENET_MODE_QSGMII_1000 = (E_ENET_IF_QSGMII | E_ENET_SPEED_1000),
+ /* 1000 Mbps QSGMII with auto-negotiation between MAC and
+ * QSGMII phy according to Cisco QSGMII specification
+ */
+ E_ENET_MODE_QSGMII_BASEX_1000 = (ENET_IF_SGMII_BASEX | E_ENET_IF_QSGMII
+ | E_ENET_SPEED_1000),
+ /* 1000 Mbps QSGMII with 1000BaseX auto-negotiation between
+ * MAC and QSGMII phy or backplane
+ */
+ E_ENET_MODE_XGMII_10000 = (E_ENET_IF_XGMII | E_ENET_SPEED_10000),
+ /* 10000 Mbps XGMII */
+ E_ENET_MODE_XFI_10000 = (E_ENET_IF_XFI | E_ENET_SPEED_10000)
+ /* 10000 Mbps XFI */
+};
+
+enum fmam_mac_statistics_level {
+ E_FMAN_MAC_NONE_STATISTICS, /* No statistics */
+ E_FMAN_MAC_PARTIAL_STATISTICS, /* Only error counters are available;
+ * Optimized for performance
+ */
+ E_FMAN_MAC_FULL_STATISTICS /* All counters available; Not
+ * optimized for performance
+ */
+};
+
+#define _MAKE_ENET_MODE(_interface, _speed) (enum enet_mode)((_interface) \
+ | (_speed))
+
+#define _ENET_INTERFACE_FROM_MODE(mode) \
+ ((enum enet_interface)((mode) & 0x0FFF0000))
+
+#define _ENET_SPEED_FROM_MODE(mode) (enum enet_speed)((mode) & 0x0000FFFF)
+#define _ENET_ADDR_TO_UINT64(_enet_addr) \
+ (uint64_t)(((uint64_t)(_enet_addr)[0] << 40) | \
+ ((uint64_t)(_enet_addr)[1] << 32) | \
+ ((uint64_t)(_enet_addr)[2] << 24) | \
+ ((uint64_t)(_enet_addr)[3] << 16) | \
+ ((uint64_t)(_enet_addr)[4] << 8) | \
+ ((uint64_t)(_enet_addr)[5]))
+
+#define _MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
+ do { \
+ int i; \
+ for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \
+ (_enet_addr)[i] = \
+ (uint8_t)((_addr64) >> ((5 - i) * 8)); \
+ } while (0)
+
+#endif /* __FSL_ENET_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h
new file mode 100644
index 0000000..ef753b3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec.h
@@ -0,0 +1,791 @@
+/*
+ * 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 __FSL_FMAN_DTSEC_H
+#define __FSL_FMAN_DTSEC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+
+/* dTSEC Init sequence
+ *To prepare dTSEC block for transfer use the following call sequence:
+ *- fman_dtsec_defconfig() - This step is optional and yet recommended. Its
+ *use is to obtain the default dTSEC configuration parameters.
+ *- Change dtsec configuration in &dtsec_cfg. This structure will be used
+ *to customize the dTSEC behavior.
+ *- fman_dtsec_init() - Applies the configuration on dTSEC hardware. Note that
+ *dTSEC is initialized while both Tx and Rx are disabled.
+ *- fman_dtsec_set_mac_address() - Set the station address (mac address).
+ *This is used by dTSEC to match against received packets.
+ *
+ *- fman_dtsec_adjust_link() - Set the link speed and duplex parameters
+ *after the PHY establishes the link.
+ *- dtsec_enable_tx() and dtsec_enable_rx() to enable transmission and
+ *reception.
+ */
+
+/* dTSEC Graceful stop
+ *To temporary stop dTSEC activity use fman_dtsec_stop_tx() and
+ *fman_dtsec_stop_rx(). Note that these functions request dTSEC graceful stop
+ *but return before this stop is complete. To query for graceful stop
+ *completion use fman_dtsec_get_event() and check DTSEC_IEVENT_GTSC and
+ *DTSEC_IEVENT_GRSC bits. Alternatively the dTSEC interrupt mask can be set to
+ *enable graceful stop interrupts.
+ *To resume operation after graceful stop use fman_dtsec_start_tx() and
+ *fman_dtsec_start_rx().
+ */
+
+/* dTSEC interrupt handling
+ *
+ *This code does not provide an interrupt handler for dTSEC. Instead this
+ *handler should be implemented and registered to the operating system by the
+ *caller. Some primitives for accessing the event status and mask registers
+ *are provided.
+ *See "dTSEC Events" section for a list of events that dTSEC can generate.
+ */
+
+/*dTSEC Events
+ *Interrupt events cause dTSEC event bits to be set. Software may poll the
+ *event register at any time to check for pending interrupts. If an event
+ *occurs and its corresponding enable bit is set in the interrupt mask
+ *register, the event also causes a hardware interrupt at the PIC.
+ *To poll for event status use the fman_dtsec_get_event() function.
+ *To configure the interrupt mask use fman_dtsec_enable_interrupt() and
+ *fman_dtsec_disable_interrupt() functions.
+ *After servicing a dTSEC interrupt use fman_dtsec_ack_event to reset the
+ *serviced event bit.
+ *The following events may be signaled by dTSEC hardware:
+ *%DTSEC_IEVENT_BABR - Babbling receive error. This bit indicates that
+ *a frame was received with length in excess of the MAC's maximum frame length
+ *register.
+ *%DTSEC_IEVENT_RXC - Receive control (pause frame) interrupt. A pause
+ *control frame was received while Rx pause frame handling is enabled.
+ *Also see fman_dtsec_handle_rx_pause().
+ *%DTSEC_IEVENT_MSRO - MIB counter overflow. The count for one of the MIB
+ *counters has exceeded the size of its register.
+ *%DTSEC_IEVENT_GTSC - Graceful transmit stop complete. Graceful stop is now
+ *complete. The transmitter is in a stopped state, in which only pause frames
+ *can be transmitted.
+ *Also see fman_dtsec_stop_tx().
+ *%DTSEC_IEVENT_BABT - Babbling transmit error. The transmitted frame length
+ *has exceeded the value in the MAC's Maximum Frame Length register.
+ *%DTSEC_IEVENT_TXC - Transmit control (pause frame) interrupt. his bit
+ *indicates that a control frame was transmitted.
+ *%DTSEC_IEVENT_TXE - Transmit error. This bit indicates that an error
+ *occurred on the transmitted channel. This bit is set whenever any transmit
+ *error occurs which causes the dTSEC to discard all or part of a frame
+ *(LC, CRL, XFUN).
+ *%DTSEC_IEVENT_LC - Late collision. This bit indicates that a collision
+ *occurred beyond the collision window (slot time) in half-duplex mode.
+ *The frame is truncated with a bad CRC and the remainder of the frame
+ *is discarded.
+ *%DTSEC_IEVENT_CRL - Collision retry limit. is bit indicates that the number
+ *of successive transmission collisions has exceeded the MAC's half-duplex
+ *register's retransmission maximum count. The frame is discarded without
+ *being transmitted and transmission of the next frame commences. This only
+ *occurs while in half-duplex mode.
+ *The number of retransmit attempts can be set in
+ *&dtsec_halfdup_cfg.retransmit before calling fman_dtsec_init().
+ *%DTSEC_IEVENT_XFUN - Transmit FIFO underrun. This bit indicates that the
+ *transmit FIFO became empty before the complete frame was transmitted.
+ *The frame is truncated with a bad CRC and the remainder of the frame is
+ *discarded.
+ *%DTSEC_IEVENT_MAG - TBD
+ *%DTSEC_IEVENT_MMRD - MII management read completion.
+ *%DTSEC_IEVENT_MMWR - MII management write completion.
+ *%DTSEC_IEVENT_GRSC - Graceful receive stop complete. It allows the user to
+ *know if the system has completed the stop and it is safe to write to receive
+ *registers (status, control or configuration registers) that are used by the
+ *system during normal operation.
+ *%DTSEC_IEVENT_TDPE - Internal data error on transmit. This bit indicates
+ *that the dTSEC has detected a parity error on its stored transmit data, which
+ *is likely to compromise the validity of recently transferred frames.
+ *%DTSEC_IEVENT_RDPE - Internal data error on receive. This bit indicates that
+ *the dTSEC has detected a parity error on its stored receive data, which is
+ *likely to compromise the validity of recently transferred frames.
+ */
+/* Interrupt Mask Register (IMASK) */
+#define DTSEC_IMASK_BREN 0x80000000
+#define DTSEC_IMASK_RXCEN 0x40000000
+#define DTSEC_IMASK_MSROEN 0x04000000
+#define DTSEC_IMASK_GTSCEN 0x02000000
+#define DTSEC_IMASK_BTEN 0x01000000
+#define DTSEC_IMASK_TXCEN 0x00800000
+#define DTSEC_IMASK_TXEEN 0x00400000
+#define DTSEC_IMASK_LCEN 0x00040000
+#define DTSEC_IMASK_CRLEN 0x00020000
+#define DTSEC_IMASK_XFUNEN 0x00010000
+#define DTSEC_IMASK_ABRTEN 0x00008000
+#define DTSEC_IMASK_IFERREN 0x00004000
+#define DTSEC_IMASK_MAGEN 0x00000800
+#define DTSEC_IMASK_MMRDEN 0x00000400
+#define DTSEC_IMASK_MMWREN 0x00000200
+#define DTSEC_IMASK_GRSCEN 0x00000100
+#define DTSEC_IMASK_TDPEEN 0x00000002
+#define DTSEC_IMASK_RDPEEN 0x00000001
+
+#define DTSEC_EVENTS_MASK \
+ ((uint32_t)(DTSEC_IMASK_BREN | \
+ DTSEC_IMASK_RXCEN | \
+ DTSEC_IMASK_BTEN | \
+ DTSEC_IMASK_TXCEN | \
+ DTSEC_IMASK_TXEEN | \
+ DTSEC_IMASK_ABRTEN | \
+ DTSEC_IMASK_LCEN | \
+ DTSEC_IMASK_CRLEN | \
+ DTSEC_IMASK_XFUNEN | \
+ DTSEC_IMASK_IFERREN | \
+ DTSEC_IMASK_MAGEN | \
+ DTSEC_IMASK_TDPEEN | \
+ DTSEC_IMASK_RDPEEN))
+
+/* dtsec timestamp event bits */
+#define TMR_PEMASK_TSREEN 0x00010000
+#define TMR_PEVENT_TSRE 0x00010000
+
+/* Group address bit indication */
+#define MAC_GROUP_ADDRESS 0x0000010000000000ULL
+/* size in bytes of L2 address */
+#define MAC_ADDRLEN 6
+
+#define DEFAULT_HALFDUP_ON false
+#define DEFAULT_HALFDUP_RETRANSMIT 0xf
+#define DEFAULT_HALFDUP_COLL_WINDOW 0x37
+#define DEFAULT_HALFDUP_EXCESS_DEFER true
+#define DEFAULT_HALFDUP_NO_BACKOFF false
+#define DEFAULT_HALFDUP_BP_NO_BACKOFF false
+#define DEFAULT_HALFDUP_ALT_BACKOFF_VAL 0x0A
+#define DEFAULT_HALFDUP_ALT_BACKOFF_EN false
+#define DEFAULT_RX_DROP_BCAST false
+#define DEFAULT_RX_SHORT_FRM true
+#define DEFAULT_RX_LEN_CHECK false
+#define DEFAULT_TX_PAD_CRC true
+#define DEFAULT_TX_CRC false
+#define DEFAULT_RX_CTRL_ACC false
+#define DEFAULT_TX_PAUSE_TIME 0xf000
+#define DEFAULT_TBIPA 5
+#define DEFAULT_RX_PREPEND 0
+#define DEFAULT_PTP_TSU_EN true
+#define DEFAULT_PTP_EXCEPTION_EN true
+#define DEFAULT_PREAMBLE_LEN 7
+#define DEFAULT_RX_PREAMBLE false
+#define DEFAULT_TX_PREAMBLE false
+#define DEFAULT_LOOPBACK false
+#define DEFAULT_RX_TIME_STAMP_EN false
+#define DEFAULT_TX_TIME_STAMP_EN false
+#define DEFAULT_RX_FLOW true
+#define DEFAULT_TX_FLOW true
+#define DEFAULT_RX_GROUP_HASH_EXD false
+#define DEFAULT_TX_PAUSE_TIME_EXTD 0
+#define DEFAULT_RX_PROMISC false
+#define DEFAULT_NON_BACK_TO_BACK_IPG1 0x40
+#define DEFAULT_NON_BACK_TO_BACK_IPG2 0x60
+#define DEFAULT_MIN_IFG_ENFORCEMENT 0x50
+#define DEFAULT_BACK_TO_BACK_IPG 0x60
+#define DEFAULT_MAXIMUM_FRAME 0x600
+#define DEFAULT_TBI_PHY_ADDR 5
+#define DEFAULT_WAKE_ON_LAN false
+
+/* register related defines (bits, field offsets..) */
+#define DTSEC_ID1_ID 0xffff0000
+#define DTSEC_ID1_REV_MJ 0x0000FF00
+#define DTSEC_ID1_REV_MN 0x000000ff
+
+#define DTSEC_ID2_INT_REDUCED_OFF 0x00010000
+#define DTSEC_ID2_INT_NORMAL_OFF 0x00020000
+
+#define DTSEC_ECNTRL_CLRCNT 0x00004000
+#define DTSEC_ECNTRL_AUTOZ 0x00002000
+#define DTSEC_ECNTRL_STEN 0x00001000
+#define DTSEC_ECNTRL_CFG_RO 0x80000000
+#define DTSEC_ECNTRL_GMIIM 0x00000040
+#define DTSEC_ECNTRL_TBIM 0x00000020
+#define DTSEC_ECNTRL_SGMIIM 0x00000002
+#define DTSEC_ECNTRL_RPM 0x00000010
+#define DTSEC_ECNTRL_R100M 0x00000008
+#define DTSEC_ECNTRL_RMM 0x00000004
+#define DTSEC_ECNTRL_QSGMIIM 0x00000001
+
+#define DTSEC_TCTRL_THDF 0x00000800
+#define DTSEC_TCTRL_TTSE 0x00000040
+#define DTSEC_TCTRL_GTS 0x00000020
+#define DTSEC_TCTRL_TFC_PAUSE 0x00000010
+
+/* PTV offsets */
+#define PTV_PTE_OFST 16
+
+#define RCTRL_CFA 0x00008000
+#define RCTRL_GHTX 0x00000400
+#define RCTRL_RTSE 0x00000040
+#define RCTRL_GRS 0x00000020
+#define RCTRL_BC_REJ 0x00000010
+#define RCTRL_MPROM 0x00000008
+#define RCTRL_RSF 0x00000004
+#define RCTRL_UPROM 0x00000001
+#define RCTRL_PROM (RCTRL_UPROM | RCTRL_MPROM)
+
+#define TMR_CTL_ESFDP 0x00000800
+#define TMR_CTL_ESFDE 0x00000400
+
+#define MACCFG1_SOFT_RESET 0x80000000
+#define MACCFG1_LOOPBACK 0x00000100
+#define MACCFG1_RX_FLOW 0x00000020
+#define MACCFG1_TX_FLOW 0x00000010
+#define MACCFG1_TX_EN 0x00000001
+#define MACCFG1_RX_EN 0x00000004
+
+#define MACCFG2_NIBBLE_MODE 0x00000100
+#define MACCFG2_BYTE_MODE 0x00000200
+#define MACCFG2_PRE_AM_RX_EN 0x00000080
+#define MACCFG2_PRE_AM_TX_EN 0x00000040
+#define MACCFG2_LENGTH_CHECK 0x00000010
+#define MACCFG2_MAGIC_PACKET_EN 0x00000008
+#define MACCFG2_PAD_CRC_EN 0x00000004
+#define MACCFG2_CRC_EN 0x00000002
+#define MACCFG2_FULL_DUPLEX 0x00000001
+
+#define PREAMBLE_LENGTH_SHIFT 12
+
+#define IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT 24
+#define IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT 16
+#define IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT 8
+
+#define IPGIFG_NON_BACK_TO_BACK_IPG_1 0x7F000000
+#define IPGIFG_NON_BACK_TO_BACK_IPG_2 0x007F0000
+#define IPGIFG_MIN_IFG_ENFORCEMENT 0x0000FF00
+#define IPGIFG_BACK_TO_BACK_IPG 0x0000007F
+
+#define HAFDUP_ALT_BEB 0x00080000
+#define HAFDUP_BP_NO_BACKOFF 0x00040000
+#define HAFDUP_NO_BACKOFF 0x00020000
+#define HAFDUP_EXCESS_DEFER 0x00010000
+#define HAFDUP_COLLISION_WINDOW 0x000003ff
+
+#define HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT 20
+#define HAFDUP_RETRANSMISSION_MAX_SHIFT 12
+#define HAFDUP_RETRANSMISSION_MAX 0x0000f000
+
+#define NUM_OF_HASH_REGS 8 /* Number of hash table registers */
+
+/* CAR1/2 bits */
+#define DTSEC_CAR1_TR64 0x80000000
+#define DTSEC_CAR1_TR127 0x40000000
+#define DTSEC_CAR1_TR255 0x20000000
+#define DTSEC_CAR1_TR511 0x10000000
+#define DTSEC_CAR1_TRK1 0x08000000
+#define DTSEC_CAR1_TRMAX 0x04000000
+#define DTSEC_CAR1_TRMGV 0x02000000
+
+#define DTSEC_CAR1_RBYT 0x00010000
+#define DTSEC_CAR1_RPKT 0x00008000
+#define DTSEC_CAR1_RFCS 0x00004000
+#define DTSEC_CAR1_RMCA 0x00002000
+#define DTSEC_CAR1_RBCA 0x00001000
+#define DTSEC_CAR1_RXCF 0x00000800
+#define DTSEC_CAR1_RXPF 0x00000400
+#define DTSEC_CAR1_RXUO 0x00000200
+#define DTSEC_CAR1_RALN 0x00000100
+#define DTSEC_CAR1_RFLR 0x00000080
+#define DTSEC_CAR1_RCDE 0x00000040
+#define DTSEC_CAR1_RCSE 0x00000020
+#define DTSEC_CAR1_RUND 0x00000010
+#define DTSEC_CAR1_ROVR 0x00000008
+#define DTSEC_CAR1_RFRG 0x00000004
+#define DTSEC_CAR1_RJBR 0x00000002
+#define DTSEC_CAR1_RDRP 0x00000001
+
+#define DTSEC_CAR2_TJBR 0x00080000
+#define DTSEC_CAR2_TFCS 0x00040000
+#define DTSEC_CAR2_TXCF 0x00020000
+#define DTSEC_CAR2_TOVR 0x00010000
+#define DTSEC_CAR2_TUND 0x00008000
+#define DTSEC_CAR2_TFRG 0x00004000
+#define DTSEC_CAR2_TBYT 0x00002000
+#define DTSEC_CAR2_TPKT 0x00001000
+#define DTSEC_CAR2_TMCA 0x00000800
+#define DTSEC_CAR2_TBCA 0x00000400
+#define DTSEC_CAR2_TXPF 0x00000200
+#define DTSEC_CAR2_TDFR 0x00000100
+#define DTSEC_CAR2_TEDF 0x00000080
+#define DTSEC_CAR2_TSCL 0x00000040
+#define DTSEC_CAR2_TMCL 0x00000020
+#define DTSEC_CAR2_TLCL 0x00000010
+#define DTSEC_CAR2_TXCL 0x00000008
+#define DTSEC_CAR2_TNCL 0x00000004
+#define DTSEC_CAR2_TDRP 0x00000001
+
+/* memory map */
+
+struct dtsec_regs {
+ /* dTSEC General Control and Status Registers */
+ uint32_t tsec_id; /* 0x000 ETSEC_ID register */
+ uint32_t tsec_id2; /* 0x004 ETSEC_ID2 register */
+ uint32_t ievent; /* 0x008 Interrupt event register */
+ uint32_t imask; /* 0x00C Interrupt mask register */
+ uint32_t reserved0010[1];
+ uint32_t ecntrl; /* 0x014 E control register */
+ uint32_t ptv; /* 0x018 Pause time value register */
+ uint32_t tbipa; /* 0x01C TBI PHY address register */
+ uint32_t tmr_ctrl; /* 0x020 Time-stamp Control register */
+ uint32_t tmr_pevent; /* 0x024 Time-stamp event register */
+ uint32_t tmr_pemask; /* 0x028 Timer event mask register */
+ uint32_t reserved002c[5];
+ uint32_t tctrl; /* 0x040 Transmit control register */
+ uint32_t reserved0044[3];
+ uint32_t rctrl; /* 0x050 Receive control register */
+ uint32_t reserved0054[11];
+ uint32_t igaddr[8]; /* 0x080-0x09C Individual/group address */
+ uint32_t gaddr[8]; /* 0x0A0-0x0BC Group address registers 0-7 */
+ uint32_t reserved00c0[16];
+ uint32_t maccfg1; /* 0x100 MAC configuration #1 */
+ uint32_t maccfg2; /* 0x104 MAC configuration #2 */
+ uint32_t ipgifg; /* 0x108 IPG/IFG */
+ uint32_t hafdup; /* 0x10C Half-duplex */
+ uint32_t maxfrm; /* 0x110 Maximum frame */
+ uint32_t reserved0114[10];
+ uint32_t ifstat; /* 0x13C Interface status */
+ uint32_t macstnaddr1; /* 0x140 Station Address,part 1 */
+ uint32_t macstnaddr2; /* 0x144 Station Address,part 2 */
+ struct {
+ uint32_t exact_match1; /* octets 1-4 */
+ uint32_t exact_match2; /* octets 5-6 */
+ } macaddr[15]; /* 0x148-0x1BC mac exact match addresses 1-15 */
+ uint32_t reserved01c0[16];
+ /* 0x200 transmit and receive 64 byte frame counter */
+ uint32_t tr64;
+ /* 0x204 transmit and receive 65 to 127 byte frame counter */
+ uint32_t tr127;
+ /* 0x208 transmit and receive 128 to 255 byte frame counter */
+ uint32_t tr255;
+ /* 0x20C transmit and receive 256 to 511 byte frame counter */
+ uint32_t tr511;
+ /* 0x210 transmit and receive 512 to 1023 byte frame counter */
+ uint32_t tr1k;
+ /* 0x214 transmit and receive 1024 to 1518 byte frame counter */
+ uint32_t trmax;
+ /* 0x218 transmit and receive 1519 to 1522 byte good VLAN frame count*/
+ uint32_t trmgv;
+ uint32_t rbyt; /* 0x21C receive byte counter */
+ uint32_t rpkt; /* 0x220 receive packet counter */
+ uint32_t rfcs; /* 0x224 receive FCS error counter */
+ /* 0x228 RMCA receive multicast packet counter */
+ uint32_t rmca;
+ uint32_t rbca; /* 0x22C receive broadcast packet counter */
+ uint32_t rxcf; /* 0x230 receive control frame packet counter */
+ uint32_t rxpf; /* 0x234 receive pause frame packet counter */
+ uint32_t rxuo; /* 0x238 receive unknown OP code counter */
+ uint32_t raln; /* 0x23C receive alignment error counter */
+ uint32_t rflr; /* 0x240 receive frame length error counter */
+ uint32_t rcde; /* 0x244 receive code error counter */
+ uint32_t rcse; /* 0x248 receive carrier sense error counter */
+ uint32_t rund; /* 0x24C receive undersize packet counter */
+ uint32_t rovr; /* 0x250 receive oversize packet counter */
+ uint32_t rfrg; /* 0x254 receive fragments counter */
+ uint32_t rjbr; /* 0x258 receive jabber counter */
+ uint32_t rdrp; /* 0x25C receive drop */
+ uint32_t tbyt; /* 0x260 transmit byte counter */
+ uint32_t tpkt; /* 0x264 transmit packet counter */
+ uint32_t tmca; /* 0x268 transmit multicast packet counter */
+ uint32_t tbca; /* 0x26C transmit broadcast packet counter */
+ uint32_t txpf; /* 0x270 transmit pause control frame counter */
+ uint32_t tdfr; /* 0x274 transmit deferral packet counter */
+ /* 0x278 transmit excessive deferral packet counter */
+ uint32_t tedf;
+ /* 0x27C transmit single collision packet counter */
+ uint32_t tscl;
+ /* 0x280 transmit multiple collision packet counter */
+ uint32_t tmcl;
+ /* 0x284 transmit late collision packet counter */
+ uint32_t tlcl;
+ /* 0x288 transmit excessive collision packet counter */
+ uint32_t txcl;
+ uint32_t tncl; /* 0x28C transmit total collision counter */
+ uint32_t reserved0290[1];
+ uint32_t tdrp; /* 0x294 transmit drop frame counter */
+ uint32_t tjbr; /* 0x298 transmit jabber frame counter */
+ uint32_t tfcs; /* 0x29C transmit FCS error counter */
+ uint32_t txcf; /* 0x2A0 transmit control frame counter */
+ uint32_t tovr; /* 0x2A4 transmit oversize frame counter */
+ uint32_t tund; /* 0x2A8 transmit undersize frame counter */
+ uint32_t tfrg; /* 0x2AC transmit fragments frame counter */
+ uint32_t car1; /* 0x2B0 carry register one register* */
+ uint32_t car2; /* 0x2B4 carry register two register* */
+ uint32_t cam1; /* 0x2B8 carry register one mask register */
+ uint32_t cam2; /* 0x2BC carry register two mask register */
+ uint32_t reserved02c0[848];
+};
+
+/* struct dtsec_cfg - dTSEC configuration
+ * Transmit half-duplex flow control, under software
+ * control for 10/100-Mbps half-duplex media. If set,
+ * back pressure is applied to media by raising carrier.
+ * halfdup_retransmit:
+ * Number of retransmission attempts following a collision.
+ * If this is exceeded dTSEC aborts transmission due to
+ * excessive collisions. The standard specifies the
+ * attempt limit to be 15.
+ * halfdup_coll_window:
+ * The number of bytes of the frame during which
+ * collisions may occur. The default value of 55
+ * corresponds to the frame byte at the end of the
+ * standard 512-bit slot time window. If collisions are
+ * detected after this byte, the late collision event is
+ * asserted and transmission of current frame is aborted.
+ * rx_drop_bcast:
+ * Discard broadcast frames. If set, all broadcast frames
+ * will be discarded by dTSEC.
+ * rx_short_frm:
+ * Accept short frames. If set, dTSEC will accept frames
+ * of length 14..63 bytes.
+ * rx_len_check:
+ * Length check for received frames. If set, the MAC
+ * checks the frame's length field on receive to ensure it
+ * matches the actual data field length. This only works
+ * for received frames with length field less than 1500.
+ * No check is performed for larger frames.
+ * tx_pad_crc:
+ * Pad and append CRC. If set, the MAC pads all
+ * transmitted short frames and appends a CRC to every
+ * frame regardless of padding requirement.
+ * tx_crc:
+ * Transmission CRC enable. If set, the MAC appends a CRC
+ * to all frames. If frames presented to the MAC have a
+ * valid length and contain a valid CRC, tx_crc should be
+ * reset.
+ * This field is ignored if tx_pad_crc is set.
+ * rx_ctrl_acc:
+ * Control frame accept. If set, this overrides 802.3
+ * standard control frame behavior, and all Ethernet frames
+ * that have an ethertype of 0x8808 are treated as normal
+ * Ethernet frames and passed up to the packet interface on
+ * a DA match. Received pause control frames are passed to
+ * the packet interface only if Rx flow control is also
+ * disabled. See fman_dtsec_handle_rx_pause() function.
+ * tx_pause_time:
+ * Transmit pause time value. This pause value is used as
+ * part of the pause frame to be sent when a transmit pause
+ * frame is initiated. If set to 0 this disables
+ * transmission of pause frames.
+ * rx_preamble:
+ * Receive preamble enable. If set, the MAC recovers the
+ * received Ethernet 7-byte preamble and passes it to the
+ * packet interface at the start of each received frame.
+ * This field should be reset for internal MAC loop-back
+ * mode.
+ * tx_preamble: User defined preamble enable for transmitted frames.
+ * If set, a user-defined preamble must passed to the MAC
+ * and it is transmitted instead of the standard preamble.
+ * preamble_len:
+ * Length, in bytes, of the preamble field preceding each
+ * Ethernet start-of-frame delimiter byte. The default
+ * value of 0x7 should be used in order to guarantee
+ * reliable operation with IEEE 802.3 compliant hardware.
+ * rx_prepend:
+ * Packet alignment padding length. The specified number
+ * of bytes (1-31) of zero padding are inserted before the
+ * start of each received frame. For Ethernet, where
+ * optional preamble extraction is enabled, the padding
+ * appears before the preamble, otherwise the padding
+ * precedes the layer 2 header.
+ *
+ * This structure contains basic dTSEC configuration and must be passed to
+ * fman_dtsec_init() function. A default set of configuration values can be
+ * obtained by calling fman_dtsec_defconfig().
+ */
+struct dtsec_cfg {
+ bool halfdup_on;
+ bool halfdup_alt_backoff_en;
+ bool halfdup_excess_defer;
+ bool halfdup_no_backoff;
+ bool halfdup_bp_no_backoff;
+ uint8_t halfdup_alt_backoff_val;
+ uint16_t halfdup_retransmit;
+ uint16_t halfdup_coll_window;
+ bool rx_drop_bcast;
+ bool rx_short_frm;
+ bool rx_len_check;
+ bool tx_pad_crc;
+ bool tx_crc;
+ bool rx_ctrl_acc;
+ unsigned short tx_pause_time;
+ unsigned short tbipa;
+ bool ptp_tsu_en;
+ bool ptp_exception_en;
+ bool rx_preamble;
+ bool tx_preamble;
+ unsigned char preamble_len;
+ unsigned char rx_prepend;
+ bool loopback;
+ bool rx_time_stamp_en;
+ bool tx_time_stamp_en;
+ bool rx_flow;
+ bool tx_flow;
+ bool rx_group_hash_exd;
+ bool rx_promisc;
+ uint8_t tbi_phy_addr;
+ uint16_t tx_pause_time_extd;
+ uint16_t maximum_frame;
+ uint32_t non_back_to_back_ipg1;
+ uint32_t non_back_to_back_ipg2;
+ uint32_t min_ifg_enforcement;
+ uint32_t back_to_back_ipg;
+ bool wake_on_lan;
+};
+
+/*fman_dtsec_defconfig() - Get default dTSEC configuration
+ *cfg: pointer to configuration structure.
+ *
+ *Call this function to obtain a default set of configuration values for
+ *initializing dTSEC. The user can overwrite any of the values before calling
+ *fman_dtsec_init(), if specific configuration needs to be applied.
+ */
+void fman_dtsec_defconfig(struct dtsec_cfg *cfg);
+
+/*fman_dtsec_init() - Init dTSEC hardware block
+ *regs: Pointer to dTSEC register block
+ *cfg: dTSEC configuration data
+ *iface_mode: dTSEC interface mode, the type of MAC - PHY interface.
+ *iface_speed: 1G or 10G
+ *macaddr: MAC station address to be assigned to the device
+ *fm_rev_maj: major rev number
+ *fm_rev_min: minor rev number
+ *exceptions_mask: initial exceptions mask
+ *This function initializes dTSEC and applies basic configuration.
+ *
+ *dTSEC initialization sequence:
+ *Before enabling Rx/Tx call dtsec_set_address() to set MAC address,
+ *fman_dtsec_adjust_link() to configure interface speed and duplex and finally
+ *dtsec_enable_tx()/dtsec_enable_rx() to start transmission and reception.
+ *
+ *Returns: 0 if successful, an error code otherwise.
+ */
+int fman_dtsec_init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg,
+ enum enet_interface iface_mode,
+ enum enet_speed iface_speed,
+ uint8_t *macaddr, uint8_t fm_rev_maj,
+ uint8_t fm_rev_min, uint32_t exception_mask);
+
+/*fman_dtsec_enable() - Enable dTSEC Tx and Tx
+ *regs: Pointer to dTSEC register block
+ *apply_rx: enable rx side
+ *apply_tx: enable tx side
+ *This function resets Tx and Rx graceful stop bit and enables dTSEC Tx and Rx.
+ */
+void fman_dtsec_enable(struct dtsec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx);
+
+/*fman_dtsec_disable() - Disable dTSEC Tx and Rx
+ *regs: Pointer to dTSEC register block
+ *apply_rx: disable rx side
+ *apply_tx: disable tx side
+ *This function disables Tx and Rx in dTSEC.
+ */
+void fman_dtsec_disable(struct dtsec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx);
+
+/*fman_dtsec_get_revision() - Get dTSEC hardware revision
+ *regs: Pointer to dTSEC register block
+ *Returns dtsec_id content
+ *Call this function to obtain the dTSEC hardware version.
+ */
+uint32_t fman_dtsec_get_revision(struct dtsec_regs __iomem *regs);
+
+/*fman_dtsec_set_mac_address() - Set MAC station address
+ *regs: Pointer to dTSEC register block
+ *macaddr: MAC address array
+ *This function sets MAC station address. To enable unicast reception call
+ *this after fman_dtsec_init(). While promiscuous mode is disabled dTSEC will
+ *match the destination address of received unicast frames against this
+ *address.
+ */
+void fman_dtsec_set_mac_address(struct dtsec_regs __iomem *regs,
+ uint8_t *macaddr);
+
+/*fman_dtsec_get_mac_address() - Query MAC station address
+ *regs: Pointer to dTSEC register block
+ *macaddr: MAC address array
+ */
+void fman_dtsec_get_mac_address(struct dtsec_regs __iomem *regs,
+ uint8_t *macaddr);
+
+/*fman_dtsec_set_uc_promisc() - Sets unicast promiscuous mode
+ *regs: Pointer to dTSEC register block
+ *enable: Enable unicast promiscuous mode
+ *Use this function to enable/disable dTSEC L2 address filtering. If the
+ *address filtering is disabled all unicast packets are accepted.
+ *To set dTSEC in promiscuous mode call both fman_dtsec_set_uc_promisc() and
+ *fman_dtsec_set_mc_promisc() to disable filtering for both unicast and
+ *multicast addresses.
+ */
+void fman_dtsec_set_uc_promisc(struct dtsec_regs __iomem *regs, bool enable);
+
+/*fman_dtsec_adjust_link() - Adjust dTSEC speed/duplex settings
+ *regs: Pointer to dTSEC register block
+ *iface_mode: dTSEC interface mode
+ *speed: Link speed
+ *full_dx: True for full-duplex, false for half-duplex.
+ *This function configures the MAC to function and the desired rates. Use it
+ *to configure dTSEC after fman_dtsec_init() and whenever the link speed
+ *changes (for instance following PHY auto-negociation).
+ *Returns: 0 if successful, an error code otherwise.
+ */
+int fman_dtsec_adjust_link(struct dtsec_regs __iomem *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx);
+
+/*fman_dtsec_set_max_frame_len() - Set max frame length
+ *regs: Pointer to dTSEC register block
+ *length: Max frame length.
+ *Sets maximum frame length for received and transmitted frames. Frames that
+ *exceeds this length are truncated.
+ */
+void fman_dtsec_set_max_frame_len(struct dtsec_regs __iomem *regs,
+ uint16_t length);
+
+/*fman_dtsec_get_max_frame_len() - Query max frame length
+ *regs: Pointer to dTSEC register block
+ *Returns: the current value of the maximum frame length.
+ */
+uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs __iomem *regs);
+
+/*fman_dtsec_handle_rx_pause() - Configure pause frame handling
+ *regs: Pointer to dTSEC register block
+ *en: Enable pause frame handling in dTSEC
+ *If enabled, dTSEC will handle pause frames internally. This must be disabled
+ *if dTSEC is set in half-duplex mode.
+ *If pause frame handling is disabled and &dtsec_cfg.rx_ctrl_acc is set, pause
+ *frames will be transferred to the packet interface just like regular Ethernet
+ *frames.
+ */
+void fman_dtsec_handle_rx_pause(struct dtsec_regs __iomem *regs, bool en);
+
+/*fman_dtsec_set_tx_pause_frames() - Configure Tx pause time
+ *regs: Pointer to dTSEC register block
+ *time: Time value included in pause frames
+ *Call this function to set the time value used in transmitted pause frames.
+ *If time is 0, transmission of pause frames is disabled
+ */
+void fman_dtsec_set_tx_pause_frames(struct dtsec_regs __iomem *regs,
+ uint16_t time);
+
+/*fman_dtsec_ack_event() - Acknowledge handled events
+ *regs: Pointer to dTSEC register block
+ *ev_mask: Events to acknowledge
+ *After handling events signaled by dTSEC in either polling or interrupt mode,
+ *call this function to reset the associated status bits in dTSEC event
+ *register.
+ */
+void fman_dtsec_ack_event(struct dtsec_regs __iomem *regs, uint32_t ev_mask);
+
+/*fman_dtsec_get_event() - Returns currently asserted events
+ *regs: Pointer to dTSEC register block
+ *ev_mask: Mask of relevant events
+ *Call this function to obtain a bit-mask of events that are currently asserted
+ *in dTSEC, taken from IEVENT register.
+ *Returns: a bit-mask of events asserted in dTSEC.
+ */
+uint32_t fman_dtsec_get_event(struct dtsec_regs __iomem *regs,
+ uint32_t ev_mask);
+
+/*fman_dtsec_get_interrupt_mask() - Returns a bit-mask of enabled interrupts
+ *regs: Pointer to dTSEC register block
+ *Call this function to obtain a bit-mask of enabled interrupts
+ *in dTSEC, taken from IMASK register.
+ *Returns: a bit-mask of enabled interrupts in dTSEC.
+ */
+uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs __iomem *regs);
+
+void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs __iomem *regs);
+
+void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs __iomem *regs);
+
+/*fman_dtsec_disable_interrupt() - Disables interrupts for the specified events
+ *regs: Pointer to dTSEC register block
+ *ev_mask: Mask of relevant events
+ *Call this function to disable interrupts in dTSEC for the specified events.
+ *To enable interrupts use fman_dtsec_enable_interrupt().
+ */
+void fman_dtsec_disable_interrupt(struct dtsec_regs __iomem *regs,
+ uint32_t ev_mask);
+
+/*fman_dtsec_enable_interrupt() - Enable interrupts for the specified events
+ *regs: Pointer to dTSEC register block
+ *ev_mask: Mask of relevant events
+ *Call this function to enable interrupts in dTSEC for the specified events.
+ *To disable interrupts use fman_dtsec_disable_interrupt().
+ */
+void fman_dtsec_enable_interrupt(struct dtsec_regs __iomem *regs,
+ uint32_t ev_mask);
+
+/*fman_dtsec_set_bucket() - Enables/disables a filter bucket
+ *regs: Pointer to dTSEC register block
+ *bucket: Bucket index
+ *enable: true/false to enable/disable this bucket
+ *This function enables or disables the specified bucket. Enabling a bucket
+ *associated with an address configures dTSEC to accept received packets
+ *with that destination address.
+ *Multiple addresses may be associated with the same bucket. Disabling a
+ *bucket will affect all addresses associated with that bucket. A bucket that
+ *is enabled requires further filtering and verification in the upper layers
+ */
+void fman_dtsec_set_bucket(struct dtsec_regs __iomem *regs, int bucket,
+ bool enable);
+
+/*fman_dtsec_set_mc_promisc() - Set multicast promiscuous mode
+ *regs: Pointer to dTSEC register block
+ *enable: Enable multicast promiscuous mode
+ *Call this to enable/disable L2 address filtering for multicast packets.
+ */
+void fman_dtsec_set_mc_promisc(struct dtsec_regs __iomem *regs, bool enable);
+
+/*fman_dtsec_get_clear_carry_regs() - Read and clear carry bits
+ * (CAR1-2 registers)
+ *regs: Pointer to dTSEC register block
+ *car1: car1 register value
+ *car2: car2 register value
+ *When set, the carry bits signal that an overflow occurred on the
+ *corresponding counters.
+ *Note that the carry bits (CAR1-2 registers) will assert the
+ *%DTSEC_IEVENT_MSRO interrupt if unmasked (via CAM1-2 regs).
+ *Returns: true if overflow occurred, otherwise - false
+ */
+bool fman_dtsec_get_clear_carry_regs(struct dtsec_regs __iomem *regs,
+ uint32_t *car1, uint32_t *car2);
+
+uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs __iomem *regs);
+
+void fman_dtsec_start_tx(struct dtsec_regs __iomem *regs);
+void fman_dtsec_start_rx(struct dtsec_regs __iomem *regs);
+void fman_dtsec_stop_tx(struct dtsec_regs __iomem *regs);
+void fman_dtsec_stop_rx(struct dtsec_regs __iomem *regs);
+uint32_t fman_dtsec_get_rctrl(struct dtsec_regs __iomem *regs);
+
+#endif /* __FSL_FMAN_DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h
new file mode 100644
index 0000000..4425910
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_dtsec_mii_acc.h
@@ -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 __FSL_FMAN_DTSEC_MII_ACC_H
+#define __FSL_FMAN_DTSEC_MII_ACC_H
+
+#include "common/general.h"
+
+/* MII Management Configuration Register */
+#define MIIMCFG_RESET_MGMT 0x80000000
+#define MIIMCFG_MGNTCLK_MASK 0x00000007
+#define MIIMCFG_MGNTCLK_SHIFT 0
+
+/* MII Management Command Register */
+#define MIIMCOM_SCAN_CYCLE 0x00000002
+#define MIIMCOM_READ_CYCLE 0x00000001
+
+/* MII Management Address Register */
+#define MIIMADD_PHY_ADDR_SHIFT 8
+#define MIIMADD_PHY_ADDR_MASK 0x00001f00
+
+#define MIIMADD_REG_ADDR_SHIFT 0
+#define MIIMADD_REG_ADDR_MASK 0x0000001f
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY 0x00000001
+
+/* PHY Control Register */
+#define PHY_CR_PHY_RESET 0x8000
+#define PHY_CR_LOOPBACK 0x4000
+#define PHY_CR_SPEED0 0x2000
+#define PHY_CR_ANE 0x1000
+#define PHY_CR_RESET_AN 0x0200
+#define PHY_CR_FULLDUPLEX 0x0100
+#define PHY_CR_SPEED1 0x0040
+
+#define PHY_TBICON_SRESET 0x8000
+#define PHY_TBICON_SPEED2 0x0020
+#define PHY_TBICON_CLK_SEL 0x0020
+#define PHY_TBIANA_SGMII 0x4001
+#define PHY_TBIANA_1000X 0x01a0
+/* register map */
+
+/* MII Configuration Control Memory Map Registers */
+struct dtsec_mii_reg {
+ uint32_t reserved1[72];
+ uint32_t miimcfg; /* MII Mgmt:configuration */
+ uint32_t miimcom; /* MII Mgmt:command */
+ uint32_t miimadd; /* MII Mgmt:address */
+ uint32_t miimcon; /* MII Mgmt:control 3 */
+ uint32_t miimstat; /* MII Mgmt:status */
+ uint32_t miimind; /* MII Mgmt:indicators */
+};
+
+/* dTSEC MII API */
+
+/* functions to access the mii registers for phy configuration.
+ * this functionality may not be available for all dtsecs in the system.
+ * consult the reference manual for details
+ **/
+void fman_dtsec_mii_reset(struct dtsec_mii_reg __iomem *regs);
+/* frequency is in MHz.
+ * note that dtsec clock is 1/2 of fman clock
+ **/
+void fman_dtsec_mii_init(struct dtsec_mii_reg __iomem *regs,
+ uint16_t dtsec_freq);
+int fman_dtsec_mii_write_reg(struct dtsec_mii_reg __iomem *regs,
+ uint8_t addr,
+ uint8_t reg, uint16_t data, uint16_t dtsec_freq);
+
+int fman_dtsec_mii_read_reg(struct dtsec_mii_reg __iomem *regs,
+ uint8_t addr,
+ uint8_t reg, uint16_t *data, uint16_t dtsec_freq);
+
+#endif /* __FSL_FMAN_DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h
new file mode 100644
index 0000000..c589025
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac.h
@@ -0,0 +1,453 @@
+/*
+ * 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 __FSL_FMAN_MEMAC_H
+#define __FSL_FMAN_MEMAC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+/* Num of additional exact match MAC adr regs */
+#define MEMAC_NUM_OF_PADDRS 7
+
+/* Control and Configuration Register (COMMAND_CONFIG) */
+/* 00 Magic Packet detection */
+#define CMD_CFG_MG 0x80000000
+/* 07 Rx low power indication */
+#define CMD_CFG_REG_LOWP_RXETY 0x01000000
+/* 08 Tx Low Power Idle Enable */
+#define CMD_CFG_TX_LOWP_ENA 0x00800000
+/* 10 Disable SFD check */
+#define CMD_CFG_SFD_ANY 0x00200000
+/* 12 Enable PFC */
+#define CMD_CFG_PFC_MODE 0x00080000
+/* 14 Payload length check disable */
+#define CMD_CFG_NO_LEN_CHK 0x00020000
+/* 15 Force idle generation */
+#define CMD_CFG_SEND_IDLE 0x00010000
+/* 18 Control frame rx enable */
+#define CMD_CFG_CNT_FRM_EN 0x00002000
+/* 19 S/W Reset, self clearing bit */
+#define CMD_CFG_SW_RESET 0x00001000
+/* 20 Enable Tx padding of frames */
+#define CMD_CFG_TX_PAD_EN 0x00000800
+/* 21 XGMII/GMII loopback enable */
+#define CMD_CFG_LOOPBACK_EN 0x00000400
+/* 22 Tx source MAC addr insertion */
+#define CMD_CFG_TX_ADDR_INS 0x00000200
+/* 23 Ignore Pause frame quanta */
+#define CMD_CFG_PAUSE_IGNORE 0x00000100
+/* 24 Terminate/frwd Pause frames */
+#define CMD_CFG_PAUSE_FWD 0x00000080
+/* 25 Terminate/frwd CRC of frames */
+#define CMD_CFG_CRC_FWD 0x00000040
+/* 26 Frame padding removal */
+#define CMD_CFG_PAD_EN 0x00000020
+/* 27 Promiscuous operation enable */
+#define CMD_CFG_PROMIS_EN 0x00000010
+/* 28 WAN mode enable */
+#define CMD_CFG_WAN_MODE 0x00000008
+/* 30 MAC receive path enable */
+#define CMD_CFG_RX_EN 0x00000002
+/* 31 MAC transmit path enable */
+#define CMD_CFG_TX_EN 0x00000001
+
+/* Transmit FIFO Sections Register (TX_FIFO_SECTIONS) */
+#define TX_FIFO_SECTIONS_TX_EMPTY_MASK 0xFFFF0000
+#define TX_FIFO_SECTIONS_TX_AVAIL_MASK 0x0000FFFF
+#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G 0x00400000
+#define TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G 0x00100000
+#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G 0x00360000
+#define TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G 0x00040000
+#define TX_FIFO_SECTIONS_TX_AVAIL_10G 0x00000019
+#define TX_FIFO_SECTIONS_TX_AVAIL_1G 0x00000020
+#define TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G 0x00000060
+
+#define GET_TX_EMPTY_DEFAULT_VALUE(_val) \
+do { \
+ _val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK; \
+ ((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ? \
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G) :\
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G));\
+} while (0)
+
+#define GET_TX_EMPTY_PFC_VALUE(_val) \
+do { \
+ _val &= ~TX_FIFO_SECTIONS_TX_EMPTY_MASK; \
+ ((_val == TX_FIFO_SECTIONS_TX_AVAIL_10G) ? \
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_10G) : \
+ (_val |= TX_FIFO_SECTIONS_TX_EMPTY_PFC_1G)); \
+} while (0)
+
+/* Interface Mode Register (IF_MODE) */
+/* 30-31 Mask on i/f mode bits */
+#define IF_MODE_MASK 0x00000003
+/* 30-31 XGMII (10G) interface */
+#define IF_MODE_XGMII 0x00000000
+/* 30-31 GMII (1G) interface */
+#define IF_MODE_GMII 0x00000002
+#define IF_MODE_RGMII 0x00000004
+#define IF_MODE_RGMII_AUTO 0x00008000
+#define IF_MODE_RGMII_1000 0x00004000 /* 10 - 1000Mbps RGMII */
+#define IF_MODE_RGMII_100 0x00000000 /* 00 - 100Mbps RGMII */
+#define IF_MODE_RGMII_10 0x00002000 /* 01 - 10Mbps RGMII */
+#define IF_MODE_RGMII_SP_MASK 0x00006000 /* Setsp mask bits */
+#define IF_MODE_RGMII_FD 0x00001000 /* Full duplex RGMII */
+#define IF_MODE_HD 0x00000040 /* Half duplex operation */
+
+/* Hash table Control Register (HASHTABLE_CTRL) */
+#define HASH_CTRL_MCAST_SHIFT 26
+/* 23 Mcast frame rx for hash */
+#define HASH_CTRL_MCAST_EN 0x00000100
+/* 26-31 Hash table address code */
+#define HASH_CTRL_ADDR_MASK 0x0000003F
+/* MAC mcast indication */
+#define GROUP_ADDRESS 0x0000010000000000LL
+#define HASH_TABLE_SIZE 64 /* Hash tbl size */
+
+/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
+#define MEMAC_TX_IPG_LENGTH_MASK 0x0000003F
+
+/* Statistics Configuration Register (STATN_CONFIG) */
+#define STATS_CFG_CLR 0x00000004 /* 29 Reset all counters */
+#define STATS_CFG_CLR_ON_RD 0x00000002 /* 30 Clear on read */
+/* 31 Saturate at the maximum val */
+#define STATS_CFG_SATURATE 0x00000001
+
+/* Interrupt Mask Register (IMASK) */
+/* 1 Magic pkt detect indication */
+#define MEMAC_IMASK_MGI 0x40000000
+/* 2 Timestamp FIFO ECC error evnt */
+#define MEMAC_IMASK_TSECC_ER 0x20000000
+/* 6 Transmit frame ECC error evnt */
+#define MEMAC_IMASK_TECC_ER 0x02000000
+/* 7 Receive frame ECC error evnt */
+#define MEMAC_IMASK_RECC_ER 0x01000000
+
+#define MEMAC_ALL_ERRS_IMASK \
+ ((uint32_t)(MEMAC_IMASK_TSECC_ER | \
+ MEMAC_IMASK_TECC_ER | \
+ MEMAC_IMASK_RECC_ER | \
+ MEMAC_IMASK_MGI))
+
+/* PCS (XG). Link sync (G) */
+#define MEMAC_IEVNT_PCS 0x80000000
+/* Auto-negotiation */
+#define MEMAC_IEVNT_AN 0x40000000
+/* Link Training/New page */
+#define MEMAC_IEVNT_LT 0x20000000
+/* Magic pkt detection */
+#define MEMAC_IEVNT_MGI 0x00004000
+/* Timestamp FIFO ECC error */
+#define MEMAC_IEVNT_TS_ECC_ER 0x00002000
+/* Rx FIFO overflow */
+#define MEMAC_IEVNT_RX_FIFO_OVFL 0x00001000
+/* Tx FIFO underflow */
+#define MEMAC_IEVNT_TX_FIFO_UNFL 0x00000800
+/* Tx FIFO overflow */
+#define MEMAC_IEVNT_TX_FIFO_OVFL 0x00000400
+/* Tx frame ECC error */
+#define MEMAC_IEVNT_TX_ECC_ER 0x00000200
+/* Rx frame ECC error */
+#define MEMAC_IEVNT_RX_ECC_ER 0x00000100
+/* Link Interruption flt */
+#define MEMAC_IEVNT_LI_FAULT 0x00000080
+/* Rx FIFO empty */
+#define MEMAC_IEVNT_RX_EMPTY 0x00000040
+/* Tx FIFO empty */
+#define MEMAC_IEVNT_TX_EMPTY 0x00000020
+/* Low Power Idle */
+#define MEMAC_IEVNT_RX_LOWP 0x00000010
+/* Phy loss of signal */
+#define MEMAC_IEVNT_PHY_LOS 0x00000004
+/* Remote fault (XGMII) */
+#define MEMAC_IEVNT_REM_FAULT 0x00000002
+/* Local fault (XGMII) */
+#define MEMAC_IEVNT_LOC_FAULT 0x00000001
+
+#define DEFAULT_PAUSE_QUANTA 0xf000
+#define DEFAULT_FRAME_LENGTH 0x600
+#define DEFAULT_TX_IPG_LENGTH 12
+
+/**
+ * memory map
+ **/
+
+struct mac_addr {
+ /* Lower 32 bits of 48-bit MAC address */
+ uint32_t mac_addr_l;
+ /* Upper 16 bits of 48-bit MAC address */
+ uint32_t mac_addr_u;
+};
+
+struct memac_regs {
+ /* General Control and Status */
+ uint32_t res0000[2];
+ /* 0x008 Ctrl and cfg */
+ uint32_t command_config;
+ /* 0x00C-0x010 MAC_ADDR_0...1 */
+ struct mac_addr mac_addr0;
+ /* 0x014 Max frame length */
+ uint32_t maxfrm;
+ uint32_t res0018[1];
+ /* Receive FIFO configuration reg */
+ uint32_t rx_fifo_sections;
+ /* Transmit FIFO configuration reg */
+ uint32_t tx_fifo_sections;
+ uint32_t res0024[2];
+ /* 0x02C Hash table control */
+ uint32_t hashtable_ctrl;
+ uint32_t res0030[4];
+ /* 0x040 Interrupt event */
+ uint32_t ievent;
+ /* 0x044 Transmitter inter-packet-gap */
+ uint32_t tx_ipg_length;
+ uint32_t res0048;
+ /* 0x04C Interrupt mask */
+ uint32_t imask;
+ uint32_t res0050;
+ /* 0x054 Pause quanta */
+ uint32_t pause_quanta[4];
+ /* 0x064 Pause quanta threshold */
+ uint32_t pause_thresh[4];
+ /* 0x074 Receive pause status */
+ uint32_t rx_pause_status;
+ uint32_t res0078[2];
+ /* 0x80-0x0B4 mac padr */
+ struct mac_addr mac_addr[MEMAC_NUM_OF_PADDRS];
+ /* 0x0B8 Low Power Wakeup Timer */
+ uint32_t lpwake_timer;
+ /* 0x0BC Transmit EEE Low Power Timer */
+ uint32_t sleep_timer;
+ uint32_t res00c0[8];
+ /* 0x0E0 Statistics configuration */
+ uint32_t statn_config;
+ uint32_t res00e4[7];
+ /* Rx Statistics Counter */
+ uint32_t reoct_l;
+ uint32_t reoct_u;
+ uint32_t roct_l;
+ uint32_t roct_u;
+ uint32_t raln_l;
+ uint32_t raln_u;
+ uint32_t rxpf_l;
+ uint32_t rxpf_u;
+ uint32_t rfrm_l;
+ uint32_t rfrm_u;
+ uint32_t rfcs_l;
+ uint32_t rfcs_u;
+ uint32_t rvlan_l;
+ uint32_t rvlan_u;
+ uint32_t rerr_l;
+ uint32_t rerr_u;
+ uint32_t ruca_l;
+ uint32_t ruca_u;
+ uint32_t rmca_l;
+ uint32_t rmca_u;
+ uint32_t rbca_l;
+ uint32_t rbca_u;
+ uint32_t rdrp_l;
+ uint32_t rdrp_u;
+ uint32_t rpkt_l;
+ uint32_t rpkt_u;
+ uint32_t rund_l;
+ uint32_t rund_u;
+ uint32_t r64_l;
+ uint32_t r64_u;
+ uint32_t r127_l;
+ uint32_t r127_u;
+ uint32_t r255_l;
+ uint32_t r255_u;
+ uint32_t r511_l;
+ uint32_t r511_u;
+ uint32_t r1023_l;
+ uint32_t r1023_u;
+ uint32_t r1518_l;
+ uint32_t r1518_u;
+ uint32_t r1519x_l;
+ uint32_t r1519x_u;
+ uint32_t rovr_l;
+ uint32_t rovr_u;
+ uint32_t rjbr_l;
+ uint32_t rjbr_u;
+ uint32_t rfrg_l;
+ uint32_t rfrg_u;
+ uint32_t rcnp_l;
+ uint32_t rcnp_u;
+ uint32_t rdrntp_l;
+ uint32_t rdrntp_u;
+ uint32_t res01d0[12];
+ /* Tx Statistics Counter */
+ uint32_t teoct_l;
+ uint32_t teoct_u;
+ uint32_t toct_l;
+ uint32_t toct_u;
+ uint32_t res0210[2];
+ uint32_t txpf_l;
+ uint32_t txpf_u;
+ uint32_t tfrm_l;
+ uint32_t tfrm_u;
+ uint32_t tfcs_l;
+ uint32_t tfcs_u;
+ uint32_t tvlan_l;
+ uint32_t tvlan_u;
+ uint32_t terr_l;
+ uint32_t terr_u;
+ uint32_t tuca_l;
+ uint32_t tuca_u;
+ uint32_t tmca_l;
+ uint32_t tmca_u;
+ uint32_t tbca_l;
+ uint32_t tbca_u;
+ uint32_t res0258[2];
+ uint32_t tpkt_l;
+ uint32_t tpkt_u;
+ uint32_t tund_l;
+ uint32_t tund_u;
+ uint32_t t64_l;
+ uint32_t t64_u;
+ uint32_t t127_l;
+ uint32_t t127_u;
+ uint32_t t255_l;
+ uint32_t t255_u;
+ uint32_t t511_l;
+ uint32_t t511_u;
+ uint32_t t1023_l;
+ uint32_t t1023_u;
+ uint32_t t1518_l;
+ uint32_t t1518_u;
+ uint32_t t1519x_l;
+ uint32_t t1519x_u;
+ uint32_t res02a8[6];
+ uint32_t tcnp_l;
+ uint32_t tcnp_u;
+ uint32_t res02c8[14];
+ /* Line Interface Control */
+ uint32_t if_mode; /* 0x300 Interface Mode Control */
+ uint32_t if_status; /* 0x304 Interface Status */
+ uint32_t res0308[14];
+ /* HiGig/2 */
+ uint32_t hg_config; /* 0x340 Control and cfg */
+ uint32_t res0344[3];
+ uint32_t hg_pause_quanta; /* 0x350 Pause quanta */
+ uint32_t res0354[3];
+ uint32_t hg_pause_thresh; /* 0x360 Pause quanta threshold */
+ uint32_t res0364[3];
+ uint32_t hgrx_pause_status; /* 0x370 Receive pause status */
+ uint32_t hg_fifos_status; /* 0x374 fifos status */
+ uint32_t rhm; /* 0x378 rx messages counter */
+ uint32_t thm; /* 0x37C tx messages counter */
+};
+
+struct memac_cfg {
+ bool reset_on_init;
+ bool rx_error_discard;
+ bool pause_ignore;
+ bool pause_forward_enable;
+ bool no_length_check_enable;
+ bool cmd_frame_enable;
+ bool send_idle_enable;
+ bool wan_mode_enable;
+ bool promiscuous_mode_enable;
+ bool tx_addr_ins_enable;
+ bool loopback_enable;
+ bool lgth_check_nostdr;
+ bool time_stamp_enable;
+ bool pad_enable;
+ bool phy_tx_ena_on;
+ bool rx_sfd_any;
+ bool rx_pbl_fwd;
+ bool tx_pbl_fwd;
+ bool debug_mode;
+ bool wake_on_lan;
+ uint16_t max_frame_length;
+ uint16_t pause_quanta;
+ uint32_t tx_ipg_length;
+};
+
+/**
+*fman_memac_defconfig() - Get default MEMAC configuration
+*@cfg: pointer to configuration structure.
+ *
+*Call this function to obtain a default set of configuration values for
+*initializing MEMAC. The user can overwrite any of the values before calling
+*fman_memac_init(), if specific configuration needs to be applied.
+ */
+void fman_memac_defconfig(struct memac_cfg *cfg);
+
+int fman_memac_init(struct memac_regs __iomem *regs,
+ struct memac_cfg *cfg,
+ enum enet_interface enet_interface,
+ enum enet_speed enet_speed,
+ bool slow_10g_if,
+ uint32_t exceptions);
+
+void fman_memac_enable(struct memac_regs __iomem *regs, bool apply_rx,
+ bool apply_tx);
+
+void fman_memac_disable(struct memac_regs __iomem *regs, bool apply_rx,
+ bool apply_tx);
+
+void fman_memac_set_promiscuous(struct memac_regs __iomem *regs, bool val);
+
+void fman_memac_add_addr_in_paddr(struct memac_regs __iomem *regs,
+ uint8_t *adr, uint8_t paddr_num);
+
+void fman_memac_clear_addr_in_paddr(struct memac_regs __iomem *regs,
+ uint8_t paddr_num);
+
+void fman_memac_set_tx_pause_frames(struct memac_regs __iomem *regs,
+ uint8_t priority, uint16_t pause_time,
+ uint16_t thresh_time);
+
+uint16_t fman_memac_get_max_frame_len(struct memac_regs __iomem *regs);
+
+void fman_memac_set_exception(struct memac_regs __iomem *regs, uint32_t val,
+ bool enable);
+
+void fman_memac_reset(struct memac_regs __iomem *regs);
+
+void fman_memac_set_hash_table(struct memac_regs __iomem *regs, uint32_t val);
+
+void fman_memac_set_rx_ignore_pause_frames(struct memac_regs __iomem *regs,
+ bool enable);
+
+uint32_t fman_memac_get_event(struct memac_regs __iomem *regs,
+ uint32_t ev_mask);
+
+void fman_memac_ack_event(struct memac_regs __iomem *regs, uint32_t ev_mask);
+
+uint32_t fman_memac_get_interrupt_mask(struct memac_regs __iomem *regs);
+
+void fman_memac_adjust_link(struct memac_regs __iomem *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx);
+
+#endif /*__FSL_FMAN_MEMAC_H*/
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h
new file mode 100644
index 0000000..ad18d6f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_memac_mii_acc.h
@@ -0,0 +1,76 @@
+/*
+ * 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 __FSL_FMAN_MEMAC_MII_ACC_H
+#define __FSL_FMAN_MEMAC_MII_ACC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK 0x0080ff80
+#define MDIO_CFG_HOLD_MASK 0x0000001c
+#define MDIO_CFG_ENC45 0x00000040
+#define MDIO_CFG_READ_ERR 0x00000002
+#define MDIO_CFG_BSY 0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT 5
+#define MDIO_CTL_READ 0x00008000
+
+#define MDIO_DATA_BSY 0x80000000
+
+/*MEMAC Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_PHY_RESET 0x8000
+#define PHY_SGMII_CR_RESET_AN 0x0200
+#define PHY_SGMII_CR_DEF_VAL 0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0
+#define PHY_SGMII_IF_MODE_AN 0x0002
+#define PHY_SGMII_IF_MODE_SGMII 0x0001
+#define PHY_SGMII_IF_MODE_1000X 0x0000
+
+/*----------------------------------------------------*/
+/* MII Configuration Control Memory Map Registers */
+/*----------------------------------------------------*/
+struct memac_mii_access_mem_map {
+ uint32_t mdio_cfg; /* 0x030 */
+ uint32_t mdio_ctrl; /* 0x034 */
+ uint32_t mdio_data; /* 0x038 */
+ uint32_t mdio_addr; /* 0x03c */
+};
+
+int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map __iomem
+ *mii_regs, uint8_t phy_addr, uint8_t reg,
+ uint16_t *data, enum enet_speed enet_speed);
+int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map __iomem
+ *mii_regs, uint8_t phy_addr, uint8_t reg,
+ uint16_t data, enum enet_speed enet_speed);
+
+#endif /* __MAC_API_MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h
new file mode 100644
index 0000000..6f8d440
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/flib/fsl_fman_tgec.h
@@ -0,0 +1,409 @@
+/*
+ * 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 __FSL_FMAN_TGEC_H
+#define __FSL_FMAN_TGEC_H
+
+#include "common/general.h"
+#include "fsl_enet.h"
+
+/* Transmit Inter-Packet Gap Length Register (TX_IPG_LENGTH) */
+#define TGEC_TX_IPG_LENGTH_MASK 0x000003ff
+
+/* Command and Configuration Register (COMMAND_CONFIG) */
+#define CMD_CFG_EN_TIMESTAMP 0x00100000
+#define CMD_CFG_TX_ADDR_INS_SEL 0x00080000
+#define CMD_CFG_NO_LEN_CHK 0x00020000
+#define CMD_CFG_SEND_IDLE 0x00010000
+#define CMD_CFG_RX_ER_DISC 0x00004000
+#define CMD_CFG_CMD_FRM_EN 0x00002000
+#define CMD_CFG_STAT_CLR 0x00001000
+#define CMD_CFG_LOOPBACK_EN 0x00000400
+#define CMD_CFG_TX_ADDR_INS 0x00000200
+#define CMD_CFG_PAUSE_IGNORE 0x00000100
+#define CMD_CFG_PAUSE_FWD 0x00000080
+#define CMD_CFG_PROMIS_EN 0x00000010
+#define CMD_CFG_WAN_MODE 0x00000008
+#define CMD_CFG_RX_EN 0x00000002
+#define CMD_CFG_TX_EN 0x00000001
+
+/* Interrupt Mask Register (IMASK) */
+#define TGEC_IMASK_MDIO_SCAN_EVENT 0x00010000
+#define TGEC_IMASK_MDIO_CMD_CMPL 0x00008000
+#define TGEC_IMASK_REM_FAULT 0x00004000
+#define TGEC_IMASK_LOC_FAULT 0x00002000
+#define TGEC_IMASK_TX_ECC_ER 0x00001000
+#define TGEC_IMASK_TX_FIFO_UNFL 0x00000800
+#define TGEC_IMASK_TX_FIFO_OVFL 0x00000400
+#define TGEC_IMASK_TX_ER 0x00000200
+#define TGEC_IMASK_RX_FIFO_OVFL 0x00000100
+#define TGEC_IMASK_RX_ECC_ER 0x00000080
+#define TGEC_IMASK_RX_JAB_FRM 0x00000040
+#define TGEC_IMASK_RX_OVRSZ_FRM 0x00000020
+#define TGEC_IMASK_RX_RUNT_FRM 0x00000010
+#define TGEC_IMASK_RX_FRAG_FRM 0x00000008
+#define TGEC_IMASK_RX_LEN_ER 0x00000004
+#define TGEC_IMASK_RX_CRC_ER 0x00000002
+#define TGEC_IMASK_RX_ALIGN_ER 0x00000001
+
+#define TGEC_EVENTS_MASK \
+ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT | \
+ TGEC_IMASK_MDIO_CMD_CMPL | \
+ TGEC_IMASK_REM_FAULT | \
+ TGEC_IMASK_LOC_FAULT | \
+ TGEC_IMASK_TX_ECC_ER | \
+ TGEC_IMASK_TX_FIFO_UNFL | \
+ TGEC_IMASK_TX_FIFO_OVFL | \
+ TGEC_IMASK_TX_ER | \
+ TGEC_IMASK_RX_FIFO_OVFL | \
+ TGEC_IMASK_RX_ECC_ER | \
+ TGEC_IMASK_RX_JAB_FRM | \
+ TGEC_IMASK_RX_OVRSZ_FRM | \
+ TGEC_IMASK_RX_RUNT_FRM | \
+ TGEC_IMASK_RX_FRAG_FRM | \
+ TGEC_IMASK_RX_LEN_ER | \
+ TGEC_IMASK_RX_CRC_ER | \
+ TGEC_IMASK_RX_ALIGN_ER))
+
+/* Hashtable Control Register (HASHTABLE_CTRL) */
+#define TGEC_HASH_MCAST_SHIFT 23
+#define TGEC_HASH_MCAST_EN 0x00000200
+#define TGEC_HASH_ADR_MSK 0x000001ff
+
+#define DEFAULT_WAN_MODE_ENABLE false
+#define DEFAULT_PROMISCUOUS_MODE_ENABLE false
+#define DEFAULT_PAUSE_FORWARD_ENABLE false
+#define DEFAULT_PAUSE_IGNORE false
+#define DEFAULT_TX_ADDR_INS_ENABLE false
+#define DEFAULT_LOOPBACK_ENABLE false
+#define DEFAULT_CMD_FRAME_ENABLE false
+#define DEFAULT_RX_ERROR_DISCARD false
+#define DEFAULT_SEND_IDLE_ENABLE false
+#define DEFAULT_NO_LENGTH_CHECK_ENABLE true
+#define DEFAULT_LGTH_CHECK_NOSTDR false
+#define DEFAULT_TIME_STAMP_ENABLE false
+#define DEFAULT_TX_IPG_LENGTH 12
+#define DEFAULT_MAX_FRAME_LENGTH 0x600
+#define DEFAULT_PAUSE_QUANT 0xf000
+
+/**
+ * 10G memory map
+ **/
+struct tgec_regs {
+ uint32_t tgec_id; /* 0x000 Controller ID */
+ uint32_t reserved001[1]; /* 0x004 */
+ uint32_t command_config; /* 0x008 Control and configuration */
+ uint32_t mac_addr_0; /* 0x00c Lower 32 bits of the MAC adr */
+ uint32_t mac_addr_1; /* 0x010 Upper 16 bits of the MAC adr */
+ uint32_t maxfrm; /* 0x014 Maximum frame length */
+ uint32_t pause_quant; /* 0x018 Pause quanta */
+ uint32_t rx_fifo_sections; /* 0x01c */
+ uint32_t tx_fifo_sections; /* 0x020 */
+ uint32_t rx_fifo_almost_f_e; /* 0x024 */
+ uint32_t tx_fifo_almost_f_e; /* 0x028 */
+ uint32_t hashtable_ctrl; /* 0x02c Hash table control */
+ uint32_t mdio_cfg_status; /* 0x030 */
+ uint32_t mdio_command; /* 0x034 */
+ uint32_t mdio_data; /* 0x038 */
+ uint32_t mdio_regaddr; /* 0x03c */
+ uint32_t status; /* 0x040 */
+ uint32_t tx_ipg_len; /* 0x044 Transmitter inter-packet-gap */
+ uint32_t mac_addr_2; /* 0x048 Lower 32 bits of 2nd MAC adr */
+ uint32_t mac_addr_3; /* 0x04c Upper 16 bits of 2nd MAC adr */
+ uint32_t rx_fifo_ptr_rd; /* 0x050 */
+ uint32_t rx_fifo_ptr_wr; /* 0x054 */
+ uint32_t tx_fifo_ptr_rd; /* 0x058 */
+ uint32_t tx_fifo_ptr_wr; /* 0x05c */
+ uint32_t imask; /* 0x060 Interrupt mask */
+ uint32_t ievent; /* 0x064 Interrupt event */
+ uint32_t udp_port; /* 0x068 Defines a UDP Port number */
+ uint32_t type_1588v2; /* 0x06c Type field for 1588v2 */
+ uint32_t reserved070[4]; /* 0x070 */
+ /*10Ge Statistics Counter */
+ uint32_t tfrm_u; /* 80 aFramesTransmittedOK */
+ uint32_t tfrm_l; /* 84 aFramesTransmittedOK */
+ uint32_t rfrm_u; /* 88 aFramesReceivedOK */
+ uint32_t rfrm_l; /* 8c aFramesReceivedOK */
+ uint32_t rfcs_u; /* 90 aFrameCheckSequenceErrors */
+ uint32_t rfcs_l; /* 94 aFrameCheckSequenceErrors */
+ uint32_t raln_u; /* 98 aAlignmentErrors */
+ uint32_t raln_l; /* 9c aAlignmentErrors */
+ uint32_t txpf_u; /* A0 aPAUSEMACCtrlFramesTransmitted */
+ uint32_t txpf_l; /* A4 aPAUSEMACCtrlFramesTransmitted */
+ uint32_t rxpf_u; /* A8 aPAUSEMACCtrlFramesReceived */
+ uint32_t rxpf_l; /* Ac aPAUSEMACCtrlFramesReceived */
+ uint32_t rlong_u; /* B0 aFrameTooLongErrors */
+ uint32_t rlong_l; /* B4 aFrameTooLongErrors */
+ uint32_t rflr_u; /* B8 aInRangeLengthErrors */
+ uint32_t rflr_l; /* Bc aInRangeLengthErrors */
+ uint32_t tvlan_u; /* C0 VLANTransmittedOK */
+ uint32_t tvlan_l; /* C4 VLANTransmittedOK */
+ uint32_t rvlan_u; /* C8 VLANReceivedOK */
+ uint32_t rvlan_l; /* Cc VLANReceivedOK */
+ uint32_t toct_u; /* D0 if_out_octets */
+ uint32_t toct_l; /* D4 if_out_octets */
+ uint32_t roct_u; /* D8 if_in_octets */
+ uint32_t roct_l; /* Dc if_in_octets */
+ uint32_t ruca_u; /* E0 if_in_ucast_pkts */
+ uint32_t ruca_l; /* E4 if_in_ucast_pkts */
+ uint32_t rmca_u; /* E8 ifInMulticastPkts */
+ uint32_t rmca_l; /* Ec ifInMulticastPkts */
+ uint32_t rbca_u; /* F0 ifInBroadcastPkts */
+ uint32_t rbca_l; /* F4 ifInBroadcastPkts */
+ uint32_t terr_u; /* F8 if_out_errors */
+ uint32_t terr_l; /* Fc if_out_errors */
+ uint32_t reserved100[2]; /* 100-108 */
+ uint32_t tuca_u; /* 108 if_out_ucast_pkts */
+ uint32_t tuca_l; /* 10c if_out_ucast_pkts */
+ uint32_t tmca_u; /* 110 ifOutMulticastPkts */
+ uint32_t tmca_l; /* 114 ifOutMulticastPkts */
+ uint32_t tbca_u; /* 118 ifOutBroadcastPkts */
+ uint32_t tbca_l; /* 11c ifOutBroadcastPkts */
+ uint32_t rdrp_u; /* 120 etherStatsDropEvents */
+ uint32_t rdrp_l; /* 124 etherStatsDropEvents */
+ uint32_t reoct_u; /* 128 etherStatsOctets */
+ uint32_t reoct_l; /* 12c etherStatsOctets */
+ uint32_t rpkt_u; /* 130 etherStatsPkts */
+ uint32_t rpkt_l; /* 134 etherStatsPkts */
+ uint32_t trund_u; /* 138 etherStatsUndersizePkts */
+ uint32_t trund_l; /* 13c etherStatsUndersizePkts */
+ uint32_t r64_u; /* 140 etherStatsPkts64Octets */
+ uint32_t r64_l; /* 144 etherStatsPkts64Octets */
+ uint32_t r127_u; /* 148 etherStatsPkts65to127Octets */
+ uint32_t r127_l; /* 14c etherStatsPkts65to127Octets */
+ uint32_t r255_u; /* 150 etherStatsPkts128to255Octets */
+ uint32_t r255_l; /* 154 etherStatsPkts128to255Octets */
+ uint32_t r511_u; /* 158 etherStatsPkts256to511Octets */
+ uint32_t r511_l; /* 15c etherStatsPkts256to511Octets */
+ uint32_t r1023_u; /* 160 etherStatsPkts512to1023Octets */
+ uint32_t r1023_l; /* 164 etherStatsPkts512to1023Octets */
+ uint32_t r1518_u; /* 168 etherStatsPkts1024to1518Octets */
+ uint32_t r1518_l; /* 16c etherStatsPkts1024to1518Octets */
+ uint32_t r1519x_u; /* 170 etherStatsPkts1519toX */
+ uint32_t r1519x_l; /* 174 etherStatsPkts1519toX */
+ uint32_t trovr_u; /* 178 etherStatsOversizePkts */
+ uint32_t trovr_l; /* 17c etherStatsOversizePkts */
+ uint32_t trjbr_u; /* 180 etherStatsJabbers */
+ uint32_t trjbr_l; /* 184 etherStatsJabbers */
+ uint32_t trfrg_u; /* 188 etherStatsFragments */
+ uint32_t trfrg_l; /* 18C etherStatsFragments */
+ uint32_t rerr_u; /* 190 if_in_errors */
+ uint32_t rerr_l; /* 194 if_in_errors */
+};
+
+/**
+*struct tgec_cfg - TGEC configuration
+ *
+*@rx_error_discard: Receive Erroneous Frame Discard Enable. When set to 1
+* any frame received with an error is discarded in the
+* Core and not forwarded to the Client interface.
+* When set to 0 (Reset value), erroneous Frames are
+* forwarded to the Client interface with ff_rx_err
+* asserted.
+*@pause_ignore: Ignore Pause Frame Quanta. If set to 1 received pause
+* frames are ignored by the MAC. When set to 0
+* (Reset value) the transmit process is stopped for the
+* amount of time specified in the pause quanta received
+* within a pause frame.
+*@pause_forward_enable:
+* Terminate / Forward Pause Frames. If set to 1 pause
+* frames are forwarded to the user application. When set
+* to 0 (Reset value) pause frames are terminated and
+* discarded within the MAC.
+*@no_length_check_enable:
+* Payload Length Check Disable. When set to 0
+* (Reset value), the Core checks the frame's payload
+* length with the Frame Length/Type field, when set to 1
+* the payload length check is disabled.
+*@cmd_frame_enable: Enables reception of all command frames. When set to 1
+* all Command Frames are accepted, when set to 0
+* (Reset Value) only Pause Frames are accepted and all
+* other Command Frames are rejected.
+*@send_idle_enable: Force Idle Generation. When set to 1, the MAC
+* permanently sends XGMII Idle sequences even when faults
+* are received.
+*@wan_mode_enable: WAN Mode Enable. Sets WAN mode (1) or LAN mode
+* (0, default) of operation.
+*@promiscuous_mode_enable:
+* Enables MAC promiscuous operation. When set to 1, all
+* frames are received without any MAC address filtering,
+* when set to 0 (Reset value) Unicast Frames with a
+* destination address not matching the Core MAC Address
+* (MAC Address programmed in Registers MAC_ADDR_0 and
+* MAC_ADDR_1 or the MAC address programmed in Registers
+* MAC_ADDR_2 and MAC_ADDR_3) are rejected.
+*@tx_addr_ins_enable: Set Source MAC Address on Transmit. If set to 1 the
+* MAC overwrites the source MAC address received from the
+* Client Interface with one of the MAC addresses. If set
+* to 0 (Reset value), the source MAC address from the
+* Client Interface is transmitted unmodified to the line.
+*@loopback_enable: PHY Interface Loopback. When set to 1, the signal
+* loop_ena is set to '1', when set to 0 (Reset value)
+* the signal loop_ena is set to 0.
+*@lgth_check_nostdr: The Core interprets the Length/Type field differently
+* depending on the value of this Bit
+*@time_stamp_enable: This bit selects between enabling and disabling the
+* IEEE 1588 functionality. 1: IEEE 1588 is enabled
+* 0: IEEE 1588 is disabled
+*@max_frame_length: Maximum supported received frame length.
+* The 10GEC MAC supports reception of any frame size up
+* to 16,352 bytes (0x3FE0). Typical settings are
+* 0x05EE (1,518 bytes) for standard frames.
+* Default setting is 0x0600 (1,536 bytes).
+* Received frames that exceed this stated maximum
+* are truncated.
+*@pause_quant: Pause quanta value used with transmitted pause frames.
+* Each quanta represents a 512 bit-times.
+*@tx_ipg_length: Transmit Inter-Packet-Gap (IPG) value. A 6-bit value:
+* Depending on LAN or WAN mode of operation the value has
+* the following meaning: - LAN Mode: Number of octets in
+* steps of 4. Valid values are 8, 12, 16, ... 100. DIC is
+* fully supported (see 10.6.1 page 49) for any setting. A
+* default of 12 (reset value) must be set to conform to
+* IEEE802.3ae. Warning: When set to 8, PCS layers may not
+* be able to perform clock rate compensation. - WAN Mode:
+* Stretch factor. Valid values are 4..15. The stretch
+* factor is calculated as (value+1)*8. A default of 12
+* (reset value) must be set to conform to IEEE 802.3ae
+* (i.e. 13*8=104). A larger value shrinks the IPG
+* (increasing bandwidth).
+ *
+*This structure contains basic TGEC configuration and must be passed to
+*fman_tgec_init() function. A default set of configuration values can be
+*obtained by calling fman_tgec_defconfig().
+ */
+struct tgec_cfg {
+ bool rx_error_discard;
+ bool pause_ignore;
+ bool pause_forward_enable;
+ bool no_length_check_enable;
+ bool cmd_frame_enable;
+ bool send_idle_enable;
+ bool wan_mode_enable;
+ bool promiscuous_mode_enable;
+ bool tx_addr_ins_enable;
+ bool loopback_enable;
+ bool lgth_check_nostdr;
+ bool time_stamp_enable;
+ uint16_t max_frame_length;
+ uint16_t pause_quant;
+ uint32_t tx_ipg_length;
+ bool skip_fman11_workaround;
+};
+
+void fman_tgec_defconfig(struct tgec_cfg *cfg);
+
+/**
+*fman_tgec_init() - Init tgec hardware block
+*@regs: Pointer to tgec register block
+*@cfg: tgec configuration data
+*@exceptions_mask: initial exceptions mask
+ *
+*This function initializes the tgec controller and applies its
+*basic configuration.
+ *
+*Returns: 0 if successful, an error code otherwise.
+ */
+
+int fman_tgec_init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg,
+ uint32_t exception_mask);
+
+void fman_tgec_enable(struct tgec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx);
+
+void fman_tgec_disable(struct tgec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx);
+
+uint32_t fman_tgec_get_revision(struct tgec_regs __iomem *regs);
+
+void fman_tgec_set_mac_address(struct tgec_regs __iomem *regs,
+ uint8_t *macaddr);
+
+void fman_tgec_set_promiscuous(struct tgec_regs __iomem *regs, bool val);
+
+/**
+*fman_tgec_set_hash_table() - Sets the Hashtable Control Register
+*@regs: Pointer to TGEC register block
+*@value: Value to be written in Hashtable Control Register
+ */
+void fman_tgec_set_hash_table(struct tgec_regs __iomem *regs, uint32_t value);
+
+/**
+*fman_tgec_set_tx_pause_frames() - Sets the Pause Quanta Register
+*@regs: Pointer to TGEC register block
+*@pause_time: Pause quanta value used with transmitted pause frames.
+* Each quanta represents a 512 bit-times
+ */
+void fman_tgec_set_tx_pause_frames(struct tgec_regs __iomem *regs,
+ uint16_t pause_time);
+
+/**
+*fman_tgec_set_rx_ignore_pause_frames() - Changes the policy WRT pause frames
+*@regs: Pointer to TGEC register block
+*@en: Ignore/Respond to pause frame quanta
+ *
+*Sets the value of PAUSE_IGNORE field in the COMMAND_CONFIG Register
+*0 - MAC stops transmit process for the duration specified
+*in the Pause frame quanta of a received Pause frame.
+*1 - MAC ignores received Pause frames.
+ */
+void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs __iomem *regs,
+ bool en);
+
+uint32_t fman_tgec_get_event(struct tgec_regs __iomem *regs, uint32_t ev_mask);
+
+void fman_tgec_ack_event(struct tgec_regs __iomem *regs, uint32_t ev_mask);
+
+uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs __iomem *regs);
+
+void fman_tgec_enable_interrupt(struct tgec_regs __iomem *regs,
+ uint32_t ev_mask);
+
+void fman_tgec_disable_interrupt(struct tgec_regs __iomem *regs,
+ uint32_t ev_mask);
+
+/**
+*fman_tgec_get_max_frame_len() - Returns the maximum frame length value
+*@regs: Pointer to TGEC register block
+ */
+uint16_t fman_tgec_get_max_frame_len(struct tgec_regs __iomem *regs);
+
+/**
+*fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007() - Initialize the
+*main tgec configuration parameters
+*@regs: Pointer to TGEC register block
+ *
+*TODO
+ */
+void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs
+ __iomem *regs);
+
+#endif /* __FSL_FMAN_TGEC_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB
2015-05-07 13:05 ` [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 07/12] fsl/fman: Add FMan MURAM support Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
The FMan MAC FLib provides basic API used by the drivers to
configure and control the FMan MAC hardware.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
drivers/net/ethernet/freescale/fman/Makefile | 1 +
drivers/net/ethernet/freescale/fman/mac/Makefile | 5 +
.../net/ethernet/freescale/fman/mac/fman_crc32.c | 116 +++++
.../net/ethernet/freescale/fman/mac/fman_crc32.h | 39 ++
.../net/ethernet/freescale/fman/mac/fman_dtsec.c | 571 +++++++++++++++++++++
.../freescale/fman/mac/fman_dtsec_mii_acc.c | 168 ++++++
.../net/ethernet/freescale/fman/mac/fman_memac.c | 365 +++++++++++++
.../freescale/fman/mac/fman_memac_mii_acc.c | 217 ++++++++
.../net/ethernet/freescale/fman/mac/fman_tgec.c | 217 ++++++++
9 files changed, 1699 insertions(+)
create mode 100644 drivers/net/ethernet/freescale/fman/mac/Makefile
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_crc32.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_crc32.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_memac.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fman_tgec.c
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index a9ae0aa..534d1ed 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -5,3 +5,4 @@ obj-y += fsl_fman.o
fsl_fman-objs := fman.o
obj-y += port/
+obj-y += mac/
diff --git a/drivers/net/ethernet/freescale/fman/mac/Makefile b/drivers/net/ethernet/freescale/fman/mac/Makefile
new file mode 100644
index 0000000..80b7048
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/Makefile
@@ -0,0 +1,5 @@
+obj-$(CONFIG_FSL_FMAN_MAC) += fsl_fman_mac.o
+
+fsl_fman_mac-objs := fman_dtsec.o fman_dtsec_mii_acc.o \
+ fman_memac.o fman_tgec.o \
+ fman_crc32.o fman_memac_mii_acc.o
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_crc32.c b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.c
new file mode 100644
index 0000000..1536d12
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.c
@@ -0,0 +1,116 @@
+/*
+ * 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_crc32.h"
+#include "common/general.h"
+
+/* precomputed CRC values for address hashing */
+static const uint32_t crc_tbl[256] = {
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
+ 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
+ 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+ 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
+ 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
+ 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
+ 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
+ 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+ 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
+ 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
+ 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
+ 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
+ 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+ 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
+ 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
+ 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
+ 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
+ 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+ 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
+ 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
+ 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
+ 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/* Get the mirrored value of a byte size number. (0x11010011 --> 0x11001011) */
+static inline uint8_t get_mirror8(uint8_t n)
+{
+ uint8_t mirror[16] = {
+ 0x00, 0x08, 0x04, 0x0c, 0x02, 0x0a, 0x06, 0x0e,
+ 0x01, 0x09, 0x05, 0x0d, 0x03, 0x0b, 0x07, 0x0f
+ };
+ return (uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4])));
+}
+
+static inline uint32_t get_mirror32(uint32_t n)
+{
+ return ((uint32_t)get_mirror8((uint8_t)(n)) << 24) |
+ ((uint32_t)get_mirror8((uint8_t)(n >> 8)) << 16) |
+ ((uint32_t)get_mirror8((uint8_t)(n >> 16)) << 8) |
+ ((uint32_t)get_mirror8((uint8_t)(n >> 24)));
+}
+
+uint32_t get_mac_addr_crc(uint64_t _addr)
+{
+ uint32_t i;
+ uint8_t data;
+ uint32_t crc;
+
+ /* CRC calculation */
+ crc = 0xffffffff;
+ for (i = 0; i < 6; i++) {
+ data = (uint8_t)(_addr >> ((5 - i) * 8));
+ crc = crc ^ data;
+ crc = crc_tbl[crc & 0xff] ^ (crc >> 8);
+ }
+
+ crc = get_mirror32(crc);
+ return crc;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_crc32.h b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.h
new file mode 100644
index 0000000..eac30f3
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_crc32.h
@@ -0,0 +1,39 @@
+/*
+ * 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 __FMAN_CRC32_H
+#define __FMAN_CRC32_H
+
+#include "common/general.h"
+
+uint32_t get_mac_addr_crc(uint64_t _addr);
+
+#endif /* __FMAN_CRC32_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c
new file mode 100644
index 0000000..290a037
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec.c
@@ -0,0 +1,571 @@
+/*
+ * 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 "fsl_fman_dtsec.h"
+
+void fman_dtsec_stop_rx(struct dtsec_regs __iomem *regs)
+{
+ /* Assert the graceful stop bit */
+ iowrite32be(ioread32be(®s->rctrl) | RCTRL_GRS, ®s->rctrl);
+}
+
+void fman_dtsec_stop_tx(struct dtsec_regs __iomem *regs)
+{
+ /* Assert the graceful stop bit */
+ iowrite32be(ioread32be(®s->tctrl) | DTSEC_TCTRL_GTS, ®s->tctrl);
+}
+
+void fman_dtsec_start_tx(struct dtsec_regs __iomem *regs)
+{
+ /* clear the graceful stop bit */
+ iowrite32be(ioread32be(®s->tctrl) & ~DTSEC_TCTRL_GTS, ®s->tctrl);
+}
+
+void fman_dtsec_start_rx(struct dtsec_regs __iomem *regs)
+{
+ /* clear the graceful stop bit */
+ iowrite32be(ioread32be(®s->rctrl) & ~RCTRL_GRS, ®s->rctrl);
+}
+
+void fman_dtsec_defconfig(struct dtsec_cfg *cfg)
+{
+ cfg->halfdup_on = DEFAULT_HALFDUP_ON;
+ cfg->halfdup_retransmit = DEFAULT_HALFDUP_RETRANSMIT;
+ cfg->halfdup_coll_window = DEFAULT_HALFDUP_COLL_WINDOW;
+ cfg->halfdup_excess_defer = DEFAULT_HALFDUP_EXCESS_DEFER;
+ cfg->halfdup_no_backoff = DEFAULT_HALFDUP_NO_BACKOFF;
+ cfg->halfdup_bp_no_backoff = DEFAULT_HALFDUP_BP_NO_BACKOFF;
+ cfg->halfdup_alt_backoff_val = DEFAULT_HALFDUP_ALT_BACKOFF_VAL;
+ cfg->halfdup_alt_backoff_en = DEFAULT_HALFDUP_ALT_BACKOFF_EN;
+ cfg->rx_drop_bcast = DEFAULT_RX_DROP_BCAST;
+ cfg->rx_short_frm = DEFAULT_RX_SHORT_FRM;
+ cfg->rx_len_check = DEFAULT_RX_LEN_CHECK;
+ cfg->tx_pad_crc = DEFAULT_TX_PAD_CRC;
+ cfg->tx_crc = DEFAULT_TX_CRC;
+ cfg->rx_ctrl_acc = DEFAULT_RX_CTRL_ACC;
+ cfg->tx_pause_time = DEFAULT_TX_PAUSE_TIME;
+ /* PHY address 0 is reserved (DPAA RM) */
+ cfg->tbipa = DEFAULT_TBIPA;
+ cfg->rx_prepend = DEFAULT_RX_PREPEND;
+ cfg->ptp_tsu_en = DEFAULT_PTP_TSU_EN;
+ cfg->ptp_exception_en = DEFAULT_PTP_EXCEPTION_EN;
+ cfg->preamble_len = DEFAULT_PREAMBLE_LEN;
+ cfg->rx_preamble = DEFAULT_RX_PREAMBLE;
+ cfg->tx_preamble = DEFAULT_TX_PREAMBLE;
+ cfg->loopback = DEFAULT_LOOPBACK;
+ cfg->rx_time_stamp_en = DEFAULT_RX_TIME_STAMP_EN;
+ cfg->tx_time_stamp_en = DEFAULT_TX_TIME_STAMP_EN;
+ cfg->rx_flow = DEFAULT_RX_FLOW;
+ cfg->tx_flow = DEFAULT_TX_FLOW;
+ cfg->rx_group_hash_exd = DEFAULT_RX_GROUP_HASH_EXD;
+ cfg->tx_pause_time_extd = DEFAULT_TX_PAUSE_TIME_EXTD;
+ cfg->rx_promisc = DEFAULT_RX_PROMISC;
+ cfg->non_back_to_back_ipg1 = DEFAULT_NON_BACK_TO_BACK_IPG1;
+ cfg->non_back_to_back_ipg2 = DEFAULT_NON_BACK_TO_BACK_IPG2;
+ cfg->min_ifg_enforcement = DEFAULT_MIN_IFG_ENFORCEMENT;
+ cfg->back_to_back_ipg = DEFAULT_BACK_TO_BACK_IPG;
+ cfg->maximum_frame = DEFAULT_MAXIMUM_FRAME;
+ cfg->tbi_phy_addr = DEFAULT_TBI_PHY_ADDR;
+ cfg->wake_on_lan = DEFAULT_WAKE_ON_LAN;
+}
+
+int fman_dtsec_init(struct dtsec_regs __iomem *regs, struct dtsec_cfg *cfg,
+ enum enet_interface iface_mode,
+ enum enet_speed iface_speed,
+ uint8_t *macaddr,
+ uint8_t __maybe_unused fm_rev_maj,
+ uint8_t __maybe_unused fm_rev_min, uint32_t exception_mask)
+{
+ bool is_rgmii, is_sgmii, is_qsgmii;
+ int i;
+ uint32_t tmp;
+
+ /* let's start with a soft reset */
+ iowrite32be(MACCFG1_SOFT_RESET, ®s->maccfg1);
+ iowrite32be(0, ®s->maccfg1);
+
+ /*dtsec_id2*/
+ tmp = ioread32be(®s->tsec_id2);
+
+ /* check RGMII support */
+ if (iface_mode == E_ENET_IF_RGMII || iface_mode == E_ENET_IF_RMII)
+ if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+ return -EINVAL;
+
+ if (iface_mode == E_ENET_IF_SGMII || iface_mode == E_ENET_IF_MII)
+ if (tmp & DTSEC_ID2_INT_REDUCED_OFF)
+ return -EINVAL;
+
+ /*ECNTRL*/
+
+ is_rgmii = (bool)((iface_mode == E_ENET_IF_RGMII) ? true : false);
+ is_sgmii = (bool)((iface_mode == E_ENET_IF_SGMII) ? true : false);
+ is_qsgmii = (bool)((iface_mode == E_ENET_IF_QSGMII) ? true : false);
+
+ tmp = 0;
+ if (is_rgmii || iface_mode == E_ENET_IF_GMII)
+ tmp |= DTSEC_ECNTRL_GMIIM;
+ if (is_sgmii)
+ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM);
+ if (is_qsgmii)
+ tmp |= (DTSEC_ECNTRL_SGMIIM | DTSEC_ECNTRL_TBIM |
+ DTSEC_ECNTRL_QSGMIIM);
+ if (is_rgmii)
+ tmp |= DTSEC_ECNTRL_RPM;
+ if (iface_speed == E_ENET_SPEED_100)
+ tmp |= DTSEC_ECNTRL_R100M;
+
+ iowrite32be(tmp, ®s->ecntrl);
+ /*ECNTRL*/
+
+ /*TCTRL*/
+ tmp = 0;
+ if (cfg->halfdup_on)
+ tmp |= DTSEC_TCTRL_THDF;
+ if (cfg->tx_time_stamp_en)
+ tmp |= DTSEC_TCTRL_TTSE;
+
+ iowrite32be(tmp, ®s->tctrl);
+
+ /*TCTRL*/
+
+ /*PTV*/
+ tmp = 0;
+
+#ifdef FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1
+ if ((fm_rev_maj == 1) && (fm_rev_min == 0))
+ cfg->tx_pause_time += 2;
+#endif /* FM_SHORT_PAUSE_TIME_ERRATA_DTSEC1 */
+
+ if (cfg->tx_pause_time)
+ tmp |= cfg->tx_pause_time;
+ if (cfg->tx_pause_time_extd)
+ tmp |= cfg->tx_pause_time_extd << PTV_PTE_OFST;
+ iowrite32be(tmp, ®s->ptv);
+
+ /*RCTRL*/
+ tmp = 0;
+ tmp |= ((uint32_t)(cfg->rx_prepend & 0x0000001f)) << 16;
+ if (cfg->rx_ctrl_acc)
+ tmp |= RCTRL_CFA;
+ if (cfg->rx_group_hash_exd)
+ tmp |= RCTRL_GHTX;
+ if (cfg->rx_time_stamp_en)
+ tmp |= RCTRL_RTSE;
+ if (cfg->rx_drop_bcast)
+ tmp |= RCTRL_BC_REJ;
+ if (cfg->rx_short_frm)
+ tmp |= RCTRL_RSF;
+ if (cfg->rx_promisc)
+ tmp |= RCTRL_PROM;
+
+ iowrite32be(tmp, ®s->rctrl);
+ /*RCTRL*/
+
+ /*Assign a Phy Address to the TBI (TBIPA).
+ *Done also in cases where TBI is not selected to avoid conflict with
+ *the external PHY's Physical address
+ */
+ iowrite32be(cfg->tbipa, ®s->tbipa);
+
+ /*TMR_CTL*/
+ iowrite32be(0, ®s->tmr_ctrl);
+
+ if (cfg->ptp_tsu_en) {
+ tmp = 0;
+ tmp |= TMR_PEVENT_TSRE;
+ iowrite32be(tmp, ®s->tmr_pevent);
+
+ if (cfg->ptp_exception_en) {
+ tmp = 0;
+ tmp |= TMR_PEMASK_TSREEN;
+ iowrite32be(tmp, ®s->tmr_pemask);
+ }
+ }
+
+ /*MACCFG1*/
+ tmp = 0;
+ if (cfg->loopback)
+ tmp |= MACCFG1_LOOPBACK;
+ if (cfg->rx_flow)
+ tmp |= MACCFG1_RX_FLOW;
+ if (cfg->tx_flow)
+ tmp |= MACCFG1_TX_FLOW;
+ iowrite32be(tmp, ®s->maccfg1);
+
+ /*MACCFG1*/
+
+ /*MACCFG2*/
+ tmp = 0;
+
+ if (iface_speed < E_ENET_SPEED_1000)
+ tmp |= MACCFG2_NIBBLE_MODE;
+ else if (iface_speed == E_ENET_SPEED_1000)
+ tmp |= MACCFG2_BYTE_MODE;
+
+ tmp |= ((uint32_t)cfg->preamble_len & 0x0000000f)
+ << PREAMBLE_LENGTH_SHIFT;
+
+ if (cfg->rx_preamble)
+ tmp |= MACCFG2_PRE_AM_RX_EN;
+ if (cfg->tx_preamble)
+ tmp |= MACCFG2_PRE_AM_TX_EN;
+ if (cfg->rx_len_check)
+ tmp |= MACCFG2_LENGTH_CHECK;
+ if (cfg->tx_pad_crc)
+ tmp |= MACCFG2_PAD_CRC_EN;
+ if (cfg->tx_crc)
+ tmp |= MACCFG2_CRC_EN;
+ if (!cfg->halfdup_on)
+ tmp |= MACCFG2_FULL_DUPLEX;
+ iowrite32be(tmp, ®s->maccfg2);
+
+ /*MACCFG2*/
+
+ /*IPGIFG*/
+ tmp = (((cfg->non_back_to_back_ipg1 <<
+ IPGIFG_NON_BACK_TO_BACK_IPG_1_SHIFT)
+ & IPGIFG_NON_BACK_TO_BACK_IPG_1)
+ | ((cfg->non_back_to_back_ipg2 <<
+ IPGIFG_NON_BACK_TO_BACK_IPG_2_SHIFT)
+ & IPGIFG_NON_BACK_TO_BACK_IPG_2)
+ | ((cfg->min_ifg_enforcement << IPGIFG_MIN_IFG_ENFORCEMENT_SHIFT)
+ & IPGIFG_MIN_IFG_ENFORCEMENT)
+ | (cfg->back_to_back_ipg & IPGIFG_BACK_TO_BACK_IPG));
+ iowrite32be(tmp, ®s->ipgifg);
+
+ /*IPGIFG*/
+
+ /*HAFDUP*/
+ tmp = 0;
+
+ if (cfg->halfdup_alt_backoff_en)
+ tmp = (uint32_t)(HAFDUP_ALT_BEB |
+ ((cfg->halfdup_alt_backoff_val & 0x0000000f)
+ << HAFDUP_ALTERNATE_BEB_TRUNCATION_SHIFT));
+ if (cfg->halfdup_bp_no_backoff)
+ tmp |= HAFDUP_BP_NO_BACKOFF;
+ if (cfg->halfdup_no_backoff)
+ tmp |= HAFDUP_NO_BACKOFF;
+ if (cfg->halfdup_excess_defer)
+ tmp |= HAFDUP_EXCESS_DEFER;
+ tmp |= ((cfg->halfdup_retransmit << HAFDUP_RETRANSMISSION_MAX_SHIFT)
+ & HAFDUP_RETRANSMISSION_MAX);
+ tmp |= (cfg->halfdup_coll_window & HAFDUP_COLLISION_WINDOW);
+
+ iowrite32be(tmp, ®s->hafdup);
+ /*HAFDUP*/
+
+ /*MAXFRM*/
+ /* Initialize MAXFRM */
+ iowrite32be(cfg->maximum_frame, ®s->maxfrm);
+
+ /*MAXFRM*/
+
+ /*CAM1*/
+ iowrite32be(0xffffffff, ®s->cam1);
+ iowrite32be(0xffffffff, ®s->cam2);
+
+ /*IMASK*/
+ iowrite32be(exception_mask, ®s->imask);
+ /*IMASK*/
+
+ /*IEVENT*/
+ iowrite32be(0xffffffff, ®s->ievent);
+
+ /*MACSTNADDR1/2*/
+
+ tmp = (uint32_t)((macaddr[5] << 24) |
+ (macaddr[4] << 16) | (macaddr[3] << 8) | macaddr[2]);
+ iowrite32be(tmp, ®s->macstnaddr1);
+
+ tmp = (uint32_t)((macaddr[1] << 24) | (macaddr[0] << 16));
+ iowrite32be(tmp, ®s->macstnaddr2);
+
+ /*MACSTNADDR1/2*/
+
+ /*HASH*/
+ for (i = 0; i < NUM_OF_HASH_REGS; i++) {
+ /* Initialize IADDRx */
+ iowrite32be(0, ®s->igaddr[i]);
+ /* Initialize GADDRx */
+ iowrite32be(0, ®s->gaddr[i]);
+ }
+
+ return 0;
+}
+
+uint16_t fman_dtsec_get_max_frame_len(struct dtsec_regs __iomem *regs)
+{
+ return (uint16_t)ioread32be(®s->maxfrm);
+}
+
+void fman_dtsec_set_max_frame_len(struct dtsec_regs __iomem *regs,
+ uint16_t length)
+{
+ iowrite32be(length, ®s->maxfrm);
+}
+
+void fman_dtsec_set_mac_address(struct dtsec_regs __iomem *regs, uint8_t *adr)
+{
+ uint32_t tmp;
+
+ tmp = (uint32_t)((adr[5] << 24) |
+ (adr[4] << 16) | (adr[3] << 8) | adr[2]);
+ iowrite32be(tmp, ®s->macstnaddr1);
+
+ tmp = (uint32_t)((adr[1] << 24) | (adr[0] << 16));
+ iowrite32be(tmp, ®s->macstnaddr2);
+}
+
+void fman_dtsec_get_mac_address(struct dtsec_regs __iomem *regs,
+ uint8_t *macaddr)
+{
+ uint32_t tmp1, tmp2;
+
+ tmp1 = ioread32be(®s->macstnaddr1);
+ tmp2 = ioread32be(®s->macstnaddr2);
+
+ macaddr[0] = (uint8_t)((tmp2 & 0x00ff0000) >> 16);
+ macaddr[1] = (uint8_t)((tmp2 & 0xff000000) >> 24);
+ macaddr[2] = (uint8_t)(tmp1 & 0x000000ff);
+ macaddr[3] = (uint8_t)((tmp1 & 0x0000ff00) >> 8);
+ macaddr[4] = (uint8_t)((tmp1 & 0x00ff0000) >> 16);
+ macaddr[5] = (uint8_t)((tmp1 & 0xff000000) >> 24);
+}
+
+void fman_dtsec_set_bucket(struct dtsec_regs __iomem *regs, int bucket,
+ bool enable)
+{
+ int reg_idx = (bucket >> 5) & 0xf;
+ int bit_idx = bucket & 0x1f;
+ uint32_t bit_mask = 0x80000000 >> bit_idx;
+ uint32_t __iomem *reg;
+
+ if (reg_idx > 7)
+ reg = ®s->gaddr[reg_idx - 8];
+ else
+ reg = ®s->igaddr[reg_idx];
+
+ if (enable)
+ iowrite32be(ioread32be(reg) | bit_mask, reg);
+ else
+ iowrite32be(ioread32be(reg) & (~bit_mask), reg);
+}
+
+int fman_dtsec_adjust_link(struct dtsec_regs __iomem *regs,
+ enum enet_interface __maybe_unused iface_mode,
+ enum enet_speed speed, bool full_dx)
+{
+ uint32_t tmp;
+
+ if ((speed == E_ENET_SPEED_1000) && !full_dx)
+ return -EINVAL;
+
+ tmp = ioread32be(®s->maccfg2);
+ if (!full_dx)
+ tmp &= ~MACCFG2_FULL_DUPLEX;
+ else
+ tmp |= MACCFG2_FULL_DUPLEX;
+
+ tmp &= ~(MACCFG2_NIBBLE_MODE | MACCFG2_BYTE_MODE);
+ if (speed < E_ENET_SPEED_1000)
+ tmp |= MACCFG2_NIBBLE_MODE;
+ else if (speed == E_ENET_SPEED_1000)
+ tmp |= MACCFG2_BYTE_MODE;
+ iowrite32be(tmp, ®s->maccfg2);
+
+ tmp = ioread32be(®s->ecntrl);
+ if (speed == E_ENET_SPEED_100)
+ tmp |= DTSEC_ECNTRL_R100M;
+ else
+ tmp &= ~DTSEC_ECNTRL_R100M;
+ iowrite32be(tmp, ®s->ecntrl);
+
+ return 0;
+}
+
+void fman_dtsec_set_uc_promisc(struct dtsec_regs __iomem *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->rctrl);
+
+ if (enable)
+ tmp |= RCTRL_UPROM;
+ else
+ tmp &= ~RCTRL_UPROM;
+
+ iowrite32be(tmp, ®s->rctrl);
+}
+
+void fman_dtsec_set_mc_promisc(struct dtsec_regs __iomem *regs, bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->rctrl);
+
+ if (enable)
+ tmp |= RCTRL_MPROM;
+ else
+ tmp &= ~RCTRL_MPROM;
+
+ iowrite32be(tmp, ®s->rctrl);
+}
+
+void fman_dtsec_enable(struct dtsec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->maccfg1);
+
+ if (apply_rx)
+ tmp |= MACCFG1_RX_EN;
+
+ if (apply_tx)
+ tmp |= MACCFG1_TX_EN;
+
+ iowrite32be(tmp, ®s->maccfg1);
+}
+
+void fman_dtsec_disable(struct dtsec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->maccfg1);
+
+ if (apply_rx)
+ tmp &= ~MACCFG1_RX_EN;
+
+ if (apply_tx)
+ tmp &= ~MACCFG1_TX_EN;
+
+ iowrite32be(tmp, ®s->maccfg1);
+}
+
+void fman_dtsec_set_tx_pause_frames(struct dtsec_regs __iomem *regs,
+ uint16_t time)
+{
+ uint32_t ptv = 0;
+
+ /* fixme: don't enable tx pause for half-duplex */
+
+ if (time) {
+ ptv = ioread32be(®s->ptv);
+ ptv &= 0xffff0000;
+ ptv |= time & 0x0000ffff;
+ iowrite32be(ptv, ®s->ptv);
+
+ /* trigger the transmission of a flow-control pause frame */
+ iowrite32be(ioread32be(®s->maccfg1) | MACCFG1_TX_FLOW,
+ ®s->maccfg1);
+ } else
+ iowrite32be(ioread32be(®s->maccfg1) & ~MACCFG1_TX_FLOW,
+ ®s->maccfg1);
+}
+
+void fman_dtsec_handle_rx_pause(struct dtsec_regs __iomem *regs, bool en)
+{
+ uint32_t tmp;
+
+ /* todo: check if mac is set to full-duplex */
+
+ tmp = ioread32be(®s->maccfg1);
+ if (en)
+ tmp |= MACCFG1_RX_FLOW;
+ else
+ tmp &= ~MACCFG1_RX_FLOW;
+ iowrite32be(tmp, ®s->maccfg1);
+}
+
+uint32_t fman_dtsec_get_rctrl(struct dtsec_regs __iomem *regs)
+{
+ return ioread32be(®s->rctrl);
+}
+
+uint32_t fman_dtsec_get_revision(struct dtsec_regs __iomem *regs)
+{
+ return ioread32be(®s->tsec_id);
+}
+
+uint32_t fman_dtsec_get_event(struct dtsec_regs __iomem *regs,
+ uint32_t ev_mask)
+{
+ return ioread32be(®s->ievent) & ev_mask;
+}
+
+void fman_dtsec_ack_event(struct dtsec_regs __iomem *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, ®s->ievent);
+}
+
+uint32_t fman_dtsec_get_interrupt_mask(struct dtsec_regs __iomem *regs)
+{
+ return ioread32be(®s->imask);
+}
+
+uint32_t fman_dtsec_check_and_clear_tmr_event(struct dtsec_regs __iomem *regs)
+{
+ uint32_t event;
+
+ event = ioread32be(®s->tmr_pevent);
+ event &= ioread32be(®s->tmr_pemask);
+
+ if (event)
+ iowrite32be(event, ®s->tmr_pevent);
+ return event;
+}
+
+void fman_dtsec_enable_tmr_interrupt(struct dtsec_regs __iomem *regs)
+{
+ iowrite32be(ioread32be(®s->tmr_pemask) | TMR_PEMASK_TSREEN,
+ ®s->tmr_pemask);
+}
+
+void fman_dtsec_disable_tmr_interrupt(struct dtsec_regs __iomem *regs)
+{
+ iowrite32be(ioread32be(®s->tmr_pemask) & ~TMR_PEMASK_TSREEN,
+ ®s->tmr_pemask);
+}
+
+void fman_dtsec_enable_interrupt(struct dtsec_regs __iomem *regs,
+ uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask);
+}
+
+void fman_dtsec_disable_interrupt(struct dtsec_regs __iomem *regs,
+ uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask);
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c
new file mode 100644
index 0000000..c393938
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_dtsec_mii_acc.c
@@ -0,0 +1,168 @@
+/*
+ * 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 "common/general.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+/*dtsec_mii_get_div() - calculates the value of the dtsec mii divider
+ *@dtsec_freq: dtsec clock frequency (in Mhz)
+ *This function calculates the dtsec mii clock divider that determines
+ *the MII MDC clock. MII MDC clock will be set to work in the range
+ *of 1.5 to 2.5Mhz
+ *The output of this function is the value of MIIMCFG[MgmtClk] which
+ *implicitly determines the divider value.
+ *Note: the dTSEC system clock is equal to 1/2 of the FMan clock.
+ *The table below which reflects dtsec_mii_get_div() functionality
+ *shows the relations among dtsec_freq, MgmtClk, actual divider
+ *and the MII frequency:
+ *dtsec freq MgmtClk div MII freq Mhz
+ *[0.....80] 1 (1/4)(1/8) [0 to 2.5]
+ *[81...120] 2 (1/6)(1/8) [1.6 to 2.5]
+ *[121..160] 3 (1/8)(1/8) [1.8 to 2.5]
+ *[161..200] 4 (1/10)(1/8) [2.0 to 2.5]
+ *[201..280] 5 (1/14)(1/8) [1.8 to 2.5]
+ *[281..400] 6 (1/20)(1/8) [1.1 to 2.5]
+ *[401..560] 7 (1/28)(1/8) [1.8 to 2.5]
+ *[560..frq] 7 (1/28)(1/8) [frq/224]
+ *Returns: the MIIMCFG[MgmtClk] appropriate value
+ */
+
+static uint8_t dtsec_mii_get_div(uint16_t dtsec_freq)
+{
+ uint16_t mgmt_clk;
+
+ if (dtsec_freq < 80)
+ mgmt_clk = 1;
+ else if (dtsec_freq < 120)
+ mgmt_clk = 2;
+ else if (dtsec_freq < 160)
+ mgmt_clk = 3;
+ else if (dtsec_freq < 200)
+ mgmt_clk = 4;
+ else if (dtsec_freq < 280)
+ mgmt_clk = 5;
+ else if (dtsec_freq < 400)
+ mgmt_clk = 6;
+ else
+ mgmt_clk = 7;
+
+ return (uint8_t)mgmt_clk;
+}
+
+void fman_dtsec_mii_reset(struct dtsec_mii_reg __iomem *regs)
+{
+ /* Reset the management interface */
+ iowrite32be(ioread32be(®s->miimcfg) | MIIMCFG_RESET_MGMT,
+ ®s->miimcfg);
+ iowrite32be(ioread32be(®s->miimcfg) & ~MIIMCFG_RESET_MGMT,
+ ®s->miimcfg);
+}
+
+int fman_dtsec_mii_write_reg(struct dtsec_mii_reg __iomem *regs, uint8_t addr,
+ uint8_t reg, uint16_t data, uint16_t dtsec_freq)
+{
+ uint32_t tmp;
+
+ /* Setup the MII Mgmt clock speed */
+ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), ®s->miimcfg);
+ /* Memory barrier */
+ wmb();
+
+ /* Stop the MII management read cycle */
+ iowrite32be(0, ®s->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(®s->miimcom);
+ /* Memory barrier */
+ wmb();
+
+ /* Setting up MII Management Address Register */
+ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+ iowrite32be(tmp, ®s->miimadd);
+ /* Memory barrier */
+ wmb();
+
+ /* Setting up MII Management Control Register with data */
+ iowrite32be((uint32_t)data, ®s->miimcon);
+ /* Dummy read to make sure MIIMCON is written */
+ tmp = ioread32be(®s->miimcon);
+ /* Memory barrier */
+ wmb();
+
+ /* Wait until MII management write is complete */
+ /* todo: a timeout could be useful here */
+ while ((ioread32be(®s->miimind)) & MIIMIND_BUSY)
+ ; /* busy wait */
+
+ return 0;
+}
+
+int fman_dtsec_mii_read_reg(struct dtsec_mii_reg __iomem *regs, uint8_t addr,
+ uint8_t reg, uint16_t *data, uint16_t dtsec_freq)
+{
+ uint32_t tmp;
+
+ /* Setup the MII Mgmt clock speed */
+ iowrite32be((uint32_t)dtsec_mii_get_div(dtsec_freq), ®s->miimcfg);
+ /* Memory barrier */
+ wmb();
+
+ /* Setting up the MII Management Address Register */
+ tmp = (uint32_t)((addr << MIIMADD_PHY_ADDR_SHIFT) | reg);
+ iowrite32be(tmp, ®s->miimadd);
+ /* Memory barrier */
+ wmb();
+
+ /* Perform an MII management read cycle */
+ iowrite32be(MIIMCOM_READ_CYCLE, ®s->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(®s->miimcom);
+ /* Memory barrier */
+ wmb();
+
+ /* Wait until MII management read is complete */
+ /* todo: a timeout could be useful here */
+ while ((ioread32be(®s->miimind)) & MIIMIND_BUSY)
+ ; /* busy wait */
+
+ /* Read MII management status */
+ *data = (uint16_t)ioread32be(®s->miimstat);
+ /* Memory barrier */
+ wmb();
+
+ iowrite32be(0, ®s->miimcom);
+ /* Dummy read to make sure MIIMCOM is written */
+ tmp = ioread32be(®s->miimcom);
+
+ if (*data == 0xffff)
+ return -ENXIO;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_memac.c b/drivers/net/ethernet/freescale/fman/mac/fman_memac.c
new file mode 100644
index 0000000..e0bac5a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_memac.c
@@ -0,0 +1,365 @@
+/*
+ * 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 "fsl_fman_memac.h"
+
+uint32_t fman_memac_get_event(struct memac_regs __iomem *regs, uint32_t ev_mask)
+{
+ return ioread32be(®s->ievent) & ev_mask;
+}
+
+uint32_t fman_memac_get_interrupt_mask(struct memac_regs __iomem *regs)
+{
+ return ioread32be(®s->imask);
+}
+
+void fman_memac_ack_event(struct memac_regs __iomem *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, ®s->ievent);
+}
+
+void fman_memac_set_promiscuous(struct memac_regs __iomem *regs, bool val)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+
+ if (val)
+ tmp |= CMD_CFG_PROMIS_EN;
+ else
+ tmp &= ~CMD_CFG_PROMIS_EN;
+
+ iowrite32be(tmp, ®s->command_config);
+}
+
+void fman_memac_clear_addr_in_paddr(struct memac_regs __iomem *regs,
+ uint8_t paddr_num)
+{
+ if (paddr_num == 0) {
+ iowrite32be(0, ®s->mac_addr0.mac_addr_l);
+ iowrite32be(0, ®s->mac_addr0.mac_addr_u);
+ } else {
+ iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_l);
+ iowrite32be(0x0, ®s->mac_addr[paddr_num - 1].mac_addr_u);
+ }
+}
+
+void fman_memac_add_addr_in_paddr(struct memac_regs __iomem *regs,
+ uint8_t *adr, uint8_t paddr_num)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+
+ if (paddr_num == 0) {
+ iowrite32be(tmp0, ®s->mac_addr0.mac_addr_l);
+ iowrite32be(tmp1, ®s->mac_addr0.mac_addr_u);
+ } else {
+ iowrite32be(tmp0, ®s->mac_addr[paddr_num - 1].mac_addr_l);
+ iowrite32be(tmp1, ®s->mac_addr[paddr_num - 1].mac_addr_u);
+ }
+}
+
+void fman_memac_enable(struct memac_regs __iomem *regs, bool apply_rx,
+ bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+
+ if (apply_rx)
+ tmp |= CMD_CFG_RX_EN;
+
+ if (apply_tx)
+ tmp |= CMD_CFG_TX_EN;
+
+ iowrite32be(tmp, ®s->command_config);
+}
+
+void fman_memac_disable(struct memac_regs __iomem *regs, bool apply_rx,
+ bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+
+ if (apply_rx)
+ tmp &= ~CMD_CFG_RX_EN;
+
+ if (apply_tx)
+ tmp &= ~CMD_CFG_TX_EN;
+
+ iowrite32be(tmp, ®s->command_config);
+}
+
+void fman_memac_reset(struct memac_regs __iomem *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+
+ tmp |= CMD_CFG_SW_RESET;
+
+ iowrite32be(tmp, ®s->command_config);
+
+ while (ioread32be(®s->command_config) & CMD_CFG_SW_RESET)
+ ;
+}
+
+int fman_memac_init(struct memac_regs __iomem *regs,
+ struct memac_cfg *cfg,
+ enum enet_interface enet_interface,
+ enum enet_speed enet_speed,
+ bool slow_10g_if,
+ uint32_t exceptions)
+{
+ uint32_t tmp;
+
+ /* Config */
+ tmp = 0;
+ if (cfg->wan_mode_enable)
+ tmp |= CMD_CFG_WAN_MODE;
+ if (cfg->promiscuous_mode_enable)
+ tmp |= CMD_CFG_PROMIS_EN;
+ if (cfg->pause_forward_enable)
+ tmp |= CMD_CFG_PAUSE_FWD;
+ if (cfg->pause_ignore)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ if (cfg->tx_addr_ins_enable)
+ tmp |= CMD_CFG_TX_ADDR_INS;
+ if (cfg->loopback_enable)
+ tmp |= CMD_CFG_LOOPBACK_EN;
+ if (cfg->cmd_frame_enable)
+ tmp |= CMD_CFG_CNT_FRM_EN;
+ if (cfg->send_idle_enable)
+ tmp |= CMD_CFG_SEND_IDLE;
+ if (cfg->no_length_check_enable)
+ tmp |= CMD_CFG_NO_LEN_CHK;
+ if (cfg->rx_sfd_any)
+ tmp |= CMD_CFG_SFD_ANY;
+ if (cfg->pad_enable)
+ tmp |= CMD_CFG_TX_PAD_EN;
+ if (cfg->wake_on_lan)
+ tmp |= CMD_CFG_MG;
+
+ tmp |= CMD_CFG_CRC_FWD;
+
+ iowrite32be(tmp, ®s->command_config);
+
+ /* Max Frame Length */
+ iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm);
+
+ /* Pause Time */
+ iowrite32be((uint32_t)cfg->pause_quanta, ®s->pause_quanta[0]);
+ iowrite32be((uint32_t)0, ®s->pause_thresh[0]);
+
+ /* IF_MODE */
+ tmp = 0;
+ switch (enet_interface) {
+ case E_ENET_IF_XGMII:
+ case E_ENET_IF_XFI:
+ tmp |= IF_MODE_XGMII;
+ break;
+ default:
+ tmp |= IF_MODE_GMII;
+ if (enet_interface == E_ENET_IF_RGMII && !cfg->loopback_enable)
+ tmp |= IF_MODE_RGMII | IF_MODE_RGMII_AUTO;
+ }
+ iowrite32be(tmp, ®s->if_mode);
+
+ /* TX_FIFO_SECTIONS */
+ tmp = 0;
+ if (enet_interface == E_ENET_IF_XGMII ||
+ enet_interface == E_ENET_IF_XFI) {
+ if (slow_10g_if) {
+ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_SLOW_10G |
+ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
+ } else {
+ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_10G |
+ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_10G);
+ }
+ } else {
+ tmp |= (TX_FIFO_SECTIONS_TX_AVAIL_1G |
+ TX_FIFO_SECTIONS_TX_EMPTY_DEFAULT_1G);
+ }
+ iowrite32be(tmp, ®s->tx_fifo_sections);
+
+ /* clear all pending events and set-up interrupts */
+ fman_memac_ack_event(regs, 0xffffffff);
+ fman_memac_set_exception(regs, exceptions, true);
+
+ return 0;
+}
+
+void fman_memac_set_exception(struct memac_regs __iomem *regs, uint32_t val,
+ bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->imask);
+ if (enable)
+ tmp |= val;
+ else
+ tmp &= ~val;
+
+ iowrite32be(tmp, ®s->imask);
+}
+
+void fman_memac_set_hash_table(struct memac_regs __iomem *regs, uint32_t val)
+{
+ iowrite32be(val, ®s->hashtable_ctrl);
+}
+
+uint16_t fman_memac_get_max_frame_len(struct memac_regs __iomem *regs)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->maxfrm);
+
+ return (uint16_t)tmp;
+}
+
+void fman_memac_set_tx_pause_frames(struct memac_regs __iomem *regs,
+ uint8_t priority,
+ uint16_t pause_time, uint16_t thresh_time)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->tx_fifo_sections);
+
+ GET_TX_EMPTY_DEFAULT_VALUE(tmp);
+ iowrite32be(tmp, ®s->tx_fifo_sections);
+
+ tmp = ioread32be(®s->command_config);
+ tmp &= ~CMD_CFG_PFC_MODE;
+ priority = 0;
+
+ iowrite32be(tmp, ®s->command_config);
+
+ tmp = ioread32be(®s->pause_quanta[priority / 2]);
+ if (priority % 2)
+ tmp &= 0x0000FFFF;
+ else
+ tmp &= 0xFFFF0000;
+ tmp |= ((uint32_t)pause_time << (16 * (priority % 2)));
+ iowrite32be(tmp, ®s->pause_quanta[priority / 2]);
+
+ tmp = ioread32be(®s->pause_thresh[priority / 2]);
+ if (priority % 2)
+ tmp &= 0x0000FFFF;
+ else
+ tmp &= 0xFFFF0000;
+ tmp |= ((uint32_t)thresh_time << (16 * (priority % 2)));
+ iowrite32be(tmp, ®s->pause_thresh[priority / 2]);
+}
+
+void fman_memac_set_rx_ignore_pause_frames(struct memac_regs __iomem *regs,
+ bool enable)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+ if (enable)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ else
+ tmp &= ~CMD_CFG_PAUSE_IGNORE;
+
+ iowrite32be(tmp, ®s->command_config);
+}
+
+void fman_memac_adjust_link(struct memac_regs __iomem *regs,
+ enum enet_interface iface_mode,
+ enum enet_speed speed, bool full_dx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->if_mode);
+
+ if (full_dx)
+ tmp &= ~IF_MODE_HD;
+ else
+ tmp |= IF_MODE_HD;
+
+ if (iface_mode == E_ENET_IF_RGMII) {
+ /* Configure RGMII in manual mode */
+ tmp &= ~IF_MODE_RGMII_AUTO;
+ tmp &= ~IF_MODE_RGMII_SP_MASK;
+
+ if (full_dx)
+ tmp |= IF_MODE_RGMII_FD;
+ else
+ tmp &= ~IF_MODE_RGMII_FD;
+
+ switch (speed) {
+ case E_ENET_SPEED_1000:
+ tmp |= IF_MODE_RGMII_1000;
+ break;
+ case E_ENET_SPEED_100:
+ tmp |= IF_MODE_RGMII_100;
+ break;
+ case E_ENET_SPEED_10:
+ tmp |= IF_MODE_RGMII_10;
+ break;
+ default:
+ break;
+ }
+ }
+
+ iowrite32be(tmp, ®s->if_mode);
+}
+
+void fman_memac_defconfig(struct memac_cfg *cfg)
+{
+ cfg->reset_on_init = false;
+ cfg->wan_mode_enable = false;
+ cfg->promiscuous_mode_enable = false;
+ cfg->pause_forward_enable = false;
+ cfg->pause_ignore = false;
+ cfg->tx_addr_ins_enable = false;
+ cfg->loopback_enable = false;
+ cfg->cmd_frame_enable = false;
+ cfg->rx_error_discard = false;
+ cfg->send_idle_enable = false;
+ cfg->no_length_check_enable = true;
+ cfg->lgth_check_nostdr = false;
+ cfg->time_stamp_enable = false;
+ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+ cfg->max_frame_length = DEFAULT_FRAME_LENGTH;
+ cfg->pause_quanta = DEFAULT_PAUSE_QUANTA;
+ cfg->pad_enable = true;
+ cfg->phy_tx_ena_on = false;
+ cfg->rx_sfd_any = false;
+ cfg->rx_pbl_fwd = false;
+ cfg->tx_pbl_fwd = false;
+ cfg->debug_mode = false;
+ cfg->wake_on_lan = false;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c
new file mode 100644
index 0000000..7addd6d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_memac_mii_acc.c
@@ -0,0 +1,217 @@
+/*
+ * 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 "fsl_fman_memac_mii_acc.h"
+
+static void write_phy_reg_10g(struct memac_mii_access_mem_map __iomem *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ /* Leave only MDIO_CLK_DIV bits set on */
+ tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
+ /* Set maximum MDIO_HOLD value to allow phy to see
+ * change of data signal
+ **/
+ tmp_reg |= MDIO_CFG_HOLD_MASK;
+ /* Add 10G interface mode */
+ tmp_reg |= MDIO_CFG_ENC45;
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Specify phy and register to be accessed */
+ iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
+ iowrite32be(reg, &mii_regs->mdio_addr);
+ /* memory barrier */
+ wmb();
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Write data */
+ iowrite32be(data, &mii_regs->mdio_data);
+ /* memory barrier */
+ wmb();
+
+ /* Wait for write transaction end */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+}
+
+static uint32_t read_phy_reg_10g(struct memac_mii_access_mem_map __iomem
+ *mii_regs, uint8_t phy_addr, uint8_t reg,
+ uint16_t *data)
+{
+ uint32_t tmp_reg;
+
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ /* Leave only MDIO_CLK_DIV bits set on */
+ tmp_reg &= MDIO_CFG_CLK_DIV_MASK;
+ /* Set maximum MDIO_HOLD value to allow phy to see
+ * change of data signal
+ **/
+ tmp_reg |= MDIO_CFG_HOLD_MASK;
+ /* Add 10G interface mode */
+ tmp_reg |= MDIO_CFG_ENC45;
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Specify phy and register to be accessed */
+ iowrite32be(phy_addr, &mii_regs->mdio_ctrl);
+ iowrite32be(reg, &mii_regs->mdio_addr);
+ /* memory barrier */
+ wmb();
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Read cycle */
+ tmp_reg = phy_addr;
+ tmp_reg |= MDIO_CTL_READ;
+ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+ /* memory barrier */
+ wmb();
+
+ /* Wait for data to be available */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+
+ *data = (uint16_t)ioread32be(&mii_regs->mdio_data);
+
+ /* Check if there was an error */
+ return ioread32be(&mii_regs->mdio_cfg);
+}
+
+static void write_phy_reg_1g(struct memac_mii_access_mem_map __iomem *mii_regs,
+ uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+ uint32_t tmp_reg;
+
+ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Write transaction */
+ tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
+ tmp_reg |= reg;
+ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ iowrite32be(data, &mii_regs->mdio_data);
+
+ /* memory barrier */
+ wmb();
+
+ /* Wait for write transaction to end */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+}
+
+static uint32_t read_phy_reg_1g(struct memac_mii_access_mem_map __iomem
+ *mii_regs, uint8_t phy_addr, uint8_t reg,
+ uint16_t *data)
+{
+ uint32_t tmp_reg;
+
+ /* Leave only MDIO_CLK_DIV and MDIO_HOLD bits set on */
+ tmp_reg = ioread32be(&mii_regs->mdio_cfg);
+ tmp_reg &= (MDIO_CFG_CLK_DIV_MASK | MDIO_CFG_HOLD_MASK);
+ iowrite32be(tmp_reg, &mii_regs->mdio_cfg);
+
+ /* Wait for command completion */
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Read transaction */
+ tmp_reg = (phy_addr << MDIO_CTL_PHY_ADDR_SHIFT);
+ tmp_reg |= reg;
+ tmp_reg |= MDIO_CTL_READ;
+ iowrite32be(tmp_reg, &mii_regs->mdio_ctrl);
+
+ while ((ioread32be(&mii_regs->mdio_cfg)) & MDIO_CFG_BSY)
+ udelay(1);
+
+ /* Wait for data to be available */
+ while ((ioread32be(&mii_regs->mdio_data)) & MDIO_DATA_BSY)
+ udelay(1);
+
+ *data = (uint16_t)ioread32be(&mii_regs->mdio_data);
+
+ /* Check error */
+ return ioread32be(&mii_regs->mdio_cfg);
+}
+
+int fman_memac_mii_write_phy_reg(struct memac_mii_access_mem_map __iomem
+ *mii_regs, uint8_t phy_addr, uint8_t reg,
+ uint16_t data, enum enet_speed enet_speed)
+{
+ /* Figure out interface type - 10G vs 1G.
+ * In 10G interface both phy_addr and devAddr present.
+ **/
+ if (enet_speed == E_ENET_SPEED_10000)
+ write_phy_reg_10g(mii_regs, phy_addr, reg, data);
+ else
+ write_phy_reg_1g(mii_regs, phy_addr, reg, data);
+
+ return 0;
+}
+
+int fman_memac_mii_read_phy_reg(struct memac_mii_access_mem_map __iomem
+ *mii_regs, uint8_t phy_addr, uint8_t reg,
+ uint16_t *data, enum enet_speed enet_speed)
+{
+ uint32_t ans;
+ /* Figure out interface type - 10G vs 1G.
+ * In 10G interface both phy_addr and devAddr present.
+ **/
+ if (enet_speed == E_ENET_SPEED_10000)
+ ans = read_phy_reg_10g(mii_regs, phy_addr, reg, data);
+ else
+ ans = read_phy_reg_1g(mii_regs, phy_addr, reg, data);
+
+ if (ans & MDIO_CFG_READ_ERR)
+ return -EINVAL;
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c b/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c
new file mode 100644
index 0000000..11bcc1a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fman_tgec.c
@@ -0,0 +1,217 @@
+/*
+ * 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 "fsl_fman_tgec.h"
+
+void fman_tgec_set_mac_address(struct tgec_regs __iomem *regs, uint8_t *adr)
+{
+ uint32_t tmp0, tmp1;
+
+ tmp0 = (uint32_t)(adr[0] | adr[1] << 8 | adr[2] << 16 | adr[3] << 24);
+ tmp1 = (uint32_t)(adr[4] | adr[5] << 8);
+ iowrite32be(tmp0, ®s->mac_addr_0);
+ iowrite32be(tmp1, ®s->mac_addr_1);
+}
+
+void fman_tgec_enable(struct tgec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+ if (apply_rx)
+ tmp |= CMD_CFG_RX_EN;
+ if (apply_tx)
+ tmp |= CMD_CFG_TX_EN;
+ iowrite32be(tmp, ®s->command_config);
+}
+
+void fman_tgec_disable(struct tgec_regs __iomem *regs, bool apply_rx,
+ bool apply_tx)
+{
+ uint32_t tmp_reg_32;
+
+ tmp_reg_32 = ioread32be(®s->command_config);
+ if (apply_rx)
+ tmp_reg_32 &= ~CMD_CFG_RX_EN;
+ if (apply_tx)
+ tmp_reg_32 &= ~CMD_CFG_TX_EN;
+ iowrite32be(tmp_reg_32, ®s->command_config);
+}
+
+void fman_tgec_set_promiscuous(struct tgec_regs __iomem *regs, bool val)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+ if (val)
+ tmp |= CMD_CFG_PROMIS_EN;
+ else
+ tmp &= ~CMD_CFG_PROMIS_EN;
+ iowrite32be(tmp, ®s->command_config);
+}
+
+void fman_tgec_set_hash_table(struct tgec_regs __iomem *regs, uint32_t value)
+{
+ iowrite32be(value, ®s->hashtable_ctrl);
+}
+
+void fman_tgec_set_tx_pause_frames(struct tgec_regs __iomem *regs,
+ uint16_t pause_time)
+{
+ iowrite32be((uint32_t)pause_time, ®s->pause_quant);
+}
+
+void fman_tgec_set_rx_ignore_pause_frames(struct tgec_regs __iomem *regs,
+ bool en)
+{
+ uint32_t tmp;
+
+ tmp = ioread32be(®s->command_config);
+ if (en)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ else
+ tmp &= ~CMD_CFG_PAUSE_IGNORE;
+ iowrite32be(tmp, ®s->command_config);
+}
+
+uint32_t fman_tgec_get_event(struct tgec_regs __iomem *regs, uint32_t ev_mask)
+{
+ return ioread32be(®s->ievent) & ev_mask;
+}
+
+void fman_tgec_ack_event(struct tgec_regs __iomem *regs, uint32_t ev_mask)
+{
+ iowrite32be(ev_mask, ®s->ievent);
+}
+
+uint32_t fman_tgec_get_interrupt_mask(struct tgec_regs __iomem *regs)
+{
+ return ioread32be(®s->imask);
+}
+
+uint32_t fman_tgec_get_revision(struct tgec_regs __iomem *regs)
+{
+ return ioread32be(®s->tgec_id);
+}
+
+void fman_tgec_enable_interrupt(struct tgec_regs __iomem *regs,
+ uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(®s->imask) | ev_mask, ®s->imask);
+}
+
+void fman_tgec_disable_interrupt(struct tgec_regs __iomem *regs,
+ uint32_t ev_mask)
+{
+ iowrite32be(ioread32be(®s->imask) & ~ev_mask, ®s->imask);
+}
+
+uint16_t fman_tgec_get_max_frame_len(struct tgec_regs __iomem *regs)
+{
+ return (uint16_t)ioread32be(®s->maxfrm);
+}
+
+void fman_tgec_defconfig(struct tgec_cfg *cfg)
+{
+ cfg->wan_mode_enable = DEFAULT_WAN_MODE_ENABLE;
+ cfg->promiscuous_mode_enable = DEFAULT_PROMISCUOUS_MODE_ENABLE;
+ cfg->pause_forward_enable = DEFAULT_PAUSE_FORWARD_ENABLE;
+ cfg->pause_ignore = DEFAULT_PAUSE_IGNORE;
+ cfg->tx_addr_ins_enable = DEFAULT_TX_ADDR_INS_ENABLE;
+ cfg->loopback_enable = DEFAULT_LOOPBACK_ENABLE;
+ cfg->cmd_frame_enable = DEFAULT_CMD_FRAME_ENABLE;
+ cfg->rx_error_discard = DEFAULT_RX_ERROR_DISCARD;
+ cfg->send_idle_enable = DEFAULT_SEND_IDLE_ENABLE;
+ cfg->no_length_check_enable = DEFAULT_NO_LENGTH_CHECK_ENABLE;
+ cfg->lgth_check_nostdr = DEFAULT_LGTH_CHECK_NOSTDR;
+ cfg->time_stamp_enable = DEFAULT_TIME_STAMP_ENABLE;
+ cfg->tx_ipg_length = DEFAULT_TX_IPG_LENGTH;
+ cfg->max_frame_length = DEFAULT_MAX_FRAME_LENGTH;
+ cfg->pause_quant = DEFAULT_PAUSE_QUANT;
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ cfg->skip_fman11_workaround = false;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+}
+
+int fman_tgec_init(struct tgec_regs __iomem *regs, struct tgec_cfg *cfg,
+ uint32_t exception_mask)
+{
+ uint32_t tmp;
+
+ /* Config */
+ tmp = 0x40; /* CRC forward */
+ if (cfg->wan_mode_enable)
+ tmp |= CMD_CFG_WAN_MODE;
+ if (cfg->promiscuous_mode_enable)
+ tmp |= CMD_CFG_PROMIS_EN;
+ if (cfg->pause_forward_enable)
+ tmp |= CMD_CFG_PAUSE_FWD;
+ if (cfg->pause_ignore)
+ tmp |= CMD_CFG_PAUSE_IGNORE;
+ if (cfg->tx_addr_ins_enable)
+ tmp |= CMD_CFG_TX_ADDR_INS;
+ if (cfg->loopback_enable)
+ tmp |= CMD_CFG_LOOPBACK_EN;
+ if (cfg->cmd_frame_enable)
+ tmp |= CMD_CFG_CMD_FRM_EN;
+ if (cfg->rx_error_discard)
+ tmp |= CMD_CFG_RX_ER_DISC;
+ if (cfg->send_idle_enable)
+ tmp |= CMD_CFG_SEND_IDLE;
+ if (cfg->no_length_check_enable)
+ tmp |= CMD_CFG_NO_LEN_CHK;
+ if (cfg->time_stamp_enable)
+ tmp |= CMD_CFG_EN_TIMESTAMP;
+ iowrite32be(tmp, ®s->command_config);
+
+ /* Max Frame Length */
+ iowrite32be((uint32_t)cfg->max_frame_length, ®s->maxfrm);
+ /* Pause Time */
+ iowrite32be(cfg->pause_quant, ®s->pause_quant);
+
+ /* clear all pending events and set-up interrupts */
+ fman_tgec_ack_event(regs, 0xffffffff);
+ fman_tgec_enable_interrupt(regs, exception_mask);
+
+ return 0;
+}
+
+void fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(struct tgec_regs
+ __iomem *regs)
+{
+ uint32_t tmp;
+
+ /* restore the default tx ipg Length */
+ tmp = (ioread32be(®s->tx_ipg_len) & ~TGEC_TX_IPG_LENGTH_MASK) | 12;
+
+ iowrite32be(tmp, ®s->tx_ipg_len);
+}
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 07/12] fsl/fman: Add FMan MURAM support
2015-05-07 13:05 ` [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 08/12] fsl/fman: Add Frame Manager support Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
Add Frame Manager Multi-User RAM support.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
drivers/net/ethernet/freescale/fman/Kconfig | 1 +
drivers/net/ethernet/freescale/fman/Makefile | 6 +-
drivers/net/ethernet/freescale/fman/fm_muram.c | 114 +++++++++++++++++++++
.../net/ethernet/freescale/fman/inc/fm_muram_ext.h | 89 ++++++++++++++++
4 files changed, 208 insertions(+), 2 deletions(-)
create mode 100644 drivers/net/ethernet/freescale/fman/fm_muram.c
create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index af42c3a..825a0d5 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -1,6 +1,7 @@
config FSL_FMAN
bool "FMan support"
depends on FSL_SOC || COMPILE_TEST
+ select GENERIC_ALLOCATOR
default n
help
Freescale Data-Path Acceleration Architecture Frame Manager
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index 534d1ed..55c91bd 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -1,8 +1,10 @@
-subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib
+subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \
+ -I$(srctree)/drivers/net/ethernet/freescale/fman/inc \
+ -I$(srctree)/drivers/net/ethernet/freescale/fman
obj-y += fsl_fman.o
-fsl_fman-objs := fman.o
+fsl_fman-objs := fman.o fm_muram.o
obj-y += port/
obj-y += mac/
diff --git a/drivers/net/ethernet/freescale/fman/fm_muram.c b/drivers/net/ethernet/freescale/fman/fm_muram.c
new file mode 100644
index 0000000..2bca725
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_muram.c
@@ -0,0 +1,114 @@
+/*
+ * 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 MURAM ... */
+#include "fm_muram_ext.h"
+
+#include <linux/io.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/genalloc.h>
+
+struct muram_info {
+ struct gen_pool *pool;
+ void __iomem *vbase;
+ uint64_t size;
+ phys_addr_t pbase;
+};
+
+struct muram_info *fm_muram_init(phys_addr_t base, uint64_t size)
+{
+ struct muram_info *p_muram;
+ void __iomem *vaddr;
+ int ret;
+
+ p_muram = kzalloc(sizeof(*p_muram), GFP_KERNEL);
+ if (!p_muram)
+ return NULL;
+
+ p_muram->pool = gen_pool_create(ilog2(64), -1);
+ if (!p_muram->pool) {
+ pr_err("%s(): MURAM pool create failed\n", __func__);
+ return NULL;
+ }
+
+ vaddr = ioremap(base, size);
+ if (!vaddr) {
+ pr_err("%s(): MURAM ioremap failed\n", __func__);
+ return NULL;
+ }
+
+ ret = gen_pool_add_virt(p_muram->pool, (unsigned long)vaddr,
+ base, size, -1);
+ if (ret < 0) {
+ pr_err("%s(): MURAM pool add failed\n", __func__);
+ iounmap(vaddr);
+ return NULL;
+ }
+
+ p_muram->vbase = vaddr;
+ p_muram->pbase = base;
+ return p_muram;
+}
+
+void fm_muram_free(struct muram_info *p_muram)
+{
+ /* Destroy pool */
+ gen_pool_destroy(p_muram->pool);
+ /* Unmap memory */
+ iounmap(p_muram->vbase);
+ /* Free pointer */
+ kfree(p_muram);
+}
+
+void fm_muram_clear(struct muram_info *p_muram)
+{
+ memset_io(p_muram->vbase, 0, p_muram->size);
+}
+
+unsigned long fm_muram_alloc(struct muram_info *p_muram, uint32_t size)
+{
+ unsigned long vaddr;
+
+ vaddr = gen_pool_alloc(p_muram->pool, size);
+ if (!vaddr)
+ return 0;
+
+ return vaddr;
+}
+
+void fm_muram_free_mem(struct muram_info *p_muram, unsigned long addr,
+ uint32_t size)
+{
+ gen_pool_free(p_muram->pool, addr, size);
+}
+
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h
new file mode 100644
index 0000000..48c066a
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_muram_ext.h
@@ -0,0 +1,89 @@
+/*
+ * 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_muram_ext.h
+ * Description FM MURAM Application Programming Interface.
+ */
+#ifndef __FM_MURAM_EXT
+#define __FM_MURAM_EXT
+
+#include "linux/types.h"
+
+/* Structure for FM MURAM information */
+struct muram_info;
+
+/* FM MURAM initialization API functions, definitions and enums */
+
+/* Function fm_muram_init
+ * Description Creates partition in the MURAM.
+ * The routine returns a pointer to the MURAM partition.
+ * This pointer must be passed as first parameter to all other
+ * FM-MURAM function calls.
+ * No actual initialization or configuration of FM_MURAM hardware
+ * is done by this routine.
+ * Param[in] base - Pointer to base of memory mapped FM-MURAM.
+ * Param[in] size - Size of the FM-MURAM partition.
+ * Return pointer to FM-MURAM object, or NULL for Failure.
+ */
+struct muram_info *fm_muram_init(phys_addr_t base, uint64_t size);
+
+/* Function fm_muram_free
+ * Description Frees all resources that were assigned to FM-MURAM module.
+ * Calling this routine invalidates the pointer.
+ * Param[in] p_muram - FM-MURAM module pointer.
+ */
+void fm_muram_free(struct muram_info *p_muram);
+
+/* Function fm_muram_clear
+ * Description Set zeros to MURAM memory
+ * Param[in] p_muram - FM-MURAM module pointer.
+ */
+void fm_muram_clear(struct muram_info *p_muram);
+
+/* Function fm_muram_alloc
+ * Description Allocate some memory from FM-MURAM partition.
+ * Param[in] p_muram - FM-MURAM module pointer.
+ * Param[in] size - size of the memory to be allocated.
+ * Return address of the allocated memory; NULL otherwise.
+ */
+unsigned long fm_muram_alloc(struct muram_info *p_muram, uint32_t size);
+
+/* Function fm_muram_free_mem
+ * Description Free an allocated memory from FM-MURAM partition.
+ * Param[in] p_muram - FM-MURAM module pointer.
+ * Param[in] addr - address to be freed.
+ * Param[in] size - size of the memory to be freed.
+ */
+void fm_muram_free_mem(struct muram_info *p_muram, unsigned long addr,
+ uint32_t size);
+
+#endif /* __FM_MURAM_EXT */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 08/12] fsl/fman: Add Frame Manager support
2015-05-07 13:05 ` [RFC,v3 07/12] fsl/fman: Add FMan MURAM support Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 09/12] fsl/fman: Add FMan MAC support Madalin Bucur
0 siblings, 1 reply; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
Add Frame Manger Driver support.
This patch adds The FMan configuration, initialization and
runtime control routines.
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
drivers/net/ethernet/freescale/fman/Kconfig | 37 +
drivers/net/ethernet/freescale/fman/Makefile | 2 +-
drivers/net/ethernet/freescale/fman/fm.c | 1515 ++++++++++++++++++++
drivers/net/ethernet/freescale/fman/fm.h | 486 +++++++
drivers/net/ethernet/freescale/fman/fm_common.h | 331 +++++
drivers/net/ethernet/freescale/fman/fm_drv.c | 856 +++++++++++
drivers/net/ethernet/freescale/fman/fm_drv.h | 121 ++
drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h | 253 ++++
.../freescale/fman/inc/dpaa_integration_ext.h | 120 ++
drivers/net/ethernet/freescale/fman/inc/enet_ext.h | 199 +++
drivers/net/ethernet/freescale/fman/inc/fm_ext.h | 657 +++++++++
.../net/ethernet/freescale/fman/inc/fsl_fman_drv.h | 94 ++
drivers/net/ethernet/freescale/fman/inc/net_ext.h | 534 +++++++
drivers/net/ethernet/freescale/fman/inc/service.h | 90 ++
14 files changed, 5294 insertions(+), 1 deletion(-)
create mode 100644 drivers/net/ethernet/freescale/fman/fm.c
create mode 100644 drivers/net/ethernet/freescale/fman/fm.h
create mode 100644 drivers/net/ethernet/freescale/fman/fm_common.h
create mode 100644 drivers/net/ethernet/freescale/fman/fm_drv.c
create mode 100644 drivers/net/ethernet/freescale/fman/fm_drv.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/enet_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/net_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/service.h
diff --git a/drivers/net/ethernet/freescale/fman/Kconfig b/drivers/net/ethernet/freescale/fman/Kconfig
index 825a0d5..d7de35f 100644
--- a/drivers/net/ethernet/freescale/fman/Kconfig
+++ b/drivers/net/ethernet/freescale/fman/Kconfig
@@ -7,3 +7,40 @@ config FSL_FMAN
Freescale Data-Path Acceleration Architecture Frame Manager
(FMan) support
+if FSL_FMAN
+
+config FSL_FM_MAX_FRAME_SIZE
+ int "Maximum L2 frame size"
+ depends on FSL_FMAN
+ range 64 9600
+ default "1522"
+ help
+ Configure this in relation to the maximum possible MTU of your
+ network configuration. In particular, one would need to
+ increase this value in order to use jumbo frames.
+ FSL_FM_MAX_FRAME_SIZE must accommodate the Ethernet FCS
+ (4 bytes) and one ETH+VLAN header (18 bytes), to a total of
+ 22 bytes in excess of the desired L3 MTU.
+
+ Note that having too large a FSL_FM_MAX_FRAME_SIZE (much larger
+ than the actual MTU) may lead to buffer exhaustion, especially
+ in the case of badly fragmented datagrams on the Rx path.
+ Conversely, having a FSL_FM_MAX_FRAME_SIZE smaller than the
+ actual MTU will lead to frames being dropped.
+
+config FSL_FM_RX_EXTRA_HEADROOM
+ int "Add extra headroom at beginning of data buffers"
+ depends on FSL_FMAN
+ range 16 384
+ default "64"
+ help
+ Configure this to tell the Frame Manager to reserve some extra
+ space at the beginning of a data buffer on the receive path,
+ before Internal Context fields are copied. This is in addition
+ to the private data area already reserved for driver internal
+ use. The provided value must be a multiple of 16.
+
+ This option does not affect in any way the layout of
+ transmitted buffers.
+
+endif # FSL_FMAN
diff --git a/drivers/net/ethernet/freescale/fman/Makefile b/drivers/net/ethernet/freescale/fman/Makefile
index 55c91bd..f61d3a6 100644
--- a/drivers/net/ethernet/freescale/fman/Makefile
+++ b/drivers/net/ethernet/freescale/fman/Makefile
@@ -4,7 +4,7 @@ subdir-ccflags-y += -I$(srctree)/drivers/net/ethernet/freescale/fman/flib \
obj-y += fsl_fman.o
-fsl_fman-objs := fman.o fm_muram.o
+fsl_fman-objs := fman.o fm_muram.o fm.o fm_drv.o
obj-y += port/
obj-y += mac/
diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c
new file mode 100644
index 0000000..fbe4c16
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm.c
@@ -0,0 +1,1515 @@
+/*
+ * 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 driver routines implementation. */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+
+#include "fm_common.h"
+#include "fm.h"
+#include "fm_muram_ext.h"
+#include <asm/mpc85xx.h>
+#include "fsl_fman.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* static functions */
+
+static struct fm_intg_t *fill_intg_params(uint8_t major, uint8_t minor,
+ struct fm_params_t *p_fm_param)
+{
+ struct fm_intg_t *intg;
+
+ intg = kzalloc(sizeof(*intg), GFP_KERNEL);
+ if (!intg)
+ return NULL;
+
+ /* P1023 - Major 4
+ * P4080 - Major 2
+ * P2041/P3041/P5020/P5040 - Major 3
+ * Tx/Bx - Major 6
+ */
+
+ switch (major) {
+ case FM_IP_BLOCK_P2_P3_P5:
+ intg->fm_muram_size = 160 * 1024;
+ intg->fm_iram_size = 64 * 1024;
+ intg->fm_num_of_ctrl = 2;
+
+ intg->dma_thresh_max_commq = 31;
+ intg->dma_thresh_max_buf = 127;
+
+ intg->qmi_max_num_of_tnums = 64;
+ intg->qmi_def_tnums_thresh = 48;
+
+ intg->bmi_max_num_of_tasks = 128;
+ intg->bmi_max_num_of_dmas = 32;
+ intg->port_max_weight = 16;
+
+ intg->fm_port_num_of_cg = 256;
+
+ intg->num_of_rx_ports = 6;
+ break;
+
+ case FM_IP_BLOCK_P4:
+
+ intg->fm_muram_size = 160 * 1024;
+ intg->fm_iram_size = 64 * 1024;
+ intg->fm_num_of_ctrl = 2;
+
+ intg->dma_thresh_max_commq = 31;
+ intg->dma_thresh_max_buf = 127;
+
+ intg->qmi_max_num_of_tnums = 64;
+ intg->qmi_def_tnums_thresh = 48;
+
+ intg->bmi_max_num_of_tasks = 128;
+ intg->bmi_max_num_of_dmas = 32;
+ intg->port_max_weight = 16;
+
+ intg->fm_port_num_of_cg = 256;
+
+ intg->num_of_rx_ports = 5;
+ break;
+
+ case FM_IP_BLOCK_P1:
+
+ intg->fm_muram_size = 64 * 1024;
+ intg->fm_iram_size = 32 * 1024;
+ intg->fm_num_of_ctrl = 2;
+
+ intg->dma_thresh_max_commq = 15;
+ intg->dma_thresh_max_buf = 7;
+
+ intg->qmi_max_num_of_tnums = 15;
+
+ intg->bmi_max_num_of_tasks = 64;
+ intg->bmi_max_num_of_dmas = 16;
+ intg->port_max_weight = 4;
+
+ intg->fm_port_num_of_cg = 32;
+
+ intg->num_of_rx_ports = 2;
+ break;
+
+ case FM_IP_BLOCK_B_T:
+ intg->dma_thresh_max_commq = 83;
+ intg->dma_thresh_max_buf = 127;
+
+ intg->qmi_max_num_of_tnums = 64;
+ intg->qmi_def_tnums_thresh = 32;
+
+ intg->port_max_weight = 16;
+ intg->fm_port_num_of_cg = 256;
+
+ /* FManV3L */
+ if (minor == 1 || minor == 4) {
+ intg->fm_muram_size = 192 * 1024;
+ intg->fm_num_of_ctrl = 2;
+
+ intg->bmi_max_num_of_tasks = 64;
+ intg->bmi_max_num_of_dmas = 32;
+
+ intg->num_of_rx_ports = 5;
+
+ if (minor == 1)
+ intg->fm_iram_size = 32 * 1024;
+ else
+ intg->fm_iram_size = 64 * 1024;
+ }
+ /* FManV3H */
+ else if (minor == 0 || minor == 2 || minor == 3) {
+ intg->fm_muram_size = 384 * 1024;
+ intg->fm_iram_size = 64 * 1024;
+ intg->fm_num_of_ctrl = 4;
+
+ intg->bmi_max_num_of_tasks = 128;
+ intg->bmi_max_num_of_dmas = 84;
+
+ intg->num_of_rx_ports = 8;
+ } else {
+ pr_err("Unsupported FManv3 version\n");
+ kfree(intg);
+ return NULL;
+ }
+
+ break;
+ default:
+ pr_err("Unsupported FMan version\n");
+ kfree(intg);
+ return NULL;
+ }
+
+ intg->bmi_max_fifo_size = intg->fm_muram_size;
+
+ return intg;
+}
+
+/* Checks if p_fm driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct fman_cfg *p_fm_drv_parameters)
+{
+ if (!p_fm_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+static void free_init_resources(struct fm_t *p_fm)
+{
+ if (p_fm->cam_base_addr)
+ fm_muram_free_mem(p_fm->p_muram, p_fm->cam_base_addr,
+ p_fm->cam_size);
+ if (p_fm->fifo_base_addr)
+ fm_muram_free_mem(p_fm->p_muram, p_fm->fifo_base_addr,
+ p_fm->fifo_size);
+}
+
+static bool is_fman_ctrl_code_loaded(struct fm_t *p_fm)
+{
+ struct fm_iram_regs_t __iomem *p_iram;
+
+ p_iram = (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+ FM_MM_IMEM);
+
+ return (bool)!!(GET_UINT32(p_iram->iready) & IRAM_READY);
+}
+
+static int check_fm_parameters(struct fm_t *p_fm)
+{
+ if (is_fman_ctrl_code_loaded(p_fm) && !p_fm->reset_on_init) {
+ pr_err("Old FMan CTRL code is loaded; FM must be reset!\n");
+ return -EDOM;
+ }
+ if (p_fm->p_fm_state_struct->rev_info.major_rev < 6) {
+ if (!p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats ||
+ (p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats >
+ DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS)) {
+ pr_err("axiDbgNumOfBeats has to be in the range 1 - %d\n",
+ DMA_MODE_MAX_AXI_DBG_NUM_OF_BEATS);
+ return -EDOM;
+ }
+ }
+ if (p_fm->p_fm_drv_param->dma_cam_num_of_entries %
+ DMA_CAM_UNITS) {
+ pr_err("dma_cam_num_of_entries has to be divisble by %d\n",
+ DMA_CAM_UNITS);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_comm_qtsh_asrt_emer >
+ p_fm->intg->dma_thresh_max_commq) {
+ pr_err("dma_comm_qtsh_asrt_emer can not be larger than %d\n",
+ p_fm->intg->dma_thresh_max_commq);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_comm_qtsh_clr_emer >
+ p_fm->intg->dma_thresh_max_commq) {
+ pr_err("dma_comm_qtsh_clr_emer can not be larger than %d\n",
+ p_fm->intg->dma_thresh_max_commq);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_comm_qtsh_clr_emer >=
+ p_fm->p_fm_drv_param->dma_comm_qtsh_asrt_emer) {
+ pr_err("dma_comm_qtsh_clr_emer must be smaller than dma_comm_qtsh_asrt_emer\n");
+ return -EDOM;
+ }
+ if (p_fm->p_fm_state_struct->rev_info.major_rev < 6) {
+ if (p_fm->p_fm_drv_param->dma_read_buf_tsh_asrt_emer >
+ p_fm->intg->dma_thresh_max_buf) {
+ pr_err("dma_read_buf_tsh_asrt_emer can not be larger than %d\n",
+ p_fm->intg->dma_thresh_max_buf);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_read_buf_tsh_clr_emer >
+ p_fm->intg->dma_thresh_max_buf) {
+ pr_err("dma_read_buf_tsh_clr_emer can not be larger than %d\n",
+ p_fm->intg->dma_thresh_max_buf);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_read_buf_tsh_clr_emer >=
+ p_fm->p_fm_drv_param->dma_read_buf_tsh_asrt_emer) {
+ pr_err("dma_read_buf_tsh_clr_emer must be < dma_read_buf_tsh_asrt_emer\n");
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_write_buf_tsh_asrt_emer >
+ p_fm->intg->dma_thresh_max_buf) {
+ pr_err("dma_write_buf_tsh_asrt_emer can not be larger than %d\n",
+ p_fm->intg->dma_thresh_max_buf);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_write_buf_tsh_clr_emer >
+ p_fm->intg->dma_thresh_max_buf) {
+ pr_err("dma_write_buf_tsh_clr_emer can not be larger than %d\n",
+ p_fm->intg->dma_thresh_max_buf);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_write_buf_tsh_clr_emer >=
+ p_fm->p_fm_drv_param->dma_write_buf_tsh_asrt_emer) {
+ pr_err("dma_write_buf_tsh_clr_emer has to be less than dma_write_buf_tsh_asrt_emer\n");
+ return -EDOM;
+ }
+ } else {
+ if ((p_fm->p_fm_drv_param->dma_dbg_cnt_mode ==
+ E_FMAN_DMA_DBG_CNT_INT_READ_EM) ||
+ (p_fm->p_fm_drv_param->dma_dbg_cnt_mode ==
+ E_FMAN_DMA_DBG_CNT_INT_WRITE_EM) ||
+ (p_fm->p_fm_drv_param->dma_dbg_cnt_mode ==
+ E_FMAN_DMA_DBG_CNT_RAW_WAR_PROT)) {
+ pr_err("dma_dbg_cnt_mode value not supported by this integration.\n");
+ return -EDOM;
+ }
+ if ((p_fm->p_fm_drv_param->dma_emergency_bus_select ==
+ FM_DMA_MURAM_READ_EMERGENCY) ||
+ (p_fm->p_fm_drv_param->dma_emergency_bus_select ==
+ FM_DMA_MURAM_WRITE_EMERGENCY)) {
+ pr_err("emergencyBusSelect value not supported by this integration.\n");
+ return -EDOM;
+ }
+ if (p_fm->p_fm_drv_param->dma_stop_on_bus_error) {
+ pr_err("dma_stop_on_bus_error not supported by this integration.\n");
+ return -EDOM;
+ }
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+ if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6 &&
+ p_fm->p_fm_drv_param->dma_aid_mode !=
+ E_FMAN_DMA_AID_OUT_PORT_ID) {
+ pr_err("dma_aid_mode not supported by this integration.\n");
+ return -EDOM;
+ }
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+ if (p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats) {
+ pr_err("dma_axi_dbg_num_of_beats not supported by this integration.\n");
+ return -EDOM;
+ }
+ }
+
+ if (!p_fm->p_fm_state_struct->fm_clk_freq) {
+ pr_err("fm_clk_freq must be set.\n");
+ return -EDOM;
+ }
+ if (USEC_TO_CLK
+ (p_fm->p_fm_drv_param->dma_watchdog,
+ p_fm->p_fm_state_struct->fm_clk_freq) > DMA_MAX_WATCHDOG) {
+ pr_err("dma_watchdog depends on FM clock. dma_watchdog(in microseconds)*clk (in Mhz), may not exceed 0x08%x\n",
+ DMA_MAX_WATCHDOG);
+ return -EDOM;
+ }
+ if (p_fm->p_fm_state_struct->total_fifo_size % BMI_FIFO_UNITS) {
+ pr_err("total_fifo_size number has to be divisible by %d\n",
+ BMI_FIFO_UNITS);
+ }
+ if (!p_fm->p_fm_state_struct->total_fifo_size ||
+ (p_fm->p_fm_state_struct->total_fifo_size >
+ p_fm->intg->bmi_max_fifo_size)) {
+ pr_err("total_fifo_size (curr - %d) has to be in the range 256 - %d\n",
+ p_fm->p_fm_state_struct->total_fifo_size,
+ p_fm->intg->bmi_max_fifo_size);
+ return -EDOM;
+ }
+ if (!p_fm->p_fm_state_struct->total_num_of_tasks ||
+ (p_fm->p_fm_state_struct->total_num_of_tasks >
+ p_fm->intg->bmi_max_num_of_tasks)) {
+ pr_err("total_num_of_tasks number has to be in the range 1 - %d\n",
+ p_fm->intg->bmi_max_num_of_tasks);
+ return -EDOM;
+ }
+
+#ifdef FM_HAS_TOTAL_DMAS
+ if ((p_fm->p_fm_state_struct->rev_info.major_rev < 6) &&
+ (!p_fm->p_fm_state_struct->max_num_of_open_dmas ||
+ (p_fm->p_fm_state_struct->max_num_of_open_dmas >
+ p_fm->intg->bmi_max_num_of_dmas))) {
+ pr_err("max_num_of_open_dmas number has to be in the range 1 - %d\n",
+ p_fm->intg->bmi_max_num_of_dmas);
+ return -EDOM;
+ }
+#endif /* FM_HAS_TOTAL_DMAS */
+
+ if (p_fm->p_fm_drv_param->disp_limit_tsh > FPM_MAX_DISP_LIMIT) {
+ pr_err("disp_limit_tsh can't be greater than %d\n",
+ FPM_MAX_DISP_LIMIT);
+ return -EDOM;
+ }
+ if (!p_fm->f_exception) {
+ pr_err("Exceptions callback not provided\n");
+ return -EDOM;
+ }
+ if (!p_fm->f_bus_error) {
+ pr_err("Exceptions callback not provided\n");
+ return -EDOM;
+ }
+#ifdef FM_NO_WATCHDOG
+ if ((p_fm->p_fm_state_struct->rev_info.major_rev == 2) &&
+ (p_fm->p_fm_drv_param->dma_watchdog)) {
+ pr_err("watchdog!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_NO_WATCHDOG */
+
+#ifdef FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008
+ if ((p_fm->p_fm_state_struct->rev_info.major_rev < 6) &&
+ (p_fm->p_fm_state_struct->rev_info.major_rev != 4) &&
+ (p_fm->p_fm_drv_param->halt_on_unrecov_ecc_err)) {
+ pr_err("HaltOnEccError!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 */
+
+#ifdef FM_NO_TNUM_AGING
+ if ((p_fm->p_fm_state_struct->rev_info.major_rev != 4) &&
+ (p_fm->p_fm_state_struct->rev_info.major_rev < 6))
+ if (p_fm->p_fm_drv_param->tnum_aging_period) {
+ pr_err("Tnum aging!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_NO_TNUM_AGING */
+
+ /* check that user did not set revision-dependent exceptions */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+ if ((p_fm->p_fm_state_struct->rev_info.major_rev != 4) &&
+ (p_fm->p_fm_state_struct->rev_info.major_rev < 6))
+ if (p_fm->user_set_exceptions & FM_EX_BMI_DISPATCH_RAM_ECC) {
+ pr_err("exception FM_EX_BMI_DISPATCH_RAM_ECC!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+ if (p_fm->p_fm_state_struct->rev_info.major_rev == 4)
+ if (p_fm->user_set_exceptions &
+ (FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC)) {
+ pr_err("exception FM_EX_QMI_SINGLE_ECC/FM_EX_QMI_DOUBLE_ECC!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+ if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6)
+ if (p_fm->user_set_exceptions & FM_EX_QMI_SINGLE_ECC) {
+ pr_err("exception FM_EX_QMI_SINGLE_ECC!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+ return 0;
+}
+
+static void bmi_err_event(struct fm_t *p_fm)
+{
+ uint32_t event;
+ struct fman_bmi_regs __iomem *bmi_rg = p_fm->p_fm_bmi_regs;
+
+ event = fman_get_bmi_err_event(bmi_rg);
+
+ if (event & BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_BMI_STORAGE_PROFILE_ECC);
+ if (event & BMI_ERR_INTR_EN_LIST_RAM_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_BMI_LIST_RAM_ECC);
+ if (event & BMI_ERR_INTR_EN_STATISTICS_RAM_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_BMI_STATISTICS_RAM_ECC);
+ if (event & BMI_ERR_INTR_EN_DISPATCH_RAM_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_BMI_DISPATCH_RAM_ECC);
+}
+
+static void qmi_err_event(struct fm_t *p_fm)
+{
+ uint32_t event;
+ struct fman_qmi_regs __iomem *qmi_rg = p_fm->p_fm_qmi_regs;
+
+ event = fman_get_qmi_err_event(qmi_rg);
+
+ if (event & QMI_ERR_INTR_EN_DOUBLE_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_QMI_DOUBLE_ECC);
+ if (event & QMI_ERR_INTR_EN_DEQ_FROM_DEF)
+ p_fm->f_exception(p_fm->h_app,
+ FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID);
+}
+
+static void dma_err_event(struct fm_t *p_fm)
+{
+ uint32_t status;
+ struct fman_dma_regs __iomem *dma_rg = p_fm->p_fm_dma_regs;
+
+ status = fman_get_dma_err_event(dma_rg);
+
+ if (status & DMA_STATUS_FM_SPDAT_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_DMA_SINGLE_PORT_ECC);
+ if (status & DMA_STATUS_READ_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_DMA_READ_ECC);
+ if (status & DMA_STATUS_SYSTEM_WRITE_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_DMA_SYSTEM_WRITE_ECC);
+ if (status & DMA_STATUS_FM_WRITE_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_DMA_FM_WRITE_ECC);
+}
+
+static void fpm_err_event(struct fm_t *p_fm)
+{
+ uint32_t event;
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ event = fman_get_fpm_err_event(fpm_rg);
+
+ if ((event & FPM_EV_MASK_DOUBLE_ECC) &&
+ (event & FPM_EV_MASK_DOUBLE_ECC_EN))
+ p_fm->f_exception(p_fm->h_app, FM_EX_FPM_DOUBLE_ECC);
+ if ((event & FPM_EV_MASK_STALL) && (event & FPM_EV_MASK_STALL_EN))
+ p_fm->f_exception(p_fm->h_app, FM_EX_FPM_STALL_ON_TASKS);
+ if ((event & FPM_EV_MASK_SINGLE_ECC) &&
+ (event & FPM_EV_MASK_SINGLE_ECC_EN))
+ p_fm->f_exception(p_fm->h_app, FM_EX_FPM_SINGLE_ECC);
+}
+
+static void muram_err_intr(struct fm_t *p_fm)
+{
+ uint32_t event;
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ event = fman_get_muram_err_event(fpm_rg);
+
+ if (event & FPM_RAM_MURAM_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_MURAM_ECC);
+}
+
+static void iram_err_intr(struct fm_t *p_fm)
+{
+ uint32_t event;
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ event = fman_get_iram_err_event(fpm_rg);
+
+ if (event & FPM_RAM_IRAM_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_IRAM_ECC);
+}
+
+static void qmi_event(struct fm_t *p_fm)
+{
+ uint32_t event;
+ struct fman_qmi_regs __iomem *qmi_rg = p_fm->p_fm_qmi_regs;
+
+ event = fman_get_qmi_event(qmi_rg);
+
+ if (event & QMI_INTR_EN_SINGLE_ECC)
+ p_fm->f_exception(p_fm->h_app, FM_EX_QMI_SINGLE_ECC);
+}
+
+static void unimplemented_isr(void __maybe_unused *h_src_arg)
+{
+ pr_err("Unimplemented ISR!\n");
+}
+
+static void enable_time_stamp(struct fm_t *p_fm)
+{
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ ASSERT(p_fm->p_fm_state_struct);
+ ASSERT(p_fm->p_fm_state_struct->count1_micro_bit);
+
+ fman_enable_time_stamp(fpm_rg,
+ p_fm->p_fm_state_struct->count1_micro_bit,
+ p_fm->p_fm_state_struct->fm_clk_freq);
+
+ p_fm->p_fm_state_struct->enabled_time_stamp = true;
+}
+
+static int clear_iram(struct fm_t *p_fm)
+{
+ struct fm_iram_regs_t __iomem *p_iram;
+ int i;
+
+ p_iram = (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+ FM_MM_IMEM);
+
+ /* Enable the auto-increment */
+ WRITE_UINT32(p_iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_iram->iadd) != IRAM_IADD_AIE)
+ ;
+
+ for (i = 0; i < (p_fm->intg->fm_iram_size / 4); i++)
+ WRITE_UINT32(p_iram->idata, 0xffffffff);
+
+ WRITE_UINT32(p_iram->iadd, p_fm->intg->fm_iram_size - 4);
+ /* Memory barrier */
+ mb();
+ while (GET_UINT32(p_iram->idata) != 0xffffffff)
+ ;
+
+ return 0;
+}
+
+static int load_fman_ctrl_code(struct fm_t *p_fm)
+{
+ struct fm_iram_regs_t __iomem *p_iram;
+ int i;
+ uint32_t tmp;
+ uint8_t comp_to_16;
+
+ p_iram = (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+ FM_MM_IMEM);
+
+ /* Enable the auto-increment */
+ WRITE_UINT32(p_iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_iram->iadd) != IRAM_IADD_AIE)
+ ;
+
+ for (i = 0; i < (p_fm->firmware.size / 4); i++)
+ WRITE_UINT32(p_iram->idata, p_fm->firmware.p_code[i]);
+
+ comp_to_16 = (uint8_t)(p_fm->firmware.size % 16);
+ if (comp_to_16)
+ for (i = 0; i < ((16 - comp_to_16) / 4); i++)
+ WRITE_UINT32(p_iram->idata, 0xffffffff);
+
+ WRITE_UINT32(p_iram->iadd, p_fm->firmware.size - 4);
+ while (GET_UINT32(p_iram->iadd) != (p_fm->firmware.size - 4))
+ ;
+
+ /* verify that writing has completed */
+ while (GET_UINT32(p_iram->idata) !=
+ p_fm->firmware.p_code[(p_fm->firmware.size / 4) - 1])
+ ;
+
+ if (p_fm->fw_verify) {
+ WRITE_UINT32(p_iram->iadd, IRAM_IADD_AIE);
+ while (GET_UINT32(p_iram->iadd) != IRAM_IADD_AIE)
+ ;
+ for (i = 0; i < (p_fm->firmware.size / 4); i++) {
+ tmp = GET_UINT32(p_iram->idata);
+ if (tmp != p_fm->firmware.p_code[i]) {
+ pr_err("UCode write error : write 0x%x, read 0x%x\n",
+ p_fm->firmware.p_code[i], tmp);
+ return -EIO;
+ }
+ }
+ WRITE_UINT32(p_iram->iadd, 0x0);
+ }
+
+ /* Enable patch from IRAM */
+ WRITE_UINT32(p_iram->iready, IRAM_READY);
+ usleep_range(1000, 1001);
+
+ pr_debug("FMan-Controller code (ver %d.%d.%d) loaded to IRAM.\n",
+ ((uint16_t *)p_fm->firmware.p_code)[2],
+ ((uint8_t *)p_fm->firmware.p_code)[6],
+ ((uint8_t *)p_fm->firmware.p_code)[7]);
+
+ return 0;
+}
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+static int fw_not_reset_erratum_bugzilla6173wa(struct fm_t *p_fm)
+{
+ struct fm_iram_regs_t __iomem *p_iram =
+ (struct fm_iram_regs_t __iomem *)UINT_TO_PTR(p_fm->base_addr +
+ FM_MM_IMEM);
+ uint32_t tmp_reg;
+ uint32_t saved_spliodn[63];
+
+ /* write to IRAM first location the debug instruction */
+ WRITE_UINT32(p_iram->iadd, 0);
+ while (GET_UINT32(p_iram->iadd) != 0)
+ ;
+
+ WRITE_UINT32(p_iram->idata, FM_FW_DEBUG_INSTRUCTION);
+
+ WRITE_UINT32(p_iram->iadd, 0);
+ while (GET_UINT32(p_iram->iadd) != 0)
+ ;
+ while (GET_UINT32(p_iram->idata) != FM_FW_DEBUG_INSTRUCTION)
+ ;
+
+ /* Enable patch from IRAM */
+ WRITE_UINT32(p_iram->iready, IRAM_READY);
+ /* Memory barrier */
+ mb();
+ usleep_range(100, 101);
+
+ memcpy_fromio((void *)saved_spliodn,
+ (void __iomem *)p_fm->p_fm_bmi_regs->fmbm_spliodn,
+ 63 * sizeof(uint32_t));
+
+ /* reset FMAN */
+ WRITE_UINT32(p_fm->p_fm_fpm_regs->fm_rstc, FPM_RSTC_FM_RESET);
+ /* Memory barrier */
+ mb();
+ usleep_range(100, 101);
+
+ /* verify breakpoint debug status register */
+ tmp_reg =
+ GET_UINT32(*(uint32_t __iomem *)
+ UINT_TO_PTR(p_fm->base_addr +
+ FM_DEBUG_STATUS_REGISTER_OFFSET));
+ if (!tmp_reg) {
+ pr_err("Invalid debug status register value is '0'\n");
+ return -ENOSYS;
+ }
+
+ /* Load FMan-Controller code to IRAM */
+
+ if (clear_iram(p_fm) != 0)
+ return -ENOSYS;
+ if (p_fm->firmware.p_code && (load_fman_ctrl_code(p_fm) != 0))
+ return -ENOSYS;
+ usleep_range(100, 101);
+
+ /* reset FMAN again to start the microcode */
+ WRITE_UINT32(p_fm->p_fm_fpm_regs->fm_rstc, FPM_RSTC_FM_RESET);
+ /* Memory barrier */
+ mb();
+ usleep_range(100, 101);
+ memcpy_toio((void __iomem *)p_fm->p_fm_bmi_regs->fmbm_spliodn,
+ (void *)saved_spliodn, 63 * sizeof(uint32_t));
+
+ if (fman_is_qmi_halt_not_busy_state(p_fm->p_fm_qmi_regs)) {
+ fman_resume(p_fm->p_fm_fpm_regs);
+ /* Memory barrier */
+ mb();
+ usleep_range(100, 101);
+ }
+
+ return 0;
+}
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+/* Inter-Module functions */
+
+void fm_register_intr(void *h_fm, enum fm_event_modules module,
+ uint8_t mod_id, enum fm_intr_type intr_type,
+ void (*f_isr)(void *h_src_arg), void *h_src_arg)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ int event = 0;
+
+ GET_FM_MODULE_EVENT(p_fm, module, mod_id, intr_type, event);
+ ASSERT(event < FM_EV_DUMMY_LAST);
+
+ /* register in local FM structure */
+ p_fm->intr_mng[event].f_isr = f_isr;
+ p_fm->intr_mng[event].h_src_handle = h_src_arg;
+}
+
+void fm_unregister_intr(void *h_fm, enum fm_event_modules module,
+ uint8_t mod_id, enum fm_intr_type intr_type)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ int event = 0;
+
+ GET_FM_MODULE_EVENT(p_fm, module, mod_id, intr_type, event);
+ ASSERT(event < FM_EV_DUMMY_LAST);
+
+ p_fm->intr_mng[event].f_isr = unimplemented_isr;
+ p_fm->intr_mng[event].h_src_handle = NULL;
+}
+
+uint8_t fm_get_id(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ return p_fm->p_fm_state_struct->fm_id;
+}
+
+uint16_t fm_get_clock_freq(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ /* for multicore environment: this depends on the
+ * fact that fm_clk_freq was properly initialized at "init".
+ */
+ return p_fm->p_fm_state_struct->fm_clk_freq;
+}
+
+uint32_t fm_get_bmi_max_fifo_size(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ return p_fm->intg->bmi_max_fifo_size;
+}
+
+static int init_fm_dma(struct fm_t *p_fm)
+{
+ int err;
+
+ err = (int)fman_dma_init(p_fm->p_fm_dma_regs,
+ p_fm->p_fm_drv_param);
+ if (err != 0)
+ return err;
+
+ /* Allocate MURAM for CAM */
+ p_fm->cam_size = (uint32_t)(p_fm->p_fm_drv_param->
+ dma_cam_num_of_entries *
+ DMA_CAM_SIZEOF_ENTRY);
+ p_fm->cam_base_addr = fm_muram_alloc(p_fm->p_muram, p_fm->cam_size);
+ if (!p_fm->cam_base_addr) {
+ pr_err("MURAM alloc for DMA CAM failed\n");
+ return -ENOMEM;
+ }
+
+ memset_io(UINT_TO_PTR(p_fm->cam_base_addr),
+ 0,
+ (uint32_t)(p_fm->p_fm_drv_param->dma_cam_num_of_entries *
+ DMA_CAM_SIZEOF_ENTRY));
+
+ if (p_fm->p_fm_state_struct->rev_info.major_rev == 2) {
+ fm_muram_free_mem(p_fm->p_muram, p_fm->cam_base_addr,
+ p_fm->cam_size);
+
+ p_fm->cam_size = p_fm->p_fm_drv_param->
+ dma_cam_num_of_entries * 72 + 128;
+ p_fm->cam_base_addr = fm_muram_alloc(p_fm->p_muram, (uint32_t)
+ p_fm->cam_size);
+ if (!p_fm->cam_base_addr) {
+ pr_err("MURAM alloc for DMA CAM failed\n");
+ return -ENOMEM;
+ }
+
+ memset_io(UINT_TO_PTR(p_fm->cam_base_addr),
+ 0,
+ (uint32_t)(p_fm->p_fm_drv_param->
+ dma_cam_num_of_entries * 72 + 128));
+
+ switch (p_fm->p_fm_drv_param->dma_cam_num_of_entries) {
+ case (8):
+ WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+ 0xff000000);
+ break;
+ case (16):
+ WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+ 0xffff0000);
+ break;
+ case (24):
+ WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+ 0xffffff00);
+ break;
+ case (32):
+ WRITE_UINT32(*(uint32_t __iomem *)p_fm->cam_base_addr,
+ 0xffffffff);
+ break;
+ default:
+ pr_err("wrong dma_cam_num_of_entries\n");
+ return -EDOM;
+ }
+ }
+
+ p_fm->p_fm_drv_param->cam_base_addr =
+ (uint32_t)(virt_to_phys(UINT_TO_PTR(p_fm->cam_base_addr)) -
+ p_fm->fm_muram_phys_base_addr);
+
+ return 0;
+}
+
+static int init_fm_fpm(struct fm_t *p_fm)
+{
+ return (int)fman_fpm_init(p_fm->p_fm_fpm_regs,
+ p_fm->p_fm_drv_param);
+}
+
+static int init_fm_bmi(struct fm_t *p_fm)
+{
+ return (int)fman_bmi_init(p_fm->p_fm_bmi_regs,
+ p_fm->p_fm_drv_param);
+}
+
+static int init_fm_qmi(struct fm_t *p_fm)
+{
+ return (int)fman_qmi_init(p_fm->p_fm_qmi_regs,
+ p_fm->p_fm_drv_param);
+}
+
+/* API Init unit functions */
+
+void *fm_config(struct fm_params_t *p_fm_param)
+{
+ struct fm_t *p_fm;
+ uintptr_t base_addr;
+
+ if (!((p_fm_param->firmware.p_code && p_fm_param->firmware.size) ||
+ (!p_fm_param->firmware.p_code && !p_fm_param->firmware.size)))
+ return NULL;
+
+ base_addr = p_fm_param->base_addr;
+
+ /* Allocate FM structure */
+ p_fm = kzalloc(sizeof(*p_fm), GFP_KERNEL);
+ if (!p_fm)
+ return NULL;
+
+ p_fm->p_fm_state_struct = kzalloc(sizeof(*p_fm->p_fm_state_struct),
+ GFP_KERNEL);
+ if (!p_fm->p_fm_state_struct) {
+ kfree(p_fm);
+ pr_err("FM Status structure\n");
+ return NULL;
+ }
+
+ /* Initialize FM parameters which will be kept by the driver */
+ p_fm->p_fm_state_struct->fm_id = p_fm_param->fm_id;
+
+ /* Allocate the FM driver's parameters structure */
+ p_fm->p_fm_drv_param = kzalloc(sizeof(*p_fm->p_fm_drv_param),
+ GFP_KERNEL);
+ if (!p_fm->p_fm_drv_param) {
+ kfree(p_fm->p_fm_state_struct);
+ kfree(p_fm);
+ pr_err("FM driver parameters\n");
+ return NULL;
+ }
+
+ /* Initialize FM parameters which will be kept by the driver */
+ p_fm->p_fm_state_struct->fm_id = p_fm_param->fm_id;
+ p_fm->p_muram = p_fm_param->p_muram;
+ p_fm->h_app = p_fm_param->h_app;
+ p_fm->p_fm_state_struct->fm_clk_freq = p_fm_param->fm_clk_freq;
+ p_fm->f_exception = p_fm_param->f_exception;
+ p_fm->f_bus_error = p_fm_param->f_bus_error;
+ p_fm->p_fm_fpm_regs =
+ (struct fman_fpm_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_FPM);
+ p_fm->p_fm_bmi_regs =
+ (struct fman_bmi_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_BMI);
+ p_fm->p_fm_qmi_regs =
+ (struct fman_qmi_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_QMI);
+ p_fm->p_fm_dma_regs =
+ (struct fman_dma_regs __iomem *)UINT_TO_PTR(base_addr + FM_MM_DMA);
+ p_fm->p_fm_regs = (struct fman_regs __iomem *)
+ UINT_TO_PTR(base_addr + FM_MM_BMI);
+ p_fm->base_addr = base_addr;
+
+ p_fm->spinlock = kmalloc(sizeof(spinlock_t), GFP_KERNEL);
+ if (!p_fm->spinlock) {
+ kfree(p_fm->p_fm_drv_param);
+ kfree(p_fm->p_fm_state_struct);
+ kfree(p_fm);
+ pr_err("can't allocate spinlock!\n");
+ return NULL;
+ }
+
+ spin_lock_init(p_fm->spinlock);
+ fman_defconfig(p_fm->p_fm_drv_param);
+
+/* overide macros dependent parameters */
+#ifdef FM_PEDANTIC_DMA
+ if (p_fm->p_fm_state_struct->rev_info.major_rev == 4) {
+ p_fm->p_fm_drv_param->pedantic_dma = true;
+ p_fm->p_fm_drv_param->dma_aid_override = true;
+ }
+#endif /* FM_PEDANTIC_DMA */
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_fm->p_fm_state_struct->rev_info.major_rev != 4)
+ p_fm->p_fm_drv_param->qmi_deq_option_support = true;
+#endif /* !FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ p_fm->p_fm_state_struct->rams_ecc_enable = false;
+ p_fm->p_fm_state_struct->extra_fifo_pool_size = 0;
+ p_fm->p_fm_state_struct->exceptions = DEFAULT_exceptions;
+ p_fm->reset_on_init = DEFAULT_RESET_ON_INIT;
+ p_fm->fw_verify = DEFAULT_VERIFY_UCODE;
+ p_fm->firmware.size = p_fm_param->firmware.size;
+ if (p_fm->firmware.size) {
+ p_fm->firmware.p_code = kmalloc(p_fm->firmware.size,
+ GFP_KERNEL);
+ if (!p_fm->firmware.p_code) {
+ kfree(p_fm->spinlock);
+ kfree(p_fm->p_fm_state_struct);
+ kfree(p_fm->p_fm_drv_param);
+ kfree(p_fm);
+ pr_err("FM firmware code\n");
+ return NULL;
+ }
+ memcpy(p_fm->firmware.p_code,
+ p_fm_param->firmware.p_code, p_fm->firmware.size);
+ }
+ /* read revision */
+ /* Chip dependent, will be configured in Init */
+ fman_get_revision(p_fm->p_fm_fpm_regs,
+ &p_fm->p_fm_state_struct->rev_info.major_rev,
+ &p_fm->p_fm_state_struct->rev_info.minor_rev);
+
+ p_fm->intg =
+ fill_intg_params(p_fm->p_fm_state_struct->rev_info.major_rev,
+ p_fm->p_fm_state_struct->rev_info.minor_rev,
+ p_fm_param);
+ if (!p_fm->intg) {
+ kfree(p_fm->firmware.p_code);
+ kfree(p_fm->spinlock);
+ kfree(p_fm->p_fm_state_struct);
+ kfree(p_fm->p_fm_drv_param);
+ kfree(p_fm);
+ return NULL;
+ }
+
+#ifdef FM_AID_MODE_NO_TNUM_SW005
+ if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6)
+ p_fm->p_fm_drv_param->dma_aid_mode = FM_DMA_AID_OUT_PORT_ID;
+#endif /* FM_AID_MODE_NO_TNUM_SW005 */
+#ifdef FM_QMI_NO_DEQ_OPTIONS_SUPPORT
+ if (p_fm->p_fm_state_struct->rev_info.major_rev != 4)
+ p_fm->p_fm_drv_param->qmi_def_tnums_thresh =
+ p_fm->intg->qmi_def_tnums_thresh;
+#endif /* FM_QMI_NO_DEQ_OPTIONS_SUPPORT */
+
+ p_fm->p_fm_state_struct->total_fifo_size = 0;
+ p_fm->p_fm_state_struct->total_num_of_tasks =
+ (u8)DFLT_TOTAL_NUM_OF_TASKS(
+ p_fm->p_fm_state_struct->rev_info.major_rev,
+ p_fm->p_fm_state_struct->rev_info.minor_rev,
+ p_fm->intg->bmi_max_num_of_tasks);
+#ifdef FM_HAS_TOTAL_DMAS
+ if (p_fm->p_fm_state_struct->rev_info.major_rev < 6)
+ p_fm->p_fm_state_struct->max_num_of_open_dmas =
+ p_fm->intg->bmi_max_num_of_dmas;
+#endif /* FM_HAS_TOTAL_DMAS */
+ if (p_fm->p_fm_state_struct->rev_info.major_rev < 6) {
+ p_fm->p_fm_drv_param->dma_comm_qtsh_clr_emer =
+ (u8)DFLT_DMA_COMM_Q_LOW(p_fm->p_fm_state_struct->rev_info.
+ major_rev,
+ p_fm->intg->dma_thresh_max_commq);
+
+ p_fm->p_fm_drv_param->dma_comm_qtsh_asrt_emer =
+ (u8)DFLT_DMA_COMM_Q_HIGH(p_fm->p_fm_state_struct->rev_info.
+ major_rev,
+ p_fm->intg->dma_thresh_max_commq);
+
+ p_fm->p_fm_drv_param->dma_cam_num_of_entries =
+ DFLT_DMA_CAM_NUM_OF_ENTRIES(p_fm->p_fm_state_struct->
+ rev_info.major_rev);
+ p_fm->p_fm_drv_param->dma_read_buf_tsh_clr_emer =
+ (u8)DFLT_DMA_READ_INT_BUF_LOW(p_fm->intg->dma_thresh_max_buf);
+
+ p_fm->p_fm_drv_param->dma_read_buf_tsh_asrt_emer =
+ (u8)DFLT_DMA_READ_INT_BUF_HIGH(p_fm->intg->dma_thresh_max_buf);
+
+ p_fm->p_fm_drv_param->dma_write_buf_tsh_clr_emer =
+ (u8)DFLT_DMA_WRITE_INT_BUF_LOW(p_fm->intg->dma_thresh_max_buf);
+
+ p_fm->p_fm_drv_param->dma_write_buf_tsh_asrt_emer =
+ (u8)DFLT_DMA_WRITE_INT_BUF_HIGH(p_fm->intg->dma_thresh_max_buf);
+
+ p_fm->p_fm_drv_param->dma_axi_dbg_num_of_beats =
+ DEFAULT_AXI_DBG_NUM_OF_BEATS;
+ }
+
+#ifdef FM_NO_TNUM_AGING
+ p_fm->p_fm_drv_param->tnum_aging_period = 0;
+#endif /* FM_NO_TNUM_AGING */
+ p_fm->tnum_aging_period = p_fm->p_fm_drv_param->tnum_aging_period;
+
+ return p_fm;
+}
+
+/* fm_init
+ *
+ * Initializes the FM module
+ *
+ * @Param[in] h_fm - FM module descriptor
+ *
+ * @Return 0 on success; Error code otherwise.
+ */
+int fm_init(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ struct fman_cfg *p_fm_drv_param = NULL;
+ int err = 0;
+ int i;
+ struct fm_revision_info_t rev_info;
+ struct fman_rg fman_rg;
+ int ret, ret_err;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ fman_rg.bmi_rg = p_fm->p_fm_bmi_regs;
+ fman_rg.qmi_rg = p_fm->p_fm_qmi_regs;
+ fman_rg.fpm_rg = p_fm->p_fm_fpm_regs;
+ fman_rg.dma_rg = p_fm->p_fm_dma_regs;
+
+ p_fm->p_fm_state_struct->count1_micro_bit = FM_TIMESTAMP_1_USEC_BIT;
+ p_fm->p_fm_drv_param->num_of_fman_ctrl_evnt_regs =
+ FM_NUM_OF_FMAN_CTRL_EVENT_REGS;
+
+ /* if user didn't configured total_fifo_size -
+ * (total_fifo_size=0) we configure default
+ * according to chip. otherwise, we use user's configuration.
+ */
+ if (p_fm->p_fm_state_struct->total_fifo_size == 0)
+ p_fm->p_fm_state_struct->total_fifo_size =
+ DFLT_TOTAL_FIFO_SIZE(
+ p_fm->p_fm_state_struct->rev_info.major_rev,
+ p_fm->p_fm_state_struct->rev_info.minor_rev);
+
+ ret_err = check_fm_parameters(p_fm);
+ if (ret_err)
+ return ret_err;
+
+ p_fm_drv_param = p_fm->p_fm_drv_param;
+
+ fm_get_revision(p_fm, &rev_info);
+
+ /* clear revision-dependent non existing exception */
+#ifdef FM_NO_DISPATCH_RAM_ECC
+ if ((rev_info.major_rev != 4) && (rev_info.major_rev < 6))
+ p_fm->p_fm_state_struct->exceptions &=
+ ~FM_EX_BMI_DISPATCH_RAM_ECC;
+#endif /* FM_NO_DISPATCH_RAM_ECC */
+
+#ifdef FM_QMI_NO_ECC_EXCEPTIONS
+ if (rev_info.major_rev == 4)
+ p_fm->p_fm_state_struct->exceptions &=
+ ~(FM_EX_QMI_SINGLE_ECC | FM_EX_QMI_DOUBLE_ECC);
+#endif /* FM_QMI_NO_ECC_EXCEPTIONS */
+
+#ifdef FM_QMI_NO_SINGLE_ECC_EXCEPTION
+ if (rev_info.major_rev >= 6)
+ p_fm->p_fm_state_struct->exceptions &= ~FM_EX_QMI_SINGLE_ECC;
+#endif /* FM_QMI_NO_SINGLE_ECC_EXCEPTION */
+
+ fm_muram_clear(p_fm->p_muram);
+
+ /* clear CPG */
+ memset_io(UINT_TO_PTR(p_fm->base_addr + FM_MM_CGP), 0,
+ p_fm->intg->fm_port_num_of_cg);
+
+ /* add to the default exceptions the user's definitions */
+ p_fm->p_fm_state_struct->exceptions |= p_fm->user_set_exceptions;
+
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+ if (p_fm->p_fm_state_struct->rev_info.major_rev < 6 &&
+ p_fm->p_fm_state_struct->rev_info.major_rev != 4 &&
+ p_fm->reset_on_init) {
+ err = fw_not_reset_erratum_bugzilla6173wa(p_fm);
+ if (err != 0)
+ return err;
+ } else {
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+ /* Reset the FM if required. */
+ if (p_fm->reset_on_init) {
+ u32 svr = mfspr(SPRN_SVR);
+
+ if (((SVR_SOC_VER(svr) == SVR_T4240 &&
+ SVR_REV(svr) > 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_T4160 &&
+ SVR_REV(svr) > 0x10)) ||
+ ((SVR_SOC_VER(svr) == SVR_T4080 &&
+ SVR_REV(svr) > 0x10)) ||
+ (SVR_SOC_VER(svr) == SVR_T2080) ||
+ (SVR_SOC_VER(svr) == SVR_T2081)) {
+ pr_debug("Hack: No FM reset!\n");
+ } else {
+ WRITE_UINT32(p_fm->p_fm_fpm_regs->fm_rstc,
+ FPM_RSTC_FM_RESET);
+ /* Memory barrier */
+ mb();
+ usleep_range(100, 101);
+ }
+
+ if (fman_is_qmi_halt_not_busy_state(
+ p_fm->p_fm_qmi_regs)) {
+ fman_resume(p_fm->p_fm_fpm_regs);
+ usleep_range(100, 101);
+ }
+ }
+
+ /* Load FMan-Controller code to IRAM */
+
+ if (clear_iram(p_fm) != 0)
+ return -ENOSYS;
+ if (p_fm->firmware.p_code && (load_fman_ctrl_code(p_fm) != 0))
+ return -ENOSYS;
+#ifdef FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173
+ }
+#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
+
+ /* General FM driver initialization */
+ p_fm->fm_muram_phys_base_addr =
+ (uint64_t)(virt_to_phys
+ (UINT_TO_PTR(p_fm->base_addr + FM_MM_MURAM)));
+
+ for (i = 0; i < FM_EV_DUMMY_LAST; i++)
+ p_fm->intr_mng[i].f_isr = unimplemented_isr;
+
+ p_fm_drv_param->exceptions = p_fm->p_fm_state_struct->exceptions;
+
+ /* Init DMA Registers */
+
+ err = init_fm_dma(p_fm);
+ if (err != 0) {
+ free_init_resources(p_fm);
+ return err;
+ }
+
+ /* Init FPM Registers */
+
+ err = init_fm_fpm(p_fm);
+ if (err != 0) {
+ free_init_resources(p_fm);
+ return err;
+ }
+
+ /* define common resources */
+ /* allocate MURAM for FIFO according to total size */
+ p_fm->fifo_base_addr = fm_muram_alloc(p_fm->p_muram,
+ p_fm->p_fm_state_struct->
+ total_fifo_size);
+ if (!p_fm->fifo_base_addr) {
+ free_init_resources(p_fm);
+ pr_err("MURAM alloc for BMI FIFO failed\n");
+ return -ENOMEM;
+ }
+
+ p_fm_drv_param->fifo_base_addr =
+ (uint32_t)(virt_to_phys(UINT_TO_PTR(p_fm->fifo_base_addr)) -
+ p_fm->fm_muram_phys_base_addr);
+
+ p_fm_drv_param->total_fifo_size = p_fm->p_fm_state_struct->
+ total_fifo_size;
+ p_fm_drv_param->total_num_of_tasks =
+ p_fm->p_fm_state_struct->total_num_of_tasks;
+ p_fm_drv_param->clk_freq = p_fm->p_fm_state_struct->fm_clk_freq;
+
+ /* Init BMI Registers */
+
+ err = init_fm_bmi(p_fm);
+ if (err != 0) {
+ free_init_resources(p_fm);
+ return err;
+ }
+
+ /* Init QMI Registers */
+
+ err = init_fm_qmi(p_fm);
+ if (err != 0) {
+ free_init_resources(p_fm);
+ return err;
+ }
+
+ err = (int)fman_enable(&fman_rg, p_fm_drv_param);
+ if (err != 0)
+ return err; /* FIXME */
+
+ enable_time_stamp(p_fm);
+
+ kfree(p_fm->firmware.p_code);
+ p_fm->firmware.p_code = NULL;
+
+ kfree(p_fm->p_fm_drv_param);
+ p_fm->p_fm_drv_param = NULL;
+
+ return 0;
+}
+
+/* fm_free
+ * Frees all resources that were assigned to FM module.
+ * Calling this routine invalidates the descriptor.
+ * h_fm - FM module descriptor
+ *Return 0 on success; Error code otherwise.
+ */
+int fm_free(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ struct fman_rg fman_rg;
+
+ fman_rg.bmi_rg = p_fm->p_fm_bmi_regs;
+ fman_rg.qmi_rg = p_fm->p_fm_qmi_regs;
+ fman_rg.fpm_rg = p_fm->p_fm_fpm_regs;
+ fman_rg.dma_rg = p_fm->p_fm_dma_regs;
+
+ fman_free_resources(&fman_rg);
+
+ kfree(p_fm->spinlock);
+
+ if (p_fm->p_fm_drv_param) {
+ kfree(p_fm->firmware.p_code);
+ kfree(p_fm->p_fm_drv_param);
+ p_fm->p_fm_drv_param = NULL;
+ }
+
+ free_init_resources(p_fm);
+
+ kfree(p_fm->p_fm_state_struct);
+
+ kfree(p_fm);
+
+ return 0;
+}
+
+/* API Advanced Init unit functions */
+
+int fm_cfg_reset_on_init(void *h_fm, bool enable)
+{
+ int ret;
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_fm->reset_on_init = enable;
+
+ return 0;
+}
+
+int fm_cfg_total_fifo_size(void *h_fm, uint32_t total_fifo_size)
+{
+ int ret;
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_fm->p_fm_state_struct->total_fifo_size = total_fifo_size;
+
+ return 0;
+}
+
+int fm_cfg_dma_aid_override(void *h_fm, bool aid_override)
+{
+ int ret;
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_fm->p_fm_drv_param->dma_aid_override = aid_override;
+
+ return 0;
+}
+
+/* API Run-time Control uint functions */
+
+void fm_event_isr(void *h_fm)
+{
+#define FM_M_CALL_MAC_ISR(_id) \
+ (p_fm->intr_mng[(enum fm_inter_module_event)(FM_EV_MAC0 + _id)]. \
+ f_isr(p_fm->intr_mng[(enum fm_inter_module_event)(FM_EV_MAC0 + _id)] \
+ .h_src_handle))
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ uint32_t pending;
+ int ret;
+ struct fman_fpm_regs __iomem *fpm_rg;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (ret)
+ return;
+
+ fpm_rg = p_fm->p_fm_fpm_regs;
+
+ /* normal interrupts */
+ pending = fman_get_normal_pending(fpm_rg);
+ if (!pending)
+ return;
+
+ if (pending & INTR_EN_QMI)
+ qmi_event(p_fm);
+ if (pending & INTR_EN_PRS)
+ p_fm->intr_mng[FM_EV_PRS].f_isr(p_fm->intr_mng[FM_EV_PRS].
+ h_src_handle);
+ if (pending & INTR_EN_TMR)
+ p_fm->intr_mng[FM_EV_TMR].f_isr(p_fm->intr_mng[FM_EV_TMR].
+ h_src_handle);
+
+ /* MAC events may belong to different partitions */
+ if (pending & INTR_EN_MAC0)
+ FM_M_CALL_MAC_ISR(0);
+ if (pending & INTR_EN_MAC1)
+ FM_M_CALL_MAC_ISR(1);
+ if (pending & INTR_EN_MAC2)
+ FM_M_CALL_MAC_ISR(2);
+ if (pending & INTR_EN_MAC3)
+ FM_M_CALL_MAC_ISR(3);
+ if (pending & INTR_EN_MAC4)
+ FM_M_CALL_MAC_ISR(4);
+ if (pending & INTR_EN_MAC5)
+ FM_M_CALL_MAC_ISR(5);
+ if (pending & INTR_EN_MAC6)
+ FM_M_CALL_MAC_ISR(6);
+ if (pending & INTR_EN_MAC7)
+ FM_M_CALL_MAC_ISR(7);
+ if (pending & INTR_EN_MAC8)
+ FM_M_CALL_MAC_ISR(8);
+ if (pending & INTR_EN_MAC9)
+ FM_M_CALL_MAC_ISR(9);
+}
+
+int fm_error_isr(void *h_fm)
+{
+#define FM_M_CALL_MAC_ERR_ISR(_id) \
+ (p_fm->intr_mng[(enum fm_inter_module_event)(FM_EV_ERR_MAC0 + _id)]. \
+ f_isr(p_fm->intr_mng[(enum fm_inter_module_event)\
+ (FM_EV_ERR_MAC0 + _id)].h_src_handle))
+
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ uint32_t pending;
+ struct fman_fpm_regs __iomem *fpm_rg;
+ int ret;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (ret)
+ return ret;
+
+ fpm_rg = p_fm->p_fm_fpm_regs;
+
+ /* error interrupts */
+ pending = fman_get_fpm_error_interrupts(fpm_rg);
+ if (!pending)
+ return -ENOSYS;
+
+ if (pending & ERR_INTR_EN_BMI)
+ bmi_err_event(p_fm);
+ if (pending & ERR_INTR_EN_QMI)
+ qmi_err_event(p_fm);
+ if (pending & ERR_INTR_EN_FPM)
+ fpm_err_event(p_fm);
+ if (pending & ERR_INTR_EN_DMA)
+ dma_err_event(p_fm);
+ if (pending & ERR_INTR_EN_IRAM)
+ iram_err_intr(p_fm);
+ if (pending & ERR_INTR_EN_MURAM)
+ muram_err_intr(p_fm);
+ if (pending & ERR_INTR_EN_PRS)
+ p_fm->intr_mng[FM_EV_ERR_PRS].f_isr(p_fm->
+ intr_mng[FM_EV_ERR_PRS].
+ h_src_handle);
+
+ /* MAC events may belong to different partitions */
+ if (pending & ERR_INTR_EN_MAC0)
+ FM_M_CALL_MAC_ERR_ISR(0);
+ if (pending & ERR_INTR_EN_MAC1)
+ FM_M_CALL_MAC_ERR_ISR(1);
+ if (pending & ERR_INTR_EN_MAC2)
+ FM_M_CALL_MAC_ERR_ISR(2);
+ if (pending & ERR_INTR_EN_MAC3)
+ FM_M_CALL_MAC_ERR_ISR(3);
+ if (pending & ERR_INTR_EN_MAC4)
+ FM_M_CALL_MAC_ERR_ISR(4);
+ if (pending & ERR_INTR_EN_MAC5)
+ FM_M_CALL_MAC_ERR_ISR(5);
+ if (pending & ERR_INTR_EN_MAC6)
+ FM_M_CALL_MAC_ERR_ISR(6);
+ if (pending & ERR_INTR_EN_MAC7)
+ FM_M_CALL_MAC_ERR_ISR(7);
+ if (pending & ERR_INTR_EN_MAC8)
+ FM_M_CALL_MAC_ERR_ISR(8);
+ if (pending & ERR_INTR_EN_MAC9)
+ FM_M_CALL_MAC_ERR_ISR(9);
+
+ return 0;
+}
+
+int fm_disable_rams_ecc(void *h_fm)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ bool explicit_disable = false;
+ struct fman_fpm_regs __iomem *fpm_rg;
+ int ret;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (ret)
+ return ret;
+
+ fpm_rg = p_fm->p_fm_fpm_regs;
+
+ if (!p_fm->p_fm_state_struct->internal_call)
+ explicit_disable = true;
+ p_fm->p_fm_state_struct->internal_call = false;
+
+ /* if rams are already disabled, or if rams were explicitly enabled and
+ * are currently called indirectly (not explicitly), ignore this call.
+ */
+ if (!p_fm->p_fm_state_struct->rams_ecc_enable ||
+ (p_fm->p_fm_state_struct->explicit_enable && !explicit_disable))
+ return 0;
+ if (p_fm->p_fm_state_struct->explicit_enable)
+ /* This is the case were both explicit are true.
+ * Turn off this flag for cases were following
+ * ramsEnable routines are called
+ */
+ p_fm->p_fm_state_struct->explicit_enable = false;
+
+ fman_enable_rams_ecc(fpm_rg);
+ p_fm->p_fm_state_struct->rams_ecc_enable = false;
+
+ return 0;
+}
+
+int fm_set_exception(void *h_fm, enum fm_exceptions exception,
+ bool enable)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ uint32_t bit_mask = 0;
+ enum fman_exceptions fsl_exception;
+ struct fman_rg fman_rg;
+ int ret;
+
+ ret = is_init_done(p_fm->p_fm_drv_param);
+ if (ret)
+ return ret;
+
+ fman_rg.bmi_rg = p_fm->p_fm_bmi_regs;
+ fman_rg.qmi_rg = p_fm->p_fm_qmi_regs;
+ fman_rg.fpm_rg = p_fm->p_fm_fpm_regs;
+ fman_rg.dma_rg = p_fm->p_fm_dma_regs;
+
+ GET_EXCEPTION_FLAG(bit_mask, exception);
+ if (bit_mask) {
+ if (enable)
+ p_fm->p_fm_state_struct->exceptions |= bit_mask;
+ else
+ p_fm->p_fm_state_struct->exceptions &= ~bit_mask;
+
+ FMAN_EXCEPTION_TRANS(fsl_exception, exception);
+
+ return (int)fman_set_exception(&fman_rg,
+ fsl_exception, enable);
+ } else {
+ pr_err("Undefined exceptioni\n");
+ return -EDOM;
+ }
+
+ return 0;
+}
+
+int fm_get_revision(void *h_fm, struct fm_revision_info_t
+ *p_fm_revision_info)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ p_fm_revision_info->major_rev = p_fm->p_fm_state_struct->
+ rev_info.major_rev;
+ p_fm_revision_info->minor_rev = p_fm->p_fm_state_struct->
+ rev_info.minor_rev;
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/freescale/fman/fm.h b/drivers/net/ethernet/freescale/fman/fm.h
new file mode 100644
index 0000000..ba5bb16
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm.h
@@ -0,0 +1,486 @@
+/*
+ * 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 internal structures and definitions. */
+#ifndef __FM_H
+#define __FM_H
+
+#include "service.h"
+#include "fm_ext.h"
+
+#include "fsl_fman.h"
+
+#define FM_MAX_NUM_OF_HW_PORT_IDS 64
+#define FM_MAX_NUM_OF_GUESTS 100
+
+/* Exceptions */
+/* DMA bus error. */
+#define FM_EX_DMA_BUS_ERROR 0x80000000
+#define FM_EX_DMA_READ_ECC 0x40000000
+#define FM_EX_DMA_SYSTEM_WRITE_ECC 0x20000000
+#define FM_EX_DMA_FM_WRITE_ECC 0x10000000
+/* Stall of tasks on FPM */
+#define FM_EX_FPM_STALL_ON_TASKS 0x08000000
+/* Single ECC on FPM */
+#define FM_EX_FPM_SINGLE_ECC 0x04000000
+#define FM_EX_FPM_DOUBLE_ECC 0x02000000
+/* Single ECC on FPM */
+#define FM_EX_QMI_SINGLE_ECC 0x01000000
+/* Dequeu from default queue id */
+#define FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID 0x00800000
+#define FM_EX_QMI_DOUBLE_ECC 0x00400000
+#define FM_EX_BMI_LIST_RAM_ECC 0x00200000
+#define FM_EX_BMI_STORAGE_PROFILE_ECC 0x00100000
+#define FM_EX_BMI_STATISTICS_RAM_ECC 0x00080000
+#define FM_EX_IRAM_ECC 0x00040000
+#define FM_EX_MURAM_ECC 0x00020000
+#define FM_EX_BMI_DISPATCH_RAM_ECC 0x00010000
+#define FM_EX_DMA_SINGLE_PORT_ECC 0x00008000
+
+#define DMA_EMSR_EMSTR_MASK 0x0000FFFF
+
+#define DMA_THRESH_COMMQ_MASK 0xFF000000
+#define DMA_THRESH_READ_INT_BUF_MASK 0x007F0000
+#define DMA_THRESH_WRITE_INT_BUF_MASK 0x0000007F
+
+#define GET_EXCEPTION_FLAG(bit_mask, exception) \
+do { \
+ switch ((int)exception) { \
+ case FM_EX_DMA_BUS_ERROR: \
+ bit_mask = FM_EX_DMA_BUS_ERROR; \
+ break; \
+ case FM_EX_DMA_SINGLE_PORT_ECC: \
+ bit_mask = FM_EX_DMA_SINGLE_PORT_ECC; \
+ break; \
+ case FM_EX_DMA_READ_ECC: \
+ bit_mask = FM_EX_DMA_READ_ECC; \
+ break; \
+ case FM_EX_DMA_SYSTEM_WRITE_ECC: \
+ bit_mask = FM_EX_DMA_SYSTEM_WRITE_ECC; \
+ break; \
+ case FM_EX_DMA_FM_WRITE_ECC: \
+ bit_mask = FM_EX_DMA_FM_WRITE_ECC; \
+ break; \
+ case FM_EX_FPM_STALL_ON_TASKS: \
+ bit_mask = FM_EX_FPM_STALL_ON_TASKS; \
+ break; \
+ case FM_EX_FPM_SINGLE_ECC: \
+ bit_mask = FM_EX_FPM_SINGLE_ECC; \
+ break; \
+ case FM_EX_FPM_DOUBLE_ECC: \
+ bit_mask = FM_EX_FPM_DOUBLE_ECC; \
+ break; \
+ case FM_EX_QMI_SINGLE_ECC: \
+ bit_mask = FM_EX_QMI_SINGLE_ECC; \
+ break; \
+ case FM_EX_QMI_DOUBLE_ECC: \
+ bit_mask = FM_EX_QMI_DOUBLE_ECC; \
+ break; \
+ case FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: \
+ bit_mask = FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID; \
+ break; \
+ case FM_EX_BMI_LIST_RAM_ECC: \
+ bit_mask = FM_EX_BMI_LIST_RAM_ECC; \
+ break; \
+ case FM_EX_BMI_STORAGE_PROFILE_ECC: \
+ bit_mask = FM_EX_BMI_STORAGE_PROFILE_ECC; \
+ break; \
+ case FM_EX_BMI_STATISTICS_RAM_ECC: \
+ bit_mask = FM_EX_BMI_STATISTICS_RAM_ECC; \
+ break; \
+ case FM_EX_BMI_DISPATCH_RAM_ECC: \
+ bit_mask = FM_EX_BMI_DISPATCH_RAM_ECC; \
+ break; \
+ case FM_EX_IRAM_ECC: \
+ bit_mask = FM_EX_IRAM_ECC; \
+ break; \
+ case FM_EX_MURAM_ECC: \
+ bit_mask = FM_EX_MURAM_ECC; \
+ break; \
+ default: \
+ bit_mask = 0; \
+ break; \
+ } \
+} while (0)
+
+#define GET_FM_MODULE_EVENT(_p_fm, _mod, _id, _intr_type, _event) \
+do { \
+ switch (_mod) { \
+ case (FM_MOD_PRS): \
+ if (_id) \
+ _event = FM_EV_DUMMY_LAST; \
+ else \
+ event = (_intr_type == FM_INTR_TYPE_ERR) ? \
+ FM_EV_ERR_PRS : FM_EV_PRS; \
+ break; \
+ case (FM_MOD_TMR): \
+ if (_id) \
+ _event = FM_EV_DUMMY_LAST; \
+ else \
+ _event = (_intr_type == FM_INTR_TYPE_ERR) ? \
+ FM_EV_DUMMY_LAST : FM_EV_TMR; \
+ break; \
+ case (FM_MOD_MAC): \
+ _event = (_intr_type == FM_INTR_TYPE_ERR) ? \
+ (FM_EV_ERR_MAC0 + _id) : \
+ (FM_EV_MAC0 + _id); \
+ break; \
+ case (FM_MOD_FMAN_CTRL): \
+ if (_intr_type == FM_INTR_TYPE_ERR) \
+ _event = FM_EV_DUMMY_LAST; \
+ else \
+ _event = (FM_EV_FMAN_CTRL_0 + _id); \
+ break; \
+ default: \
+ _event = FM_EV_DUMMY_LAST; \
+ break; \
+ } \
+} while (0)
+
+#define FMAN_EXCEPTION_TRANS(fsl_exception, _exception) do {\
+switch ((int)_exception) {\
+case FM_EX_DMA_BUS_ERROR: \
+ fsl_exception = E_FMAN_EX_DMA_BUS_ERROR;\
+ break; \
+case FM_EX_DMA_READ_ECC: \
+ fsl_exception = E_FMAN_EX_DMA_READ_ECC;\
+ break; \
+case FM_EX_DMA_SYSTEM_WRITE_ECC: \
+ fsl_exception = E_FMAN_EX_DMA_SYSTEM_WRITE_ECC;\
+ break; \
+case FM_EX_DMA_FM_WRITE_ECC: \
+ fsl_exception = E_FMAN_EX_DMA_FM_WRITE_ECC;\
+ break; \
+case FM_EX_FPM_STALL_ON_TASKS: \
+ fsl_exception = E_FMAN_EX_FPM_STALL_ON_TASKS;\
+ break; \
+case FM_EX_FPM_SINGLE_ECC: \
+ fsl_exception = E_FMAN_EX_FPM_SINGLE_ECC;\
+ break; \
+case FM_EX_FPM_DOUBLE_ECC: \
+ fsl_exception = E_FMAN_EX_FPM_DOUBLE_ECC;\
+ break; \
+case FM_EX_QMI_SINGLE_ECC: \
+ fsl_exception = E_FMAN_EX_QMI_SINGLE_ECC;\
+ break; \
+case FM_EX_QMI_DOUBLE_ECC: \
+ fsl_exception = E_FMAN_EX_QMI_DOUBLE_ECC;\
+ break; \
+case FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID: \
+ fsl_exception = E_FMAN_EX_QMI_DEQ_FROM_UNKNOWN_PORTID;\
+ break; \
+case FM_EX_BMI_LIST_RAM_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_LIST_RAM_ECC;\
+ break; \
+case FM_EX_BMI_STORAGE_PROFILE_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_STORAGE_PROFILE_ECC;\
+ break; \
+case FM_EX_BMI_STATISTICS_RAM_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_STATISTICS_RAM_ECC;\
+ break; \
+case FM_EX_BMI_DISPATCH_RAM_ECC: \
+ fsl_exception = E_FMAN_EX_BMI_DISPATCH_RAM_ECC;\
+ break; \
+case FM_EX_IRAM_ECC: \
+ fsl_exception = E_FMAN_EX_IRAM_ECC;\
+ break; \
+case FM_EX_MURAM_ECC: \
+ fsl_exception = E_FMAN_EX_MURAM_ECC;\
+ break; \
+default: \
+ fsl_exception = E_FMAN_EX_DMA_BUS_ERROR; break; \
+} \
+} while (0)
+
+/* defaults */
+#define DEFAULT_exceptions \
+(FM_EX_DMA_BUS_ERROR | \
+FM_EX_DMA_READ_ECC | \
+FM_EX_DMA_SYSTEM_WRITE_ECC | \
+FM_EX_DMA_FM_WRITE_ECC | \
+FM_EX_FPM_STALL_ON_TASKS | \
+FM_EX_FPM_SINGLE_ECC | \
+FM_EX_FPM_DOUBLE_ECC | \
+FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID | \
+FM_EX_BMI_LIST_RAM_ECC | \
+FM_EX_BMI_STORAGE_PROFILE_ECC | \
+FM_EX_BMI_STATISTICS_RAM_ECC | \
+FM_EX_IRAM_ECC | \
+FM_EX_MURAM_ECC | \
+FM_EX_BMI_DISPATCH_RAM_ECC | \
+FM_EX_QMI_DOUBLE_ECC | \
+FM_EX_QMI_SINGLE_ECC)
+
+#ifdef FM_PEDANTIC_DMA
+#define DEFAULT_aid_override(major) (major == 4 ? : true : false)
+#else
+#define DEFAULT_aid_override(major) false
+#endif /* FM_PEDANTIC_DMA */
+#define DEFAULT_AXI_DBG_NUM_OF_BEATS 1
+#define DEFAULT_RESET_ON_INIT false
+/* do not change! if changed, must be disabled for rev1 ! */
+#define DEFAULT_VERIFY_UCODE false
+
+#define DFLT_DMA_READ_INT_BUF_LOW(dma_thresh_max_buf) \
+ ((dma_thresh_max_buf + 1) / 2)
+#define DFLT_DMA_READ_INT_BUF_HIGH(dma_thresh_max_buf) \
+ ((dma_thresh_max_buf + 1) * 3 / 4)
+#define DFLT_DMA_WRITE_INT_BUF_LOW(dma_thresh_max_buf) \
+ ((dma_thresh_max_buf + 1) / 2)
+#define DFLT_DMA_WRITE_INT_BUF_HIGH(dma_thresh_max_buf)\
+ ((dma_thresh_max_buf + 1) * 3 / 4)
+
+#define DFLT_DMA_COMM_Q_LOW(major, dma_thresh_max_commq) \
+ ((major == 6) ? 0x2A : ((dma_thresh_max_commq + 1) / 2))
+
+#define DFLT_DMA_COMM_Q_HIGH(major, dma_thresh_max_commq) \
+ ((major == 6) ? 0x3f : ((dma_thresh_max_commq + 1) * 3 / 4))
+
+#define DFLT_TOTAL_NUM_OF_TASKS(major, minor, bmi_max_num_of_tasks) \
+ ((major == 6) ? ((minor == 1 || minor == 4) ? 59 : 124) : \
+ bmi_max_num_of_tasks)
+
+#define DFLT_CACHE_OVERRIDE FM_DMA_NO_CACHE_OR
+#define DFLT_DMA_CAM_NUM_OF_ENTRIES(major) (major == 6 ? 64 : 32)
+#define DFLT_DMA_EN_EMERGENCY false
+#define DFLT_DMA_SOS_EMERGENCY 0
+#define DFLT_DMA_WATCH_DOG 0
+#define DFLT_DMA_EN_EMERGENCY_SMOOTHER false
+#define DFLT_DMA_EMERGENCY_SWITCH_COUNTER 0
+
+#define DFLT_DISP_LIMIT 0
+#define DFLT_PRS_DISP_TH 16
+#define DFLT_BMI_DISP_TH 16
+#define DFLT_QMI_ENQ_DISP_TH 16
+#define DFLT_QMI_DEQ_DISP_TH 16
+#define DFLT_FM_CTL1_DISP_TH 16
+#define DFLT_FM_CTL2_DISP_TH 16
+
+#define DFLT_TOTAL_FIFO_SIZE(major, minor) \
+ ((major == 6) ? \
+ ((minor == 1 || minor == 4) ? (156 * 1024) : (295 * 1024)) : \
+ (((major == 2) || (major == 5)) ? \
+ (100 * 1024) : ((major == 4) ? \
+ (46 * 1024) : (122 * 1024))))
+
+#define FM_TIMESTAMP_1_USEC_BIT 8
+
+/* Defines used for enabling/disabling FM interrupts */
+#define ERR_INTR_EN_DMA 0x00010000
+#define ERR_INTR_EN_FPM 0x80000000
+#define ERR_INTR_EN_BMI 0x00800000
+#define ERR_INTR_EN_QMI 0x00400000
+#define ERR_INTR_EN_PRS 0x00200000
+#define ERR_INTR_EN_MURAM 0x00040000
+#define ERR_INTR_EN_IRAM 0x00020000
+#define ERR_INTR_EN_MAC8 0x00008000
+#define ERR_INTR_EN_MAC9 0x00000040
+#define ERR_INTR_EN_MAC0 0x00004000
+#define ERR_INTR_EN_MAC1 0x00002000
+#define ERR_INTR_EN_MAC2 0x00001000
+#define ERR_INTR_EN_MAC3 0x00000800
+#define ERR_INTR_EN_MAC4 0x00000400
+#define ERR_INTR_EN_MAC5 0x00000200
+#define ERR_INTR_EN_MAC6 0x00000100
+#define ERR_INTR_EN_MAC7 0x00000080
+
+#define INTR_EN_QMI 0x40000000
+#define INTR_EN_PRS 0x20000000
+#define INTR_EN_MAC0 0x00080000
+#define INTR_EN_MAC1 0x00040000
+#define INTR_EN_MAC2 0x00020000
+#define INTR_EN_MAC3 0x00010000
+#define INTR_EN_MAC4 0x00000040
+#define INTR_EN_MAC5 0x00000020
+#define INTR_EN_MAC6 0x00000008
+#define INTR_EN_MAC7 0x00000002
+#define INTR_EN_MAC8 0x00200000
+#define INTR_EN_MAC9 0x00100000
+#define INTR_EN_REV0 0x00008000
+#define INTR_EN_REV1 0x00004000
+#define INTR_EN_REV2 0x00002000
+#define INTR_EN_REV3 0x00001000
+#define INTR_EN_BRK 0x00000080
+#define INTR_EN_TMR 0x01000000
+
+/* Modules registers offsets */
+#define FM_MM_MURAM 0x00000000
+#define FM_MM_BMI 0x00080000
+#define FM_MM_QMI 0x00080400
+#define FM_MM_PRS 0x000c7000
+#define FM_MM_DMA 0x000C2000
+#define FM_MM_FPM 0x000C3000
+#define FM_MM_IMEM 0x000C4000
+#define FM_MM_CGP 0x000DB000
+#define FM_MM_TRB(i) (0x000D0200 + 0x400 * (i))
+#define FM_MM_SP 0x000dc000
+
+/* Memory Mapped Registers */
+
+struct fm_iram_regs_t {
+ uint32_t iadd; /* FM IRAM instruction address register */
+ uint32_t idata;/* FM IRAM instruction data register */
+ uint32_t itcfg;/* FM IRAM timing config register */
+ uint32_t iready;/* FM IRAM ready register */
+ uint8_t res[0x80000 - 0x10];
+} __attribute__((__packed__));
+
+/* General defines */
+#define FM_DEBUG_STATUS_REGISTER_OFFSET 0x000d1084UL
+#define FM_FW_DEBUG_INSTRUCTION 0x6ffff805UL
+
+/* FPM defines */
+/* masks */
+#define FPM_BRKC_RDBG 0x00000200
+/* BMI defines */
+/* masks */
+#define BMI_INIT_START 0x80000000
+#define BMI_ERR_INTR_EN_STORAGE_PROFILE_ECC 0x80000000
+#define BMI_ERR_INTR_EN_LIST_RAM_ECC 0x40000000
+#define BMI_ERR_INTR_EN_STATISTICS_RAM_ECC 0x20000000
+#define BMI_ERR_INTR_EN_DISPATCH_RAM_ECC 0x10000000
+/* QMI defines */
+/* masks */
+#define QMI_ERR_INTR_EN_DOUBLE_ECC 0x80000000
+#define QMI_ERR_INTR_EN_DEQ_FROM_DEF 0x40000000
+#define QMI_INTR_EN_SINGLE_ECC 0x80000000
+
+/* IRAM defines */
+/* masks */
+#define IRAM_IADD_AIE 0x80000000
+#define IRAM_READY 0x80000000
+
+/* TRB defines */
+/* masks */
+#define TRB_TCRH_RESET 0x04000000
+#define TRB_TCRH_ENABLE_COUNTERS 0x84008000
+#define TRB_TCRH_DISABLE_COUNTERS 0x8400C000
+#define TRB_TCRL_RESET 0x20000000
+#define TRB_TCRL_UTIL 0x00000460
+
+struct fm_state_struct_t {
+/* Master/Guest parameters */
+
+ uint8_t fm_id;
+ uint16_t fm_clk_freq;
+ struct fm_revision_info_t rev_info;
+
+/* Master Only parameters */
+
+ bool enabled_time_stamp;
+ uint8_t count1_micro_bit;
+ uint8_t total_num_of_tasks;
+ uint32_t total_fifo_size;
+ uint8_t max_num_of_open_dmas;
+ uint8_t accumulated_num_of_tasks;
+ uint32_t accumulated_fifo_size;
+ uint8_t accumulated_num_of_open_dmas;
+ uint8_t accumulated_num_of_deq_tnums;
+#ifdef FM_LOW_END_RESTRICTION
+ bool low_end_restriction;
+#endif /* FM_LOW_END_RESTRICTION */
+ uint32_t exceptions;
+ bool rams_ecc_enable;
+ bool explicit_enable;
+ bool internal_call;
+ uint8_t rams_ecc_owners;
+ uint32_t extra_fifo_pool_size;
+ uint8_t extra_tasks_pool_size;
+ uint8_t extra_open_dmas_pool_size;
+};
+
+struct fm_intg_t {
+ /* Ram defines */
+ uint32_t fm_muram_size;
+ uint32_t fm_iram_size;
+ uint32_t fm_num_of_ctrl;
+
+ /* DMA defines */
+ uint32_t dma_thresh_max_commq;
+ uint32_t dma_thresh_max_buf;
+
+ /* QMI defines */
+ uint32_t qmi_max_num_of_tnums;
+ uint32_t qmi_def_tnums_thresh;
+
+ /* BMI defines */
+ uint32_t bmi_max_num_of_tasks;
+ uint32_t bmi_max_num_of_dmas;
+ uint32_t bmi_max_fifo_size;
+ uint32_t port_max_weight;
+
+ uint32_t fm_port_num_of_cg;
+ uint32_t num_of_rx_ports;
+};
+
+struct fm_t {
+/* locals for recovery */
+ uintptr_t base_addr;
+
+/* un-needed for recovery */
+ char fm_module_name[MODULE_NAME_SIZE];
+ /* FM exceptions user callback */
+ struct fm_intr_src_t intr_mng[FM_EV_DUMMY_LAST];
+
+/* Master Only parameters */
+
+/* locals for recovery */
+ struct fman_fpm_regs __iomem *p_fm_fpm_regs;
+ struct fman_bmi_regs __iomem *p_fm_bmi_regs;
+ struct fman_qmi_regs __iomem *p_fm_qmi_regs;
+ struct fman_dma_regs __iomem *p_fm_dma_regs;
+ struct fman_regs __iomem *p_fm_regs;
+ fm_exceptions_cb *f_exception;
+ fm_bus_error_cb *f_bus_error;
+ void *h_app; /* Application handle */
+ spinlock_t *spinlock;
+ struct fm_state_struct_t *p_fm_state_struct;
+ uint16_t tnum_aging_period;
+
+/* un-needed for recovery */
+ struct fman_cfg *p_fm_drv_param;
+ struct muram_info *p_muram;
+ phys_addr_t fm_muram_phys_base_addr;
+ uintptr_t cam_base_addr; /* save for freeing */
+ uint32_t cam_size;
+ uintptr_t res_addr;
+ uintptr_t fifo_base_addr; /* save for freeing */
+ uint32_t fifo_size;
+ struct fm_firmware_params_t firmware;
+ bool fw_verify;
+ bool reset_on_init;
+ uint32_t user_set_exceptions;
+
+ struct fm_intg_t *intg;
+};
+
+#endif /* __FM_H */
diff --git a/drivers/net/ethernet/freescale/fman/fm_common.h b/drivers/net/ethernet/freescale/fman/fm_common.h
new file mode 100644
index 0000000..f9d6575
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_common.h
@@ -0,0 +1,331 @@
+/*
+ * 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_common.h
+ * Description FM internal structures and definitions.
+ */
+#ifndef __FM_COMMON_H
+#define __FM_COMMON_H
+
+#include "service.h"
+#include "fm_ext.h"
+
+#define CLS_PLAN_NUM_PER_GRP 8
+
+/* list_object
+ * Macro to get the struct (object) for this entry.
+ * type - The type of the struct (object) this list
+ * is embedded in.
+ * member - The name of the struct list_head object
+ * within the struct.
+ * Return The structure pointer for this entry.
+ */
+#define member_offset(type, member) (PTR_TO_UINT(&((type *)0)->member))
+#define list_object(p_list, type, member) \
+((type *)((char *)(p_list) - member_offset(type, member)))
+
+/* Enum for inter-module interrupts registration */
+enum fm_event_modules {
+ FM_MOD_PRS = 0, /* Parser event */
+ FM_MOD_MAC, /* MAC event */
+ FM_MOD_TMR, /* Timer event */
+ FM_MOD_FMAN_CTRL, /* FMAN Controller Timer event */
+ FM_MOD_DUMMY_LAST
+};
+
+/* Enum for interrupts types */
+enum fm_intr_type {
+ FM_INTR_TYPE_ERR,
+ FM_INTR_TYPE_NORMAL
+};
+
+/* Enum for inter-module interrupts registration */
+enum fm_inter_module_event {
+ FM_EV_PRS = 0, /* Parser event */
+ FM_EV_ERR_PRS, /* Parser error event */
+ FM_EV_ERR_MAC8, /* MAC 8 error event */
+ FM_EV_ERR_MAC9, /* MAC 9 error event */
+ FM_EV_ERR_MAC0, /* MAC 0 error event */
+ FM_EV_ERR_MAC1, /* MAC 1 error event */
+ FM_EV_ERR_MAC2, /* MAC 2 error event */
+ FM_EV_ERR_MAC3, /* MAC 3 error event */
+ FM_EV_ERR_MAC4, /* MAC 4 error event */
+ FM_EV_ERR_MAC5, /* MAC 5 error event */
+ FM_EV_ERR_MAC6, /* MAC 6 error event */
+ FM_EV_ERR_MAC7, /* MAC 7 error event */
+ FM_EV_TMR, /* Timer event */
+ FM_EV_MAC8, /* MAC 8 event (Magic packet detection)*/
+ FM_EV_MAC9, /* MAC 9 event (Magic packet detection)*/
+ FM_EV_MAC0, /* MAC 0 event (Magic packet detection)*/
+ FM_EV_MAC1, /* MAC 1 event (Magic packet detection)*/
+ FM_EV_MAC2, /* MAC 2 (Magic packet detection)*/
+ FM_EV_MAC3, /* MAC 3 (Magic packet detection)*/
+ FM_EV_MAC4, /* MAC 4 (Magic packet detection)*/
+ FM_EV_MAC5, /* MAC 5 (Magic packet detection)*/
+ FM_EV_MAC6, /* MAC 6 (Magic packet detection)*/
+ FM_EV_MAC7, /* MAC 7 (Magic packet detection)*/
+ FM_EV_FMAN_CTRL_0, /* Fman controller event 0 */
+ FM_EV_FMAN_CTRL_1, /* Fman controller event 1 */
+ FM_EV_FMAN_CTRL_2, /* Fman controller event 2 */
+ FM_EV_FMAN_CTRL_3, /* Fman controller event 3 */
+ FM_EV_DUMMY_LAST
+};
+
+/* FM IP BLOCK versions */
+#define FM_IP_BLOCK_P1 4
+#define FM_IP_BLOCK_P2_P3_P5 3
+#define FM_IP_BLOCK_P4 2
+#define FM_IP_BLOCK_B_T 6
+
+/*for UNDER_CONSTRUCTION_FM_RMU_USE_SEC its defined in fm_ext.h*/
+typedef uint32_t fm_fman_ctrl_t;
+
+#define FPM_PORT_FM_CTL1 0x00000001
+#define FPM_PORT_FM_CTL2 0x00000002
+
+static inline bool TRY_LOCK(spinlock_t *spinlock, volatile bool *p_flag)
+{
+ unsigned long int_flags;
+
+ if (spinlock)
+ spin_lock_irqsave(spinlock, int_flags);
+ else
+ local_irq_save(int_flags);
+
+ if (*p_flag) {
+ if (spinlock)
+ spin_unlock_irqrestore(spinlock, int_flags);
+ else
+ local_irq_restore(int_flags);
+ return false;
+ }
+ *p_flag = true;
+
+ if (spinlock)
+ spin_unlock_irqrestore(spinlock, int_flags);
+ else
+ local_irq_restore(int_flags);
+
+ return true;
+}
+
+#define RELEASE_LOCK(_flag) (_flag = false)
+
+/* Defines used for manipulation CC and BMI */
+#define INTERNAL_CONTEXT_OFFSET 0x80000000
+#define OFFSET_OF_PR 0x40000000
+#define NUM_OF_TASKS 0x10000000
+#define OFFSET_OF_DATA 0x08000000
+#define HW_PORT_ID 0x04000000
+#define FM_REV 0x02000000
+#define GET_NIA_FPNE 0x01000000
+#define GET_NIA_PNDN 0x00800000
+#define NUM_OF_EXTRA_TASKS 0x00400000
+#define DISCARD_MASK 0x00200000
+
+#define UPDATE_NIA_PNEN 0x80000000
+#define UPDATE_PSO 0x40000000
+#define UPDATE_NIA_PNDN 0x20000000
+#define UPDATE_FMFP_PRC_WITH_ONE_RISC_ONLY 0x10000000
+#define UPDATE_NIA_FENE 0x04000000
+#define UPDATE_NIA_CMNE 0x02000000
+#define UPDATE_NIA_FPNE 0x01000000
+
+/* Defines used for manipulation CC and CC */
+#define UPDATE_NIA_ENQ_WITHOUT_DMA 0x80000000
+
+#define MODULE_NAME_SIZE 30
+#define DUMMY_PORT_ID 0
+
+#define FM_LIODN_OFFSET_MASK 0x3FF
+
+/* Description CTRL Parameters Page defines */
+#define FM_CTL_PARAMS_PAGE_OP_FIX_EN 0x80000000
+#define FM_CTL_PARAMS_PAGE_ALWAYS_ON 0x00000100
+
+#define FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK 0x0000003f
+
+#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE)
+#define BMI_FIFO_UNITS 0x100
+
+struct fm_intr_src_t {
+ void (*f_isr)(void *h_src_arg);
+ void *h_src_handle;
+};
+
+#define ILLEGAL_HDR_NUM 0xFF
+#define NO_HDR_NUM FM_PCD_PRS_NUM_OF_HDRS
+
+#define IS_PRIVATE_HEADER(hdr) (((hdr) == HEADER_TYPE_USER_DEFINED_SHIM1) || \
+ ((hdr) == HEADER_TYPE_USER_DEFINED_SHIM2))
+
+#define GET_PRS_HDR_NUM(num, hdr) do {\
+switch (hdr) { \
+case (HEADER_TYPE_ETH):\
+ num = 0; break; \
+case (HEADER_TYPE_LLC_SNAP):\
+ num = 1; break; \
+case (HEADER_TYPE_VLAN):\
+ num = 2; break; \
+case (HEADER_TYPE_PPPOE):\
+ num = 3; break; \
+case (HEADER_TYPE_PPP):\
+ num = 3; break; \
+case (HEADER_TYPE_MPLS):\
+ num = 4; break; \
+case (HEADER_TYPE_IPV4):\
+ num = 5; break; \
+case (HEADER_TYPE_IPV6):\
+ num = 6; break; \
+case (HEADER_TYPE_GRE):\
+ num = 7; break; \
+case (HEADER_TYPE_MINENCAP):\
+ num = 8; break; \
+case (HEADER_TYPE_USER_DEFINED_L3):\
+ num = 9; break; \
+case (HEADER_TYPE_TCP):\
+ num = 10; break; \
+case (HEADER_TYPE_UDP):\
+ num = 11; break; \
+case (HEADER_TYPE_IPSEC_AH): \
+case (HEADER_TYPE_IPSEC_ESP):\
+ num = 12; break; \
+case (HEADER_TYPE_SCTP):\
+ num = 13; break; \
+case (HEADER_TYPE_DCCP):\
+ num = 14; break; \
+case (HEADER_TYPE_USER_DEFINED_L4):\
+ num = 15; break; \
+case (HEADER_TYPE_USER_DEFINED_SHIM1): \
+case (HEADER_TYPE_USER_DEFINED_SHIM2): \
+ num = NO_HDR_NUM; break; \
+default: \
+ pr_err("Unsupported header for parser\n");\
+ num = ILLEGAL_HDR_NUM; break; \
+} \
+} while (0)
+
+#define FM_PCD_MAX_NUM_OF_OPTIONS(cls_plan_entries) \
+((cls_plan_entries == 256) ? 8 : ((cls_plan_entries == 128) ? 7 : \
+((cls_plan_entries == 64) ? 6 : ((cls_plan_entries == 32) ? 5 : 0))))
+
+/* Function fm_register_intr
+ * Description Used to register
+ * an inter-module event handler to be processed by FM
+ * Param[in] h_fm A handle to an FM Module.
+ * Param[in] mod The module that causes the event
+ * Param[in] mod_id Module id - if more than 1 instance of this
+ * mode exists,0 otherwise.
+ * Param[in] intr_type Interrupt type (error/normal) selection.
+ * Param[in] f_isr The interrupt service routine.
+ * Param[in] h_src_arg Argument to be passed to f_isr.
+ * Return None.
+ */
+void fm_register_intr(void *h_fm,
+ enum fm_event_modules mod,
+ uint8_t mod_id,
+ enum fm_intr_type intr_type,
+ void (*f_isr)(void *h_src_arg), void *h_src_arg);
+
+/* Function fm_unregister_intr
+ * Description Used to un-register an
+ * inter-module event handler that was processed by FM
+ * Param[in] h_fm A handle to an FM Module.
+ * Param[in] mod The module that causes the event
+ * Param[in] mod_id Module id - if more than 1 instance of this
+ * mode exists,0 otherwise.
+ * Param[in] intr_type Interrupt type (error/normal) selection.
+ * Return None.
+ */
+void fm_unregister_intr(void *h_fm,
+ enum fm_event_modules mod,
+ uint8_t mod_id, enum fm_intr_type intr_type);
+
+/* Description enum for defining MAC types */
+enum fm_mac_type {
+ FM_MAC_10G = 0, /* 10G MAC */
+ FM_MAC_1G /* 1G MAC */
+};
+
+/* 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.
+ * Return MURAM module pointer.
+ */
+struct muram_info *fm_get_muram_pointer(void *h_fm);
+
+/* Function fm_get_physical_muram_base
+ * Description Get the physical base address of the MURAM from the FM module
+ * Param[in] h_fm A handle to an FM Module.
+ * Param[in] fm_phys_addr Physical MURAM base
+ * Return Physical base address.
+ */
+void fm_get_physical_muram_base(void *h_fm,
+ struct fm_phys_addr_t *fm_phys_addr);
+
+/* Function fm_get_clock_freq
+ * Description Used by MAC driver to get the FM clock frequency
+ * Param[in] h_fm A handle to an FM Module.
+ * Return clock-freq on success; 0 otherwise.
+ * Cautions Allowed only following fm_init().
+ */
+uint16_t fm_get_clock_freq(void *h_fm);
+
+/*Function fm_get_id
+ * Description Used by PCD driver to read rhe FM id
+ * Param[in] h_fm A handle to an FM Module.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_init().
+ */
+uint8_t fm_get_id(void *h_fm);
+
+void fm_muram_clear(struct muram_info *p_muram);
+int fm_set_num_of_open_dmas(void *h_fm,
+ uint8_t port_id,
+ uint8_t *p_num_of_open_dmas,
+ uint8_t *p_num_of_extra_open_dmas,
+ bool initial_config);
+int fm_set_num_of_tasks(void *h_fm,
+ uint8_t port_id,
+ uint8_t *p_num_of_tasks,
+ uint8_t *p_num_of_extra_tasks,
+ bool initial_config);
+int fm_set_size_of_fifo(void *h_fm,
+ uint8_t port_id,
+ uint32_t *p_size_of_fifo,
+ uint32_t *p_extra_size_of_fifo,
+ bool initial_config);
+
+uint32_t fm_get_bmi_max_fifo_size(void *h_fm);
+struct num_of_ports_info_t *fm_get_num_of_ports(void *h_fm);
+
+#endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/fm_drv.c b/drivers/net/ethernet/freescale/fman/fm_drv.c
new file mode 100644
index 0000000..2d8db7f
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_drv.c
@@ -0,0 +1,856 @@
+/*
+ * 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 <linux/version.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/of_platform.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/uaccess.h>
+#include <linux/errno.h>
+#include <asm/qe.h> /* For struct qe_firmware */
+#include <sysdev/fsl_soc.h>
+#include <linux/stat.h> /* For file access mask */
+#include <linux/skbuff.h>
+
+/* Internal services */
+#include "service.h"
+#include "fm_ext.h"
+#include "fm_drv.h"
+#include "fm_muram_ext.h"
+
+/* Bootarg used to override the Kconfig FSL_FM_MAX_FRAME_SIZE value */
+#define FSL_FM_MAX_FRM_BOOTARG "fsl_fm_max_frm"
+
+/* Bootarg used to override FSL_FM_RX_EXTRA_HEADROOM Kconfig value */
+#define FSL_FM_RX_EXTRA_HEADROOM_BOOTARG "fsl_fm_rx_extra_headroom"
+
+/* Minimum and maximum value for the fsl_fm_rx_extra_headroom bootarg */
+#define FSL_FM_RX_EXTRA_HEADROOM_MIN 16
+#define FSL_FM_RX_EXTRA_HEADROOM_MAX 384
+
+/* Max frame size, across all interfaces.
+ * Configurable from Kconfig or bootargs, to avoid allocating oversized
+ * (socket) buffers when not using jumbo frames.
+ * Must be large enough to accommodate the network MTU, but small enough
+ * to avoid wasting skb memory.
+ *
+ * Could be overridden once, at boot-time, via the
+ * fm_set_max_frm() callback.
+ */
+int fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+
+/* Extra headroom for Rx buffers.
+ * FMan is instructed to allocate, on the Rx path, this amount of
+ * space at the beginning of a data buffer, beside the DPA private
+ * data area and the IC fields.
+ * Does not impact Tx buffer layout.
+ * Configurable from Kconfig or bootargs. Zero by default, it's needed on
+ * particular forwarding scenarios that add extra headers to the
+ * forwarded frame.
+ */
+int fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+static struct lnx_wrp_fm_t lnx_wrp_fm;
+
+u16 fm_get_max_frm(void)
+{
+ return fsl_fm_max_frm;
+}
+EXPORT_SYMBOL(fm_get_max_frm);
+
+int fm_get_rx_extra_headroom(void)
+{
+ return ALIGN(fsl_fm_rx_extra_headroom, 16);
+}
+EXPORT_SYMBOL(fm_get_rx_extra_headroom);
+
+static int __init fm_set_max_frm(char *str)
+{
+ int ret = 0;
+
+ ret = get_option(&str, &fsl_fm_max_frm);
+ if (ret != 1) {
+ /* This will only work if CONFIG_EARLY_PRINTK is compiled in,
+ * and something like "earlyprintk=serial,uart0,115200" is
+ * specified in the bootargs.
+ */
+ pr_err("No suitable %s=<int> prop in bootargs; will use the default FSL_FM_MAX_FRAME_SIZE (%d) from Kconfig.\n",
+ FSL_FM_MAX_FRM_BOOTARG,
+ CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+ return 1;
+ }
+
+ /* Don't allow invalid bootargs; fallback to the Kconfig value */
+ if (fsl_fm_max_frm < 64 || fsl_fm_max_frm > 9600) {
+ pr_err("Invalid %s=%d in bootargs, valid range is 64-9600. Falling back to the FSL_FM_MAX_FRAME_SIZE (%d) from Kconfig.\n",
+ FSL_FM_MAX_FRM_BOOTARG, fsl_fm_max_frm,
+ CONFIG_FSL_FM_MAX_FRAME_SIZE);
+
+ fsl_fm_max_frm = CONFIG_FSL_FM_MAX_FRAME_SIZE;
+ return 1;
+ }
+
+ pr_info("Using fsl_fm_max_frm=%d from bootargs\n", fsl_fm_max_frm);
+ return 0;
+}
+
+early_param(FSL_FM_MAX_FRM_BOOTARG, fm_set_max_frm);
+
+static int __init fm_set_rx_extra_headroom(char *str)
+{
+ int ret;
+
+ ret = get_option(&str, &fsl_fm_rx_extra_headroom);
+
+ if (ret != 1) {
+ pr_err("No suitable %s=<int> prop in bootargs; will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n",
+ FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+ CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+
+ return 1;
+ }
+
+ if (fsl_fm_rx_extra_headroom < FSL_FM_RX_EXTRA_HEADROOM_MIN ||
+ fsl_fm_rx_extra_headroom > FSL_FM_RX_EXTRA_HEADROOM_MAX) {
+ pr_err("Invalid value for %s=%d prop in bootargs; will use the default FSL_FM_RX_EXTRA_HEADROOM (%d) from Kconfig.\n",
+ FSL_FM_RX_EXTRA_HEADROOM_BOOTARG,
+ fsl_fm_rx_extra_headroom,
+ CONFIG_FSL_FM_RX_EXTRA_HEADROOM);
+ fsl_fm_rx_extra_headroom = CONFIG_FSL_FM_RX_EXTRA_HEADROOM;
+ }
+
+ pr_info("Using fsl_fm_rx_extra_headroom=%d from bootargs\n",
+ fsl_fm_rx_extra_headroom);
+
+ return 0;
+}
+
+early_param(FSL_FM_RX_EXTRA_HEADROOM_BOOTARG, fm_set_rx_extra_headroom);
+
+static irqreturn_t fm_irq(int irq, void *_dev)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+ (struct lnx_wrp_fm_dev_t *)_dev;
+
+ if (!p_lnx_wrp_fm_dev || !p_lnx_wrp_fm_dev->h_dev)
+ return IRQ_NONE;
+
+ fm_event_isr(p_lnx_wrp_fm_dev->h_dev);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t fm_err_irq(int irq, void *_dev)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+ (struct lnx_wrp_fm_dev_t *)_dev;
+
+ if (!p_lnx_wrp_fm_dev || !p_lnx_wrp_fm_dev->h_dev)
+ return IRQ_NONE;
+
+ if (fm_error_isr(p_lnx_wrp_fm_dev->h_dev) == 0)
+ return IRQ_HANDLED;
+
+ return IRQ_NONE;
+}
+
+/* used to protect FMD from concurrent calls in functions
+ * fm_mutex_lock / fm_mutex_unlock
+ */
+static struct mutex lnxwrp_mutex;
+
+static struct lnx_wrp_fm_dev_t *create_fm_dev(uint8_t id)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+
+ p_lnx_wrp_fm_dev = kzalloc(sizeof(*p_lnx_wrp_fm_dev), GFP_KERNEL);
+ if (!p_lnx_wrp_fm_dev)
+ return NULL;
+
+ return p_lnx_wrp_fm_dev;
+}
+
+static void destroy_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+ kfree(p_lnx_wrp_fm_dev);
+}
+
+/**
+*find_fman_microcode - find the Fman microcode
+ *
+*This function returns a pointer to the QE Firmware blob that holds
+*the Fman microcode. We use the QE Firmware structure because Fman microcode
+*is similar to QE microcode, so there's no point in defining a new layout.
+ *
+*Current versions of U-Boot embed the Fman firmware into the device tree,
+*so we check for that first. Each Fman node in the device tree contains a
+*node or a pointer to node that holds the firmware. Technically, we should
+*be fetching the firmware node for the current Fman, but we don't have that
+*information any more, so we assume that there is only one firmware node in
+*the device tree, and that all Fmen use the same firmware.
+ */
+static const struct qe_firmware *find_fman_microcode(void)
+{
+ static const struct qe_firmware *p4080_uc_patch;
+ struct device_node *np;
+
+ if (p4080_uc_patch)
+ return p4080_uc_patch;
+
+ /* The firmware should be inside the device tree. */
+ np = of_find_compatible_node(NULL, NULL, "fsl,fman-firmware");
+ if (np) {
+ p4080_uc_patch = of_get_property(np, "fsl,firmware", NULL);
+ of_node_put(np);
+ if (p4080_uc_patch)
+ return p4080_uc_patch;
+
+ pr_info("firmware node is incomplete\n");
+ }
+
+ /* Returning NULL here forces the reuse of the IRAM content */
+ return NULL;
+}
+
+static int fill_qman_channhels_info(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+ p_lnx_wrp_fm_dev->qman_channels = kcalloc(
+ p_lnx_wrp_fm_dev->num_of_qman_channels,
+ sizeof(uint32_t),
+ GFP_KERNEL);
+ if (!p_lnx_wrp_fm_dev->qman_channels)
+ return -ENOMEM;
+
+ if (p_lnx_wrp_fm_dev->fm_rev_info.major_rev >= 6) {
+ p_lnx_wrp_fm_dev->qman_channels[0] = 0x30;
+ p_lnx_wrp_fm_dev->qman_channels[1] = 0x31;
+ p_lnx_wrp_fm_dev->qman_channels[2] = 0x28;
+ p_lnx_wrp_fm_dev->qman_channels[3] = 0x29;
+ p_lnx_wrp_fm_dev->qman_channels[4] = 0x2a;
+ p_lnx_wrp_fm_dev->qman_channels[5] = 0x2b;
+ p_lnx_wrp_fm_dev->qman_channels[6] = 0x2c;
+ p_lnx_wrp_fm_dev->qman_channels[7] = 0x2d;
+ p_lnx_wrp_fm_dev->qman_channels[8] = 0x2;
+ p_lnx_wrp_fm_dev->qman_channels[9] = 0x3;
+ p_lnx_wrp_fm_dev->qman_channels[10] = 0x4;
+ p_lnx_wrp_fm_dev->qman_channels[11] = 0x5;
+ p_lnx_wrp_fm_dev->qman_channels[12] = 0x6;
+ p_lnx_wrp_fm_dev->qman_channels[13] = 0x7;
+ } else {
+ p_lnx_wrp_fm_dev->qman_channels[0] = 0x30;
+ p_lnx_wrp_fm_dev->qman_channels[1] = 0x28;
+ p_lnx_wrp_fm_dev->qman_channels[2] = 0x29;
+ p_lnx_wrp_fm_dev->qman_channels[3] = 0x2a;
+ p_lnx_wrp_fm_dev->qman_channels[4] = 0x2b;
+ p_lnx_wrp_fm_dev->qman_channels[5] = 0x2c;
+ p_lnx_wrp_fm_dev->qman_channels[6] = 0x1;
+ p_lnx_wrp_fm_dev->qman_channels[7] = 0x2;
+ p_lnx_wrp_fm_dev->qman_channels[8] = 0x3;
+ p_lnx_wrp_fm_dev->qman_channels[9] = 0x4;
+ p_lnx_wrp_fm_dev->qman_channels[10] = 0x5;
+ p_lnx_wrp_fm_dev->qman_channels[11] = 0x6;
+ }
+
+ return 0;
+}
+
+#define SVR_SECURITY_MASK 0x00080000
+#define SVR_PERSONALITY_MASK 0x0000FF00
+#define SVR_VER_IGNORE_MASK (SVR_SECURITY_MASK | SVR_PERSONALITY_MASK)
+#define SVR_B4860_REV1_VALUE 0x86800010
+#define SVR_B4860_REV2_VALUE 0x86800020
+
+static struct lnx_wrp_fm_dev_t *read_fm_dev_tree_node(struct platform_device
+ *of_dev)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+ struct device_node *fm_node, *dev_node;
+ struct of_device_id name; /* used temporarily */
+ struct resource res;
+ const uint32_t *uint32_prop;
+ int lenp, err;
+ struct clk *clk;
+ u32 clk_rate;
+ u8 cell_index;
+
+ fm_node = of_node_get(of_dev->dev.of_node);
+
+ uint32_prop =
+ (uint32_t *)of_get_property(fm_node, "cell-index", &lenp);
+ if (unlikely(!uint32_prop)) {
+ pr_err("of_get_property(%s, cell-index) failed\n",
+ fm_node->full_name);
+ goto _return_null;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t)))
+ return NULL;
+
+ cell_index = (u8)*uint32_prop;
+ p_lnx_wrp_fm_dev = create_fm_dev(cell_index);
+ if (!p_lnx_wrp_fm_dev)
+ goto _return_null;
+ p_lnx_wrp_fm_dev->dev = &of_dev->dev;
+ p_lnx_wrp_fm_dev->id = cell_index;
+
+ /* Get the FM interrupt */
+ p_lnx_wrp_fm_dev->irq = of_irq_to_resource(fm_node, 0, NULL);
+ if (unlikely(p_lnx_wrp_fm_dev->irq == /*NO_IRQ */ 0)) {
+ pr_err("of_irq_to_resource() = %d\n", NO_IRQ);
+ goto _return_null;
+ }
+
+ /* Get the FM error interrupt */
+ p_lnx_wrp_fm_dev->err_irq = of_irq_to_resource(fm_node, 1, NULL);
+
+ /* Get the FM address */
+ err = of_address_to_resource(fm_node, 0, &res);
+ if (unlikely(err < 0)) {
+ pr_err("of_address_to_resource() = %d\n", err);
+ goto _return_null;
+ }
+
+ p_lnx_wrp_fm_dev->fm_base_addr = 0;
+ p_lnx_wrp_fm_dev->fm_phys_base_addr = res.start;
+ p_lnx_wrp_fm_dev->fm_mem_size = res.end + 1 - res.start;
+
+ clk = clk_get(p_lnx_wrp_fm_dev->dev,
+ p_lnx_wrp_fm_dev->id == 0 ? "fm0clk" : "fm1clk");
+ if (IS_ERR(clk)) {
+ pr_err("Failed to get FM%d clock structure\n",
+ p_lnx_wrp_fm_dev->id);
+ goto _return_null;
+ }
+
+ clk_rate = clk_get_rate(clk);
+ if (!clk_rate) {
+ pr_err("Failed to determine FM%d clock rate\n",
+ p_lnx_wrp_fm_dev->id);
+ goto _return_null;
+ }
+ /* Rounding to MHz */
+ clk_rate = (clk_rate + 500000) / 1000000;
+ p_lnx_wrp_fm_dev->params.fm_clk_freq = (u16)clk_rate;
+
+ uint32_prop =
+ (uint32_t *)of_get_property(fm_node,
+ "fsl,qman-channel-range",
+ &lenp);
+ if (unlikely(!uint32_prop)) {
+ pr_err("of_get_property(%s, fsl,qman-channel-range) failed\n",
+ fm_node->full_name);
+ goto _return_null;
+ }
+ if (WARN_ON(lenp != sizeof(uint32_t) * 2))
+ goto _return_null;
+ p_lnx_wrp_fm_dev->qman_channel_base = uint32_prop[0];
+ p_lnx_wrp_fm_dev->num_of_qman_channels = uint32_prop[1];
+
+ /* Get the MURAM base address and size */
+ memset(&name, 0, sizeof(name));
+ if (WARN_ON(strlen("muram") >= sizeof(name.name)))
+ goto _return_null;
+ strcpy(name.name, "muram");
+ if (WARN_ON(strlen("fsl,fman-muram") >= sizeof(name.compatible)))
+ goto _return_null;
+ strcpy(name.compatible, "fsl,fman-muram");
+ for_each_child_of_node(fm_node, dev_node) {
+ if (likely(of_match_node(&name, dev_node))) {
+ err = of_address_to_resource(dev_node, 0, &res);
+ if (unlikely(err < 0)) {
+ pr_err("of_address_to_resource() = %d\n",
+ err);
+ goto _return_null;
+ }
+
+ p_lnx_wrp_fm_dev->fm_muram_base_addr = 0;
+ p_lnx_wrp_fm_dev->fm_muram_phys_base_addr = res.start;
+ p_lnx_wrp_fm_dev->fm_muram_mem_size =
+ res.end + 1 - res.start;
+ {
+ /* In B4 rev 2.0 (and above) the MURAM size is
+ * 512KB.
+ * Check the SVR and update MURAM size if
+ * required.
+ */
+ uint32_t svr;
+
+ svr = mfspr(SPRN_SVR);
+
+ if ((svr & ~SVR_VER_IGNORE_MASK) >=
+ SVR_B4860_REV2_VALUE)
+ p_lnx_wrp_fm_dev->fm_muram_mem_size =
+ 0x80000;
+ }
+ }
+ }
+
+ of_node_put(fm_node);
+
+ p_lnx_wrp_fm_dev->active = true;
+
+ goto _return;
+
+_return_null:
+ of_node_put(fm_node);
+ return NULL;
+_return:
+ return p_lnx_wrp_fm_dev;
+}
+
+static void lnxwrp_fm_dev_exceptions_cb(void *h_app,
+ enum fm_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 exception %d\n", exception);
+}
+
+static void lnxwrp_fm_dev_bus_error_cb(void *h_app,
+ enum fm_port_type
+ __maybe_unused port_type,
+ uint8_t __maybe_unused port_id,
+ uint64_t __maybe_unused addr,
+ uint8_t __maybe_unused tnum,
+ uint16_t __maybe_unused liodn)
+{
+ 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);
+}
+
+uint32_t get_qman_channel_id(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev,
+ uint32_t port_id,
+ enum fm_port_type port_type,
+ enum fm_port_speed port_speed)
+{
+ uint32_t qman_channel = 0;
+ int i;
+
+ for (i = 0; i < p_lnx_wrp_fm_dev->num_of_qman_channels; i++) {
+ if (p_lnx_wrp_fm_dev->qman_channels[i] == port_id)
+ break;
+ }
+
+ if (i == p_lnx_wrp_fm_dev->num_of_qman_channels)
+ return 0;
+
+ qman_channel = p_lnx_wrp_fm_dev->qman_channel_base + i;
+
+ return qman_channel;
+}
+
+static int configure_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+ int err;
+
+ if (!p_lnx_wrp_fm_dev->active) {
+ pr_err("FM not configured!\n");
+ return -ENOSYS;
+ }
+
+#ifndef MODULE
+ err = can_request_irq(p_lnx_wrp_fm_dev->irq, 0);
+ if (unlikely(err < 0)) {
+ pr_err("can_request_irq() = %d\n", err);
+ return -ENOSYS;
+ }
+#endif
+ err = devm_request_irq(p_lnx_wrp_fm_dev->dev,
+ p_lnx_wrp_fm_dev->irq,
+ fm_irq,
+ IRQF_NO_SUSPEND,
+ "fman",
+ p_lnx_wrp_fm_dev);
+ if (unlikely(err < 0)) {
+ pr_err("request_irq(%d) = %d\n", p_lnx_wrp_fm_dev->irq,
+ err);
+ return -ENOSYS;
+ }
+
+ if (p_lnx_wrp_fm_dev->err_irq != 0) {
+#ifndef MODULE
+ err = can_request_irq(p_lnx_wrp_fm_dev->err_irq, 0);
+ if (unlikely(err < 0)) {
+ pr_err("can_request_irq() = %d\n", err);
+ return -ENOSYS;
+ }
+#endif
+ err = devm_request_irq(p_lnx_wrp_fm_dev->dev,
+ p_lnx_wrp_fm_dev->err_irq,
+ fm_err_irq,
+ IRQF_SHARED | IRQF_NO_SUSPEND,
+ "fman-err",
+ p_lnx_wrp_fm_dev);
+ if (unlikely(err < 0)) {
+ pr_err("request_irq(%d) = %d\n",
+ p_lnx_wrp_fm_dev->err_irq, err);
+ return -ENOSYS;
+ }
+ }
+
+ p_lnx_wrp_fm_dev->res =
+ devm_request_mem_region(p_lnx_wrp_fm_dev->dev,
+ p_lnx_wrp_fm_dev->fm_phys_base_addr,
+ p_lnx_wrp_fm_dev->fm_mem_size, "fman");
+ if (unlikely(!p_lnx_wrp_fm_dev->res)) {
+ pr_err("request_mem_region() failed\n");
+ return -ENOSYS;
+ }
+
+ p_lnx_wrp_fm_dev->fm_base_addr =
+ PTR_TO_UINT(devm_ioremap
+ (p_lnx_wrp_fm_dev->dev,
+ p_lnx_wrp_fm_dev->fm_phys_base_addr,
+ p_lnx_wrp_fm_dev->fm_mem_size));
+ if (unlikely(p_lnx_wrp_fm_dev->fm_base_addr == 0)) {
+ pr_err("devm_ioremap() failed\n");
+ return -ENOSYS;
+ }
+
+ p_lnx_wrp_fm_dev->params.base_addr = p_lnx_wrp_fm_dev->fm_base_addr;
+ p_lnx_wrp_fm_dev->params.fm_id = p_lnx_wrp_fm_dev->id;
+ p_lnx_wrp_fm_dev->params.f_exception = lnxwrp_fm_dev_exceptions_cb;
+ p_lnx_wrp_fm_dev->params.f_bus_error = lnxwrp_fm_dev_bus_error_cb;
+ p_lnx_wrp_fm_dev->params.h_app = p_lnx_wrp_fm_dev;
+
+ return 0;
+}
+
+static int init_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+ const struct qe_firmware *fw;
+
+ if (!p_lnx_wrp_fm_dev->active) {
+ pr_err("FM not configured!!!\n");
+ return -ENOSYS;
+ }
+
+ p_lnx_wrp_fm_dev->p_muram =
+ fm_muram_init(p_lnx_wrp_fm_dev->fm_muram_phys_base_addr,
+ p_lnx_wrp_fm_dev->fm_muram_mem_size);
+ if (!p_lnx_wrp_fm_dev->p_muram) {
+ pr_err("FM-MURAM!\n");
+ return -ENOSYS;
+ }
+
+ fw = find_fman_microcode();
+
+ if (!fw) {
+ /* this forces the reuse of the current IRAM content */
+ p_lnx_wrp_fm_dev->params.firmware.size = 0;
+ p_lnx_wrp_fm_dev->params.firmware.p_code = NULL;
+ } else {
+ p_lnx_wrp_fm_dev->params.firmware.p_code =
+ (void *)fw + fw->microcode[0].code_offset;
+ p_lnx_wrp_fm_dev->params.firmware.size =
+ sizeof(u32) * fw->microcode[0].count;
+ pr_debug("Loading fman-controller code version %d.%d.%d\n",
+ fw->microcode[0].major, fw->microcode[0].minor,
+ fw->microcode[0].revision);
+ }
+
+ p_lnx_wrp_fm_dev->params.p_muram = p_lnx_wrp_fm_dev->p_muram;
+
+ p_lnx_wrp_fm_dev->h_dev = fm_config(&p_lnx_wrp_fm_dev->params);
+ if (!p_lnx_wrp_fm_dev->h_dev) {
+ pr_err("FM\n");
+ return -ENOSYS;
+ }
+
+ if (fm_get_revision(p_lnx_wrp_fm_dev->h_dev,
+ &p_lnx_wrp_fm_dev->fm_rev_info) != 0) {
+ pr_err("FM\n");
+ return -ENOSYS;
+ }
+
+ if (fm_cfg_reset_on_init(p_lnx_wrp_fm_dev->h_dev, true) != 0) {
+ pr_err("FM\n");
+ return -ENOSYS;
+ }
+ /* Config fm_cfg_dma_aid_override for P1023 */
+ if (p_lnx_wrp_fm_dev->fm_rev_info.major_rev == 4)
+ if (fm_cfg_dma_aid_override(p_lnx_wrp_fm_dev->h_dev,
+ true) != 0) {
+ pr_err("FM\n");
+ return -ENOSYS;
+ }
+ /* Config total fifo size for FManV3H */
+ if ((p_lnx_wrp_fm_dev->fm_rev_info.major_rev >= 6) &&
+ (p_lnx_wrp_fm_dev->fm_rev_info.minor_rev != 1 &&
+ p_lnx_wrp_fm_dev->fm_rev_info.minor_rev != 4))
+ fm_cfg_total_fifo_size(p_lnx_wrp_fm_dev->h_dev,
+ 295 * 1024);
+
+ if (fm_init(p_lnx_wrp_fm_dev->h_dev) != 0) {
+ pr_err("FM\n");
+ return -ENOSYS;
+ }
+
+ /* 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,
+ FM_EX_DMA_BUS_ERROR, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_DMA_READ_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_DMA_SYSTEM_WRITE_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_DMA_FM_WRITE_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_DMA_SINGLE_PORT_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_FPM_STALL_ON_TASKS, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_FPM_SINGLE_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_FPM_DOUBLE_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_QMI_SINGLE_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_QMI_DOUBLE_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_BMI_LIST_RAM_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_BMI_STORAGE_PROFILE_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_BMI_STATISTICS_RAM_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev,
+ FM_EX_BMI_DISPATCH_RAM_ECC, false);
+ fm_set_exception(p_lnx_wrp_fm_dev->h_dev, FM_EX_IRAM_ECC,
+ false);
+ /* TODO: _fm_disable_rams_ecc assert for rams_ecc_owners.
+ * fm_set_exception(p_lnx_wrp_fm_dev->h_dev,FM_EX_MURAM_ECC,
+ * false);
+ */
+ }
+
+ if (unlikely(fill_qman_channhels_info(p_lnx_wrp_fm_dev) < 0)) {
+ pr_err("can't fill qman channel info\n");
+ return -ENOSYS;
+ }
+
+ return 0;
+}
+
+static void free_fm_dev(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev)
+{
+ if (!p_lnx_wrp_fm_dev->active)
+ return;
+
+ if (p_lnx_wrp_fm_dev->h_dev)
+ fm_free(p_lnx_wrp_fm_dev->h_dev);
+
+ if (p_lnx_wrp_fm_dev->p_muram)
+ fm_muram_free(p_lnx_wrp_fm_dev->p_muram);
+
+ devm_iounmap(p_lnx_wrp_fm_dev->dev,
+ UINT_TO_PTR(p_lnx_wrp_fm_dev->fm_base_addr));
+ devm_release_mem_region(p_lnx_wrp_fm_dev->dev,
+ p_lnx_wrp_fm_dev->fm_phys_base_addr,
+ p_lnx_wrp_fm_dev->fm_mem_size);
+ if (p_lnx_wrp_fm_dev->err_irq != 0) {
+ devm_free_irq(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev->err_irq,
+ p_lnx_wrp_fm_dev);
+ }
+
+ devm_free_irq(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev->irq,
+ p_lnx_wrp_fm_dev);
+}
+
+/* FMan character device file operations */
+static const struct file_operations fm_fops;
+
+static int /*__devinit*/ fm_probe(struct platform_device *of_dev)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+
+ p_lnx_wrp_fm_dev = read_fm_dev_tree_node(of_dev);
+ if (!p_lnx_wrp_fm_dev)
+ return -EIO;
+ if (configure_fm_dev(p_lnx_wrp_fm_dev) != 0)
+ return -EIO;
+ if (init_fm_dev(p_lnx_wrp_fm_dev) != 0)
+ return -EIO;
+
+ dev_set_drvdata(p_lnx_wrp_fm_dev->dev, p_lnx_wrp_fm_dev);
+
+ pr_debug("FM%d probed\n", p_lnx_wrp_fm_dev->id);
+
+ return 0;
+}
+
+static int fm_remove(struct platform_device *of_dev)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev;
+ struct device *dev;
+
+ dev = &of_dev->dev;
+ p_lnx_wrp_fm_dev = dev_get_drvdata(dev);
+
+ free_fm_dev(p_lnx_wrp_fm_dev);
+
+ destroy_fm_dev(p_lnx_wrp_fm_dev);
+
+ dev_set_drvdata(dev, NULL);
+
+ return 0;
+}
+
+static const struct of_device_id fm_match[] = {
+ {
+ .compatible = "fsl,fman"},
+ {}
+};
+
+#ifndef MODULE
+MODULE_DEVICE_TABLE(of, fm_match);
+#endif /* !MODULE */
+
+static struct platform_driver fm_driver = {
+ .driver = {
+ .name = "fsl-fman",
+ .of_match_table = fm_match,
+ .owner = THIS_MODULE,
+ },
+ .probe = fm_probe,
+ .remove = fm_remove
+};
+
+void *lnxwrp_fm_init(void)
+{
+ memset(&lnx_wrp_fm, 0, sizeof(lnx_wrp_fm));
+ mutex_init(&lnxwrp_mutex);
+
+ /* Register to the DTB for basic FM API */
+ platform_driver_register(&fm_driver);
+
+ return &lnx_wrp_fm;
+}
+
+int lnxwrp_fm_free(void *h_lnx_wrp_fm)
+{
+ platform_driver_unregister(&fm_driver);
+ mutex_destroy(&lnxwrp_mutex);
+
+ return 0;
+}
+
+struct fm *fm_bind(struct device *fm_dev)
+{
+ return (struct fm *)(dev_get_drvdata(get_device(fm_dev)));
+}
+EXPORT_SYMBOL(fm_bind);
+
+void fm_unbind(struct fm *fm)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+ (struct lnx_wrp_fm_dev_t *)fm;
+
+ put_device(p_lnx_wrp_fm_dev->dev);
+}
+EXPORT_SYMBOL(fm_unbind);
+
+struct resource *fm_get_mem_region(struct fm *fm)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+ (struct lnx_wrp_fm_dev_t *)fm;
+
+ return p_lnx_wrp_fm_dev->res;
+}
+EXPORT_SYMBOL(fm_get_mem_region);
+
+void *fm_get_handle(struct fm *fm)
+{
+ struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev =
+ (struct lnx_wrp_fm_dev_t *)fm;
+
+ return (void *)p_lnx_wrp_fm_dev->h_dev;
+}
+EXPORT_SYMBOL(fm_get_handle);
+
+
+void fm_mutex_lock(void)
+{
+ mutex_lock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_lock);
+
+void fm_mutex_unlock(void)
+{
+ mutex_unlock(&lnxwrp_mutex);
+}
+EXPORT_SYMBOL(fm_mutex_unlock);
+
+static void *h_fm_lnx_wrp;
+
+static int __init __cold fm_load(void)
+{
+ h_fm_lnx_wrp = lnxwrp_fm_init();
+ if (!h_fm_lnx_wrp) {
+ pr_err("Failed to init FM wrapper!\n");
+ return -ENODEV;
+ }
+
+ pr_info("Freescale FM module\n");
+ return 0;
+}
+
+static void __exit __cold fm_unload(void)
+{
+ if (h_fm_lnx_wrp)
+ lnxwrp_fm_free(h_fm_lnx_wrp);
+}
+
+module_init(fm_load);
+module_exit(fm_unload);
diff --git a/drivers/net/ethernet/freescale/fman/fm_drv.h b/drivers/net/ethernet/freescale/fman/fm_drv.h
new file mode 100644
index 0000000..de69965
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/fm_drv.h
@@ -0,0 +1,121 @@
+/*
+ * 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_DRV_H__
+#define __FM_DRV_H__
+
+#include "service.h"
+#include "fsl_fman_drv.h"
+
+#ifndef CONFIG_FSL_FM_MAX_FRAME_SIZE
+#define CONFIG_FSL_FM_MAX_FRAME_SIZE 0
+#endif
+
+#ifndef CONFIG_FSL_FM_RX_EXTRA_HEADROOM
+#define CONFIG_FSL_FM_RX_EXTRA_HEADROOM 16
+#endif
+
+/* SoC info */
+#define SOC_VERSION(svr) (((svr) & 0xFFF7FF00) >> 8)
+#define SOC_MAJOR_REV(svr) (((svr) & 0x000000F0) >> 4)
+#define SOC_MINOR_REV(svr) ((svr) & 0x0000000F)
+
+/* Port defines */
+#define NUM_OF_FM_PORTS 63
+#define FIRST_OP_PORT(major) (major >= 6 ? 0x02 : 0x01)
+#define FIRST_RX_PORT 0x08
+#define FIRST_TX_PORT 0x28
+#define LAST_OP_PORT 0x07
+#define LAST_RX_PORT 0x11
+#define LAST_TX_PORT 0x31
+
+#define TX_10G_PORT_BASE 0x30
+#define RX_10G_PORT_BASE 0x10
+
+struct lnx_wrp_fm_port_dev_t {
+ uint8_t id;
+ char name[20];
+ bool active;
+ uint64_t phys_base_addr;
+ uint64_t base_addr; /* Port's *virtual* address */
+ resource_size_t mem_size;
+ struct fm_buffer_prefix_content_t buff_prefix_content;
+ void *h_dev;
+ void *h_lnx_wrp_fm_dev;
+ uint16_t tx_ch;
+ struct device *dev;
+ struct device_attribute *dev_attr_stats;
+ struct device_attribute *dev_attr_regs;
+ struct device_attribute *dev_attr_bmi_regs;
+ struct device_attribute *dev_attr_qmi_regs;
+ struct device_attribute *dev_attr_ipv4_opt;
+
+ struct fm_revision_info_t fm_rev_info;
+};
+
+struct lnx_wrp_fm_dev_t {
+ uint8_t id;
+ char name[10];
+ bool active;
+ uint64_t fm_phys_base_addr;
+ uint64_t fm_base_addr;
+ resource_size_t fm_mem_size;
+ phys_addr_t fm_muram_phys_base_addr;
+ uint64_t fm_muram_base_addr;
+ resource_size_t fm_muram_mem_size;
+ int irq;
+ int err_irq;
+ struct fm_params_t params;
+ void *h_dev;
+ struct muram_info *p_muram;
+
+ struct lnx_wrp_fm_port_dev_t ports[NUM_OF_FM_PORTS];
+
+ struct device *dev;
+ struct resource *res;
+
+ struct fm_revision_info_t fm_rev_info;
+ uint32_t qman_channel_base;
+ uint32_t num_of_qman_channels;
+ uint32_t *qman_channels;
+
+};
+
+struct lnx_wrp_fm_t {
+ struct lnx_wrp_fm_dev_t *p_fm_devs[INTG_MAX_NUM_OF_FM];
+};
+
+uint32_t get_qman_channel_id(struct lnx_wrp_fm_dev_t *p_lnx_wrp_fm_dev,
+ uint32_t port_id,
+ enum fm_port_type port_type,
+ enum fm_port_speed port_speed);
+#endif /* __FM_DRV_H__ */
diff --git a/drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h b/drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h
new file mode 100644
index 0000000..6630cbf
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/dpaa_ext.h
@@ -0,0 +1,253 @@
+/*
+ * 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.
+ */
+
+/* DPAA Application Programming Interface.*/
+#ifndef __DPAA_EXT_H
+#define __DPAA_EXT_H
+
+#include "service.h"
+
+/* DPAA_grp Data Path Acceleration Architecture API
+ * DPAA API functions, definitions and enums.
+ */
+
+/*Frame descriptor*/
+struct dpaa_fd_t {
+ uint32_t id; /* FD id */
+ uint32_t addrl; /* Data Address */
+ uint32_t length; /* Frame length */
+ uint32_t status; /* FD status */
+} __attribute__((__packed__));
+
+/*enum for defining frame format
+ */
+enum dpaa_fd_format_type {
+ /* Simple frame Single buffer; Offset and
+ * small length (9b OFFSET, 20b LENGTH)
+ */
+ DPAA_FD_FORMAT_TYPE_SHORT_SBSF = 0x0,
+ /* Simple frame, single buffer; big length
+ * (29b LENGTH ,No OFFSET)
+ */
+ DPAA_FD_FORMAT_TYPE_LONG_SBSF = 0x2,
+ /* Simple frame, Scatter Gather table; Offset
+ * and small length (9b OFFSET, 20b LENGTH)
+ */
+ DPAA_FD_FORMAT_TYPE_SHORT_MBSF = 0x4,
+ /* Simple frame, Scatter Gather table;
+ * big length (29b LENGTH ,No OFFSET)
+ */
+ DPAA_FD_FORMAT_TYPE_LONG_MBSF = 0x6,
+ /* Compound Frame (29b CONGESTION-WEIGHT
+ * No LENGTH or OFFSET)
+ */
+ e_DPAA_FD_FORMAT_TYPE_COMPOUND = 0x1,
+ DPAA_FD_FORMAT_TYPE_DUMMY
+};
+
+/* Frame descriptor macros */
+#define DPAA_FD_DD_MASK 0xc0000000 /* FD DD field mask */
+#define DPAA_FD_PID_MASK 0x3f000000 /* FD PID field mask */
+#define DPAA_FD_ELIODN_MASK 0x0000f000 /* FD ELIODN field mask */
+#define DPAA_FD_BPID_MASK 0x00ff0000 /* FD BPID field mask */
+#define DPAA_FD_ADDRH_MASK 0x000000ff /* FD ADDRH field mask */
+#define DPAA_FD_ADDRL_MASK 0xffffffff /* FD ADDRL field mask */
+#define DPAA_FD_FORMAT_MASK 0xe0000000 /* FD FORMAT field mask */
+#define DPAA_FD_OFFSET_MASK 0x1ff00000 /* FD OFFSET field mask */
+#define DPAA_FD_LENGTH_MASK 0x000fffff /* FD LENGTH field mask */
+
+/* Macro to get FD DD field */
+#define DPAA_FD_GET_DD(fd) \
+ ((((struct dpaa_fd_t *)fd)->id & DPAA_FD_DD_MASK) >> (31 - 1))
+/* Macro to get FD PID field */
+#define DPAA_FD_GET_PID(fd) \
+ (((((struct dpaa_fd_t *)fd)->id & DPAA_FD_PID_MASK) >> (31 - 7)) | \
+ ((((struct dpaa_fd_t *)fd)->id & DPAA_FD_ELIODN_MASK) >> \
+ (31 - 19 - 6)))
+ /* Macro to get FD BPID field */
+#define DPAA_FD_GET_BPID(fd) \
+ ((((struct dpaa_fd_t *)fd)->id & DPAA_FD_BPID_MASK) >> (31 - 15))
+ /* Macro to get FD ADDRH field */
+#define DPAA_FD_GET_ADDRH(fd) \
+ (((struct dpaa_fd_t *)fd)->id & DPAA_FD_ADDRH_MASK)
+/* Macro to get FD ADDRL field */
+#define DPAA_FD_GET_ADDRL(fd) \
+ (((struct dpaa_fd_t *)fd)->addrl)
+/* Macro to get FD ADDR field */
+#define DPAA_FD_GET_PHYS_ADDR(fd) \
+ ((phys_address_t)(((uint64_t)DPAA_FD_GET_ADDRH(fd) << 32) | \
+ (uint64_t)DPAA_FD_GET_ADDRL(fd)))
+/* Macro to get FD FORMAT field */
+#define DPAA_FD_GET_FORMAT(fd) \
+ ((((struct dpaa_fd_t *)fd)->length & DPAA_FD_FORMAT_MASK) >> (31 - 2))
+/* Macro to get FD OFFSET field */
+#define DPAA_FD_GET_OFFSET(fd) \
+ ((((struct dpaa_fd_t *)fd)->length & DPAA_FD_OFFSET_MASK) >> (31 - 11))
+/* Macro to get FD LENGTH field */
+#define DPAA_FD_GET_LENGTH(fd) \
+ (((struct dpaa_fd_t *)fd)->length & DPAA_FD_LENGTH_MASK)
+/* Macro to get FD STATUS field */
+#define DPAA_FD_GET_STATUS(fd) \
+ (((struct dpaa_fd_t *)fd)->status)
+/* Macro to set FD DD field */
+#define DPAA_FD_SET_DD(fd, val) \
+ (((struct dpaa_fd_t *)fd)->id = \
+ ((((struct dpaa_fd_t *)fd)->id & ~DPAA_FD_DD_MASK) | \
+ (((val) << (31 - 1)) & DPAA_FD_DD_MASK)))
+/* Macro to set FD PID field or LIODN offset*/
+#define DPAA_FD_SET_PID(fd, val) \
+ (((struct dpaa_fd_t *)fd)->id = \
+ ((((struct dpaa_fd_t *)fd)->id & \
+ ~(DPAA_FD_PID_MASK | DPAA_FD_ELIODN_MASK)) | \
+ ((((val) << (31 - 7)) & DPAA_FD_PID_MASK) | \
+ ((((val) >> 6) << (31 - 19)) & DPAA_FD_ELIODN_MASK))))
+/* Macro to set FD BPID field */
+#define DPAA_FD_SET_BPID(fd, val) \
+ (((struct dpaa_fd_t *)fd)->id = \
+ ((((struct dpaa_fd_t *)fd)->id & ~DPAA_FD_BPID_MASK) | \
+ (((val) << (31 - 15)) & DPAA_FD_BPID_MASK)))
+/* Macro to set FD ADDRH field */
+#define DPAA_FD_SET_ADDRH(fd, val) \
+ (((struct dpaa_fd_t *)fd)->id = \
+ ((((struct dpaa_fd_t *)fd)->id & ~DPAA_FD_ADDRH_MASK) | \
+ ((val) & DPAA_FD_ADDRH_MASK)))
+/* Macro to set FD ADDRL field */
+#define DPAA_FD_SET_ADDRL(fd, val) (((struct dpaa_fd_t *)fd)->addrl = (val))
+/* Macro to set FD FORMAT field */
+#define DPAA_FD_SET_FORMAT(fd, val) \
+ (((struct dpaa_fd_t *)fd)->length = \
+ ((((struct dpaa_fd_t *)fd)->length & ~DPAA_FD_FORMAT_MASK) | \
+ (((val) << (31 - 2)) & DPAA_FD_FORMAT_MASK)))
+/* Macro to set FD OFFSET field */
+#define DPAA_FD_SET_OFFSET(fd, val) \
+ (((struct dpaa_fd_t *)fd)->length = \
+ ((((struct dpaa_fd_t *)fd)->length & ~DPAA_FD_OFFSET_MASK) | \
+ (((val) << (31 - 11)) & DPAA_FD_OFFSET_MASK)))
+/* Macro to set FD LENGTH field */
+#define DPAA_FD_SET_LENGTH(fd, val) \
+ (((struct dpaa_fd_t *)fd)->length = \
+ (((struct dpaa_fd_t *)fd)->length & ~DPAA_FD_LENGTH_MASK) | \
+ ((val) & DPAA_FD_LENGTH_MASK))
+/* Macro to set FD STATUS field */
+#define DPAA_FD_SET_STATUS(fd, val) (((struct dpaa_fd_t *)fd)->status = (val))
+
+/* Frame Scatter/Gather Table Entry */
+struct dpaa_sgte_t {
+ uint32_t addrh; /* Buffer Address high */
+ uint32_t addrl; /* Buffer Address low */
+ uint32_t length; /* Buffer length */
+ uint32_t offset; /* SGTE offset */
+} __attribute__((__packed__));
+
+#define DPAA_NUM_OF_SG_TABLE_ENTRY 16
+
+/* Frame Scatter/Gather Table Entry macros */
+/* SGTE ADDRH field mask */
+#define DPAA_SGTE_ADDRH_MASK 0x000000ff
+/* SGTE ADDRL field mask */
+#define DPAA_SGTE_ADDRL_MASK 0xffffffff
+/* SGTE Extension field mask */
+#define DPAA_SGTE_E_MASK 0x80000000
+/* SGTE Final field mask */
+#define DPAA_SGTE_F_MASK 0x40000000
+/* SGTE LENGTH field mask */
+#define DPAA_SGTE_LENGTH_MASK 0x3fffffff
+/* SGTE BPID field mask */
+#define DPAA_SGTE_BPID_MASK 0x00ff0000
+/* SGTE OFFSET field mask */
+#define DPAA_SGTE_OFFSET_MASK 0x00001fff
+/* Macro to get SGTE ADDRH field */
+#define DPAA_SGTE_GET_ADDRH(sgte) \
+(((struct dpaa_sgte_t *)sgte)->addrh & DPAA_SGTE_ADDRH_MASK)
+/* Macro to get SGTE ADDRL field */
+#define DPAA_SGTE_GET_ADDRL(sgte) (((struct dpaa_sgte_t *)sgte)->addrl)
+/* Macro to get FD ADDR field */
+#define DPAA_SGTE_GET_PHYS_ADDR(sgte) \
+ ((phys_address_t)(((uint64_t)DPAA_SGTE_GET_ADDRH(sgte) << 32) | \\
+ (uint64_t)DPAA_SGTE_GET_ADDRL(sgte)))
+/* Macro to get SGTE EXTENSION field */
+#define DPAA_SGTE_GET_EXTENSION(sgte) \
+ ((((struct dpaa_sgte_t *)sgte)->length & \
+ DPAA_SGTE_E_MASK) >> (31 - 0))
+/* Macro to get SGTE FINAL field */
+#define DPAA_SGTE_GET_FINAL(sgte) \
+ ((((struct dpaa_sgte_t *)sgte)->length & \
+ DPAA_SGTE_F_MASK) >> (31 - 1))
+/* Macro to get SGTE LENGTH field */
+#define DPAA_SGTE_GET_LENGTH(sgte) \
+ (((struct dpaa_sgte_t *)sgte)->length & DPAA_SGTE_LENGTH_MASK)
+/* Macro to get SGTE BPID field */
+#define DPAA_SGTE_GET_BPID(sgte) \
+ ((((struct dpaa_sgte_t *)sgte)->offset & \
+ DPAA_SGTE_BPID_MASK) >> (31 - 15))
+/* Macro to get SGTE OFFSET field */
+#define DPAA_SGTE_GET_OFFSET(sgte) \
+ (((struct dpaa_sgte_t *)sgte)->offset & DPAA_SGTE_OFFSET_MASK)
+/* Macro to set SGTE ADDRH field */
+#define DPAA_SGTE_SET_ADDRH(sgte, val) \
+ (((struct dpaa_sgte_t *)sgte)->addrh = \
+ ((((struct dpaa_sgte_t *)sgte)->addrh & ~DPAA_SGTE_ADDRH_MASK) | \
+ ((val) & DPAA_SGTE_ADDRH_MASK)))
+/* Macro to set SGTE ADDRL field */
+#define DPAA_SGTE_SET_ADDRL(sgte, val) \
+ (((struct dpaa_sgte_t *)sgte)->addrl = (val))
+/* Macro to set SGTE EXTENSION field */
+#define DPAA_SGTE_SET_EXTENSION(sgte, val) \
+ (((struct dpaa_sgte_t *)sgte)->length = \
+ ((((struct dpaa_sgte_t *)sgte)->length & ~DPAA_SGTE_E_MASK) | \
+ (((val) << (31 - 0)) & DPAA_SGTE_E_MASK)))
+/* Macro to set SGTE FINAL field */
+#define DPAA_SGTE_SET_FINAL(sgte, val) \
+ (((struct dpaa_sgte_t *)sgte)->length = \
+ ((((struct dpaa_sgte_t *)sgte)->length & ~DPAA_SGTE_F_MASK) | \
+ (((val) << (31 - 1)) & DPAA_SGTE_F_MASK)))
+/* Macro to set SGTE LENGTH field */
+#define DPAA_SGTE_SET_LENGTH(sgte, val) \
+ (((struct dpaa_sgte_t *)sgte)->length = \
+ (((struct dpaa_sgte_t *)sgte)->length & ~DPAA_SGTE_LENGTH_MASK) | \
+ ((val) & DPAA_SGTE_LENGTH_MASK))
+/* Macro to set SGTE BPID field */
+#define DPAA_SGTE_SET_BPID(sgte, val) \
+ (((struct dpaa_sgte_t *)sgte)->offset = \
+ ((((struct dpaa_sgte_t *)sgte)->offset & ~DPAA_SGTE_BPID_MASK) | \
+ (((val) << (31 - 15)) & DPAA_SGTE_BPID_MASK)))
+/* Macro to set SGTE OFFSET field */
+#define DPAA_SGTE_SET_OFFSET(sgte, val) \
+ (((struct dpaa_sgte_t *)sgte)->offset = \
+ ((((struct dpaa_sgte_t *)sgte)->offset & ~DPAA_SGTE_OFFSET_MASK) | \
+ (((val) << (31 - 31)) & DPAA_SGTE_OFFSET_MASK)))
+
+#define DPAA_LIODN_DONT_OVERRIDE (-1)
+
+/* end of DPAA_grp group */
+
+#endif /* __DPAA_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h b/drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h
new file mode 100644
index 0000000..6adf122
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/dpaa_integration_ext.h
@@ -0,0 +1,120 @@
+/*
+ * 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 __DPAA_INTEGRATION_EXT_H
+#define __DPAA_INTEGRATION_EXT_H
+
+/* FM HW DEFINITIONS */
+#define INTG_MAX_NUM_OF_FM 2
+
+#define FM_MAX_NUM_OF_1G_RX_PORTS 6
+#define FM_MAX_NUM_OF_10G_RX_PORTS 2
+#define FM_MAX_NUM_OF_RX_PORTS \
+ (FM_MAX_NUM_OF_1G_RX_PORTS + FM_MAX_NUM_OF_10G_RX_PORTS)
+
+#define FM_MAX_NUM_OF_1G_TX_PORTS 6
+#define FM_MAX_NUM_OF_10G_TX_PORTS 2
+#define FM_MAX_NUM_OF_TX_PORTS \
+ (FM_MAX_NUM_OF_1G_TX_PORTS + FM_MAX_NUM_OF_10G_TX_PORTS)
+
+#define FM_MAX_NUM_OF_OH_PORTS 7
+
+#define FM_MAX_NUM_OF_MACS 10
+
+/* BMan INTEGRATION-SPECIFIC DEFINITIONS */
+#define BM_MAX_NUM_OF_POOLS 64
+/**< Number of buffers pools */
+
+/* RTC defines */
+#define FM_RTC_NUM_OF_ALARMS 2
+/**< RTC number of alarms */
+#define FM_RTC_NUM_OF_PERIODIC_PULSES 3
+/**< RTC number of periodic pulses */
+#define FM_RTC_NUM_OF_EXT_TRIGGERS 2
+/**< RTC number of external triggers */
+
+#define FM_PORT_MAX_NUM_OF_EXT_POOLS 8
+/**< Number of external BM pools per Rx port */
+
+#define FM_LOW_END_RESTRICTION
+/**< prevents the use of TX port 1 with OP port 0
+ * for FM_IP_BLOCK Major Rev 4 (P1023)
+ */
+
+/* FPM defines */
+#define FM_NUM_OF_FMAN_CTRL_EVENT_REGS 4
+
+/* Uniqe defines */
+#define FM_QMI_NO_ECC_EXCEPTIONS /* P1 */
+#define FM_CSI_CFED_LIMIT /* P1 */
+#define FM_PEDANTIC_DMA /* P1 */
+#define FM_QMI_NO_DEQ_OPTIONS_SUPPORT /* P1 */
+#define FM_HAS_TOTAL_DMAS /* P1-P5 */
+#define FM_DEQ_PIPELINE_PARAMS_FOR_OP /* P1, T/B */
+#define FM_NO_DISPATCH_RAM_ECC /* P2-P5 */
+#define FM_NO_WATCHDOG /* P4 */
+#define FM_NO_TNUM_AGING /* P2-P5 */
+#define FM_NO_BACKUP_POOLS /* P2-P5 */
+#define FM_NO_OP_OBSERVED_POOLS /* P2-P5, T/B */
+#define FM_NO_ADVANCED_RATE_LIMITER /* P2-P5 */
+#define FM_OP_OPEN_DMA_MIN_LIMIT /* T/B */
+#define FM_NO_RESTRICT_ON_ACCESS_RSRC /* T/B */
+#define FM_FRAME_END_PARAMS_FOR_OP /* T/B */
+#define FM_QMI_NO_SINGLE_ECC_EXCEPTION /* T/B */
+
+/* FMan errata */
+#define FM_RX_PREAM_4_ERRATA_DTSEC_A001 /* Dtsec */
+#define FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 /* Dtsec */
+#define FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 /* Tgec */
+#define FM_ECC_HALT_NO_SYNC_ERRATA_10GMAC_A008 /* P2-P5 */
+#define FM_GRS_ERRATA_DTSEC_A002 /* P4080 */
+#define FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 /* P4080 */
+#define FM_GTS_ERRATA_DTSEC_A004 /* P4080 */
+#define FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012 /* P4080 */
+#define FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 /* P2-P5 */
+#define FM_TX_LOCKUP_ERRATA_DTSEC6 /* P4080 */
+#define FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 /* P2-P5 */
+#define FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 /* P4080 */
+#define FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 /* P2-P5 */
+#define FM_LEN_CHECK_ERRATA_FMAN_SW002 /* P2-P5, T/B */
+#define FM_HEAVY_TRAFFIC_HANG_ERRATA_FMAN_A005669 /* T/B */
+#define FM_WRONG_RESET_VALUES_ERRATA_FMAN_A005127 /* T/B */
+#define FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 /* mEMAC */
+#define FM_HEAVY_TRAFFIC_SEQUENCER_HANG_ERRATA_FMAN_A006981 /* T4/B4 rev1 */
+#define FM_AID_MODE_NO_TNUM_SW005
+/* refer to pdm TKT068794 - only support of port_id on aid - T/B */
+#define FM_ERROR_VSP_NO_MATCH_SW006
+/* refer to pdm TKT174304 - no match between errorQ and VSP - T/B */
+#define FM_TX_INVALID_ECC_ERRATA_10GMAC_A009 /* P2-P5 */
+#define FM_BCB_ERRATA_BMI_SW001 /* T/B */
+
+#endif /* __DPAA_INTEGRATION_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/enet_ext.h b/drivers/net/ethernet/freescale/fman/inc/enet_ext.h
new file mode 100644
index 0000000..cfade84
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/enet_ext.h
@@ -0,0 +1,199 @@
+/*
+ * 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.
+ */
+
+/* Ethernet generic definitions and enums. */
+
+#ifndef __ENET_EXT_H
+#define __ENET_EXT_H
+
+#include "fsl_enet.h"
+
+/* Number of octets (8-bit bytes) in an ethernet address */
+#define ENET_NUM_OCTETS_PER_ADDRESS 6
+/* Group address mask for ethernet addresses */
+#define ENET_GROUP_ADDR 0x01
+
+/* Ethernet Address */
+typedef uint8_t enet_addr_t[ENET_NUM_OCTETS_PER_ADDRESS];
+
+/* Ethernet MAC-PHY Interface */
+enum ethernet_interface {
+ ENET_IF_MII = E_ENET_IF_MII, /* MII interface */
+ ENET_IF_RMII = E_ENET_IF_RMII, /* RMII interface */
+ ENET_IF_SMII = E_ENET_IF_SMII, /* SMII interface */
+ ENET_IF_GMII = E_ENET_IF_GMII, /* GMII interface */
+ ENET_IF_RGMII = E_ENET_IF_RGMII,
+ /* RGMII interface */
+ ENET_IF_TBI = E_ENET_IF_TBI, /* TBI interface */
+ ENET_IF_RTBI = E_ENET_IF_RTBI, /* RTBI interface */
+ ENET_IF_SGMII = E_ENET_IF_SGMII,
+ /* SGMII interface */
+ ENET_IF_XGMII = E_ENET_IF_XGMII,
+ /* XGMII interface */
+ ENET_IF_QSGMII = E_ENET_IF_QSGMII,
+ /* QSGMII interface */
+ ENET_IF_XFI = E_ENET_IF_XFI /* XFI interface */
+};
+
+/* SGMII/QSGII interface with 1000BaseX auto-negotiation between MAC and phy
+ * or backplane; Note: 1000BaseX auto-negotiation relates only to interface
+ * between MAC and phy/backplane, SGMII phy can still synchronize with far-end
+ * phy at 10Mbps, 100Mbps or 1000Mbps
+ */
+#define ENET_IF_SGMII_BASEX 0x80000000
+
+/* Ethernet Speed (nominal data rate) */
+enum ethernet_speed {
+ ENET_SPEED_10 = E_ENET_SPEED_10, /* 10 Mbps */
+ ENET_SPEED_100 = E_ENET_SPEED_100, /* 100 Mbps */
+ ENET_SPEED_1000 = E_ENET_SPEED_1000, /* 1000 Mbps = 1 Gbps */
+ ENET_SPEED_10000 = E_ENET_SPEED_10000 /* 10000 Mbps = 10 Gbps */
+};
+
+/* Ethernet mode (combination of MAC-PHY interface and speed) */
+enum e_enet_mode {
+ ENET_MODE_INVALID = 0, /* Invalid Ethernet mode */
+ /* 10 Mbps MII */
+ ENET_MODE_MII_10 = (ENET_IF_MII | ENET_SPEED_10),
+ /* 100 Mbps MII */
+ ENET_MODE_MII_100 = (ENET_IF_MII | ENET_SPEED_100),
+ /* 10 Mbps RMII */
+ ENET_MODE_RMII_10 = (ENET_IF_RMII | ENET_SPEED_10),
+ /* 100 Mbps RMII */
+ ENET_MODE_RMII_100 = (ENET_IF_RMII | ENET_SPEED_100),
+ /* 10 Mbps SMII */
+ ENET_MODE_SMII_10 = (ENET_IF_SMII | ENET_SPEED_10),
+ /* 100 Mbps SMII */
+ ENET_MODE_SMII_100 = (ENET_IF_SMII | ENET_SPEED_100),
+ /* 1000 Mbps GMII */
+ ENET_MODE_GMII_1000 = (ENET_IF_GMII | ENET_SPEED_1000),
+ /* 10 Mbps RGMII */
+ ENET_MODE_RGMII_10 = (ENET_IF_RGMII | ENET_SPEED_10),
+ /* 100 Mbps RGMII */
+ ENET_MODE_RGMII_100 = (ENET_IF_RGMII | ENET_SPEED_100),
+ /* 1000 Mbps RGMII */
+ ENET_MODE_RGMII_1000 = (ENET_IF_RGMII | ENET_SPEED_1000),
+ /* 1000 Mbps TBI */
+ ENET_MODE_TBI_1000 = (ENET_IF_TBI | ENET_SPEED_1000),
+ /* 1000 Mbps RTBI */
+ ENET_MODE_RTBI_1000 = (ENET_IF_RTBI | ENET_SPEED_1000),
+ /* 10 Mbps SGMII with auto-negotiation between MAC and
+ * SGMII phy according to Cisco SGMII specification
+ */
+ ENET_MODE_SGMII_10 = (ENET_IF_SGMII | ENET_SPEED_10),
+ /* 100 Mbps SGMII with auto-negotiation between MAC and
+ * SGMII phy according to Cisco SGMII specification
+ */
+ ENET_MODE_SGMII_100 = (ENET_IF_SGMII | ENET_SPEED_100),
+ /* 1000 Mbps SGMII with auto-negotiation between MAC and
+ * SGMII phy according to Cisco SGMII specification
+ */
+ ENET_MODE_SGMII_1000 = (ENET_IF_SGMII | ENET_SPEED_1000),
+ /* 10 Mbps SGMII with 1000BaseX auto-negotiation between
+ * MAC and SGMII phy or backplane
+ */
+ ENET_MODE_SGMII_BASEX_10 =
+ (ENET_IF_SGMII_BASEX | ENET_IF_SGMII | ENET_SPEED_10),
+ /* 100 Mbps SGMII with 1000BaseX auto-negotiation between
+ * MAC and SGMII phy or backplane
+ */
+ ENET_MODE_SGMII_BASEX_100 =
+ (ENET_IF_SGMII_BASEX | ENET_IF_SGMII | ENET_SPEED_100),
+ /* 1000 Mbps SGMII with 1000BaseX auto-negotiation between
+ * MAC and SGMII phy or backplane
+ */
+ ENET_MODE_SGMII_BASEX_1000 =
+ (ENET_IF_SGMII_BASEX | ENET_IF_SGMII | ENET_SPEED_1000),
+ /* 1000 Mbps QSGMII with auto-negotiation between MAC and
+ * QSGMII phy according to Cisco QSGMII specification
+ */
+ ENET_MODE_QSGMII_1000 = (ENET_IF_QSGMII | ENET_SPEED_1000),
+ /* 1000 Mbps QSGMII with 1000BaseX auto-negotiation between
+ * MAC and QSGMII phy or backplane
+ */
+ ENET_MODE_QSGMII_BASEX_1000 =
+ (ENET_IF_SGMII_BASEX | ENET_IF_QSGMII | ENET_SPEED_1000),
+ /* 10000 Mbps XGMII */
+ ENET_MODE_XGMII_10000 = (ENET_IF_XGMII | ENET_SPEED_10000),
+ /* 10000 Mbps XFI */
+ ENET_MODE_XFI_10000 = (ENET_IF_XFI | ENET_SPEED_10000)
+};
+
+#define IS_ENET_MODE_VALID(mode) \
+ (((mode) == ENET_MODE_MII_10) || \
+ ((mode) == ENET_MODE_MII_100) || \
+ ((mode) == ENET_MODE_RMII_10) || \
+ ((mode) == ENET_MODE_RMII_100) || \
+ ((mode) == ENET_MODE_SMII_10) || \
+ ((mode) == ENET_MODE_SMII_100) || \
+ ((mode) == ENET_MODE_GMII_1000) || \
+ ((mode) == ENET_MODE_RGMII_10) || \
+ ((mode) == ENET_MODE_RGMII_100) || \
+ ((mode) == ENET_MODE_RGMII_1000) || \
+ ((mode) == ENET_MODE_TBI_1000) || \
+ ((mode) == ENET_MODE_RTBI_1000) || \
+ ((mode) == ENET_MODE_SGMII_10) || \
+ ((mode) == ENET_MODE_SGMII_100) || \
+ ((mode) == ENET_MODE_SGMII_1000) || \
+ ((mode) == ENET_MODE_SGMII_BASEX_10) || \
+ ((mode) == ENET_MODE_SGMII_BASEX_100) || \
+ ((mode) == ENET_MODE_SGMII_BASEX_1000) || \
+ ((mode) == ENET_MODE_XGMII_10000) || \
+ ((mode) == ENET_MODE_QSGMII_1000) || \
+ ((mode) == ENET_MODE_QSGMII_BASEX_1000) || \
+ ((mode) == ENET_MODE_XFI_10000))
+
+#define MAKE_ENET_MODE(_interface, _speed) \
+ (enum e_enet_mode)((_interface) | (_speed))
+
+#define ENET_INTERFACE_FROM_MODE(mode) \
+ (enum ethernet_interface)((mode) & 0x0FFF0000)
+#define ENET_SPEED_FROM_MODE(mode) \
+ (enum ethernet_speed)((mode) & 0x0000FFFF)
+
+#define ENET_ADDR_TO_UINT64(_enet_addr) \
+ (uint64_t)(((uint64_t)(_enet_addr)[0] << 40) | \
+ ((uint64_t)(_enet_addr)[1] << 32) | \
+ ((uint64_t)(_enet_addr)[2] << 24) | \
+ ((uint64_t)(_enet_addr)[3] << 16) | \
+ ((uint64_t)(_enet_addr)[4] << 8) | \
+ ((uint64_t)(_enet_addr)[5]))
+
+#define MAKE_ENET_ADDR_FROM_UINT64(_addr64, _enet_addr) \
+ do { \
+ int i; \
+ for (i = 0; i < ENET_NUM_OCTETS_PER_ADDRESS; i++) \
+ (_enet_addr)[i] = \
+ (uint8_t)((_addr64) >> ((5 - i) * 8)); \
+ } while (0)
+
+#endif /* __ENET_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_ext.h
new file mode 100644
index 0000000..33e3000
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_ext.h
@@ -0,0 +1,657 @@
+/*
+ * 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 Application Programming Interface. */
+#ifndef __FM_EXT
+#define __FM_EXT
+
+#include "service.h"
+#include "dpaa_ext.h"
+#include "dpaa_integration_ext.h"
+#include "fsl_fman_sp.h"
+
+/* Enum for defining port types */
+enum fm_port_type {
+ FM_PORT_TYPE_OP = 0, /* OP Port */
+ FM_PORT_TYPE_TX, /* TX Port */
+ FM_PORT_TYPE_RX, /* RX Port */
+ FM_PORT_TYPE_DUMMY
+};
+
+/* Enum for defining port speed */
+enum fm_port_speed {
+ FM_PORT_SPEED_1G = 0, /* 1G port */
+ FM_PORT_SPEED_10G, /* 10G port */
+ FM_PORT_SPEED_OP
+};
+
+/* General FM defines */
+#define FM_MAX_NUM_OF_PARTITIONS 64 /* Maximum number of partitions */
+#define FM_PHYS_ADDRESS_SIZE 6 /* FM Physical address size */
+
+/* FM physical Address */
+struct fm_phys_addr_t {
+ uint8_t high; /* High part of the physical address */
+ uint32_t low; /* Low part of the physical address */
+} __attribute__((__packed__));
+
+/* Parse results memory layout */
+struct fm_prs_result_t {
+ uint8_t lpid; /* Logical port id */
+ uint8_t shimr; /* Shim header result */
+ uint16_t l2r; /* Layer 2 result */
+ uint16_t l3r; /* Layer 3 result */
+ uint8_t l4r; /* Layer 4 result */
+ uint8_t cplan; /* Classification plan id */
+ uint16_t nxthdr; /* Next Header */
+ uint16_t cksum; /* Running-sum */
+ /* Flags&fragment-offset field of the last IP-header */
+ uint16_t flags_frag_off;
+ /* Routing type field of a IPV6 routing extension header */
+ uint8_t route_type;
+ /* Routing Extension Header Present; last bit is IP valid */
+ uint8_t rhp_ip_valid;
+ uint8_t shim_off[2]; /* Shim offset */
+ /* IP PID (last IP-proto) offset */
+ uint8_t ip_pid_off;
+ uint8_t eth_off; /* ETH offset */
+ uint8_t llc_snap_off; /* LLC_SNAP offset */
+ uint8_t vlan_off[2]; /* VLAN offset */
+ uint8_t etype_off; /* ETYPE offset */
+ uint8_t pppoe_off; /* PPP offset */
+ uint8_t mpls_off[2]; /* MPLS offset */
+ uint8_t ip_off[2]; /* IP offset */
+ uint8_t gre_off; /* GRE offset */
+ uint8_t l4_off; /* Layer 4 offset */
+ uint8_t nxthdr_off; /* Parser end point */
+} __attribute__((__packed__));
+
+/* FM Parser results */
+/* Parse Result: VLAN stack */
+#define FM_PR_L2_VLAN_STACK 0x00000100
+#define FM_PR_L2_ETHERNET 0x00008000 /* Parse Result: Ethernet*/
+#define FM_PR_L2_VLAN 0x00004000 /* Parse Result: VLAN */
+#define FM_PR_L2_LLC_SNAP 0x00002000 /* Parse Result: LLC_SNAP */
+#define FM_PR_L2_MPLS 0x00001000 /* Parse Result: MPLS */
+#define FM_PR_L2_PPPOE 0x00000800 /* Parse Result: PPPOE */
+
+/* FM Frame descriptor macros */
+/* Frame queue Context Override */
+#define FM_FD_CMD_FCO 0x80000000
+#define FM_FD_CMD_RPD 0x40000000 /* Read Prepended Data */
+/* Update Prepended Data */
+#define FM_FD_CMD_UPD 0x20000000
+#define FM_FD_CMD_DTC 0x10000000 /* Do L4 Checksum */
+/* Didn't calculate L4 Checksum */
+#define FM_FD_CMD_DCL4C 0x10000000
+/* Confirmation Frame Queue */
+#define FM_FD_CMD_CFQ 0x00ffffff
+
+/* Not for Rx-Port! Unsupported Format */
+#define FM_FD_ERR_UNSUPPORTED_FORMAT 0x04000000
+/* Not for Rx-Port! Length Error */
+#define FM_FD_ERR_LENGTH 0x02000000
+#define FM_FD_ERR_DMA 0x01000000 /* DMA Data error */
+
+/* IPR frame (not error) */
+#define FM_FD_IPR 0x00000001
+/* IPR non-consistent-sp */
+#define FM_FD_ERR_IPR_NCSP (0x00100000 | FM_FD_IPR)
+/* IPR error */
+#define FM_FD_ERR_IPR (0x00200000 | FM_FD_IPR)
+/* IPR timeout */
+#define FM_FD_ERR_IPR_TO (0x00300000 | FM_FD_IPR)
+
+/* Rx FIFO overflow, FCS error, code error, running disparity error
+ * (SGMII and TBI modes), FIFO parity error. PHY Sequence error,
+ * PHY error control character detected.
+ */
+#define FM_FD_ERR_PHYSICAL 0x00080000
+/* Frame too long OR Frame size exceeds max_length_frame */
+#define FM_FD_ERR_SIZE 0x00040000
+/* classification discard */
+#define FM_FD_ERR_CLS_DISCARD 0x00020000
+/* Extract Out of Frame */
+#define FM_FD_ERR_EXTRACTION 0x00008000
+/* No Scheme Selected */
+#define FM_FD_ERR_NO_SCHEME 0x00004000
+/* Keysize Overflow */
+#define FM_FD_ERR_KEYSIZE_OVERFLOW 0x00002000
+/* Frame color is red */
+#define FM_FD_ERR_COLOR_RED 0x00000800
+/* Frame color is yellow */
+#define FM_FD_ERR_COLOR_YELLOW 0x00000400
+/* Parser Time out Exceed */
+#define FM_FD_ERR_PRS_TIMEOUT 0x00000080
+/* Invalid Soft Parser instruction */
+#define FM_FD_ERR_PRS_ILL_INSTRUCT 0x00000040
+/* Header error was identified during parsing */
+#define FM_FD_ERR_PRS_HDR_ERR 0x00000020
+/* Frame parsed beyind 256 first bytes */
+#define FM_FD_ERR_BLOCK_LIMIT_EXCEEDED 0x00000008
+
+#define FM_FD_TX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \
+ FM_FD_ERR_LENGTH | \
+ FM_FD_ERR_DMA) /* TX Error FD bits */
+
+#define FM_FD_RX_STATUS_ERR_MASK (FM_FD_ERR_UNSUPPORTED_FORMAT | \
+ FM_FD_ERR_LENGTH | \
+ FM_FD_ERR_DMA | \
+ FM_FD_ERR_IPR | \
+ FM_FD_ERR_IPR_TO | \
+ FM_FD_ERR_IPR_NCSP | \
+ FM_FD_ERR_PHYSICAL | \
+ FM_FD_ERR_SIZE | \
+ FM_FD_ERR_CLS_DISCARD | \
+ FM_FD_ERR_COLOR_RED | \
+ FM_FD_ERR_COLOR_YELLOW | \
+ FM_FD_ERR_EXTRACTION | \
+ FM_FD_ERR_NO_SCHEME | \
+ FM_FD_ERR_KEYSIZE_OVERFLOW | \
+ FM_FD_ERR_PRS_TIMEOUT | \
+ FM_FD_ERR_PRS_ILL_INSTRUCT | \
+ FM_FD_ERR_PRS_HDR_ERR | \
+ FM_FD_ERR_BLOCK_LIMIT_EXCEEDED)
+ /* RX Error FD bits */
+
+/* non Frame-Manager error */
+#define FM_FD_RX_STATUS_ERR_NON_FM 0x00400000
+
+/* Context A */
+struct fm_context_a_t {
+ uint32_t command; /* ContextA Command */
+ uint8_t res0[4]; /* ContextA Reserved bits */
+} __attribute__((__packed__));
+
+/* Special Operation options */
+/* activate features that related to IPSec (e.g fix Eth-type) */
+#define FM_SP_OP_IPSEC 0x80000000
+/* update the UDP-Len after Encryption */
+#define FM_SP_OP_IPSEC_UPDATE_UDP_LEN 0x40000000
+#define FM_SP_OP_RPD 0x10000000 /* Set the RPD bit */
+/* Set the DCL4C bit */
+#define FM_SP_OP_DCL4C 0x08000000
+/* Check SEC errors */
+#define FM_SP_OP_CHECK_SEC_ERRORS 0x04000000
+/* Clear the RPD bit */
+#define FM_SP_OP_CLEAR_RPD 0x02000000
+
+/* Context A macros */
+#define FM_CONTEXTA_OVERRIDE_MASK 0x80000000
+#define FM_CONTEXTA_ICMD_MASK 0x40000000
+#define FM_CONTEXTA_A1_VALID_MASK 0x20000000
+#define FM_CONTEXTA_MACCMD_MASK 0x00ff0000
+#define FM_CONTEXTA_MACCMD_VALID_MASK 0x00800000
+#define FM_CONTEXTA_MACCMD_SECURED_MASK 0x00100000
+#define FM_CONTEXTA_MACCMD_SC_MASK 0x000f0000
+#define FM_CONTEXTA_A1_MASK 0x0000ffff
+
+#define FM_CONTEXTA_GET_OVERRIDE(contextA) \
+ ((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_OVERRIDE_MASK) >> (31 - 0))
+#define FM_CONTEXTA_GET_ICMD(contextA) \
+ ((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_ICMD_MASK) >> (31 - 1))
+#define FM_CONTEXTA_GET_A1_VALID(contextA) \
+ ((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_A1_VALID_MASK) >> (31 - 2))
+#define FM_CONTEXTA_GET_A1(contextA) \
+ ((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_A1_MASK) >> (31 - 31))
+#define FM_CONTEXTA_GET_MACCMD(contextA) \
+ ((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_MACCMD_MASK) >> (31 - 15))
+#define FM_CONTEXTA_GET_MACCMD_VALID(contextA) \
+ ((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_MACCMD_VALID_MASK) >> (31 - 8))
+#define FM_CONTEXTA_GET_MACCMD_SECURED(contextA) \
+((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_MACCMD_SECURED_MASK) >> (31 - 11))
+#define FM_CONTEXTA_GET_MACCMD_SECURE_CHANNEL(contextA) \
+((((struct fm_context_a_t *)contextA)->command & \
+ FM_CONTEXTA_MACCMD_SC_MASK) >> (31 - 15))
+
+#define FM_CONTEXTA_SET_OVERRIDE(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_OVERRIDE_MASK) | (((uint32_t)(val) << (31 - 0)) &\
+ FM_CONTEXTA_OVERRIDE_MASK)))
+#define FM_CONTEXTA_SET_ICMD(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_ICMD_MASK) | (((val) << (31 - 1)) & \
+ FM_CONTEXTA_ICMD_MASK)))
+#define FM_CONTEXTA_SET_A1_VALID(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_A1_VALID_MASK) | (((val) << (31 - 2)) & \
+ FM_CONTEXTA_A1_VALID_MASK)))
+#define FM_CONTEXTA_SET_A1(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_A1_MASK) | (((val) << (31 - 31)) & \
+ FM_CONTEXTA_A1_MASK)))
+#define FM_CONTEXTA_SET_MACCMD(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_MACCMD_MASK) | (((val) << (31 - 15)) & \
+ FM_CONTEXTA_MACCMD_MASK)))
+#define FM_CONTEXTA_SET_MACCMD_VALID(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_MACCMD_VALID_MASK) | (((val) << (31 - 8)) & \
+ FM_CONTEXTA_MACCMD_VALID_MASK)))
+#define FM_CONTEXTA_SET_MACCMD_SECURED(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_MACCMD_SECURED_MASK) | (((val) << (31 - 11)) & \
+ FM_CONTEXTA_MACCMD_SECURED_MASK)))
+#define FM_CONTEXTA_SET_MACCMD_SECURE_CHANNEL(contextA, val) \
+ (((struct fm_context_a_t *)contextA)->command = \
+ (uint32_t)((((struct fm_context_a_t *)contextA)->command & \
+ ~FM_CONTEXTA_MACCMD_SC_MASK) | (((val) << (31 - 15)) & \
+ FM_CONTEXTA_MACCMD_SC_MASK)))
+/* @} */
+
+/* FM Exceptions */
+enum fm_exceptions {
+ FM_EX_DMA_BUS_ERROR = 0, /* DMA bus error. */
+ /* Read Buffer ECC error (Valid for FM rev < 6)*/
+ FM_EX_DMA_READ_ECC,
+ /* Write Buffer ECC error on system side (Valid for FM rev < 6)*/
+ FM_EX_DMA_SYSTEM_WRITE_ECC,
+ /* Write Buffer ECC error on FM side (Valid for FM rev < 6)*/
+ FM_EX_DMA_FM_WRITE_ECC,
+ /* Single Port ECC error on FM side (Valid for FM rev > 6)*/
+ FM_EX_DMA_SINGLE_PORT_ECC,
+ FM_EX_FPM_STALL_ON_TASKS, /* Stall of tasks on FPM */
+ FM_EX_FPM_SINGLE_ECC, /* Single ECC on FPM. */
+ /* Double ECC error on FPM ram access */
+ FM_EX_FPM_DOUBLE_ECC,
+ FM_EX_QMI_SINGLE_ECC, /* Single ECC on QMI. */
+ FM_EX_QMI_DOUBLE_ECC, /* Double bit ECC occurred on QMI */
+ FM_EX_QMI_DEQ_FROM_UNKNOWN_PORTID,
+ /* Dequeue from unknown port id */
+ FM_EX_BMI_LIST_RAM_ECC, /* Linked List RAM ECC error */
+ FM_EX_BMI_STORAGE_PROFILE_ECC,/* Storage Profile ECC Error */
+ /* Statistics Count RAM ECC Error Enable */
+ FM_EX_BMI_STATISTICS_RAM_ECC,
+ FM_EX_BMI_DISPATCH_RAM_ECC, /* Dispatch RAM ECC Error Enable */
+ FM_EX_IRAM_ECC, /* Double bit ECC occurred on IRAM*/
+ FM_EX_MURAM_ECC /* Double bit ECC occurred on MURAM*/
+};
+
+/* Enum for defining port DMA swap mode */
+enum fm_dma_swap_option {
+ FM_DMA_NO_SWP = FMAN_DMA_NO_SWP,
+ /* No swap, transfer data as is.*/
+ FM_DMA_SWP_PPC_LE = FMAN_DMA_SWP_PPC_LE,
+ /* The transferred data should be swapped in PowerPc
+ *Little Endian mode.
+ */
+ FM_DMA_SWP_BE = FMAN_DMA_SWP_BE
+ /* The transferred data should be swapped in Big Endian mode */
+};
+
+/* fm_exceptions_cb
+ * Exceptions user callback routine, will be called upon an
+ * exception passing the exception identification.
+ * h_app - User's application descriptor.
+ * exception - The exception.
+ */
+typedef void (fm_exceptions_cb) (void *h_app,
+ enum fm_exceptions exception);
+
+/* fm_bus_error_cb
+ * Bus error user callback routine, will be called upon a
+ * bus error, passing parameters describing the errors and
+ * the owner.
+ * h_app - User's application descriptor.
+ * port_type - Port type (enum fm_port_type)
+ * port_id - Port id - relative to type.
+ * addr - Address that caused the error
+ * tnum - Owner of error
+ * liodn - Logical IO device number
+ */
+typedef void (fm_bus_error_cb) (void *h_app,
+ enum fm_port_type port_type,
+ uint8_t port_id,
+ uint64_t addr,
+ uint8_t tnum, uint16_t liodn);
+
+/* A structure for defining buffer prefix area content. */
+struct fm_buffer_prefix_content_t {
+ /* Number of bytes to be left at the beginning of the external
+ * buffer; Note that the private-area will start from the base
+ * of the buffer address.
+ */
+ uint16_t priv_data_size;
+ /* true to pass the parse result to/from the FM;
+ * User may use FM_PORT_GetBufferPrsResult() in
+ * order to get the parser-result from a buffer.
+ */
+ bool pass_prs_result;
+ /* true to pass the timeStamp to/from the FM User may use
+ * fm_port_get_buffer_time_stamp() in order to get the
+ * parser-result from a buffer.
+ */
+ bool pass_time_stamp;
+ /* true to pass the KG hash result to/from the FM User may
+ * use FM_PORT_GetBufferHashResult() in order to get the
+ * parser-result from a buffer.
+ */
+ bool pass_hash_result;
+ /* Add all other Internal-Context information: AD,
+ * hash-result, key, etc.
+ */
+ uint16_t data_align;
+};
+
+/* A structure of information about each of the external
+ * buffer pools used by a port or storage-profile.
+ */
+struct fm_ext_pool_params_t {
+ uint8_t id; /* External buffer pool id */
+ uint16_t size; /* External buffer pool buffer size */
+};
+
+/* A structure for informing the driver about the external
+ * buffer pools allocated in the BM and used by a port or a
+ * storage-profile.
+ */
+struct fm_ext_pools_t {
+ uint8_t num_of_pools_used; /* Number of pools use by this port */
+ struct fm_ext_pool_params_t ext_buf_pool[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+ /* Parameters for each port */
+};
+
+/* A structure for defining backup BM Pools. */
+struct fm_backup_bm_pools_t {
+ /* Number of BM backup pools - must be smaller
+ * than the total number of pools defined for the specified port.
+ */
+ uint8_t num_of_backup_pools;
+ /* num_of_backup_pools pool id's, specifying which pools should
+ * be used only as backup. Pool id's specified here must be a
+ * subset of the pools used by the specified port.
+ */
+ uint8_t pool_ids[FM_PORT_MAX_NUM_OF_EXT_POOLS];
+};
+
+/* A structure for defining BM pool depletion criteria */
+struct fm_buf_pool_depletion_t {
+ /* select mode in which pause frames will be sent after a
+ * number of pools (all together!) are depleted
+ */
+ bool pools_grp_mode_enable;
+ /* the number of depleted pools that will invoke pause
+ * frames transmission.
+ */
+ uint8_t num_of_pools;
+ /* For each pool, true if it should be considered for
+ * depletion (Note - this pool must be used by this port!).
+ */
+ bool pools_to_consider[BM_MAX_NUM_OF_POOLS];
+ /* select mode in which pause frames will be sent
+ * after a single-pool is depleted;
+ */
+ bool single_pool_mode_enable;
+ /* For each pool, true if it should be considered
+ * for depletion (Note - this pool must be used by this port!)
+ */
+ bool pools_to_consider_for_single_mode[BM_MAX_NUM_OF_POOLS];
+};
+
+/* A Structure for defining Ucode patch for loading. */
+struct fm_firmware_params_t {
+ uint32_t size; /* Size of uCode */
+ uint32_t *p_code; /* A pointer to the uCode */
+};
+
+/* A Structure for defining FM initialization parameters */
+struct fm_params_t {
+ uint8_t fm_id;
+ /* Index of the FM */
+ uintptr_t base_addr;
+ /* A pointer to base of memory mapped FM registers (virtual);
+ * NOTE that this should include ALL common registers of the FM
+ * including the PCD registers area.
+ */
+ struct muram_info *p_muram;
+ /* A pointer to an initialized MURAM object, to be used by the FM. */
+ uint16_t fm_clk_freq;
+ /* In Mhz; */
+ fm_exceptions_cb *f_exception;
+ /* An application callback routine to handle exceptions; */
+ fm_bus_error_cb *f_bus_error;
+ /* An application callback routine to handle exceptions; */
+ void *h_app;
+ /* A handle to an application layer object; This handle will be
+ * passed by the driver upon calling the above callbacks;
+ */
+ struct fm_firmware_params_t firmware;
+ /* The firmware parameters structure; */
+};
+
+/* FM_Config
+ * Creates the FM module and returns its handle (descriptor).
+ * This descriptor must be passed as first parameter to all other
+ * FM function calls.
+ * No actual initialization or configuration of FM hardware is
+ * done by this routine. All FM parameters get default values that
+ * may be changed by calling one or more of the advance config
+ * routines.
+ * p_fm_params - A pointer to a data structure of mandatory FM parameters
+ * Return A handle to the FM object, or NULL for Failure.
+ */
+void *fm_config(struct fm_params_t *p_fm_params);
+
+/* fm_init
+ * Initializes the FM module by defining the software structure
+ * and configuring the hardware registers.
+ * h_fm - FM module descriptor
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_init(void *h_fm);
+
+/* fm_free
+ * Frees all resources that were assigned to FM module.
+ * Calling this routine invalidates the descriptor.
+ * h_fm - FM module descriptor
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_free(void *h_fm);
+
+/* Enum for choosing the field that will be output on AID */
+enum fm_dma_aid_mode {
+ FM_DMA_AID_OUT_PORT_ID = 0, /* 4 LSB of PORT_ID */
+ FM_DMA_AID_OUT_TNUM /* 4 LSB of TNUM */
+};
+
+/* Enum for selecting DMA Emergency level by BMI emergency signal */
+enum fm_dma_emergency_level {
+ FM_DMA_EM_EBS = 0, /* EBS emergency */
+ FM_DMA_EM_SOS /* SOS emergency */
+};
+
+/* Enum for selecting DMA Emergency options */
+/* Enable emergency for MURAM1 */
+#define FM_DMA_MURAM_READ_EMERGENCY 0x00800000
+/* Enable emergency for MURAM2 */
+#define FM_DMA_MURAM_WRITE_EMERGENCY 0x00400000
+/* Enable emergency for external bus */
+#define FM_DMA_EXT_BUS_EMERGENCY 0x00100000
+
+/* fm_cfg_reset_on_init
+ * Define whether to reset the FM before initialization.
+ * Change the default configuration [DEFAULT_RESET_ON_INIT].
+ * h_fm A handle to an FM Module.
+ * enable When true, FM will be reset before any
+ * Return 0 on success; Error code otherwise.
+ * Allowed only following fm_config() and before fm_init().
+ */
+int fm_cfg_reset_on_init(void *h_fm, bool enable);
+
+/* fm_cfg_total_fifo_size
+ * Define Total FIFO size for the whole FM.
+ * Calling this routine changes the total Fifo size in the internal driver
+ * data base from its default configuration [DEFAULT_total_fifo_size]
+ * h_fm A handle to an FM Module.
+ * total_fifo_size The selected new value.
+ * Return 0 on success; Error code otherwise.
+ * Allowed only following fm_config() and before fm_init().
+ */
+int fm_cfg_total_fifo_size(void *h_fm, uint32_t total_fifo_size);
+
+/* fm_cfg_dma_aid_override
+ * Define DMA AID override mode.
+ * Calling this routine changes the AID override mode
+ * in the internal driver data base from its default
+ * configuration [DEFAULT_aid_override]
+ * h_fm A handle to an FM Module.
+ * aid_override The selected new value.
+ * Return 0 on success; Error code otherwise.
+ * Allowed only following fm_config() and before fm_init().
+ */
+int fm_cfg_dma_aid_override(void *h_fm, bool aid_override);
+
+/* General FM defines. */
+#define FM_MAX_NUM_OF_VALID_PORTS (FM_MAX_NUM_OF_OH_PORTS + \
+ FM_MAX_NUM_OF_1G_RX_PORTS + \
+ FM_MAX_NUM_OF_10G_RX_PORTS + \
+ FM_MAX_NUM_OF_1G_TX_PORTS + \
+ FM_MAX_NUM_OF_10G_TX_PORTS)
+ /* Number of available FM ports */
+
+/* A Structure for Port bandwidth requirement.
+ * Port is identified by type and relative id.
+ */
+struct fm_port_bandwidth_t {
+ enum fm_port_type type; /* FM port type */
+ uint8_t relative_port_id; /* Type relative port id */
+ uint8_t bandwidth; /* bandwidth - (in term of percents) */
+};
+
+/* A Structure containing an array of Port bandwidth requirements.
+ * The user should state the ports requiring bandwidth in terms of
+ * percentage - i.e. all port's bandwidths in the array must add
+ * up to 100.
+ */
+struct fm_ports_bandwidth_params_t {
+ /* The number of relevant ports, which is the number of
+ * valid entries in the array below
+ */
+ uint8_t num_of_ports;
+ /* for each port, it's bandwidth (all port's bandwidths
+ * must add up to 100.
+ */
+ struct fm_port_bandwidth_t ports_bandwidths[FM_MAX_NUM_OF_VALID_PORTS];
+};
+
+/* A Structure for returning FM revision information */
+struct fm_revision_info_t {
+ uint8_t major_rev; /* Major revision */
+ uint8_t minor_rev; /* Minor revision */
+};
+
+/* A Structure for returning FM ctrl code revision information */
+struct fm_ctrl_code_revision_info_t {
+ uint16_t package_rev; /* Package revision */
+ uint8_t major_rev; /* Major revision */
+ uint8_t minor_rev; /* Minor revision */
+};
+
+/* fm_set_exception
+ * Calling this routine enables/disables the specified
+ * exception.
+ * h_fm A handle to an FM Module.
+ * exception The exception to be selected.
+ * enable true to enable interrupt, false to mask it.
+ * Return 0 on success; Error code otherwise.
+ * Allowed only following fm_init().
+ */
+int fm_set_exception(void *h_fm, enum fm_exceptions exception,
+ bool enable);
+
+/* fm_disable_rams_ecc
+ * Disables ECC mechanism for all the different FM RAM's; E.g. IRAM,
+ * MURAM, etc.
+ * Note:
+ * In opposed to fm_enable_rams_ecc, this routine must be called
+ * explicitly to disable all Rams ECC.
+ * h_fm A handle to an FM Module.
+ * Return 0 on success; Error code otherwise.
+ * Allowed only following fm_config() and before fm_init().
+ */
+int fm_disable_rams_ecc(void *h_fm);
+
+/* fm_get_revision
+ * Returns the FM revision
+ * h_fm A handle to an FM Module.
+ * p_fm_revision_info A structure of revision
+ * information parameters.
+ * Return 0 on success; Error code otherwise.
+ * Allowed only following fm_init().
+ */
+int fm_get_revision(void *h_fm,
+ struct fm_revision_info_t *p_fm_revision_info);
+
+/* fm_error_isr
+ * FM interrupt-service-routine for errors.
+ * h_fm A handle to an FM Module.
+ * Return 0 on success; EMPTY if no errors found in register, other
+ * error code otherwise.
+ * Allowed only following fm_init().
+ */
+int fm_error_isr(void *h_fm);
+
+/* fm_event_isr
+ * FM interrupt-service-routine for normal events.
+ * h_fm A handle to an FM Module.
+ * Allowed only following fm_init().
+ */
+void fm_event_isr(void *h_fm);
+
+#ifdef NCSW_BACKWARD_COMPATIBLE_API
+
+#define FM_CONTEXTA_GET_OVVERIDE FM_CONTEXTA_GET_OVERRIDE
+#define FM_CONTEXTA_SET_OVVERIDE FM_CONTEXTA_SET_OVERRIDE
+
+#define FM_EX_BMI_PIPELINE_ECC FM_EX_BMI_STORAGE_PROFILE_ECC
+#define FM_PORT_DMA_NO_SWP FM_DMA_NO_SWP
+#define FM_PORT_DMA_SWP_PPC_LE FM_DMA_SWP_PPC_LE
+#define FM_PORT_DMA_SWP_BE FM_DMA_SWP_BE
+#define FM_PORT_DMA_NO_STASH FM_DMA_NO_STASH
+#define FM_PORT_DMA_STASH FM_DMA_STASH
+#endif /* NCSW_BACKWARD_COMPATIBLE_API */
+
+#endif /* __FM_EXT */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h b/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
new file mode 100644
index 0000000..cfbf462
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fsl_fman_drv.h
@@ -0,0 +1,94 @@
+/*
+ * 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.
+ */
+
+/* Linux internal kernel API */
+
+#ifndef __FSL_FMAN_DRV_H
+#define __FSL_FMAN_DRV_H
+
+#include <linux/types.h>
+#include <linux/device.h> /* struct device */
+
+/* FM device opaque structure used for type checking */
+struct fm;
+
+/* fm_bind
+ * Bind to a specific FM device.
+ *
+ * fm_dev - the OF handle of the FM device.
+ * Return A handle of the FM device.
+ * Allowed only after the port was created.
+ */
+struct fm *fm_bind(struct device *fm_dev);
+
+/* fm_unbind
+ * Un-bind from a specific FM device.
+ * fm - A handle of the FM device.
+ * Allowed only after the port was created.
+ */
+void fm_unbind(struct fm *fm);
+
+void *fm_get_handle(struct fm *fm);
+struct resource *fm_get_mem_region(struct fm *fm);
+
+/* fm_mutex_lock
+ *
+ * Lock function required before any FMD/LLD call.
+ */
+void fm_mutex_lock(void);
+
+/* fm_mutex_unlock
+ *
+ * Unlock function required after any FMD/LLD call.
+ */
+void fm_mutex_unlock(void);
+
+/* fm_get_max_frm
+ *
+ * Get the maximum frame size
+ */
+u16 fm_get_max_frm(void);
+
+/* fm_get_rx_extra_headroom
+ *
+ * Get the extra headroom size
+ */
+int fm_get_rx_extra_headroom(void);
+
+/* default values for initializing PTP 1588 timer clock */
+/* power of 2 for better performance */
+#define DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT 2
+/* 4ns,250MHz */
+#define DPA_PTP_NOMINAL_FREQ_PERIOD_NS \
+(1 << DPA_PTP_NOMINAL_FREQ_PERIOD_SHIFT)
+
+#endif /* __FSL_FMAN_DRV_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/net_ext.h b/drivers/net/ethernet/freescale/fman/inc/net_ext.h
new file mode 100644
index 0000000..a05ace0
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/net_ext.h
@@ -0,0 +1,534 @@
+/*
+ * 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.
+ */
+
+/* net_ext.h
+ * This file contains common and general headers definitions.
+ */
+#ifndef __NET_EXT_H
+#define __NET_EXT_H
+
+#define NET_HEADER_FIELD_PPP_PID (1)
+#define NET_HEADER_FIELD_PPP_COMPRESSED \
+(NET_HEADER_FIELD_PPP_PID << 1)
+#define NET_HEADER_FIELD_PPP_ALL_FIELDS \
+((NET_HEADER_FIELD_PPP_PID << 2) - 1)
+
+#define NET_HEADER_FIELD_PPPOE_VER (1)
+#define NET_HEADER_FIELD_PPPOE_TYPE \
+(NET_HEADER_FIELD_PPPOE_VER << 1)
+#define NET_HEADER_FIELD_PPPOE_CODE \
+(NET_HEADER_FIELD_PPPOE_VER << 2)
+#define NET_HEADER_FIELD_PPPOE_SID \
+(NET_HEADER_FIELD_PPPOE_VER << 3)
+#define NET_HEADER_FIELD_PPPOE_LEN \
+(NET_HEADER_FIELD_PPPOE_VER << 4)
+#define NET_HEADER_FIELD_PPPOE_SESSION \
+(NET_HEADER_FIELD_PPPOE_VER << 5)
+#define NET_HEADER_FIELD_PPPOE_PID \
+(NET_HEADER_FIELD_PPPOE_VER << 6)
+#define NET_HEADER_FIELD_PPPOE_ALL_FIELDS \
+((NET_HEADER_FIELD_PPPOE_VER << 7) - 1)
+
+#define NET_HEADER_FIELD_PPPMUX_PID (1)
+#define NET_HEADER_FIELD_PPPMUX_CKSUM \
+(NET_HEADER_FIELD_PPPMUX_PID << 1)
+#define NET_HEADER_FIELD_PPPMUX_COMPRESSED \
+(NET_HEADER_FIELD_PPPMUX_PID << 2)
+#define NET_HEADER_FIELD_PPPMUX_ALL_FIELDS \
+((NET_HEADER_FIELD_PPPMUX_PID << 3) - 1)
+
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF (1)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LXT \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 1)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_LEN \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 2)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_PID \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 3)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_USE_PID \
+(NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 4)
+#define NET_HEADER_FIELD_PPPMUX_SUBFRAME_ALL_FIELDS \
+((NET_HEADER_FIELD_PPPMUX_SUBFRAME_PFF << 5) - 1)
+
+#define NET_HEADER_FIELD_ETH_DA (1)
+#define NET_HEADER_FIELD_ETH_SA \
+(NET_HEADER_FIELD_ETH_DA << 1)
+#define NET_HEADER_FIELD_ETH_LENGTH \
+(NET_HEADER_FIELD_ETH_DA << 2)
+#define NET_HEADER_FIELD_ETH_TYPE \
+(NET_HEADER_FIELD_ETH_DA << 3)
+#define NET_HEADER_FIELD_ETH_FINAL_CKSUM \
+(NET_HEADER_FIELD_ETH_DA << 4)
+#define NET_HEADER_FIELD_ETH_PADDING \
+(NET_HEADER_FIELD_ETH_DA << 5)
+#define NET_HEADER_FIELD_ETH_ALL_FIELDS \
+((NET_HEADER_FIELD_ETH_DA << 6) - 1)
+
+#define NET_HEADER_FIELD_ETH_ADDR_SIZE 6
+
+#define NET_HEADER_FIELD_IP_VER (1)
+#define NET_HEADER_FIELD_IP_DSCP \
+(NET_HEADER_FIELD_IP_VER << 2)
+#define NET_HEADER_FIELD_IP_ECN \
+(NET_HEADER_FIELD_IP_VER << 3)
+#define NET_HEADER_FIELD_IP_PROTO \
+(NET_HEADER_FIELD_IP_VER << 4)
+
+#define NET_HEADER_FIELD_IP_PROTO_SIZE 1
+
+#define NET_HEADER_FIELD_IPV4_VER (1)
+#define NET_HEADER_FIELD_IPV4_HDR_LEN \
+(NET_HEADER_FIELD_IPV4_VER << 1)
+#define NET_HEADER_FIELD_IPV4_TOS \
+(NET_HEADER_FIELD_IPV4_VER << 2)
+#define NET_HEADER_FIELD_IPV4_TOTAL_LEN \
+(NET_HEADER_FIELD_IPV4_VER << 3)
+#define NET_HEADER_FIELD_IPV4_ID \
+(NET_HEADER_FIELD_IPV4_VER << 4)
+#define NET_HEADER_FIELD_IPV4_FLAG_D \
+(NET_HEADER_FIELD_IPV4_VER << 5)
+#define NET_HEADER_FIELD_IPV4_FLAG_M \
+(NET_HEADER_FIELD_IPV4_VER << 6)
+#define NET_HEADER_FIELD_IPV4_OFFSET \
+(NET_HEADER_FIELD_IPV4_VER << 7)
+#define NET_HEADER_FIELD_IPV4_TTL \
+(NET_HEADER_FIELD_IPV4_VER << 8)
+#define NET_HEADER_FIELD_IPV4_PROTO \
+(NET_HEADER_FIELD_IPV4_VER << 9)
+#define NET_HEADER_FIELD_IPV4_CKSUM \
+(NET_HEADER_FIELD_IPV4_VER << 10)
+#define NET_HEADER_FIELD_IPV4_SRC_IP \
+(NET_HEADER_FIELD_IPV4_VER << 11)
+#define NET_HEADER_FIELD_IPV4_DST_IP \
+(NET_HEADER_FIELD_IPV4_VER << 12)
+#define NET_HEADER_FIELD_IPV4_OPTS \
+(NET_HEADER_FIELD_IPV4_VER << 13)
+#define NET_HEADER_FIELD_IPV4_OPTS_COUNT \
+(NET_HEADER_FIELD_IPV4_VER << 14)
+#define NET_HEADER_FIELD_IPV4_ALL_FIELDS \
+((NET_HEADER_FIELD_IPV4_VER << 15) - 1)
+
+#define NET_HEADER_FIELD_IPV4_ADDR_SIZE 4
+#define NET_HEADER_FIELD_IPV4_PROTO_SIZE 1
+
+#define NET_HEADER_FIELD_IPV6_VER (1)
+#define NET_HEADER_FIELD_IPV6_TC \
+(NET_HEADER_FIELD_IPV6_VER << 1)
+#define NET_HEADER_FIELD_IPV6_SRC_IP \
+(NET_HEADER_FIELD_IPV6_VER << 2)
+#define NET_HEADER_FIELD_IPV6_DST_IP \
+(NET_HEADER_FIELD_IPV6_VER << 3)
+#define NET_HEADER_FIELD_IPV6_NEXT_HDR \
+(NET_HEADER_FIELD_IPV6_VER << 4)
+#define NET_HEADER_FIELD_IPV6_FL \
+(NET_HEADER_FIELD_IPV6_VER << 5)
+#define NET_HEADER_FIELD_IPV6_HOP_LIMIT \
+(NET_HEADER_FIELD_IPV6_VER << 6)
+#define NET_HEADER_FIELD_IPV6_ALL_FIELDS \
+((NET_HEADER_FIELD_IPV6_VER << 7) - 1)
+
+#define NET_HEADER_FIELD_IPV6_ADDR_SIZE 16
+#define NET_HEADER_FIELD_IPV6_NEXT_HDR_SIZE 1
+
+#define NET_HEADER_FIELD_ICMP_TYPE (1)
+#define NET_HEADER_FIELD_ICMP_CODE \
+(NET_HEADER_FIELD_ICMP_TYPE << 1)
+#define NET_HEADER_FIELD_ICMP_CKSUM \
+(NET_HEADER_FIELD_ICMP_TYPE << 2)
+#define NET_HEADER_FIELD_ICMP_ID \
+(NET_HEADER_FIELD_ICMP_TYPE << 3)
+#define NET_HEADER_FIELD_ICMP_SQ_NUM \
+(NET_HEADER_FIELD_ICMP_TYPE << 4)
+#define NET_HEADER_FIELD_ICMP_ALL_FIELDS \
+((NET_HEADER_FIELD_ICMP_TYPE << 5) - 1)
+
+#define NET_HEADER_FIELD_ICMP_CODE_SIZE 1
+#define NET_HEADER_FIELD_ICMP_TYPE_SIZE 1
+
+#define NET_HEADER_FIELD_IGMP_VERSION (1)
+#define NET_HEADER_FIELD_IGMP_TYPE \
+(NET_HEADER_FIELD_IGMP_VERSION << 1)
+#define NET_HEADER_FIELD_IGMP_CKSUM \
+(NET_HEADER_FIELD_IGMP_VERSION << 2)
+#define NET_HEADER_FIELD_IGMP_DATA \
+(NET_HEADER_FIELD_IGMP_VERSION << 3)
+#define NET_HEADER_FIELD_IGMP_ALL_FIELDS \
+((NET_HEADER_FIELD_IGMP_VERSION << 4) - 1)
+
+#define NET_HEADER_FIELD_TCP_PORT_SRC (1)
+#define NET_HEADER_FIELD_TCP_PORT_DST \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_TCP_SEQ \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_TCP_ACK \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_TCP_OFFSET \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 4)
+#define NET_HEADER_FIELD_TCP_FLAGS \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 5)
+#define NET_HEADER_FIELD_TCP_WINDOW \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 6)
+#define NET_HEADER_FIELD_TCP_CKSUM \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 7)
+#define NET_HEADER_FIELD_TCP_URGPTR \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 8)
+#define NET_HEADER_FIELD_TCP_OPTS \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 9)
+#define NET_HEADER_FIELD_TCP_OPTS_COUNT \
+(NET_HEADER_FIELD_TCP_PORT_SRC << 10)
+#define NET_HEADER_FIELD_TCP_ALL_FIELDS \
+((NET_HEADER_FIELD_TCP_PORT_SRC << 11) - 1)
+
+#define NET_HEADER_FIELD_TCP_PORT_SIZE 2
+
+#define NET_HEADER_FIELD_SCTP_PORT_SRC (1)
+#define NET_HEADER_FIELD_SCTP_PORT_DST \
+(NET_HEADER_FIELD_SCTP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_SCTP_VER_TAG \
+(NET_HEADER_FIELD_SCTP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_SCTP_CKSUM \
+(NET_HEADER_FIELD_SCTP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_SCTP_ALL_FIELDS \
+((NET_HEADER_FIELD_SCTP_PORT_SRC << 4) - 1)
+
+#define NET_HEADER_FIELD_SCTP_PORT_SIZE 2
+
+#define NET_HEADER_FIELD_DCCP_PORT_SRC (1)
+#define NET_HEADER_FIELD_DCCP_PORT_DST \
+(NET_HEADER_FIELD_DCCP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_DCCP_ALL_FIELDS \
+((NET_HEADER_FIELD_DCCP_PORT_SRC << 2) - 1)
+
+#define NET_HEADER_FIELD_DCCP_PORT_SIZE 2
+
+#define NET_HEADER_FIELD_UDP_PORT_SRC (1)
+#define NET_HEADER_FIELD_UDP_PORT_DST \
+(NET_HEADER_FIELD_UDP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_LEN \
+(NET_HEADER_FIELD_UDP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_UDP_CKSUM \
+(NET_HEADER_FIELD_UDP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_UDP_ALL_FIELDS \
+((NET_HEADER_FIELD_UDP_PORT_SRC << 4) - 1)
+
+#define NET_HEADER_FIELD_UDP_PORT_SIZE 2
+
+#define NET_HEADER_FIELD_UDP_LITE_PORT_SRC (1)
+#define NET_HEADER_FIELD_UDP_LITE_PORT_DST \
+(NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_LITE_ALL_FIELDS \
+((NET_HEADER_FIELD_UDP_LITE_PORT_SRC << 2) - 1)
+
+#define NET_HEADER_FIELD_UDP_LITE_PORT_SIZE 2
+
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC (1)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_DST \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 1)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_LEN \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 2)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_CKSUM \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 3)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 4)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SEQUENCE_NUM \
+(NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 5)
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_ALL_FIELDS \
+((NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SRC << 6) - 1)
+
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_PORT_SIZE 2
+#define NET_HEADER_FIELD_UDP_ENCAP_ESP_SPI_SIZE 4
+
+#define NET_HEADER_FIELD_IPHC_CID (1)
+#define NET_HEADER_FIELD_IPHC_CID_TYPE \
+(NET_HEADER_FIELD_IPHC_CID << 1)
+#define NET_HEADER_FIELD_IPHC_HCINDEX \
+(NET_HEADER_FIELD_IPHC_CID << 2)
+#define NET_HEADER_FIELD_IPHC_GEN \
+(NET_HEADER_FIELD_IPHC_CID << 3)
+#define NET_HEADER_FIELD_IPHC_D_BIT \
+(NET_HEADER_FIELD_IPHC_CID << 4)
+#define NET_HEADER_FIELD_IPHC_ALL_FIELDS \
+((NET_HEADER_FIELD_IPHC_CID << 5) - 1)
+
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE (1)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_FLAGS \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 1)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_LENGTH \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 2)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_TSN \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 3)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_ID \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 4)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_STREAM_SQN \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 5)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_PAYLOAD_PID \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 6)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_UNORDERED \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 7)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_BEGGINING \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 8)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_END \
+(NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 9)
+#define NET_HEADER_FIELD_SCTP_CHUNK_DATA_ALL_FIELDS \
+((NET_HEADER_FIELD_SCTP_CHUNK_DATA_TYPE << 10) - 1)
+
+#define NET_HEADER_FIELD_L2TPV2_TYPE_BIT (1)
+#define NET_HEADER_FIELD_L2TPV2_LENGTH_BIT \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPV2_SEQUENCE_BIT \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPV2_OFFSET_BIT \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPV2_PRIORITY_BIT \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 4)
+#define NET_HEADER_FIELD_L2TPV2_VERSION \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 5)
+#define NET_HEADER_FIELD_L2TPV2_LEN \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 6)
+#define NET_HEADER_FIELD_L2TPV2_TUNNEL_ID \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 7)
+#define NET_HEADER_FIELD_L2TPV2_SESSION_ID \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 8)
+#define NET_HEADER_FIELD_L2TPV2_NS \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 9)
+#define NET_HEADER_FIELD_L2TPV2_NR \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 10)
+#define NET_HEADER_FIELD_L2TPV2_OFFSET_SIZE \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 11)
+#define NET_HEADER_FIELD_L2TPV2_FIRST_BYTE \
+(NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 12)
+#define NET_HEADER_FIELD_L2TPV2_ALL_FIELDS \
+((NET_HEADER_FIELD_L2TPV2_TYPE_BIT << 13) - 1)
+
+#define NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT (1)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_LENGTH_BIT \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_SEQUENCE_BIT \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_VERSION \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_LENGTH \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 4)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_CONTROL \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 5)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_SENT \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 6)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_RECV \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 7)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_FIRST_BYTE \
+(NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 8)
+#define NET_HEADER_FIELD_L2TPV3_CTRL_ALL_FIELDS \
+((NET_HEADER_FIELD_L2TPV3_CTRL_TYPE_BIT << 9) - 1)
+
+#define NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT (1)
+#define NET_HEADER_FIELD_L2TPV3_SESS_VERSION \
+(NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 1)
+#define NET_HEADER_FIELD_L2TPV3_SESS_ID \
+(NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 2)
+#define NET_HEADER_FIELD_L2TPV3_SESS_COOKIE \
+(NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 3)
+#define NET_HEADER_FIELD_L2TPV3_SESS_ALL_FIELDS \
+((NET_HEADER_FIELD_L2TPV3_SESS_TYPE_BIT << 4) - 1)
+
+#define NET_HEADER_FIELD_VLAN_VPRI (1)
+#define NET_HEADER_FIELD_VLAN_CFI \
+(NET_HEADER_FIELD_VLAN_VPRI << 1)
+#define NET_HEADER_FIELD_VLAN_VID \
+(NET_HEADER_FIELD_VLAN_VPRI << 2)
+#define NET_HEADER_FIELD_VLAN_LENGTH \
+(NET_HEADER_FIELD_VLAN_VPRI << 3)
+#define NET_HEADER_FIELD_VLAN_TYPE \
+(NET_HEADER_FIELD_VLAN_VPRI << 4)
+#define NET_HEADER_FIELD_VLAN_ALL_FIELDS \
+((NET_HEADER_FIELD_VLAN_VPRI << 5) - 1)
+
+#define NET_HEADER_FIELD_VLAN_TCI \
+(NET_HEADER_FIELD_VLAN_VPRI | \
+NET_HEADER_FIELD_VLAN_CFI | \
+NET_HEADER_FIELD_VLAN_VID)
+
+#define NET_HEADER_FIELD_LLC_DSAP (1)
+#define NET_HEADER_FIELD_LLC_SSAP \
+(NET_HEADER_FIELD_LLC_DSAP << 1)
+#define NET_HEADER_FIELD_LLC_CTRL \
+(NET_HEADER_FIELD_LLC_DSAP << 2)
+#define NET_HEADER_FIELD_LLC_ALL_FIELDS \
+((NET_HEADER_FIELD_LLC_DSAP << 3) - 1)
+
+#define NET_HEADER_FIELD_NLPID_NLPID (1)
+#define NET_HEADER_FIELD_NLPID_ALL_FIELDS \
+((NET_HEADER_FIELD_NLPID_NLPID << 1) - 1)
+
+#define NET_HEADER_FIELD_SNAP_OUI (1)
+#define NET_HEADER_FIELD_SNAP_PID \
+(NET_HEADER_FIELD_SNAP_OUI << 1)
+#define NET_HEADER_FIELD_SNAP_ALL_FIELDS \
+((NET_HEADER_FIELD_SNAP_OUI << 2) - 1)
+
+#define NET_HEADER_FIELD_LLC_SNAP_TYPE (1)
+#define NET_HEADER_FIELD_LLC_SNAP_ALL_FIELDS \
+((NET_HEADER_FIELD_LLC_SNAP_TYPE << 1) - 1)
+
+#define NET_HEADER_FIELD_ARP_HTYPE (1)
+#define NET_HEADER_FIELD_ARP_PTYPE \
+(NET_HEADER_FIELD_ARP_HTYPE << 1)
+#define NET_HEADER_FIELD_ARP_HLEN \
+(NET_HEADER_FIELD_ARP_HTYPE << 2)
+#define NET_HEADER_FIELD_ARP_PLEN \
+(NET_HEADER_FIELD_ARP_HTYPE << 3)
+#define NET_HEADER_FIELD_ARP_OPER \
+(NET_HEADER_FIELD_ARP_HTYPE << 4)
+#define NET_HEADER_FIELD_ARP_SHA \
+(NET_HEADER_FIELD_ARP_HTYPE << 5)
+#define NET_HEADER_FIELD_ARP_SPA \
+(NET_HEADER_FIELD_ARP_HTYPE << 6)
+#define NET_HEADER_FIELD_ARP_THA \
+(NET_HEADER_FIELD_ARP_HTYPE << 7)
+#define NET_HEADER_FIELD_ARP_TPA \
+(NET_HEADER_FIELD_ARP_HTYPE << 8)
+#define NET_HEADER_FIELD_ARP_ALL_FIELDS \
+((NET_HEADER_FIELD_ARP_HTYPE << 9) - 1)
+
+#define NET_HEADER_FIELD_RFC2684_LLC (1)
+#define NET_HEADER_FIELD_RFC2684_NLPID \
+(NET_HEADER_FIELD_RFC2684_LLC << 1)
+#define NET_HEADER_FIELD_RFC2684_OUI \
+(NET_HEADER_FIELD_RFC2684_LLC << 2)
+#define NET_HEADER_FIELD_RFC2684_PID \
+(NET_HEADER_FIELD_RFC2684_LLC << 3)
+#define NET_HEADER_FIELD_RFC2684_VPN_OUI \
+(NET_HEADER_FIELD_RFC2684_LLC << 4)
+#define NET_HEADER_FIELD_RFC2684_VPN_IDX \
+(NET_HEADER_FIELD_RFC2684_LLC << 5)
+#define NET_HEADER_FIELD_RFC2684_ALL_FIELDS \
+((NET_HEADER_FIELD_RFC2684_LLC << 6) - 1)
+
+#define NET_HEADER_FIELD_USER_DEFINED_SRCPORT (1)
+#define NET_HEADER_FIELD_USER_DEFINED_PCDID \
+(NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 1)
+#define NET_HEADER_FIELD_USER_DEFINED_ALL_FIELDS \
+((NET_HEADER_FIELD_USER_DEFINED_SRCPORT << 2) - 1)
+
+#define NET_HEADER_FIELD_PAYLOAD_BUFFER (1)
+#define NET_HEADER_FIELD_PAYLOAD_SIZE \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 1)
+#define NET_HEADER_FIELD_MAX_FRM_SIZE \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 2)
+#define NET_HEADER_FIELD_MIN_FRM_SIZE \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 3)
+#define NET_HEADER_FIELD_PAYLOAD_TYPE \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 4)
+#define NET_HEADER_FIELD_FRAME_SIZE \
+(NET_HEADER_FIELD_PAYLOAD_BUFFER << 5)
+#define NET_HEADER_FIELD_PAYLOAD_ALL_FIELDS \
+((NET_HEADER_FIELD_PAYLOAD_BUFFER << 6) - 1)
+
+#define NET_HEADER_FIELD_GRE_TYPE (1)
+#define NET_HEADER_FIELD_GRE_ALL_FIELDS \
+((NET_HEADER_FIELD_GRE_TYPE << 1) - 1)
+
+#define NET_HEADER_FIELD_MINENCAP_SRC_IP (1)
+#define NET_HEADER_FIELD_MINENCAP_DST_IP \
+(NET_HEADER_FIELD_MINENCAP_SRC_IP << 1)
+#define NET_HEADER_FIELD_MINENCAP_TYPE \
+(NET_HEADER_FIELD_MINENCAP_SRC_IP << 2)
+#define NET_HEADER_FIELD_MINENCAP_ALL_FIELDS \
+((NET_HEADER_FIELD_MINENCAP_SRC_IP << 3) - 1)
+
+#define NET_HEADER_FIELD_IPSEC_AH_NH \
+(NET_HEADER_FIELD_IPSEC_AH_SPI << 1)
+#define NET_HEADER_FIELD_IPSEC_AH_ALL_FIELDS \
+((NET_HEADER_FIELD_IPSEC_AH_SPI << 2) - 1)
+
+#define NET_HEADER_FIELD_IPSEC_ESP_SPI (1)
+#define NET_HEADER_FIELD_IPSEC_ESP_SEQUENCE_NUM \
+(NET_HEADER_FIELD_IPSEC_ESP_SPI << 1)
+#define NET_HEADER_FIELD_IPSEC_ESP_ALL_FIELDS \
+((NET_HEADER_FIELD_IPSEC_ESP_SPI << 2) - 1)
+
+#define NET_HEADER_FIELD_IPSEC_ESP_SPI_SIZE 4
+
+#define NET_HEADER_FIELD_MPLS_LABEL_STACK (1)
+#define NET_HEADER_FIELD_MPLS_LABEL_STACK_ALL_FIELDS \
+((NET_HEADER_FIELD_MPLS_LABEL_STACK << 1) - 1)
+
+#define NET_HEADER_FIELD_MACSEC_SECTAG (1)
+#define NET_HEADER_FIELD_MACSEC_ALL_FIELDS \
+((NET_HEADER_FIELD_MACSEC_SECTAG << 1) - 1)
+
+enum net_header_type {
+ HEADER_TYPE_NONE = 0,
+ HEADER_TYPE_PAYLOAD,
+ HEADER_TYPE_ETH,
+ HEADER_TYPE_VLAN,
+ HEADER_TYPE_IPV4,
+ HEADER_TYPE_IPV6,
+ HEADER_TYPE_IP,
+ HEADER_TYPE_TCP,
+ HEADER_TYPE_UDP,
+ HEADER_TYPE_UDP_LITE,
+ HEADER_TYPE_IPHC,
+ HEADER_TYPE_SCTP,
+ HEADER_TYPE_SCTP_CHUNK_DATA,
+ HEADER_TYPE_PPPOE,
+ HEADER_TYPE_PPP,
+ HEADER_TYPE_PPPMUX,
+ HEADER_TYPE_PPPMUX_SUBFRAME,
+ HEADER_TYPE_L2TPV2,
+ HEADER_TYPE_L2TPV3_CTRL,
+ HEADER_TYPE_L2TPV3_SESS,
+ HEADER_TYPE_LLC,
+ HEADER_TYPE_LLC_SNAP,
+ HEADER_TYPE_NLPID,
+ HEADER_TYPE_SNAP,
+ HEADER_TYPE_MPLS,
+ HEADER_TYPE_IPSEC_AH,
+ HEADER_TYPE_IPSEC_ESP,
+ HEADER_TYPE_UDP_ENCAP_ESP, /* RFC 3948 */
+ HEADER_TYPE_MACSEC,
+ HEADER_TYPE_GRE,
+ HEADER_TYPE_MINENCAP,
+ HEADER_TYPE_DCCP,
+ HEADER_TYPE_ICMP,
+ HEADER_TYPE_IGMP,
+ HEADER_TYPE_ARP,
+ HEADER_TYPE_CAPWAP,
+ HEADER_TYPE_CAPWAP_DTLS,
+ HEADER_TYPE_RFC2684,
+ HEADER_TYPE_USER_DEFINED_L2,
+ HEADER_TYPE_USER_DEFINED_L3,
+ HEADER_TYPE_USER_DEFINED_L4,
+ HEADER_TYPE_USER_DEFINED_SHIM1,
+ HEADER_TYPE_USER_DEFINED_SHIM2,
+ MAX_HEADER_TYPE_COUNT
+};
+
+#endif /* __NET_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/service.h b/drivers/net/ethernet/freescale/fman/inc/service.h
new file mode 100644
index 0000000..7311d10
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/service.h
@@ -0,0 +1,90 @@
+/*
+ * 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 __SERVICE_h
+#define __SERVICE_h
+
+#include <linux/version.h>
+
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/io.h>
+
+/* Define ASSERT condition */
+#undef ASSERT
+#define ASSERT(x) WARN_ON(!(x))
+
+/* In range macro */
+#define IN_RANGE(min, val, max) ((min) <= (val) && (val) <= (max))
+
+/* Ceiling division - not the fastest way, but safer in terms of overflow */
+#define DIV_CEIL(x, y) \
+ ((div64_u64(x, y)) + (((((div64_u64(x, y))) * (y)) == (x)) ? 0 : 1))
+
+/* Round up a number to be a multiple of a second number */
+#define ROUND_UP(x, y) ((((x) + (y) - 1) / (y)) * (y))
+
+#define PTR_TO_UINT(_ptr) ((uintptr_t)(_ptr))
+#define UINT_TO_PTR(_val) ((void __iomem *)(uintptr_t)(_val))
+#define PTR_MOVE(_ptr, _offset) (void *)((uint8_t *)(_ptr) + (_offset))
+
+/* memory access macros */
+#define GET_UINT8(arg) in_be8(&(arg))
+#define GET_UINT16(arg) in_be16(&(arg))
+#define GET_UINT32(arg) in_be32(&(arg))
+#define GET_UINT64(arg) (*(__iomem uint64_t *)(&(arg)))
+
+#define WRITE_UINT8(arg, data) out_be8(&(arg), data)
+#define WRITE_UINT16(arg, data) out_be16(&(arg), data)
+#define WRITE_UINT32(arg, data) out_be32(&(arg), data)
+#define WRITE_UINT64(arg, data) (*(__iomem uint64_t *)(&(arg)) = (data))
+
+/* Timing macro for converting usec units to number of ticks
+ * (number of usec* clock_Hz) / 1,000,000) - since clk is in MHz units,
+ * no division needed.
+ */
+#define USEC_TO_CLK(usec, clk) ((usec) * (clk))
+#define CYCLES_TO_USEC(cycles, clk) ((cycles) / (clk))
+
+#define ILLEGAL_BASE (~0)
+
+/* Enumeration (bit flags) of communication modes (Transmit,
+ * receive or both).
+ */
+enum comm_mode {
+ COMM_MODE_NONE = 0, /* No transmit/receive communication */
+ COMM_MODE_RX = 1, /* Only receive communication */
+ COMM_MODE_TX = 2, /* Only transmit communication */
+ COMM_MODE_RX_AND_TX = 3 /*Both transmit and receive communication*/
+};
+
+#endif /* SERVICE */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread* [RFC,v3 09/12] fsl/fman: Add FMan MAC support
2015-05-07 13:05 ` [RFC,v3 08/12] fsl/fman: Add Frame Manager support Madalin Bucur
@ 2015-05-07 13:05 ` Madalin Bucur
0 siblings, 0 replies; 2+ messages in thread
From: Madalin Bucur @ 2015-05-07 13:05 UTC (permalink / raw)
To: netdev; +Cc: Igal Liberman
From: Igal Liberman <Igal.Liberman@freescale.com>
Add Frame Manger MAC Driver support.
This patch adds The FMan MAC configuration, initialization and
runtime control routines.
This patch contains support for these types of MACs:
tGEC, dTSEC and mEMAC
Signed-off-by: Igal Liberman <Igal.Liberman@freescale.com>
---
drivers/net/ethernet/freescale/fman/fm.c | 77 ++
drivers/net/ethernet/freescale/fman/fm.h | 4 +-
drivers/net/ethernet/freescale/fman/fm_common.h | 41 +
.../ethernet/freescale/fman/inc/crc_mac_addr_ext.h | 343 ++++++
.../net/ethernet/freescale/fman/inc/fm_mac_ext.h | 452 ++++++++
drivers/net/ethernet/freescale/fman/mac/Makefile | 7 +-
drivers/net/ethernet/freescale/fman/mac/dtsec.c | 1226 ++++++++++++++++++++
drivers/net/ethernet/freescale/fman/mac/dtsec.h | 185 +++
.../ethernet/freescale/fman/mac/dtsec_mii_acc.c | 82 ++
.../ethernet/freescale/fman/mac/dtsec_mii_acc.h | 43 +
drivers/net/ethernet/freescale/fman/mac/fm_mac.c | 510 ++++++++
drivers/net/ethernet/freescale/fman/mac/fm_mac.h | 183 +++
drivers/net/ethernet/freescale/fman/mac/memac.c | 837 +++++++++++++
drivers/net/ethernet/freescale/fman/mac/memac.h | 103 ++
.../ethernet/freescale/fman/mac/memac_mii_acc.c | 66 ++
.../ethernet/freescale/fman/mac/memac_mii_acc.h | 50 +
drivers/net/ethernet/freescale/fman/mac/tgec.c | 797 +++++++++++++
drivers/net/ethernet/freescale/fman/mac/tgec.h | 112 ++
.../net/ethernet/freescale/fman/mac/tgec_mii_acc.h | 66 ++
19 files changed, 5181 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_mac.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/fm_mac.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec.c
create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec.h
create mode 100644 drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
diff --git a/drivers/net/ethernet/freescale/fman/fm.c b/drivers/net/ethernet/freescale/fman/fm.c
index fbe4c16..c8889bd 100644
--- a/drivers/net/ethernet/freescale/fman/fm.c
+++ b/drivers/net/ethernet/freescale/fman/fm.c
@@ -703,6 +703,36 @@ static int fw_not_reset_erratum_bugzilla6173wa(struct fm_t *p_fm)
#endif /* FM_UCODE_NOT_RESET_ERRATA_BUGZILLA6173 */
/* Inter-Module functions */
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_10g_tx_ecc_workaround(void *h_fm, uint8_t mac_id)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ uint8_t rx_port_id, tx_port_id;
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ if (!(is_fman_ctrl_code_loaded(p_fm)))
+ return -ENOSYS;
+
+ SW_PORT_ID_TO_HW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+ rx_port_id,
+ FM_PORT_TYPE_RX,
+ mac_id);
+ SW_PORT_ID_TO_HW_PORT_ID(p_fm->p_fm_state_struct->rev_info.major_rev,
+ tx_port_id,
+ FM_PORT_TYPE_TX,
+ mac_id);
+
+ if ((p_fm->p_fm_state_struct->ports_types[rx_port_id] !=
+ FM_PORT_TYPE_DUMMY) ||
+ (p_fm->p_fm_state_struct->ports_types[tx_port_id] !=
+ FM_PORT_TYPE_DUMMY)) {
+ pr_err("Initialize MAC prior to Rx & Tx ports!\n");
+ return -ENOSYS;
+ }
+
+ return fman_set_erratum_10gmac_a004_wa(fpm_rg);
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
void fm_register_intr(void *h_fm, enum fm_event_modules module,
uint8_t mod_id, enum fm_intr_type intr_type,
@@ -739,6 +769,53 @@ uint8_t fm_get_id(void *h_fm)
return p_fm->p_fm_state_struct->fm_id;
}
+int fm_reset_mac(void *h_fm, enum fm_mac_type type, uint8_t mac_id)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+ int err;
+ struct fman_fpm_regs __iomem *fpm_rg = p_fm->p_fm_fpm_regs;
+
+ if (p_fm->p_fm_state_struct->rev_info.major_rev >= 6) {
+ pr_warn("FMan MAC reset!\n");
+ return -ENOSYS;
+ }
+ if (!p_fm->base_addr) {
+ pr_warn("'base_address' is required!\n");
+ return -ENOSYS;
+ }
+ err =
+ (int)fman_reset_mac(fpm_rg, mac_id);
+
+ if (err == -EINVAL) {
+ pr_warn("Illegal MAC Id\n");
+ return -EINVAL;
+ } else if (err == EINVAL) {
+ return -EINVAL;
+ }
+ return 0;
+}
+
+int fm_set_mac_max_frame(void *h_fm, enum fm_mac_type type,
+ uint8_t mac_id,
+ uint16_t mtu)
+{
+ struct fm_t *p_fm = (struct fm_t *)h_fm;
+
+ /* if port is already initialized, check that MaxFrameLength is smaller
+ * or equal to the port's max
+ */
+ if ((!p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id]) ||
+ (p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id] &&
+ (mtu <=
+ p_fm->p_fm_state_struct->port_max_frame_lengths[mac_id]))) {
+ p_fm->p_fm_state_struct->mac_max_frame_lengths[mac_id] = mtu;
+ } else {
+ pr_warn("MAC max_frame_length is larger than Port max_frame_length\n");
+ return -EDOM;
+ }
+ return 0;
+}
+
uint16_t fm_get_clock_freq(void *h_fm)
{
struct fm_t *p_fm = (struct fm_t *)h_fm;
diff --git a/drivers/net/ethernet/freescale/fman/fm.h b/drivers/net/ethernet/freescale/fman/fm.h
index ba5bb16..0f8d028 100644
--- a/drivers/net/ethernet/freescale/fman/fm.h
+++ b/drivers/net/ethernet/freescale/fman/fm.h
@@ -391,6 +391,7 @@ struct fm_state_struct_t {
/* Master/Guest parameters */
uint8_t fm_id;
+ enum fm_port_type ports_types[FM_MAX_NUM_OF_HW_PORT_IDS];
uint16_t fm_clk_freq;
struct fm_revision_info_t rev_info;
@@ -416,6 +417,8 @@ struct fm_state_struct_t {
uint32_t extra_fifo_pool_size;
uint8_t extra_tasks_pool_size;
uint8_t extra_open_dmas_pool_size;
+ uint16_t port_max_frame_lengths[FM_MAX_NUM_OF_MACS];
+ uint16_t mac_max_frame_lengths[FM_MAX_NUM_OF_MACS];
};
struct fm_intg_t {
@@ -466,7 +469,6 @@ struct fm_t {
struct fm_state_struct_t *p_fm_state_struct;
uint16_t tnum_aging_period;
-/* un-needed for recovery */
struct fman_cfg *p_fm_drv_param;
struct muram_info *p_muram;
phys_addr_t fm_muram_phys_base_addr;
diff --git a/drivers/net/ethernet/freescale/fman/fm_common.h b/drivers/net/ethernet/freescale/fman/fm_common.h
index f9d6575..4fe12c6 100644
--- a/drivers/net/ethernet/freescale/fman/fm_common.h
+++ b/drivers/net/ethernet/freescale/fman/fm_common.h
@@ -174,6 +174,30 @@ static inline bool TRY_LOCK(spinlock_t *spinlock, volatile bool *p_flag)
#define FM_CTL_PARAMS_PAGE_ERROR_VSP_MASK 0x0000003f
+/* Description Port Id defines */
+#define BASE_OH_PORTID(major) (major >= 6 ? 2 : 1)
+#define BASE_RX_PORTID 0x08
+#define BASE_TX_PORTID 0x28
+
+#define SW_PORT_ID_TO_HW_PORT_ID(major, _port, type, mac_id) \
+do { \
+ switch (type) { \
+ case (FM_PORT_TYPE_OP): \
+ _port = (uint8_t)(BASE_OH_PORTID(major) + mac_id); \
+ break; \
+ case (FM_PORT_TYPE_RX): \
+ _port = (uint8_t)(BASE_RX_PORTID + mac_id); \
+ break; \
+ case (FM_PORT_TYPE_TX): \
+ _port = (uint8_t)(BASE_TX_PORTID + mac_id); \
+ break; \
+ default: \
+ pr_err("Illegal port type\n"); \
+ _port = 0; \
+ break; \
+ } \
+} while (0)
+
#define BMI_MAX_FIFO_SIZE (FM_MURAM_SIZE)
#define BMI_FIFO_UNITS 0x100
@@ -292,6 +316,16 @@ struct muram_info *fm_get_muram_pointer(void *h_fm);
void fm_get_physical_muram_base(void *h_fm,
struct fm_phys_addr_t *fm_phys_addr);
+/* Function fm_reset_mac
+ * Description Used by MAC driver to reset the MAC registers
+ * Param[in] h_fm A handle to an FM Module.
+ * Param[in] type MAC type.
+ * Param[in] mac_id MAC id - according to type.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_init().
+ */
+int fm_reset_mac(void *h_fm, enum fm_mac_type type, uint8_t mac_id);
+
/* Function fm_get_clock_freq
* Description Used by MAC driver to get the FM clock frequency
* Param[in] h_fm A handle to an FM Module.
@@ -308,6 +342,10 @@ uint16_t fm_get_clock_freq(void *h_fm);
*/
uint8_t fm_get_id(void *h_fm);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_10g_tx_ecc_workaround(void *h_fm, uint8_t mac_id);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
void fm_muram_clear(struct muram_info *p_muram);
int fm_set_num_of_open_dmas(void *h_fm,
uint8_t port_id,
@@ -328,4 +366,7 @@ int fm_set_size_of_fifo(void *h_fm,
uint32_t fm_get_bmi_max_fifo_size(void *h_fm);
struct num_of_ports_info_t *fm_get_num_of_ports(void *h_fm);
+int fm_set_mac_max_frame(void *h_fm, enum fm_mac_type type,
+ uint8_t mac_id, uint16_t mtu);
+
#endif /* __FM_COMMON_H */
diff --git a/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h b/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
new file mode 100644
index 0000000..12468cb
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/crc_mac_addr_ext.h
@@ -0,0 +1,343 @@
+/*
+ * 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 a macro that calculate the crc value of an Ethernet MAC address
+ * (48 bitd address)
+ */
+
+#ifndef __crc_mac_addr_ext_h
+#define __crc_mac_addr_ext_h
+
+#include <linux/bitrev.h>
+
+static uint32_t crc_table[256] = {
+ 0x00000000,
+ 0x77073096,
+ 0xee0e612c,
+ 0x990951ba,
+ 0x076dc419,
+ 0x706af48f,
+ 0xe963a535,
+ 0x9e6495a3,
+ 0x0edb8832,
+ 0x79dcb8a4,
+ 0xe0d5e91e,
+ 0x97d2d988,
+ 0x09b64c2b,
+ 0x7eb17cbd,
+ 0xe7b82d07,
+ 0x90bf1d91,
+ 0x1db71064,
+ 0x6ab020f2,
+ 0xf3b97148,
+ 0x84be41de,
+ 0x1adad47d,
+ 0x6ddde4eb,
+ 0xf4d4b551,
+ 0x83d385c7,
+ 0x136c9856,
+ 0x646ba8c0,
+ 0xfd62f97a,
+ 0x8a65c9ec,
+ 0x14015c4f,
+ 0x63066cd9,
+ 0xfa0f3d63,
+ 0x8d080df5,
+ 0x3b6e20c8,
+ 0x4c69105e,
+ 0xd56041e4,
+ 0xa2677172,
+ 0x3c03e4d1,
+ 0x4b04d447,
+ 0xd20d85fd,
+ 0xa50ab56b,
+ 0x35b5a8fa,
+ 0x42b2986c,
+ 0xdbbbc9d6,
+ 0xacbcf940,
+ 0x32d86ce3,
+ 0x45df5c75,
+ 0xdcd60dcf,
+ 0xabd13d59,
+ 0x26d930ac,
+ 0x51de003a,
+ 0xc8d75180,
+ 0xbfd06116,
+ 0x21b4f4b5,
+ 0x56b3c423,
+ 0xcfba9599,
+ 0xb8bda50f,
+ 0x2802b89e,
+ 0x5f058808,
+ 0xc60cd9b2,
+ 0xb10be924,
+ 0x2f6f7c87,
+ 0x58684c11,
+ 0xc1611dab,
+ 0xb6662d3d,
+ 0x76dc4190,
+ 0x01db7106,
+ 0x98d220bc,
+ 0xefd5102a,
+ 0x71b18589,
+ 0x06b6b51f,
+ 0x9fbfe4a5,
+ 0xe8b8d433,
+ 0x7807c9a2,
+ 0x0f00f934,
+ 0x9609a88e,
+ 0xe10e9818,
+ 0x7f6a0dbb,
+ 0x086d3d2d,
+ 0x91646c97,
+ 0xe6635c01,
+ 0x6b6b51f4,
+ 0x1c6c6162,
+ 0x856530d8,
+ 0xf262004e,
+ 0x6c0695ed,
+ 0x1b01a57b,
+ 0x8208f4c1,
+ 0xf50fc457,
+ 0x65b0d9c6,
+ 0x12b7e950,
+ 0x8bbeb8ea,
+ 0xfcb9887c,
+ 0x62dd1ddf,
+ 0x15da2d49,
+ 0x8cd37cf3,
+ 0xfbd44c65,
+ 0x4db26158,
+ 0x3ab551ce,
+ 0xa3bc0074,
+ 0xd4bb30e2,
+ 0x4adfa541,
+ 0x3dd895d7,
+ 0xa4d1c46d,
+ 0xd3d6f4fb,
+ 0x4369e96a,
+ 0x346ed9fc,
+ 0xad678846,
+ 0xda60b8d0,
+ 0x44042d73,
+ 0x33031de5,
+ 0xaa0a4c5f,
+ 0xdd0d7cc9,
+ 0x5005713c,
+ 0x270241aa,
+ 0xbe0b1010,
+ 0xc90c2086,
+ 0x5768b525,
+ 0x206f85b3,
+ 0xb966d409,
+ 0xce61e49f,
+ 0x5edef90e,
+ 0x29d9c998,
+ 0xb0d09822,
+ 0xc7d7a8b4,
+ 0x59b33d17,
+ 0x2eb40d81,
+ 0xb7bd5c3b,
+ 0xc0ba6cad,
+ 0xedb88320,
+ 0x9abfb3b6,
+ 0x03b6e20c,
+ 0x74b1d29a,
+ 0xead54739,
+ 0x9dd277af,
+ 0x04db2615,
+ 0x73dc1683,
+ 0xe3630b12,
+ 0x94643b84,
+ 0x0d6d6a3e,
+ 0x7a6a5aa8,
+ 0xe40ecf0b,
+ 0x9309ff9d,
+ 0x0a00ae27,
+ 0x7d079eb1,
+ 0xf00f9344,
+ 0x8708a3d2,
+ 0x1e01f268,
+ 0x6906c2fe,
+ 0xf762575d,
+ 0x806567cb,
+ 0x196c3671,
+ 0x6e6b06e7,
+ 0xfed41b76,
+ 0x89d32be0,
+ 0x10da7a5a,
+ 0x67dd4acc,
+ 0xf9b9df6f,
+ 0x8ebeeff9,
+ 0x17b7be43,
+ 0x60b08ed5,
+ 0xd6d6a3e8,
+ 0xa1d1937e,
+ 0x38d8c2c4,
+ 0x4fdff252,
+ 0xd1bb67f1,
+ 0xa6bc5767,
+ 0x3fb506dd,
+ 0x48b2364b,
+ 0xd80d2bda,
+ 0xaf0a1b4c,
+ 0x36034af6,
+ 0x41047a60,
+ 0xdf60efc3,
+ 0xa867df55,
+ 0x316e8eef,
+ 0x4669be79,
+ 0xcb61b38c,
+ 0xbc66831a,
+ 0x256fd2a0,
+ 0x5268e236,
+ 0xcc0c7795,
+ 0xbb0b4703,
+ 0x220216b9,
+ 0x5505262f,
+ 0xc5ba3bbe,
+ 0xb2bd0b28,
+ 0x2bb45a92,
+ 0x5cb36a04,
+ 0xc2d7ffa7,
+ 0xb5d0cf31,
+ 0x2cd99e8b,
+ 0x5bdeae1d,
+ 0x9b64c2b0,
+ 0xec63f226,
+ 0x756aa39c,
+ 0x026d930a,
+ 0x9c0906a9,
+ 0xeb0e363f,
+ 0x72076785,
+ 0x05005713,
+ 0x95bf4a82,
+ 0xe2b87a14,
+ 0x7bb12bae,
+ 0x0cb61b38,
+ 0x92d28e9b,
+ 0xe5d5be0d,
+ 0x7cdcefb7,
+ 0x0bdbdf21,
+ 0x86d3d2d4,
+ 0xf1d4e242,
+ 0x68ddb3f8,
+ 0x1fda836e,
+ 0x81be16cd,
+ 0xf6b9265b,
+ 0x6fb077e1,
+ 0x18b74777,
+ 0x88085ae6,
+ 0xff0f6a70,
+ 0x66063bca,
+ 0x11010b5c,
+ 0x8f659eff,
+ 0xf862ae69,
+ 0x616bffd3,
+ 0x166ccf45,
+ 0xa00ae278,
+ 0xd70dd2ee,
+ 0x4e048354,
+ 0x3903b3c2,
+ 0xa7672661,
+ 0xd06016f7,
+ 0x4969474d,
+ 0x3e6e77db,
+ 0xaed16a4a,
+ 0xd9d65adc,
+ 0x40df0b66,
+ 0x37d83bf0,
+ 0xa9bcae53,
+ 0xdebb9ec5,
+ 0x47b2cf7f,
+ 0x30b5ffe9,
+ 0xbdbdf21c,
+ 0xcabac28a,
+ 0x53b39330,
+ 0x24b4a3a6,
+ 0xbad03605,
+ 0xcdd70693,
+ 0x54de5729,
+ 0x23d967bf,
+ 0xb3667a2e,
+ 0xc4614ab8,
+ 0x5d681b02,
+ 0x2a6f2b94,
+ 0xb40bbe37,
+ 0xc30c8ea1,
+ 0x5a05df1b,
+ 0x2d02ef8d
+};
+
+/* CRC calculation */
+#define GET_MAC_ADDR_CRC(addr, crc) \
+{ \
+ uint32_t i; \
+ uint8_t data; \
+ crc = 0xffffffff; \
+ for (i = 0; i < 6; i++) { \
+ data = (uint8_t)(addr >> ((5 - i) * 8)); \
+ crc = crc ^ data; \
+ crc = crc_table[crc & 0xff] ^ (crc >> 8); \
+ } \
+} \
+
+/* Define a macro for getting the mirrored value of */
+/* a byte size number. (0x11010011 --> 0x11001011) */
+/* Sometimes the mirrored value of the CRC is required */
+static inline uint8_t swab(uint8_t n)
+{
+ uint8_t mirror[16] = {
+ 0x00,
+ 0x08,
+ 0x04,
+ 0x0c,
+ 0x02,
+ 0x0a,
+ 0x06,
+ 0x0e,
+ 0x01,
+ 0x09,
+ 0x05,
+ 0x0d,
+ 0x03,
+ 0x0b,
+ 0x07,
+ 0x0f
+ };
+ return ((uint8_t)(((mirror[n & 0x0f] << 4) | (mirror[n >> 4]))));
+}
+
+#define MIRROR bitrev
+#define MIRROR_32 bitrev32
+
+#endif /* __crc_mac_addr_ext_h */
diff --git a/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h b/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
new file mode 100644
index 0000000..4d4b211
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/inc/fm_mac_ext.h
@@ -0,0 +1,452 @@
+/*
+ * 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_mac_ext.h
+ * Description FM MAC ...
+ */
+#ifndef __FM_MAC_EXT_H
+#define __FM_MAC_EXT_H
+
+#include "service.h"
+#include "enet_ext.h"
+#include "dpaa_integration_ext.h"
+
+struct fm_mac_dev;
+
+/* Description FM MAC API functions, definitions and enums */
+
+#define FM_MAC_NO_PFC 0xff
+
+/* FM MAC Exceptions */
+enum fm_mac_exceptions {
+ FM_MAC_EX_10G_MDIO_SCAN_EVENT = 0
+ /* 10GEC MDIO scan event interrupt */
+ , FM_MAC_EX_10G_MDIO_CMD_CMPL
+ /* 10GEC MDIO command completion interrupt */
+ , FM_MAC_EX_10G_REM_FAULT
+ /* 10GEC, mEMAC Remote fault interrupt */
+ , FM_MAC_EX_10G_LOC_FAULT
+ /* 10GEC, mEMAC Local fault interrupt */
+ , FM_MAC_EX_10G_1TX_ECC_ER
+ /* 10GEC, mEMAC Transmit frame ECC error interrupt */
+ , FM_MAC_EX_10G_TX_FIFO_UNFL
+ /* 10GEC, mEMAC Transmit FIFO underflow interrupt */
+ , FM_MAC_EX_10G_TX_FIFO_OVFL
+ /* 10GEC, mEMAC Transmit FIFO overflow interrupt */
+ , FM_MAC_EX_10G_TX_ER
+ /* 10GEC Transmit frame error interrupt */
+ , FM_MAC_EX_10G_RX_FIFO_OVFL
+ /* 10GEC, mEMAC Receive FIFO overflow interrupt */
+ , FM_MAC_EX_10G_RX_ECC_ER
+ /* 10GEC, mEMAC Receive frame ECC error interrupt */
+ , FM_MAC_EX_10G_RX_JAB_FRM
+ /* 10GEC Receive jabber frame interrupt */
+ , FM_MAC_EX_10G_RX_OVRSZ_FRM
+ /* 10GEC Receive oversized frame interrupt */
+ , FM_MAC_EX_10G_RX_RUNT_FRM
+ /* 10GEC Receive runt frame interrupt */
+ , FM_MAC_EX_10G_RX_FRAG_FRM
+ /* 10GEC Receive fragment frame interrupt */
+ , FM_MAC_EX_10G_RX_LEN_ER
+ /* 10GEC Receive payload length error interrupt */
+ , FM_MAC_EX_10G_RX_CRC_ER
+ /* 10GEC Receive CRC error interrupt */
+ , FM_MAC_EX_10G_RX_ALIGN_ER
+ /* 10GEC Receive alignment error interrupt */
+ , FM_MAC_EX_1G_BAB_RX
+ /* dTSEC Babbling receive error */
+ , FM_MAC_EX_1G_RX_CTL
+ /* dTSEC Receive control (pause frame) interrupt */
+ , FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET
+ /* dTSEC Graceful transmit stop complete */
+ , FM_MAC_EX_1G_BAB_TX
+ /* dTSEC Babbling transmit error */
+ , FM_MAC_EX_1G_TX_CTL
+ /* dTSEC Transmit control (pause frame) interrupt */
+ , FM_MAC_EX_1G_TX_ERR
+ /* dTSEC Transmit error */
+ , FM_MAC_EX_1G_LATE_COL
+ /* dTSEC Late collision */
+ , FM_MAC_EX_1G_COL_RET_LMT
+ /* dTSEC Collision retry limit */
+ , FM_MAC_EX_1G_TX_FIFO_UNDRN
+ /* dTSEC Transmit FIFO underrun */
+ , FM_MAC_EX_1G_MAG_PCKT
+ /* dTSEC Magic Packet detection */
+ , FM_MAC_EX_1G_MII_MNG_RD_COMPLET
+ /* dTSEC MII management read completion */
+ , FM_MAC_EX_1G_MII_MNG_WR_COMPLET
+ /* dTSEC MII management write completion */
+ , FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET
+ /* dTSEC Graceful receive stop complete */
+ , FM_MAC_EX_1G_DATA_ERR
+ /* dTSEC Internal data error on transmit */
+ , FM_MAC_1G_RX_DATA_ERR
+ /* dTSEC Internal data error on receive */
+ , FM_MAC_EX_1G_1588_TS_RX_ERR
+ /* dTSEC Time-Stamp Receive Error */
+ , FM_MAC_EX_1G_RX_MIB_CNT_OVFL
+ /* dTSEC MIB counter overflow */
+ , FM_MAC_EX_TS_FIFO_ECC_ERR
+ /* mEMAC Time-stamp FIFO ECC error interrupt;
+ * not supported on T4240/B4860 rev1 chips
+ */
+ , FM_MAC_EX_MAGIC_PACKET_INDICATION = FM_MAC_EX_1G_MAG_PCKT
+ /* mEMAC Magic Packet Indication Interrupt */
+};
+
+/* Function fm_mac_exception_cb
+ * Description Fm Mac Exception Callback from FM MAC to the user
+ * Param[in] h_app - Handle to the upper layer handler
+ * Param[in] exceptions - The exception that occurred
+ * Return void.
+ */
+typedef void (fm_mac_exception_cb) (void *h_app,
+ enum fm_mac_exceptions exceptions);
+
+/* FM MAC Initialization Unit */
+
+/* FM MAC config input */
+struct fm_mac_params_t {
+ /* Base of memory mapped FM MAC registers */
+ uintptr_t base_addr;
+ /* MAC address of device; First octet is sent first */
+ enet_addr_t addr;
+ /* MAC ID; numbering of dTSEC and 1G-mEMAC:
+ * 0 - FM_MAX_NUM_OF_1G_MACS;
+ * numbering of 10G-MAC (TGEC) and 10G-mEMAC:
+ * 0 - FM_MAX_NUM_OF_10G_MACS
+ */
+ uint8_t mac_id;
+ /* Ethernet operation mode (MAC-PHY interface and speed);
+ * Note that the speed should indicate the maximum rate that
+ * this MAC should support rather than the actual speed;
+ * i.e. user should use the FM_MAC_AdjustLink() routine to
+ * provide accurate speed;
+ * In case of mEMAC RGMII mode, the MAC is configured to RGMII
+ * automatic mode, where actual speed/duplex mode information
+ * is provided by PHY automatically in-band; FM_MAC_AdjustLink()
+ * function should be used to switch to manual RGMII speed/duplex mode
+ * configuration if RGMII PHY doesn't support in-band status signaling;
+ * In addition, in mEMAC, in case where user is using the higher MACs
+ * (i.e. the MACs that should support 10G), user should pass here
+ * speed=10000 even if the interface is not allowing that (e.g. SGMII).
+ */
+ enum e_enet_mode enet_mode;
+ /* A handle to the FM object this port related to */
+ void *h_fm;
+ /* MDIO exceptions interrupt source - not valid for all
+ * MACs; MUST be set to 'NO_IRQ' for MACs that don't have
+ * mdio-irq, or for polling
+ */
+ int mdio_irq;
+ fm_mac_exception_cb *f_event; /* MDIO Events Callback Routine */
+ fm_mac_exception_cb *f_exception; /* Exception Callback Routine */
+ void *h_app; /* A handle to an application layer object;
+ * This handle will be passed by the driver
+ * upon calling the above callbacks
+ */
+};
+
+struct fm_mac_dev;
+
+/* Function fm_mac_config
+ * Description Creates descriptor for the FM MAC module.
+ * The routine returns a pointer to the FM MAC object.
+ * This pointer must be passed as first parameter to all other
+ * FM MAC function calls.
+ * No actual initialization or configuration of FM MAC hardware
+ * is done by this routine.
+ * Param[in] p_fm_mac_param - Pointer to data structure of parameters
+ * Retval Pointer to FM MAC object, or NULL for Failure.
+ */
+struct fm_mac_dev *fm_mac_config(struct fm_mac_params_t *p_fm_mac_param);
+
+/* Function fm_mac_init
+ * Description Initializes the FM MAC module
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev);
+
+/* Function fm_free
+ * Description Frees all resources that were assigned to FM MAC module.
+ * Calling this routine invalidates the descriptor.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev);
+
+/* Description Configuration functions used to change default values. */
+
+/* Function fm_mac_cfg_reset_on_init
+ * Description Tell the driver whether to reset the FM MAC before
+ * initialization or not. It changes the default configuration
+ * [DEFAULT_RESET_ON_INIT].
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable - When true, FM will be reset before initialization.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_cfg_max_frame_len
+ * Description Setup maximum Rx Frame Length (in 1G MAC, effects also Tx)
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] new_val - MAX Frame length
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_max_frame_len(struct fm_mac_dev *fm_mac_dev, uint16_t new_val);
+
+/* Function fm_mac_cfg_pad_and_crc
+ * Description Config PAD and CRC mode
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable - true to enable or false to disable.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ * Not supported on 10G-MAC (i.e. CRC&PAD are added
+ * automatically by HW); on mEMAC, this routine supports only
+ * PAD (i.e. CRC is added automatically by HW).
+ */
+int fm_mac_cfg_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_cfg_tbi_phy_addr
+ * Description Configures the address of internal TBI PHY.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] new_val - TBI PHY address (1-31).
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_tbi_phy_addr(struct fm_mac_dev *fm_mac_dev, uint8_t new_val);
+
+/* Function fm_mac_cfg_len_check
+ * Description Configure the frame length checking.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable - true to enable or false to disable.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_len_check(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_cfg_exception
+ * Description Change Exception selection from default
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] ex - Type of the desired exceptions
+ * Param[in] enable - true to enable the specified exception,
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_config() and before
+ * fm_mac_init().
+ */
+int fm_mac_cfg_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable);
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_mac_cfg_skip_fman11_wa(struct fm_mac_dev *fm_mac_dev);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* FM MAC Runtime control unit API functions, definitions and enums. */
+
+/* Function fm_mac_enable
+ * Description Enable the MAC
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] mode - Mode of operation (RX, TX, Both)
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_enable(struct fm_mac_dev*, enum comm_mode mode);
+
+/* Function fm_mac_disable
+ * Description Disavle the MAC
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] mode - Mode of operation (RX, TX, Both)
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode);
+
+#define FSL_FM_PAUSE_TIME_ENABLE 0xf000
+#define FSL_FM_PAUSE_TIME_DISABLE 0
+#define FSL_FM_PAUSE_THRESH_DEFAULT 0
+
+/* Function fm_mac_set_tx_pause_frames
+ * Description Enable/Disable transmission of Pause-Frames.
+ * The routine changes the default configuration:
+ * pause-time - [DEFAULT_TX_PAUSE_TIME]
+ * threshold-time - [0]
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] priority - the PFC class of service; use 'FM_MAC_NO_PFC'
+ * to indicate legacy pause support (i.e. no PFC).
+ * Param[in] pause_time - Pause quanta value used with transmitted pause
+ * frames. Each quanta represents a 512 bit-times;
+ * Note that '0' as an input here will be used as disabling the
+ * transmission of the pause-frames.
+ * Param[in] For legacy pause support (i.e. no PFC), thus
+ * value should be '0'.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time);
+
+/* Function fm_mac_set_rx_pause_frames
+ * Description Enable/Disable rx Pause-Frames.
+ * Param[in] fm_mac_dev - A Pointer to MAC object
+ * Param[in] en - boolean indicates whether to ignore the incoming pause
+ * frames or not.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_set_rx_pause_frames(struct fm_mac_dev *fm_mac_dev, bool en);
+
+/* Function fm_mac_set_exception
+ * Description Enable/Disable a specific Exception
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] ex - Type of the desired exceptions
+ * Param[in] enable - true to enable the specified exception,
+ * false to disable it.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable);
+
+/* Function fm_mac_modify_mac_addr
+ * Description Replace the main MAC Address
+ * Param[in] fm_mac_dev - A pointer to MAC object
+ * Param[in] p_enet_addr - Ethernet Mac address
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr);
+
+/* Function fm_mac_add_hash_mac_addr
+ * Description Add an Address to the hash table. This is for filter purpose
+ * only.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] p_enet_addr - Ethernet Mac address
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ * It is a filter only address.
+ * Cautions Some address need to be filterd out in upper FM blocks.
+ */
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr);
+
+/* Function fm_mac_remove_hash_mac_addr
+ * Description Delete an Address to the hash table. This is for filter
+ * purpose only.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] p_enet_addr - Ethernet Mac address
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only following fm_mac_init().
+ */
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr);
+
+/* Function fm_mac_set_promiscuous
+ * Description Enable/Disable MAC Promiscuous mode for ALL mac addresses.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[in] enable -true to enable or false to disable.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, bool enable);
+
+/* Function fm_mac_adjust_link
+ * Description Adjusts the Ethernet link with new speed/duplex setup.
+ * This routine is relevant for dTSEC and mEMAC.
+ * In case of mEMAC, this routine is also used for manual
+ * re-configuration of RGMII speed and duplex mode for
+ * RGMII PHYs not supporting in-band status information to MAC.
+ * Param[in] fm_mac_dev - A pointer to MAC object
+ * Param[in] speed - Ethernet speed.
+ * false for half-duplex mode.
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, int link,
+ enum ethernet_speed speed);
+
+/* Function fm_mac_restart_autoneg
+ * Description Restarts the auto-negotiation process.
+ * When auto-negotiation process is invoked under traffic the
+ * auto-negotiation process between the internal SGMII PHY and
+ * the external PHY does not always complete successfully.
+ * Calling this function will restart the auto-negotiation
+ * process that will end successfully. It is recommended to
+ * call this function after issuing auto-negotiation restart
+ * command to the Eth Phy.
+ * This routine is relevant only for dTSEC.
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Return 0 on success; Error code otherwise.
+ */
+int fm_mac_restart_autoneg(struct fm_mac_dev *fm_mac_dev);
+
+/* Function fm_mac_get_max_frame_length
+ * Description Return the max frame length value
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[out] p_mac_id - MAC ID of device.
+ * Return the maximum frame length value
+ * Cautions Allowed only after fm_mac_init().
+ */
+uint16_t fm_mac_get_max_frame_length(struct fm_mac_dev *fm_mac_dev);
+
+/* Function fm_mac_get_id
+ * Description Return the MAC ID
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[out] p_mac_id - MAC ID of device.
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_get_id(struct fm_mac_dev *fm_mac_dev, uint32_t *p_mac_id);
+
+/* Function fm_mac_get_version
+ * Description Return Mac HW chip version
+ * Param[in] fm_mac_dev - Pointer to MAC object
+ * Param[out] p_mac_version - Mac version as defined by the chip
+ * Return 0 on success; Error code otherwise.
+ * Cautions Allowed only after fm_mac_init().
+ */
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev,
+ uint32_t *p_mac_version);
+
+#endif /* __FM_MAC_EXT_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/Makefile b/drivers/net/ethernet/freescale/fman/mac/Makefile
index 80b7048..042a1f7 100644
--- a/drivers/net/ethernet/freescale/fman/mac/Makefile
+++ b/drivers/net/ethernet/freescale/fman/mac/Makefile
@@ -1,5 +1,8 @@
obj-$(CONFIG_FSL_FMAN_MAC) += fsl_fman_mac.o
fsl_fman_mac-objs := fman_dtsec.o fman_dtsec_mii_acc.o \
- fman_memac.o fman_tgec.o \
- fman_crc32.o fman_memac_mii_acc.o
+ dtsec.o dtsec_mii_acc.o \
+ fman_memac.o fman_memac_mii_acc.o \
+ memac.o memac_mii_acc.o \
+ fman_tgec.o tgec.o \
+ fman_crc32.o fm_mac.o
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec.c b/drivers/net/ethernet/freescale/fman/mac/dtsec.c
new file mode 100644
index 0000000..e5c830b
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec.c
@@ -0,0 +1,1226 @@
+/*
+ * 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.
+ */
+
+/* FMan dTSEC driver */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/bitrev.h>
+
+/* Internal routines */
+
+static int check_init_parameters(struct dtsec_t *p_dtsec)
+{
+ if (ENET_SPEED_FROM_MODE(p_dtsec->enet_mode) >= ENET_SPEED_10000) {
+ pr_err("1G MAC driver supports 1G or lower speeds\n");
+ return -EDOM;
+ }
+ if (p_dtsec->addr == 0) {
+ pr_err("Ethernet MAC Must have a valid MAC Address\n");
+ return -EDOM;
+ }
+ if ((ENET_SPEED_FROM_MODE(p_dtsec->enet_mode) >= ENET_SPEED_1000) &&
+ p_dtsec->p_dtsec_drv_param->halfdup_on) {
+ pr_err("Ethernet MAC 1G can't work in half duplex\n");
+ return -EDOM;
+ }
+#ifdef FM_RX_PREAM_4_ERRATA_DTSEC_A001
+ /* fixed for rev3 */
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev <= 6)
+ if (p_dtsec->p_dtsec_drv_param->rx_preamble) {
+ pr_err("preambleRxEn\n");
+ return -ENOSYS;
+ }
+#endif /* FM_RX_PREAM_4_ERRATA_DTSEC_A001 */
+ if (((p_dtsec->p_dtsec_drv_param)->tx_preamble ||
+ (p_dtsec->p_dtsec_drv_param)->rx_preamble) &&
+ ((p_dtsec->p_dtsec_drv_param)->preamble_len != 0x7)) {
+ pr_err("Preamble length should be 0x7 bytes\n");
+ return -EDOM;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_on &&
+ (p_dtsec->p_dtsec_drv_param->tx_time_stamp_en ||
+ p_dtsec->p_dtsec_drv_param->rx_time_stamp_en)) {
+ pr_err("1588 timeStamp disabled in half duplex mode\n");
+ return -EDOM;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->rx_flow &&
+ (p_dtsec->p_dtsec_drv_param)->rx_ctrl_acc) {
+ pr_err("Receive control frame can not be accepted\n");
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->rx_prepend >
+ MAX_PACKET_ALIGNMENT) {
+ pr_err("packetAlignmentPadding can't be > than %d\n",
+ MAX_PACKET_ALIGNMENT);
+ return -ENOSYS;
+ }
+ if (((p_dtsec->p_dtsec_drv_param)->non_back_to_back_ipg1 >
+ MAX_INTER_PACKET_GAP) ||
+ ((p_dtsec->p_dtsec_drv_param)->non_back_to_back_ipg2 >
+ MAX_INTER_PACKET_GAP) ||
+ ((p_dtsec->p_dtsec_drv_param)->back_to_back_ipg >
+ MAX_INTER_PACKET_GAP)) {
+ pr_err("Inter packet gap can't be greater than %d\n",
+ MAX_INTER_PACKET_GAP);
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_alt_backoff_val >
+ MAX_INTER_PALTERNATE_BEB) {
+ pr_err("alternateBackoffVal can't be greater than %d\n",
+ MAX_INTER_PALTERNATE_BEB);
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_retransmit >
+ MAX_RETRANSMISSION) {
+ pr_err("maxRetransmission can't be greater than %d\n",
+ MAX_RETRANSMISSION);
+ return -ENOSYS;
+ }
+ if ((p_dtsec->p_dtsec_drv_param)->halfdup_coll_window >
+ MAX_COLLISION_WINDOW) {
+ pr_err("collisionWindow can't be greater than %d\n",
+ MAX_COLLISION_WINDOW);
+ return -ENOSYS;
+ /* If Auto negotiation process is disabled, need to */
+ /* Set up the PHY using the MII Management Interface */
+ }
+ if (p_dtsec->p_dtsec_drv_param->tbipa > MAX_PHYS) {
+ pr_err("PHY address (should be 0-%d)\n", MAX_PHYS);
+ return -ERANGE;
+ }
+ if (!p_dtsec->f_exception) {
+ pr_err("uninitialized f_exception\n");
+ return -EINVAL;
+ }
+ if (!p_dtsec->f_event) {
+ pr_err("uninitialized f_event\n");
+ return -EINVAL;
+ }
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev != 4 &&
+ p_dtsec->p_dtsec_drv_param->rx_len_check) {
+ pr_warn("LengthCheck!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+ uint32_t bit_mask;
+
+ switch (exception) {
+ case FM_MAC_EX_1G_BAB_RX:
+ bit_mask = DTSEC_IMASK_BREN;
+ break;
+ case FM_MAC_EX_1G_RX_CTL:
+ bit_mask = DTSEC_IMASK_RXCEN;
+ break;
+ case FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET:
+ bit_mask = DTSEC_IMASK_GTSCEN;
+ break;
+ case FM_MAC_EX_1G_BAB_TX:
+ bit_mask = DTSEC_IMASK_BTEN;
+ break;
+ case FM_MAC_EX_1G_TX_CTL:
+ bit_mask = DTSEC_IMASK_TXCEN;
+ break;
+ case FM_MAC_EX_1G_TX_ERR:
+ bit_mask = DTSEC_IMASK_TXEEN;
+ break;
+ case FM_MAC_EX_1G_LATE_COL:
+ bit_mask = DTSEC_IMASK_LCEN;
+ break;
+ case FM_MAC_EX_1G_COL_RET_LMT:
+ bit_mask = DTSEC_IMASK_CRLEN;
+ break;
+ case FM_MAC_EX_1G_TX_FIFO_UNDRN:
+ bit_mask = DTSEC_IMASK_XFUNEN;
+ break;
+ case FM_MAC_EX_1G_MAG_PCKT:
+ bit_mask = DTSEC_IMASK_MAGEN;
+ break;
+ case FM_MAC_EX_1G_MII_MNG_RD_COMPLET:
+ bit_mask = DTSEC_IMASK_MMRDEN;
+ break;
+ case FM_MAC_EX_1G_MII_MNG_WR_COMPLET:
+ bit_mask = DTSEC_IMASK_MMWREN;
+ break;
+ case FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET:
+ bit_mask = DTSEC_IMASK_GRSCEN;
+ break;
+ case FM_MAC_EX_1G_DATA_ERR:
+ bit_mask = DTSEC_IMASK_TDPEEN;
+ break;
+ case FM_MAC_EX_1G_RX_MIB_CNT_OVFL:
+ bit_mask = DTSEC_IMASK_MSROEN;
+ break;
+ default:
+ bit_mask = 0;
+ break;
+ }
+
+ return bit_mask;
+}
+
+/* Checks if p_dtsec driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct dtsec_cfg *p_dtsec_drv_parameters)
+{
+ if (!p_dtsec_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(eth_addr, crc);
+
+ crc = bitrev32(crc);
+
+ return crc;
+}
+
+static uint16_t dtsec_get_max_frame_length(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return 0;
+
+ return fman_dtsec_get_max_frame_len(p_dtsec->p_mem_map);
+}
+
+static void dtsec_isr(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t event;
+ struct dtsec_regs __iomem *p_dtsec_mem_map = p_dtsec->p_mem_map;
+
+ /* do not handle MDIO events */
+ event =
+ fman_dtsec_get_event(p_dtsec_mem_map,
+ (uint32_t)(~
+ (DTSEC_IMASK_MMRDEN |
+ DTSEC_IMASK_MMWREN)));
+
+ event &= fman_dtsec_get_interrupt_mask(p_dtsec_mem_map);
+
+ fman_dtsec_ack_event(p_dtsec_mem_map, event);
+
+ if (event & DTSEC_IMASK_BREN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_BAB_RX);
+ if (event & DTSEC_IMASK_RXCEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_RX_CTL);
+ if (event & DTSEC_IMASK_GTSCEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_GRATEFUL_TX_STP_COMPLET);
+ if (event & DTSEC_IMASK_BTEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_BAB_TX);
+ if (event & DTSEC_IMASK_TXCEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_TX_CTL);
+ if (event & DTSEC_IMASK_TXEEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_TX_ERR);
+ if (event & DTSEC_IMASK_LCEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_LATE_COL);
+ if (event & DTSEC_IMASK_CRLEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_COL_RET_LMT);
+ if (event & DTSEC_IMASK_XFUNEN) {
+#ifdef FM_TX_LOCKUP_ERRATA_DTSEC6
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2) {
+ uint32_t tpkt1, tmp_reg1, tpkt2, tmp_reg2, i;
+ /* a. Write 0x00E0_0C00 to DTSEC_ID */
+ /* This is a read only regidter
+ */
+
+ /* b. Read and save the value of TPKT */
+ tpkt1 = GET_UINT32(p_dtsec_mem_map->tpkt);
+
+ /* c. Read the register at dTSEC address offset 0x32C */
+ tmp_reg1 =
+ GET_UINT32(*(uint32_t *)
+ ((uint8_t *)p_dtsec_mem_map + 0x32c));
+
+ /* d. Compare bits [9:15] to bits [25:31] of the
+ * register at address offset 0x32C.
+ */
+ if ((tmp_reg1 & 0x007F0000) !=
+ (tmp_reg1 & 0x0000007F)) {
+ /* If they are not equal, save the value of
+ * this register and wait for at least
+ * MAXFRM*16 ns
+ */
+ usleep_range((uint32_t)(min
+ (dtsec_get_max_frame_length(p_dtsec) *
+ 16 / 1000, 1)), (uint32_t)
+ (min(dtsec_get_max_frame_length
+ (p_dtsec) * 16 / 1000, 1) + 1));
+ }
+
+ /* e. Read and save TPKT again and read the register
+ * at dTSEC address offset 0x32C again
+ */
+ tpkt2 = GET_UINT32(p_dtsec_mem_map->tpkt);
+ tmp_reg2 =
+ GET_UINT32(*(uint32_t __iomem *)
+ ((uint8_t *)p_dtsec_mem_map + 0x32c));
+
+ /* f. Compare the value of TPKT saved in step b to
+ * value read in step e. Also compare bits [9:15] of
+ * the register at offset 0x32C saved in step d to the
+ * value of bits [9:15] saved in step e. If the two
+ * registers values are unchanged, then the transmit
+ * portion of the dTSEC controller is locked up and
+ * the user should proceed to the recover sequence.
+ */
+ if ((tpkt1 == tpkt2) && ((tmp_reg1 & 0x007F0000) ==
+ (tmp_reg2 & 0x007F0000))) {
+ /* recover sequence */
+
+ /* a.Write a 1 to RCTRL[GRS] */
+
+ WRITE_UINT32(p_dtsec_mem_map->rctrl,
+ GET_UINT32(p_dtsec_mem_map->
+ rctrl) | RCTRL_GRS);
+
+ /* b.Wait until IEVENT[GRSC]=1, or at least
+ * 100 us has elapsed.
+ */
+ for (i = 0; i < 100; i++) {
+ if (GET_UINT32(p_dtsec_mem_map->
+ ievent) &
+ DTSEC_IMASK_GRSCEN)
+ break;
+ udelay(1);
+ }
+ if (GET_UINT32(p_dtsec_mem_map->ievent) &
+ DTSEC_IMASK_GRSCEN)
+ WRITE_UINT32(p_dtsec_mem_map->ievent,
+ DTSEC_IMASK_GRSCEN);
+ else
+ pr_debug("Rx lockup due to Tx lockup\n");
+
+ /* c.Write a 1 to bit n of FM_RSTC
+ * (offset 0x0CC of FPM)
+ */
+ fm_reset_mac(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MAC_1G,
+ p_dtsec->fm_mac_ctrl_drv.mac_id);
+
+ /* d.Wait 4 Tx clocks (32 ns) */
+ udelay(1);
+
+ /* e.Write a 0 to bit n of FM_RSTC. */
+ /* cleared by FMAN
+ */
+ }
+ }
+#endif /* FM_TX_LOCKUP_ERRATA_DTSEC6 */
+
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_TX_FIFO_UNDRN);
+ }
+ if (event & DTSEC_IMASK_MAGEN)
+ p_dtsec->f_exception(p_dtsec->h_app, FM_MAC_EX_1G_MAG_PCKT);
+ if (event & DTSEC_IMASK_GRSCEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_GRATEFUL_RX_STP_COMPLET);
+ if (event & DTSEC_IMASK_TDPEEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_DATA_ERR);
+ if (event & DTSEC_IMASK_RDPEEN)
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_1G_RX_DATA_ERR);
+
+ /* - masked interrupts */
+ ASSERT(!(event & DTSEC_IMASK_ABRTEN));
+ ASSERT(!(event & DTSEC_IMASK_IFERREN));
+}
+
+static void dtsec_1588_isr(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t event;
+ struct dtsec_regs __iomem *p_dtsec_mem_map = p_dtsec->p_mem_map;
+
+ if (p_dtsec->ptp_tsu_enabled) {
+ event = fman_dtsec_check_and_clear_tmr_event(p_dtsec_mem_map);
+
+ if (event) {
+ ASSERT(event & TMR_PEVENT_TSRE);
+ p_dtsec->f_exception(p_dtsec->h_app,
+ FM_MAC_EX_1G_1588_TS_RX_ERR);
+ }
+ }
+}
+
+static void free_init_resources(struct dtsec_t *p_dtsec)
+{
+ fm_unregister_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC, p_dtsec->mac_id, FM_INTR_TYPE_ERR);
+ fm_unregister_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC, p_dtsec->mac_id,
+ FM_INTR_TYPE_NORMAL);
+
+ /* release the driver's group hash table */
+ free_hash_table(p_dtsec->p_multicast_addr_hash);
+ p_dtsec->p_multicast_addr_hash = NULL;
+
+ /* release the driver's individual hash table */
+ free_hash_table(p_dtsec->p_unicast_addr_hash);
+ p_dtsec->p_unicast_addr_hash = NULL;
+}
+
+static int graceful_stop(struct dtsec_t *p_dtsec, enum comm_mode mode)
+{
+ struct dtsec_regs __iomem *p_mem_map;
+
+ p_mem_map = p_dtsec->p_mem_map;
+
+ /* Assert the graceful transmit stop bit */
+ if (mode & COMM_MODE_RX) {
+ fman_dtsec_stop_rx(p_mem_map);
+
+#ifdef FM_GRS_ERRATA_DTSEC_A002
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ usleep_range(100, 101);
+#else /* FM_GRS_ERRATA_DTSEC_A002 */
+#ifdef FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839
+ usleep_range(10, 11);
+#endif /* FM_GTS_AFTER_DROPPED_FRAME_ERRATA_DTSEC_A004839 */
+#endif /* FM_GRS_ERRATA_DTSEC_A002 */
+ }
+
+ if (mode & COMM_MODE_TX) {
+#if defined(FM_GTS_ERRATA_DTSEC_A004) || \
+defined(FM_GTS_AFTER_MAC_ABORTED_FRAME_ERRATA_DTSEC_A0012)
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ pr_debug("GTS not supported due to DTSEC_A004 errata.\n");
+#else /* not defined(FM_GTS_ERRATA_DTSEC_A004) ||..*/
+#ifdef FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev != 4)
+ pr_debug("GTS not supported due to DTSEC_A0014 errata.\n");
+#else /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+ fman_dtsec_stop_tx(p_mem_map);
+#endif /* FM_GTS_UNDERRUN_ERRATA_DTSEC_A0014 */
+#endif /* defined(FM_GTS_ERRATA_DTSEC_A004) ||... */
+ }
+ return 0;
+}
+
+static int graceful_restart(struct dtsec_t *p_dtsec, enum comm_mode mode)
+{
+ struct dtsec_regs __iomem *p_mem_map;
+
+ p_mem_map = p_dtsec->p_mem_map;
+ /* clear the graceful receive stop bit */
+ if (mode & COMM_MODE_TX)
+ fman_dtsec_start_tx(p_mem_map);
+
+ if (mode & COMM_MODE_RX)
+ fman_dtsec_start_rx(p_mem_map);
+
+ return 0;
+}
+
+/* dTSEC Configs modification functions */
+
+static int dtsec_cfg_lb(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->loopback = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_max_frame_len(void *h_dtsec, uint16_t new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->maximum_frame = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_pad_and_crc(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->tx_pad_crc = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_tbi_phy_addr(void *h_dtsec, uint8_t new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->tbi_phy_addr = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_len_check(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_dtsec->p_dtsec_drv_param->rx_len_check = new_val;
+
+ return 0;
+}
+
+static int dtsec_cfg_exception(void *h_dtsec, enum fm_mac_exceptions
+ exception, bool enable)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) {
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_dtsec->exceptions |= bit_mask;
+ else
+ p_dtsec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ } else {
+ if (!p_dtsec->ptp_tsu_enabled) {
+ pr_err("Exception valid for 1588 only\n");
+ return -EDOM;
+ }
+ switch (exception) {
+ case (FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable)
+ p_dtsec->en_tsu_err_exeption = true;
+ else
+ p_dtsec->en_tsu_err_exeption = false;
+ break;
+ default:
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ }
+ return 0;
+}
+
+/* dTSEC Run Time API functions */
+
+static int dtsec_enable(void *h_dtsec, enum comm_mode mode)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_dtsec_enable(p_dtsec->p_mem_map,
+ (bool)!!(mode & COMM_MODE_RX),
+ (bool)!!(mode & COMM_MODE_TX));
+
+ graceful_restart(p_dtsec, mode);
+
+ return 0;
+}
+
+static int dtsec_disable(void *h_dtsec, enum comm_mode mode)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ graceful_stop(p_dtsec, mode);
+
+ fman_dtsec_disable(p_dtsec->p_mem_map,
+ (bool)!!(mode & COMM_MODE_RX),
+ (bool)!!(mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int dtsec_set_tx_pause_frames(void *h_dtsec,
+ uint8_t __maybe_unused priority,
+ uint16_t pause_time,
+ uint16_t __maybe_unused thresh_time)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+#ifdef FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003
+ if (p_dtsec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ if (0 < pause_time && pause_time <= 320) {
+ pr_warn("pause-time:%d illegal.Should be >320\n",
+ pause_time);
+ return -EDOM;
+ }
+#endif /* FM_BAD_TX_TS_IN_B_2_B_ERRATA_DTSEC_A003 */
+
+ fman_dtsec_set_tx_pause_frames(p_dtsec->p_mem_map, pause_time);
+ return 0;
+}
+
+/* backward compatibility. will be removed in the future. */
+static int dtsec_tx_mac_pause(void *h_dtsec, uint16_t pause_time)
+{
+ return dtsec_set_tx_pause_frames(h_dtsec, 0, pause_time, 0);
+}
+
+static int dtsec_rx_ignore_mac_pause(void *h_dtsec, bool en)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+ bool accept_pause = !en;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_dtsec_handle_rx_pause(p_dtsec->p_mem_map, accept_pause);
+
+ return 0;
+}
+
+static int dtsec_modify_mac_address(void *h_dtsec, enet_addr_t
+ *p_enet_addr)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ /* Initialize MAC Station Address registers (1&2) */
+ /* Station address have to be swapped (big endian to little endian */
+ p_dtsec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
+ fman_dtsec_set_mac_address(p_dtsec->p_mem_map,
+ (uint8_t *)(*p_enet_addr));
+
+ return 0;
+}
+
+static int dtsec_add_hash_mac_address(void *h_dtsec,
+ enet_addr_t *p_eth_addr)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct eth_hash_entry_t *p_hash_entry;
+ uint64_t eth_addr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ ghtx = (bool)((fman_dtsec_get_rctrl(p_dtsec->p_mem_map) &
+ RCTRL_GHTX) ? true : false);
+ mcast = (bool)((eth_addr & MAC_GROUP_ADDRESS) ? true : false);
+
+ /* Cannot handle unicast mac addr when GHTX is on */
+ if (ghtx && !mcast) {
+ pr_err("Could not compute hash bucket\n");
+ return -ENOSYS;
+ }
+ crc = get_mac_addr_hash_code(eth_addr);
+
+ /* considering the 9 highest order bits in crc H[8:0]:
+ *if ghtx = 0 H[8:6] (highest order 3 bits) identify the hash register
+ *and H[5:1] (next 5 bits) identify the hash bit
+ *if ghts = 1 H[8:5] (highest order 4 bits) identify the hash register
+ *and H[4:0] (next 5 bits) identify the hash bit.
+ *
+ *In bucket index output the low 5 bits identify the hash register
+ *bit, while the higher 4 bits identify the hash register
+ */
+
+ if (ghtx) {
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ } else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set in gaddr instead of
+ *igaddr.
+ */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket, true);
+
+ /* Create element to be added to the driver hash table */
+ p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+ if (!p_hash_entry)
+ return -ENOMEM;
+ p_hash_entry->addr = eth_addr;
+ INIT_LIST_HEAD(&p_hash_entry->node);
+
+ if (eth_addr & MAC_GROUP_ADDRESS)
+ /* Group Address */
+ list_add_tail(&p_hash_entry->node,
+ &(p_dtsec->p_multicast_addr_hash->p_lsts[bucket]
+ ));
+ else
+ list_add_tail(&p_hash_entry->node,
+ &p_dtsec->p_unicast_addr_hash->p_lsts[bucket]);
+
+ return 0;
+}
+
+static int dtsec_del_hash_mac_address(void *h_dtsec, enet_addr_t
+ *p_eth_addr)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct list_head *p_pos;
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+ uint64_t eth_addr;
+ int32_t bucket;
+ uint32_t crc;
+ bool mcast, ghtx;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ ghtx =
+ (bool)((fman_dtsec_get_rctrl(p_dtsec->p_mem_map) & RCTRL_GHTX) ?
+ true : false);
+ mcast = (bool)((eth_addr & MAC_GROUP_ADDRESS) ? true : false);
+
+ /* Cannot handle unicast mac addr when GHTX is on */
+ if (ghtx && !mcast) {
+ pr_err("Could not compute hash bucket\n");
+ return -ENOSYS;
+ }
+ crc = get_mac_addr_hash_code(eth_addr);
+
+ if (ghtx) {
+ bucket = (int32_t)((crc >> 23) & 0x1ff);
+ } else {
+ bucket = (int32_t)((crc >> 24) & 0xff);
+ /* if !ghtx and mcast the bit must be set
+ * in gaddr instead of igaddr.
+ */
+ if (mcast)
+ bucket += 0x100;
+ }
+
+ if (eth_addr & MAC_GROUP_ADDRESS) {
+ /* Group Address */
+ list_for_each(p_pos,
+ &(p_dtsec->p_multicast_addr_hash->
+ p_lsts[bucket])) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_dtsec->p_multicast_addr_hash->p_lsts[bucket]))
+ fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket,
+ false);
+ } else {
+ /* Individual Address */
+ list_for_each(p_pos,
+ &p_dtsec->p_unicast_addr_hash->p_lsts[bucket]) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_dtsec->p_unicast_addr_hash->p_lsts[bucket]))
+ fman_dtsec_set_bucket(p_dtsec->p_mem_map, bucket,
+ false);
+ }
+
+ /* address does not exist */
+ ASSERT(p_hash_entry);
+
+ return 0;
+}
+
+static int dtsec_set_promiscuous(void *h_dtsec, bool new_val)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_dtsec_set_uc_promisc(p_dtsec->p_mem_map, new_val);
+ fman_dtsec_set_mc_promisc(p_dtsec->p_mem_map, new_val);
+
+ return 0;
+}
+
+static int dtsec_adjust_link(void *h_dtsec, enum ethernet_speed speed)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int err;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ int ret, full_duplex = true;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ p_dtsec->enet_mode =
+ MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode), speed);
+ enet_interface =
+ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_dtsec->enet_mode);
+
+ err =
+ (int)fman_dtsec_adjust_link(p_dtsec->p_mem_map, enet_interface,
+ enet_speed, full_duplex);
+
+ if (err == -EINVAL) {
+ pr_err("Ethernet doesn't support Half Duplex mode\n");
+ return -EINVAL;
+ }
+
+ return err;
+}
+
+static int dtsec_restart_autoneg(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint16_t tmp_reg16;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ dtsec_mii_read_phy_reg(p_dtsec, p_dtsec->tbi_phy_addr, 0, &tmp_reg16);
+
+ tmp_reg16 &= ~(PHY_CR_SPEED0 | PHY_CR_SPEED1);
+ tmp_reg16 |=
+ (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX | PHY_CR_SPEED1);
+
+ dtsec_mii_write_phy_reg(p_dtsec, p_dtsec->tbi_phy_addr, 0, tmp_reg16);
+
+ return 0;
+}
+
+static int dtsec_get_id(void *h_dtsec, uint32_t *mac_id)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ *mac_id = p_dtsec->mac_id;
+
+ return 0;
+}
+
+static int dtsec_get_version(void *h_dtsec, uint32_t *mac_version)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ *mac_version = fman_dtsec_get_revision(p_dtsec->p_mem_map);
+
+ return 0;
+}
+
+static int dtsec_set_exception(void *h_dtsec,
+ enum fm_mac_exceptions exception,
+ bool enable)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (ret)
+ return ret;
+
+ if (exception != FM_MAC_EX_1G_1588_TS_RX_ERR) {
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_dtsec->exceptions |= bit_mask;
+ else
+ p_dtsec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ if (enable)
+ fman_dtsec_enable_interrupt(p_dtsec->p_mem_map,
+ bit_mask);
+ else
+ fman_dtsec_disable_interrupt(p_dtsec->p_mem_map,
+ bit_mask);
+ } else {
+ if (!p_dtsec->ptp_tsu_enabled) {
+ pr_err("Exception valid for 1588 only\n");
+ return -EDOM;
+ }
+ switch (exception) {
+ case (FM_MAC_EX_1G_1588_TS_RX_ERR):
+ if (enable) {
+ p_dtsec->en_tsu_err_exeption = true;
+ fman_dtsec_enable_tmr_interrupt(p_dtsec->
+ p_mem_map);
+ } else {
+ p_dtsec->en_tsu_err_exeption = false;
+ fman_dtsec_disable_tmr_interrupt(p_dtsec->
+ p_mem_map);
+ }
+ break;
+ default:
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ }
+
+ return 0;
+}
+
+/* dTSEC Init&Free API */
+
+static int dtsec_init(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct dtsec_cfg *p_dtsec_drv_param;
+ int err;
+ uint16_t max_frm_ln;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ enet_addr_t eth_addr;
+ int ret, ret_err;
+
+ ret = is_init_done(p_dtsec->p_dtsec_drv_param);
+ if (!ret)
+ return ret;
+
+ fm_get_revision(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ &p_dtsec->fm_mac_ctrl_drv.fm_rev_info);
+ ret_err = check_init_parameters(p_dtsec);
+ if (ret_err)
+ return -ret_err;
+
+ p_dtsec_drv_param = p_dtsec->p_dtsec_drv_param;
+
+ enet_interface =
+ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_dtsec->enet_mode);
+ MAKE_ENET_ADDR_FROM_UINT64(p_dtsec->addr, eth_addr);
+
+ err = (int)fman_dtsec_init(p_dtsec->p_mem_map,
+ p_dtsec_drv_param,
+ enet_interface,
+ enet_speed,
+ (uint8_t *)eth_addr,
+ p_dtsec->fm_mac_ctrl_drv.
+ fm_rev_info.major_rev,
+ p_dtsec->fm_mac_ctrl_drv.
+ fm_rev_info.minor_rev,
+ p_dtsec->exceptions);
+ if (err) {
+ free_init_resources(p_dtsec);
+ pr_err("DTSEC version doesn't support this i/f mode\n");
+ return err;
+ }
+
+ if (ENET_INTERFACE_FROM_MODE(p_dtsec->enet_mode) == ENET_IF_SGMII) {
+ uint16_t tmp_reg16;
+
+ /* Configure the TBI PHY Control Register */
+ tmp_reg16 = PHY_TBICON_CLK_SEL | PHY_TBICON_SRESET;
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 17, tmp_reg16);
+
+ tmp_reg16 = PHY_TBICON_CLK_SEL;
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 17, tmp_reg16);
+
+ tmp_reg16 =
+ (PHY_CR_PHY_RESET | PHY_CR_ANE | PHY_CR_FULLDUPLEX |
+ PHY_CR_SPEED1);
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 0, tmp_reg16);
+
+ if (p_dtsec->enet_mode & ENET_IF_SGMII_BASEX)
+ tmp_reg16 = PHY_TBIANA_1000X;
+ else
+ tmp_reg16 = PHY_TBIANA_SGMII;
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 4, tmp_reg16);
+
+ tmp_reg16 =
+ (PHY_CR_ANE | PHY_CR_RESET_AN | PHY_CR_FULLDUPLEX |
+ PHY_CR_SPEED1);
+
+ dtsec_mii_write_phy_reg(p_dtsec,
+ (uint8_t)p_dtsec_drv_param->tbipa,
+ 0, tmp_reg16);
+ }
+
+ /* Max Frame Length */
+ max_frm_ln = fman_dtsec_get_max_frame_len(p_dtsec->p_mem_map);
+ err = fm_set_mac_max_frame(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MAC_1G,
+ p_dtsec->fm_mac_ctrl_drv.mac_id,
+ max_frm_ln);
+ if (err) {
+ pr_err("Setting max frame length FAILED\n");
+ free_init_resources(p_dtsec);
+ return -EINVAL;
+ }
+
+ p_dtsec->p_multicast_addr_hash =
+ alloc_hash_table(EXTENDED_HASH_TABLE_SIZE);
+ if (!p_dtsec->p_multicast_addr_hash) {
+ free_init_resources(p_dtsec);
+ pr_err("MC hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ p_dtsec->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_dtsec->p_unicast_addr_hash) {
+ free_init_resources(p_dtsec);
+ pr_err("UC hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ /* register err intr handler for dtsec to FPM (err) */
+ fm_register_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_dtsec->mac_id,
+ FM_INTR_TYPE_ERR,
+ dtsec_isr,
+ p_dtsec);
+ /* register 1588 intr handler for TMR to FPM (normal) */
+ fm_register_intr(p_dtsec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_dtsec->mac_id,
+ FM_INTR_TYPE_NORMAL,
+ dtsec_1588_isr,
+ p_dtsec);
+
+ kfree(p_dtsec_drv_param);
+ p_dtsec->p_dtsec_drv_param = NULL;
+
+ return 0;
+}
+
+static int dtsec_free(void *h_dtsec)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+
+ free_init_resources(p_dtsec);
+
+ kfree(p_dtsec->p_dtsec_drv_param);
+ p_dtsec->p_dtsec_drv_param = NULL;
+ kfree(h_dtsec);
+
+ return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+ p_fm_mac_ctrl_drv)
+{
+ p_fm_mac_ctrl_drv->f_fm_mac_init = dtsec_init;
+ p_fm_mac_ctrl_drv->f_fm_mac_free = dtsec_free;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = dtsec_cfg_lb;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len =
+ dtsec_cfg_max_frame_len;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc =
+ dtsec_cfg_pad_and_crc;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = dtsec_cfg_len_check;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr = dtsec_cfg_tbi_phy_addr;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = dtsec_cfg_exception;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init = NULL;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_enable = dtsec_enable;
+ p_fm_mac_ctrl_drv->f_fm_mac_disable = dtsec_disable;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_exception = dtsec_set_exception;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = dtsec_set_promiscuous;
+ p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = dtsec_adjust_link;
+ p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = dtsec_restart_autoneg;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+ dtsec_tx_mac_pause;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames =
+ dtsec_set_tx_pause_frames;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+ dtsec_rx_ignore_mac_pause;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr =
+ dtsec_modify_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+ dtsec_add_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+ dtsec_del_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_id = dtsec_get_id;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_version = dtsec_get_version;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+ dtsec_get_max_frame_length;
+}
+
+/* d_tsec config main entry */
+
+void *dtsec_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct dtsec_t *p_dtsec;
+ struct dtsec_cfg *p_dtsec_drv_param;
+ uintptr_t base_addr;
+
+ base_addr = p_fm_mac_param->base_addr;
+
+ /* allocate memory for the UCC GETH data structure. */
+ p_dtsec = kzalloc(sizeof(*p_dtsec), GFP_KERNEL);
+ if (!p_dtsec)
+ return ERR_PTR(-ENOMEM);
+ init_fm_mac_ctrl_drv(&p_dtsec->fm_mac_ctrl_drv);
+
+ /* allocate memory for the d_tsec driver parameters data structure. */
+ p_dtsec_drv_param = kzalloc(sizeof(*p_dtsec_drv_param),
+ GFP_KERNEL);
+ if (!p_dtsec_drv_param) {
+ kfree(p_dtsec);
+ pr_err("dTSEC driver parameters");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ /* Plant parameter structure pointer */
+ p_dtsec->p_dtsec_drv_param = p_dtsec_drv_param;
+
+ fman_dtsec_defconfig(p_dtsec_drv_param);
+
+ p_dtsec->p_mem_map = (struct dtsec_regs __iomem *)
+ UINT_TO_PTR(base_addr);
+ p_dtsec->p_mii_mem_map = (struct dtsec_mii_reg __iomem *)
+ UINT_TO_PTR(base_addr + DTSEC_TO_MII_OFFSET);
+ p_dtsec->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+ p_dtsec->enet_mode = p_fm_mac_param->enet_mode;
+ p_dtsec->mac_id = p_fm_mac_param->mac_id;
+ p_dtsec->exceptions = DEFAULT_exceptions;
+ p_dtsec->f_exception = p_fm_mac_param->f_exception;
+ p_dtsec->f_event = p_fm_mac_param->f_event;
+ p_dtsec->h_app = p_fm_mac_param->h_app;
+ p_dtsec->ptp_tsu_enabled = p_dtsec->p_dtsec_drv_param->ptp_tsu_en;
+ p_dtsec->en_tsu_err_exeption =
+ p_dtsec->p_dtsec_drv_param->ptp_exception_en;
+ p_dtsec->tbi_phy_addr = p_dtsec->p_dtsec_drv_param->tbi_phy_addr;
+
+ return p_dtsec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec.h b/drivers/net/ethernet/freescale/fman/mac/dtsec.h
new file mode 100644
index 0000000..723a7d2
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec.h
@@ -0,0 +1,185 @@
+/*
+ * 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 dTSEC ... */
+#ifndef __DTSEC_H
+#define __DTSEC_
+
+#include "service.h"
+#include "enet_ext.h"
+
+#include "dtsec_mii_acc.h"
+#include "fm_mac.h"
+
+#define DEFAULT_exceptions \
+((uint32_t)(DTSEC_IMASK_BREN | \
+ DTSEC_IMASK_RXCEN | \
+ DTSEC_IMASK_BTEN | \
+ DTSEC_IMASK_TXCEN | \
+ DTSEC_IMASK_TXEEN | \
+ DTSEC_IMASK_ABRTEN | \
+ DTSEC_IMASK_LCEN | \
+ DTSEC_IMASK_CRLEN | \
+ DTSEC_IMASK_XFUNEN | \
+ DTSEC_IMASK_IFERREN | \
+ DTSEC_IMASK_MAGEN | \
+ DTSEC_IMASK_TDPEEN | \
+ DTSEC_IMASK_RDPEEN))
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+/*number of pattern match registers (entries) */
+#define DTSEC_NUM_OF_PADDRS 15
+
+/* Group address bit indication */
+#define GROUP_ADDRESS 0x0000010000000000LL
+
+/* Hash table size (32 bits*8 regs) */
+#define HASH_TABLE_SIZE 256
+/* Extended Hash table size (32 bits*16 regs) */
+#define EXTENDED_HASH_TABLE_SIZE 512
+
+/* number of pattern match registers (entries) */
+#define DTSEC_TO_MII_OFFSET 0x1000
+/* maximum number of phys */
+#define MAX_PHYS 32
+
+#define VAL32BIT 0x100000000LL
+#define VAL22BIT 0x00400000
+#define VAL16BIT 0x00010000
+#define VAL12BIT 0x00001000
+
+/* CAR1/2 bits */
+#define CAR1_TR64 0x80000000
+#define CAR1_TR127 0x40000000
+#define CAR1_TR255 0x20000000
+#define CAR1_TR511 0x10000000
+#define CAR1_TRK1 0x08000000
+#define CAR1_TRMAX 0x04000000
+#define CAR1_TRMGV 0x02000000
+
+#define CAR1_RBYT 0x00010000
+#define CAR1_RPKT 0x00008000
+#define CAR1_RMCA 0x00002000
+#define CAR1_RBCA 0x00001000
+#define CAR1_RXPF 0x00000400
+#define CAR1_RALN 0x00000100
+#define CAR1_RFLR 0x00000080
+#define CAR1_RCDE 0x00000040
+#define CAR1_RCSE 0x00000020
+#define CAR1_RUND 0x00000010
+#define CAR1_ROVR 0x00000008
+#define CAR1_RFRG 0x00000004
+#define CAR1_RJBR 0x00000002
+#define CAR1_RDRP 0x00000001
+
+#define CAR2_TFCS 0x00040000
+#define CAR2_TBYT 0x00002000
+#define CAR2_TPKT 0x00001000
+#define CAR2_TMCA 0x00000800
+#define CAR2_TBCA 0x00000400
+#define CAR2_TXPF 0x00000200
+#define CAR2_TDRP 0x00000001
+
+struct internal_statistics_t {
+ uint64_t tr64;
+ uint64_t tr127;
+ uint64_t tr255;
+ uint64_t tr511;
+ uint64_t tr1k;
+ uint64_t trmax;
+ uint64_t trmgv;
+ uint64_t rfrg;
+ uint64_t rjbr;
+ uint64_t rdrp;
+ uint64_t raln;
+ uint64_t rund;
+ uint64_t rovr;
+ uint64_t rxpf;
+ uint64_t txpf;
+ uint64_t rbyt;
+ uint64_t rpkt;
+ uint64_t rmca;
+ uint64_t rbca;
+ uint64_t rflr;
+ uint64_t rcde;
+ uint64_t rcse;
+ uint64_t tbyt;
+ uint64_t tpkt;
+ uint64_t tmca;
+ uint64_t tbca;
+ uint64_t tdrp;
+ uint64_t tfcs;
+};
+
+struct dtsec_t {
+ struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+ /* Handle to the upper layer application */
+ void *h_app;
+ /* pointer to dTSEC memory mapped registers. */
+ struct dtsec_regs __iomem *p_mem_map;
+ /* pointer to dTSEC MII memory mapped registers. */
+ struct dtsec_mii_reg __iomem *p_mii_mem_map;
+ /* MAC address of device; */
+ uint64_t addr;
+ /* Ethernet physical interface */
+ enum e_enet_mode enet_mode;
+ fm_mac_exception_cb *f_exception;
+ fm_mac_exception_cb *f_event;
+ /* Whether a particular individual address recognition
+ * register is being used
+ */
+ bool ind_addr_reg_used[DTSEC_NUM_OF_PADDRS];
+ /* MAC address for particular individual
+ * address recognition register
+ */
+ uint64_t paddr[DTSEC_NUM_OF_PADDRS];
+ /* Number of individual addresses in registers for this station. */
+ uint8_t num_of_ind_addr_in_regs;
+ struct internal_statistics_t internal_statistics;
+ /* pointer to driver's global address hash table */
+ struct eth_hash_t *p_multicast_addr_hash;
+ /* pointer to driver's individual address hash table */
+ struct eth_hash_t *p_unicast_addr_hash;
+ uint8_t mac_id;
+ uint8_t tbi_phy_addr;
+ uint32_t exceptions;
+ bool ptp_tsu_enabled;
+ bool en_tsu_err_exeption;
+ struct dtsec_cfg *p_dtsec_drv_param;
+};
+
+#endif /* __DTSEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
new file mode 100644
index 0000000..0b2ef14
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.c
@@ -0,0 +1,82 @@
+/*
+ * 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 dtsec MII register access MAC ... */
+
+#include "service.h"
+#include "fm_mac.h"
+#include "dtsec.h"
+#include "fsl_fman_dtsec_mii_acc.h"
+
+int dtsec_mii_write_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t data)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct dtsec_mii_reg __iomem *miiregs;
+ uint16_t dtsec_freq;
+ int err;
+
+ dtsec_freq = (uint16_t)(p_dtsec->fm_mac_ctrl_drv.clk_freq >> 1);
+ miiregs = p_dtsec->p_mii_mem_map;
+
+ err =
+ (int)fman_dtsec_mii_write_reg(miiregs, phy_addr, reg, data,
+ dtsec_freq);
+
+ return err;
+}
+
+int dtsec_mii_read_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t *p_data)
+{
+ struct dtsec_t *p_dtsec = (struct dtsec_t *)h_dtsec;
+ struct dtsec_mii_reg __iomem *miiregs;
+ uint16_t dtsec_freq;
+ int err;
+
+ dtsec_freq = (uint16_t)(p_dtsec->fm_mac_ctrl_drv.clk_freq >> 1);
+ miiregs = p_dtsec->p_mii_mem_map;
+
+ err =
+ (int)fman_dtsec_mii_read_reg(miiregs, phy_addr, reg, p_data,
+ dtsec_freq);
+
+ if (*p_data == 0xffff) {
+ pr_warn("Read wrong data(0xffff):phy_addr 0x%x,reg 0x%x",
+ phy_addr, reg);
+ return -ENXIO;
+ }
+ if (err)
+ return err;
+
+ return err;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
new file mode 100644
index 0000000..e599642
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/dtsec_mii_acc.h
@@ -0,0 +1,43 @@
+/*
+ * 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 __DTSEC_MII_ACC_H
+#define __DTSEC_MII_ACC_H
+
+#include "service.h"
+
+int dtsec_mii_write_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t data);
+int dtsec_mii_read_phy_reg(void *h_dtsec, uint8_t phy_addr, uint8_t reg,
+ uint16_t *p_data);
+
+#endif /* __DTSEC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/fm_mac.c b/drivers/net/ethernet/freescale/fman/mac/fm_mac.c
new file mode 100644
index 0000000..8048446
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fm_mac.c
@@ -0,0 +1,510 @@
+/*
+ * 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 MAC ... */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "fm_ext.h"
+
+#include "fm_common.h"
+#include "fm_mac.h"
+
+#include <linux/string.h>
+
+struct fm_mac_dev *fm_mac_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct fm_mac_dev *fm_mac_dev;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv;
+ struct fm_revision_info_t fm_rev_info;
+
+ fm_get_revision(p_fm_mac_param->h_fm, &fm_rev_info);
+
+ if (fm_rev_info.major_rev >= 6) {
+ p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+ memac_config(p_fm_mac_param);
+ } else {
+ if (ENET_SPEED_FROM_MODE(p_fm_mac_param->enet_mode) <
+ ENET_SPEED_10000)
+ p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+ dtsec_config(p_fm_mac_param);
+ else if (ENET_SPEED_FROM_MODE(p_fm_mac_param->enet_mode) ==
+ ENET_SPEED_10000)
+ p_fm_mac_ctrl_drv = (struct fm_mac_ctrl_drv_t *)
+ tgec_config(p_fm_mac_param);
+ else
+ p_fm_mac_ctrl_drv = NULL;
+ }
+
+ if (!p_fm_mac_ctrl_drv)
+ return NULL;
+
+ p_fm_mac_ctrl_drv->h_fm = p_fm_mac_param->h_fm;
+ p_fm_mac_ctrl_drv->enet_mode = p_fm_mac_param->enet_mode;
+ p_fm_mac_ctrl_drv->mac_id = p_fm_mac_param->mac_id;
+ p_fm_mac_ctrl_drv->reset_on_init = DEFAULT_RESET_ON_INIT;
+ p_fm_mac_ctrl_drv->fm_rev_info.major_rev = fm_rev_info.major_rev;
+ p_fm_mac_ctrl_drv->fm_rev_info.minor_rev = fm_rev_info.minor_rev;
+ p_fm_mac_ctrl_drv->clk_freq =
+ fm_get_clock_freq(p_fm_mac_ctrl_drv->h_fm);
+
+ if (p_fm_mac_ctrl_drv->clk_freq == 0) {
+ pr_err("Can't get clock for MAC!\n");
+ kfree(p_fm_mac_ctrl_drv);
+ return NULL;
+ }
+
+ fm_mac_dev = (void *)p_fm_mac_ctrl_drv;
+
+ return fm_mac_dev;
+}
+EXPORT_SYMBOL(fm_mac_config);
+
+int fm_mac_init(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->reset_on_init &&
+ !p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init &&
+ (fm_reset_mac(p_fm_mac_ctrl_drv->h_fm,
+ ((ENET_INTERFACE_FROM_MODE
+ (p_fm_mac_ctrl_drv->enet_mode) ==
+ ENET_IF_XGMII) ? FM_MAC_10G : FM_MAC_1G),
+ p_fm_mac_ctrl_drv->mac_id) != 0)) {
+ pr_err("Can't reset MAC!\n");
+ return -ENOSYS;
+ }
+ if (p_fm_mac_ctrl_drv->f_fm_mac_init)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_init(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_init() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_init);
+
+int fm_mac_free(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_free)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_free(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_free() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_free);
+
+int fm_mac_cfg_reset_on_init(struct fm_mac_dev *fm_mac_dev, bool enable)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init(fm_mac_dev,
+ enable);
+ else
+ err = 0;
+
+ p_fm_mac_ctrl_drv->reset_on_init = enable;
+ if (unlikely(err < 0))
+ pr_err("fm_mac_reset_on_init() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_reset_on_init);
+
+int fm_mac_cfg_max_frame_len(struct fm_mac_dev *fm_mac_dev, uint16_t new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_max_frame_len() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_max_frame_len);
+
+int fm_mac_cfg_pad_and_crc(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_init() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_pad_and_crc);
+
+int fm_mac_cfg_tbi_phy_addr(struct fm_mac_dev *fm_mac_dev, uint8_t new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_tbi_phy_addr(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_tbi_phy_addr() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_tbi_phy_addr);
+
+int fm_mac_cfg_len_check(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check(fm_mac_dev,
+ new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_len_check() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_len_check);
+
+int fm_mac_cfg_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception(fm_mac_dev,
+ ex,
+ enable);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_exception() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_exception);
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+int fm_mac_cfg_skip_fman11_wa(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_cfg_skip_fman11_wa)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_cfg_skip_fman11_wa(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_cfg_skip_fman11_wa() = 0x%08x\n",
+ err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_cfg_skip_fman11_wa);
+
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* Run Time Control */
+
+int fm_mac_enable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_enable)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_enable(fm_mac_dev, mode);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_enable() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_enable);
+
+int fm_mac_disable(struct fm_mac_dev *fm_mac_dev, enum comm_mode mode)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_disable)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_disable(fm_mac_dev, mode);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_disable() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_disable);
+
+int fm_mac_set_tx_pause_frames(struct fm_mac_dev *fm_mac_dev,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames)
+ return p_fm_mac_ctrl_drv->
+ f_fm_mac_set_tx_auto_pause_frames(fm_mac_dev, pause_time);
+
+ return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_set_tx_pause_frames);
+
+int fm_mac_set_rx_pause_frames(struct fm_mac_dev *fm_mac_dev, bool en)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_set_rx_ignore_pause_frames(fm_mac_dev, !en);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_set_rx_ignore_pause_frames() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_set_rx_pause_frames);
+
+int fm_mac_set_exception(struct fm_mac_dev *fm_mac_dev,
+ enum fm_mac_exceptions ex,
+ bool enable)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_exception)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_set_exception(fm_mac_dev,
+ ex,
+ enable);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_set_exception() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_set_exception);
+
+int fm_mac_modify_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr)
+ return p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr(fm_mac_dev,
+ p_enet_addr);
+
+ return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_modify_mac_addr);
+
+int fm_mac_add_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_add_hash_mac_addr(fm_mac_dev, p_enet_addr);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_add_hash_mac_addr() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_add_hash_mac_addr);
+
+int fm_mac_remove_hash_mac_addr(struct fm_mac_dev *fm_mac_dev,
+ enet_addr_t *p_enet_addr)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_remove_hash_mac_addr(fm_mac_dev, p_enet_addr);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_remove_hash_mac_addr() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_remove_hash_mac_addr);
+
+int fm_mac_get_version(struct fm_mac_dev *fm_mac_dev, uint32_t *mac_version)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_get_version)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_get_version(fm_mac_dev,
+ mac_version);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_version() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_get_version);
+
+int fm_mac_get_id(struct fm_mac_dev *fm_mac_dev, uint32_t *mac_id)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_get_id)
+ err = p_fm_mac_ctrl_drv->f_fm_mac_get_id(fm_mac_dev, mac_id);
+ else
+ err = -ENOSYS;
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_id() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_get_id);
+
+int fm_mac_set_promiscuous(struct fm_mac_dev *fm_mac_dev, bool new_val)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_set_promiscuous(fm_mac_dev, new_val);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_id() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_set_promiscuous);
+
+int fm_mac_adjust_link(struct fm_mac_dev *fm_mac_dev, int link,
+ enum ethernet_speed speed)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (!link) {
+ if (p_fm_mac_ctrl_drv->fm_rev_info.major_rev < 6)
+ fm_mac_restart_autoneg(fm_mac_dev);
+
+ return 0;
+ }
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_adjust_link)
+ return p_fm_mac_ctrl_drv->f_fm_mac_adjust_link(fm_mac_dev,
+ speed);
+
+ return -ENOSYS;
+}
+EXPORT_SYMBOL(fm_mac_adjust_link);
+
+int fm_mac_restart_autoneg(struct fm_mac_dev *fm_mac_dev)
+{
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg)
+ return p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg(fm_mac_dev);
+
+ return -ENOSYS;
+}
+
+uint16_t fm_mac_get_max_frame_length(struct fm_mac_dev *fm_mac_dev)
+{
+ int err;
+ struct fm_mac_ctrl_drv_t *p_fm_mac_ctrl_drv = (void *)fm_mac_dev;
+
+ if (p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length)
+ err = p_fm_mac_ctrl_drv->
+ f_fm_mac_get_max_frame_length(fm_mac_dev);
+ else
+ err = -ENOSYS;
+
+ if (unlikely(err < 0))
+ pr_err("fm_mac_get_max_frame_length() = 0x%08x\n", err);
+
+ return err;
+}
+EXPORT_SYMBOL(fm_mac_get_max_frame_length);
diff --git a/drivers/net/ethernet/freescale/fman/mac/fm_mac.h b/drivers/net/ethernet/freescale/fman/mac/fm_mac.h
new file mode 100644
index 0000000..81fd563
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/fm_mac.h
@@ -0,0 +1,183 @@
+/*
+ * 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 MAC ... */
+#ifndef __FM_MAC_H
+#define __FM_MAC_H
+
+#include "service.h"
+#include "fm_mac_ext.h"
+#include "fm_common.h"
+
+#include <linux/slab.h>
+
+/* defaults */
+
+#define DEFAULT_RESET_ON_INIT false
+
+struct eth_hash_entry_t {
+ uint64_t addr; /* Ethernet Address */
+ struct list_head node;
+};
+
+#define ETH_HASH_ENTRY_OBJ(ptr) list_object(ptr, struct eth_hash_entry_t, node)
+
+struct eth_hash_t {
+ uint16_t size;
+ struct list_head *p_lsts;
+};
+
+struct fm_mac_ctrl_drv_t {
+ int (*f_fm_mac_init)(void *h_fm_mac);
+ int (*f_fm_mac_free)(void *h_fm_mac);
+
+ int (*f_fm_mac_cfg_lb)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_cfg_max_frame_len)(void *h_fm_mac, uint16_t new_val);
+ int (*f_fm_mac_cfg_pad_and_crc)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_cfg_len_check)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_cfg_tbi_phy_addr)(void *h_fm_mac, uint8_t new_val);
+ int (*f_fm_mac_cfg_exception)(void *h_fm_mac,
+ enum fm_mac_exceptions, bool enable);
+ int (*f_fm_mac_cfg_reset_on_init)(void *h_fm_mac, bool enable);
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ int (*f_fm_mac_cfg_skip_fman11_wa)(void *h_fm_mac);
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ int (*f_fm_mac_set_exception)(void *h_fm_mac,
+ enum fm_mac_exceptions ex,
+ bool enable);
+
+ int (*f_fm_mac_enable)(void *h_fm_mac, enum comm_mode mode);
+ int (*f_fm_mac_disable)(void *h_fm_mac, enum comm_mode mode);
+ int (*f_fm_mac_reset)(void *h_fm_mac, bool wait);
+
+ int (*f_fm_mac_set_tx_auto_pause_frames)(void *h_fm_mac,
+ uint16_t pause_time);
+ int (*f_fm_mac_set_tx_pause_frames)(void *h_fm_mac,
+ uint8_t priority,
+ uint16_t pause_time,
+ uint16_t thresh_time);
+ int (*f_fm_mac_set_rx_ignore_pause_frames)(void *h_fm_mac, bool en);
+
+ int (*f_fm_mac_modify_mac_addr)(void *h_fm_mac,
+ enet_addr_t *p_enet_addr);
+ int (*f_fm_mac_add_hash_mac_addr)(void *h_fm_mac,
+ enet_addr_t *p_enet_addr);
+ int (*f_fm_mac_remove_hash_mac_addr)(void *h_fm_mac,
+ enet_addr_t *p_enet_addr);
+ int (*f_fm_mac_set_promiscuous)(void *h_fm_mac, bool new_val);
+ int (*f_fm_mac_adjust_link)(void *h_fm_mac,
+ enum ethernet_speed speed);
+ int (*f_fm_mac_restart_autoneg)(void *h_fm_mac);
+
+ int (*f_fm_mac_get_id)(void *h_fm_mac, uint32_t *mac_id);
+
+ int (*f_fm_mac_get_version)(void *h_fm_mac, uint32_t *mac_version);
+
+ uint16_t (*f_fm_mac_get_max_frame_length)(void *h_fm_mac);
+
+ void *h_fm;
+ struct fm_revision_info_t fm_rev_info;
+ enum e_enet_mode enet_mode;
+ uint8_t mac_id;
+ bool reset_on_init;
+ uint16_t clk_freq;
+};
+
+void *dtsec_config(struct fm_mac_params_t *p_fm_mac_param);
+void *tgec_config(struct fm_mac_params_t *p_fm_mac_params);
+void *memac_config(struct fm_mac_params_t *p_fm_mac_param);
+
+static inline struct eth_hash_entry_t
+*dequeue_addr_from_hash_entry(struct list_head *p_addr_lst)
+{
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+
+ if (!list_empty(p_addr_lst)) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_addr_lst->next);
+ list_del_init(&p_hash_entry->node);
+ }
+ return p_hash_entry;
+}
+
+static inline void free_hash_table(struct eth_hash_t *p_hash)
+{
+ struct eth_hash_entry_t *p_hash_entry;
+ int i = 0;
+
+ if (p_hash) {
+ if (p_hash->p_lsts) {
+ for (i = 0; i < p_hash->size; i++) {
+ p_hash_entry =
+ dequeue_addr_from_hash_entry(&p_hash->
+ p_lsts[i]);
+ while (p_hash_entry) {
+ kfree(p_hash_entry);
+ p_hash_entry =
+ dequeue_addr_from_hash_entry
+ (&p_hash->p_lsts[i]);
+ }
+ }
+
+ kfree(p_hash->p_lsts);
+ }
+
+ kfree(p_hash);
+ }
+}
+
+static inline struct eth_hash_t *alloc_hash_table(uint16_t size)
+{
+ uint32_t i;
+ struct eth_hash_t *p_hash;
+
+ /* Allocate address hash table */
+ p_hash = kmalloc_array(size, sizeof(struct eth_hash_t *), GFP_KERNEL);
+ if (!p_hash)
+ return NULL;
+
+ p_hash->size = size;
+
+ p_hash->p_lsts = kmalloc_array(p_hash->size, sizeof(struct list_head),
+ GFP_KERNEL);
+ if (!p_hash->p_lsts) {
+ kfree(p_hash);
+ return NULL;
+ }
+
+ for (i = 0; i < p_hash->size; i++)
+ INIT_LIST_HEAD(&p_hash->p_lsts[i]);
+
+ return p_hash;
+}
+
+#endif /* __FM_MAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac.c b/drivers/net/ethernet/freescale/fman/mac/memac.c
new file mode 100644
index 0000000..0f6c615
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac.c
@@ -0,0 +1,837 @@
+/*
+ * 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 mEMAC driver */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+
+#include "fm_common.h"
+#include "memac.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+
+/* Internal routine */
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+ uint64_t mask1, mask2;
+ uint32_t xor_val = 0;
+ uint8_t i, j;
+
+ for (i = 0; i < 6; i++) {
+ mask1 = eth_addr & (uint64_t)0x01;
+ eth_addr >>= 1;
+
+ for (j = 0; j < 7; j++) {
+ mask2 = eth_addr & (uint64_t)0x01;
+ mask1 ^= mask2;
+ eth_addr >>= 1;
+ }
+
+ xor_val |= (mask1 << (5 - i));
+ }
+
+ return xor_val;
+}
+
+static void setup_sgmii_internal_phy(struct memac_t *p_memac, uint8_t phy_addr)
+{
+ uint16_t tmp_reg16;
+ enum e_enet_mode enet_mode;
+
+ /* In case the higher MACs are used (i.e. the MACs that should
+ * support 10G), speed=10000 is provided for SGMII ports.
+ * Temporary modify enet mode to 1G one, so MII functions can
+ * work correctly.
+ */
+ enet_mode = p_memac->enet_mode;
+ p_memac->enet_mode =
+ MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+ ENET_SPEED_1000);
+
+ /* SGMII mode + AN enable */
+ tmp_reg16 = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x14, tmp_reg16);
+
+ /* Device ability according to SGMII specification */
+ tmp_reg16 = PHY_SGMII_DEV_ABILITY_SGMII;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x4, tmp_reg16);
+
+ /* Adjust link timer for SGMII -
+ * According to Cisco SGMII specification the timer should be 1.6 ms.
+ * The link_timer register is configured in units of the clock.
+ * - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ * unit = 1 / (125*10^6 Hz) = 8 ns.
+ * 1.6 ms in units of 8 ns = 1.6ms / 8ns = 2*10^5 = 0x30d40
+ * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ * 1.6 ms in units of 3.2 ns = 1.6ms / 3.2ns = 5*10^5 = 0x7a120.
+ * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ * we always set up here a value of 2.5 SGMII.
+ */
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x13, 0x0007);
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x12, 0xa120);
+
+ /* Restart AN */
+ tmp_reg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x0, tmp_reg16);
+
+ /* Restore original enet mode */
+ p_memac->enet_mode = enet_mode;
+}
+
+static void setup_sgmii_internal_phy_base_x(struct memac_t *p_memac,
+ uint8_t phy_addr)
+{
+ uint16_t tmp_reg16;
+ enum e_enet_mode enet_mode;
+
+ /* In case the higher MACs are used (i.e. the MACs that
+ * should support 10G), speed=10000 is provided for SGMII ports.
+ * Temporary modify enet mode to 1G one, so MII functions can
+ * work correctly.
+ */
+ enet_mode = p_memac->enet_mode;
+ p_memac->enet_mode =
+ MAKE_ENET_MODE(ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+ ENET_SPEED_1000);
+
+ /* 1000BaseX mode */
+ tmp_reg16 = PHY_SGMII_IF_MODE_1000X;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x14, tmp_reg16);
+
+ /* AN Device capability */
+ tmp_reg16 = PHY_SGMII_DEV_ABILITY_1000X;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x4, tmp_reg16);
+
+ /* Adjust link timer for SGMII -
+ * For Serdes 1000BaseX auto-negotiation the timer should be 10 ms.
+ * The link_timer register is configured in units of the clock.
+ * - When running as 1G SGMII, Serdes clock is 125 MHz, so
+ * unit = 1 / (125*10^6 Hz) = 8 ns.
+ * 10 ms in units of 8 ns = 10ms / 8ns = 1250000 = 0x1312d0
+ * - When running as 2.5G SGMII, Serdes clock is 312.5 MHz, so
+ * unit = 1 / (312.5*10^6 Hz) = 3.2 ns.
+ * 10 ms in units of 3.2 ns = 10ms / 3.2ns = 3125000 = 0x2faf08.
+ * Since link_timer value of 1G SGMII will be too short for 2.5 SGMII,
+ * we always set up here a value of 2.5 SGMII.
+ */
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x13, 0x002f);
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x12, 0xaf08);
+
+ /* Restart AN */
+ tmp_reg16 = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+ memac_mii_write_phy_reg(p_memac, phy_addr, 0x0, tmp_reg16);
+
+ /* Restore original enet mode */
+ p_memac->enet_mode = enet_mode;
+}
+
+static int check_init_parameters(struct memac_t *p_memac)
+{
+ if (p_memac->addr == 0) {
+ pr_err("Ethernet MAC must have a valid MAC address\n");
+ return -EDOM;
+ }
+ if (!p_memac->f_exception) {
+ pr_err("Uninitialized f_exception\n");
+ return -EDOM;
+ }
+ if (!p_memac->f_event) {
+ pr_warn("Uninitialize f_event\n");
+ return -EDOM;
+ }
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_memac->p_memac_drv_param->no_length_check_enable) {
+ pr_err("LengthCheck!\n");
+ return -ENOSYS;
+ }
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+
+ return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+ uint32_t bit_mask;
+
+ switch (exception) {
+ case FM_MAC_EX_10G_1TX_ECC_ER:
+ bit_mask = MEMAC_IMASK_TECC_ER;
+ break;
+ case FM_MAC_EX_10G_RX_ECC_ER:
+ bit_mask = MEMAC_IMASK_RECC_ER;
+ break;
+ case FM_MAC_EX_TS_FIFO_ECC_ERR:
+ bit_mask = MEMAC_IMASK_TSECC_ER;
+ break;
+ case FM_MAC_EX_MAGIC_PACKET_INDICATION:
+ bit_mask = MEMAC_IMASK_MGI;
+ break;
+ default:
+ bit_mask = 0;
+ break;
+ }
+
+ return bit_mask;
+}
+
+static void memac_err_exception(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t event, imask;
+
+ event = fman_memac_get_event(p_memac->p_mem_map, 0xffffffff);
+ imask = fman_memac_get_interrupt_mask(p_memac->p_mem_map);
+
+ /* Imask include both error and notification/event bits.
+ * Leaving only error bits enabled by imask.
+ * The imask error bits are shifted by 16 bits offset from
+ * their corresponding location in the ievent - hence the >> 16
+ */
+ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+ fman_memac_ack_event(p_memac->p_mem_map, event);
+
+ if (event & MEMAC_IEVNT_TS_ECC_ER)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_TS_FIFO_ECC_ERR);
+ if (event & MEMAC_IEVNT_TX_ECC_ER)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & MEMAC_IEVNT_RX_ECC_ER)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_10G_RX_ECC_ER);
+}
+
+static void memac_exception(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t event, imask;
+
+ event = fman_memac_get_event(p_memac->p_mem_map, 0xffffffff);
+ imask = fman_memac_get_interrupt_mask(p_memac->p_mem_map);
+
+ /* Imask include both error and notification/event bits.
+ * Leaving only error bits enabled by imask.
+ * The imask error bits are shifted by 16 bits offset from
+ * their corresponding location in the ievent - hence the >> 16
+ */
+ event &= ((imask & MEMAC_ALL_ERRS_IMASK) >> 16);
+
+ fman_memac_ack_event(p_memac->p_mem_map, event);
+
+ if (event & MEMAC_IEVNT_MGI)
+ p_memac->f_exception(p_memac->h_app,
+ FM_MAC_EX_MAGIC_PACKET_INDICATION);
+}
+
+static void free_init_resources(struct memac_t *p_memac)
+{
+ fm_unregister_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_memac->mac_id,
+ FM_INTR_TYPE_ERR);
+
+ /* release the driver's group hash table */
+ free_hash_table(p_memac->p_multicast_addr_hash);
+ p_memac->p_multicast_addr_hash = NULL;
+
+ /* release the driver's individual hash table */
+ free_hash_table(p_memac->p_unicast_addr_hash);
+ p_memac->p_unicast_addr_hash = NULL;
+}
+
+/* Checks if p_memac driver parameters were initialized
+ * returns 0 if success else returns error code
+ */
+static int is_init_done(struct memac_cfg *p_memac_drv_parameters)
+{
+ if (!p_memac_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+/* mEMAC API routine */
+
+static int memac_enable(void *h_memac, enum comm_mode mode)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_enable(p_memac->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int memac_disable(void *h_memac, enum comm_mode mode)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_disable(p_memac->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int memac_set_promiscuous(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_set_promiscuous(p_memac->p_mem_map, new_val);
+
+ return 0;
+}
+
+static int memac_adjust_link(void *h_memac, enum ethernet_speed speed)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret, full_duplex = true;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_adjust_link(p_memac->p_mem_map,
+ (enum enet_interface)
+ ENET_INTERFACE_FROM_MODE(p_memac->enet_mode),
+ (enum enet_speed)speed, full_duplex);
+ return 0;
+}
+
+/* memac configs modification function */
+
+static int memac_cfg_lb(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->loopback_enable = new_val;
+
+ return 0;
+}
+
+static int memac_cfg_max_frame_len(void *h_memac, uint16_t new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->max_frame_length = new_val;
+
+ return 0;
+}
+
+static int memac_cfg_pad(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->pad_enable = new_val;
+
+ return 0;
+}
+
+static int memac_cfg_len_check(void *h_memac, bool new_val)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->no_length_check_enable = !new_val;
+
+ return 0;
+}
+
+static int memac_cfg_exception(void *h_memac,
+ enum fm_mac_exceptions exception, bool enable)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_memac->exceptions |= bit_mask;
+ else
+ p_memac->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ return 0;
+}
+
+static int memac_cfg_reset_on_init(void *h_memac, bool enable)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_memac->p_memac_drv_param->reset_on_init = enable;
+
+ return 0;
+}
+
+/* memac run time api functions */
+
+static int memac_set_tx_auto_pause_frames(void *h_memac,
+ uint16_t pause_time)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ fman_memac_set_tx_pause_frames(p_memac->p_mem_map, FM_MAC_NO_PFC,
+ pause_time, 0);
+
+ return 0;
+}
+
+static int memac_set_rx_ignore_pause_frames(void *h_memac, bool en)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_set_rx_ignore_pause_frames(p_memac->p_mem_map, en);
+
+ return 0;
+}
+
+static int memac_modify_mac_address(void *h_memac,
+ enet_addr_t *p_enet_addr)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ fman_memac_add_addr_in_paddr(p_memac->p_mem_map,
+ (uint8_t *)(*p_enet_addr), 0);
+
+ return 0;
+}
+
+static int memac_add_hash_mac_address(void *h_memac,
+ enet_addr_t *p_eth_addr)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ struct eth_hash_entry_t *p_hash_entry;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ if (!(eth_addr & GROUP_ADDRESS)) {
+ /* Unicast addresses not supported in hash */
+ pr_err("Unicast Address\n");
+ return -ENOSYS;
+ }
+ hash = get_mac_addr_hash_code(eth_addr) & HASH_CTRL_ADDR_MASK;
+
+ /* Create element to be added to the driver hash table */
+ p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+ if (!p_hash_entry)
+ return -ENOMEM;
+ p_hash_entry->addr = eth_addr;
+ INIT_LIST_HEAD(&p_hash_entry->node);
+
+ list_add_tail(&p_hash_entry->node,
+ &p_memac->p_multicast_addr_hash->p_lsts[hash]);
+ fman_memac_set_hash_table(p_memac->p_mem_map,
+ (hash | HASH_CTRL_MCAST_EN));
+
+ return 0;
+}
+
+static int memac_del_hash_mac_address(void *h_memac,
+ enet_addr_t *p_eth_addr)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+ struct list_head *p_pos;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ hash = get_mac_addr_hash_code(eth_addr) & HASH_CTRL_ADDR_MASK;
+
+ list_for_each(p_pos, &p_memac->p_multicast_addr_hash->p_lsts[hash]) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_memac->p_multicast_addr_hash->p_lsts[hash]))
+ fman_memac_set_hash_table(p_memac->p_mem_map,
+ (hash & ~HASH_CTRL_MCAST_EN));
+
+ return 0;
+}
+
+static int memac_set_exception(void *h_memac,
+ enum fm_mac_exceptions exception,
+ bool enable)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return ret;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_memac->exceptions |= bit_mask;
+ else
+ p_memac->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ fman_memac_set_exception(p_memac->p_mem_map, bit_mask, enable);
+
+ return 0;
+}
+
+static uint16_t memac_get_max_frame_length(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ int ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (ret)
+ return 0;
+
+ return fman_memac_get_max_frame_len(p_memac->p_mem_map);
+}
+
+/* mEMAC Init & Free API */
+static int memac_init(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+ struct memac_cfg *p_memac_drv_param;
+ enum enet_interface enet_interface;
+ enum enet_speed enet_speed;
+ uint8_t i, phy_addr;
+ enet_addr_t eth_addr;
+ enum fm_mac_type port_type;
+ bool slow_10g_if = false;
+ int err, ret;
+
+ ret = is_init_done(p_memac->p_memac_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ err = check_init_parameters(p_memac);
+ if (err)
+ return err;
+
+ p_memac_drv_param = p_memac->p_memac_drv_param;
+
+ if (p_memac->fm_mac_ctrl_drv.fm_rev_info.major_rev == 6 &&
+ p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 4)
+ slow_10g_if = true;
+
+ port_type =
+ ((ENET_SPEED_FROM_MODE(p_memac->enet_mode) <
+ ENET_SPEED_10000) ? FM_MAC_1G : FM_MAC_10G);
+
+ /* First, reset the MAC if desired. */
+ if (p_memac_drv_param->reset_on_init)
+ fman_memac_reset(p_memac->p_mem_map);
+
+ /* MAC Address */
+ MAKE_ENET_ADDR_FROM_UINT64(p_memac->addr, eth_addr);
+ fman_memac_add_addr_in_paddr(p_memac->p_mem_map,
+ (uint8_t *)eth_addr, 0);
+
+ enet_interface =
+ (enum enet_interface)ENET_INTERFACE_FROM_MODE(p_memac->enet_mode);
+ enet_speed = (enum enet_speed)ENET_SPEED_FROM_MODE(p_memac->enet_mode);
+
+ fman_memac_init(p_memac->p_mem_map,
+ p_memac->p_memac_drv_param,
+ enet_interface,
+ enet_speed,
+ slow_10g_if,
+ p_memac->exceptions);
+
+#ifdef FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320
+ {
+ uint32_t tmp_reg = 0;
+
+ fm_get_revision(p_memac->fm_mac_ctrl_drv.h_fm,
+ &p_memac->fm_mac_ctrl_drv.fm_rev_info);
+ /* check the FMAN version - the bug exists only in rev1 */
+ if ((p_memac->fm_mac_ctrl_drv.fm_rev_info.major_rev == 6) &&
+ ((p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 0) ||
+ (p_memac->fm_mac_ctrl_drv.fm_rev_info.minor_rev == 3))) {
+ /* MAC strips CRC from received frames - this
+ * workaround should decrease the likelihood of bug
+ * appearance
+ */
+ tmp_reg = GET_UINT32(p_memac->p_mem_map->
+ command_config);
+ tmp_reg &= ~CMD_CFG_CRC_FWD;
+ WRITE_UINT32(p_memac->p_mem_map->command_config,
+ tmp_reg);
+ }
+ }
+#endif /* FM_RX_FIFO_CORRUPT_ERRATA_10GMAC_A006320 */
+
+ if (ENET_INTERFACE_FROM_MODE(p_memac->enet_mode) == ENET_IF_SGMII) {
+ /* Configure internal SGMII PHY */
+ if (p_memac->enet_mode & ENET_IF_SGMII_BASEX)
+ setup_sgmii_internal_phy_base_x(p_memac, PHY_MDIO_ADDR);
+ else
+ setup_sgmii_internal_phy(p_memac, PHY_MDIO_ADDR);
+ } else if (ENET_INTERFACE_FROM_MODE(p_memac->enet_mode) ==
+ ENET_IF_QSGMII) {
+ /* Configure 4 internal SGMII PHYs */
+ for (i = 0; i < 4; i++) {
+ /* QSGMII PHY address occupies 3 upper bits of 5-bit
+ * phy_address; the lower 2 bits are used to extend
+ * register address space and access each one of 4
+ * ports inside QSGMII.
+ */
+ phy_addr = (uint8_t)((PHY_MDIO_ADDR << 2) | i);
+ if (p_memac->enet_mode & ENET_IF_SGMII_BASEX)
+ setup_sgmii_internal_phy_base_x(p_memac,
+ phy_addr);
+ else
+ setup_sgmii_internal_phy(p_memac, phy_addr);
+ }
+ }
+
+ /* Max Frame Length */
+ err = fm_set_mac_max_frame(p_memac->fm_mac_ctrl_drv.h_fm,
+ port_type,
+ p_memac->fm_mac_ctrl_drv.mac_id,
+ p_memac_drv_param->max_frame_length);
+ if (err) {
+ pr_err("settings Mac max frame length is FAILED\n");
+ return err;
+ }
+
+ p_memac->p_multicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_memac->p_multicast_addr_hash) {
+ free_init_resources(p_memac);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ p_memac->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_memac->p_unicast_addr_hash) {
+ free_init_resources(p_memac);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ fm_register_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_memac->mac_id,
+ FM_INTR_TYPE_ERR,
+ memac_err_exception,
+ p_memac);
+
+ fm_register_intr(p_memac->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_memac->mac_id, FM_INTR_TYPE_NORMAL,
+ memac_exception, p_memac);
+
+ kfree(p_memac_drv_param);
+ p_memac->p_memac_drv_param = NULL;
+
+ return 0;
+}
+
+static int memac_free(void *h_memac)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ free_init_resources(p_memac);
+
+ kfree(p_memac->p_memac_drv_param);
+ kfree(p_memac);
+
+ return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+ p_fm_mac_ctrl_drv)
+{
+ p_fm_mac_ctrl_drv->f_fm_mac_init = memac_init;
+ p_fm_mac_ctrl_drv->f_fm_mac_free = memac_free;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = memac_cfg_lb;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len =
+ memac_cfg_max_frame_len;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc = memac_cfg_pad;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = memac_cfg_len_check;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = memac_cfg_exception;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init =
+ memac_cfg_reset_on_init;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_exception = memac_set_exception;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = memac_set_promiscuous;
+ p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = memac_adjust_link;
+ p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = NULL;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_enable = memac_enable;
+ p_fm_mac_ctrl_drv->f_fm_mac_disable = memac_disable;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+ memac_set_tx_auto_pause_frames;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+ memac_set_rx_ignore_pause_frames;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr =
+ memac_modify_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+ memac_add_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+ memac_del_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_id = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_version = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+ memac_get_max_frame_length;
+}
+
+/* m_emac config main entry */
+
+void *memac_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct memac_t *p_memac;
+ struct memac_cfg *p_memac_drv_param;
+ uintptr_t base_addr;
+
+ base_addr = p_fm_mac_param->base_addr;
+ /* allocate memory for the m_emac data structure */
+ p_memac = kzalloc(sizeof(*p_memac), GFP_KERNEL);
+ if (!p_memac)
+ return NULL;
+
+ init_fm_mac_ctrl_drv(&p_memac->fm_mac_ctrl_drv);
+
+ /* allocate memory for the m_emac driver parameters data structure */
+ p_memac_drv_param = kzalloc(sizeof(*p_memac_drv_param),
+ GFP_KERNEL);
+ if (!p_memac_drv_param) {
+ memac_free(p_memac);
+ return NULL;
+ }
+
+ /* Plant parameter structure pointer */
+ p_memac->p_memac_drv_param = p_memac_drv_param;
+
+ fman_memac_defconfig(p_memac_drv_param);
+
+ p_memac->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+
+ p_memac->p_mem_map =
+ (struct memac_regs __iomem *)UINT_TO_PTR(base_addr);
+ p_memac->p_mii_mem_map = (struct memac_mii_access_mem_map __iomem *)
+ UINT_TO_PTR(base_addr + MEMAC_TO_MII_OFFSET);
+
+ p_memac->enet_mode = p_fm_mac_param->enet_mode;
+ p_memac->mac_id = p_fm_mac_param->mac_id;
+ p_memac->exceptions = MEMAC_default_exceptions;
+ p_memac->f_exception = p_fm_mac_param->f_exception;
+ p_memac->f_event = p_fm_mac_param->f_event;
+ p_memac->h_app = p_fm_mac_param->h_app;
+
+ return p_memac;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac.h b/drivers/net/ethernet/freescale/fman/mac/memac.h
new file mode 100644
index 0000000..9f0c607
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac.h
@@ -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.
+ */
+
+/* FM Multirate Ethernet MAC (mEMAC) */
+#ifndef __MEMAC_H
+#define __MEMAC_H
+
+#include "service.h"
+
+#include "fsl_fman_memac_mii_acc.h"
+#include "fm_mac.h"
+#include "fsl_fman_memac.h"
+
+#define MEMAC_default_exceptions\
+ ((uint32_t)(MEMAC_IMASK_TSECC_ER | MEMAC_IMASK_TECC_ER |\
+ MEMAC_IMASK_RECC_ER | MEMAC_IMASK_MGI))
+
+struct memac_t {
+ /* Upper Mac control block */
+ struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+ /* Handle to the upper layer application */
+ void *h_app;
+ /* Pointer to MAC memory mapped registers */
+ struct memac_regs __iomem *p_mem_map;
+ /* Pointer to MII memory mapped registers */
+ struct memac_mii_access_mem_map __iomem *p_mii_mem_map;
+ /* MAC address of device */
+ uint64_t addr;
+ /* Ethernet physical interface */
+ enum e_enet_mode enet_mode;
+ fm_mac_exception_cb *f_exception;
+ int mdio_irq;
+ fm_mac_exception_cb *f_event;
+ /* Whether a particular individual address
+ * recognition register is being used
+ */
+ bool ind_addr_reg_used[MEMAC_NUM_OF_PADDRS];
+ /* MAC address for particular individual address
+ * recognition register
+ */
+ uint64_t paddr[MEMAC_NUM_OF_PADDRS];
+ /* Number of individual addresses in registers for this station. */
+ uint8_t num_of_ind_addr_in_regs;
+ /* Pointer to driver's global address hash table */
+ struct eth_hash_t *p_multicast_addr_hash;
+ /* Pointer to driver's individual address hash table */
+ struct eth_hash_t *p_unicast_addr_hash;
+ bool debug_mode;
+ uint8_t mac_id;
+ uint32_t exceptions;
+ struct memac_cfg *p_memac_drv_param;
+};
+
+/* Internal PHY access */
+#define PHY_MDIO_ADDR 0
+
+/* Internal PHY Registers - SGMII */
+#define PHY_SGMII_CR_RESET_AN 0x0200
+#define PHY_SGMII_CR_DEF_VAL 0x1140
+#define PHY_SGMII_DEV_ABILITY_SGMII 0x4001
+#define PHY_SGMII_DEV_ABILITY_1000X 0x01A0
+#define PHY_SGMII_IF_MODE_AN 0x0002
+#define PHY_SGMII_IF_MODE_SGMII 0x0001
+#define PHY_SGMII_IF_MODE_1000X 0x0000
+
+/* Offset from the MEM map to the MDIO mem map */
+#define MEMAC_TO_MII_OFFSET 0x030
+
+int memac_mii_write_phy_reg(void *h_memac, uint8_t phy_addr, uint8_t reg,
+ uint16_t data);
+int memac_mii_read_phy_reg(void *h_memac, uint8_t phy_addr, uint8_t reg,
+ uint16_t *p_data);
+
+#endif /* __MEMAC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
new file mode 100644
index 0000000..0150e9d
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.c
@@ -0,0 +1,66 @@
+/*
+ * 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 "fm_mac.h"
+#include "memac.h"
+
+#include "fm_common.h"
+#include "memac_mii_acc.h"
+
+int memac_mii_write_phy_reg(void *h_memac,
+ uint8_t phy_addr, uint8_t reg, uint16_t data)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ return (int)fman_memac_mii_write_phy_reg(p_memac->p_mii_mem_map,
+ phy_addr,
+ reg,
+ data,
+ (enum enet_speed)
+ ENET_SPEED_FROM_MODE
+ (p_memac->enet_mode));
+}
+
+int memac_mii_read_phy_reg(void *h_memac,
+ uint8_t phy_addr, uint8_t reg, uint16_t *p_data)
+{
+ struct memac_t *p_memac = (struct memac_t *)h_memac;
+
+ return fman_memac_mii_read_phy_reg(p_memac->p_mii_mem_map,
+ phy_addr,
+ reg,
+ p_data,
+ (enum enet_speed)
+ ENET_SPEED_FROM_MODE(p_memac->
+ enet_mode));
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
new file mode 100644
index 0000000..f38572c
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/memac_mii_acc.h
@@ -0,0 +1,50 @@
+/*
+ * 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 __MEMAC_MII_ACC_H
+#define __MEMAC_MII_ACC_H
+
+#include "service.h"
+
+/* MII Management Registers */
+#define MDIO_CFG_CLK_DIV_MASK 0x0080ff80
+#define MDIO_CFG_HOLD_MASK 0x0000001c
+#define MDIO_CFG_ENC45 0x00000040
+#define MDIO_CFG_READ_ERR 0x00000002
+#define MDIO_CFG_BSY 0x00000001
+
+#define MDIO_CTL_PHY_ADDR_SHIFT 5
+#define MDIO_CTL_READ 0x00008000
+
+#define MDIO_DATA_BSY 0x80000000
+
+#endif /* __MEMAC_MII_ACC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec.c b/drivers/net/ethernet/freescale/fman/mac/tgec.c
new file mode 100644
index 0000000..30b0078
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec.c
@@ -0,0 +1,797 @@
+/*
+ * 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.
+ */
+
+/* TGEC MAC ... */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "service.h"
+#include "crc_mac_addr_ext.h"
+
+#include "fm_common.h"
+#include "fsl_fman_tgec.h"
+#include "tgec.h"
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/bitrev.h>
+
+/* Internal routines */
+
+static int check_init_parameters(struct tgec_t *p_tgec)
+{
+ if (ENET_SPEED_FROM_MODE(p_tgec->enet_mode) < ENET_SPEED_10000) {
+ pr_err("10G MAC driver only support 10G speed\n");
+ return -EDOM;
+ }
+ if (p_tgec->addr == 0) {
+ pr_err("Ethernet 10G MAC Must have valid MAC Address\n");
+ return -EDOM;
+ }
+ if (!p_tgec->f_exception) {
+ pr_err("uninitialized f_exception\n");
+ return -EDOM;
+ }
+ if (!p_tgec->f_event) {
+ pr_err("uninitialized f_event\n");
+ return -EDOM;
+ }
+#ifdef FM_LEN_CHECK_ERRATA_FMAN_SW002
+ if (!p_tgec->p_tgec_drv_param->no_length_check_enable) {
+ pr_warn("LengthCheck!\n");
+ return -EDOM;
+ }
+#endif /* FM_LEN_CHECK_ERRATA_FMAN_SW002 */
+ return 0;
+}
+
+static int get_exception_flag(enum fm_mac_exceptions exception)
+{
+ uint32_t bit_mask;
+
+ switch (exception) {
+ case FM_MAC_EX_10G_MDIO_SCAN_EVENT:
+ bit_mask = TGEC_IMASK_MDIO_SCAN_EVENT;
+ break;
+ case FM_MAC_EX_10G_MDIO_CMD_CMPL:
+ bit_mask = TGEC_IMASK_MDIO_CMD_CMPL;
+ break;
+ case FM_MAC_EX_10G_REM_FAULT:
+ bit_mask = TGEC_IMASK_REM_FAULT;
+ break;
+ case FM_MAC_EX_10G_LOC_FAULT:
+ bit_mask = TGEC_IMASK_LOC_FAULT;
+ break;
+ case FM_MAC_EX_10G_1TX_ECC_ER:
+ bit_mask = TGEC_IMASK_TX_ECC_ER;
+ break;
+ case FM_MAC_EX_10G_TX_FIFO_UNFL:
+ bit_mask = TGEC_IMASK_TX_FIFO_UNFL;
+ break;
+ case FM_MAC_EX_10G_TX_FIFO_OVFL:
+ bit_mask = TGEC_IMASK_TX_FIFO_OVFL;
+ break;
+ case FM_MAC_EX_10G_TX_ER:
+ bit_mask = TGEC_IMASK_TX_ER;
+ break;
+ case FM_MAC_EX_10G_RX_FIFO_OVFL:
+ bit_mask = TGEC_IMASK_RX_FIFO_OVFL;
+ break;
+ case FM_MAC_EX_10G_RX_ECC_ER:
+ bit_mask = TGEC_IMASK_RX_ECC_ER;
+ break;
+ case FM_MAC_EX_10G_RX_JAB_FRM:
+ bit_mask = TGEC_IMASK_RX_JAB_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_OVRSZ_FRM:
+ bit_mask = TGEC_IMASK_RX_OVRSZ_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_RUNT_FRM:
+ bit_mask = TGEC_IMASK_RX_RUNT_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_FRAG_FRM:
+ bit_mask = TGEC_IMASK_RX_FRAG_FRM;
+ break;
+ case FM_MAC_EX_10G_RX_LEN_ER:
+ bit_mask = TGEC_IMASK_RX_LEN_ER;
+ break;
+ case FM_MAC_EX_10G_RX_CRC_ER:
+ bit_mask = TGEC_IMASK_RX_CRC_ER;
+ break;
+ case FM_MAC_EX_10G_RX_ALIGN_ER:
+ bit_mask = TGEC_IMASK_RX_ALIGN_ER;
+ break;
+ default:
+ bit_mask = 0;
+ break;
+ }
+
+ return bit_mask;
+}
+
+static uint32_t get_mac_addr_hash_code(uint64_t eth_addr)
+{
+ uint32_t crc;
+
+ /* CRC calculation */
+ GET_MAC_ADDR_CRC(eth_addr, crc);
+
+ crc = bitrev32(crc);
+
+ return crc;
+}
+
+static void tgec_err_exception(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ uint32_t event;
+ struct tgec_regs __iomem *p_tgec_mem_map = p_tgec->p_mem_map;
+
+ /* do not handle MDIO events */
+ event =
+ fman_tgec_get_event(p_tgec_mem_map,
+ ~(TGEC_IMASK_MDIO_SCAN_EVENT |
+ TGEC_IMASK_MDIO_CMD_CMPL));
+ event &= fman_tgec_get_interrupt_mask(p_tgec_mem_map);
+
+ fman_tgec_ack_event(p_tgec_mem_map, event);
+
+ if (event & TGEC_IMASK_REM_FAULT)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_REM_FAULT);
+ if (event & TGEC_IMASK_LOC_FAULT)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_LOC_FAULT);
+ if (event & TGEC_IMASK_TX_ECC_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_1TX_ECC_ER);
+ if (event & TGEC_IMASK_TX_FIFO_UNFL)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_TX_FIFO_UNFL);
+ if (event & TGEC_IMASK_TX_FIFO_OVFL)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_TX_FIFO_OVFL);
+ if (event & TGEC_IMASK_TX_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_TX_ER);
+ if (event & TGEC_IMASK_RX_FIFO_OVFL)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_RX_FIFO_OVFL);
+ if (event & TGEC_IMASK_RX_ECC_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_ECC_ER);
+ if (event & TGEC_IMASK_RX_JAB_FRM)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_JAB_FRM);
+ if (event & TGEC_IMASK_RX_OVRSZ_FRM)
+ p_tgec->f_exception(p_tgec->h_app,
+ FM_MAC_EX_10G_RX_OVRSZ_FRM);
+ if (event & TGEC_IMASK_RX_RUNT_FRM)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_RUNT_FRM);
+ if (event & TGEC_IMASK_RX_FRAG_FRM)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_FRAG_FRM);
+ if (event & TGEC_IMASK_RX_LEN_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_LEN_ER);
+ if (event & TGEC_IMASK_RX_CRC_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_CRC_ER);
+ if (event & TGEC_IMASK_RX_ALIGN_ER)
+ p_tgec->f_exception(p_tgec->h_app, FM_MAC_EX_10G_RX_ALIGN_ER);
+}
+
+static void free_init_resources(struct tgec_t *p_tgec)
+{
+ fm_unregister_intr(p_tgec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC, p_tgec->mac_id, FM_INTR_TYPE_ERR);
+
+ /* release the driver's group hash table */
+ free_hash_table(p_tgec->p_multicast_addr_hash);
+ p_tgec->p_multicast_addr_hash = NULL;
+
+ /* release the driver's individual hash table */
+ free_hash_table(p_tgec->p_unicast_addr_hash);
+ p_tgec->p_unicast_addr_hash = NULL;
+}
+
+/* Checks if p_tgec driver parameters were initialized
+ * returns 0 if success else returns error
+ */
+static int is_init_done(struct tgec_cfg *p_tgec_drv_parameters)
+{
+ if (!p_tgec_drv_parameters)
+ return 0;
+ return -ENOSYS;
+}
+
+/* TGEC MAC API routines */
+static int tgec_enable(void *h_tgec, enum comm_mode mode)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_enable(p_tgec->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int tgec_disable(void *h_tgec, enum comm_mode mode)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_disable(p_tgec->p_mem_map,
+ (mode & COMM_MODE_RX),
+ (mode & COMM_MODE_TX));
+
+ return 0;
+}
+
+static int tgec_set_promiscuous(void *h_tgec, bool new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_promiscuous(p_tgec->p_mem_map, new_val);
+
+ return 0;
+}
+
+/* tgec configs modification functions */
+
+static int tgec_cfg_lb(void *h_tgec, bool new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->loopback_enable = new_val;
+
+ return 0;
+}
+
+static int tgec_cfg_max_frame_len(void *h_tgec, uint16_t new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->max_frame_length = new_val;
+
+ return 0;
+}
+
+static int tgec_cfg_len_check(void *h_tgec, bool __maybe_unused new_val)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->no_length_check_enable = !new_val;
+
+ return 0;
+}
+
+static int tgec_cfg_exception(void *h_tgec,
+ enum fm_mac_exceptions exception, bool enable)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_tgec->exceptions |= bit_mask;
+ else
+ p_tgec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ return 0;
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+
+static int tgec_cfg_skip_fman11_wa(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ p_tgec->p_tgec_drv_param->skip_fman11_workaround = true;
+
+ return 0;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* tgec run time api functions */
+
+/* backward compatibility. will be removed in the future. */
+static int tgec_tx_mac_pause(void *h_tgec, uint16_t pause_time)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_tx_pause_frames(p_tgec->p_mem_map, pause_time);
+
+ return 0;
+}
+
+static int tgec_set_tx_pause_frames(void *h_tgec,
+ uint8_t __maybe_unused priority,
+ uint16_t pause_time,
+ uint16_t __maybe_unused thresh_time)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_tx_pause_frames(p_tgec->p_mem_map, pause_time);
+
+ return 0;
+}
+
+static int tgec_rx_ignore_mac_pause(void *h_tgec, bool en)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ fman_tgec_set_rx_ignore_pause_frames(p_tgec->p_mem_map, en);
+
+ return 0;
+}
+
+static int tgec_modify_mac_address(void *h_tgec, enet_addr_t
+ *p_enet_addr)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ p_tgec->addr = ENET_ADDR_TO_UINT64(*p_enet_addr);
+ fman_tgec_set_mac_address(p_tgec->p_mem_map, (uint8_t *)(*p_enet_addr));
+
+ return 0;
+}
+
+static int tgec_add_hash_mac_address(void *h_tgec, enet_addr_t
+ *p_eth_addr)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ struct eth_hash_entry_t *p_hash_entry;
+ uint32_t crc;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ENET_ADDR_TO_UINT64(*p_eth_addr);
+
+ if (!(eth_addr & GROUP_ADDRESS)) {
+ /* Unicast addresses not supported in hash */
+ pr_err("Unicast Address\n");
+ return -ENOSYS;
+ }
+ /* CRC calculation */
+ crc = get_mac_addr_hash_code(eth_addr);
+
+ /* Take 9 MSB bits */
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;
+
+ /* Create element to be added to the driver hash table */
+ p_hash_entry = kmalloc(sizeof(*p_hash_entry), GFP_KERNEL);
+ if (!p_hash_entry)
+ return -ENOMEM;
+ p_hash_entry->addr = eth_addr;
+ INIT_LIST_HEAD(&p_hash_entry->node);
+
+ list_add_tail(&p_hash_entry->node,
+ &p_tgec->p_multicast_addr_hash->p_lsts[hash]);
+ fman_tgec_set_hash_table(p_tgec->p_mem_map,
+ (hash | TGEC_HASH_MCAST_EN));
+
+ return 0;
+}
+
+static int tgec_del_hash_mac_address(void *h_tgec, enet_addr_t
+ *p_eth_addr)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ struct eth_hash_entry_t *p_hash_entry = NULL;
+ struct list_head *p_pos;
+ uint32_t crc;
+ uint32_t hash;
+ uint64_t eth_addr;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ eth_addr = ((*(uint64_t *)p_eth_addr) >> 16);
+
+ /* CRC calculation */
+ crc = get_mac_addr_hash_code(eth_addr);
+ /* Take 9 MSB bits */
+ hash = (crc >> TGEC_HASH_MCAST_SHIFT) & TGEC_HASH_ADR_MSK;
+
+ list_for_each(p_pos, &p_tgec->p_multicast_addr_hash->p_lsts[hash]) {
+ p_hash_entry = ETH_HASH_ENTRY_OBJ(p_pos);
+ if (p_hash_entry->addr == eth_addr) {
+ list_del_init(&p_hash_entry->node);
+ kfree(p_hash_entry);
+ break;
+ }
+ }
+ if (list_empty(&p_tgec->p_multicast_addr_hash->p_lsts[hash]))
+ fman_tgec_set_hash_table(p_tgec->p_mem_map,
+ (hash & ~TGEC_HASH_MCAST_EN));
+
+ return 0;
+}
+
+static int tgec_get_id(void *h_tgec,
+ uint32_t __maybe_unused *mac_id)
+{
+ struct tgec_t __maybe_unused *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ pr_warn("tgec_get_id not supported\n");
+ return -ENOSYS;
+}
+
+static int tgec_get_version(void *h_tgec, uint32_t *mac_version)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ *mac_version = fman_tgec_get_revision(p_tgec->p_mem_map);
+
+ return 0;
+}
+
+static int tgec_set_excpetion(void *h_tgec,
+ enum fm_mac_exceptions exception,
+ bool enable)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ uint32_t bit_mask = 0;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return ret;
+
+ bit_mask = get_exception_flag(exception);
+ if (bit_mask) {
+ if (enable)
+ p_tgec->exceptions |= bit_mask;
+ else
+ p_tgec->exceptions &= ~bit_mask;
+ } else {
+ pr_err("Undefined exception\n");
+ return -EDOM;
+ }
+ if (enable)
+ fman_tgec_enable_interrupt(p_tgec->p_mem_map, bit_mask);
+ else
+ fman_tgec_disable_interrupt(p_tgec->p_mem_map, bit_mask);
+
+ return 0;
+}
+
+static uint16_t tgec_get_max_frame_length(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ int ret;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (ret)
+ return 0;
+
+ return fman_tgec_get_max_frame_len(p_tgec->p_mem_map);
+}
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+static int tgec_tx_ecc_workaround(struct tgec_t *p_tgec)
+{
+ int err;
+
+ pr_info("Applying 10G TX ECC workaround (10GMAC-A004) ... ");
+
+ /* enable and set promiscuous */
+ fman_tgec_enable(p_tgec->p_mem_map, true, true);
+ fman_tgec_set_promiscuous(p_tgec->p_mem_map, true);
+ err =
+ fm_10g_tx_ecc_workaround(p_tgec->fm_mac_ctrl_drv.h_fm,
+ p_tgec->mac_id);
+ /* disable */
+ fman_tgec_set_promiscuous(p_tgec->p_mem_map, false);
+ fman_tgec_enable(p_tgec->p_mem_map, false, false);
+ fman_tgec_ack_event(p_tgec->p_mem_map, 0xffffffff);
+
+ if (err)
+ pr_err("FAILED!\n");
+ else
+ pr_info("done.\n");
+
+ return err;
+}
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+/* FM Init&Free API */
+
+static int tgec_init(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+ struct tgec_cfg *p_tgec_drv_param;
+ enet_addr_t eth_addr;
+ int err, ret, ret_err;
+
+ ret = is_init_done(p_tgec->p_tgec_drv_param);
+ if (!ret)
+ return -ENOSYS;
+
+ fm_get_revision(p_tgec->fm_mac_ctrl_drv.h_fm,
+ &p_tgec->fm_mac_ctrl_drv.fm_rev_info);
+ ret_err = check_init_parameters(p_tgec);
+ if (ret_err)
+ return ret_err;
+
+ p_tgec_drv_param = p_tgec->p_tgec_drv_param;
+
+ MAKE_ENET_ADDR_FROM_UINT64(p_tgec->addr, eth_addr);
+ fman_tgec_set_mac_address(p_tgec->p_mem_map, (uint8_t *)eth_addr);
+
+ /* interrupts */
+#ifdef FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005
+ {
+ if (p_tgec->fm_mac_ctrl_drv.fm_rev_info.major_rev <= 2)
+ p_tgec->exceptions &=
+ ~(TGEC_IMASK_REM_FAULT | TGEC_IMASK_LOC_FAULT);
+ }
+#endif /* FM_10G_REM_N_LCL_FLT_EX_10GMAC_ERRATA_SW005 */
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ if (!p_tgec->p_tgec_drv_param->skip_fman11_workaround) {
+ err = tgec_tx_ecc_workaround(p_tgec);
+ if (err != 0) {
+ free_init_resources(p_tgec);
+ pr_warn("tgec_tx_ecc_workaround failed\n");
+ }
+ }
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ err =
+ fman_tgec_init(p_tgec->p_mem_map, p_tgec_drv_param,
+ p_tgec->exceptions);
+ if (err) {
+ free_init_resources(p_tgec);
+ pr_err("TGEC version doesn't support this i/f mode\n");
+ return err;
+ }
+
+ /* Max Frame Length */
+ err = fm_set_mac_max_frame(p_tgec->fm_mac_ctrl_drv.h_fm,
+ FM_MAC_10G,
+ p_tgec->fm_mac_ctrl_drv.mac_id,
+ p_tgec_drv_param->max_frame_length);
+ if (err) {
+ pr_err("Setting max frame length FAILED\n");
+ free_init_resources(p_tgec);
+ return -EINVAL;
+ }
+
+#ifdef FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007
+ if (p_tgec->fm_mac_ctrl_drv.fm_rev_info.major_rev == 2)
+ fman_tgec_set_erratum_tx_fifo_corruption_10gmac_a007(p_tgec->
+ p_mem_map);
+#endif /* FM_TX_FIFO_CORRUPTION_ERRATA_10GMAC_A007 */
+
+ p_tgec->p_multicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_tgec->p_multicast_addr_hash) {
+ free_init_resources(p_tgec);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ p_tgec->p_unicast_addr_hash = alloc_hash_table(HASH_TABLE_SIZE);
+ if (!p_tgec->p_unicast_addr_hash) {
+ free_init_resources(p_tgec);
+ pr_err("allocation hash table is FAILED\n");
+ return -ENOMEM;
+ }
+
+ fm_register_intr(p_tgec->fm_mac_ctrl_drv.h_fm,
+ FM_MOD_MAC,
+ p_tgec->mac_id,
+ FM_INTR_TYPE_ERR, tgec_err_exception, p_tgec);
+
+ kfree(p_tgec_drv_param);
+ p_tgec->p_tgec_drv_param = NULL;
+
+ return 0;
+}
+
+static int tgec_free(void *h_tgec)
+{
+ struct tgec_t *p_tgec = (struct tgec_t *)h_tgec;
+
+ free_init_resources(p_tgec);
+
+ if (p_tgec->p_tgec_drv_param)
+ p_tgec->p_tgec_drv_param = NULL;
+
+ kfree(p_tgec->p_tgec_drv_param);
+ kfree(p_tgec);
+
+ return 0;
+}
+
+static void init_fm_mac_ctrl_drv(struct fm_mac_ctrl_drv_t *
+ p_fm_mac_ctrl_drv)
+{
+ p_fm_mac_ctrl_drv->f_fm_mac_init = tgec_init;
+ p_fm_mac_ctrl_drv->f_fm_mac_free = tgec_free;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_lb = tgec_cfg_lb;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_max_frame_len = tgec_cfg_max_frame_len;
+
+ /* tgec always works with pad+crc */
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_pad_and_crc = NULL;
+ /* half-duplex is not supported in xgec */
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_len_check = tgec_cfg_len_check;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_exception = tgec_cfg_exception;
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_reset_on_init = NULL;
+
+#ifdef FM_TX_ECC_FRMS_ERRATA_10GMAC_A004
+ p_fm_mac_ctrl_drv->f_fm_mac_cfg_skip_fman11_wa =
+ tgec_cfg_skip_fman11_wa;
+#endif /* FM_TX_ECC_FRMS_ERRATA_10GMAC_A004 */
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_exception = tgec_set_excpetion;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_promiscuous = tgec_set_promiscuous;
+ p_fm_mac_ctrl_drv->f_fm_mac_adjust_link = NULL;
+ p_fm_mac_ctrl_drv->f_fm_mac_restart_autoneg = NULL;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_enable = tgec_enable;
+ p_fm_mac_ctrl_drv->f_fm_mac_disable = tgec_disable;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_auto_pause_frames =
+ tgec_tx_mac_pause;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_tx_pause_frames =
+ tgec_set_tx_pause_frames;
+ p_fm_mac_ctrl_drv->f_fm_mac_set_rx_ignore_pause_frames =
+ tgec_rx_ignore_mac_pause;
+
+ p_fm_mac_ctrl_drv->f_fm_mac_modify_mac_addr = tgec_modify_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_add_hash_mac_addr =
+ tgec_add_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_remove_hash_mac_addr =
+ tgec_del_hash_mac_address;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_id = tgec_get_id;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_version = tgec_get_version;
+ p_fm_mac_ctrl_drv->f_fm_mac_get_max_frame_length =
+ tgec_get_max_frame_length;
+}
+
+/* tgec config main entry */
+
+void *tgec_config(struct fm_mac_params_t *p_fm_mac_param)
+{
+ struct tgec_t *p_tgec;
+ struct tgec_cfg *p_tgec_drv_param;
+ uintptr_t base_addr;
+
+ base_addr = p_fm_mac_param->base_addr;
+ /* allocate memory for the UCC GETH data structure. */
+ p_tgec = kzalloc(sizeof(*p_tgec), GFP_KERNEL);
+ if (!p_tgec)
+ return NULL;
+
+ init_fm_mac_ctrl_drv(&p_tgec->fm_mac_ctrl_drv);
+
+ /* allocate memory for the 10G MAC driver parameters data structure. */
+ p_tgec_drv_param = kzalloc(sizeof(*p_tgec_drv_param), GFP_KERNEL);
+ if (!p_tgec_drv_param) {
+ tgec_free(p_tgec);
+ return NULL;
+ }
+
+ /* Plant parameter structure pointer */
+ p_tgec->p_tgec_drv_param = p_tgec_drv_param;
+
+ fman_tgec_defconfig(p_tgec_drv_param);
+
+ p_tgec->p_mem_map = (struct tgec_regs __iomem *)UINT_TO_PTR(base_addr);
+ p_tgec->p_mii_mem_map = (struct tgec_mii_access_mem_map_t *)
+ UINT_TO_PTR(base_addr + TGEC_TO_MII_OFFSET);
+ p_tgec->addr = ENET_ADDR_TO_UINT64(p_fm_mac_param->addr);
+ p_tgec->enet_mode = p_fm_mac_param->enet_mode;
+ p_tgec->mac_id = p_fm_mac_param->mac_id;
+ p_tgec->exceptions = DEFAULT_exceptions;
+ p_tgec->f_exception = p_fm_mac_param->f_exception;
+ p_tgec->f_event = p_fm_mac_param->f_event;
+ p_tgec->h_app = p_fm_mac_param->h_app;
+
+ return p_tgec;
+}
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec.h b/drivers/net/ethernet/freescale/fman/mac/tgec.h
new file mode 100644
index 0000000..f839250
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec.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.
+ */
+
+/* TGEC MAC ... */
+#ifndef __TGEC_H
+#define __TGEC_H
+
+#include "service.h"
+#include "enet_ext.h"
+
+#include "tgec_mii_acc.h"
+#include "fm_mac.h"
+
+#define DEFAULT_exceptions\
+ ((uint32_t)(TGEC_IMASK_MDIO_SCAN_EVENT |\
+ TGEC_IMASK_REM_FAULT |\
+ TGEC_IMASK_LOC_FAULT |\
+ TGEC_IMASK_TX_ECC_ER |\
+ TGEC_IMASK_TX_FIFO_UNFL |\
+ TGEC_IMASK_TX_FIFO_OVFL |\
+ TGEC_IMASK_TX_ER |\
+ TGEC_IMASK_RX_FIFO_OVFL |\
+ TGEC_IMASK_RX_ECC_ER |\
+ TGEC_IMASK_RX_JAB_FRM |\
+ TGEC_IMASK_RX_OVRSZ_FRM |\
+ TGEC_IMASK_RX_RUNT_FRM |\
+ TGEC_IMASK_RX_FRAG_FRM |\
+ TGEC_IMASK_RX_CRC_ER |\
+ TGEC_IMASK_RX_ALIGN_ER))
+
+#define MAX_PACKET_ALIGNMENT 31
+#define MAX_INTER_PACKET_GAP 0x7f
+#define MAX_INTER_PALTERNATE_BEB 0x0f
+#define MAX_RETRANSMISSION 0x0f
+#define MAX_COLLISION_WINDOW 0x03ff
+
+/* number of pattern match registers (entries) */
+#define TGEC_NUM_OF_PADDRS 1
+
+/* Group address bit indication */
+#define GROUP_ADDRESS 0x0000010000000000LL
+
+#define HASH_TABLE_SIZE 512 /* Hash table size (= 32 bits*8 regs)*/
+
+/* Offset from the MEM map to the MDIO mem map */
+#define TGEC_TO_MII_OFFSET 0x1030
+
+struct tgec_t {
+ /* Upper Mac control block */
+ struct fm_mac_ctrl_drv_t fm_mac_ctrl_drv;
+ /* Handle to the upper layer application */
+ void *h_app;
+ /* pointer to 10G memory mapped registers. */
+ struct tgec_regs __iomem *p_mem_map;
+ /* pointer to MII memory mapped registers. */
+ struct tgec_mii_access_mem_map_t *p_mii_mem_map;
+ /* MAC address of device; */
+ uint64_t addr;
+ /* Ethernet physical interface */
+ enum e_enet_mode enet_mode;
+ fm_mac_exception_cb *f_exception;
+ fm_mac_exception_cb *f_event;
+ /* Whether a particular individual address recognition
+ * register is being used
+ */
+ bool ind_addr_reg_used[TGEC_NUM_OF_PADDRS];
+ /* MAC address for particular individual address
+ * recognition register
+ */
+ uint64_t paddr[TGEC_NUM_OF_PADDRS];
+ /* Number of individual addresses in registers for this station. */
+ uint8_t num_of_ind_addr_in_regs;
+ /* pointer to driver's global address hash table */
+ struct eth_hash_t *p_multicast_addr_hash;
+ /* pointer to driver's individual address hash table */
+ struct eth_hash_t *p_unicast_addr_hash;
+ bool debug_mode;
+ uint8_t mac_id;
+ uint32_t exceptions;
+ struct tgec_cfg *p_tgec_drv_param;
+};
+
+#endif /* __TGEC_H */
diff --git a/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h b/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
new file mode 100644
index 0000000..4ea9b35
--- /dev/null
+++ b/drivers/net/ethernet/freescale/fman/mac/tgec_mii_acc.h
@@ -0,0 +1,66 @@
+/*
+ * 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 __TGEC_MII_ACC_H
+#define __TGEC_MII_ACC_H
+
+#include "service.h"
+
+/* MII Management Command Register */
+#define MIIMCOM_READ_POST_INCREMENT 0x00004000
+#define MIIMCOM_READ_CYCLE 0x00008000
+#define MIIMCOM_SCAN_CYCLE 0x00000800
+#define MIIMCOM_PREAMBLE_DISABLE 0x00000400
+
+#define MIIMCOM_MDIO_HOLD_1_REG_CLK 0
+#define MIIMCOM_MDIO_HOLD_2_REG_CLK 1
+#define MIIMCOM_MDIO_HOLD_3_REG_CLK 2
+#define MIIMCOM_MDIO_HOLD_4_REG_CLK 3
+
+#define MIIMCOM_DIV_MASK 0x0000ff00
+#define MIIMCOM_DIV_SHIFT 8
+
+/* MII Management Indicator Register */
+#define MIIMIND_BUSY 0x00000001
+#define MIIMIND_READ_ERROR 0x00000002
+
+#define MIIDATA_BUSY 0x80000000
+
+/* MII Configuration Control Memory Map Registers */
+struct tgec_mii_access_mem_map_t {
+ uint32_t mdio_cfg_status; /* 0x030 */
+ uint32_t mdio_command; /* 0x034 */
+ uint32_t mdio_data; /* 0x038 */
+ uint32_t mdio_regaddr; /* 0x03c */
+} __attribute__((__packed__));
+
+#endif /* __TGEC_MII_ACC_H */
--
1.7.11.7
^ permalink raw reply related [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-05-07 13:06 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-04-29 9:28 [RFC,v3,09/12] fsl/fman: Add FMan MAC support Igal.Liberman
-- strict thread matches above, loose matches on Subject: below --
2015-05-07 13:05 [RFC,v3 01/12] fsl/fman: Add the FMan FLIB headers Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 02/12] fsl/fman: Add the FMan FLIB Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 03/12] fsl/fman: Add the FMan port FLIB headers Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 04/12] fsl/fman: Add the FMan port FLIB Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 05/12] fsl/fman: Add the FMan MAC FLIB headers Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 06/12] fsl/fman: Add the FMan MAC FLIB Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 07/12] fsl/fman: Add FMan MURAM support Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 08/12] fsl/fman: Add Frame Manager support Madalin Bucur
2015-05-07 13:05 ` [RFC,v3 09/12] fsl/fman: Add FMan MAC support Madalin Bucur
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).