]> git.sur5r.net Git - u-boot/commitdiff
board: freescale: ls1012aqds: enable network support on ls1012aqds
authorCalvin Johnson <calvin.johnson@nxp.com>
Thu, 8 Mar 2018 10:00:28 +0000 (15:30 +0530)
committerJoe Hershberger <joe.hershberger@ni.com>
Thu, 22 Mar 2018 20:05:29 +0000 (15:05 -0500)
This patch enables ethernet support for ls1012aqds.

Signed-off-by: Calvin Johnson <calvin.johnson@nxp.com>
Signed-off-by: Anjaneyulu Jagarlmudi <anji.jagarlmudi@nxp.com>
Acked-by: Joe Hershberger <joe.hershberger@ni.com>
board/freescale/ls1012aqds/Kconfig
board/freescale/ls1012aqds/Makefile
board/freescale/ls1012aqds/eth.c [new file with mode: 0644]
board/freescale/ls1012aqds/ls1012aqds.c
board/freescale/ls1012aqds/ls1012aqds_pfe.h [new file with mode: 0644]
board/freescale/ls1012aqds/ls1012aqds_qixis.h

index fc9250b253ed43f66987caf3775e351f8dff56fe..c0b12ed78f265387a0724aad2db91665721aaffd 100644 (file)
@@ -12,6 +12,51 @@ config SYS_SOC
 config SYS_CONFIG_NAME
        default "ls1012aqds"
 
+
+if FSL_PFE
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+       def_bool y
+       select PHYLIB
+       imply PHY_VITESSE
+       imply PHY_REALTEK
+       imply PHY_AQUANTIA
+       imply PHYLIB_10G
+
+config PFE_RGMII_RESET_WA
+       def_bool y
+
+config SYS_LS_PFE_FW_ADDR
+       hex "Flash address of PFE firmware"
+       default 0x40a00000
+
+config DDR_PFE_PHYS_BASEADDR
+       hex "PFE DDR physical base address"
+       default 0x03800000
+
+config DDR_PFE_BASEADDR
+       hex "PFE DDR base address"
+       default 0x83800000
+
+config PFE_EMAC1_PHY_ADDR
+       hex "PFE DDR base address"
+       default 0x1e
+
+config PFE_EMAC2_PHY_ADDR
+       hex "PFE DDR base address"
+       default 0x1
+
+config PFE_SGMII_2500_PHY1_ADDR
+       hex "PFE DDR base address"
+       default 0x1
+
+config PFE_SGMII_2500_PHY2_ADDR
+       hex "PFE DDR base address"
+       default 0x2
+
+endif
+
+
 source "board/freescale/common/Kconfig"
 
 endif
index 0b813f9784852603371d951d8bdd38b81e68d3fa..5aba9caf92754e5e03b8a17f9efb353231095acd 100644 (file)
@@ -5,3 +5,4 @@
 #
 
 obj-y += ls1012aqds.o
