fm/mEMAC: add mEMAC frame work
authorRoy Zang <tie-fei.zang@freescale.com>
Mon, 8 Oct 2012 07:44:21 +0000 (07:44 +0000)
committerAndy Fleming <afleming@freescale.com>
Mon, 22 Oct 2012 19:31:25 +0000 (14:31 -0500)
The multirate ethernet media access controller (mEMAC) interfaces to
10Gbps and below Ethernet/IEEE 802.3 networks via either RGMII/RMII
interfaces or XAUI/XFI/SGMII/QSGMII using the high-speed SerDes interface.

Signed-off-by: Sandeep Singh <Sandeep@freescale.com>
Signed-off-by: Poonam Aggrwal <poonam.aggrwal@freescale.com>
Signed-off-by: Roy Zang <tie-fei.zang@freescale.com>
Signed-off-by: Andy Fleming <afleming@freescale.com>
arch/powerpc/include/asm/config_mpc85xx.h
arch/powerpc/include/asm/fsl_fman.h
arch/powerpc/include/asm/fsl_memac.h [new file with mode: 0644]
drivers/net/fm/Makefile
drivers/net/fm/eth.c
drivers/net/fm/memac.c [new file with mode: 0644]
drivers/net/fm/memac_phy.c [new file with mode: 0644]
include/fm_eth.h
include/fsl_mdio.h

index 5e1d2e90f75d55c9d9183191096fc32cb75000bf..c63f9e500aa3f34fc21d5f9c76be1bda61fe34ee 100644 (file)
 #define CONFIG_SYS_NUM_FM2_10GEC       2
 #define CONFIG_NUM_DDR_CONTROLLERS     3
 #define CONFIG_SYS_FSL_DDR_VER         FSL_DDR_VER_4_7
+#define CONFIG_SYS_FMAN_V3
 #define CONFIG_SYS_FM_MURAM_SIZE       0x60000
 #define CONFIG_SYS_FSL_TBCLK_DIV       16
 #define CONFIG_SYS_FSL_PCIE_COMPAT     "fsl,qoriq-pcie-v3.0"
 #define CONFIG_SYS_NUM_FM1_10GEC       2
 #define CONFIG_NUM_DDR_CONTROLLERS     1
 #define CONFIG_SYS_FSL_DDR_VER         FSL_DDR_VER_4_7
+#define CONFIG_SYS_FMAN_V3
 #define CONFIG_SYS_FM_MURAM_SIZE       0x60000
 #define CONFIG_SYS_FSL_TBCLK_DIV       16
 #define CONFIG_SYS_FSL_PCIE_COMPAT     "fsl,qoriq-pcie-v2.4"
index 2c0c9bc2f2cc79e85a6b98bf6c2fb04850a8ec1a..299daca132d8826cf7fa786c89530729f99062d9 100644 (file)
@@ -423,6 +423,14 @@ typedef struct fm_10gec_mdio {
        u8      res[4*1024];
 } fm_10gec_mdio_t;
 
+typedef struct fm_memac {
+       u8      res[4*1024];
+} fm_memac_t;
+
+typedef struct fm_memac_mdio {
+       u8      res[4*1024];
+} fm_memac_mdio_t;
+
 typedef struct fm_1588 {
        u8      res[4*1024];
 } fm_1588_t;
@@ -446,6 +454,14 @@ typedef struct ccsr_fman {
        u8                      res1[8*1024];
        fm_soft_parser_t        fm_soft_parser;
        u8                      res2[96*1024];
+#ifdef CONFIG_SYS_FMAN_V3
+       struct {
+               fm_memac_t              fm_memac;
+               fm_memac_mdio_t         fm_memac_mdio;
+       } memac[10];
+       u8                      res4[32*1024];
+       fm_memac_mdio_t         fm_dedicated_mdio[2];
+#else
        struct {
                fm_dtsec_t      fm_dtesc;
                fm_mdio_t       fm_mdio;
@@ -455,6 +471,7 @@ typedef struct ccsr_fman {
                fm_10gec_mdio_t         fm_10gec_mdio;
        } mac_10g[1];
        u8                      res4[48*1024];
+#endif
        fm_1588_t               fm_1588;
        u8                      res5[4*1024];
 } ccsr_fman_t;
diff --git a/arch/powerpc/include/asm/fsl_memac.h b/arch/powerpc/include/asm/fsl_memac.h
new file mode 100644 (file)
index 0000000..d6b60e6
--- /dev/null
@@ -0,0 +1,271 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *     Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __MEMAC_H__
+#define __MEMAC_H__
+
+#include <phy.h>
+
+struct memac {
+       /* memac general control and status registers */
+       u32     res_0[2];
+       u32     command_config; /* Control and configuration register */
+       u32     mac_addr_0;     /* Lower 32 bits of 48-bit MAC address */
+       u32     mac_addr_1;     /* Upper 16 bits of 48-bit MAC address */
+       u32     maxfrm;         /* Maximum frame length register */
+       u32     res_18[5];
+       u32     hashtable_ctrl; /* Hash table control register */
+       u32     res_30[4];
+       u32     ievent;         /* Interrupt event register */
+       u32     tx_ipg_length;  /* Transmitter inter-packet-gap register */
+       u32     res_48;
+       u32     imask;          /* interrupt mask register */
+       u32     res_50;
+       u32     cl_pause_quanta[4]; /* CL01-CL67 pause quanta register */
+       u32     cl_pause_thresh[4]; /* CL01-CL67 pause thresh register */
+       u32     rx_pause_status;        /* Receive pause status register */
+       u32     res_78[2];
+       u32     mac_addr[14];   /* MAC address */
+       u32     lpwake_timer;   /* EEE low power wakeup timer register */
+       u32     sleep_timer;    /* Transmit EEE Low Power Timer register */
+       u32     res_c0[8];
+       u32     statn_config;   /* Statistics configuration register */
+       u32     res_e4[7];
+
+       /* memac statistics counter registers */
+       u32     rx_eoct_l;      /* Rx ethernet octests lower */
+       u32     rx_eoct_u;      /* Rx ethernet octests upper */
+       u32     rx_oct_l;       /* Rx octests lower */
+       u32     rx_oct_u;       /* Rx octests upper */
+       u32     rx_align_err_l; /* Rx alignment error lower */
+       u32     rx_align_err_u; /* Rx alignment error upper */
+       u32     rx_pause_frame_l; /* Rx valid pause frame upper */
+       u32     rx_pause_frame_u; /* Rx valid pause frame upper */
+       u32     rx_frame_l;     /* Rx frame counter lower */
+       u32     rx_frame_u;     /* Rx frame counter upper */
+       u32     rx_frame_crc_err_l; /* Rx frame check sequence error lower */
+       u32     rx_frame_crc_err_u; /* Rx frame check sequence error upper */
+       u32     rx_vlan_l;      /* Rx VLAN frame lower */
+       u32     rx_vlan_u;      /* Rx VLAN frame upper */
+       u32     rx_err_l;       /* Rx frame error lower */
+       u32     rx_err_u;       /* Rx frame error upper */
+       u32     rx_uni_l;       /* Rx unicast frame lower */
+       u32     rx_uni_u;       /* Rx unicast frame upper */
+       u32     rx_multi_l;     /* Rx multicast frame lower */
+       u32     rx_multi_u;     /* Rx multicast frame upper */
+       u32     rx_brd_l;       /* Rx broadcast frame lower */
+       u32     rx_brd_u;       /* Rx broadcast frame upper */
+       u32     rx_drop_l;      /* Rx dropped packets lower */
+       u32     rx_drop_u;      /* Rx dropped packets upper */
+       u32     rx_pkt_l;       /* Rx packets lower */
+       u32     rx_pkt_u;       /* Rx packets upper */
+       u32     rx_undsz_l;     /* Rx undersized packet lower */
+       u32     rx_undsz_u;     /* Rx undersized packet upper */
+       u32     rx_64_l;        /* Rx 64 oct packet lower */
+       u32     rx_64_u;        /* Rx 64 oct packet upper */
+       u32     rx_127_l;       /* Rx 65 to 127 oct packet lower */
+       u32     rx_127_u;       /* Rx 65 to 127 oct packet upper */
+       u32     rx_255_l;       /* Rx 128 to 255 oct packet lower */
+       u32     rx_255_u;       /* Rx 128 to 255 oct packet upper */
+       u32     rx_511_l;       /* Rx 256 to 511 oct packet lower */
+       u32     rx_511_u;       /* Rx 256 to 511 oct packet upper */
+       u32     rx_1023_l;      /* Rx 512 to 1023 oct packet lower */
+       u32     rx_1023_u;      /* Rx 512 to 1023 oct packet upper */
+       u32     rx_1518_l;      /* Rx 1024 to 1518 oct packet lower */
+       u32     rx_1518_u;      /* Rx 1024 to 1518 oct packet upper */
+       u32     rx_1519_l;      /* Rx 1519 to max oct packet lower */
+       u32     rx_1519_u;      /* Rx 1519 to max oct packet upper */
+       u32     rx_oversz_l;    /* Rx oversized packet lower */
+       u32     rx_oversz_u;    /* Rx oversized packet upper */
+       u32     rx_jabber_l;    /* Rx Jabber packet lower */
+       u32     rx_jabber_u;    /* Rx Jabber packet upper */
+       u32     rx_frag_l;      /* Rx Fragment packet lower */
+       u32     rx_frag_u;      /* Rx Fragment packet upper */
+       u32     rx_cnp_l;       /* Rx control packet lower */
+       u32     rx_cnp_u;       /* Rx control packet upper */
+       u32     rx_drntp_l;     /* Rx dripped not truncated packet lower */
+       u32     rx_drntp_u;     /* Rx dripped not truncated packet upper */
+       u32     res_1d0[0xc];
+
+       u32     tx_eoct_l;      /* Tx ethernet octests lower */
+       u32     tx_eoct_u;      /* Tx ethernet octests upper */
+       u32     tx_oct_l;       /* Tx octests lower */
+       u32     tx_oct_u;       /* Tx octests upper */
+       u32     res_210[0x2];
+       u32     tx_pause_frame_l; /* Tx valid pause frame lower */
+       u32     tx_pause_frame_u; /* Tx valid pause frame upper */
+       u32     tx_frame_l;     /* Tx frame counter lower */
+       u32     tx_frame_u;     /* Tx frame counter upper */
+       u32     tx_frame_crc_err_l; /* Tx frame check sequence error lower */
+       u32     tx_frame_crc_err_u; /* Tx frame check sequence error upper */
+       u32     tx_vlan_l;      /* Tx VLAN frame lower */
+       u32     tx_vlan_u;      /* Tx VLAN frame upper */
+       u32     tx_frame_err_l; /* Tx frame error lower */
+       u32     tx_frame_err_u; /* Tx frame error upper */
+       u32     tx_uni_l;       /* Tx unicast frame lower */
+       u32     tx_uni_u;       /* Tx unicast frame upper */
+       u32     tx_multi_l;     /* Tx multicast frame lower */
+       u32     tx_multi_u;     /* Tx multicast frame upper */
+       u32     tx_brd_l;       /* Tx broadcast frame lower */
+       u32     tx_brd_u;       /* Tx broadcast frame upper */
+       u32     res_258[0x2];
+       u32     tx_pkt_l;       /* Tx packets lower */
+       u32     tx_pkt_u;       /* Tx packets upper */
+       u32     tx_undsz_l;     /* Tx undersized packet lower */
+       u32     tx_undsz_u;     /* Tx undersized packet upper */
+       u32     tx_64_l;        /* Tx 64 oct packet lower */
+       u32     tx_64_u;        /* Tx 64 oct packet upper */
+       u32     tx_127_l;       /* Tx 65 to 127 oct packet lower */
+       u32     tx_127_u;       /* Tx 65 to 127 oct packet upper */
+       u32     tx_255_l;       /* Tx 128 to 255 oct packet lower */
+       u32     tx_255_u;       /* Tx 128 to 255 oct packet upper */
+       u32     tx_511_l;       /* Tx 256 to 511 oct packet lower */
+       u32     tx_511_u;       /* Tx 256 to 511 oct packet upper */
+       u32     tx_1023_l;      /* Tx 512 to 1023 oct packet lower */
+       u32     tx_1023_u;      /* Tx 512 to 1023 oct packet upper */
+       u32     tx_1518_l;      /* Tx 1024 to 1518 oct packet lower */
+       u32     tx_1518_u;      /* Tx 1024 to 1518 oct packet upper */
+       u32     tx_1519_l;      /* Tx 1519 to max oct packet lower */
+       u32     tx_1519_u;      /* Tx 1519 to max oct packet upper */
+       u32     res_2a8[0x6];
+       u32     tx_cnp_l;       /* Tx control packet lower */
+       u32     tx_cnp_u;       /* Tx control packet upper */
+       u32     res_2c8[0xe];
+
+       /* Line interface control register */
+       u32 if_mode;            /* interface mode control */
+       u32 if_status;          /* interface status */
+       u32 res_308[0xe];
+
+       /* HiGig/2 Register */
+       u32 hg_config;  /* HiGig2 control and configuration */
+       u32 res_344[0x3];
+       u32 hg_pause_quanta;    /* HiGig2 pause quanta */
+       u32 res_354[0x3];
+       u32 hg_pause_thresh;    /* HiGig2 pause quanta threshold */
+       u32 res_364[0x3];
+       u32 hgrx_pause_status;  /* HiGig2 rx pause quanta status */
+       u32 hg_fifos_status;    /* HiGig2 fifos status */
+       u32 rhm;        /* Rx HiGig2 message counter register */
+       u32 thm;/* Tx HiGig2 message counter register */
+       u32 res_380[0x320];
+};
+
+/* COMMAND_CONFIG - command and configuration register */
+#define MEMAC_CMD_CFG_RX_EN            0x00000002 /* MAC Rx path enable */
+#define MEMAC_CMD_CFG_TX_EN            0x00000001 /* MAC Tx path enable */
+#define MEMAC_CMD_CFG_RXTX_EN  (MEMAC_CMD_CFG_RX_EN | MEMAC_CMD_CFG_TX_EN)
+
+/* HASHTABLE_CTRL - Hashtable control register */
+#define HASHTABLE_CTRL_MCAST_EN        0x00000200 /* enable mulitcast Rx hash */
+#define HASHTABLE_CTRL_ADDR_MASK       0x000001ff
+
+/* TX_IPG_LENGTH - Transmit inter-packet gap length register */
+#define TX_IPG_LENGTH_IPG_LEN_MASK     0x000003ff
+
+/* IMASK - interrupt mask register */
+#define IMASK_MDIO_SCAN_EVENT  0x00010000 /* MDIO scan event mask */
+#define IMASK_MDIO_CMD_CMPL    0x00008000 /* MDIO cmd completion mask */
+#define IMASK_REM_FAULT                0x00004000 /* remote fault mask */
+#define IMASK_LOC_FAULT                0x00002000 /* local fault mask */
+#define IMASK_TX_ECC_ER                0x00001000 /* Tx frame ECC error mask */
+#define IMASK_TX_FIFO_UNFL     0x00000800 /* Tx FIFO underflow mask */
+#define IMASK_TX_ER            0x00000200 /* Tx frame error mask */
+#define IMASK_RX_FIFO_OVFL     0x00000100 /* Rx FIFO overflow mask */
+#define IMASK_RX_ECC_ER                0x00000080 /* Rx frame ECC error mask */
+#define IMASK_RX_JAB_FRM       0x00000040 /* Rx jabber frame mask */
+#define IMASK_RX_OVRSZ_FRM     0x00000020 /* Rx oversized frame mask */
+#define IMASK_RX_RUNT_FRM      0x00000010 /* Rx runt frame mask */
+#define IMASK_RX_FRAG_FRM      0x00000008 /* Rx fragment frame mask */
+#define IMASK_RX_LEN_ER                0x00000004 /* Rx payload length error mask */
+#define IMASK_RX_CRC_ER                0x00000002 /* Rx CRC error mask */
+#define IMASK_RX_ALIGN_ER      0x00000001 /* Rx alignment error mask */
+
+#define IMASK_MASK_ALL         0x00000000
+
+/* IEVENT - interrupt event register */
+#define IEVENT_MDIO_SCAN_EVENT 0x00010000 /* MDIO scan event */
+#define IEVENT_MDIO_CMD_CMPL   0x00008000 /* MDIO cmd completion */
+#define IEVENT_REM_FAULT       0x00004000 /* remote fault */
+#define IEVENT_LOC_FAULT       0x00002000 /* local fault */
+#define IEVENT_TX_ECC_ER       0x00001000 /* Tx frame ECC error */
+#define IEVENT_TX_FIFO_UNFL    0x00000800 /* Tx FIFO underflow */
+#define IEVENT_TX_ER           0x00000200 /* Tx frame error */
+#define IEVENT_RX_FIFO_OVFL    0x00000100 /* Rx FIFO overflow */
+#define IEVENT_RX_ECC_ER       0x00000080 /* Rx frame ECC error */
+#define IEVENT_RX_JAB_FRM      0x00000040 /* Rx jabber frame */
+#define IEVENT_RX_OVRSZ_FRM    0x00000020 /* Rx oversized frame */
+#define IEVENT_RX_RUNT_FRM     0x00000010 /* Rx runt frame */
+#define IEVENT_RX_FRAG_FRM     0x00000008 /* Rx fragment frame */
+#define IEVENT_RX_LEN_ER       0x00000004 /* Rx payload length error */
+#define IEVENT_RX_CRC_ER       0x00000002 /* Rx CRC error */
+#define IEVENT_RX_ALIGN_ER     0x00000001 /* Rx alignment error */
+
+#define IEVENT_CLEAR_ALL       0xffffffff
+
+/* IF_MODE - Interface Mode Register */
+#define IF_MODE_EN_AUTO        0x00008000 /* 1 - Enable automatic speed selection */
+#define IF_MODE_XGMII  0x00000000 /* 00- XGMII(10) interface mode */
+#define IF_MODE_GMII           0x00000002 /* 10- GMII interface mode */
+#define IF_MODE_MASK   0x00000003 /* mask for mode interface mode */
+#define IF_MODE_RG             0x00000004 /* 1- RGMII */
+#define IF_MODE_RM             0x00000008 /* 1- RGMII */
+
+#define IF_DEFAULT     (IF_GMII)
+
+/* 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_IF_MODE_AN        0x0002
+#define PHY_SGMII_IF_MODE_SGMII     0x0001
+
+struct memac_mdio_controller {
+       u32     res0[0xc];
+       u32     mdio_stat;      /* MDIO configuration and status */
+       u32     mdio_ctl;       /* MDIO control */
+       u32     mdio_data;      /* MDIO data */
+       u32     mdio_addr;      /* MDIO address */
+};
+
+#define MDIO_STAT_CLKDIV(x)    (((x>>1) & 0xff) << 8)
+#define MDIO_STAT_BSY          (1 << 0)
+#define MDIO_STAT_RD_ER                (1 << 1)
+#define MDIO_STAT_PRE          (1 << 5)
+#define MDIO_STAT_ENC          (1 << 6)
+#define MDIO_STAT_HOLD_15_CLK  (7 << 2)
+
+#define MDIO_CTL_DEV_ADDR(x)   (x & 0x1f)
+#define MDIO_CTL_PORT_ADDR(x)  ((x & 0x1f) << 5)
+#define MDIO_CTL_PRE_DIS       (1 << 10)
+#define MDIO_CTL_SCAN_EN       (1 << 11)
+#define MDIO_CTL_POST_INC      (1 << 14)
+#define MDIO_CTL_READ          (1 << 15)
+
+#define MDIO_DATA(x)           (x & 0xffff)
+#define MDIO_DATA_BSY          (1 << 31)
+
+struct fsl_enet_mac;
+
+void init_memac(struct fsl_enet_mac *mac, void *base, void *phyregs,
+               int max_rx_len);
+
+#endif
index 4642c54ecea78b29eb71690c68e0bd1def6e5b3d..7a1fcdd81fbe4009dad08f373feb27672e6542f6 100644 (file)
@@ -32,6 +32,10 @@ COBJS-y += init.o
 COBJS-y += tgec.o
 COBJS-y += tgec_phy.o
 