+obj-$(CONFIG_FSL_PFE) += eth.o
diff --git a/board/freescale/ls1012aqds/eth.c b/board/freescale/ls1012aqds/eth.c
new file mode 100644 (file)
index 0000000..f8026a2
--- /dev/null
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2015-2016 Freescale Semiconductor, Inc.
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:    GPL-2.0+
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <asm/io.h>
+#include <netdev.h>
+#include <fm_eth.h>
+#include <fsl_mdio.h>
+#include <malloc.h>
+#include <asm/types.h>
+#include <fsl_dtsec.h>
+#include <asm/arch/soc.h>
+#include <asm/arch-fsl-layerscape/config.h>
+#include <asm/arch-fsl-layerscape/immap_lsch2.h>
+#include <asm/arch/fsl_serdes.h>
+#include "../common/qixis.h"
+#include <net/pfe_eth/pfe_eth.h>
+#include <dm/platform_data/pfe_dm_eth.h>
+#include "ls1012aqds_qixis.h"
+
+#define EMI_NONE       0xFF
+#define EMI1_RGMII     1
+#define EMI1_SLOT1     2
+#define EMI1_SLOT2     3
+
+#define DEFAULT_PFE_MDIO_NAME "PFE_MDIO"
+#define DEFAULT_PFE_MDIO1_NAME "PFE_MDIO1"
+
+static const char * const mdio_names[] = {
+       "NULL",
+       "LS1012AQDS_MDIO_RGMII",
+       "LS1012AQDS_MDIO_SLOT1",
+       "LS1012AQDS_MDIO_SLOT2",
+       "NULL",
+};
+
+static const char *ls1012aqds_mdio_name_for_muxval(u8 muxval)
+{
+       return mdio_names[muxval];
+}
+
+struct ls1012aqds_mdio {
+       u8 muxval;
+       struct mii_dev *realbus;
+};
+
+static void ls1012aqds_mux_mdio(u8 muxval)
+{
+       u8 brdcfg4;
+
+       if (muxval < 7) {
+               brdcfg4 = QIXIS_READ(brdcfg[4]);
+               brdcfg4 &= ~BRDCFG4_EMISEL_MASK;
+               brdcfg4 |= (muxval << BRDCFG4_EMISEL_SHIFT);
+               QIXIS_WRITE(brdcfg[4], brdcfg4);
+       }
+}
+
+static int ls1012aqds_mdio_read(struct mii_dev *bus, int addr, int devad,
+                               int regnum)
+{
+       struct ls1012aqds_mdio *priv = bus->priv;
+
+       ls1012aqds_mux_mdio(priv->muxval);
+
+       return priv->realbus->read(priv->realbus, addr, devad, regnum);
+}
+
+static int ls1012aqds_mdio_write(struct mii_dev *bus, int addr, int devad,
+                                int regnum, u16 value)
+{
+       struct ls1012aqds_mdio *priv = bus->priv;
+
+       ls1012aqds_mux_mdio(priv->muxval);
+
+       return priv->realbus->write(priv->realbus, addr, devad, regnum, value);
+}
+
+static int ls1012aqds_mdio_reset(struct mii_dev *bus)
+{
+       struct ls1012aqds_mdio *priv = bus->priv;
+
+       if (priv->realbus->reset)
+               return priv->realbus->reset(priv->realbus);
+       else
+               return -1;
+}
+
+static int ls1012aqds_mdio_init(char *realbusname, u8 muxval)
+{
+       struct ls1012aqds_mdio *pmdio;
+       struct mii_dev *bus = mdio_alloc();
+
+       if (!bus) {
+               printf("Failed to allocate ls1012aqds MDIO bus\n");
+               return -1;
+       }
+
+       pmdio = malloc(sizeof(*pmdio));
+       if (!pmdio) {
+               printf("Failed to allocate ls1012aqds private data\n");
+               free(bus);
+               return -1;
+       }
+
+       bus->read = ls1012aqds_mdio_read;
+       bus->write = ls1012aqds_mdio_write;
+       bus->reset = ls1012aqds_mdio_reset;
+       sprintf(bus->name, ls1012aqds_mdio_name_for_muxval(muxval));
+
+       pmdio->realbus = miiphy_get_dev_by_name(realbusname);
+
+       if (!pmdio->realbus) {
+               printf("No bus with name %s\n", realbusname);
+               free(bus);
+               free(pmdio);
+               return -1;
+       }
+
+       pmdio->muxval = muxval;
+       bus->priv = pmdio;
+       return mdio_register(bus);
+}
+
+int pfe_eth_board_init(struct udevice *dev)
+{
+       static int init_done;
+       struct mii_dev *bus;
+       static const char *mdio_name;
+       struct pfe_mdio_info mac_mdio_info;
+       struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+       u8 data8;
+       struct pfe_eth_dev *priv = dev_get_priv(dev);
+
+       int srds_s1 = in_be32(&gur->rcwsr[4]) &
+                       FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+       srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+       ls1012aqds_mux_mdio(EMI1_SLOT1);
+
+       if (!init_done) {
+               mac_mdio_info.reg_base = (void *)EMAC1_BASE_ADDR;
+               mac_mdio_info.name = DEFAULT_PFE_MDIO_NAME;
+
+               bus = pfe_mdio_init(&mac_mdio_info);
+               if (!bus) {
+                       printf("Failed to register mdio\n");
+                       return -1;
+               }
+               init_done = 1;
+       }
+
+       if (priv->gemac_port) {
+               mac_mdio_info.reg_base = (void *)EMAC2_BASE_ADDR;
+               mac_mdio_info.name = DEFAULT_PFE_MDIO1_NAME;
+
+               bus = pfe_mdio_init(&mac_mdio_info);
+               if (!bus) {
+                       printf("Failed to register mdio\n");
+                       return -1;
+               }
+       }
+
+       switch (srds_s1) {
+       case 0x3508:
+               printf("ls1012aqds:supported SerDes PRCTL= %d\n", srds_s1);
+#ifdef CONFIG_PFE_RGMII_RESET_WA
+               /*
+                * Work around for FPGA registers initialization
+                * This is needed for RGMII to work.
+                */
+               printf("Reset RGMII WA....\n");
+               data8 = QIXIS_READ(rst_frc[0]);
+               data8 |= 0x2;
+               QIXIS_WRITE(rst_frc[0], data8);
+               data8 = QIXIS_READ(rst_frc[0]);
+
+               data8 = QIXIS_READ(res8[6]);
+               data8 |= 0xff;
+               QIXIS_WRITE(res8[6], data8);
+               data8 = QIXIS_READ(res8[6]);
+#endif
+       if (priv->gemac_port) {
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_RGMII);
+               if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_RGMII)
+                   < 0) {
+                       printf("Failed to register mdio for %s\n", mdio_name);
+               }
+
+               /* MAC2 */
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_RGMII);
+               bus = miiphy_get_dev_by_name(mdio_name);
+               pfe_set_mdio(priv->gemac_port, bus);
+               pfe_set_phy_address_mode(priv->gemac_port,
+                                        CONFIG_PFE_EMAC2_PHY_ADDR,
+                                        PHY_INTERFACE_MODE_RGMII);
+
+       } else {
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1);
+               if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_SLOT1)
+               < 0) {
+                       printf("Failed to register mdio for %s\n", mdio_name);
+               }
+
+               /* MAC1 */
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1);
+               bus = miiphy_get_dev_by_name(mdio_name);
+               pfe_set_mdio(priv->gemac_port, bus);
+               pfe_set_phy_address_mode(priv->gemac_port,
+                                        CONFIG_PFE_EMAC1_PHY_ADDR,
+                                        PHY_INTERFACE_MODE_SGMII);
+       }
+
+               break;
+
+       case 0x2205:
+               printf("ls1012aqds:supported SerDes PRCTL= %d\n", srds_s1);
+               /*
+                * Work around for FPGA registers initialization
+                * This is needed for RGMII to work.
+                */
+               printf("Reset SLOT1 SLOT2....\n");
+               data8 = QIXIS_READ(rst_frc[2]);
+               data8 |= 0xc0;
+               QIXIS_WRITE(rst_frc[2], data8);
+               mdelay(100);
+               data8 = QIXIS_READ(rst_frc[2]);
+               data8 &= 0x3f;
+               QIXIS_WRITE(rst_frc[2], data8);
+
+       if (priv->gemac_port) {
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT2);
+               if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_SLOT2)
+               < 0) {
+                       printf("Failed to register mdio for %s\n", mdio_name);
+               }
+               /* MAC2 */
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT2);
+               bus = miiphy_get_dev_by_name(mdio_name);
+               pfe_set_mdio(1, bus);
+               pfe_set_phy_address_mode(1, CONFIG_PFE_SGMII_2500_PHY2_ADDR,
+                                        PHY_INTERFACE_MODE_SGMII_2500);
+
+               data8 = QIXIS_READ(brdcfg[12]);
+               data8 |= 0x20;
+               QIXIS_WRITE(brdcfg[12], data8);
+
+       } else {
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1);
+               if (ls1012aqds_mdio_init(DEFAULT_PFE_MDIO_NAME, EMI1_SLOT1)
+                   < 0) {
+                       printf("Failed to register mdio for %s\n", mdio_name);
+               }
+
+               /* MAC1 */
+               mdio_name = ls1012aqds_mdio_name_for_muxval(EMI1_SLOT1);
+               bus = miiphy_get_dev_by_name(mdio_name);
+               pfe_set_mdio(0, bus);
+               pfe_set_phy_address_mode(0,
+                                        CONFIG_PFE_SGMII_2500_PHY1_ADDR,
+                                        PHY_INTERFACE_MODE_SGMII_2500);
+       }
+               break;
+
+       default:
+               printf("ls1012aqds:unsupported SerDes PRCTL= %d\n", srds_s1);
+               break;
+       }
+       return 0;
+}
+
+static struct pfe_eth_pdata pfe_pdata0 = {
+       .pfe_eth_pdata_mac = {
+               .iobase = (phys_addr_t)EMAC1_BASE_ADDR,
+               .phy_interface = 0,
+       },
+
+       .pfe_ddr_addr = {
+               .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR,
+               .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR,
+       },
+};
+
+static struct pfe_eth_pdata pfe_pdata1 = {
+       .pfe_eth_pdata_mac = {
+               .iobase = (phys_addr_t)EMAC2_BASE_ADDR,
+               .phy_interface = 1,
+       },
+
+       .pfe_ddr_addr = {
+               .ddr_pfe_baseaddr = (void *)CONFIG_DDR_PFE_BASEADDR,
+               .ddr_pfe_phys_baseaddr = CONFIG_DDR_PFE_PHYS_BASEADDR,
+       },
+};
+
+U_BOOT_DEVICE(ls1012a_pfe0) = {
+       .name = "pfe_eth",
+       .platdata = &pfe_pdata0,
+};
+
+U_BOOT_DEVICE(ls1012a_pfe1) = {
+       .name = "pfe_eth",
+       .platdata = &pfe_pdata1,
+};
index 406194da27facce39f494eb1df634abdd6514e1e..4577917e8d2fa387b80c17c22da4b17ad5ded613 100644 (file)
@@ -25,9 +25,9 @@
 #include <fsl_mmdc.h>
 #include <spl.h>
 #include <netdev.h>