+# Soc have FMAN v3 with mEMAC
+COBJS-$(CONFIG_SYS_FMAN_V3) += memac_phy.o
+COBJS-$(CONFIG_SYS_FMAN_V3) += memac.o
+
 # SoC specific SERDES support
 COBJS-$(CONFIG_P1017)  += p1023.o
 COBJS-$(CONFIG_P1023)  += p1023.o
index 2b616adb6e545803307ed53104fd2f8966cf919a..ed23fdd4ac5c1898bf4025444ef1d5fb39e0060b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
  *     Dave Liu <daveliu@freescale.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -28,6 +28,7 @@
 #include <phy.h>
 #include <asm/fsl_dtsec.h>
 #include <asm/fsl_tgec.h>
+#include <asm/fsl_memac.h>
 
 #include "fm.h"
 
@@ -47,6 +48,28 @@ static int num_controllers;
 /* Configure the TBI for SGMII operation */
 void dtsec_configure_serdes(struct fm_eth *priv)
 {
+#ifdef CONFIG_SYS_FMAN_V3
+       u32 value;
+       struct mii_dev bus;
+       bus.priv = priv->mac->phyregs;
+
+       /* SGMII IF mode + AN enable */
+       value = PHY_SGMII_IF_MODE_AN | PHY_SGMII_IF_MODE_SGMII;
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
+
+       /* Dev ability according to SGMII specification */
+       value = PHY_SGMII_DEV_ABILITY_SGMII;
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
+
+       /* Adjust link timer for SGMII  -
+       1.6 ms in units of 8 ns = 2 * 10^5 = 0x30d40 */
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x3);
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xd40);
+
+       /* Restart AN */
+       value = PHY_SGMII_CR_DEF_VAL | PHY_SGMII_CR_RESET_AN;
+       memac_mdio_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
+#else
        struct dtsec *regs = priv->mac->base;
        struct tsec_mii_mng *phyregs = priv->mac->phyregs;
 