-
 #include "../common/qixis.h"
 #include "ls1012aqds_qixis.h"
+#include "ls1012aqds_pfe.h"
 
 DECLARE_GLOBAL_DATA_PTR;
 
@@ -128,11 +128,6 @@ int board_init(void)
        return 0;
 }
 
-int board_eth_init(bd_t *bis)
-{
-       return pci_eth_init(bis);
-}
-
 int esdhc_status_fixup(void *blob, const char *compat)
 {
        char esdhc0_path[] = "/soc/esdhc@1560000";
@@ -161,12 +156,102 @@ int esdhc_status_fixup(void *blob, const char *compat)
        return 0;
 }
 
+static int pfe_set_properties(void *set_blob, struct pfe_prop_val prop_val,
+                             char *enet_path, char *mdio_path)
+{
+       do_fixup_by_path(set_blob, enet_path, "fsl,gemac-bus-id",
+                        &prop_val.busid, PFE_PROP_LEN, 1);
+       do_fixup_by_path(set_blob, enet_path, "fsl,gemac-phy-id",
+                        &prop_val.phyid, PFE_PROP_LEN, 1);
+       do_fixup_by_path(set_blob, enet_path, "fsl,mdio-mux-val",
+                        &prop_val.mux_val, PFE_PROP_LEN, 1);
+       do_fixup_by_path(set_blob, enet_path, "phy-mode",
+                        prop_val.phy_mode, strlen(prop_val.phy_mode) + 1, 1);
+       do_fixup_by_path(set_blob, mdio_path, "fsl,mdio-phy-mask",
+                        &prop_val.phy_mask, PFE_PROP_LEN, 1);
+       return 0;
+}
+
+static void fdt_fsl_fixup_of_pfe(void *blob)
+{
+       int i = 0;
+       struct pfe_prop_val prop_val;
+       void *l_blob = blob;
+
+       struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
+       unsigned int srds_s1 = in_be32(&gur->rcwsr[4]) &
+               FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
+       srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
+
+       for (i = 0; i < NUM_ETH_NODE; i++) {
+               switch (srds_s1) {
+               case SERDES_1_G_PROTOCOL:
+                       if (i == 0) {
+                               prop_val.busid = cpu_to_fdt32(
+                                               ETH_1_1G_BUS_ID);
+                               prop_val.phyid = cpu_to_fdt32(
+                                               ETH_1_1G_PHY_ID);
+                               prop_val.mux_val = cpu_to_fdt32(
+                                               ETH_1_1G_MDIO_MUX);
+                               prop_val.phy_mask = cpu_to_fdt32(
+                                               ETH_1G_MDIO_PHY_MASK);
+                               prop_val.phy_mode = "sgmii";
+                               pfe_set_properties(l_blob, prop_val, ETH_1_PATH,
+                                                  ETH_1_MDIO);
+                       } else {
+                               prop_val.busid = cpu_to_fdt32(
+                                               ETH_2_1G_BUS_ID);
+                               prop_val.phyid = cpu_to_fdt32(
+                                               ETH_2_1G_PHY_ID);
+                               prop_val.mux_val = cpu_to_fdt32(
+                                               ETH_2_1G_MDIO_MUX);
+                               prop_val.phy_mask = cpu_to_fdt32(
+                                               ETH_1G_MDIO_PHY_MASK);
+                               prop_val.phy_mode = "rgmii";
+                               pfe_set_properties(l_blob, prop_val, ETH_2_PATH,
+                                                  ETH_2_MDIO);
+                       }
+               break;
+               case SERDES_2_5_G_PROTOCOL:
+                       if (i == 0) {
+                               prop_val.busid = cpu_to_fdt32(
+                                               ETH_1_2_5G_BUS_ID);
+                               prop_val.phyid = cpu_to_fdt32(
+                                               ETH_1_2_5G_PHY_ID);
+                               prop_val.mux_val = cpu_to_fdt32(
+                                               ETH_1_2_5G_MDIO_MUX);
+                               prop_val.phy_mask = cpu_to_fdt32(
+                                               ETH_2_5G_MDIO_PHY_MASK);
+                               prop_val.phy_mode = "sgmii-2500";
+                               pfe_set_properties(l_blob, prop_val, ETH_1_PATH,
+                                                  ETH_1_MDIO);
+                       } else {
+                               prop_val.busid = cpu_to_fdt32(
+                                               ETH_2_2_5G_BUS_ID);
+                               prop_val.phyid = cpu_to_fdt32(
+                                               ETH_2_2_5G_PHY_ID);
+                               prop_val.mux_val = cpu_to_fdt32(
+                                               ETH_2_2_5G_MDIO_MUX);
+                               prop_val.phy_mask = cpu_to_fdt32(
+                                               ETH_2_5G_MDIO_PHY_MASK);
+                               prop_val.phy_mode = "sgmii-2500";
+                               pfe_set_properties(l_blob, prop_val, ETH_2_PATH,
+                                                  ETH_2_MDIO);
+                       }
+               break;
+               default:
+                       printf("serdes:[%d]\n", srds_s1);
+               }
+       }
+}
+
 #ifdef CONFIG_OF_BOARD_SETUP
 int ft_board_setup(void *blob, bd_t *bd)
 {
        arch_fixup_fdt(blob);
 
        ft_cpu_setup(blob, bd);
+       fdt_fsl_fixup_of_pfe(blob);
 
        return 0;
 }
diff --git a/board/freescale/ls1012aqds/ls1012aqds_pfe.h b/board/freescale/ls1012aqds/ls1012aqds_pfe.h
new file mode 100644 (file)
index 0000000..b06f722
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier:     GPL-2.0+
+ */
+
+#define ETH_1_1G_BUS_ID                0x1
+#define ETH_1_1G_PHY_ID                0x1e
+#define ETH_1_1G_MDIO_MUX      0x2
+#define ETH_1G_MDIO_PHY_MASK   0xBFFFFFFD
+#define ETH_1_1G_PHY_MODE      "sgmii"
+#define ETH_2_1G_BUS_ID                0x1
+#define ETH_2_1G_PHY_ID                0x1
+#define ETH_2_1G_MDIO_MUX      0x1
+#define ETH_2_1G_PHY_MODE      "rgmii"
+
+#define ETH_1_2_5G_BUS_ID      0x0
+#define ETH_1_2_5G_PHY_ID      0x1
+#define ETH_1_2_5G_MDIO_MUX    0x2
+#define ETH_2_5G_MDIO_PHY_MASK 0xFFFFFFF9
+#define ETH_2_5G_PHY_MODE      "sgmii-2500"
+#define ETH_2_2_5G_BUS_ID      0x1
+#define ETH_2_2_5G_PHY_ID      0x2
+#define ETH_2_2_5G_MDIO_MUX    0x3
+
+#define SERDES_1_G_PROTOCOL    0x3508
+#define SERDES_2_5_G_PROTOCOL  0x2205
+
+#define PFE_PROP_LEN           4
+
+#define ETH_1_PATH             "/pfe@04000000/ethernet@0"
+#define ETH_1_MDIO             ETH_1_PATH "/mdio@0"
+
+#define ETH_2_PATH             "/pfe@04000000/ethernet@1"
+#define ETH_2_MDIO             ETH_2_PATH "/mdio@0"
+
+#define NUM_ETH_NODE           2
+
+struct pfe_prop_val {
+       int busid;
+       int phyid;
+       int mux_val;
+       int phy_mask;
+       char *phy_mode;
+};
index 584f604aa865174340c2a187651f95e9adb64360..7a1ba3d938c12374e7a0a1a68d47f088c77edfb4 100644 (file)
@@ -11,7 +11,7 @@
 
 /* BRDCFG4[4:7] select EC1 and EC2 as a pair */
 #define BRDCFG4_EMISEL_MASK            0xe0
-#define BRDCFG4_EMISEL_SHIFT           5
+#define BRDCFG4_EMISEL_SHIFT           6
 
 /* SYSCLK */
 #define QIXIS_SYSCLK_66                        0x0