@@ -60,15 +83,18 @@ void dtsec_configure_serdes(struct fm_eth *priv)
                        TBIANA_SGMII_ACK);
        tsec_local_mdio_write(phyregs, in_be32(&regs->tbipa), 0,
                        TBI_CR, TBICR_SETTINGS);
+#endif
 }
 
 static void dtsec_init_phy(struct eth_device *dev)
 {
        struct fm_eth *fm_eth = dev->priv;
-       struct dtsec *regs = (struct dtsec *)fm_eth->mac->base;
 
+#ifndef CONFIG_SYS_FMAN_V3
+       struct dtsec *regs = (struct dtsec *)fm_eth->mac->base;
        /* Assign a Physical address to the TBI */
        out_be32(&regs->tbipa, CONFIG_SYS_TBIPA_VALUE);
+#endif
 
        if (fm_eth->enet_if == PHY_INTERFACE_MODE_SGMII)
                dtsec_configure_serdes(fm_eth);
@@ -541,6 +567,10 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
 
        num = fm_eth->num;
 
+#ifdef CONFIG_SYS_FMAN_V3
+       base = &reg->memac[num].fm_memac;
+       phyregs = &reg->memac[num].fm_memac_mdio;
+#else
        /* Get the mac registers base address */
        if (fm_eth->type == FM_ETH_1G_E) {
                base = &reg->mac_1g[num].fm_dtesc;
@@ -549,6 +579,7 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
                base = &reg->mac_10g[num].fm_10gec;
                phyregs = &reg->mac_10g[num].fm_10gec_mdio;
        }
+#endif
 
        /* alloc mac controller */
        mac = malloc(sizeof(struct fsl_enet_mac));
@@ -559,10 +590,14 @@ static int fm_eth_init_mac(struct fm_eth *fm_eth, struct ccsr_fman *reg)
        /* save the mac to fm_eth struct */
        fm_eth->mac = mac;
 
+#ifdef CONFIG_SYS_FMAN_V3
+       init_memac(mac, base, phyregs, MAX_RXBUF_LEN);
+#else
        if (fm_eth->type == FM_ETH_1G_E)
                init_dtsec(mac, base, phyregs, MAX_RXBUF_LEN);
        else
                init_tgec(mac, base, phyregs, MAX_RXBUF_LEN);
+#endif
 
        return 1;
 }
diff --git a/drivers/net/fm/memac.c b/drivers/net/fm/memac.c
new file mode 100644 (file)
index 0000000..32c7054
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *     Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* MAXFRM - maximum frame length */
+#define MAXFRM_MASK    0x0000ffff
+
+#include <common.h>
+#include <phy.h>
+#include <asm/types.h>
+#include <asm/io.h>
+#include <asm/fsl_enet.h>
+#include <asm/fsl_memac.h>
+
+#include "fm.h"
+
+static void memac_init_mac(struct fsl_enet_mac *mac)
+{
+       struct memac *regs = mac->base;
+
+       /* mask all interrupt */
+       out_be32(&regs->imask, IMASK_MASK_ALL);
+
+       /* clear all events */
+       out_be32(&regs->ievent, IEVENT_CLEAR_ALL);
+
+       /* set the max receive length */
+       out_be32(&regs->maxfrm, mac->max_rx_len & MAXFRM_MASK);
+
+       /* multicast frame reception for the hash entry disable */
+       out_be32(&regs->hashtable_ctrl, 0);
+}
+
+static void memac_enable_mac(struct fsl_enet_mac *mac)
+{
+       struct memac *regs = mac->base;
+
+       setbits_be32(&regs->command_config, MEMAC_CMD_CFG_RXTX_EN);
+}
+
+static void memac_disable_mac(struct fsl_enet_mac *mac)
+{
+       struct memac *regs = mac->base;
+
+       clrbits_be32(&regs->command_config, MEMAC_CMD_CFG_RXTX_EN);
+}
+
+static void memac_set_mac_addr(struct fsl_enet_mac *mac, u8 *mac_addr)
+{
+       struct memac *regs = mac->base;
+       u32 mac_addr0, mac_addr1;
+
+       /*
+        * if a station address of 0x12345678ABCD, perform a write to
+        * MAC_ADDR0 of 0x78563412, MAC_ADDR1 of 0x0000CDAB
+        */
+       mac_addr0 = (mac_addr[3] << 24) | (mac_addr[2] << 16) | \
+                       (mac_addr[1] << 8)  | (mac_addr[0]);
+       out_be32(&regs->mac_addr_0, mac_addr0);
+
+       mac_addr1 = ((mac_addr[5] << 8) | mac_addr[4]) & 0x0000ffff;
+       out_be32(&regs->mac_addr_1, mac_addr1);
+}
+
+static void memac_set_interface_mode(struct fsl_enet_mac *mac,
+                                       phy_interface_t type, int speed)
+{
+       /* Roy need more work here */
+
+       struct memac *regs = mac->base;
+       u32 if_mode, if_status;
+
+       /* clear all bits relative with interface mode */
+       if_mode = in_be32(&regs->if_mode);
+       if_status = in_be32(&regs->if_status);
+
+       /* set interface mode */
+       switch (type) {
+       case PHY_INTERFACE_MODE_GMII:
+               if_mode &= ~IF_MODE_MASK;
+               if_mode |= IF_MODE_GMII;
+               break;
+       case PHY_INTERFACE_MODE_RGMII:
+               if_mode |= (IF_MODE_GMII | IF_MODE_RG);
+               break;
+       case PHY_INTERFACE_MODE_RMII:
+               if_mode |= (IF_MODE_GMII | IF_MODE_RM);
+               break;
+       case PHY_INTERFACE_MODE_SGMII:
+               if_mode &= ~IF_MODE_MASK;
+               if_mode |= (IF_MODE_GMII);
+               break;
+       default:
+               break;
+       }
+       /* Enable automatic speed selection */
+       if_mode |= IF_MODE_EN_AUTO;
+
+       debug(" %s, if_mode = %x\n", __func__,  if_mode);
+       debug(" %s, if_status = %x\n", __func__,  if_status);
+       out_be32(&regs->if_mode, if_mode);
+       return;
+}
+
+void init_memac(struct fsl_enet_mac *mac, void *base,
+               void *phyregs, int max_rx_len)
+{
+       mac->base = base;
+       mac->phyregs = phyregs;
+       mac->max_rx_len = max_rx_len;
+       mac->init_mac = memac_init_mac;
+       mac->enable_mac = memac_enable_mac;
+       mac->disable_mac = memac_disable_mac;
+       mac->set_mac_addr = memac_set_mac_addr;
+       mac->set_if_mode = memac_set_interface_mode;
+}
diff --git a/drivers/net/fm/memac_phy.c b/drivers/net/fm/memac_phy.c
new file mode 100644 (file)
index 0000000..ea6118b
--- /dev/null
@@ -0,0 +1,150 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ *     Andy Fleming <afleming@freescale.com>
+ *     Roy Zang <tie-fei.zang@freescale.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ * Some part is taken from tsec.c
+ */
+#include <common.h>
+#include <miiphy.h>
+#include <phy.h>
+#include <asm/io.h>
+#include <asm/fsl_memac.h>
+#include <fm_eth.h>
+
+/*
+ * Write value to the PHY for this device to the register at regnum, waiting
+ * until the write is done before it returns.  All PHY configuration has to be
+ * done through the TSEC1 MIIM regs
+ */
+int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
+                       int regnum, u16 value)
+{
+       u32 mdio_ctl;
+       struct memac_mdio_controller *regs = bus->priv;
+       u32 c45 = 1; /* Default to 10G interface */
+
+       if (dev_addr == MDIO_DEVAD_NONE) {
+               c45 = 0; /* clause 22 */
+               dev_addr = regnum & 0x1f;
+               clrbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+       } else {
+               setbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+               setbits_be32(&regs->mdio_stat, MDIO_STAT_HOLD_15_CLK);
+       }
+
+       /* Wait till the bus is free */
+       while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+               ;
+
+       /* Set the port and dev addr */
+       mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
+       out_be32(&regs->mdio_ctl, mdio_ctl);
+
+       /* Set the register address */
+       if (c45)
+               out_be32(&regs->mdio_addr, regnum & 0xffff);
+
+       /* Wait till the bus is free */
+       while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+               ;
+
+       /* Write the value to the register */
+       out_be32(&regs->mdio_data, MDIO_DATA(value));
+
+       /* Wait till the MDIO write is complete */
+       while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+               ;
+
+       return 0;
+}
+
+/*
+ * Reads from register regnum in the PHY for device dev, returning the value.
+ * Clears miimcom first.  All PHY configuration has to be done through the
+ * TSEC1 MIIM regs
+ */
+int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
+                       int regnum)
+{
+       u32 mdio_ctl;
+       struct memac_mdio_controller *regs = bus->priv;
+       u32 c45 = 1;
+
+       if (dev_addr == MDIO_DEVAD_NONE) {
+               c45 = 0; /* clause 22 */
+               dev_addr = regnum & 0x1f;
+               clrbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+       } else {
+               setbits_be32(&regs->mdio_stat, MDIO_STAT_ENC);
+               setbits_be32(&regs->mdio_stat, MDIO_STAT_HOLD_15_CLK);
+       }
+
+       /* Wait till the bus is free */
+       while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+               ;
+
+       /* Set the Port and Device Addrs */
+       mdio_ctl = MDIO_CTL_PORT_ADDR(port_addr) | MDIO_CTL_DEV_ADDR(dev_addr);
+       out_be32(&regs->mdio_ctl, mdio_ctl);
+
+       /* Set the register address */
+       if (c45)
+               out_be32(&regs->mdio_addr, regnum & 0xffff);
+
+       /* Wait till the bus is free */
+       while ((in_be32(&regs->mdio_stat)) & MDIO_STAT_BSY)
+               ;
+
+       /* Initiate the read */
+       mdio_ctl |= MDIO_CTL_READ;
+       out_be32(&regs->mdio_ctl, mdio_ctl);
+
+       /* Wait till the MDIO write is complete */
+       while ((in_be32(&regs->mdio_data)) & MDIO_DATA_BSY)
+               ;
+
+       /* Return all Fs if nothing was there */
+       if (in_be32(&regs->mdio_stat) & MDIO_STAT_RD_ER)
+               return 0xffff;
+
+       return in_be32(&regs->mdio_data) & 0xffff;
+}
+
+int memac_mdio_reset(struct mii_dev *bus)
+{
+       return 0;
+}
+
+int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info)
+{
+       struct mii_dev *bus = mdio_alloc();
+
+       if (!bus) {
+               printf("Failed to allocate FM TGEC MDIO bus\n");
+               return -1;
+       }
+
+       bus->read = memac_mdio_read;
+       bus->write = memac_mdio_write;
+       bus->reset = memac_mdio_reset;
+       sprintf(bus->name, info->name);
+
+       bus->priv = info->regs;
+
+       return mdio_register(bus);
+}
index 5d80e4962ed3b7277870a8c88aebef5be50ca7bd..495765b933fa87273d1f81873dd5a93e3cd07d73 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2011 Freescale Semiconductor, Inc.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -53,8 +53,15 @@ enum fm_eth_type {
        FM_ETH_10G_E,
 };
 
+#ifdef CONFIG_SYS_FMAN_V3
+#define CONFIG_SYS_FM1_DTSEC_MDIO_ADDR (CONFIG_SYS_FSL_FM1_ADDR + 0xfc000)
+#define CONFIG_SYS_FM1_TGEC_MDIO_ADDR  (CONFIG_SYS_FSL_FM1_ADDR + 0xfd000)
+#define CONFIG_SYS_FM2_DTSEC_MDIO_ADDR (CONFIG_SYS_FSL_FM2_ADDR + 0xfc000)
+#define CONFIG_SYS_FM2_TGEC_MDIO_ADDR  (CONFIG_SYS_FSL_FM2_ADDR + 0xfd000)
+#else
 #define CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR        (CONFIG_SYS_FSL_FM1_ADDR + 0xe1120)
 #define CONFIG_SYS_FM1_TGEC_MDIO_ADDR  (CONFIG_SYS_FSL_FM1_ADDR + 0xf1000)
+#endif
 
 #define DEFAULT_FM_MDIO_NAME "FSL_MDIO0"
 #define DEFAULT_FM_TGEC_MDIO_NAME "FM_TGEC_MDIO"
@@ -65,6 +72,33 @@ enum fm_eth_type {
        .phy_regs       = (void *)pregs,                                \
        .enet_if        = PHY_INTERFACE_MODE_NONE,                      \
 
+#ifdef CONFIG_SYS_FMAN_V3
+#define FM_DTSEC_INFO_INITIALIZER(idx, n) \
+{                                                                      \
+       FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_DTSEC_MDIO_ADDR)    \
+       .index          = idx,                                          \
+       .num            = n - 1,                                        \
+       .type           = FM_ETH_1G_E,                                  \
+       .port           = FM##idx##_DTSEC##n,                           \
+       .rx_port_id     = RX_PORT_1G_BASE + n - 1,                      \
+       .tx_port_id     = TX_PORT_1G_BASE + n - 1,                      \
+       .compat_offset  = CONFIG_SYS_FSL_FM##idx##_OFFSET +             \
+                               offsetof(struct ccsr_fman, memac[n-1]),\
+}
+
+#define FM_TGEC_INFO_INITIALIZER(idx, n) \
+{                                                                      \
+       FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_TGEC_MDIO_ADDR)     \
+       .index          = idx,                                          \
+       .num            = n - 1,                                        \
+       .type           = FM_ETH_10G_E,                                 \
+       .port           = FM##idx##_10GEC##n,                           \
+       .rx_port_id     = RX_PORT_10G_BASE + n - 1,                     \
+       .tx_port_id     = TX_PORT_10G_BASE + n - 1,                     \
+       .compat_offset  = CONFIG_SYS_FSL_FM##idx##_OFFSET +             \
+                               offsetof(struct ccsr_fman, memac[n-1]),\
+}
+#else
 #define FM_DTSEC_INFO_INITIALIZER(idx, n) \
 {                                                                      \
        FM_ETH_INFO_INITIALIZER(idx, CONFIG_SYS_FM1_DTSEC1_MDIO_ADDR)   \
@@ -90,7 +124,7 @@ enum fm_eth_type {
        .compat_offset  = CONFIG_SYS_FSL_FM##idx##_OFFSET +             \
                                offsetof(struct ccsr_fman, mac_10g[n-1]),\
 }
-
+#endif
 struct fm_eth_info {
        u8 enabled;
        u8 fm;
@@ -112,7 +146,14 @@ struct tgec_mdio_info {
        char *name;
 };
 
+struct memac_mdio_info {
+       struct memac_mdio_controller *regs;
+       char *name;
+};
+
 int fm_tgec_mdio_init(bd_t *bis, struct tgec_mdio_info *info);
+int fm_memac_mdio_init(bd_t *bis, struct memac_mdio_info *info);
+
 int fm_standard_init(bd_t *bis);
 void fman_enet_init(void);
 void fdt_fixup_fman_ethernet(void *fdt);
index ea8b54b56f9e987b7822fbfa88227d939d9b89c5..e24e828cd1d7178ea4e5dd98696ee866ea112454 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright 2009-2010 Freescale Semiconductor, Inc.
+ * Copyright 2009-2012 Freescale Semiconductor, Inc.
  *     Jun-jie Zhang <b18070@freescale.com>
  *     Mingkai Hu <Mingkai.hu@freescale.com>
  *
@@ -51,6 +51,10 @@ int tsec_local_mdio_read(struct tsec_mii_mng *phyregs, int port_addr,
 int tsec_phy_read(struct mii_dev *bus, int addr, int dev_addr, int regnum);
 int tsec_phy_write(struct mii_dev *bus, int addr, int dev_addr, int regnum,
                u16 value);
+int memac_mdio_write(struct mii_dev *bus, int port_addr, int dev_addr,
+               int regnum, u16 value);
+int memac_mdio_read(struct mii_dev *bus, int port_addr, int dev_addr,
+               int regnum);
 
 struct fsl_pq_mdio_info {
        struct tsec_mii_mng *regs;