mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 15:41:40 +00:00
Merge git://git.denx.de/u-boot-net
This commit is contained in:
commit
b0af10443a
65 changed files with 5199 additions and 1268 deletions
|
@ -612,6 +612,29 @@ int setup_chip_volt(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FSL_PFE
|
||||
void init_pfe_scfg_dcfg_regs(void)
|
||||
{
|
||||
struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
u32 ecccr2;
|
||||
|
||||
out_be32(&scfg->pfeasbcr,
|
||||
in_be32(&scfg->pfeasbcr) | SCFG_PFEASBCR_AWCACHE0);
|
||||
out_be32(&scfg->pfebsbcr,
|
||||
in_be32(&scfg->pfebsbcr) | SCFG_PFEASBCR_AWCACHE0);
|
||||
|
||||
/* CCI-400 QoS settings for PFE */
|
||||
out_be32(&scfg->wr_qos1, (unsigned int)(SCFG_WR_QOS1_PFE1_QOS
|
||||
| SCFG_WR_QOS1_PFE2_QOS));
|
||||
out_be32(&scfg->rd_qos1, (unsigned int)(SCFG_RD_QOS1_PFE1_QOS
|
||||
| SCFG_RD_QOS1_PFE2_QOS));
|
||||
|
||||
ecccr2 = in_be32(CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2);
|
||||
out_be32((void *)CONFIG_SYS_DCSR_DCFG_ADDR + DCFG_DCSR_ECCCR2,
|
||||
ecccr2 | (unsigned int)DISABLE_PFE_ECC);
|
||||
}
|
||||
#endif
|
||||
|
||||
void fsl_lsch2_early_init_f(void)
|
||||
{
|
||||
struct ccsr_cci400 *cci = (struct ccsr_cci400 *)(CONFIG_SYS_IMMR +
|
||||
|
|
|
@ -82,6 +82,11 @@
|
|||
#define QSPI0_BASE_ADDR (CONFIG_SYS_IMMR + 0x00550000)
|
||||
#define DSPI1_BASE_ADDR (CONFIG_SYS_IMMR + 0x01100000)
|
||||
|
||||
#define GPIO1_BASE_ADDR (CONFIG_SYS_IMMR + 0x1300000)
|
||||
#define GPIO2_BASE_ADDR (CONFIG_SYS_IMMR + 0x1310000)
|
||||
#define GPIO3_BASE_ADDR (CONFIG_SYS_IMMR + 0x1320000)
|
||||
#define GPIO4_BASE_ADDR (CONFIG_SYS_IMMR + 0x1330000)
|
||||
|
||||
#define LPUART_BASE (CONFIG_SYS_IMMR + 0x01950000)
|
||||
|
||||
#define AHCI_BASE_ADDR (CONFIG_SYS_IMMR + 0x02200000)
|
||||
|
@ -200,6 +205,8 @@ struct sys_info {
|
|||
|
||||
/* Device Configuration and Pin Control */
|
||||
#define DCFG_DCSR_PORCR1 0x0
|
||||
#define DCFG_DCSR_ECCCR2 0x524
|
||||
#define DISABLE_PFE_ECC BIT(13)
|
||||
|
||||
struct ccsr_gur {
|
||||
u32 porsr1; /* POR status 1 */
|
||||
|
@ -390,6 +397,29 @@ struct ccsr_gur {
|
|||
#define SCFG_SNPCNFGCR_SATARDSNP 0x00800000
|
||||
#define SCFG_SNPCNFGCR_SATAWRSNP 0x00400000
|
||||
|
||||
/* RGMIIPCR bit definitions*/
|
||||
#define SCFG_RGMIIPCR_EN_AUTO BIT(3)
|
||||
#define SCFG_RGMIIPCR_SETSP_1000M BIT(2)
|
||||
#define SCFG_RGMIIPCR_SETSP_100M 0
|
||||
#define SCFG_RGMIIPCR_SETSP_10M BIT(1)
|
||||
#define SCFG_RGMIIPCR_SETFD BIT(0)
|
||||
|
||||
/* PFEASBCR bit definitions */
|
||||
#define SCFG_PFEASBCR_ARCACHE0 BIT(31)
|
||||
#define SCFG_PFEASBCR_AWCACHE0 BIT(30)
|
||||
#define SCFG_PFEASBCR_ARCACHE1 BIT(29)
|
||||
#define SCFG_PFEASBCR_AWCACHE1 BIT(28)
|
||||
#define SCFG_PFEASBCR_ARSNP BIT(27)
|
||||
#define SCFG_PFEASBCR_AWSNP BIT(26)
|
||||
|
||||
/* WR_QoS1 PFE bit definitions */
|
||||
#define SCFG_WR_QOS1_PFE1_QOS GENMASK(27, 24)
|
||||
#define SCFG_WR_QOS1_PFE2_QOS GENMASK(23, 20)
|
||||
|
||||
/* RD_QoS1 PFE bit definitions */
|
||||
#define SCFG_RD_QOS1_PFE1_QOS GENMASK(27, 24)
|
||||
#define SCFG_RD_QOS1_PFE2_QOS GENMASK(23, 20)
|
||||
|
||||
/* Supplemental Configuration Unit */
|
||||
struct ccsr_scfg {
|
||||
u8 res_000[0x100-0x000];
|
||||
|
@ -407,7 +437,12 @@ struct ccsr_scfg {
|
|||
u8 res_140[0x158-0x140];
|
||||
u32 altcbar;
|
||||
u32 qspi_cfg;
|
||||
u8 res_160[0x180-0x160];
|
||||
u8 res_160[0x164 - 0x160];
|
||||
u32 wr_qos1;
|
||||
u32 wr_qos2;
|
||||
u32 rd_qos1;
|
||||
u32 rd_qos2;
|
||||
u8 res_174[0x180 - 0x174];
|
||||
u32 dmamcr;
|
||||
u8 res_184[0x188-0x184];
|
||||
u32 gic_align;
|
||||
|
@ -438,7 +473,21 @@ struct ccsr_scfg {
|
|||
u32 usb_refclk_selcr1;
|
||||
u32 usb_refclk_selcr2;
|
||||
u32 usb_refclk_selcr3;
|
||||
u8 res_424[0x600-0x424];
|
||||
u8 res_424[0x434 - 0x424];
|
||||
u32 rgmiipcr;
|
||||
u32 res_438;
|
||||
u32 rgmiipsr;
|
||||
u32 pfepfcssr1;
|
||||
u32 pfeintencr1;
|
||||
u32 pfepfcssr2;
|
||||
u32 pfeintencr2;
|
||||
u32 pfeerrcr;
|
||||
u32 pfeeerrintencr;
|
||||
u32 pfeasbcr;
|
||||
u32 pfebsbcr;
|
||||
u8 res_460[0x484 - 0x460];
|
||||
u32 mdioselcr;
|
||||
u8 res_468[0x600 - 0x488];
|
||||
u32 scratchrw[4];
|
||||
u8 res_610[0x680-0x610];
|
||||
u32 corebcr;
|
||||
|
@ -591,6 +640,16 @@ struct ccsr_serdes {
|
|||
u8 res_19a0[0x2000-0x19a0]; /* from 0x19a0 to 0x1fff */
|
||||
};
|
||||
|
||||
struct ccsr_gpio {
|
||||
u32 gpdir;
|
||||
u32 gpodr;
|
||||
u32 gpdat;
|
||||
u32 gpier;
|
||||
u32 gpimr;
|
||||
u32 gpicr;
|
||||
u32 gpibe;
|
||||
};
|
||||
|
||||
/* MMU 500 */
|
||||
#define SMMU_SCR0 (SMMU_BASE + 0x0)
|
||||
#define SMMU_SCR1 (SMMU_BASE + 0x4)
|
||||
|
|
|
@ -26,6 +26,7 @@ enum csu_cslx_ind {
|
|||
CSU_CSLX_PCIE3_IO,
|
||||
CSU_CSLX_USB3 = 20,
|
||||
CSU_CSLX_USB2,
|
||||
CSU_CSLX_PFE = 23,
|
||||
CSU_CSLX_SERDES = 32,
|
||||
CSU_CSLX_QDMA,
|
||||
CSU_CSLX_LPUART2,
|
||||
|
@ -105,6 +106,7 @@ static struct csu_ns_dev ns_dev[] = {
|
|||
{CSU_CSLX_PCIE3_IO, CSU_ALL_RW},
|
||||
{CSU_CSLX_USB3, CSU_ALL_RW},
|
||||
{CSU_CSLX_USB2, CSU_ALL_RW},
|
||||
{CSU_CSLX_PFE, CSU_ALL_RW},
|
||||
{CSU_CSLX_SERDES, CSU_ALL_RW},
|
||||
{CSU_CSLX_QDMA, CSU_ALL_RW},
|
||||
{CSU_CSLX_LPUART2, CSU_ALL_RW},
|
||||
|
|
|
@ -127,6 +127,9 @@ void fsl_lsch2_early_init_f(void);
|
|||
int setup_chip_volt(void);
|
||||
/* Setup core vdd in unit mV */
|
||||
int board_setup_core_volt(u32 vdd);
|
||||
#ifdef CONFIG_FSL_PFE
|
||||
void init_pfe_scfg_dcfg_regs(void);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void cpu_name(char *name);
|
||||
|
|
|
@ -12,6 +12,35 @@ config SYS_SOC
|
|||
config SYS_CONFIG_NAME
|
||||
default "ls1012afrdm"
|
||||
|
||||
if FSL_PFE
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select PHYLIB
|
||||
imply PHY_REALTEK
|
||||
|
||||
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 0x2
|
||||
|
||||
config PFE_EMAC2_PHY_ADDR
|
||||
hex "PFE DDR base address"
|
||||
default 0x1
|
||||
|
||||
endif
|
||||
|
||||
source "board/freescale/common/Kconfig"
|
||||
|
||||
endif
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
#
|
||||
|
||||
obj-y += ls1012afrdm.o
|
||||
obj-$(CONFIG_FSL_PFE) += eth.o
|
||||
|
|
124
board/freescale/ls1012afrdm/eth.c
Normal file
124
board/freescale/ls1012afrdm/eth.c
Normal file
|
@ -0,0 +1,124 @@
|
|||
/*
|
||||
* 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 <net/pfe_eth/pfe_eth.h>
|
||||
#include <dm/platform_data/pfe_dm_eth.h>
|
||||
|
||||
#define DEFAULT_PFE_MDIO_NAME "PFE_MDIO"
|
||||
#define DEFAULT_PFE_MDIO1_NAME "PFE_MDIO1"
|
||||
|
||||
#define MASK_ETH_PHY_RST 0x00000100
|
||||
|
||||
static inline void ls1012afrdm_reset_phy(void)
|
||||
{
|
||||
unsigned int val;
|
||||
struct ccsr_gpio *pgpio = (void *)(GPIO1_BASE_ADDR);
|
||||
|
||||
setbits_be32(&pgpio->gpdir, MASK_ETH_PHY_RST);
|
||||
|
||||
val = in_be32(&pgpio->gpdat);
|
||||
setbits_be32(&pgpio->gpdat, val & ~MASK_ETH_PHY_RST);
|
||||
mdelay(10);
|
||||
|
||||
val = in_be32(&pgpio->gpdat);
|
||||
setbits_be32(&pgpio->gpdat, val | MASK_ETH_PHY_RST);
|
||||
mdelay(50);
|
||||
}
|
||||
|
||||
int pfe_eth_board_init(struct udevice *dev)
|
||||
{
|
||||
static int init_done;
|
||||
struct mii_dev *bus;
|
||||
struct pfe_mdio_info mac_mdio_info;
|
||||
struct pfe_eth_dev *priv = dev_get_priv(dev);
|
||||
|
||||
if (!init_done) {
|
||||
ls1012afrdm_reset_phy();
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
pfe_set_mdio(priv->gemac_port,
|
||||
miiphy_get_dev_by_name(DEFAULT_PFE_MDIO_NAME));
|
||||
if (!priv->gemac_port)
|
||||
/* MAC1 */
|
||||
pfe_set_phy_address_mode(priv->gemac_port,
|
||||
CONFIG_PFE_EMAC1_PHY_ADDR,
|
||||
PHY_INTERFACE_MODE_SGMII);
|
||||
else
|
||||
/* MAC2 */
|
||||
pfe_set_phy_address_mode(priv->gemac_port,
|
||||
CONFIG_PFE_EMAC2_PHY_ADDR,
|
||||
PHY_INTERFACE_MODE_SGMII);
|
||||
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,
|
||||
};
|
|
@ -57,11 +57,6 @@ int dram_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
return pci_eth_init(bis);
|
||||
}
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
fsl_lsch2_early_init_f();
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
#
|
||||
|
||||
obj-y += ls1012aqds.o
|
||||
obj-$(CONFIG_FSL_PFE) += eth.o
|
||||
|
|
309
board/freescale/ls1012aqds/eth.c
Normal file
309
board/freescale/ls1012aqds/eth.c
Normal file
|
@ -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,
|
||||
};
|
|
@ -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;
|
||||
}
|
||||
|
|
45
board/freescale/ls1012aqds/ls1012aqds_pfe.h
Normal file
45
board/freescale/ls1012aqds/ls1012aqds_pfe.h
Normal file
|
@ -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;
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -12,6 +12,35 @@ config SYS_SOC
|
|||
config SYS_CONFIG_NAME
|
||||
default "ls1012ardb"
|
||||
|
||||
if FSL_PFE
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select PHYLIB
|
||||
imply PHY_REALTEK
|
||||
|
||||
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 0x2
|
||||
|
||||
config PFE_EMAC2_PHY_ADDR
|
||||
hex "PFE DDR base address"
|
||||
default 0x1
|
||||
|
||||
endif
|
||||
|
||||
source "board/freescale/common/Kconfig"
|
||||
|
||||
endif
|
||||
|
@ -30,6 +59,36 @@ config SYS_SOC
|
|||
config SYS_CONFIG_NAME
|
||||
default "ls1012a2g5rdb"
|
||||
|
||||
if FSL_PFE
|
||||
|
||||
config BOARD_SPECIFIC_OPTIONS # dummy
|
||||
def_bool y
|
||||
select PHYLIB
|
||||
imply CONFIG_PHYLIB_10G
|
||||
imply CONFIG_PHY_AQUANTIA
|
||||
|
||||
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 0x2
|
||||
|
||||
config PFE_EMAC2_PHY_ADDR
|
||||
hex "PFE DDR base address"
|
||||
default 0x1
|
||||
|
||||
endif
|
||||
|
||||
source "board/freescale/common/Kconfig"
|
||||
|
||||
endif
|
||||
|
|
|
@ -5,3 +5,4 @@
|
|||
#
|
||||
|
||||
obj-y += ls1012ardb.o
|
||||
obj-$(CONFIG_FSL_PFE) += eth.o
|
||||
|
|
135
board/freescale/ls1012ardb/eth.c
Normal file
135
board/freescale/ls1012ardb/eth.c
Normal file
|
@ -0,0 +1,135 @@
|
|||
/*
|
||||
* 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 <net/pfe_eth/pfe_eth.h>
|
||||
#include <dm/platform_data/pfe_dm_eth.h>
|
||||
#include <i2c.h>
|
||||
|
||||
#define DEFAULT_PFE_MDIO_NAME "PFE_MDIO"
|
||||
|
||||
static inline void ls1012ardb_reset_phy(void)
|
||||
{
|
||||
#ifdef CONFIG_TARGET_LS1012ARDB
|
||||
/* Through reset IO expander reset both RGMII and SGMII PHYs */
|
||||
i2c_reg_write(I2C_MUX_IO2_ADDR, 6, __PHY_MASK);
|
||||
i2c_reg_write(I2C_MUX_IO2_ADDR, 2, __PHY_ETH2_MASK);
|
||||
mdelay(10);
|
||||
i2c_reg_write(I2C_MUX_IO2_ADDR, 2, __PHY_ETH1_MASK);
|
||||
mdelay(10);
|
||||
i2c_reg_write(I2C_MUX_IO2_ADDR, 2, 0xFF);
|
||||
mdelay(50);
|
||||
#endif
|
||||
}
|
||||
|
||||
int pfe_eth_board_init(struct udevice *dev)
|
||||
{
|
||||
static int init_done;
|
||||
struct mii_dev *bus;
|
||||
struct pfe_mdio_info mac_mdio_info;
|
||||
struct pfe_eth_dev *priv = dev_get_priv(dev);
|
||||
struct ccsr_gur __iomem *gur = (void *)CONFIG_SYS_FSL_GUTS_ADDR;
|
||||
|
||||
int srds_s1 = in_be32(&gur->rcwsr[4]) &
|
||||
FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_MASK;
|
||||
srds_s1 >>= FSL_CHASSIS2_RCWSR4_SRDS1_PRTCL_SHIFT;
|
||||
|
||||
if (!init_done) {
|
||||
ls1012ardb_reset_phy();
|
||||
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;
|
||||
}
|
||||
|
||||
pfe_set_mdio(priv->gemac_port,
|
||||
miiphy_get_dev_by_name(DEFAULT_PFE_MDIO_NAME));
|
||||
|
||||
switch (srds_s1) {
|
||||
case 0x3508:
|
||||
if (!priv->gemac_port) {
|
||||
/* MAC1 */
|
||||
pfe_set_phy_address_mode(priv->gemac_port,
|
||||
CONFIG_PFE_EMAC1_PHY_ADDR,
|
||||
PHY_INTERFACE_MODE_SGMII);
|
||||
} else {
|
||||
/* MAC2 */
|
||||
pfe_set_phy_address_mode(priv->gemac_port,
|
||||
CONFIG_PFE_EMAC2_PHY_ADDR,
|
||||
PHY_INTERFACE_MODE_RGMII_TXID);
|
||||
}
|
||||
break;
|
||||
case 0x2208:
|
||||
if (!priv->gemac_port) {
|
||||
/* MAC1 */
|
||||
pfe_set_phy_address_mode(priv->gemac_port,
|
||||
CONFIG_PFE_EMAC1_PHY_ADDR,
|
||||
PHY_INTERFACE_MODE_SGMII_2500);
|
||||
} else {
|
||||
/* MAC2 */
|
||||
pfe_set_phy_address_mode(priv->gemac_port,
|
||||
CONFIG_PFE_EMAC2_PHY_ADDR,
|
||||
PHY_INTERFACE_MODE_SGMII_2500);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("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,
|
||||
};
|
|
@ -114,10 +114,6 @@ int dram_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int board_eth_init(bd_t *bis)
|
||||
{
|
||||
return pci_eth_init(bis);
|
||||
}
|
||||
|
||||
int board_early_init_f(void)
|
||||
{
|
||||
|
|
|
@ -31,7 +31,9 @@ CONFIG_DM=y
|
|||
CONFIG_DM_MMC=y
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_FSL_PFE=y
|
||||
CONFIG_SYS_NS16550=y
|
||||
CONFIG_DM_SPI=y
|
||||
CONFIG_USB=y
|
||||
|
|
|
@ -29,8 +29,10 @@ CONFIG_DM=y
|
|||
# CONFIG_MMC is not set
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_E1000=y
|
||||
CONFIG_FSL_PFE=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_DM_PCI_COMPAT=y
|
||||
|
|
|
@ -36,8 +36,10 @@ CONFIG_SCSI_AHCI=y
|
|||
CONFIG_DM_MMC=y
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_E1000=y
|
||||
CONFIG_FSL_PFE=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_DM_PCI_COMPAT=y
|
||||
|
|
|
@ -32,8 +32,10 @@ CONFIG_DM=y
|
|||
CONFIG_DM_MMC=y
|
||||
CONFIG_DM_SPI_FLASH=y
|
||||
CONFIG_SPI_FLASH=y
|
||||
CONFIG_DM_ETH=y
|
||||
CONFIG_NETDEVICES=y
|
||||
CONFIG_E1000=y
|
||||
CONFIG_FSL_PFE=y
|
||||
CONFIG_PCI=y
|
||||
CONFIG_DM_PCI=y
|
||||
CONFIG_DM_PCI_COMPAT=y
|
||||
|
|
|
@ -12,3 +12,5 @@ CONFIG_SPL=y
|
|||
CONFIG_SUN8I_EMAC=y
|
||||
CONFIG_USB_EHCI_HCD=y
|
||||
CONFIG_SYS_USB_EVENT_POLL_VIA_INT_QUEUE=y
|
||||
CONFIG_PHY_REALTEK=y
|
||||
CONFIG_RTL8211E_PINE64_GIGABIT_FIX=y
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
source "drivers/net/phy/Kconfig"
|
||||
source "drivers/net/pfe_eth/Kconfig"
|
||||
|
||||
config DM_ETH
|
||||
bool "Enable Driver Model for Ethernet drivers"
|
||||
|
|
|
@ -23,7 +23,6 @@ obj-$(CONFIG_E1000_SPI) += e1000_spi.o
|
|||
obj-$(CONFIG_EEPRO100) += eepro100.o
|
||||
obj-$(CONFIG_SUN4I_EMAC) += sunxi_emac.o
|
||||
obj-$(CONFIG_SUN8I_EMAC) += sun8i_emac.o
|
||||
obj-$(CONFIG_ENC28J60) += enc28j60.o
|
||||
obj-$(CONFIG_EP93XX) += ep93xx_eth.o
|
||||
obj-$(CONFIG_ETHOC) += ethoc.o
|
||||
obj-$(CONFIG_FEC_MXC) += fec_mxc.o
|
||||
|
@ -73,3 +72,4 @@ obj-$(CONFIG_FSL_MEMAC) += fm/memac_phy.o
|
|||
obj-$(CONFIG_VSC9953) += vsc9953.o
|
||||
obj-$(CONFIG_PIC32_ETH) += pic32_mdio.o pic32_eth.o
|
||||
obj-$(CONFIG_DWC_ETH_QOS) += dwc_eth_qos.o
|
||||
obj-$(CONFIG_FSL_PFE) += pfe_eth/
|
||||
|
|
|
@ -949,7 +949,7 @@ static int _cpsw_recv(struct cpsw_priv *priv, uchar **pkt)
|
|||
{
|
||||
void *buffer;
|
||||
int len;
|
||||
int ret = -EAGAIN;
|
||||
int ret;
|
||||
|
||||
ret = cpdma_process(priv, &priv->rx_chan, &buffer, &len);
|
||||
if (ret < 0)
|
||||
|
|
|
@ -1,959 +0,0 @@
|
|||
/*
|
||||
* (C) Copyright 2010
|
||||
* Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
|
||||
* Martin Krause, Martin.Krause@tqs.de
|
||||
* reworked original enc28j60.c
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <net.h>
|
||||
#include <spi.h>
|
||||
#include <malloc.h>
|
||||
#include <netdev.h>
|
||||
#include <miiphy.h>
|
||||
#include "enc28j60.h"
|
||||
|
||||
/*
|
||||
* IMPORTANT: spi_claim_bus() and spi_release_bus()
|
||||
* are called at begin and end of each of the following functions:
|
||||
* enc_miiphy_read(), enc_miiphy_write(), enc_write_hwaddr(),
|
||||
* enc_init(), enc_recv(), enc_send(), enc_halt()
|
||||
* ALL other functions assume that the bus has already been claimed!
|
||||
* Since net_process_received_packet() might call enc_send() in return, the bus
|
||||
* must be released, net_process_received_packet() called and claimed again.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Controller memory layout.
|
||||
* We only allow 1 frame for transmission and reserve the rest
|
||||
* for reception to handle as many broadcast packets as possible.
|
||||
* Also use the memory from 0x0000 for receiver buffer. See errata pt. 5
|
||||
* 0x0000 - 0x19ff 6656 bytes receive buffer
|
||||
* 0x1a00 - 0x1fff 1536 bytes transmit buffer =
|
||||
* control(1)+frame(1518)+status(7)+reserve(10).
|
||||
*/
|
||||
#define ENC_RX_BUF_START 0x0000
|
||||
#define ENC_RX_BUF_END 0x19ff
|
||||
#define ENC_TX_BUF_START 0x1a00
|
||||
#define ENC_TX_BUF_END 0x1fff
|
||||
#define ENC_MAX_FRM_LEN 1518
|
||||
#define RX_RESET_COUNTER 1000
|
||||
|
||||
/*
|
||||
* For non data transfer functions, like phy read/write, set hwaddr, init
|
||||
* we do not need a full, time consuming init including link ready wait.
|
||||
* This enum helps to bring the chip through the minimum necessary inits.
|
||||
*/
|
||||
enum enc_initstate {none=0, setupdone, linkready};
|
||||
typedef struct enc_device {
|
||||
struct eth_device *dev; /* back pointer */
|
||||
struct spi_slave *slave;
|
||||
int rx_reset_counter;
|
||||
u16 next_pointer;
|
||||
u8 bank; /* current bank in enc28j60 */
|
||||
enum enc_initstate initstate;
|
||||
} enc_dev_t;
|
||||
|
||||
/*
|
||||
* enc_bset: set bits in a common register
|
||||
* enc_bclr: clear bits in a common register
|
||||
*
|
||||
* making the reg parameter u8 will give a compile time warning if the
|
||||
* functions are called with a register not accessible in all Banks
|
||||
*/
|
||||
static void enc_bset(enc_dev_t *enc, const u8 reg, const u8 data)
|
||||
{
|
||||
u8 dout[2];
|
||||
|
||||
dout[0] = CMD_BFS(reg);
|
||||
dout[1] = data;
|
||||
spi_xfer(enc->slave, 2 * 8, dout, NULL,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
}
|
||||
|
||||
static void enc_bclr(enc_dev_t *enc, const u8 reg, const u8 data)
|
||||
{
|
||||
u8 dout[2];
|
||||
|
||||
dout[0] = CMD_BFC(reg);
|
||||
dout[1] = data;
|
||||
spi_xfer(enc->slave, 2 * 8, dout, NULL,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* high byte of the register contains bank number:
|
||||
* 0: no bank switch necessary
|
||||
* 1: switch to bank 0
|
||||
* 2: switch to bank 1
|
||||
* 3: switch to bank 2
|
||||
* 4: switch to bank 3
|
||||
*/
|
||||
static void enc_set_bank(enc_dev_t *enc, const u16 reg)
|
||||
{
|
||||
u8 newbank = reg >> 8;
|
||||
|
||||
if (newbank == 0 || newbank == enc->bank)
|
||||
return;
|
||||
switch (newbank) {
|
||||
case 1:
|
||||
enc_bclr(enc, CTL_REG_ECON1,
|
||||
ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1);
|
||||
break;
|
||||
case 2:
|
||||
enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0);
|
||||
enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1);
|
||||
break;
|
||||
case 3:
|
||||
enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_BSEL0);
|
||||
enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_BSEL1);
|
||||
break;
|
||||
case 4:
|
||||
enc_bset(enc, CTL_REG_ECON1,
|
||||
ENC_ECON1_BSEL0 | ENC_ECON1_BSEL1);
|
||||
break;
|
||||
}
|
||||
enc->bank = newbank;
|
||||
}
|
||||
|
||||
/*
|
||||
* local functions to access SPI
|
||||
*
|
||||
* reg: register inside ENC28J60
|
||||
* data: 8/16 bits to write
|
||||
* c: number of retries
|
||||
*
|
||||
* enc_r8: read 8 bits
|
||||
* enc_r16: read 16 bits
|
||||
* enc_w8: write 8 bits
|
||||
* enc_w16: write 16 bits
|
||||
* enc_w8_retry: write 8 bits, verify and retry
|
||||
* enc_rbuf: read from ENC28J60 into buffer
|
||||
* enc_wbuf: write from buffer into ENC28J60
|
||||
*/
|
||||
|
||||
/*
|
||||
* MAC and MII registers need a 3 byte SPI transfer to read,
|
||||
* all other registers need a 2 byte SPI transfer.
|
||||
*/
|
||||
static int enc_reg2nbytes(const u16 reg)
|
||||
{
|
||||
/* check if MAC or MII register */
|
||||
return ((reg >= CTL_REG_MACON1 && reg <= CTL_REG_MIRDH) ||
|
||||
(reg >= CTL_REG_MAADR1 && reg <= CTL_REG_MAADR4) ||
|
||||
(reg == CTL_REG_MISTAT)) ? 3 : 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a byte register
|
||||
*/
|
||||
static u8 enc_r8(enc_dev_t *enc, const u16 reg)
|
||||
{
|
||||
u8 dout[3];
|
||||
u8 din[3];
|
||||
int nbytes = enc_reg2nbytes(reg);
|
||||
|
||||
enc_set_bank(enc, reg);
|
||||
dout[0] = CMD_RCR(reg);
|
||||
spi_xfer(enc->slave, nbytes * 8, dout, din,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
return din[nbytes-1];
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a L/H register pair and return a word.
|
||||
* Must be called with the L register's address.
|
||||
*/
|
||||
static u16 enc_r16(enc_dev_t *enc, const u16 reg)
|
||||
{
|
||||
u8 dout[3];
|
||||
u8 din[3];
|
||||
u16 result;
|
||||
int nbytes = enc_reg2nbytes(reg);
|
||||
|
||||
enc_set_bank(enc, reg);
|
||||
dout[0] = CMD_RCR(reg);
|
||||
spi_xfer(enc->slave, nbytes * 8, dout, din,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
result = din[nbytes-1];
|
||||
dout[0]++; /* next register */
|
||||
spi_xfer(enc->slave, nbytes * 8, dout, din,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
result |= din[nbytes-1] << 8;
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a byte register
|
||||
*/
|
||||
static void enc_w8(enc_dev_t *enc, const u16 reg, const u8 data)
|
||||
{
|
||||
u8 dout[2];
|
||||
|
||||
enc_set_bank(enc, reg);
|
||||
dout[0] = CMD_WCR(reg);
|
||||
dout[1] = data;
|
||||
spi_xfer(enc->slave, 2 * 8, dout, NULL,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a L/H register pair.
|
||||
* Must be called with the L register's address.
|
||||
*/
|
||||
static void enc_w16(enc_dev_t *enc, const u16 reg, const u16 data)
|
||||
{
|
||||
u8 dout[2];
|
||||
|
||||
enc_set_bank(enc, reg);
|
||||
dout[0] = CMD_WCR(reg);
|
||||
dout[1] = data;
|
||||
spi_xfer(enc->slave, 2 * 8, dout, NULL,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
dout[0]++; /* next register */
|
||||
dout[1] = data >> 8;
|
||||
spi_xfer(enc->slave, 2 * 8, dout, NULL,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a byte register, verify and retry
|
||||
*/
|
||||
static void enc_w8_retry(enc_dev_t *enc, const u16 reg, const u8 data, const int c)
|
||||
{
|
||||
u8 dout[2];
|
||||
u8 readback;
|
||||
int i;
|
||||
|
||||
enc_set_bank(enc, reg);
|
||||
for (i = 0; i < c; i++) {
|
||||
dout[0] = CMD_WCR(reg);
|
||||
dout[1] = data;
|
||||
spi_xfer(enc->slave, 2 * 8, dout, NULL,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
readback = enc_r8(enc, reg);
|
||||
if (readback == data)
|
||||
break;
|
||||
/* wait 1ms */
|
||||
udelay(1000);
|
||||
}
|
||||
if (i == c) {
|
||||
printf("%s: write reg 0x%03x failed\n", enc->dev->name, reg);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Read ENC RAM into buffer
|
||||
*/
|
||||
static void enc_rbuf(enc_dev_t *enc, const u16 length, u8 *buf)
|
||||
{
|
||||
u8 dout[1];
|
||||
|
||||
dout[0] = CMD_RBM;
|
||||
spi_xfer(enc->slave, 8, dout, NULL, SPI_XFER_BEGIN);
|
||||
spi_xfer(enc->slave, length * 8, NULL, buf, SPI_XFER_END);
|
||||
#ifdef DEBUG
|
||||
puts("Rx:\n");
|
||||
print_buffer(0, buf, 1, length, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Write buffer into ENC RAM
|
||||
*/
|
||||
static void enc_wbuf(enc_dev_t *enc, const u16 length, const u8 *buf, const u8 control)
|
||||
{
|
||||
u8 dout[2];
|
||||
dout[0] = CMD_WBM;
|
||||
dout[1] = control;
|
||||
spi_xfer(enc->slave, 2 * 8, dout, NULL, SPI_XFER_BEGIN);
|
||||
spi_xfer(enc->slave, length * 8, buf, NULL, SPI_XFER_END);
|
||||
#ifdef DEBUG
|
||||
puts("Tx:\n");
|
||||
print_buffer(0, buf, 1, length, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to claim the SPI bus.
|
||||
* Print error message on failure.
|
||||
*/
|
||||
static int enc_claim_bus(enc_dev_t *enc)
|
||||
{
|
||||
int rc = spi_claim_bus(enc->slave);
|
||||
if (rc)
|
||||
printf("%s: failed to claim SPI bus\n", enc->dev->name);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
* Release previously claimed SPI bus.
|
||||
* This function is mainly for symmetry to enc_claim_bus().
|
||||
* Let the toolchain decide to inline it...
|
||||
*/
|
||||
static void enc_release_bus(enc_dev_t *enc)
|
||||
{
|
||||
spi_release_bus(enc->slave);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read PHY register
|
||||
*/
|
||||
static u16 enc_phy_read(enc_dev_t *enc, const u8 addr)
|
||||
{
|
||||
uint64_t etime;
|
||||
u8 status;
|
||||
|
||||
enc_w8(enc, CTL_REG_MIREGADR, addr);
|
||||
enc_w8(enc, CTL_REG_MICMD, ENC_MICMD_MIIRD);
|
||||
/* 1 second timeout - only happens on hardware problem */
|
||||
etime = get_ticks() + get_tbclk();
|
||||
/* poll MISTAT.BUSY bit until operation is complete */
|
||||
do
|
||||
{
|
||||
status = enc_r8(enc, CTL_REG_MISTAT);
|
||||
} while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY));
|
||||
if (status & ENC_MISTAT_BUSY) {
|
||||
printf("%s: timeout reading phy\n", enc->dev->name);
|
||||
return 0;
|
||||
}
|
||||
enc_w8(enc, CTL_REG_MICMD, 0);
|
||||
return enc_r16(enc, CTL_REG_MIRDL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write PHY register
|
||||
*/
|
||||
static void enc_phy_write(enc_dev_t *enc, const u8 addr, const u16 data)
|
||||
{
|
||||
uint64_t etime;
|
||||
u8 status;
|
||||
|
||||
enc_w8(enc, CTL_REG_MIREGADR, addr);
|
||||
enc_w16(enc, CTL_REG_MIWRL, data);
|
||||
/* 1 second timeout - only happens on hardware problem */
|
||||
etime = get_ticks() + get_tbclk();
|
||||
/* poll MISTAT.BUSY bit until operation is complete */
|
||||
do
|
||||
{
|
||||
status = enc_r8(enc, CTL_REG_MISTAT);
|
||||
} while (get_ticks() <= etime && (status & ENC_MISTAT_BUSY));
|
||||
if (status & ENC_MISTAT_BUSY) {
|
||||
printf("%s: timeout writing phy\n", enc->dev->name);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify link status, wait if necessary
|
||||
*
|
||||
* Note: with a 10 MBit/s only PHY there is no autonegotiation possible,
|
||||
* half/full duplex is a pure setup matter. For the time being, this driver
|
||||
* will setup in half duplex mode only.
|
||||
*/
|
||||
static int enc_phy_link_wait(enc_dev_t *enc)
|
||||
{
|
||||
u16 status;
|
||||
int duplex;
|
||||
uint64_t etime;
|
||||
|
||||
#ifdef CONFIG_ENC_SILENTLINK
|
||||
/* check if we have a link, then just return */
|
||||
status = enc_phy_read(enc, PHY_REG_PHSTAT1);
|
||||
if (status & ENC_PHSTAT1_LLSTAT)
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
/* wait for link with 1 second timeout */
|
||||
etime = get_ticks() + get_tbclk();
|
||||
while (get_ticks() <= etime) {
|
||||
status = enc_phy_read(enc, PHY_REG_PHSTAT1);
|
||||
if (status & ENC_PHSTAT1_LLSTAT) {
|
||||
/* now we have a link */
|
||||
status = enc_phy_read(enc, PHY_REG_PHSTAT2);
|
||||
duplex = (status & ENC_PHSTAT2_DPXSTAT) ? 1 : 0;
|
||||
printf("%s: link up, 10Mbps %s-duplex\n",
|
||||
enc->dev->name, duplex ? "full" : "half");
|
||||
return 0;
|
||||
}
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
/* timeout occurred */
|
||||
printf("%s: link down\n", enc->dev->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function resets the receiver only.
|
||||
*/
|
||||
static void enc_reset_rx(enc_dev_t *enc)
|
||||
{
|
||||
u8 econ1;
|
||||
|
||||
econ1 = enc_r8(enc, CTL_REG_ECON1);
|
||||
if ((econ1 & ENC_ECON1_RXRST) == 0) {
|
||||
enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXRST);
|
||||
enc->rx_reset_counter = RX_RESET_COUNTER;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reset receiver and reenable it.
|
||||
*/
|
||||
static void enc_reset_rx_call(enc_dev_t *enc)
|
||||
{
|
||||
enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXRST);
|
||||
enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy a packet from the receive ring and forward it to
|
||||
* the protocol stack.
|
||||
*/
|
||||
static void enc_receive(enc_dev_t *enc)
|
||||
{
|
||||
u8 *packet = (u8 *)net_rx_packets[0];
|
||||
u16 pkt_len;
|
||||
u16 copy_len;
|
||||
u16 status;
|
||||
u8 pkt_cnt = 0;
|
||||
u16 rxbuf_rdpt;
|
||||
u8 hbuf[6];
|
||||
|
||||
enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer);
|
||||
do {
|
||||
enc_rbuf(enc, 6, hbuf);
|
||||
enc->next_pointer = hbuf[0] | (hbuf[1] << 8);
|
||||
pkt_len = hbuf[2] | (hbuf[3] << 8);
|
||||
status = hbuf[4] | (hbuf[5] << 8);
|
||||
debug("next_pointer=$%04x pkt_len=%u status=$%04x\n",
|
||||
enc->next_pointer, pkt_len, status);
|
||||
if (pkt_len <= ENC_MAX_FRM_LEN)
|
||||
copy_len = pkt_len;
|
||||
else
|
||||
copy_len = 0;
|
||||
if ((status & (1L << 7)) == 0) /* check Received Ok bit */
|
||||
copy_len = 0;
|
||||
/* check if next pointer is resonable */
|
||||
if (enc->next_pointer >= ENC_TX_BUF_START)
|
||||
copy_len = 0;
|
||||
if (copy_len > 0) {
|
||||
enc_rbuf(enc, copy_len, packet);
|
||||
}
|
||||
/* advance read pointer to next pointer */
|
||||
enc_w16(enc, CTL_REG_ERDPTL, enc->next_pointer);
|
||||
/* decrease packet counter */
|
||||
enc_bset(enc, CTL_REG_ECON2, ENC_ECON2_PKTDEC);
|
||||
/*
|
||||
* Only odd values should be written to ERXRDPTL,
|
||||
* see errata B4 pt.13
|
||||
*/
|
||||
rxbuf_rdpt = enc->next_pointer - 1;
|
||||
if ((rxbuf_rdpt < enc_r16(enc, CTL_REG_ERXSTL)) ||
|
||||
(rxbuf_rdpt > enc_r16(enc, CTL_REG_ERXNDL))) {
|
||||
enc_w16(enc, CTL_REG_ERXRDPTL,
|
||||
enc_r16(enc, CTL_REG_ERXNDL));
|
||||
} else {
|
||||
enc_w16(enc, CTL_REG_ERXRDPTL, rxbuf_rdpt);
|
||||
}
|
||||
/* read pktcnt */
|
||||
pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT);
|
||||
if (copy_len == 0) {
|
||||
(void)enc_r8(enc, CTL_REG_EIR);
|
||||
enc_reset_rx(enc);
|
||||
printf("%s: receive copy_len=0\n", enc->dev->name);
|
||||
continue;
|
||||
}
|
||||
/*
|
||||
* Because net_process_received_packet() might call enc_send(),
|
||||
* we need to release the SPI bus, call
|
||||
* net_process_received_packet(), reclaim the bus.
|
||||
*/
|
||||
enc_release_bus(enc);
|
||||
net_process_received_packet(packet, pkt_len);
|
||||
if (enc_claim_bus(enc))
|
||||
return;
|
||||
(void)enc_r8(enc, CTL_REG_EIR);
|
||||
} while (pkt_cnt);
|
||||
/* Use EPKTCNT not EIR.PKTIF flag, see errata pt. 6 */
|
||||
}
|
||||
|
||||
/*
|
||||
* Poll for completely received packets.
|
||||
*/
|
||||
static void enc_poll(enc_dev_t *enc)
|
||||
{
|
||||
u8 eir_reg;
|
||||
u8 pkt_cnt;
|
||||
|
||||
(void)enc_r8(enc, CTL_REG_ESTAT);
|
||||
eir_reg = enc_r8(enc, CTL_REG_EIR);
|
||||
if (eir_reg & ENC_EIR_TXIF) {
|
||||
/* clear TXIF bit in EIR */
|
||||
enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXIF);
|
||||
}
|
||||
/* We have to use pktcnt and not pktif bit, see errata pt. 6 */
|
||||
pkt_cnt = enc_r8(enc, CTL_REG_EPKTCNT);
|
||||
if (pkt_cnt > 0) {
|
||||
if ((eir_reg & ENC_EIR_PKTIF) == 0) {
|
||||
debug("enc_poll: pkt cnt > 0, but pktif not set\n");
|
||||
}
|
||||
enc_receive(enc);
|
||||
/*
|
||||
* clear PKTIF bit in EIR, this should not need to be done
|
||||
* but it seems like we get problems if we do not
|
||||
*/
|
||||
enc_bclr(enc, CTL_REG_EIR, ENC_EIR_PKTIF);
|
||||
}
|
||||
if (eir_reg & ENC_EIR_RXERIF) {
|
||||
printf("%s: rx error\n", enc->dev->name);
|
||||
enc_bclr(enc, CTL_REG_EIR, ENC_EIR_RXERIF);
|
||||
}
|
||||
if (eir_reg & ENC_EIR_TXERIF) {
|
||||
printf("%s: tx error\n", enc->dev->name);
|
||||
enc_bclr(enc, CTL_REG_EIR, ENC_EIR_TXERIF);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Completely Reset the ENC
|
||||
*/
|
||||
static void enc_reset(enc_dev_t *enc)
|
||||
{
|
||||
u8 dout[1];
|
||||
|
||||
dout[0] = CMD_SRC;
|
||||
spi_xfer(enc->slave, 8, dout, NULL,
|
||||
SPI_XFER_BEGIN | SPI_XFER_END);
|
||||
/* sleep 1 ms. See errata pt. 2 */
|
||||
udelay(1000);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialisation data for most of the ENC registers
|
||||
*/
|
||||
static const u16 enc_initdata[] = {
|
||||
/*
|
||||
* Setup the buffer space. The reset values are valid for the
|
||||
* other pointers.
|
||||
*
|
||||
* We shall not write to ERXST, see errata pt. 5. Instead we
|
||||
* have to make sure that ENC_RX_BUS_START is 0.
|
||||
*/
|
||||
CTL_REG_ERXSTL, ENC_RX_BUF_START,
|
||||
CTL_REG_ERXSTH, ENC_RX_BUF_START >> 8,
|
||||
CTL_REG_ERXNDL, ENC_RX_BUF_END,
|
||||
CTL_REG_ERXNDH, ENC_RX_BUF_END >> 8,
|
||||
CTL_REG_ERDPTL, ENC_RX_BUF_START,
|
||||
CTL_REG_ERDPTH, ENC_RX_BUF_START >> 8,
|
||||
/*
|
||||
* Set the filter to receive only good-CRC, unicast and broadcast
|
||||
* frames.
|
||||
* Note: some DHCP servers return their answers as broadcasts!
|
||||
* So its unwise to remove broadcast from this. This driver
|
||||
* might incur receiver overruns with packet loss on a broadcast
|
||||
* flooded network.
|
||||
*/
|
||||
CTL_REG_ERXFCON, ENC_RFR_BCEN | ENC_RFR_UCEN | ENC_RFR_CRCEN,
|
||||
|
||||
/* enable MAC to receive frames */
|
||||
CTL_REG_MACON1,
|
||||
ENC_MACON1_MARXEN | ENC_MACON1_TXPAUS | ENC_MACON1_RXPAUS,
|
||||
|
||||
/* configure pad, tx-crc and duplex */
|
||||
CTL_REG_MACON3,
|
||||
ENC_MACON3_PADCFG0 | ENC_MACON3_TXCRCEN |
|
||||
ENC_MACON3_FRMLNEN,
|
||||
|
||||
/* Allow infinite deferals if the medium is continously busy */
|
||||
CTL_REG_MACON4, ENC_MACON4_DEFER,
|
||||
|
||||
/* Late collisions occur beyond 63 bytes */
|
||||
CTL_REG_MACLCON2, 63,
|
||||
|
||||
/*
|
||||
* Set (low byte) Non-Back-to_Back Inter-Packet Gap.
|
||||
* Recommended 0x12
|
||||
*/
|
||||
CTL_REG_MAIPGL, 0x12,
|
||||
|
||||
/*
|
||||
* Set (high byte) Non-Back-to_Back Inter-Packet Gap.
|
||||
* Recommended 0x0c for half-duplex. Nothing for full-duplex
|
||||
*/
|
||||
CTL_REG_MAIPGH, 0x0C,
|
||||
|
||||
/* set maximum frame length */
|
||||
CTL_REG_MAMXFLL, ENC_MAX_FRM_LEN,
|
||||
CTL_REG_MAMXFLH, ENC_MAX_FRM_LEN >> 8,
|
||||
|
||||
/*
|
||||
* Set MAC back-to-back inter-packet gap.
|
||||
* Recommended 0x12 for half duplex
|
||||
* and 0x15 for full duplex.
|
||||
*/
|
||||
CTL_REG_MABBIPG, 0x12,
|
||||
|
||||
/* end of table */
|
||||
0xffff
|
||||
};
|
||||
|
||||
/*
|
||||
* Wait for the XTAL oscillator to become ready
|
||||
*/
|
||||
static int enc_clock_wait(enc_dev_t *enc)
|
||||
{
|
||||
uint64_t etime;
|
||||
|
||||
/* one second timeout */
|
||||
etime = get_ticks() + get_tbclk();
|
||||
|
||||
/*
|
||||
* Wait for CLKRDY to become set (i.e., check that we can
|
||||
* communicate with the ENC)
|
||||
*/
|
||||
do
|
||||
{
|
||||
if (enc_r8(enc, CTL_REG_ESTAT) & ENC_ESTAT_CLKRDY)
|
||||
return 0;
|
||||
} while (get_ticks() <= etime);
|
||||
|
||||
printf("%s: timeout waiting for CLKRDY\n", enc->dev->name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write the MAC address into the ENC
|
||||
*/
|
||||
static int enc_write_macaddr(enc_dev_t *enc)
|
||||
{
|
||||
unsigned char *p = enc->dev->enetaddr;
|
||||
|
||||
enc_w8_retry(enc, CTL_REG_MAADR5, *p++, 5);
|
||||
enc_w8_retry(enc, CTL_REG_MAADR4, *p++, 5);
|
||||
enc_w8_retry(enc, CTL_REG_MAADR3, *p++, 5);
|
||||
enc_w8_retry(enc, CTL_REG_MAADR2, *p++, 5);
|
||||
enc_w8_retry(enc, CTL_REG_MAADR1, *p++, 5);
|
||||
enc_w8_retry(enc, CTL_REG_MAADR0, *p, 5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setup most of the ENC registers
|
||||
*/
|
||||
static int enc_setup(enc_dev_t *enc)
|
||||
{
|
||||
u16 phid1 = 0;
|
||||
u16 phid2 = 0;
|
||||
const u16 *tp;
|
||||
|
||||
/* reset enc struct values */
|
||||
enc->next_pointer = ENC_RX_BUF_START;
|
||||
enc->rx_reset_counter = RX_RESET_COUNTER;
|
||||
enc->bank = 0xff; /* invalidate current bank in enc28j60 */
|
||||
|
||||
/* verify PHY identification */
|
||||
phid1 = enc_phy_read(enc, PHY_REG_PHID1);
|
||||
phid2 = enc_phy_read(enc, PHY_REG_PHID2) & ENC_PHID2_MASK;
|
||||
if (phid1 != ENC_PHID1_VALUE || phid2 != ENC_PHID2_VALUE) {
|
||||
printf("%s: failed to identify PHY. Found %04x:%04x\n",
|
||||
enc->dev->name, phid1, phid2);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* now program registers */
|
||||
for (tp = enc_initdata; *tp != 0xffff; tp += 2)
|
||||
enc_w8_retry(enc, tp[0], tp[1], 10);
|
||||
|
||||
/*
|
||||
* Prevent automatic loopback of data beeing transmitted by setting
|
||||
* ENC_PHCON2_HDLDIS
|
||||
*/
|
||||
enc_phy_write(enc, PHY_REG_PHCON2, (1<<8));
|
||||
|
||||
/*
|
||||
* LEDs configuration
|
||||
* LEDA: LACFG = 0100 -> display link status
|
||||
* LEDB: LBCFG = 0111 -> display TX & RX activity
|
||||
* STRCH = 1 -> LED pulses
|
||||
*/
|
||||
enc_phy_write(enc, PHY_REG_PHLCON, 0x0472);
|
||||
|
||||
/* Reset PDPXMD-bit => half duplex */
|
||||
enc_phy_write(enc, PHY_REG_PHCON1, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check if ENC has been initialized.
|
||||
* If not, try to initialize it.
|
||||
* Remember initialized state in struct.
|
||||
*/
|
||||
static int enc_initcheck(enc_dev_t *enc, const enum enc_initstate requiredstate)
|
||||
{
|
||||
if (enc->initstate >= requiredstate)
|
||||
return 0;
|
||||
|
||||
if (enc->initstate < setupdone) {
|
||||
/* Initialize the ENC only */
|
||||
enc_reset(enc);
|
||||
/* if any of functions fails, skip the rest and return an error */
|
||||
if (enc_clock_wait(enc) || enc_setup(enc) || enc_write_macaddr(enc)) {
|
||||
return -1;
|
||||
}
|
||||
enc->initstate = setupdone;
|
||||
}
|
||||
/* if that's all we need, return here */
|
||||
if (enc->initstate >= requiredstate)
|
||||
return 0;
|
||||
|
||||
/* now wait for link ready condition */
|
||||
if (enc_phy_link_wait(enc)) {
|
||||
return -1;
|
||||
}
|
||||
enc->initstate = linkready;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_CMD_MII)
|
||||
/*
|
||||
* Read a PHY register.
|
||||
*
|
||||
* This function is registered with miiphy_register().
|
||||
*/
|
||||
int enc_miiphy_read(struct mii_dev *bus, int phy_adr, int devad, int reg)
|
||||
{
|
||||
u16 value = 0;
|
||||
struct eth_device *dev = eth_get_dev_by_name(bus->name);
|
||||
enc_dev_t *enc;
|
||||
|
||||
if (!dev || phy_adr != 0)
|
||||
return -1;
|
||||
|
||||
enc = dev->priv;
|
||||
if (enc_claim_bus(enc))
|
||||
return -1;
|
||||
if (enc_initcheck(enc, setupdone)) {
|
||||
enc_release_bus(enc);
|
||||
return -1;
|
||||
}
|
||||
value = enc_phy_read(enc, reg);
|
||||
enc_release_bus(enc);
|
||||
return value;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write a PHY register.
|
||||
*
|
||||
* This function is registered with miiphy_register().
|
||||
*/
|
||||
int enc_miiphy_write(struct mii_dev *bus, int phy_adr, int devad, int reg,
|
||||
u16 value)
|
||||
{
|
||||
struct eth_device *dev = eth_get_dev_by_name(bus->name);
|
||||
enc_dev_t *enc;
|
||||
|
||||
if (!dev || phy_adr != 0)
|
||||
return -1;
|
||||
|
||||
enc = dev->priv;
|
||||
if (enc_claim_bus(enc))
|
||||
return -1;
|
||||
if (enc_initcheck(enc, setupdone)) {
|
||||
enc_release_bus(enc);
|
||||
return -1;
|
||||
}
|
||||
enc_phy_write(enc, reg, value);
|
||||
enc_release_bus(enc);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Write hardware (MAC) address.
|
||||
*
|
||||
* This function entered into eth_device structure.
|
||||
*/
|
||||
static int enc_write_hwaddr(struct eth_device *dev)
|
||||
{
|
||||
enc_dev_t *enc = dev->priv;
|
||||
|
||||
if (enc_claim_bus(enc))
|
||||
return -1;
|
||||
if (enc_initcheck(enc, setupdone)) {
|
||||
enc_release_bus(enc);
|
||||
return -1;
|
||||
}
|
||||
enc_release_bus(enc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize ENC28J60 for use.
|
||||
*
|
||||
* This function entered into eth_device structure.
|
||||
*/
|
||||
static int enc_init(struct eth_device *dev, bd_t *bis)
|
||||
{
|
||||
enc_dev_t *enc = dev->priv;
|
||||
|
||||
if (enc_claim_bus(enc))
|
||||
return -1;
|
||||
if (enc_initcheck(enc, linkready)) {
|
||||
enc_release_bus(enc);
|
||||
return -1;
|
||||
}
|
||||
/* enable receive */
|
||||
enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
|
||||
enc_release_bus(enc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check for received packets.
|
||||
*
|
||||
* This function entered into eth_device structure.
|
||||
*/
|
||||
static int enc_recv(struct eth_device *dev)
|
||||
{
|
||||
enc_dev_t *enc = dev->priv;
|
||||
|
||||
if (enc_claim_bus(enc))
|
||||
return -1;
|
||||
if (enc_initcheck(enc, linkready)) {
|
||||
enc_release_bus(enc);
|
||||
return -1;
|
||||
}
|
||||
/* Check for dead receiver */
|
||||
if (enc->rx_reset_counter > 0)
|
||||
enc->rx_reset_counter--;
|
||||
else
|
||||
enc_reset_rx_call(enc);
|
||||
enc_poll(enc);
|
||||
enc_release_bus(enc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send a packet.
|
||||
*
|
||||
* This function entered into eth_device structure.
|
||||
*
|
||||
* Should we wait here until we have a Link? Or shall we leave that to
|
||||
* protocol retries?
|
||||
*/
|
||||
static int enc_send(
|
||||
struct eth_device *dev,
|
||||
void *packet,
|
||||
int length)
|
||||
{
|
||||
enc_dev_t *enc = dev->priv;
|
||||
|
||||
if (enc_claim_bus(enc))
|
||||
return -1;
|
||||
if (enc_initcheck(enc, linkready)) {
|
||||
enc_release_bus(enc);
|
||||
return -1;
|
||||
}
|
||||
/* setup transmit pointers */
|
||||
enc_w16(enc, CTL_REG_EWRPTL, ENC_TX_BUF_START);
|
||||
enc_w16(enc, CTL_REG_ETXNDL, length + ENC_TX_BUF_START);
|
||||
enc_w16(enc, CTL_REG_ETXSTL, ENC_TX_BUF_START);
|
||||
/* write packet to ENC */
|
||||
enc_wbuf(enc, length, (u8 *) packet, 0x00);
|
||||
/*
|
||||
* Check that the internal transmit logic has not been altered
|
||||
* by excessive collisions. Reset transmitter if so.
|
||||
* See Errata B4 12 and 14.
|
||||
*/
|
||||
if (enc_r8(enc, CTL_REG_EIR) & ENC_EIR_TXERIF) {
|
||||
enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRST);
|
||||
enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_TXRST);
|
||||
}
|
||||
enc_bclr(enc, CTL_REG_EIR, (ENC_EIR_TXERIF | ENC_EIR_TXIF));
|
||||
/* start transmitting */
|
||||
enc_bset(enc, CTL_REG_ECON1, ENC_ECON1_TXRTS);
|
||||
enc_release_bus(enc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Finish use of ENC.
|
||||
*
|
||||
* This function entered into eth_device structure.
|
||||
*/
|
||||
static void enc_halt(struct eth_device *dev)
|
||||
{
|
||||
enc_dev_t *enc = dev->priv;
|
||||
|
||||
if (enc_claim_bus(enc))
|
||||
return;
|
||||
/* Just disable receiver */
|
||||
enc_bclr(enc, CTL_REG_ECON1, ENC_ECON1_RXEN);
|
||||
enc_release_bus(enc);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the only exported function.
|
||||
*
|
||||
* It may be called several times with different bus:cs combinations.
|
||||
*/
|
||||
int enc28j60_initialize(unsigned int bus, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int mode)
|
||||
{
|
||||
struct eth_device *dev;
|
||||
enc_dev_t *enc;
|
||||
|
||||
/* try to allocate, check and clear eth_device object */
|
||||
dev = malloc(sizeof(*dev));
|
||||
if (!dev) {
|
||||
return -1;
|
||||
}
|
||||
memset(dev, 0, sizeof(*dev));
|
||||
|
||||
/* try to allocate, check and clear enc_dev_t object */
|
||||
enc = malloc(sizeof(*enc));
|
||||
if (!enc) {
|
||||
free(dev);
|
||||
return -1;
|
||||
}
|
||||
memset(enc, 0, sizeof(*enc));
|
||||
|
||||
/* try to setup the SPI slave */
|
||||
enc->slave = spi_setup_slave(bus, cs, max_hz, mode);
|
||||
if (!enc->slave) {
|
||||
printf("enc28j60: invalid SPI device %i:%i\n", bus, cs);
|
||||
free(enc);
|
||||
free(dev);
|
||||
return -1;
|
||||
}
|
||||
|
||||
enc->dev = dev;
|
||||
/* now fill the eth_device object */
|
||||
dev->priv = enc;
|
||||
dev->init = enc_init;
|
||||
dev->halt = enc_halt;
|
||||
dev->send = enc_send;
|
||||
dev->recv = enc_recv;
|
||||
dev->write_hwaddr = enc_write_hwaddr;
|
||||
sprintf(dev->name, "enc%i.%i", bus, cs);
|
||||
eth_register(dev);
|
||||
#if defined(CONFIG_CMD_MII)
|
||||
int retval;
|
||||
struct mii_dev *mdiodev = mdio_alloc();
|
||||
if (!mdiodev)
|
||||
return -ENOMEM;
|
||||
strncpy(mdiodev->name, dev->name, MDIO_NAME_LEN);
|
||||
mdiodev->read = enc_miiphy_read;
|
||||
mdiodev->write = enc_miiphy_write;
|
||||
|
||||
retval = mdio_register(mdiodev);
|
||||
if (retval < 0)
|
||||
return retval;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
|
@ -1,238 +0,0 @@
|
|||
/*
|
||||
* (X) extracted from enc28j60.c
|
||||
* Reinhard Meyer, EMK Elektronik, reinhard.meyer@emk-elektronik.de
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _enc28j60_h
|
||||
#define _enc28j60_h
|
||||
|
||||
/*
|
||||
* SPI Commands
|
||||
*
|
||||
* Bits 7-5: Command
|
||||
* Bits 4-0: Register
|
||||
*/
|
||||
#define CMD_RCR(x) (0x00+((x)&0x1f)) /* Read Control Register */
|
||||
#define CMD_RBM 0x3a /* Read Buffer Memory */
|
||||
#define CMD_WCR(x) (0x40+((x)&0x1f)) /* Write Control Register */
|
||||
#define CMD_WBM 0x7a /* Write Buffer Memory */
|
||||
#define CMD_BFS(x) (0x80+((x)&0x1f)) /* Bit Field Set */
|
||||
#define CMD_BFC(x) (0xa0+((x)&0x1f)) /* Bit Field Clear */
|
||||
#define CMD_SRC 0xff /* System Reset Command */
|
||||
|
||||
/* NEW: encode (bank number+1) in upper byte */
|
||||
|
||||
/* Common Control Registers accessible in all Banks */
|
||||
#define CTL_REG_EIE 0x01B
|
||||
#define CTL_REG_EIR 0x01C
|
||||
#define CTL_REG_ESTAT 0x01D
|
||||
#define CTL_REG_ECON2 0x01E
|
||||
#define CTL_REG_ECON1 0x01F
|
||||
|
||||
/* Control Registers accessible in Bank 0 */
|
||||
#define CTL_REG_ERDPTL 0x100
|
||||
#define CTL_REG_ERDPTH 0x101
|
||||
#define CTL_REG_EWRPTL 0x102
|
||||
#define CTL_REG_EWRPTH 0x103
|
||||
#define CTL_REG_ETXSTL 0x104
|
||||
#define CTL_REG_ETXSTH 0x105
|
||||
#define CTL_REG_ETXNDL 0x106
|
||||
#define CTL_REG_ETXNDH 0x107
|
||||
#define CTL_REG_ERXSTL 0x108
|
||||
#define CTL_REG_ERXSTH 0x109
|
||||
#define CTL_REG_ERXNDL 0x10A
|
||||
#define CTL_REG_ERXNDH 0x10B
|
||||
#define CTL_REG_ERXRDPTL 0x10C
|
||||
#define CTL_REG_ERXRDPTH 0x10D
|
||||
#define CTL_REG_ERXWRPTL 0x10E
|
||||
#define CTL_REG_ERXWRPTH 0x10F
|
||||
#define CTL_REG_EDMASTL 0x110
|
||||
#define CTL_REG_EDMASTH 0x111
|
||||
#define CTL_REG_EDMANDL 0x112
|
||||
#define CTL_REG_EDMANDH 0x113
|
||||
#define CTL_REG_EDMADSTL 0x114
|
||||
#define CTL_REG_EDMADSTH 0x115
|
||||
#define CTL_REG_EDMACSL 0x116
|
||||
#define CTL_REG_EDMACSH 0x117
|
||||
|
||||
/* Control Registers accessible in Bank 1 */
|
||||
#define CTL_REG_EHT0 0x200
|
||||
#define CTL_REG_EHT1 0x201
|
||||
#define CTL_REG_EHT2 0x202
|
||||
#define CTL_REG_EHT3 0x203
|
||||
#define CTL_REG_EHT4 0x204
|
||||
#define CTL_REG_EHT5 0x205
|
||||
#define CTL_REG_EHT6 0x206
|
||||
#define CTL_REG_EHT7 0x207
|
||||
#define CTL_REG_EPMM0 0x208
|
||||
#define CTL_REG_EPMM1 0x209
|
||||
#define CTL_REG_EPMM2 0x20A
|
||||
#define CTL_REG_EPMM3 0x20B
|
||||
#define CTL_REG_EPMM4 0x20C
|
||||
#define CTL_REG_EPMM5 0x20D
|
||||
#define CTL_REG_EPMM6 0x20E
|
||||
#define CTL_REG_EPMM7 0x20F
|
||||
#define CTL_REG_EPMCSL 0x210
|
||||
#define CTL_REG_EPMCSH 0x211
|
||||
#define CTL_REG_EPMOL 0x214
|
||||
#define CTL_REG_EPMOH 0x215
|
||||
#define CTL_REG_EWOLIE 0x216
|
||||
#define CTL_REG_EWOLIR 0x217
|
||||
#define CTL_REG_ERXFCON 0x218
|
||||
#define CTL_REG_EPKTCNT 0x219
|
||||
|
||||
/* Control Registers accessible in Bank 2 */
|
||||
#define CTL_REG_MACON1 0x300
|
||||
#define CTL_REG_MACON2 0x301
|
||||
#define CTL_REG_MACON3 0x302
|
||||
#define CTL_REG_MACON4 0x303
|
||||
#define CTL_REG_MABBIPG 0x304
|
||||
#define CTL_REG_MAIPGL 0x306
|
||||
#define CTL_REG_MAIPGH 0x307
|
||||
#define CTL_REG_MACLCON1 0x308
|
||||
#define CTL_REG_MACLCON2 0x309
|
||||
#define CTL_REG_MAMXFLL 0x30A
|
||||
#define CTL_REG_MAMXFLH 0x30B
|
||||
#define CTL_REG_MAPHSUP 0x30D
|
||||
#define CTL_REG_MICON 0x311
|
||||
#define CTL_REG_MICMD 0x312
|
||||
#define CTL_REG_MIREGADR 0x314
|
||||
#define CTL_REG_MIWRL 0x316
|
||||
#define CTL_REG_MIWRH 0x317
|
||||
#define CTL_REG_MIRDL 0x318
|
||||
#define CTL_REG_MIRDH 0x319
|
||||
|
||||
/* Control Registers accessible in Bank 3 */
|
||||
#define CTL_REG_MAADR1 0x400
|
||||
#define CTL_REG_MAADR0 0x401
|
||||
#define CTL_REG_MAADR3 0x402
|
||||
#define CTL_REG_MAADR2 0x403
|
||||
#define CTL_REG_MAADR5 0x404
|
||||
#define CTL_REG_MAADR4 0x405
|
||||
#define CTL_REG_EBSTSD 0x406
|
||||
#define CTL_REG_EBSTCON 0x407
|
||||
#define CTL_REG_EBSTCSL 0x408
|
||||
#define CTL_REG_EBSTCSH 0x409
|
||||
#define CTL_REG_MISTAT 0x40A
|
||||
#define CTL_REG_EREVID 0x412
|
||||
#define CTL_REG_ECOCON 0x415
|
||||
#define CTL_REG_EFLOCON 0x417
|
||||
#define CTL_REG_EPAUSL 0x418
|
||||
#define CTL_REG_EPAUSH 0x419
|
||||
|
||||
/* PHY Register */
|
||||
#define PHY_REG_PHCON1 0x00
|
||||
#define PHY_REG_PHSTAT1 0x01
|
||||
#define PHY_REG_PHID1 0x02
|
||||
#define PHY_REG_PHID2 0x03
|
||||
#define PHY_REG_PHCON2 0x10
|
||||
#define PHY_REG_PHSTAT2 0x11
|
||||
#define PHY_REG_PHLCON 0x14
|
||||
|
||||
/* Receive Filter Register (ERXFCON) bits */
|
||||
#define ENC_RFR_UCEN 0x80
|
||||
#define ENC_RFR_ANDOR 0x40
|
||||
#define ENC_RFR_CRCEN 0x20
|
||||
#define ENC_RFR_PMEN 0x10
|
||||
#define ENC_RFR_MPEN 0x08
|
||||
#define ENC_RFR_HTEN 0x04
|
||||
#define ENC_RFR_MCEN 0x02
|
||||
#define ENC_RFR_BCEN 0x01
|
||||
|
||||
/* ECON1 Register Bits */
|
||||
#define ENC_ECON1_TXRST 0x80
|
||||
#define ENC_ECON1_RXRST 0x40
|
||||
#define ENC_ECON1_DMAST 0x20
|
||||
#define ENC_ECON1_CSUMEN 0x10
|
||||
#define ENC_ECON1_TXRTS 0x08
|
||||
#define ENC_ECON1_RXEN 0x04
|
||||
#define ENC_ECON1_BSEL1 0x02
|
||||
#define ENC_ECON1_BSEL0 0x01
|
||||
|
||||
/* ECON2 Register Bits */
|
||||
#define ENC_ECON2_AUTOINC 0x80
|
||||
#define ENC_ECON2_PKTDEC 0x40
|
||||
#define ENC_ECON2_PWRSV 0x20
|
||||
#define ENC_ECON2_VRPS 0x08
|
||||
|
||||
/* EIR Register Bits */
|
||||
#define ENC_EIR_PKTIF 0x40
|
||||
#define ENC_EIR_DMAIF 0x20
|
||||
#define ENC_EIR_LINKIF 0x10
|
||||
#define ENC_EIR_TXIF 0x08
|
||||
#define ENC_EIR_WOLIF 0x04
|
||||
#define ENC_EIR_TXERIF 0x02
|
||||
#define ENC_EIR_RXERIF 0x01
|
||||
|
||||
/* ESTAT Register Bits */
|
||||
#define ENC_ESTAT_INT 0x80
|
||||
#define ENC_ESTAT_LATECOL 0x10
|
||||
#define ENC_ESTAT_RXBUSY 0x04
|
||||
#define ENC_ESTAT_TXABRT 0x02
|
||||
#define ENC_ESTAT_CLKRDY 0x01
|
||||
|
||||
/* EIE Register Bits */
|
||||
#define ENC_EIE_INTIE 0x80
|
||||
#define ENC_EIE_PKTIE 0x40
|
||||
#define ENC_EIE_DMAIE 0x20
|
||||
#define ENC_EIE_LINKIE 0x10
|
||||
#define ENC_EIE_TXIE 0x08
|
||||
#define ENC_EIE_WOLIE 0x04
|
||||
#define ENC_EIE_TXERIE 0x02
|
||||
#define ENC_EIE_RXERIE 0x01
|
||||
|
||||
/* MACON1 Register Bits */
|
||||
#define ENC_MACON1_LOOPBK 0x10
|
||||
#define ENC_MACON1_TXPAUS 0x08
|
||||
#define ENC_MACON1_RXPAUS 0x04
|
||||
#define ENC_MACON1_PASSALL 0x02
|
||||
#define ENC_MACON1_MARXEN 0x01
|
||||
|
||||
/* MACON2 Register Bits */
|
||||
#define ENC_MACON2_MARST 0x80
|
||||
#define ENC_MACON2_RNDRST 0x40
|
||||
#define ENC_MACON2_MARXRST 0x08
|
||||
#define ENC_MACON2_RFUNRST 0x04
|
||||
#define ENC_MACON2_MATXRST 0x02
|
||||
#define ENC_MACON2_TFUNRST 0x01
|
||||
|
||||
/* MACON3 Register Bits */
|
||||
#define ENC_MACON3_PADCFG2 0x80
|
||||
#define ENC_MACON3_PADCFG1 0x40
|
||||
#define ENC_MACON3_PADCFG0 0x20
|
||||
#define ENC_MACON3_TXCRCEN 0x10
|
||||
#define ENC_MACON3_PHDRLEN 0x08
|
||||
#define ENC_MACON3_HFRMEN 0x04
|
||||
#define ENC_MACON3_FRMLNEN 0x02
|
||||
#define ENC_MACON3_FULDPX 0x01
|
||||
|
||||
/* MACON4 Register Bits */
|
||||
#define ENC_MACON4_DEFER 0x40
|
||||
|
||||
/* MICMD Register Bits */
|
||||
#define ENC_MICMD_MIISCAN 0x02
|
||||
#define ENC_MICMD_MIIRD 0x01
|
||||
|
||||
/* MISTAT Register Bits */
|
||||
#define ENC_MISTAT_NVALID 0x04
|
||||
#define ENC_MISTAT_SCAN 0x02
|
||||
#define ENC_MISTAT_BUSY 0x01
|
||||
|
||||
/* PHID1 and PHID2 values */
|
||||
#define ENC_PHID1_VALUE 0x0083
|
||||
#define ENC_PHID2_VALUE 0x1400
|
||||
#define ENC_PHID2_MASK 0xFC00
|
||||
|
||||
/* PHCON1 values */
|
||||
#define ENC_PHCON1_PDPXMD 0x0100
|
||||
|
||||
/* PHSTAT1 values */
|
||||
#define ENC_PHSTAT1_LLSTAT 0x0004
|
||||
|
||||
/* PHSTAT2 values */
|
||||
#define ENC_PHSTAT2_LSTAT 0x0400
|
||||
#define ENC_PHSTAT2_DPXSTAT 0x0200
|
||||
|
||||
#endif
|
|
@ -915,7 +915,7 @@ static int macb_recv(struct eth_device *netdev)
|
|||
if (length >= 0) {
|
||||
net_process_received_packet(packet, length);
|
||||
reclaim_rx_buffers(macb, macb->next_rx_tail);
|
||||
} else if (length < 0) {
|
||||
} else {
|
||||
return length;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5598,6 +5598,10 @@ static int mvpp2_base_bind(struct udevice *parent)
|
|||
id += base_id_add;
|
||||
|
||||
name = calloc(1, 16);
|
||||
if (!name) {
|
||||
free(plat);
|
||||
return -ENOMEM;
|
||||
}
|
||||
sprintf(name, "mvpp2-%d", id);
|
||||
|
||||
/* Create child device UCLASS_ETH and bind it */
|
||||
|
|
12
drivers/net/pfe_eth/Kconfig
Normal file
12
drivers/net/pfe_eth/Kconfig
Normal file
|
@ -0,0 +1,12 @@
|
|||
menuconfig FSL_PFE
|
||||
bool "NXP PFE Ethernet driver"
|
||||
help
|
||||
This driver provides support for NXP's Packet Forwarding Engine.
|
||||
|
||||
if FSL_PFE
|
||||
|
||||
config SYS_FSL_PFE_ADDR
|
||||
hex "PFE base address"
|
||||
default 0x04000000
|
||||
|
||||
endif
|
12
drivers/net/pfe_eth/Makefile
Normal file
12
drivers/net/pfe_eth/Makefile
Normal file
|
@ -0,0 +1,12 @@
|
|||
# Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
# Copyright 2017 NXP
|
||||
#
|
||||
# SPDX-License-Identifier:GPL-2.0+
|
||||
|
||||
# Layerscape PFE driver
|
||||
obj-y += pfe_cmd.o \
|
||||
pfe_driver.o \
|
||||
pfe_eth.o \
|
||||
pfe_firmware.o \
|
||||
pfe_hw.o \
|
||||
pfe_mdio.o
|
497
drivers/net/pfe_eth/pfe_cmd.c
Normal file
497
drivers/net/pfe_eth/pfe_cmd.c
Normal file
|
@ -0,0 +1,497 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file
|
||||
* @brief PFE utility commands
|
||||
*/
|
||||
|
||||
#include <net/pfe_eth/pfe_eth.h>
|
||||
|
||||
static inline void pfe_command_help(void)
|
||||
{
|
||||
printf("Usage: pfe [pe | status | expt ] <options>\n");
|
||||
}
|
||||
|
||||
static void pfe_command_pe(int argc, char * const argv[])
|
||||
{
|
||||
if (argc >= 3 && strcmp(argv[2], "pmem") == 0) {
|
||||
if (argc >= 4 && strcmp(argv[3], "read") == 0) {
|
||||
int i;
|
||||
int num;
|
||||
int id;
|
||||
u32 addr;
|
||||
u32 size;
|
||||
u32 val;
|
||||
|
||||
if (argc == 7) {
|
||||
num = simple_strtoul(argv[6], NULL, 0);
|
||||
} else if (argc == 6) {
|
||||
num = 1;
|
||||
} else {
|
||||
printf("Usage: pfe pe pmem read <id> <addr> [<num>]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
id = simple_strtoul(argv[4], NULL, 0);
|
||||
addr = simple_strtoul(argv[5], NULL, 16);
|
||||
size = 4;
|
||||
|
||||
for (i = 0; i < num; i++, addr += 4) {
|
||||
val = pe_pmem_read(id, addr, size);
|
||||
val = be32_to_cpu(val);
|
||||
if (!(i & 3))
|
||||
printf("%08x: ", addr);
|
||||
printf("%08x%s", val, i == num - 1 || (i & 3)
|
||||
== 3 ? "\n" : " ");
|
||||
}
|
||||
|
||||
} else {
|
||||
printf("Usage: pfe pe pmem read <parameters>\n");
|
||||
}
|
||||
} else if (argc >= 3 && strcmp(argv[2], "dmem") == 0) {
|
||||
if (argc >= 4 && strcmp(argv[3], "read") == 0) {
|
||||
int i;
|
||||
int num;
|
||||
int id;
|
||||
u32 addr;
|
||||
u32 size;
|
||||
u32 val;
|
||||
|
||||
if (argc == 7) {
|
||||
num = simple_strtoul(argv[6], NULL, 0);
|
||||
} else if (argc == 6) {
|
||||
num = 1;
|
||||
} else {
|
||||
printf("Usage: pfe pe dmem read <id> <addr> [<num>]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
id = simple_strtoul(argv[4], NULL, 0);
|
||||
addr = simple_strtoul(argv[5], NULL, 16);
|
||||
size = 4;
|
||||
|
||||
for (i = 0; i < num; i++, addr += 4) {
|
||||
val = pe_dmem_read(id, addr, size);
|
||||
val = be32_to_cpu(val);
|
||||
if (!(i & 3))
|
||||
printf("%08x: ", addr);
|
||||
printf("%08x%s", val, i == num - 1 || (i & 3)
|
||||
== 3 ? "\n" : " ");
|
||||
}
|
||||
|
||||
} else if (argc >= 4 && strcmp(argv[3], "write") == 0) {
|
||||
int id;
|
||||
u32 val;
|
||||
u32 addr;
|
||||
u32 size;
|
||||
|
||||
if (argc != 7) {
|
||||
printf("Usage: pfe pe dmem write <id> <val> <addr>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
id = simple_strtoul(argv[4], NULL, 0);
|
||||
val = simple_strtoul(argv[5], NULL, 16);
|
||||
val = cpu_to_be32(val);
|
||||
addr = simple_strtoul(argv[6], NULL, 16);
|
||||
size = 4;
|
||||
pe_dmem_write(id, val, addr, size);
|
||||
} else {
|
||||
printf("Usage: pfe pe dmem [read | write] <parameters>\n");
|
||||
}
|
||||
} else if (argc >= 3 && strcmp(argv[2], "lmem") == 0) {
|
||||
if (argc >= 4 && strcmp(argv[3], "read") == 0) {
|
||||
int i;
|
||||
int num;
|
||||
u32 val;
|
||||
u32 offset;
|
||||
|
||||
if (argc == 6) {
|
||||
num = simple_strtoul(argv[5], NULL, 0);
|
||||
} else if (argc == 5) {
|
||||
num = 1;
|
||||
} else {
|
||||
printf("Usage: pfe pe lmem read <offset> [<num>]\n");
|
||||
return;
|
||||
}
|
||||
|
||||
offset = simple_strtoul(argv[4], NULL, 16);
|
||||
|
||||
for (i = 0; i < num; i++, offset += 4) {
|
||||
pe_lmem_read(&val, 4, offset);
|
||||
val = be32_to_cpu(val);
|
||||
printf("%08x%s", val, i == num - 1 || (i & 7)
|
||||
== 7 ? "\n" : " ");
|
||||
}
|
||||
|
||||
} else if (argc >= 4 && strcmp(argv[3], "write") == 0) {
|
||||
u32 val;
|
||||
u32 offset;
|
||||
|
||||
if (argc != 6) {
|
||||
printf("Usage: pfe pe lmem write <val> <offset>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
val = simple_strtoul(argv[4], NULL, 16);
|
||||
val = cpu_to_be32(val);
|
||||
offset = simple_strtoul(argv[5], NULL, 16);
|
||||
pe_lmem_write(&val, 4, offset);
|
||||
} else {
|
||||
printf("Usage: pfe pe lmem [read | write] <parameters>\n");
|
||||
}
|
||||
} else {
|
||||
if (strcmp(argv[2], "help") != 0)
|
||||
printf("Unknown option: %s\n", argv[2]);
|
||||
|
||||
printf("Usage: pfe pe <parameters>\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define NUM_QUEUES 16
|
||||
|
||||
/*
|
||||
* qm_read_drop_stat
|
||||
* This function is used to read the drop statistics from the TMU
|
||||
* hw drop counter. Since the hw counter is always cleared afer
|
||||
* reading, this function maintains the previous drop count, and
|
||||
* adds the new value to it. That value can be retrieved by
|
||||
* passing a pointer to it with the total_drops arg.
|
||||
*
|
||||
* @param tmu TMU number (0 - 3)
|
||||
* @param queue queue number (0 - 15)
|
||||
* @param total_drops pointer to location to store total drops (or NULL)
|
||||
* @param do_reset if TRUE, clear total drops after updating
|
||||
*
|
||||
*/
|
||||
u32 qm_read_drop_stat(u32 tmu, u32 queue, u32 *total_drops, int do_reset)
|
||||
{
|
||||
static u32 qtotal[TMU_MAX_ID + 1][NUM_QUEUES];
|
||||
u32 val;
|
||||
|
||||
writel((tmu << 8) | queue, TMU_TEQ_CTRL);
|
||||
writel((tmu << 8) | queue, TMU_LLM_CTRL);
|
||||
val = readl(TMU_TEQ_DROP_STAT);
|
||||
qtotal[tmu][queue] += val;
|
||||
if (total_drops)
|
||||
*total_drops = qtotal[tmu][queue];
|
||||
if (do_reset)
|
||||
qtotal[tmu][queue] = 0;
|
||||
return val;
|
||||
}
|
||||
|
||||
static ssize_t tmu_queue_stats(char *buf, int tmu, int queue)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
u32 drops;
|
||||
|
||||
printf("%d-%02d, ", tmu, queue);
|
||||
|
||||
drops = qm_read_drop_stat(tmu, queue, NULL, 0);
|
||||
|
||||
/* Select queue */
|
||||
writel((tmu << 8) | queue, TMU_TEQ_CTRL);
|
||||
writel((tmu << 8) | queue, TMU_LLM_CTRL);
|
||||
|
||||
printf("(teq) drop: %10u, tx: %10u (llm) head: %08x, tail: %08x, drop: %10u\n",
|
||||
drops, readl(TMU_TEQ_TRANS_STAT),
|
||||
readl(TMU_LLM_QUE_HEADPTR), readl(TMU_LLM_QUE_TAILPTR),
|
||||
readl(TMU_LLM_QUE_DROPCNT));
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t tmu_queues(char *buf, int tmu)
|
||||
{
|
||||
ssize_t len = 0;
|
||||
int queue;
|
||||
|
||||
for (queue = 0; queue < 16; queue++)
|
||||
len += tmu_queue_stats(buf + len, tmu, queue);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static inline void hif_status(void)
|
||||
{
|
||||
printf("hif:\n");
|
||||
|
||||
printf(" tx curr bd: %x\n", readl(HIF_TX_CURR_BD_ADDR));
|
||||
printf(" tx status: %x\n", readl(HIF_TX_STATUS));
|
||||
printf(" tx dma status: %x\n", readl(HIF_TX_DMA_STATUS));
|
||||
|
||||
printf(" rx curr bd: %x\n", readl(HIF_RX_CURR_BD_ADDR));
|
||||
printf(" rx status: %x\n", readl(HIF_RX_STATUS));
|
||||
printf(" rx dma status: %x\n", readl(HIF_RX_DMA_STATUS));
|
||||
|
||||
printf("hif nocopy:\n");
|
||||
|
||||
printf(" tx curr bd: %x\n", readl(HIF_NOCPY_TX_CURR_BD_ADDR));
|
||||
printf(" tx status: %x\n", readl(HIF_NOCPY_TX_STATUS));
|
||||
printf(" tx dma status: %x\n", readl(HIF_NOCPY_TX_DMA_STATUS));
|
||||
|
||||
printf(" rx curr bd: %x\n", readl(HIF_NOCPY_RX_CURR_BD_ADDR));
|
||||
printf(" rx status: %x\n", readl(HIF_NOCPY_RX_STATUS));
|
||||
printf(" rx dma status: %x\n", readl(HIF_NOCPY_RX_DMA_STATUS));
|
||||
}
|
||||
|
||||
static void gpi(int id, void *base)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
printf("%s%d:\n", __func__, id);
|
||||
|
||||
printf(" tx under stick: %x\n", readl(base + GPI_FIFO_STATUS));
|
||||
val = readl(base + GPI_FIFO_DEBUG);
|
||||
printf(" tx pkts: %x\n", (val >> 23) & 0x3f);
|
||||
printf(" rx pkts: %x\n", (val >> 18) & 0x3f);
|
||||
printf(" tx bytes: %x\n", (val >> 9) & 0x1ff);
|
||||
printf(" rx bytes: %x\n", (val >> 0) & 0x1ff);
|
||||
printf(" overrun: %x\n", readl(base + GPI_OVERRUN_DROPCNT));
|
||||
}
|
||||
|
||||
static void bmu(int id, void *base)
|
||||
{
|
||||
printf("%s%d:\n", __func__, id);
|
||||
|
||||
printf(" buf size: %x\n", (1 << readl(base + BMU_BUF_SIZE)));
|
||||
printf(" buf count: %x\n", readl(base + BMU_BUF_CNT));
|
||||
printf(" buf rem: %x\n", readl(base + BMU_REM_BUF_CNT));
|
||||
printf(" buf curr: %x\n", readl(base + BMU_CURR_BUF_CNT));
|
||||
printf(" free err: %x\n", readl(base + BMU_FREE_ERR_ADDR));
|
||||
}
|
||||
|
||||
#define PESTATUS_ADDR_CLASS 0x800
|
||||
#define PEMBOX_ADDR_CLASS 0x890
|
||||
#define PESTATUS_ADDR_TMU 0x80
|
||||
#define PEMBOX_ADDR_TMU 0x290
|
||||
#define PESTATUS_ADDR_UTIL 0x0
|
||||
|
||||
static void pfe_pe_status(int argc, char * const argv[])
|
||||
{
|
||||
int do_clear = 0;
|
||||
u32 id;
|
||||
u32 dmem_addr;
|
||||
u32 cpu_state;
|
||||
u32 activity_counter;
|
||||
u32 rx;
|
||||
u32 tx;
|
||||
u32 drop;
|
||||
char statebuf[5];
|
||||
u32 class_debug_reg = 0;
|
||||
|
||||
if (argc == 4 && strcmp(argv[3], "clear") == 0)
|
||||
do_clear = 1;
|
||||
|
||||
for (id = CLASS0_ID; id < MAX_PE; id++) {
|
||||
if (id >= TMU0_ID) {
|
||||
if (id == TMU2_ID)
|
||||
continue;
|
||||
if (id == TMU0_ID)
|
||||
printf("tmu:\n");
|
||||
dmem_addr = PESTATUS_ADDR_TMU;
|
||||
} else {
|
||||
if (id == CLASS0_ID)
|
||||
printf("class:\n");
|
||||
dmem_addr = PESTATUS_ADDR_CLASS;
|
||||
class_debug_reg = readl(CLASS_PE0_DEBUG + id * 4);
|
||||
}
|
||||
|
||||
cpu_state = pe_dmem_read(id, dmem_addr, 4);
|
||||
dmem_addr += 4;
|
||||
memcpy(statebuf, (char *)&cpu_state, 4);
|
||||
statebuf[4] = '\0';
|
||||
activity_counter = pe_dmem_read(id, dmem_addr, 4);
|
||||
dmem_addr += 4;
|
||||
rx = pe_dmem_read(id, dmem_addr, 4);
|
||||
if (do_clear)
|
||||
pe_dmem_write(id, 0, dmem_addr, 4);
|
||||
dmem_addr += 4;
|
||||
tx = pe_dmem_read(id, dmem_addr, 4);
|
||||
if (do_clear)
|
||||
pe_dmem_write(id, 0, dmem_addr, 4);
|
||||
dmem_addr += 4;
|
||||
drop = pe_dmem_read(id, dmem_addr, 4);
|
||||
if (do_clear)
|
||||
pe_dmem_write(id, 0, dmem_addr, 4);
|
||||
dmem_addr += 4;
|
||||
|
||||
if (id >= TMU0_ID) {
|
||||
printf("%d: state=%4s ctr=%08x rx=%x qstatus=%x\n",
|
||||
id - TMU0_ID, statebuf,
|
||||
cpu_to_be32(activity_counter),
|
||||
cpu_to_be32(rx), cpu_to_be32(tx));
|
||||
} else {
|
||||
printf("%d: pc=1%04x ldst=%04x state=%4s ctr=%08x rx=%x tx=%x drop=%x\n",
|
||||
id - CLASS0_ID, class_debug_reg & 0xFFFF,
|
||||
class_debug_reg >> 16,
|
||||
statebuf, cpu_to_be32(activity_counter),
|
||||
cpu_to_be32(rx), cpu_to_be32(tx),
|
||||
cpu_to_be32(drop));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void pfe_command_status(int argc, char * const argv[])
|
||||
{
|
||||
if (argc >= 3 && strcmp(argv[2], "pe") == 0) {
|
||||
pfe_pe_status(argc, argv);
|
||||
} else if (argc == 3 && strcmp(argv[2], "bmu") == 0) {
|
||||
bmu(1, BMU1_BASE_ADDR);
|
||||
bmu(2, BMU2_BASE_ADDR);
|
||||
} else if (argc == 3 && strcmp(argv[2], "hif") == 0) {
|
||||
hif_status();
|
||||
} else if (argc == 3 && strcmp(argv[2], "gpi") == 0) {
|
||||
gpi(0, EGPI1_BASE_ADDR);
|
||||
gpi(1, EGPI2_BASE_ADDR);
|
||||
gpi(3, HGPI_BASE_ADDR);
|
||||
} else if (argc == 3 && strcmp(argv[2], "tmu0_queues") == 0) {
|
||||
tmu_queues(NULL, 0);
|
||||
} else if (argc == 3 && strcmp(argv[2], "tmu1_queues") == 0) {
|
||||
tmu_queues(NULL, 1);
|
||||
} else if (argc == 3 && strcmp(argv[2], "tmu3_queues") == 0) {
|
||||
tmu_queues(NULL, 3);
|
||||
} else {
|
||||
printf("Usage: pfe status [pe <clear> | bmu | gpi | hif | tmuX_queues ]\n");
|
||||
}
|
||||
}
|
||||
|
||||
#define EXPT_DUMP_ADDR 0x1fa8
|
||||
#define EXPT_REG_COUNT 20
|
||||
static const char *register_names[EXPT_REG_COUNT] = {
|
||||
" pc", "ECAS", " EID", " ED",
|
||||
" sp", " r1", " r2", " r3",
|
||||
" r4", " r5", " r6", " r7",
|
||||
" r8", " r9", " r10", " r11",
|
||||
" r12", " r13", " r14", " r15"
|
||||
};
|
||||
|
||||
static void pfe_command_expt(int argc, char * const argv[])
|
||||
{
|
||||
unsigned int id, i, val, addr;
|
||||
|
||||
if (argc == 3) {
|
||||
id = simple_strtoul(argv[2], NULL, 0);
|
||||
addr = EXPT_DUMP_ADDR;
|
||||
printf("Exception information for PE %d:\n", id);
|
||||
for (i = 0; i < EXPT_REG_COUNT; i++) {
|
||||
val = pe_dmem_read(id, addr, 4);
|
||||
val = be32_to_cpu(val);
|
||||
printf("%s:%08x%s", register_names[i], val,
|
||||
(i & 3) == 3 ? "\n" : " ");
|
||||
addr += 4;
|
||||
}
|
||||
} else {
|
||||
printf("Usage: pfe expt <id>\n");
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef PFE_RESET_WA
|
||||
/*This function sends a dummy packet to HIF through TMU3 */
|
||||
static void send_dummy_pkt_to_hif(void)
|
||||
{
|
||||
u32 buf;
|
||||
static u32 dummy_pkt[] = {
|
||||
0x4200800a, 0x01000003, 0x00018100, 0x00000000,
|
||||
0x33221100, 0x2b785544, 0xd73093cb, 0x01000608,
|
||||
0x04060008, 0x2b780200, 0xd73093cb, 0x0a01a8c0,
|
||||
0x33221100, 0xa8c05544, 0x00000301, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0xbe86c51f };
|
||||
|
||||
/*Allocate BMU2 buffer */
|
||||
buf = readl(BMU2_BASE_ADDR + BMU_ALLOC_CTRL);
|
||||
|
||||
debug("Sending a dummy pkt to HIF %x\n", buf);
|
||||
buf += 0x80;
|
||||
memcpy((void *)DDR_PFE_TO_VIRT(buf), dummy_pkt, sizeof(dummy_pkt));
|
||||
|
||||
/*Write length and pkt to TMU*/
|
||||
writel(0x03000042, TMU_PHY_INQ_PKTPTR);
|
||||
writel(buf, TMU_PHY_INQ_PKTINFO);
|
||||
}
|
||||
|
||||
static void pfe_command_stop(int argc, char * const argv[])
|
||||
{
|
||||
int pfe_pe_id, hif_stop_loop = 10;
|
||||
u32 rx_status;
|
||||
|
||||
printf("Stopping PFE...\n");
|
||||
|
||||
/*Mark all descriptors as LAST_BD */
|
||||
hif_rx_desc_disable();
|
||||
|
||||
/*If HIF Rx BDP is busy send a dummy packet */
|
||||
do {
|
||||
rx_status = readl(HIF_RX_STATUS);
|
||||
if (rx_status & BDP_CSR_RX_DMA_ACTV)
|
||||
send_dummy_pkt_to_hif();
|
||||
udelay(10);
|
||||
} while (hif_stop_loop--);
|
||||
|
||||
if (readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV)
|
||||
printf("Unable to stop HIF\n");
|
||||
|
||||
/*Disable Class PEs */
|
||||
for (pfe_pe_id = CLASS0_ID; pfe_pe_id <= CLASS_MAX_ID; pfe_pe_id++) {
|
||||
/*Inform PE to stop */
|
||||
pe_dmem_write(pfe_pe_id, cpu_to_be32(1), PEMBOX_ADDR_CLASS, 4);
|
||||
udelay(10);
|
||||
|
||||
/*Read status */
|
||||
if (!pe_dmem_read(pfe_pe_id, PEMBOX_ADDR_CLASS + 4, 4))
|
||||
printf("Failed to stop PE%d\n", pfe_pe_id);
|
||||
}
|
||||
|
||||
/*Disable TMU PEs */
|
||||
for (pfe_pe_id = TMU0_ID; pfe_pe_id <= TMU_MAX_ID; pfe_pe_id++) {
|
||||
if (pfe_pe_id == TMU2_ID)
|
||||
continue;
|
||||
|
||||
/*Inform PE to stop */
|
||||
pe_dmem_write(pfe_pe_id, 1, PEMBOX_ADDR_TMU, 4);
|
||||
udelay(10);
|
||||
|
||||
/*Read status */
|
||||
if (!pe_dmem_read(pfe_pe_id, PEMBOX_ADDR_TMU + 4, 4))
|
||||
printf("Failed to stop PE%d\n", pfe_pe_id);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static int pfe_command(cmd_tbl_t *cmdtp, int flag, int argc,
|
||||
char * const argv[])
|
||||
{
|
||||
if (argc == 1 || strcmp(argv[1], "help") == 0) {
|
||||
pfe_command_help();
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
if (strcmp(argv[1], "pe") == 0) {
|
||||
pfe_command_pe(argc, argv);
|
||||
} else if (strcmp(argv[1], "status") == 0) {
|
||||
pfe_command_status(argc, argv);
|
||||
} else if (strcmp(argv[1], "expt") == 0) {
|
||||
pfe_command_expt(argc, argv);
|
||||
#ifdef PFE_RESET_WA
|
||||
} else if (strcmp(argv[1], "stop") == 0) {
|
||||
pfe_command_stop(argc, argv);
|
||||
#endif
|
||||
} else {
|
||||
printf("Unknown option: %s\n", argv[1]);
|
||||
pfe_command_help();
|
||||
return CMD_RET_FAILURE;
|
||||
}
|
||||
return CMD_RET_SUCCESS;
|
||||
}
|
||||
|
||||
U_BOOT_CMD(
|
||||
pfe, 7, 1, pfe_command,
|
||||
"Performs PFE lib utility functions",
|
||||
"Usage:\n"
|
||||
"pfe <options>"
|
||||
);
|
643
drivers/net/pfe_eth/pfe_driver.c
Normal file
643
drivers/net/pfe_eth/pfe_driver.c
Normal file
|
@ -0,0 +1,643 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <net/pfe_eth/pfe_eth.h>
|
||||
#include <net/pfe_eth/pfe_firmware.h>
|
||||
|
||||
static struct tx_desc_s *g_tx_desc;
|
||||
static struct rx_desc_s *g_rx_desc;
|
||||
|
||||
/*
|
||||
* HIF Rx interface function
|
||||
* Reads the rx descriptor from the current location (rx_to_read).
|
||||
* - If the descriptor has a valid data/pkt, then get the data pointer
|
||||
* - check for the input rx phy number
|
||||
* - increment the rx data pointer by pkt_head_room_size
|
||||
* - decrement the data length by pkt_head_room_size
|
||||
* - handover the packet to caller.
|
||||
*
|
||||
* @param[out] pkt_ptr - Pointer to store rx packet
|
||||
* @param[out] phy_port - Pointer to store recv phy port
|
||||
*
|
||||
* @return -1 if no packet, else return length of packet.
|
||||
*/
|
||||
int pfe_recv(uchar **pkt_ptr, int *phy_port)
|
||||
{
|
||||
struct rx_desc_s *rx_desc = g_rx_desc;
|
||||
struct buf_desc *bd;
|
||||
int len = 0;
|
||||
|
||||
struct hif_header_s *hif_header;
|
||||
|
||||
bd = rx_desc->rx_base + rx_desc->rx_to_read;
|
||||
|
||||
if (readl(&bd->ctrl) & BD_CTRL_DESC_EN)
|
||||
return len; /* No pending Rx packet */
|
||||
|
||||
/* this len include hif_header(8 bytes) */
|
||||
len = readl(&bd->ctrl) & 0xFFFF;
|
||||
|
||||
hif_header = (struct hif_header_s *)DDR_PFE_TO_VIRT(readl(&bd->data));
|
||||
|
||||
/* Get the receive port info from the packet */
|
||||
debug("Pkt received:");
|
||||
debug(" Pkt ptr(%p), len(%d), gemac_port(%d) status(%08x)\n",
|
||||
hif_header, len, hif_header->port_no, readl(&bd->status));
|
||||
#ifdef DEBUG
|
||||
{
|
||||
int i;
|
||||
unsigned char *p = (unsigned char *)hif_header;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
if (!(i % 16))
|
||||
printf("\n");
|
||||
printf(" %02x", p[i]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
*pkt_ptr = (uchar *)(hif_header + 1);
|
||||
*phy_port = hif_header->port_no;
|
||||
len -= sizeof(struct hif_header_s);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
/*
|
||||
* HIF function to check the Rx done
|
||||
* This function will check the rx done indication of the current rx_to_read
|
||||
* locations
|
||||
* if success, moves the rx_to_read to next location.
|
||||
*/
|
||||
int pfe_eth_free_pkt(struct udevice *dev, uchar *packet, int length)
|
||||
{
|
||||
struct rx_desc_s *rx_desc = g_rx_desc;
|
||||
struct buf_desc *bd;
|
||||
|
||||
debug("%s:rx_base: %p, rx_to_read: %d\n", __func__, rx_desc->rx_base,
|
||||
rx_desc->rx_to_read);
|
||||
|
||||
bd = rx_desc->rx_base + rx_desc->rx_to_read;
|
||||
|
||||
/* reset the control field */
|
||||
writel((MAX_FRAME_SIZE | BD_CTRL_LIFM | BD_CTRL_DESC_EN
|
||||
| BD_CTRL_DIR), &bd->ctrl);
|
||||
writel(0, &bd->status);
|
||||
|
||||
debug("Rx Done : status: %08x, ctrl: %08x\n", readl(&bd->status),
|
||||
readl(&bd->ctrl));
|
||||
|
||||
/* Give START_STROBE to BDP to fetch the descriptor __NOW__,
|
||||
* BDP need not wait for rx_poll_cycle time to fetch the descriptor,
|
||||
* In idle state (ie., no rx pkt), BDP will not fetch
|
||||
* the descriptor even if strobe is given.
|
||||
*/
|
||||
writel((readl(HIF_RX_CTRL) | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL);
|
||||
|
||||
/* increment the rx_to_read index to next location */
|
||||
rx_desc->rx_to_read = (rx_desc->rx_to_read + 1)
|
||||
& (rx_desc->rx_ring_size - 1);
|
||||
|
||||
debug("Rx next pkt location: %d\n", rx_desc->rx_to_read);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* HIF Tx interface function
|
||||
* This function sends a single packet to PFE from HIF interface.
|
||||
* - No interrupt indication on tx completion.
|
||||
* - Data is copied to tx buffers before tx descriptor is updated
|
||||
* and TX DMA is enabled.
|
||||
*
|
||||
* @param[in] phy_port Phy port number to send out this packet
|
||||
* @param[in] data Pointer to the data
|
||||
* @param[in] length Length of the ethernet packet to be transferred.
|
||||
*
|
||||
* @return -1 if tx Q is full, else returns the tx location where the pkt is
|
||||
* placed.
|
||||
*/
|
||||
int pfe_send(int phy_port, void *data, int length)
|
||||
{
|
||||
struct tx_desc_s *tx_desc = g_tx_desc;
|
||||
struct buf_desc *bd;
|
||||
struct hif_header_s hif_header;
|
||||
u8 *tx_buf_va;
|
||||
|
||||
debug("%s:pkt: %p, len: %d, tx_base: %p, tx_to_send: %d\n", __func__,
|
||||
data, length, tx_desc->tx_base, tx_desc->tx_to_send);
|
||||
|
||||
bd = tx_desc->tx_base + tx_desc->tx_to_send;
|
||||
|
||||
/* check queue-full condition */
|
||||
if (readl(&bd->ctrl) & BD_CTRL_DESC_EN)
|
||||
return -1;
|
||||
|
||||
/* PFE checks for min pkt size */
|
||||
if (length < MIN_PKT_SIZE)
|
||||
length = MIN_PKT_SIZE;
|
||||
|
||||
tx_buf_va = (void *)DDR_PFE_TO_VIRT(readl(&bd->data));
|
||||
debug("%s: tx_buf_va: %p, tx_buf_pa: %08x\n", __func__, tx_buf_va,
|
||||
readl(&bd->data));
|
||||
|
||||
/* Fill the gemac/phy port number to send this packet out */
|
||||
memset(&hif_header, 0, sizeof(struct hif_header_s));
|
||||
hif_header.port_no = phy_port;
|
||||
|
||||
memcpy(tx_buf_va, (u8 *)&hif_header, sizeof(struct hif_header_s));
|
||||
memcpy(tx_buf_va + sizeof(struct hif_header_s), data, length);
|
||||
length += sizeof(struct hif_header_s);
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
int i;
|
||||
unsigned char *p = (unsigned char *)tx_buf_va;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
if (!(i % 16))
|
||||
printf("\n");
|
||||
printf("%02x ", p[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
debug("Tx Done: status: %08x, ctrl: %08x\n", readl(&bd->status),
|
||||
readl(&bd->ctrl));
|
||||
|
||||
/* fill the tx desc */
|
||||
writel((u32)(BD_CTRL_DESC_EN | BD_CTRL_LIFM | (length & 0xFFFF)),
|
||||
&bd->ctrl);
|
||||
writel(0, &bd->status);
|
||||
|
||||
writel((HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB), HIF_TX_CTRL);
|
||||
|
||||
udelay(100);
|
||||
|
||||
return tx_desc->tx_to_send;
|
||||
}
|
||||
|
||||
/*
|
||||
* HIF function to check the Tx done
|
||||
* This function will check the tx done indication of the current tx_to_send
|
||||
* locations
|
||||
* if success, moves the tx_to_send to next location.
|
||||
*
|
||||
* @return -1 if TX ownership bit is not cleared by hw.
|
||||
* else on success (tx done completion) return zero.
|
||||
*/
|
||||
int pfe_tx_done(void)
|
||||
{
|
||||
struct tx_desc_s *tx_desc = g_tx_desc;
|
||||
struct buf_desc *bd;
|
||||
|
||||
debug("%s:tx_base: %p, tx_to_send: %d\n", __func__, tx_desc->tx_base,
|
||||
tx_desc->tx_to_send);
|
||||
|
||||
bd = tx_desc->tx_base + tx_desc->tx_to_send;
|
||||
|
||||
/* check queue-full condition */
|
||||
if (readl(&bd->ctrl) & BD_CTRL_DESC_EN)
|
||||
return -1;
|
||||
|
||||
/* reset the control field */
|
||||
writel(0, &bd->ctrl);
|
||||
writel(0, &bd->status);
|
||||
|
||||
debug("Tx Done : status: %08x, ctrl: %08x\n", readl(&bd->status),
|
||||
readl(&bd->ctrl));
|
||||
|
||||
/* increment the txtosend index to next location */
|
||||
tx_desc->tx_to_send = (tx_desc->tx_to_send + 1)
|
||||
& (tx_desc->tx_ring_size - 1);
|
||||
|
||||
debug("Tx next pkt location: %d\n", tx_desc->tx_to_send);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to dump Rx descriptors.
|
||||
*/
|
||||
static inline void hif_rx_desc_dump(void)
|
||||
{
|
||||
struct buf_desc *bd_va;
|
||||
int i;
|
||||
struct rx_desc_s *rx_desc;
|
||||
|
||||
if (!g_rx_desc) {
|
||||
printf("%s: HIF Rx desc no init\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rx_desc = g_rx_desc;
|
||||
bd_va = rx_desc->rx_base;
|
||||
|
||||
debug("HIF rx desc: base_va: %p, base_pa: %08x\n", rx_desc->rx_base,
|
||||
rx_desc->rx_base_pa);
|
||||
for (i = 0; i < rx_desc->rx_ring_size; i++) {
|
||||
debug("status: %08x, ctrl: %08x, data: %08x, next: 0x%08x\n",
|
||||
readl(&bd_va->status),
|
||||
readl(&bd_va->ctrl),
|
||||
readl(&bd_va->data),
|
||||
readl(&bd_va->next));
|
||||
bd_va++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function mark all Rx descriptors as LAST_BD.
|
||||
*/
|
||||
void hif_rx_desc_disable(void)
|
||||
{
|
||||
int i;
|
||||
struct rx_desc_s *rx_desc;
|
||||
struct buf_desc *bd_va;
|
||||
|
||||
if (!g_rx_desc) {
|
||||
printf("%s: HIF Rx desc not initialized\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
rx_desc = g_rx_desc;
|
||||
bd_va = rx_desc->rx_base;
|
||||
|
||||
for (i = 0; i < rx_desc->rx_ring_size; i++) {
|
||||
writel(readl(&bd_va->ctrl) | BD_CTRL_LAST_BD, &bd_va->ctrl);
|
||||
bd_va++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* HIF Rx Desc initialization function.
|
||||
*/
|
||||
static int hif_rx_desc_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
u32 ctrl;
|
||||
struct buf_desc *bd_va;
|
||||
struct buf_desc *bd_pa;
|
||||
struct rx_desc_s *rx_desc;
|
||||
u32 rx_buf_pa;
|
||||
int i;
|
||||
|
||||
/* sanity check */
|
||||
if (g_rx_desc) {
|
||||
printf("%s: HIF Rx desc re-init request\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
rx_desc = (struct rx_desc_s *)malloc(sizeof(struct rx_desc_s));
|
||||
if (!rx_desc) {
|
||||
printf("%s: Memory allocation failure\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(rx_desc, 0, sizeof(struct rx_desc_s));
|
||||
|
||||
/* init: Rx ring buffer */
|
||||
rx_desc->rx_ring_size = HIF_RX_DESC_NT;
|
||||
|
||||
/* NOTE: must be 64bit aligned */
|
||||
bd_va = (struct buf_desc *)(pfe_addr->ddr_pfe_baseaddr
|
||||
+ RX_BD_BASEADDR);
|
||||
bd_pa = (struct buf_desc *)(pfe_addr->ddr_pfe_phys_baseaddr
|
||||
+ RX_BD_BASEADDR);
|
||||
|
||||
rx_desc->rx_base = bd_va;
|
||||
rx_desc->rx_base_pa = (unsigned long)bd_pa;
|
||||
|
||||
rx_buf_pa = pfe_addr->ddr_pfe_phys_baseaddr + HIF_RX_PKT_DDR_BASEADDR;
|
||||
|
||||
debug("%s: Rx desc base: %p, base_pa: %08x, desc_count: %d\n",
|
||||
__func__, rx_desc->rx_base, rx_desc->rx_base_pa,
|
||||
rx_desc->rx_ring_size);
|
||||
|
||||
memset(bd_va, 0, sizeof(struct buf_desc) * rx_desc->rx_ring_size);
|
||||
|
||||
ctrl = (MAX_FRAME_SIZE | BD_CTRL_DESC_EN | BD_CTRL_DIR | BD_CTRL_LIFM);
|
||||
|
||||
for (i = 0; i < rx_desc->rx_ring_size; i++) {
|
||||
writel((unsigned long)(bd_pa + 1), &bd_va->next);
|
||||
writel(ctrl, &bd_va->ctrl);
|
||||
writel(rx_buf_pa + (i * MAX_FRAME_SIZE), &bd_va->data);
|
||||
bd_va++;
|
||||
bd_pa++;
|
||||
}
|
||||
--bd_va;
|
||||
writel((u32)rx_desc->rx_base_pa, &bd_va->next);
|
||||
|
||||
writel(rx_desc->rx_base_pa, HIF_RX_BDP_ADDR);
|
||||
writel((readl(HIF_RX_CTRL) | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL);
|
||||
|
||||
g_rx_desc = rx_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper function to dump Tx Descriptors.
|
||||
*/
|
||||
static inline void hif_tx_desc_dump(void)
|
||||
{
|
||||
struct tx_desc_s *tx_desc;
|
||||
int i;
|
||||
struct buf_desc *bd_va;
|
||||
|
||||
if (!g_tx_desc) {
|
||||
printf("%s: HIF Tx desc no init\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
tx_desc = g_tx_desc;
|
||||
bd_va = tx_desc->tx_base;
|
||||
|
||||
debug("HIF tx desc: base_va: %p, base_pa: %08x\n", tx_desc->tx_base,
|
||||
tx_desc->tx_base_pa);
|
||||
|
||||
for (i = 0; i < tx_desc->tx_ring_size; i++)
|
||||
bd_va++;
|
||||
}
|
||||
|
||||
/*
|
||||
* HIF Tx descriptor initialization function.
|
||||
*/
|
||||
static int hif_tx_desc_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
struct buf_desc *bd_va;
|
||||
struct buf_desc *bd_pa;
|
||||
int i;
|
||||
struct tx_desc_s *tx_desc;
|
||||
u32 tx_buf_pa;
|
||||
|
||||
/* sanity check */
|
||||
if (g_tx_desc) {
|
||||
printf("%s: HIF Tx desc re-init request\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
tx_desc = (struct tx_desc_s *)malloc(sizeof(struct tx_desc_s));
|
||||
if (!tx_desc) {
|
||||
printf("%s:%d:Memory allocation failure\n", __func__,
|
||||
__LINE__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
memset(tx_desc, 0, sizeof(struct tx_desc_s));
|
||||
|
||||
/* init: Tx ring buffer */
|
||||
tx_desc->tx_ring_size = HIF_TX_DESC_NT;
|
||||
|
||||
/* NOTE: must be 64bit aligned */
|
||||
bd_va = (struct buf_desc *)(pfe_addr->ddr_pfe_baseaddr
|
||||
+ TX_BD_BASEADDR);
|
||||
bd_pa = (struct buf_desc *)(pfe_addr->ddr_pfe_phys_baseaddr
|
||||
+ TX_BD_BASEADDR);
|
||||
|
||||
tx_desc->tx_base_pa = (unsigned long)bd_pa;
|
||||
tx_desc->tx_base = bd_va;
|
||||
|
||||
debug("%s: Tx desc_base: %p, base_pa: %08x, desc_count: %d\n",
|
||||
__func__, tx_desc->tx_base, tx_desc->tx_base_pa,
|
||||
tx_desc->tx_ring_size);
|
||||
|
||||
memset(bd_va, 0, sizeof(struct buf_desc) * tx_desc->tx_ring_size);
|
||||
|
||||
tx_buf_pa = pfe_addr->ddr_pfe_phys_baseaddr + HIF_TX_PKT_DDR_BASEADDR;
|
||||
|
||||
for (i = 0; i < tx_desc->tx_ring_size; i++) {
|
||||
writel((unsigned long)(bd_pa + 1), &bd_va->next);
|
||||
writel(tx_buf_pa + (i * MAX_FRAME_SIZE), &bd_va->data);
|
||||
bd_va++;
|
||||
bd_pa++;
|
||||
}
|
||||
--bd_va;
|
||||
writel((u32)tx_desc->tx_base_pa, &bd_va->next);
|
||||
|
||||
writel(tx_desc->tx_base_pa, HIF_TX_BDP_ADDR);
|
||||
|
||||
g_tx_desc = tx_desc;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE/Class initialization.
|
||||
*/
|
||||
static void pfe_class_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
struct class_cfg class_cfg = {
|
||||
.route_table_baseaddr = pfe_addr->ddr_pfe_phys_baseaddr +
|
||||
ROUTE_TABLE_BASEADDR,
|
||||
.route_table_hash_bits = ROUTE_TABLE_HASH_BITS,
|
||||
};
|
||||
|
||||
class_init(&class_cfg);
|
||||
|
||||
debug("class init complete\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE/TMU initialization.
|
||||
*/
|
||||
static void pfe_tmu_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
struct tmu_cfg tmu_cfg = {
|
||||
.llm_base_addr = pfe_addr->ddr_pfe_phys_baseaddr
|
||||
+ TMU_LLM_BASEADDR,
|
||||
.llm_queue_len = TMU_LLM_QUEUE_LEN,
|
||||
};
|
||||
|
||||
tmu_init(&tmu_cfg);
|
||||
|
||||
debug("tmu init complete\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE/BMU (both BMU1 & BMU2) initialization.
|
||||
*/
|
||||
static void pfe_bmu_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
struct bmu_cfg bmu1_cfg = {
|
||||
.baseaddr = CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR +
|
||||
BMU1_LMEM_BASEADDR),
|
||||
.count = BMU1_BUF_COUNT,
|
||||
.size = BMU1_BUF_SIZE,
|
||||
};
|
||||
|
||||
struct bmu_cfg bmu2_cfg = {
|
||||
.baseaddr = pfe_addr->ddr_pfe_phys_baseaddr + BMU2_DDR_BASEADDR,
|
||||
.count = BMU2_BUF_COUNT,
|
||||
.size = BMU2_BUF_SIZE,
|
||||
};
|
||||
|
||||
bmu_init(BMU1_BASE_ADDR, &bmu1_cfg);
|
||||
debug("bmu1 init: done\n");
|
||||
|
||||
bmu_init(BMU2_BASE_ADDR, &bmu2_cfg);
|
||||
debug("bmu2 init: done\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE/GPI initialization function.
|
||||
* - egpi1, egpi2, egpi3, hgpi
|
||||
*/
|
||||
static void pfe_gpi_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
struct gpi_cfg egpi1_cfg = {
|
||||
.lmem_rtry_cnt = EGPI1_LMEM_RTRY_CNT,
|
||||
.tmlf_txthres = EGPI1_TMLF_TXTHRES,
|
||||
.aseq_len = EGPI1_ASEQ_LEN,
|
||||
};
|
||||
|
||||
struct gpi_cfg egpi2_cfg = {
|
||||
.lmem_rtry_cnt = EGPI2_LMEM_RTRY_CNT,
|
||||
.tmlf_txthres = EGPI2_TMLF_TXTHRES,
|
||||
.aseq_len = EGPI2_ASEQ_LEN,
|
||||
};
|
||||
|
||||
struct gpi_cfg hgpi_cfg = {
|
||||
.lmem_rtry_cnt = HGPI_LMEM_RTRY_CNT,
|
||||
.tmlf_txthres = HGPI_TMLF_TXTHRES,
|
||||
.aseq_len = HGPI_ASEQ_LEN,
|
||||
};
|
||||
|
||||
gpi_init(EGPI1_BASE_ADDR, &egpi1_cfg);
|
||||
debug("GPI1 init complete\n");
|
||||
|
||||
gpi_init(EGPI2_BASE_ADDR, &egpi2_cfg);
|
||||
debug("GPI2 init complete\n");
|
||||
|
||||
gpi_init(HGPI_BASE_ADDR, &hgpi_cfg);
|
||||
debug("HGPI init complete\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE/HIF initialization function.
|
||||
*/
|
||||
static int pfe_hif_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
hif_tx_disable();
|
||||
hif_rx_disable();
|
||||
|
||||
ret = hif_tx_desc_init(pfe_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
ret = hif_rx_desc_init(pfe_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
hif_init();
|
||||
|
||||
hif_tx_enable();
|
||||
hif_rx_enable();
|
||||
|
||||
hif_rx_desc_dump();
|
||||
hif_tx_desc_dump();
|
||||
|
||||
debug("HIF init complete\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE initialization
|
||||
* - Firmware loading (CLASS-PE and TMU-PE)
|
||||
* - BMU1 and BMU2 init
|
||||
* - GEMAC init
|
||||
* - GPI init
|
||||
* - CLASS-PE init
|
||||
* - TMU-PE init
|
||||
* - HIF tx and rx descriptors init
|
||||
*
|
||||
* @param[in] edev Pointer to eth device structure.
|
||||
*
|
||||
* @return 0, on success.
|
||||
*/
|
||||
static int pfe_hw_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
debug("%s: start\n", __func__);
|
||||
|
||||
writel(0x3, CLASS_PE_SYS_CLK_RATIO);
|
||||
writel(0x3, TMU_PE_SYS_CLK_RATIO);
|
||||
writel(0x3, UTIL_PE_SYS_CLK_RATIO);
|
||||
udelay(10);
|
||||
|
||||
pfe_class_init(pfe_addr);
|
||||
|
||||
pfe_tmu_init(pfe_addr);
|
||||
|
||||
pfe_bmu_init(pfe_addr);
|
||||
|
||||
pfe_gpi_init(pfe_addr);
|
||||
|
||||
ret = pfe_hif_init(pfe_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
bmu_enable(BMU1_BASE_ADDR);
|
||||
debug("bmu1 enabled\n");
|
||||
|
||||
bmu_enable(BMU2_BASE_ADDR);
|
||||
debug("bmu2 enabled\n");
|
||||
|
||||
debug("%s: done\n", __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE driver init function.
|
||||
* - Initializes pfe_lib
|
||||
* - pfe hw init
|
||||
* - fw loading and enables PEs
|
||||
* - should be executed once.
|
||||
*
|
||||
* @param[in] pfe Pointer the pfe control block
|
||||
*/
|
||||
int pfe_drv_init(struct pfe_ddr_address *pfe_addr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pfe_lib_init();
|
||||
|
||||
ret = pfe_hw_init(pfe_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Load the class,TM, Util fw.
|
||||
* By now pfe is:
|
||||
* - out of reset + disabled + configured.
|
||||
* Fw loading should be done after pfe_hw_init()
|
||||
*/
|
||||
/* It loads default inbuilt sbl firmware */
|
||||
pfe_firmware_init();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE remove function
|
||||
* - stops PEs
|
||||
* - frees tx/rx descriptor resources
|
||||
* - should be called once.
|
||||
*
|
||||
* @param[in] pfe Pointer to pfe control block.
|
||||
*/
|
||||
int pfe_eth_remove(struct udevice *dev)
|
||||
{
|
||||
if (g_tx_desc)
|
||||
free(g_tx_desc);
|
||||
|
||||
if (g_rx_desc)
|
||||
free(g_rx_desc);
|
||||
|
||||
pfe_firmware_exit();
|
||||
|
||||
return 0;
|
||||
}
|
297
drivers/net/pfe_eth/pfe_eth.c
Normal file
297
drivers/net/pfe_eth/pfe_eth.c
Normal file
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/platform_data/pfe_dm_eth.h>
|
||||
#include <net.h>
|
||||
#include <net/pfe_eth/pfe_eth.h>
|
||||
#include <net/pfe_eth/pfe_mdio.h>
|
||||
|
||||
struct gemac_s gem_info[] = {
|
||||
/* PORT_0 configuration */
|
||||
{
|
||||
/* GEMAC config */
|
||||
.gemac_speed = PFE_MAC_SPEED_1000M,
|
||||
.gemac_duplex = DUPLEX_FULL,
|
||||
|
||||
/* phy iface */
|
||||
.phy_address = CONFIG_PFE_EMAC1_PHY_ADDR,
|
||||
.phy_mode = PHY_INTERFACE_MODE_SGMII,
|
||||
},
|
||||
/* PORT_1 configuration */
|
||||
{
|
||||
/* GEMAC config */
|
||||
.gemac_speed = PFE_MAC_SPEED_1000M,
|
||||
.gemac_duplex = DUPLEX_FULL,
|
||||
|
||||
/* phy iface */
|
||||
.phy_address = CONFIG_PFE_EMAC2_PHY_ADDR,
|
||||
.phy_mode = PHY_INTERFACE_MODE_RGMII_TXID,
|
||||
},
|
||||
};
|
||||
|
||||
static inline void pfe_gemac_enable(void *gemac_base)
|
||||
{
|
||||
writel(readl(gemac_base + EMAC_ECNTRL_REG) |
|
||||
EMAC_ECNTRL_ETHER_EN, gemac_base + EMAC_ECNTRL_REG);
|
||||
}
|
||||
|
||||
static inline void pfe_gemac_disable(void *gemac_base)
|
||||
{
|
||||
writel(readl(gemac_base + EMAC_ECNTRL_REG) &
|
||||
~EMAC_ECNTRL_ETHER_EN, gemac_base + EMAC_ECNTRL_REG);
|
||||
}
|
||||
|
||||
static inline void pfe_gemac_set_speed(void *gemac_base, u32 speed)
|
||||
{
|
||||
struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
u32 ecr = readl(gemac_base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_SPEED;
|
||||
u32 rcr = readl(gemac_base + EMAC_RCNTRL_REG) & ~EMAC_RCNTRL_RMII_10T;
|
||||
u32 rgmii_pcr = in_be32(&scfg->rgmiipcr) &
|
||||
~(SCFG_RGMIIPCR_SETSP_1000M | SCFG_RGMIIPCR_SETSP_10M);
|
||||
|
||||
if (speed == _1000BASET) {
|
||||
ecr |= EMAC_ECNTRL_SPEED;
|
||||
rgmii_pcr |= SCFG_RGMIIPCR_SETSP_1000M;
|
||||
} else if (speed != _100BASET) {
|
||||
rcr |= EMAC_RCNTRL_RMII_10T;
|
||||
rgmii_pcr |= SCFG_RGMIIPCR_SETSP_10M;
|
||||
}
|
||||
|
||||
writel(ecr, gemac_base + EMAC_ECNTRL_REG);
|
||||
out_be32(&scfg->rgmiipcr, rgmii_pcr | SCFG_RGMIIPCR_SETFD);
|
||||
|
||||
/* remove loop back */
|
||||
rcr &= ~EMAC_RCNTRL_LOOP;
|
||||
/* enable flow control */
|
||||
rcr |= EMAC_RCNTRL_FCE;
|
||||
|
||||
/* Enable MII mode */
|
||||
rcr |= EMAC_RCNTRL_MII_MODE;
|
||||
|
||||
writel(rcr, gemac_base + EMAC_RCNTRL_REG);
|
||||
|
||||
/* Enable Tx full duplex */
|
||||
writel(readl(gemac_base + EMAC_TCNTRL_REG) | EMAC_TCNTRL_FDEN,
|
||||
gemac_base + EMAC_TCNTRL_REG);
|
||||
}
|
||||
|
||||
static int pfe_eth_write_hwaddr(struct udevice *dev)
|
||||
{
|
||||
struct pfe_eth_dev *priv = dev_get_priv(dev);
|
||||
struct gemac_s *gem = priv->gem;
|
||||
struct eth_pdata *pdata = dev_get_platdata(dev);
|
||||
uchar *mac = pdata->enetaddr;
|
||||
|
||||
writel((mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3],
|
||||
gem->gemac_base + EMAC_PHY_ADDR_LOW);
|
||||
writel((mac[4] << 24) + (mac[5] << 16) + 0x8808, gem->gemac_base +
|
||||
EMAC_PHY_ADDR_HIGH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Stops or Disables GEMAC pointing to this eth iface.
|
||||
*
|
||||
* @param[in] edev Pointer to eth device structure.
|
||||
*
|
||||
* @return none
|
||||
*/
|
||||
static inline void pfe_eth_stop(struct udevice *dev)
|
||||
{
|
||||
struct pfe_eth_dev *priv = dev_get_priv(dev);
|
||||
|
||||
pfe_gemac_disable(priv->gem->gemac_base);
|
||||
|
||||
gpi_disable(priv->gem->egpi_base);
|
||||
}
|
||||
|
||||
static int pfe_eth_start(struct udevice *dev)
|
||||
{
|
||||
struct pfe_eth_dev *priv = dev_get_priv(dev);
|
||||
struct gemac_s *gem = priv->gem;
|
||||
int speed;
|
||||
|
||||
/* set ethernet mac address */
|
||||
pfe_eth_write_hwaddr(dev);
|
||||
|
||||
writel(EMAC_TFWR, gem->gemac_base + EMAC_TFWR_STR_FWD);
|
||||
writel(EMAC_RX_SECTION_FULL_32, gem->gemac_base + EMAC_RX_SECTIOM_FULL);
|
||||
writel(EMAC_TRUNC_FL_16K, gem->gemac_base + EMAC_TRUNC_FL);
|
||||
writel(EMAC_TX_SECTION_EMPTY_30, gem->gemac_base
|
||||
+ EMAC_TX_SECTION_EMPTY);
|
||||
writel(EMAC_MIBC_NO_CLR_NO_DIS, gem->gemac_base
|
||||
+ EMAC_MIB_CTRL_STS_REG);
|
||||
|
||||
#ifdef CONFIG_PHYLIB
|
||||
/* Start up the PHY */
|
||||
if (phy_startup(priv->phydev)) {
|
||||
printf("Could not initialize PHY %s\n",
|
||||
priv->phydev->dev->name);
|
||||
return -1;
|
||||
}
|
||||
speed = priv->phydev->speed;
|
||||
printf("Speed detected %x\n", speed);
|
||||
if (priv->phydev->duplex == DUPLEX_HALF) {
|
||||
printf("Half duplex not supported\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
pfe_gemac_set_speed(gem->gemac_base, speed);
|
||||
|
||||
/* Enable GPI */
|
||||
gpi_enable(gem->egpi_base);
|
||||
|
||||
/* Enable GEMAC */
|
||||
pfe_gemac_enable(gem->gemac_base);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pfe_eth_send(struct udevice *dev, void *packet, int length)
|
||||
{
|
||||
struct pfe_eth_dev *priv = (struct pfe_eth_dev *)dev->priv;
|
||||
|
||||
int rc;
|
||||
int i = 0;
|
||||
|
||||
rc = pfe_send(priv->gemac_port, packet, length);
|
||||
|
||||
if (rc < 0) {
|
||||
printf("Tx Queue full\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
while (1) {
|
||||
rc = pfe_tx_done();
|
||||
if (rc == 0)
|
||||
break;
|
||||
|
||||
udelay(100);
|
||||
i++;
|
||||
if (i == 30000)
|
||||
printf("Tx timeout, send failed\n");
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pfe_eth_recv(struct udevice *dev, int flags, uchar **packetp)
|
||||
{
|
||||
struct pfe_eth_dev *priv = dev_get_priv(dev);
|
||||
uchar *pkt_buf;
|
||||
int len;
|
||||
int phy_port;
|
||||
|
||||
len = pfe_recv(&pkt_buf, &phy_port);
|
||||
|
||||
if (len == 0)
|
||||
return -EAGAIN; /* no packet in rx */
|
||||
else if (len < 0)
|
||||
return -EAGAIN;
|
||||
|
||||
debug("Rx pkt: pkt_buf(0x%p), phy_port(%d), len(%d)\n", pkt_buf,
|
||||
phy_port, len);
|
||||
if (phy_port != priv->gemac_port) {
|
||||
printf("Rx pkt not on expected port\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
*packetp = pkt_buf;
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static int pfe_eth_probe(struct udevice *dev)
|
||||
{
|
||||
struct pfe_eth_dev *priv = dev_get_priv(dev);
|
||||
struct pfe_ddr_address *pfe_addr;
|
||||
struct pfe_eth_pdata *pdata = dev_get_platdata(dev);
|
||||
int ret = 0;
|
||||
static int init_done;
|
||||
|
||||
if (!init_done) {
|
||||
pfe_addr = (struct pfe_ddr_address *)malloc(sizeof
|
||||
(struct pfe_ddr_address));
|
||||
if (!pfe_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
pfe_addr->ddr_pfe_baseaddr =
|
||||
(void *)pdata->pfe_ddr_addr.ddr_pfe_baseaddr;
|
||||
pfe_addr->ddr_pfe_phys_baseaddr =
|
||||
(unsigned long)pdata->pfe_ddr_addr.ddr_pfe_phys_baseaddr;
|
||||
|
||||
debug("ddr_pfe_baseaddr: %p, ddr_pfe_phys_baseaddr: %08x\n",
|
||||
pfe_addr->ddr_pfe_baseaddr,
|
||||
(u32)pfe_addr->ddr_pfe_phys_baseaddr);
|
||||
|
||||
ret = pfe_drv_init(pfe_addr);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
init_pfe_scfg_dcfg_regs();
|
||||
init_done = 1;
|
||||
}
|
||||
|
||||
priv->gemac_port = pdata->pfe_eth_pdata_mac.phy_interface;
|
||||
priv->gem = &gem_info[priv->gemac_port];
|
||||
priv->dev = dev;
|
||||
|
||||
switch (priv->gemac_port) {
|
||||
case EMAC_PORT_0:
|
||||
default:
|
||||
priv->gem->gemac_base = EMAC1_BASE_ADDR;
|
||||
priv->gem->egpi_base = EGPI1_BASE_ADDR;
|
||||
break;
|
||||
case EMAC_PORT_1:
|
||||
priv->gem->gemac_base = EMAC2_BASE_ADDR;
|
||||
priv->gem->egpi_base = EGPI2_BASE_ADDR;
|
||||
break;
|
||||
}
|
||||
|
||||
ret = pfe_eth_board_init(dev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#if defined(CONFIG_PHYLIB)
|
||||
ret = pfe_phy_configure(priv, pdata->pfe_eth_pdata_mac.phy_interface,
|
||||
gem_info[priv->gemac_port].phy_address);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int pfe_eth_bind(struct udevice *dev)
|
||||
{
|
||||
struct pfe_eth_pdata *pdata = dev_get_platdata(dev);
|
||||
char name[20];
|
||||
|
||||
sprintf(name, "pfe_eth%u", pdata->pfe_eth_pdata_mac.phy_interface);
|
||||
|
||||
return device_set_name(dev, name);
|
||||
}
|
||||
|
||||
static const struct eth_ops pfe_eth_ops = {
|
||||
.start = pfe_eth_start,
|
||||
.send = pfe_eth_send,
|
||||
.recv = pfe_eth_recv,
|
||||
.free_pkt = pfe_eth_free_pkt,
|
||||
.stop = pfe_eth_stop,
|
||||
.write_hwaddr = pfe_eth_write_hwaddr,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(pfe_eth) = {
|
||||
.name = "pfe_eth",
|
||||
.id = UCLASS_ETH,
|
||||
.bind = pfe_eth_bind,
|
||||
.probe = pfe_eth_probe,
|
||||
.remove = pfe_eth_remove,
|
||||
.ops = &pfe_eth_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct pfe_eth_dev),
|
||||
.platdata_auto_alloc_size = sizeof(struct pfe_eth_pdata)
|
||||
};
|
230
drivers/net/pfe_eth/pfe_firmware.c
Normal file
230
drivers/net/pfe_eth/pfe_firmware.c
Normal file
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file
|
||||
* Contains all the functions to handle parsing and loading of PE firmware
|
||||
* files.
|
||||
*/
|
||||
|
||||
#include <net/pfe_eth/pfe_eth.h>
|
||||
#include <net/pfe_eth/pfe_firmware.h>
|
||||
|
||||
#define PFE_FIRMEWARE_FIT_CNF_NAME "config@1"
|
||||
|
||||
static const void *pfe_fit_addr = (void *)CONFIG_SYS_LS_PFE_FW_ADDR;
|
||||
|
||||
/*
|
||||
* PFE elf firmware loader.
|
||||
* Loads an elf firmware image into a list of PE's (specified using a bitmask)
|
||||
*
|
||||
* @param pe_mask Mask of PE id's to load firmware to
|
||||
* @param pfe_firmware Pointer to the firmware image
|
||||
*
|
||||
* @return 0 on success, a negative value on error
|
||||
*/
|
||||
static int pfe_load_elf(int pe_mask, uint8_t *pfe_firmware)
|
||||
{
|
||||
Elf32_Ehdr *elf_hdr = (Elf32_Ehdr *)pfe_firmware;
|
||||
Elf32_Half sections = be16_to_cpu(elf_hdr->e_shnum);
|
||||
Elf32_Shdr *shdr = (Elf32_Shdr *)(pfe_firmware +
|
||||
be32_to_cpu(elf_hdr->e_shoff));
|
||||
int id, section;
|
||||
int ret;
|
||||
|
||||
debug("%s: no of sections: %d\n", __func__, sections);
|
||||
|
||||
/* Some sanity checks */
|
||||
if (strncmp((char *)&elf_hdr->e_ident[EI_MAG0], ELFMAG, SELFMAG)) {
|
||||
printf("%s: incorrect elf magic number\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (elf_hdr->e_ident[EI_CLASS] != ELFCLASS32) {
|
||||
printf("%s: incorrect elf class(%x)\n", __func__,
|
||||
elf_hdr->e_ident[EI_CLASS]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (elf_hdr->e_ident[EI_DATA] != ELFDATA2MSB) {
|
||||
printf("%s: incorrect elf data(%x)\n", __func__,
|
||||
elf_hdr->e_ident[EI_DATA]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (be16_to_cpu(elf_hdr->e_type) != ET_EXEC) {
|
||||
printf("%s: incorrect elf file type(%x)\n", __func__,
|
||||
be16_to_cpu(elf_hdr->e_type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (section = 0; section < sections; section++, shdr++) {
|
||||
if (!(be32_to_cpu(shdr->sh_flags) & (SHF_WRITE | SHF_ALLOC |
|
||||
SHF_EXECINSTR)))
|
||||
continue;
|
||||
for (id = 0; id < MAX_PE; id++)
|
||||
if (pe_mask & BIT(id)) {
|
||||
ret = pe_load_elf_section(id,
|
||||
pfe_firmware, shdr);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get PFE firmware from FIT image
|
||||
*
|
||||
* @param data pointer to PFE firmware
|
||||
* @param size pointer to size of the firmware
|
||||
* @param fw_name pfe firmware name, either class or tmu
|
||||
*
|
||||
* @return 0 on success, a negative value on error
|
||||
*/
|
||||
static int pfe_get_fw(const void **data,
|
||||
size_t *size, char *fw_name)
|
||||
{
|
||||
int conf_node_off, fw_node_off;
|
||||
char *conf_node_name = NULL;
|
||||
char *desc;
|
||||
int ret = 0;
|
||||
|
||||
conf_node_name = PFE_FIRMEWARE_FIT_CNF_NAME;
|
||||
|
||||
conf_node_off = fit_conf_get_node(pfe_fit_addr, conf_node_name);
|
||||
if (conf_node_off < 0) {
|
||||
printf("PFE Firmware: %s: no such config\n", conf_node_name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
fw_node_off = fit_conf_get_prop_node(pfe_fit_addr, conf_node_off,
|
||||
fw_name);
|
||||
if (fw_node_off < 0) {
|
||||
printf("PFE Firmware: No '%s' in config\n",
|
||||
fw_name);
|
||||
return -ENOLINK;
|
||||
}
|
||||
|
||||
if (!(fit_image_verify(pfe_fit_addr, fw_node_off))) {
|
||||
printf("PFE Firmware: Bad firmware image (bad CRC)\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (fit_image_get_data(pfe_fit_addr, fw_node_off, data, size)) {
|
||||
printf("PFE Firmware: Can't get %s subimage data/size",
|
||||
fw_name);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
ret = fit_get_desc(pfe_fit_addr, fw_node_off, &desc);
|
||||
if (ret)
|
||||
printf("PFE Firmware: Can't get description\n");
|
||||
else
|
||||
printf("%s\n", desc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Check PFE FIT image
|
||||
*
|
||||
* @return 0 on success, a negative value on error
|
||||
*/
|
||||
static int pfe_fit_check(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = fdt_check_header(pfe_fit_addr);
|
||||
if (ret) {
|
||||
printf("PFE Firmware: Bad firmware image (not a FIT image)\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!fit_check_format(pfe_fit_addr)) {
|
||||
printf("PFE Firmware: Bad firmware image (bad FIT header)\n");
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE firmware initialization.
|
||||
* Loads different firmware files from FIT image.
|
||||
* Initializes PE IMEM/DMEM and UTIL-PE DDR
|
||||
* Initializes control path symbol addresses (by looking them up in the elf
|
||||
* firmware files
|
||||
* Takes PE's out of reset
|
||||
*
|
||||
* @return 0 on success, a negative value on error
|
||||
*/
|
||||
int pfe_firmware_init(void)
|
||||
{
|
||||
char *pfe_firmware_name;
|
||||
const void *raw_image_addr;
|
||||
size_t raw_image_size = 0;
|
||||
u8 *pfe_firmware;
|
||||
int ret = 0;
|
||||
int fw_count;
|
||||
|
||||
ret = pfe_fit_check();
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
for (fw_count = 0; fw_count < 2; fw_count++) {
|
||||
if (fw_count == 0)
|
||||
pfe_firmware_name = "class";
|
||||
else if (fw_count == 1)
|
||||
pfe_firmware_name = "tmu";
|
||||
|
||||
pfe_get_fw(&raw_image_addr, &raw_image_size, pfe_firmware_name);
|
||||
pfe_firmware = malloc(raw_image_size);
|
||||
if (!pfe_firmware)
|
||||
return -ENOMEM;
|
||||
memcpy((void *)pfe_firmware, (void *)raw_image_addr,
|
||||
raw_image_size);
|
||||
|
||||
if (fw_count == 0)
|
||||
ret = pfe_load_elf(CLASS_MASK, pfe_firmware);
|
||||
else if (fw_count == 1)
|
||||
ret = pfe_load_elf(TMU_MASK, pfe_firmware);
|
||||
|
||||
if (ret < 0) {
|
||||
printf("%s: %s firmware load failed\n", __func__,
|
||||
pfe_firmware_name);
|
||||
goto err;
|
||||
}
|
||||
debug("%s: %s firmware loaded\n", __func__, pfe_firmware_name);
|
||||
free(pfe_firmware);
|
||||
}
|
||||
|
||||
tmu_enable(0xb);
|
||||
class_enable();
|
||||
gpi_enable(HGPI_BASE_ADDR);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* PFE firmware cleanup
|
||||
* Puts PE's in reset
|
||||
*/
|
||||
void pfe_firmware_exit(void)
|
||||
{
|
||||
debug("%s\n", __func__);
|
||||
|
||||
class_disable();
|
||||
tmu_disable(0xf);
|
||||
hif_tx_disable();
|
||||
hif_rx_disable();
|
||||
}
|
999
drivers/net/pfe_eth/pfe_hw.c
Normal file
999
drivers/net/pfe_eth/pfe_hw.c
Normal file
|
@ -0,0 +1,999 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier:GPL-2.0+
|
||||
*/
|
||||
#include <net/pfe_eth/pfe_eth.h>
|
||||
#include <net/pfe_eth/pfe/pfe_hw.h>
|
||||
|
||||
static struct pe_info pe[MAX_PE];
|
||||
|
||||
/*
|
||||
* Initializes the PFE library.
|
||||
* Must be called before using any of the library functions.
|
||||
*/
|
||||
void pfe_lib_init(void)
|
||||
{
|
||||
int pfe_pe_id;
|
||||
|
||||
for (pfe_pe_id = CLASS0_ID; pfe_pe_id <= CLASS_MAX_ID; pfe_pe_id++) {
|
||||
pe[pfe_pe_id].dmem_base_addr =
|
||||
(u32)CLASS_DMEM_BASE_ADDR(pfe_pe_id);
|
||||
pe[pfe_pe_id].pmem_base_addr =
|
||||
(u32)CLASS_IMEM_BASE_ADDR(pfe_pe_id);
|
||||
pe[pfe_pe_id].pmem_size = (u32)CLASS_IMEM_SIZE;
|
||||
pe[pfe_pe_id].mem_access_wdata =
|
||||
(void *)CLASS_MEM_ACCESS_WDATA;
|
||||
pe[pfe_pe_id].mem_access_addr = (void *)CLASS_MEM_ACCESS_ADDR;
|
||||
pe[pfe_pe_id].mem_access_rdata = (void *)CLASS_MEM_ACCESS_RDATA;
|
||||
}
|
||||
|
||||
for (pfe_pe_id = TMU0_ID; pfe_pe_id <= TMU_MAX_ID; pfe_pe_id++) {
|
||||
if (pfe_pe_id == TMU2_ID)
|
||||
continue;
|
||||
pe[pfe_pe_id].dmem_base_addr =
|
||||
(u32)TMU_DMEM_BASE_ADDR(pfe_pe_id - TMU0_ID);
|
||||
pe[pfe_pe_id].pmem_base_addr =
|
||||
(u32)TMU_IMEM_BASE_ADDR(pfe_pe_id - TMU0_ID);
|
||||
pe[pfe_pe_id].pmem_size = (u32)TMU_IMEM_SIZE;
|
||||
pe[pfe_pe_id].mem_access_wdata = (void *)TMU_MEM_ACCESS_WDATA;
|
||||
pe[pfe_pe_id].mem_access_addr = (void *)TMU_MEM_ACCESS_ADDR;
|
||||
pe[pfe_pe_id].mem_access_rdata = (void *)TMU_MEM_ACCESS_RDATA;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a buffer to PE internal memory from the host
|
||||
* through indirect access registers.
|
||||
*
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., UTIL_ID)
|
||||
* @param[in] mem_access_addr DMEM destination address (must be 32bit
|
||||
* aligned)
|
||||
* @param[in] src Buffer source address
|
||||
* @param[in] len Number of bytes to copy
|
||||
*/
|
||||
static void pe_mem_memcpy_to32(int id, u32 mem_access_addr, const void *src,
|
||||
unsigned int len)
|
||||
{
|
||||
u32 offset = 0, val, addr;
|
||||
unsigned int len32 = len >> 2;
|
||||
int i;
|
||||
|
||||
addr = mem_access_addr | PE_MEM_ACCESS_WRITE |
|
||||
PE_MEM_ACCESS_BYTE_ENABLE(0, 4);
|
||||
|
||||
for (i = 0; i < len32; i++, offset += 4, src += 4) {
|
||||
val = *(u32 *)src;
|
||||
writel(cpu_to_be32(val), pe[id].mem_access_wdata);
|
||||
writel(addr + offset, pe[id].mem_access_addr);
|
||||
}
|
||||
|
||||
len = (len & 0x3);
|
||||
if (len) {
|
||||
val = 0;
|
||||
|
||||
addr = (mem_access_addr | PE_MEM_ACCESS_WRITE |
|
||||
PE_MEM_ACCESS_BYTE_ENABLE(0, len)) + offset;
|
||||
|
||||
for (i = 0; i < len; i++, src++)
|
||||
val |= (*(u8 *)src) << (8 * i);
|
||||
|
||||
writel(cpu_to_be32(val), pe[id].mem_access_wdata);
|
||||
writel(addr, pe[id].mem_access_addr);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a buffer to PE internal data memory (DMEM) from the host
|
||||
* through indirect access registers.
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., UTIL_ID)
|
||||
* @param[in] dst DMEM destination address (must be 32bit
|
||||
* aligned)
|
||||
* @param[in] src Buffer source address
|
||||
* @param[in] len Number of bytes to copy
|
||||
*/
|
||||
static void pe_dmem_memcpy_to32(int id, u32 dst, const void *src,
|
||||
unsigned int len)
|
||||
{
|
||||
pe_mem_memcpy_to32(id, pe[id].dmem_base_addr | dst | PE_MEM_ACCESS_DMEM,
|
||||
src, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a buffer to PE internal program memory (PMEM) from the host
|
||||
* through indirect access registers.
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., TMU3_ID)
|
||||
* @param[in] dst PMEM destination address (must be 32bit
|
||||
* aligned)
|
||||
* @param[in] src Buffer source address
|
||||
* @param[in] len Number of bytes to copy
|
||||
*/
|
||||
static void pe_pmem_memcpy_to32(int id, u32 dst, const void *src,
|
||||
unsigned int len)
|
||||
{
|
||||
pe_mem_memcpy_to32(id, pe[id].pmem_base_addr | (dst & (pe[id].pmem_size
|
||||
- 1)) | PE_MEM_ACCESS_IMEM, src, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads PE internal program memory (IMEM) from the host
|
||||
* through indirect access registers.
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., TMU3_ID)
|
||||
* @param[in] addr PMEM read address (must be aligned on size)
|
||||
* @param[in] size Number of bytes to read (maximum 4, must not
|
||||
* cross 32bit boundaries)
|
||||
* @return the data read (in PE endianness, i.e BE).
|
||||
*/
|
||||
u32 pe_pmem_read(int id, u32 addr, u8 size)
|
||||
{
|
||||
u32 offset = addr & 0x3;
|
||||
u32 mask = 0xffffffff >> ((4 - size) << 3);
|
||||
u32 val;
|
||||
|
||||
addr = pe[id].pmem_base_addr | ((addr & ~0x3) & (pe[id].pmem_size - 1))
|
||||
| PE_MEM_ACCESS_READ | PE_MEM_ACCESS_IMEM |
|
||||
PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
|
||||
|
||||
writel(addr, pe[id].mem_access_addr);
|
||||
val = be32_to_cpu(readl(pe[id].mem_access_rdata));
|
||||
|
||||
return (val >> (offset << 3)) & mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes PE internal data memory (DMEM) from the host
|
||||
* through indirect access registers.
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., UTIL_ID)
|
||||
* @param[in] val Value to write (in PE endianness, i.e BE)
|
||||
* @param[in] addr DMEM write address (must be aligned on size)
|
||||
* @param[in] size Number of bytes to write (maximum 4, must not
|
||||
* cross 32bit boundaries)
|
||||
*/
|
||||
void pe_dmem_write(int id, u32 val, u32 addr, u8 size)
|
||||
{
|
||||
u32 offset = addr & 0x3;
|
||||
|
||||
addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_WRITE |
|
||||
PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
|
||||
|
||||
/* Indirect access interface is byte swapping data being written */
|
||||
writel(cpu_to_be32(val << (offset << 3)), pe[id].mem_access_wdata);
|
||||
writel(addr, pe[id].mem_access_addr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads PE internal data memory (DMEM) from the host
|
||||
* through indirect access registers.
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., UTIL_ID)
|
||||
* @param[in] addr DMEM read address (must be aligned on size)
|
||||
* @param[in] size Number of bytes to read (maximum 4, must not
|
||||
* cross 32bit boundaries)
|
||||
* @return the data read (in PE endianness, i.e BE).
|
||||
*/
|
||||
u32 pe_dmem_read(int id, u32 addr, u8 size)
|
||||
{
|
||||
u32 offset = addr & 0x3;
|
||||
u32 mask = 0xffffffff >> ((4 - size) << 3);
|
||||
u32 val;
|
||||
|
||||
addr = pe[id].dmem_base_addr | (addr & ~0x3) | PE_MEM_ACCESS_READ |
|
||||
PE_MEM_ACCESS_DMEM | PE_MEM_ACCESS_BYTE_ENABLE(offset, size);
|
||||
|
||||
writel(addr, pe[id].mem_access_addr);
|
||||
|
||||
/* Indirect access interface is byte swapping data being read */
|
||||
val = be32_to_cpu(readl(pe[id].mem_access_rdata));
|
||||
|
||||
return (val >> (offset << 3)) & mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to write to CLASS internal bus peripherals (ccu,
|
||||
* pe-lem) from the host
|
||||
* through indirect access registers.
|
||||
* @param[in] val value to write
|
||||
* @param[in] addr Address to write to (must be aligned on size)
|
||||
* @param[in] size Number of bytes to write (1, 2 or 4)
|
||||
*
|
||||
*/
|
||||
static void class_bus_write(u32 val, u32 addr, u8 size)
|
||||
{
|
||||
u32 offset = addr & 0x3;
|
||||
|
||||
writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE);
|
||||
|
||||
addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | PE_MEM_ACCESS_WRITE |
|
||||
(size << 24);
|
||||
|
||||
writel(cpu_to_be32(val << (offset << 3)), CLASS_BUS_ACCESS_WDATA);
|
||||
writel(addr, CLASS_BUS_ACCESS_ADDR);
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads from CLASS internal bus peripherals (ccu, pe-lem) from the host
|
||||
* through indirect access registers.
|
||||
* @param[in] addr Address to read from (must be aligned on size)
|
||||
* @param[in] size Number of bytes to read (1, 2 or 4)
|
||||
* @return the read data
|
||||
*/
|
||||
static u32 class_bus_read(u32 addr, u8 size)
|
||||
{
|
||||
u32 offset = addr & 0x3;
|
||||
u32 mask = 0xffffffff >> ((4 - size) << 3);
|
||||
u32 val;
|
||||
|
||||
writel((addr & CLASS_BUS_ACCESS_BASE_MASK), CLASS_BUS_ACCESS_BASE);
|
||||
|
||||
addr = (addr & ~CLASS_BUS_ACCESS_BASE_MASK) | (size << 24);
|
||||
|
||||
writel(addr, CLASS_BUS_ACCESS_ADDR);
|
||||
val = be32_to_cpu(readl(CLASS_BUS_ACCESS_RDATA));
|
||||
|
||||
return (val >> (offset << 3)) & mask;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes data to the cluster memory (PE_LMEM)
|
||||
* @param[in] dst PE LMEM destination address (must be 32bit aligned)
|
||||
* @param[in] src Buffer source address
|
||||
* @param[in] len Number of bytes to copy
|
||||
*/
|
||||
static void class_pe_lmem_memcpy_to32(u32 dst, const void *src,
|
||||
unsigned int len)
|
||||
{
|
||||
u32 len32 = len >> 2;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len32; i++, src += 4, dst += 4)
|
||||
class_bus_write(*(u32 *)src, dst, 4);
|
||||
|
||||
if (len & 0x2) {
|
||||
class_bus_write(*(u16 *)src, dst, 2);
|
||||
src += 2;
|
||||
dst += 2;
|
||||
}
|
||||
|
||||
if (len & 0x1) {
|
||||
class_bus_write(*(u8 *)src, dst, 1);
|
||||
src++;
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes value to the cluster memory (PE_LMEM)
|
||||
* @param[in] dst PE LMEM destination address (must be 32bit aligned)
|
||||
* @param[in] val Value to write
|
||||
* @param[in] len Number of bytes to write
|
||||
*/
|
||||
static void class_pe_lmem_memset(u32 dst, int val, unsigned int len)
|
||||
{
|
||||
u32 len32 = len >> 2;
|
||||
int i;
|
||||
|
||||
val = val | (val << 8) | (val << 16) | (val << 24);
|
||||
|
||||
for (i = 0; i < len32; i++, dst += 4)
|
||||
class_bus_write(val, dst, 4);
|
||||
|
||||
if (len & 0x2) {
|
||||
class_bus_write(val, dst, 2);
|
||||
dst += 2;
|
||||
}
|
||||
|
||||
if (len & 0x1) {
|
||||
class_bus_write(val, dst, 1);
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads data from the cluster memory (PE_LMEM)
|
||||
* @param[out] dst pointer to the source buffer data are copied to
|
||||
* @param[in] len length in bytes of the amount of data to read
|
||||
* from cluster memory
|
||||
* @param[in] offset offset in bytes in the cluster memory where data are
|
||||
* read from
|
||||
*/
|
||||
void pe_lmem_read(u32 *dst, u32 len, u32 offset)
|
||||
{
|
||||
u32 len32 = len >> 2;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < len32; dst++, i++, offset += 4)
|
||||
*dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, 4);
|
||||
|
||||
if (len & 0x03)
|
||||
*dst = class_bus_read(PE_LMEM_BASE_ADDR + offset, (len & 0x03));
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes data to the cluster memory (PE_LMEM)
|
||||
* @param[in] src pointer to the source buffer data are copied from
|
||||
* @param[in] len length in bytes of the amount of data to write to the
|
||||
* cluster memory
|
||||
* @param[in] offset offset in bytes in the cluster memory where data are
|
||||
* written to
|
||||
*/
|
||||
void pe_lmem_write(u32 *src, u32 len, u32 offset)
|
||||
{
|
||||
u32 len32 = len >> 2;
|
||||
int i = 0;
|
||||
|
||||
for (i = 0; i < len32; src++, i++, offset += 4)
|
||||
class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, 4);
|
||||
|
||||
if (len & 0x03)
|
||||
class_bus_write(*src, PE_LMEM_BASE_ADDR + offset, (len &
|
||||
0x03));
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads an elf section into pmem
|
||||
* Code needs to be at least 16bit aligned and only PROGBITS sections are
|
||||
* supported
|
||||
*
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID, ...,
|
||||
* TMU3_ID)
|
||||
* @param[in] data pointer to the elf firmware
|
||||
* @param[in] shdr pointer to the elf section header
|
||||
*/
|
||||
static int pe_load_pmem_section(int id, const void *data, Elf32_Shdr *shdr)
|
||||
{
|
||||
u32 offset = be32_to_cpu(shdr->sh_offset);
|
||||
u32 addr = be32_to_cpu(shdr->sh_addr);
|
||||
u32 size = be32_to_cpu(shdr->sh_size);
|
||||
u32 type = be32_to_cpu(shdr->sh_type);
|
||||
|
||||
if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
|
||||
printf(
|
||||
"%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
|
||||
__func__, addr, (unsigned long)data + offset);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr & 0x1) {
|
||||
printf("%s: load address(%x) is not 16bit aligned\n",
|
||||
__func__, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size & 0x1) {
|
||||
printf("%s: load size(%x) is not 16bit aligned\n", __func__,
|
||||
size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("pmem pe%d @%x len %d\n", id, addr, size);
|
||||
switch (type) {
|
||||
case SHT_PROGBITS:
|
||||
pe_pmem_memcpy_to32(id, addr, data + offset, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%s: unsupported section type(%x)\n", __func__, type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads an elf section into dmem
|
||||
* Data needs to be at least 32bit aligned, NOBITS sections are correctly
|
||||
* initialized to 0
|
||||
*
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., UTIL_ID)
|
||||
* @param[in] data pointer to the elf firmware
|
||||
* @param[in] shdr pointer to the elf section header
|
||||
*/
|
||||
static int pe_load_dmem_section(int id, const void *data, Elf32_Shdr *shdr)
|
||||
{
|
||||
u32 offset = be32_to_cpu(shdr->sh_offset);
|
||||
u32 addr = be32_to_cpu(shdr->sh_addr);
|
||||
u32 size = be32_to_cpu(shdr->sh_size);
|
||||
u32 type = be32_to_cpu(shdr->sh_type);
|
||||
u32 size32 = size >> 2;
|
||||
int i;
|
||||
|
||||
if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
|
||||
printf(
|
||||
"%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
|
||||
__func__, addr, (unsigned long)data + offset);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr & 0x3) {
|
||||
printf("%s: load address(%x) is not 32bit aligned\n",
|
||||
__func__, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case SHT_PROGBITS:
|
||||
debug("dmem pe%d @%x len %d\n", id, addr, size);
|
||||
pe_dmem_memcpy_to32(id, addr, data + offset, size);
|
||||
break;
|
||||
|
||||
case SHT_NOBITS:
|
||||
debug("dmem zero pe%d @%x len %d\n", id, addr, size);
|
||||
for (i = 0; i < size32; i++, addr += 4)
|
||||
pe_dmem_write(id, 0, addr, 4);
|
||||
|
||||
if (size & 0x3)
|
||||
pe_dmem_write(id, 0, addr, size & 0x3);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%s: unsupported section type(%x)\n", __func__, type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads an elf section into DDR
|
||||
* Data needs to be at least 32bit aligned, NOBITS sections are correctly
|
||||
* initialized to 0
|
||||
*
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., UTIL_ID)
|
||||
* @param[in] data pointer to the elf firmware
|
||||
* @param[in] shdr pointer to the elf section header
|
||||
*/
|
||||
static int pe_load_ddr_section(int id, const void *data, Elf32_Shdr *shdr)
|
||||
{
|
||||
u32 offset = be32_to_cpu(shdr->sh_offset);
|
||||
u32 addr = be32_to_cpu(shdr->sh_addr);
|
||||
u32 size = be32_to_cpu(shdr->sh_size);
|
||||
u32 type = be32_to_cpu(shdr->sh_type);
|
||||
u32 flags = be32_to_cpu(shdr->sh_flags);
|
||||
|
||||
switch (type) {
|
||||
case SHT_PROGBITS:
|
||||
debug("ddr pe%d @%x len %d\n", id, addr, size);
|
||||
if (flags & SHF_EXECINSTR) {
|
||||
if (id <= CLASS_MAX_ID) {
|
||||
/* DO the loading only once in DDR */
|
||||
if (id == CLASS0_ID) {
|
||||
debug(
|
||||
"%s: load address(%x) and elf file address(%lx) rcvd\n"
|
||||
, __func__, addr,
|
||||
(unsigned long)data + offset);
|
||||
if (((unsigned long)(data + offset)
|
||||
& 0x3) != (addr & 0x3)) {
|
||||
printf(
|
||||
"%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
|
||||
__func__, addr,
|
||||
(unsigned long)data +
|
||||
offset);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr & 0x1) {
|
||||
printf(
|
||||
"%s: load address(%x) is not 16bit aligned\n"
|
||||
, __func__, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (size & 0x1) {
|
||||
printf(
|
||||
"%s: load length(%x) is not 16bit aligned\n"
|
||||
, __func__, size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy((void *)DDR_PFE_TO_VIRT(addr),
|
||||
data + offset, size);
|
||||
}
|
||||
} else {
|
||||
printf(
|
||||
"%s: unsupported ddr section type(%x) for PE(%d)\n"
|
||||
, __func__, type, id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
} else {
|
||||
memcpy((void *)DDR_PFE_TO_VIRT(addr), data + offset,
|
||||
size);
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SHT_NOBITS:
|
||||
debug("ddr zero pe%d @%x len %d\n", id, addr, size);
|
||||
memset((void *)DDR_PFE_TO_VIRT(addr), 0, size);
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%s: unsupported section type(%x)\n", __func__, type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads an elf section into pe lmem
|
||||
* Data needs to be at least 32bit aligned, NOBITS sections are correctly
|
||||
* initialized to 0
|
||||
*
|
||||
* @param[in] id PE identification (CLASS0_ID,..., CLASS5_ID)
|
||||
* @param[in] data pointer to the elf firmware
|
||||
* @param[in] shdr pointer to the elf section header
|
||||
*/
|
||||
static int pe_load_pe_lmem_section(int id, const void *data, Elf32_Shdr *shdr)
|
||||
{
|
||||
u32 offset = be32_to_cpu(shdr->sh_offset);
|
||||
u32 addr = be32_to_cpu(shdr->sh_addr);
|
||||
u32 size = be32_to_cpu(shdr->sh_size);
|
||||
u32 type = be32_to_cpu(shdr->sh_type);
|
||||
|
||||
if (id > CLASS_MAX_ID) {
|
||||
printf("%s: unsupported pe-lmem section type(%x) for PE(%d)\n",
|
||||
__func__, type, id);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (((unsigned long)(data + offset) & 0x3) != (addr & 0x3)) {
|
||||
printf(
|
||||
"%s: load address(%x) and elf file address(%lx) don't have the same alignment\n",
|
||||
__func__, addr, (unsigned long)data + offset);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (addr & 0x3) {
|
||||
printf("%s: load address(%x) is not 32bit aligned\n",
|
||||
__func__, addr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
debug("lmem pe%d @%x len %d\n", id, addr, size);
|
||||
|
||||
switch (type) {
|
||||
case SHT_PROGBITS:
|
||||
class_pe_lmem_memcpy_to32(addr, data + offset, size);
|
||||
break;
|
||||
|
||||
case SHT_NOBITS:
|
||||
class_pe_lmem_memset(addr, 0, size);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("%s: unsupported section type(%x)\n", __func__, type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Loads an elf section into a PE
|
||||
* For now only supports loading a section to dmem (all PE's), pmem (class and
|
||||
* tmu PE's), DDDR (util PE code)
|
||||
* @param[in] id PE identification (CLASS0_ID, ..., TMU0_ID,
|
||||
* ..., UTIL_ID)
|
||||
* @param[in] data pointer to the elf firmware
|
||||
* @param[in] shdr pointer to the elf section header
|
||||
*/
|
||||
int pe_load_elf_section(int id, const void *data, Elf32_Shdr *shdr)
|
||||
{
|
||||
u32 addr = be32_to_cpu(shdr->sh_addr);
|
||||
u32 size = be32_to_cpu(shdr->sh_size);
|
||||
|
||||
if (IS_DMEM(addr, size))
|
||||
return pe_load_dmem_section(id, data, shdr);
|
||||
else if (IS_PMEM(addr, size))
|
||||
return pe_load_pmem_section(id, data, shdr);
|
||||
else if (IS_PFE_LMEM(addr, size))
|
||||
return 0;
|
||||
else if (IS_PHYS_DDR(addr, size))
|
||||
return pe_load_ddr_section(id, data, shdr);
|
||||
else if (IS_PE_LMEM(addr, size))
|
||||
return pe_load_pe_lmem_section(id, data, shdr);
|
||||
|
||||
printf("%s: unsupported memory range(%x)\n", __func__, addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**************************** BMU ***************************/
|
||||
/*
|
||||
* Resets a BMU block.
|
||||
* @param[in] base BMU block base address
|
||||
*/
|
||||
static inline void bmu_reset(void *base)
|
||||
{
|
||||
writel(CORE_SW_RESET, base + BMU_CTRL);
|
||||
|
||||
/* Wait for self clear */
|
||||
while (readl(base + BMU_CTRL) & CORE_SW_RESET)
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Enabled a BMU block.
|
||||
* @param[in] base BMU block base address
|
||||
*/
|
||||
void bmu_enable(void *base)
|
||||
{
|
||||
writel(CORE_ENABLE, base + BMU_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables a BMU block.
|
||||
* @param[in] base BMU block base address
|
||||
*/
|
||||
static inline void bmu_disable(void *base)
|
||||
{
|
||||
writel(CORE_DISABLE, base + BMU_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the configuration of a BMU block.
|
||||
* @param[in] base BMU block base address
|
||||
* @param[in] cfg BMU configuration
|
||||
*/
|
||||
static inline void bmu_set_config(void *base, struct bmu_cfg *cfg)
|
||||
{
|
||||
writel(cfg->baseaddr, base + BMU_UCAST_BASE_ADDR);
|
||||
writel(cfg->count & 0xffff, base + BMU_UCAST_CONFIG);
|
||||
writel(cfg->size & 0xffff, base + BMU_BUF_SIZE);
|
||||
|
||||
/* Interrupts are never used */
|
||||
writel(0x0, base + BMU_INT_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes a BMU block.
|
||||
* @param[in] base BMU block base address
|
||||
* @param[in] cfg BMU configuration
|
||||
*/
|
||||
void bmu_init(void *base, struct bmu_cfg *cfg)
|
||||
{
|
||||
bmu_disable(base);
|
||||
|
||||
bmu_set_config(base, cfg);
|
||||
|
||||
bmu_reset(base);
|
||||
}
|
||||
|
||||
/**************************** GPI ***************************/
|
||||
/*
|
||||
* Resets a GPI block.
|
||||
* @param[in] base GPI base address
|
||||
*/
|
||||
static inline void gpi_reset(void *base)
|
||||
{
|
||||
writel(CORE_SW_RESET, base + GPI_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enables a GPI block.
|
||||
* @param[in] base GPI base address
|
||||
*/
|
||||
void gpi_enable(void *base)
|
||||
{
|
||||
writel(CORE_ENABLE, base + GPI_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables a GPI block.
|
||||
* @param[in] base GPI base address
|
||||
*/
|
||||
void gpi_disable(void *base)
|
||||
{
|
||||
writel(CORE_DISABLE, base + GPI_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the configuration of a GPI block.
|
||||
* @param[in] base GPI base address
|
||||
* @param[in] cfg GPI configuration
|
||||
*/
|
||||
static inline void gpi_set_config(void *base, struct gpi_cfg *cfg)
|
||||
{
|
||||
writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_ALLOC_CTRL), base
|
||||
+ GPI_LMEM_ALLOC_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(BMU1_BASE_ADDR + BMU_FREE_CTRL), base
|
||||
+ GPI_LMEM_FREE_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_ALLOC_CTRL), base
|
||||
+ GPI_DDR_ALLOC_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL), base
|
||||
+ GPI_DDR_FREE_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(CLASS_INQ_PKTPTR), base + GPI_CLASS_ADDR);
|
||||
writel(DDR_HDR_SIZE, base + GPI_DDR_DATA_OFFSET);
|
||||
writel(LMEM_HDR_SIZE, base + GPI_LMEM_DATA_OFFSET);
|
||||
writel(0, base + GPI_LMEM_SEC_BUF_DATA_OFFSET);
|
||||
writel(0, base + GPI_DDR_SEC_BUF_DATA_OFFSET);
|
||||
writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, base + GPI_HDR_SIZE);
|
||||
writel((DDR_BUF_SIZE << 16) | LMEM_BUF_SIZE, base + GPI_BUF_SIZE);
|
||||
|
||||
writel(((cfg->lmem_rtry_cnt << 16) | (GPI_DDR_BUF_EN << 1) |
|
||||
GPI_LMEM_BUF_EN), base + GPI_RX_CONFIG);
|
||||
writel(cfg->tmlf_txthres, base + GPI_TMLF_TX);
|
||||
writel(cfg->aseq_len, base + GPI_DTX_ASEQ);
|
||||
|
||||
/*Make GPI AXI transactions non-bufferable */
|
||||
writel(0x1, base + GPI_AXI_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes a GPI block.
|
||||
* @param[in] base GPI base address
|
||||
* @param[in] cfg GPI configuration
|
||||
*/
|
||||
void gpi_init(void *base, struct gpi_cfg *cfg)
|
||||
{
|
||||
gpi_reset(base);
|
||||
|
||||
gpi_disable(base);
|
||||
|
||||
gpi_set_config(base, cfg);
|
||||
}
|
||||
|
||||
/**************************** CLASSIFIER ***************************/
|
||||
/*
|
||||
* Resets CLASSIFIER block.
|
||||
*/
|
||||
static inline void class_reset(void)
|
||||
{
|
||||
writel(CORE_SW_RESET, CLASS_TX_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enables all CLASS-PE's cores.
|
||||
*/
|
||||
void class_enable(void)
|
||||
{
|
||||
writel(CORE_ENABLE, CLASS_TX_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables all CLASS-PE's cores.
|
||||
*/
|
||||
void class_disable(void)
|
||||
{
|
||||
writel(CORE_DISABLE, CLASS_TX_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets the configuration of the CLASSIFIER block.
|
||||
* @param[in] cfg CLASSIFIER configuration
|
||||
*/
|
||||
static inline void class_set_config(struct class_cfg *cfg)
|
||||
{
|
||||
if (PLL_CLK_EN == 0) {
|
||||
/* Clock ratio: for 1:1 the value is 0 */
|
||||
writel(0x0, CLASS_PE_SYS_CLK_RATIO);
|
||||
} else {
|
||||
/* Clock ratio: for 1:2 the value is 1 */
|
||||
writel(0x1, CLASS_PE_SYS_CLK_RATIO);
|
||||
}
|
||||
writel((DDR_HDR_SIZE << 16) | LMEM_HDR_SIZE, CLASS_HDR_SIZE);
|
||||
writel(LMEM_BUF_SIZE, CLASS_LMEM_BUF_SIZE);
|
||||
writel(CLASS_ROUTE_ENTRY_SIZE(CLASS_ROUTE_SIZE) |
|
||||
CLASS_ROUTE_HASH_SIZE(cfg->route_table_hash_bits),
|
||||
CLASS_ROUTE_HASH_ENTRY_SIZE);
|
||||
writel(HASH_CRC_PORT_IP | QB2BUS_LE, CLASS_ROUTE_MULTI);
|
||||
|
||||
writel(cfg->route_table_baseaddr, CLASS_ROUTE_TABLE_BASE);
|
||||
memset((void *)DDR_PFE_TO_VIRT(cfg->route_table_baseaddr), 0,
|
||||
ROUTE_TABLE_SIZE);
|
||||
|
||||
writel(CLASS_PE0_RO_DM_ADDR0_VAL, CLASS_PE0_RO_DM_ADDR0);
|
||||
writel(CLASS_PE0_RO_DM_ADDR1_VAL, CLASS_PE0_RO_DM_ADDR1);
|
||||
writel(CLASS_PE0_QB_DM_ADDR0_VAL, CLASS_PE0_QB_DM_ADDR0);
|
||||
writel(CLASS_PE0_QB_DM_ADDR1_VAL, CLASS_PE0_QB_DM_ADDR1);
|
||||
writel(CBUS_VIRT_TO_PFE(TMU_PHY_INQ_PKTPTR), CLASS_TM_INQ_ADDR);
|
||||
|
||||
writel(23, CLASS_AFULL_THRES);
|
||||
writel(23, CLASS_TSQ_FIFO_THRES);
|
||||
|
||||
writel(24, CLASS_MAX_BUF_CNT);
|
||||
writel(24, CLASS_TSQ_MAX_CNT);
|
||||
|
||||
/*Make Class AXI transactions non-bufferable */
|
||||
writel(0x1, CLASS_AXI_CTRL);
|
||||
|
||||
/*Make Util AXI transactions non-bufferable */
|
||||
/*Util is disabled in U-boot, do it from here */
|
||||
writel(0x1, UTIL_AXI_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes CLASSIFIER block.
|
||||
* @param[in] cfg CLASSIFIER configuration
|
||||
*/
|
||||
void class_init(struct class_cfg *cfg)
|
||||
{
|
||||
class_reset();
|
||||
|
||||
class_disable();
|
||||
|
||||
class_set_config(cfg);
|
||||
}
|
||||
|
||||
/**************************** TMU ***************************/
|
||||
/*
|
||||
* Enables TMU-PE cores.
|
||||
* @param[in] pe_mask TMU PE mask
|
||||
*/
|
||||
void tmu_enable(u32 pe_mask)
|
||||
{
|
||||
writel(readl(TMU_TX_CTRL) | (pe_mask & 0xF), TMU_TX_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disables TMU cores.
|
||||
* @param[in] pe_mask TMU PE mask
|
||||
*/
|
||||
void tmu_disable(u32 pe_mask)
|
||||
{
|
||||
writel(readl(TMU_TX_CTRL) & ~(pe_mask & 0xF), TMU_TX_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes TMU block.
|
||||
* @param[in] cfg TMU configuration
|
||||
*/
|
||||
void tmu_init(struct tmu_cfg *cfg)
|
||||
{
|
||||
int q, phyno;
|
||||
|
||||
/* keep in soft reset */
|
||||
writel(SW_RESET, TMU_CTRL);
|
||||
|
||||
/*Make Class AXI transactions non-bufferable */
|
||||
writel(0x1, TMU_AXI_CTRL);
|
||||
|
||||
/* enable EMAC PHY ports */
|
||||
writel(0x3, TMU_SYS_GENERIC_CONTROL);
|
||||
|
||||
writel(750, TMU_INQ_WATERMARK);
|
||||
|
||||
writel(CBUS_VIRT_TO_PFE(EGPI1_BASE_ADDR + GPI_INQ_PKTPTR),
|
||||
TMU_PHY0_INQ_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(EGPI2_BASE_ADDR + GPI_INQ_PKTPTR),
|
||||
TMU_PHY1_INQ_ADDR);
|
||||
|
||||
writel(CBUS_VIRT_TO_PFE(HGPI_BASE_ADDR + GPI_INQ_PKTPTR),
|
||||
TMU_PHY3_INQ_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(HIF_NOCPY_RX_INQ0_PKTPTR), TMU_PHY4_INQ_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(UTIL_INQ_PKTPTR), TMU_PHY5_INQ_ADDR);
|
||||
writel(CBUS_VIRT_TO_PFE(BMU2_BASE_ADDR + BMU_FREE_CTRL),
|
||||
TMU_BMU_INQ_ADDR);
|
||||
|
||||
/* enabling all 10 schedulers [9:0] of each TDQ */
|
||||
writel(0x3FF, TMU_TDQ0_SCH_CTRL);
|
||||
writel(0x3FF, TMU_TDQ1_SCH_CTRL);
|
||||
writel(0x3FF, TMU_TDQ3_SCH_CTRL);
|
||||
|
||||
if (PLL_CLK_EN == 0) {
|
||||
/* Clock ratio: for 1:1 the value is 0 */
|
||||
writel(0x0, TMU_PE_SYS_CLK_RATIO);
|
||||
} else {
|
||||
/* Clock ratio: for 1:2 the value is 1 */
|
||||
writel(0x1, TMU_PE_SYS_CLK_RATIO);
|
||||
}
|
||||
|
||||
/* Extra packet pointers will be stored from this address onwards */
|
||||
debug("TMU_LLM_BASE_ADDR %x\n", cfg->llm_base_addr);
|
||||
writel(cfg->llm_base_addr, TMU_LLM_BASE_ADDR);
|
||||
|
||||
debug("TMU_LLM_QUE_LEN %x\n", cfg->llm_queue_len);
|
||||
writel(cfg->llm_queue_len, TMU_LLM_QUE_LEN);
|
||||
|
||||
writel(5, TMU_TDQ_IIFG_CFG);
|
||||
writel(DDR_BUF_SIZE, TMU_BMU_BUF_SIZE);
|
||||
|
||||
writel(0x0, TMU_CTRL);
|
||||
|
||||
/* MEM init */
|
||||
writel(MEM_INIT, TMU_CTRL);
|
||||
|
||||
while (!(readl(TMU_CTRL) & MEM_INIT_DONE))
|
||||
;
|
||||
|
||||
/* LLM init */
|
||||
writel(LLM_INIT, TMU_CTRL);
|
||||
|
||||
while (!(readl(TMU_CTRL) & LLM_INIT_DONE))
|
||||
;
|
||||
|
||||
/* set up each queue for tail drop */
|
||||
for (phyno = 0; phyno < 4; phyno++) {
|
||||
if (phyno == 2)
|
||||
continue;
|
||||
for (q = 0; q < 16; q++) {
|
||||
u32 qmax;
|
||||
|
||||
writel((phyno << 8) | q, TMU_TEQ_CTRL);
|
||||
writel(BIT(22), TMU_TEQ_QCFG);
|
||||
|
||||
if (phyno == 3)
|
||||
qmax = DEFAULT_TMU3_QDEPTH;
|
||||
else
|
||||
qmax = (q == 0) ? DEFAULT_Q0_QDEPTH :
|
||||
DEFAULT_MAX_QDEPTH;
|
||||
|
||||
writel(qmax << 18, TMU_TEQ_HW_PROB_CFG2);
|
||||
writel(qmax >> 14, TMU_TEQ_HW_PROB_CFG3);
|
||||
}
|
||||
}
|
||||
writel(0x05, TMU_TEQ_DISABLE_DROPCHK);
|
||||
writel(0, TMU_CTRL);
|
||||
}
|
||||
|
||||
/**************************** HIF ***************************/
|
||||
/*
|
||||
* Enable hif tx DMA and interrupt
|
||||
*/
|
||||
void hif_tx_enable(void)
|
||||
{
|
||||
writel(HIF_CTRL_DMA_EN, HIF_TX_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable hif tx DMA and interrupt
|
||||
*/
|
||||
void hif_tx_disable(void)
|
||||
{
|
||||
u32 hif_int;
|
||||
|
||||
writel(0, HIF_TX_CTRL);
|
||||
|
||||
hif_int = readl(HIF_INT_ENABLE);
|
||||
hif_int &= HIF_TXPKT_INT_EN;
|
||||
writel(hif_int, HIF_INT_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Enable hif rx DMA and interrupt
|
||||
*/
|
||||
void hif_rx_enable(void)
|
||||
{
|
||||
writel((HIF_CTRL_DMA_EN | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable hif rx DMA and interrupt
|
||||
*/
|
||||
void hif_rx_disable(void)
|
||||
{
|
||||
u32 hif_int;
|
||||
|
||||
writel(0, HIF_RX_CTRL);
|
||||
|
||||
hif_int = readl(HIF_INT_ENABLE);
|
||||
hif_int &= HIF_RXPKT_INT_EN;
|
||||
writel(hif_int, HIF_INT_ENABLE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes HIF copy block.
|
||||
*/
|
||||
void hif_init(void)
|
||||
{
|
||||
/* Initialize HIF registers */
|
||||
writel(HIF_RX_POLL_CTRL_CYCLE << 16 | HIF_TX_POLL_CTRL_CYCLE,
|
||||
HIF_POLL_CTRL);
|
||||
/* Make HIF AXI transactions non-bufferable */
|
||||
writel(0x1, HIF_AXI_CTRL);
|
||||
}
|
291
drivers/net/pfe_eth/pfe_mdio.c
Normal file
291
drivers/net/pfe_eth/pfe_mdio.c
Normal file
|
@ -0,0 +1,291 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <dm/platform_data/pfe_dm_eth.h>
|
||||
#include <net.h>
|
||||
#include <net/pfe_eth/pfe_eth.h>
|
||||
|
||||
extern struct gemac_s gem_info[];
|
||||
#if defined(CONFIG_PHYLIB)
|
||||
|
||||
#define MDIO_TIMEOUT 5000
|
||||
static int pfe_write_addr(struct mii_dev *bus, int phy_addr, int dev_addr,
|
||||
int reg_addr)
|
||||
{
|
||||
void *reg_base = bus->priv;
|
||||
u32 devadr;
|
||||
u32 phy;
|
||||
u32 reg_data;
|
||||
int timeout = MDIO_TIMEOUT;
|
||||
|
||||
devadr = ((dev_addr & EMAC_MII_DATA_RA_MASK) << EMAC_MII_DATA_RA_SHIFT);
|
||||
phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
|
||||
|
||||
reg_data = (EMAC_MII_DATA_TA | phy | devadr | reg_addr);
|
||||
|
||||
writel(reg_data, reg_base + EMAC_MII_DATA_REG);
|
||||
|
||||
/*
|
||||
* wait for the MII interrupt
|
||||
*/
|
||||
while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
|
||||
if (timeout-- <= 0) {
|
||||
printf("Phy MDIO read/write timeout\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* clear MII interrupt
|
||||
*/
|
||||
writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pfe_phy_read(struct mii_dev *bus, int phy_addr, int dev_addr,
|
||||
int reg_addr)
|
||||
{
|
||||
void *reg_base = bus->priv;
|
||||
u32 reg;
|
||||
u32 phy;
|
||||
u32 reg_data;
|
||||
u16 val;
|
||||
int timeout = MDIO_TIMEOUT;
|
||||
|
||||
if (dev_addr == MDIO_DEVAD_NONE) {
|
||||
reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
|
||||
EMAC_MII_DATA_RA_SHIFT);
|
||||
} else {
|
||||
pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
|
||||
reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
|
||||
EMAC_MII_DATA_RA_SHIFT);
|
||||
}
|
||||
|
||||
phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
|
||||
|
||||
if (dev_addr == MDIO_DEVAD_NONE)
|
||||
reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_RD |
|
||||
EMAC_MII_DATA_TA | phy | reg);
|
||||
else
|
||||
reg_data = (EMAC_MII_DATA_OP_CL45_RD | EMAC_MII_DATA_TA |
|
||||
phy | reg);
|
||||
|
||||
writel(reg_data, reg_base + EMAC_MII_DATA_REG);
|
||||
|
||||
/*
|
||||
* wait for the MII interrupt
|
||||
*/
|
||||
while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
|
||||
if (timeout-- <= 0) {
|
||||
printf("Phy MDIO read/write timeout\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* clear MII interrupt
|
||||
*/
|
||||
writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
|
||||
|
||||
/*
|
||||
* it's now safe to read the PHY's register
|
||||
*/
|
||||
val = (u16)readl(reg_base + EMAC_MII_DATA_REG);
|
||||
debug("%s: %p phy: 0x%x reg:0x%08x val:%#x\n", __func__, reg_base,
|
||||
phy_addr, reg_addr, val);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int pfe_phy_write(struct mii_dev *bus, int phy_addr, int dev_addr,
|
||||
int reg_addr, u16 data)
|
||||
{
|
||||
void *reg_base = bus->priv;
|
||||
u32 reg;
|
||||
u32 phy;
|
||||
u32 reg_data;
|
||||
int timeout = MDIO_TIMEOUT;
|
||||
int val;
|
||||
|
||||
if (dev_addr == MDIO_DEVAD_NONE) {
|
||||
reg = ((reg_addr & EMAC_MII_DATA_RA_MASK) <<
|
||||
EMAC_MII_DATA_RA_SHIFT);
|
||||
} else {
|
||||
pfe_write_addr(bus, phy_addr, dev_addr, reg_addr);
|
||||
reg = ((dev_addr & EMAC_MII_DATA_RA_MASK) <<
|
||||
EMAC_MII_DATA_RA_SHIFT);
|
||||
}
|
||||
|
||||
phy = ((phy_addr & EMAC_MII_DATA_PA_MASK) << EMAC_MII_DATA_PA_SHIFT);
|
||||
|
||||
if (dev_addr == MDIO_DEVAD_NONE)
|
||||
reg_data = (EMAC_MII_DATA_ST | EMAC_MII_DATA_OP_WR |
|
||||
EMAC_MII_DATA_TA | phy | reg | data);
|
||||
else
|
||||
reg_data = (EMAC_MII_DATA_OP_CL45_WR | EMAC_MII_DATA_TA |
|
||||
phy | reg | data);
|
||||
|
||||
writel(reg_data, reg_base + EMAC_MII_DATA_REG);
|
||||
|
||||
/*
|
||||
* wait for the MII interrupt
|
||||
*/
|
||||
while (!(readl(reg_base + EMAC_IEVENT_REG) & EMAC_IEVENT_MII)) {
|
||||
if (timeout-- <= 0) {
|
||||
printf("Phy MDIO read/write timeout\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* clear MII interrupt
|
||||
*/
|
||||
writel(EMAC_IEVENT_MII, reg_base + EMAC_IEVENT_REG);
|
||||
|
||||
debug("%s: phy: %02x reg:%02x val:%#x\n", __func__, phy_addr,
|
||||
reg_addr, data);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static void pfe_configure_serdes(struct pfe_eth_dev *priv)
|
||||
{
|
||||
struct mii_dev bus;
|
||||
int value, sgmii_2500 = 0;
|
||||
struct gemac_s *gem = priv->gem;
|
||||
|
||||
if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500)
|
||||
sgmii_2500 = 1;
|
||||
|
||||
printf("%s %d\n", __func__, priv->gemac_port);
|
||||
|
||||
/* PCS configuration done with corresponding GEMAC */
|
||||
bus.priv = gem_info[priv->gemac_port].gemac_base;
|
||||
|
||||
pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x0);
|
||||
pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x1);
|
||||
pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x2);
|
||||
pfe_phy_read(&bus, 0, MDIO_DEVAD_NONE, 0x3);
|
||||
|
||||
/* Reset serdes */
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x0, 0x8000);
|
||||
|
||||
/* SGMII IF mode + AN enable only for 1G SGMII, not for 2.5G */
|
||||
value = PHY_SGMII_IF_MODE_SGMII;
|
||||
if (!sgmii_2500)
|
||||
value |= PHY_SGMII_IF_MODE_AN;
|
||||
else
|
||||
value |= PHY_SGMII_IF_MODE_SGMII_GBT;
|
||||
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x14, value);
|
||||
|
||||
/* Dev ability according to SGMII specification */
|
||||
value = PHY_SGMII_DEV_ABILITY_SGMII;
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x4, value);
|
||||
|
||||
/* These values taken from validation team */
|
||||
if (!sgmii_2500) {
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x0);
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0x400);
|
||||
} else {
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x13, 0x7);
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0x12, 0xa120);
|
||||
}
|
||||
|
||||
/* Restart AN */
|
||||
value = PHY_SGMII_CR_DEF_VAL;
|
||||
if (!sgmii_2500)
|
||||
value |= PHY_SGMII_CR_RESET_AN;
|
||||
/* Disable Auto neg for 2.5G SGMII as it doesn't support auto neg*/
|
||||
if (sgmii_2500)
|
||||
value &= ~PHY_SGMII_ENABLE_AN;
|
||||
pfe_phy_write(&bus, 0, MDIO_DEVAD_NONE, 0, value);
|
||||
}
|
||||
|
||||
int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id)
|
||||
{
|
||||
struct phy_device *phydev = NULL;
|
||||
struct udevice *dev = priv->dev;
|
||||
struct gemac_s *gem = priv->gem;
|
||||
struct ccsr_scfg *scfg = (struct ccsr_scfg *)CONFIG_SYS_FSL_SCFG_ADDR;
|
||||
|
||||
if (!gem->bus)
|
||||
return -1;
|
||||
|
||||
/* Configure SGMII PCS */
|
||||
if (gem->phy_mode == PHY_INTERFACE_MODE_SGMII ||
|
||||
gem->phy_mode == PHY_INTERFACE_MODE_SGMII_2500) {
|
||||
out_be32(&scfg->mdioselcr, 0x00000000);
|
||||
pfe_configure_serdes(priv);
|
||||
}
|
||||
|
||||
mdelay(100);
|
||||
|
||||
/* By this time on-chip SGMII initialization is done
|
||||
* we can switch mdio interface to external PHYs
|
||||
*/
|
||||
out_be32(&scfg->mdioselcr, 0x80000000);
|
||||
|
||||
phydev = phy_connect(gem->bus, phy_id, dev, gem->phy_mode);
|
||||
if (!phydev) {
|
||||
printf("phy_connect failed\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
phy_config(phydev);
|
||||
|
||||
priv->phydev = phydev;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info)
|
||||
{
|
||||
struct mii_dev *bus;
|
||||
int ret;
|
||||
u32 mdio_speed;
|
||||
u32 pclk = 250000000;
|
||||
|
||||
bus = mdio_alloc();
|
||||
if (!bus) {
|
||||
printf("mdio_alloc failed\n");
|
||||
return NULL;
|
||||
}
|
||||
bus->read = pfe_phy_read;
|
||||
bus->write = pfe_phy_write;
|
||||
|
||||
/* MAC1 MDIO used to communicate with external PHYS */
|
||||
bus->priv = mdio_info->reg_base;
|
||||
sprintf(bus->name, mdio_info->name);
|
||||
|
||||
/* configure mdio speed */
|
||||
mdio_speed = (DIV_ROUND_UP(pclk, 4000000) << EMAC_MII_SPEED_SHIFT);
|
||||
mdio_speed |= EMAC_HOLDTIME(0x5);
|
||||
writel(mdio_speed, mdio_info->reg_base + EMAC_MII_CTRL_REG);
|
||||
|
||||
ret = mdio_register(bus);
|
||||
if (ret) {
|
||||
printf("mdio_register failed\n");
|
||||
free(bus);
|
||||
return NULL;
|
||||
}
|
||||
return bus;
|
||||
}
|
||||
|
||||
void pfe_set_mdio(int dev_id, struct mii_dev *bus)
|
||||
{
|
||||
gem_info[dev_id].bus = bus;
|
||||
}
|
||||
|
||||
void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode)
|
||||
{
|
||||
gem_info[dev_id].phy_address = phy_id;
|
||||
gem_info[dev_id].phy_mode = phy_mode;
|
||||
}
|
|
@ -139,6 +139,16 @@ config PHY_NATSEMI
|
|||
config PHY_REALTEK
|
||||
bool "Realtek Ethernet PHYs support"
|
||||
|
||||
config RTL8211E_PINE64_GIGABIT_FIX
|
||||
bool "Fix gigabit throughput on some Pine64+ models"
|
||||
depends on PHY_REALTEK
|
||||
help
|
||||
Configure the Realtek RTL8211E found on some Pine64+ models differently to
|
||||
fix throughput on Gigabit links, turning off all internal delays in the
|
||||
process. The settings that this touches are not documented in the CONFREG
|
||||
section of the RTL8211E datasheet, but come from Realtek by way of the
|
||||
Pine64 engineering team.
|
||||
|
||||
config RTL8211X_PHY_FORCE_MASTER
|
||||
bool "Ethernet PHY RTL8211x: force 1000BASE-T master mode"
|
||||
depends on PHY_REALTEK
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
#include <config.h>
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <phy.h>
|
||||
|
||||
#ifndef CONFIG_PHYLIB_10G
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* Copyright 2014 Freescale Semiconductor, Inc.
|
||||
* Copyright 2018 NXP
|
||||
*
|
||||
*/
|
||||
|
||||
|
@ -27,6 +28,7 @@
|
|||
#error The Cortina PHY needs 10G support
|
||||
#endif
|
||||
|
||||
#ifndef CORTINA_NO_FW_UPLOAD
|
||||
struct cortina_reg_config cortina_reg_cfg[] = {
|
||||
/* CS4315_enable_sr_mode */
|
||||
{VILLA_GLOBAL_MSEQCLKCTRL, 0x8004},
|
||||
|
@ -215,12 +217,22 @@ void cs4340_upload_firmware(struct phy_device *phydev)
|
|||
phy_write(phydev, 0x00, fw_temp.reg_addr, fw_temp.reg_value);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int cs4340_phy_init(struct phy_device *phydev)
|
||||
{
|
||||
#ifndef CORTINA_NO_FW_UPLOAD
|
||||
int timeout = 100; /* 100ms */
|
||||
#endif
|
||||
int reg_value;
|
||||
|
||||
/*
|
||||
* Cortina phy has provision to store
|
||||
* phy firmware in attached dedicated EEPROM.
|
||||
* Boards designed with EEPROM attached to Cortina
|
||||
* does not require FW upload.
|
||||
*/
|
||||
#ifndef CORTINA_NO_FW_UPLOAD
|
||||
/* step1: BIST test */
|
||||
phy_write(phydev, 0x00, VILLA_GLOBAL_MSEQCLKCTRL, 0x0004);
|
||||
phy_write(phydev, 0x00, VILLA_GLOBAL_LINE_SOFT_RESET, 0x0000);
|
||||
|
@ -241,6 +253,7 @@ int cs4340_phy_init(struct phy_device *phydev)
|
|||
|
||||
/* setp2: upload ucode */
|
||||
cs4340_upload_firmware(phydev);
|
||||
#endif
|
||||
reg_value = phy_read(phydev, 0x00, VILLA_GLOBAL_DWNLD_CHECKSUM_STATUS);
|
||||
if (reg_value) {
|
||||
debug("%s checksum status failed.\n", __func__);
|
||||
|
@ -295,45 +308,33 @@ int phy_cortina_init(void)
|
|||
int get_phy_id(struct mii_dev *bus, int addr, int devad, u32 *phy_id)
|
||||
{
|
||||
int phy_reg;
|
||||
bool is_cortina_phy = false;
|
||||
|
||||
switch (addr) {
|
||||
#ifdef CORTINA_PHY_ADDR1
|
||||
case CORTINA_PHY_ADDR1:
|
||||
#endif
|
||||
#ifdef CORTINA_PHY_ADDR2
|
||||
case CORTINA_PHY_ADDR2:
|
||||
#endif
|
||||
#ifdef CORTINA_PHY_ADDR3
|
||||
case CORTINA_PHY_ADDR3:
|
||||
#endif
|
||||
#ifdef CORTINA_PHY_ADDR4
|
||||
case CORTINA_PHY_ADDR4:
|
||||
#endif
|
||||
is_cortina_phy = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Cortina PHY has non-standard offset of PHY ID registers */
|
||||
if (is_cortina_phy)
|
||||
phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_LSB);
|
||||
else
|
||||
phy_reg = bus->read(bus, addr, devad, MII_PHYSID1);
|
||||
|
||||
phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_LSB);
|
||||
if (phy_reg < 0)
|
||||
return -EIO;
|
||||
|
||||
*phy_id = (phy_reg & 0xffff) << 16;
|
||||
if (is_cortina_phy)
|
||||
phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_MSB);
|
||||
else
|
||||
phy_reg = bus->read(bus, addr, devad, MII_PHYSID2);
|
||||
|
||||
phy_reg = bus->read(bus, addr, 0, VILLA_GLOBAL_CHIP_ID_MSB);
|
||||
if (phy_reg < 0)
|
||||
return -EIO;
|
||||
*phy_id |= (phy_reg & 0xffff);
|
||||
|
||||
if (*phy_id == PHY_UID_CS4340)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* If Cortina PHY not detected,
|
||||
* try generic way to find PHY ID registers
|
||||
*/
|
||||
phy_reg = bus->read(bus, addr, devad, MII_PHYSID1);
|
||||
if (phy_reg < 0)
|
||||
return -EIO;
|
||||
*phy_id = (phy_reg & 0xffff) << 16;
|
||||
|
||||
phy_reg = bus->read(bus, addr, devad, MII_PHYSID2);
|
||||
if (phy_reg < 0)
|
||||
return -EIO;
|
||||
*phy_id |= (phy_reg & 0xffff);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include <phy.h>
|
||||
|
||||
#define PHY_RTL8211x_FORCE_MASTER BIT(1)
|
||||
#define PHY_RTL8211E_PINE64_GIGABIT_FIX BIT(2)
|
||||
|
||||
#define PHY_AUTONEGOTIATE_TIMEOUT 5000
|
||||
|
||||
|
@ -47,6 +48,13 @@
|
|||
#define MIIM_RTL8211F_PHYSTAT_SPDDONE 0x0800
|
||||
#define MIIM_RTL8211F_PHYSTAT_LINK 0x0004
|
||||
|
||||
#define MIIM_RTL8211E_CONFREG 0x1c
|
||||
#define MIIM_RTL8211E_CONFREG_TXD 0x0002
|
||||
#define MIIM_RTL8211E_CONFREG_RXD 0x0004
|
||||
#define MIIM_RTL8211E_CONFREG_MAGIC 0xb400 /* Undocumented */
|
||||
|
||||
#define MIIM_RTL8211E_EXT_PAGE_SELECT 0x1e
|
||||
|
||||
#define MIIM_RTL8211F_PAGE_SELECT 0x1f
|
||||
#define MIIM_RTL8211F_TX_DELAY 0x100
|
||||
#define MIIM_RTL8211F_LCR 0x10
|
||||
|
@ -60,6 +68,15 @@ static int rtl8211b_probe(struct phy_device *phydev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int rtl8211e_probe(struct phy_device *phydev)
|
||||
{
|
||||
#ifdef CONFIG_RTL8211E_PINE64_GIGABIT_FIX
|
||||
phydev->flags |= PHY_RTL8211E_PINE64_GIGABIT_FIX;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* RealTek RTL8211x */
|
||||
static int rtl8211x_config(struct phy_device *phydev)
|
||||
{
|
||||
|
@ -81,6 +98,22 @@ static int rtl8211x_config(struct phy_device *phydev)
|
|||
reg |= MIIM_RTL8211x_CTRL1000T_MASTER;
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MII_CTRL1000, reg);
|
||||
}
|
||||
if (phydev->flags & PHY_RTL8211E_PINE64_GIGABIT_FIX) {
|
||||
unsigned int reg;
|
||||
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT,
|
||||
7);
|
||||
phy_write(phydev, MDIO_DEVAD_NONE,
|
||||
MIIM_RTL8211E_EXT_PAGE_SELECT, 0xa4);
|
||||
reg = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG);
|
||||
/* Ensure both internal delays are turned off */
|
||||
reg &= ~(MIIM_RTL8211E_CONFREG_TXD | MIIM_RTL8211E_CONFREG_RXD);
|
||||
/* Flip the magic undocumented bits */
|
||||
reg |= MIIM_RTL8211E_CONFREG_MAGIC;
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211E_CONFREG, reg);
|
||||
phy_write(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211F_PAGE_SELECT,
|
||||
0);
|
||||
}
|
||||
/* read interrupt status just to clear it */
|
||||
phy_read(phydev, MDIO_DEVAD_NONE, MIIM_RTL8211x_PHY_INER);
|
||||
|
||||
|
@ -279,6 +312,7 @@ static struct phy_driver RTL8211E_driver = {
|
|||
.uid = 0x1cc915,
|
||||
.mask = 0xffffff,
|
||||
.features = PHY_GBIT_FEATURES,
|
||||
.probe = &rtl8211e_probe,
|
||||
.config = &rtl8211x_config,
|
||||
.startup = &rtl8211e_startup,
|
||||
.shutdown = &genphy_shutdown,
|
||||
|
|
|
@ -23,6 +23,7 @@ config USB_ETHER_ASIX88179
|
|||
config USB_ETHER_LAN75XX
|
||||
bool "Microchip LAN75XX support"
|
||||
depends on USB_HOST_ETHER
|
||||
depends on PHYLIB
|
||||
---help---
|
||||
Say Y here if you would like to support Microchip LAN75XX Hi-Speed
|
||||
USB 2.0 to 10/100/1000 Gigabit Ethernet controller.
|
||||
|
@ -32,6 +33,7 @@ config USB_ETHER_LAN75XX
|
|||
config USB_ETHER_LAN78XX
|
||||
bool "Microchip LAN78XX support"
|
||||
depends on USB_HOST_ETHER
|
||||
depends on PHYLIB
|
||||
---help---
|
||||
Say Y here if you would like to support Microchip LAN78XX USB 3.1
|
||||
Gen 1 to 10/100/1000 Gigabit Ethernet controller.
|
||||
|
|
|
@ -9,15 +9,6 @@
|
|||
|
||||
#include "ls1012a_common.h"
|
||||
|
||||
/* PFE Ethernet */
|
||||
#ifdef CONFIG_FSL_PFE
|
||||
#define EMAC1_PHY_ADDR 0x2
|
||||
#define EMAC2_PHY_ADDR 0x1
|
||||
#define CONFIG_PHYLIB
|
||||
#define CONFIG_PHYLIB_10G
|
||||
#define CONFIG_PHY_AQUANTIA
|
||||
#endif
|
||||
|
||||
/* DDR */
|
||||
#define CONFIG_DIMM_SLOTS_PER_CTLR 1
|
||||
#define CONFIG_CHIP_SELECTS_PER_CTRL 1
|
||||
|
@ -110,7 +101,7 @@
|
|||
|
||||
#undef CONFIG_BOOTCOMMAND
|
||||
#if defined(CONFIG_QSPI_BOOT) || defined(CONFIG_SD_BOOT_QSPI)
|
||||
#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run qspi_bootcmd; " \
|
||||
#define CONFIG_BOOTCOMMAND "pfe stop;run distro_bootcmd; run qspi_bootcmd; " \
|
||||
"env exists secureboot && esbc_halt;"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -112,9 +112,9 @@
|
|||
"kernel_size=0x2800000\0" \
|
||||
|
||||
#undef CONFIG_BOOTCOMMAND
|
||||
#define CONFIG_BOOTCOMMAND "sf probe 0:0; sf read $kernel_load "\
|
||||
"$kernel_start $kernel_size && "\
|
||||
"bootm $kernel_load"
|
||||
#define CONFIG_BOOTCOMMAND "pfe stop; sf probe 0:0; sf read $kernel_load "\
|
||||
"$kernel_start $kernel_size && "\
|
||||
"bootm $kernel_load"
|
||||
|
||||
/* Monitor Command Prompt */
|
||||
#define CONFIG_SYS_CBSIZE 512 /* Console I/O Buffer Size */
|
||||
|
|
|
@ -68,7 +68,7 @@
|
|||
"$kernel_addr $kernel_size && bootm $load_addr#$board\0"
|
||||
|
||||
#undef CONFIG_BOOTCOMMAND
|
||||
#define CONFIG_BOOTCOMMAND "run distro_bootcmd;run qspi_bootcmd"
|
||||
#define CONFIG_BOOTCOMMAND "pfe stop;run distro_bootcmd;run qspi_bootcmd"
|
||||
|
||||
#define CONFIG_CMD_MEMINFO
|
||||
#define CONFIG_CMD_MEMTEST
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
*/
|
||||
|
||||
#define I2C_MUX_IO_ADDR 0x24
|
||||
#define I2C_MUX_IO2_ADDR 0x25
|
||||
#define I2C_MUX_IO_0 0
|
||||
#define I2C_MUX_IO_1 1
|
||||
#define SW_BOOT_MASK 0x03
|
||||
|
@ -39,6 +40,9 @@
|
|||
#define SW_REV_C2 0xD8
|
||||
#define SW_REV_D 0xD0
|
||||
#define SW_REV_E 0xC8
|
||||
#define __PHY_MASK 0xF9
|
||||
#define __PHY_ETH2_MASK 0xFB
|
||||
#define __PHY_ETH1_MASK 0xFD
|
||||
|
||||
/* MMC */
|
||||
#ifdef CONFIG_MMC
|
||||
|
@ -113,7 +117,7 @@
|
|||
"bootm $load_addr#$board\0"
|
||||
|
||||
#undef CONFIG_BOOTCOMMAND
|
||||
#define CONFIG_BOOTCOMMAND "run distro_bootcmd; run qspi_bootcmd; " \
|
||||
#define CONFIG_BOOTCOMMAND "pfe stop; run distro_bootcmd; run qspi_bootcmd; "\
|
||||
"env exists secureboot && esbc_halt;"
|
||||
|
||||
#include <asm/fsl_secure_boot.h>
|
||||
|
|
21
include/dm/platform_data/pfe_dm_eth.h
Normal file
21
include/dm/platform_data/pfe_dm_eth.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __PFE_DM_ETH_H__
|
||||
#define __PFE_DM_ETH_H__
|
||||
#include <net.h>
|
||||
|
||||
struct pfe_ddr_address {
|
||||
void *ddr_pfe_baseaddr;
|
||||
unsigned long ddr_pfe_phys_baseaddr;
|
||||
};
|
||||
|
||||
struct pfe_eth_pdata {
|
||||
struct eth_pdata pfe_eth_pdata_mac;
|
||||
struct pfe_ddr_address pfe_ddr_addr;
|
||||
};
|
||||
#endif /* __PFE_DM_ETH_H__ */
|
77
include/net/pfe_eth/pfe/cbus.h
Normal file
77
include/net/pfe_eth/pfe/cbus.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _CBUS_H_
|
||||
#define _CBUS_H_
|
||||
|
||||
#include "cbus/emac.h"
|
||||
#include "cbus/gpi.h"
|
||||
#include "cbus/bmu.h"
|
||||
#include "cbus/hif.h"
|
||||
#include "cbus/tmu_csr.h"
|
||||
#include "cbus/class_csr.h"
|
||||
#include "cbus/hif_nocpy.h"
|
||||
#include "cbus/util_csr.h"
|
||||
|
||||
#define CBUS_BASE_ADDR ((void *)CONFIG_SYS_FSL_PFE_ADDR)
|
||||
|
||||
/* PFE Control and Status Register Desciption */
|
||||
#define EMAC1_BASE_ADDR (CBUS_BASE_ADDR + 0x200000)
|
||||
#define EGPI1_BASE_ADDR (CBUS_BASE_ADDR + 0x210000)
|
||||
#define EMAC2_BASE_ADDR (CBUS_BASE_ADDR + 0x220000)
|
||||
#define EGPI2_BASE_ADDR (CBUS_BASE_ADDR + 0x230000)
|
||||
#define BMU1_BASE_ADDR (CBUS_BASE_ADDR + 0x240000)
|
||||
#define BMU2_BASE_ADDR (CBUS_BASE_ADDR + 0x250000)
|
||||
#define ARB_BASE_ADDR (CBUS_BASE_ADDR + 0x260000)
|
||||
#define DDR_CONFIG_BASE_ADDR (CBUS_BASE_ADDR + 0x270000)
|
||||
#define HIF_BASE_ADDR (CBUS_BASE_ADDR + 0x280000)
|
||||
#define HGPI_BASE_ADDR (CBUS_BASE_ADDR + 0x290000)
|
||||
#define LMEM_BASE_ADDR (CBUS_BASE_ADDR + 0x300000)
|
||||
#define LMEM_SIZE 0x10000
|
||||
#define LMEM_END (LMEM_BASE_ADDR + LMEM_SIZE)
|
||||
#define TMU_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x310000)
|
||||
#define CLASS_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x320000)
|
||||
#define HIF_NOCPY_BASE_ADDR (CBUS_BASE_ADDR + 0x350000)
|
||||
#define UTIL_CSR_BASE_ADDR (CBUS_BASE_ADDR + 0x360000)
|
||||
#define CBUS_GPT_BASE_ADDR (CBUS_BASE_ADDR + 0x370000)
|
||||
|
||||
/*
|
||||
* defgroup XXX_MEM_ACCESS_ADDR PE memory access through CSR
|
||||
* XXX_MEM_ACCESS_ADDR register bit definitions.
|
||||
*/
|
||||
/* Internal Memory Write. */
|
||||
#define PE_MEM_ACCESS_WRITE BIT(31)
|
||||
/* Internal Memory Read. */
|
||||
#define PE_MEM_ACCESS_READ (0 << 31)
|
||||
|
||||
#define PE_MEM_ACCESS_IMEM BIT(15)
|
||||
#define PE_MEM_ACCESS_DMEM BIT(16)
|
||||
|
||||
/* Byte Enables of the Internal memory access. These are interpred in BE */
|
||||
#define PE_MEM_ACCESS_BYTE_ENABLE(offset, size) (((((1 << (size)) - 1) << (4 \
|
||||
- (offset) - (size)))\
|
||||
& 0xf) << 24)
|
||||
|
||||
/* PFE cores states */
|
||||
#define CORE_DISABLE 0x00000000
|
||||
#define CORE_ENABLE 0x00000001
|
||||
#define CORE_SW_RESET 0x00000002
|
||||
|
||||
/* LMEM defines */
|
||||
#define LMEM_HDR_SIZE 0x0010
|
||||
#define LMEM_BUF_SIZE_LN2 0x7
|
||||
#define LMEM_BUF_SIZE BIT(LMEM_BUF_SIZE_LN2)
|
||||
|
||||
/* DDR defines */
|
||||
#define DDR_HDR_SIZE 0x0100
|
||||
#define DDR_BUF_SIZE_LN2 0xb
|
||||
#define DDR_BUF_SIZE BIT(DDR_BUF_SIZE_LN2)
|
||||
|
||||
/* Clock generation through PLL */
|
||||
#define PLL_CLK_EN 1
|
||||
|
||||
#endif /* _CBUS_H_ */
|
40
include/net/pfe_eth/pfe/cbus/bmu.h
Normal file
40
include/net/pfe_eth/pfe/cbus/bmu.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _BMU_H_
|
||||
#define _BMU_H_
|
||||
|
||||
#define BMU_VERSION 0x000
|
||||
#define BMU_CTRL 0x004
|
||||
#define BMU_UCAST_CONFIG 0x008
|
||||
#define BMU_UCAST_BASE_ADDR 0x00c
|
||||
#define BMU_BUF_SIZE 0x010
|
||||
#define BMU_BUF_CNT 0x014
|
||||
#define BMU_THRES 0x018
|
||||
#define BMU_INT_SRC 0x020
|
||||
#define BMU_INT_ENABLE 0x024
|
||||
#define BMU_ALLOC_CTRL 0x030
|
||||
#define BMU_FREE_CTRL 0x034
|
||||
#define BMU_FREE_ERR_ADDR 0x038
|
||||
#define BMU_CURR_BUF_CNT 0x03c
|
||||
#define BMU_MCAST_CNT 0x040
|
||||
#define BMU_MCAST_ALLOC_CTRL 0x044
|
||||
#define BMU_REM_BUF_CNT 0x048
|
||||
#define BMU_LOW_WATERMARK 0x050
|
||||
#define BMU_HIGH_WATERMARK 0x054
|
||||
#define BMU_INT_MEM_ACCESS 0x100
|
||||
|
||||
struct bmu_cfg {
|
||||
u32 baseaddr;
|
||||
u32 count;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
#define BMU1_BUF_SIZE LMEM_BUF_SIZE_LN2
|
||||
#define BMU2_BUF_SIZE DDR_BUF_SIZE_LN2
|
||||
|
||||
#endif /* _BMU_H_ */
|
180
include/net/pfe_eth/pfe/cbus/class_csr.h
Normal file
180
include/net/pfe_eth/pfe/cbus/class_csr.h
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _CLASS_CSR_H_
|
||||
#define _CLASS_CSR_H_
|
||||
|
||||
/*
|
||||
* @file class_csr.h.
|
||||
* class_csr - block containing all the classifier control and status register.
|
||||
* Mapped on CBUS and accessible from all PE's and ARM.
|
||||
*/
|
||||
#define CLASS_VERSION (CLASS_CSR_BASE_ADDR + 0x000)
|
||||
#define CLASS_TX_CTRL (CLASS_CSR_BASE_ADDR + 0x004)
|
||||
#define CLASS_INQ_PKTPTR (CLASS_CSR_BASE_ADDR + 0x010)
|
||||
/* (ddr_hdr_size[24:16], lmem_hdr_size[5:0]) */
|
||||
#define CLASS_HDR_SIZE (CLASS_CSR_BASE_ADDR + 0x014)
|
||||
/* LMEM header size for the Classifier block.
|
||||
* Data in the LMEM is written from this offset.
|
||||
*/
|
||||
#define CLASS_HDR_SIZE_LMEM(off) ((off) & 0x3f)
|
||||
/* DDR header size for the Classifier block.
|
||||
* Data in the DDR is written from this offset.
|
||||
*/
|
||||
#define CLASS_HDR_SIZE_DDR(off) (((off) & 0x1ff) << 16)
|
||||
|
||||
/* DMEM address of first [15:0] and second [31:16] buffers on QB side. */
|
||||
#define CLASS_PE0_QB_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x020)
|
||||
/* DMEM address of third [15:0] and fourth [31:16] buffers on QB side. */
|
||||
#define CLASS_PE0_QB_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x024)
|
||||
|
||||
/* DMEM address of first [15:0] and second [31:16] buffers on RO side. */
|
||||
#define CLASS_PE0_RO_DM_ADDR0 (CLASS_CSR_BASE_ADDR + 0x060)
|
||||
/* DMEM address of third [15:0] and fourth [31:16] buffers on RO side. */
|
||||
#define CLASS_PE0_RO_DM_ADDR1 (CLASS_CSR_BASE_ADDR + 0x064)
|
||||
|
||||
/*
|
||||
* @name Class PE memory access. Allows external PE's and HOST to
|
||||
* read/write PMEM/DMEM memory ranges for each classifier PE.
|
||||
*/
|
||||
#define CLASS_MEM_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x100)
|
||||
/* Internal Memory Access Write Data [31:0] */
|
||||
#define CLASS_MEM_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x104)
|
||||
/* Internal Memory Access Read Data [31:0] */
|
||||
#define CLASS_MEM_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x108)
|
||||
#define CLASS_TM_INQ_ADDR (CLASS_CSR_BASE_ADDR + 0x114)
|
||||
#define CLASS_PE_STATUS (CLASS_CSR_BASE_ADDR + 0x118)
|
||||
|
||||
#define CLASS_PE_SYS_CLK_RATIO (CLASS_CSR_BASE_ADDR + 0x200)
|
||||
#define CLASS_AFULL_THRES (CLASS_CSR_BASE_ADDR + 0x204)
|
||||
#define CLASS_GAP_BETWEEN_READS (CLASS_CSR_BASE_ADDR + 0x208)
|
||||
#define CLASS_MAX_BUF_CNT (CLASS_CSR_BASE_ADDR + 0x20c)
|
||||
#define CLASS_TSQ_FIFO_THRES (CLASS_CSR_BASE_ADDR + 0x210)
|
||||
#define CLASS_TSQ_MAX_CNT (CLASS_CSR_BASE_ADDR + 0x214)
|
||||
#define CLASS_IRAM_DATA_0 (CLASS_CSR_BASE_ADDR + 0x218)
|
||||
#define CLASS_IRAM_DATA_1 (CLASS_CSR_BASE_ADDR + 0x21c)
|
||||
#define CLASS_IRAM_DATA_2 (CLASS_CSR_BASE_ADDR + 0x220)
|
||||
#define CLASS_IRAM_DATA_3 (CLASS_CSR_BASE_ADDR + 0x224)
|
||||
|
||||
#define CLASS_BUS_ACCESS_ADDR (CLASS_CSR_BASE_ADDR + 0x228)
|
||||
/* bit 23:0 of PE peripheral address are stored in CLASS_BUS_ACCESS_ADDR */
|
||||
#define CLASS_BUS_ACCESS_ADDR_MASK (0x0001FFFF)
|
||||
|
||||
#define CLASS_BUS_ACCESS_WDATA (CLASS_CSR_BASE_ADDR + 0x22c)
|
||||
#define CLASS_BUS_ACCESS_RDATA (CLASS_CSR_BASE_ADDR + 0x230)
|
||||
|
||||
/*
|
||||
* (route_entry_size[9:0], route_hash_size[23:16]
|
||||
* (this is actually ln2(size)))
|
||||
*/
|
||||
#define CLASS_ROUTE_HASH_ENTRY_SIZE (CLASS_CSR_BASE_ADDR + 0x234)
|
||||
#define CLASS_ROUTE_ENTRY_SIZE(size) ((size) & 0x1ff)
|
||||
#define CLASS_ROUTE_HASH_SIZE(hash_bits) (((hash_bits) & 0xff) << 16)
|
||||
|
||||
#define CLASS_ROUTE_TABLE_BASE (CLASS_CSR_BASE_ADDR + 0x238)
|
||||
#define CLASS_ROUTE_MULTI (CLASS_CSR_BASE_ADDR + 0x23c)
|
||||
#define CLASS_SMEM_OFFSET (CLASS_CSR_BASE_ADDR + 0x240)
|
||||
#define CLASS_LMEM_BUF_SIZE (CLASS_CSR_BASE_ADDR + 0x244)
|
||||
#define CLASS_VLAN_ID (CLASS_CSR_BASE_ADDR + 0x248)
|
||||
#define CLASS_BMU1_BUF_FREE (CLASS_CSR_BASE_ADDR + 0x24c)
|
||||
#define CLASS_USE_TMU_INQ (CLASS_CSR_BASE_ADDR + 0x250)
|
||||
#define CLASS_VLAN_ID1 (CLASS_CSR_BASE_ADDR + 0x254)
|
||||
|
||||
#define CLASS_BUS_ACCESS_BASE (CLASS_CSR_BASE_ADDR + 0x258)
|
||||
/* bit 31:24 of PE peripheral address are stored in CLASS_BUS_ACCESS_BASE */
|
||||
#define CLASS_BUS_ACCESS_BASE_MASK (0xFF000000)
|
||||
|
||||
#define CLASS_HIF_PARSE (CLASS_CSR_BASE_ADDR + 0x25c)
|
||||
|
||||
#define CLASS_HOST_PE0_GP (CLASS_CSR_BASE_ADDR + 0x260)
|
||||
#define CLASS_PE0_GP (CLASS_CSR_BASE_ADDR + 0x264)
|
||||
#define CLASS_HOST_PE1_GP (CLASS_CSR_BASE_ADDR + 0x268)
|
||||
#define CLASS_PE1_GP (CLASS_CSR_BASE_ADDR + 0x26c)
|
||||
#define CLASS_HOST_PE2_GP (CLASS_CSR_BASE_ADDR + 0x270)
|
||||
#define CLASS_PE2_GP (CLASS_CSR_BASE_ADDR + 0x274)
|
||||
#define CLASS_HOST_PE3_GP (CLASS_CSR_BASE_ADDR + 0x278)
|
||||
#define CLASS_PE3_GP (CLASS_CSR_BASE_ADDR + 0x27c)
|
||||
#define CLASS_HOST_PE4_GP (CLASS_CSR_BASE_ADDR + 0x280)
|
||||
#define CLASS_PE4_GP (CLASS_CSR_BASE_ADDR + 0x284)
|
||||
#define CLASS_HOST_PE5_GP (CLASS_CSR_BASE_ADDR + 0x288)
|
||||
#define CLASS_PE5_GP (CLASS_CSR_BASE_ADDR + 0x28c)
|
||||
|
||||
#define CLASS_PE_INT_SRC (CLASS_CSR_BASE_ADDR + 0x290)
|
||||
#define CLASS_PE_INT_ENABLE (CLASS_CSR_BASE_ADDR + 0x294)
|
||||
|
||||
#define CLASS_TPID0_TPID1 (CLASS_CSR_BASE_ADDR + 0x298)
|
||||
#define CLASS_TPID2 (CLASS_CSR_BASE_ADDR + 0x29c)
|
||||
|
||||
#define CLASS_L4_CHKSUM_ADDR (CLASS_CSR_BASE_ADDR + 0x2a0)
|
||||
|
||||
#define CLASS_PE0_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a4)
|
||||
#define CLASS_PE1_DEBUG (CLASS_CSR_BASE_ADDR + 0x2a8)
|
||||
#define CLASS_PE2_DEBUG (CLASS_CSR_BASE_ADDR + 0x2ac)
|
||||
#define CLASS_PE3_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b0)
|
||||
#define CLASS_PE4_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b4)
|
||||
#define CLASS_PE5_DEBUG (CLASS_CSR_BASE_ADDR + 0x2b8)
|
||||
|
||||
#define CLASS_STATE (CLASS_CSR_BASE_ADDR + 0x2bc)
|
||||
#define CLASS_AXI_CTRL (CLASS_CSR_BASE_ADDR + 0x2d0)
|
||||
|
||||
/* CLASS defines */
|
||||
#define CLASS_PBUF_SIZE 0x100 /* Fixed by hardware */
|
||||
#define CLASS_PBUF_HEADER_OFFSET 0x80 /* Can be configured */
|
||||
|
||||
#define CLASS_PBUF0_BASE_ADDR 0x000 /* Can be configured */
|
||||
/* Can be configured */
|
||||
#define CLASS_PBUF1_BASE_ADDR (CLASS_PBUF0_BASE_ADDR + CLASS_PBUF_SIZE)
|
||||
/* Can be configured */
|
||||
#define CLASS_PBUF2_BASE_ADDR (CLASS_PBUF1_BASE_ADDR + CLASS_PBUF_SIZE)
|
||||
/* Can be configured */
|
||||
#define CLASS_PBUF3_BASE_ADDR (CLASS_PBUF2_BASE_ADDR + CLASS_PBUF_SIZE)
|
||||
|
||||
#define CLASS_PBUF0_HEADER_BASE_ADDR (CLASS_PBUF0_BASE_ADDR +\
|
||||
CLASS_PBUF_HEADER_OFFSET)
|
||||
#define CLASS_PBUF1_HEADER_BASE_ADDR (CLASS_PBUF1_BASE_ADDR +\
|
||||
CLASS_PBUF_HEADER_OFFSET)
|
||||
#define CLASS_PBUF2_HEADER_BASE_ADDR (CLASS_PBUF2_BASE_ADDR +\
|
||||
CLASS_PBUF_HEADER_OFFSET)
|
||||
#define CLASS_PBUF3_HEADER_BASE_ADDR (CLASS_PBUF3_BASE_ADDR +\
|
||||
CLASS_PBUF_HEADER_OFFSET)
|
||||
|
||||
#define CLASS_PE0_RO_DM_ADDR0_VAL ((CLASS_PBUF1_BASE_ADDR << 16) |\
|
||||
CLASS_PBUF0_BASE_ADDR)
|
||||
#define CLASS_PE0_RO_DM_ADDR1_VAL ((CLASS_PBUF3_BASE_ADDR << 16) |\
|
||||
CLASS_PBUF2_BASE_ADDR)
|
||||
|
||||
#define CLASS_PE0_QB_DM_ADDR0_VAL ((CLASS_PBUF1_HEADER_BASE_ADDR << 16)\
|
||||
| CLASS_PBUF0_HEADER_BASE_ADDR)
|
||||
#define CLASS_PE0_QB_DM_ADDR1_VAL ((CLASS_PBUF3_HEADER_BASE_ADDR << 16)\
|
||||
| CLASS_PBUF2_HEADER_BASE_ADDR)
|
||||
|
||||
#define CLASS_ROUTE_SIZE 128
|
||||
#define CLASS_ROUTE_HASH_BITS 20
|
||||
#define CLASS_ROUTE_HASH_MASK (BIT(CLASS_ROUTE_HASH_BITS) - 1)
|
||||
|
||||
#define TWO_LEVEL_ROUTE BIT(0)
|
||||
#define PHYNO_IN_HASH BIT(1)
|
||||
#define HW_ROUTE_FETCH BIT(3)
|
||||
#define HW_BRIDGE_FETCH BIT(5)
|
||||
#define IP_ALIGNED BIT(6)
|
||||
#define ARC_HIT_CHECK_EN BIT(7)
|
||||
#define CLASS_TOE BIT(11)
|
||||
#define HASH_CRC_PORT BIT(12)
|
||||
#define HASH_CRC_IP BIT(13)
|
||||
#define HASH_CRC_PORT_IP GENMASK(13, 12)
|
||||
#define QB2BUS_LE BIT(15)
|
||||
|
||||
#define TCP_CHKSUM_DROP BIT(0)
|
||||
#define UDP_CHKSUM_DROP BIT(1)
|
||||
#define IPV4_CHKSUM_DROP BIT(9)
|
||||
|
||||
struct class_cfg {
|
||||
u32 route_table_baseaddr;
|
||||
u32 route_table_hash_bits;
|
||||
};
|
||||
|
||||
#endif /* _CLASS_CSR_H_ */
|
140
include/net/pfe_eth/pfe/cbus/emac.h
Normal file
140
include/net/pfe_eth/pfe/cbus/emac.h
Normal file
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _EMAC_H_
|
||||
#define _EMAC_H_
|
||||
|
||||
#define EMAC_IEVENT_REG 0x004
|
||||
#define EMAC_IMASK_REG 0x008
|
||||
#define EMAC_R_DES_ACTIVE_REG 0x010
|
||||
#define EMAC_X_DES_ACTIVE_REG 0x014
|
||||
#define EMAC_ECNTRL_REG 0x024
|
||||
#define EMAC_MII_DATA_REG 0x040
|
||||
#define EMAC_MII_CTRL_REG 0x044
|
||||
#define EMAC_MIB_CTRL_STS_REG 0x064
|
||||
#define EMAC_RCNTRL_REG 0x084
|
||||
#define EMAC_TCNTRL_REG 0x0C4
|
||||
#define EMAC_PHY_ADDR_LOW 0x0E4
|
||||
#define EMAC_PHY_ADDR_HIGH 0x0E8
|
||||
#define EMAC_TFWR_STR_FWD 0x144
|
||||
#define EMAC_RX_SECTIOM_FULL 0x190
|
||||
#define EMAC_TX_SECTION_EMPTY 0x1A0
|
||||
#define EMAC_TRUNC_FL 0x1B0
|
||||
|
||||
/* GEMAC definitions and settings */
|
||||
#define EMAC_PORT_0 0
|
||||
#define EMAC_PORT_1 1
|
||||
|
||||
/* GEMAC Bit definitions */
|
||||
#define EMAC_IEVENT_HBERR BIT(31)
|
||||
#define EMAC_IEVENT_BABR BIT(30)
|
||||
#define EMAC_IEVENT_BABT BIT(29)
|
||||
#define EMAC_IEVENT_GRA BIT(28)
|
||||
#define EMAC_IEVENT_TXF BIT(27)
|
||||
#define EMAC_IEVENT_TXB BIT(26)
|
||||
#define EMAC_IEVENT_RXF BIT(25)
|
||||
#define EMAC_IEVENT_RXB BIT(24)
|
||||
#define EMAC_IEVENT_MII BIT(23)
|
||||
#define EMAC_IEVENT_EBERR BIT(22)
|
||||
#define EMAC_IEVENT_LC BIT(21)
|
||||
#define EMAC_IEVENT_RL BIT(20)
|
||||
#define EMAC_IEVENT_UN BIT(19)
|
||||
|
||||
#define EMAC_IMASK_HBERR BIT(31)
|
||||
#define EMAC_IMASK_BABR BIT(30)
|
||||
#define EMAC_IMASKT_BABT BIT(29)
|
||||
#define EMAC_IMASK_GRA BIT(28)
|
||||
#define EMAC_IMASKT_TXF BIT(27)
|
||||
#define EMAC_IMASK_TXB BIT(26)
|
||||
#define EMAC_IMASKT_RXF BIT(25)
|
||||
#define EMAC_IMASK_RXB BIT(24)
|
||||
#define EMAC_IMASK_MII BIT(23)
|
||||
#define EMAC_IMASK_EBERR BIT(22)
|
||||
#define EMAC_IMASK_LC BIT(21)
|
||||
#define EMAC_IMASKT_RL BIT(20)
|
||||
#define EMAC_IMASK_UN BIT(19)
|
||||
|
||||
#define EMAC_RCNTRL_MAX_FL_SHIFT 16
|
||||
#define EMAC_RCNTRL_LOOP BIT(0)
|
||||
#define EMAC_RCNTRL_DRT BIT(1)
|
||||
#define EMAC_RCNTRL_MII_MODE BIT(2)
|
||||
#define EMAC_RCNTRL_PROM BIT(3)
|
||||
#define EMAC_RCNTRL_BC_REJ BIT(4)
|
||||
#define EMAC_RCNTRL_FCE BIT(5)
|
||||
#define EMAC_RCNTRL_RGMII BIT(6)
|
||||
#define EMAC_RCNTRL_SGMII BIT(7)
|
||||
#define EMAC_RCNTRL_RMII BIT(8)
|
||||
#define EMAC_RCNTRL_RMII_10T BIT(9)
|
||||
#define EMAC_RCNTRL_CRC_FWD BIT(10)
|
||||
|
||||
#define EMAC_TCNTRL_GTS BIT(0)
|
||||
#define EMAC_TCNTRL_HBC BIT(1)
|
||||
#define EMAC_TCNTRL_FDEN BIT(2)
|
||||
#define EMAC_TCNTRL_TFC_PAUSE BIT(3)
|
||||
#define EMAC_TCNTRL_RFC_PAUSE BIT(4)
|
||||
|
||||
#define EMAC_ECNTRL_RESET BIT(0) /* reset the EMAC */
|
||||
#define EMAC_ECNTRL_ETHER_EN BIT(1) /* enable the EMAC */
|
||||
#define EMAC_ECNTRL_SPEED BIT(5)
|
||||
#define EMAC_ECNTRL_DBSWAP BIT(8)
|
||||
|
||||
#define EMAC_X_WMRK_STRFWD BIT(8)
|
||||
|
||||
#define EMAC_X_DES_ACTIVE_TDAR BIT(24)
|
||||
#define EMAC_R_DES_ACTIVE_RDAR BIT(24)
|
||||
|
||||
#define EMAC_TFWR (0x4)
|
||||
#define EMAC_RX_SECTION_FULL_32 (0x5)
|
||||
#define EMAC_TRUNC_FL_16K (0x3FFF)
|
||||
#define EMAC_TX_SECTION_EMPTY_30 (0x30)
|
||||
#define EMAC_MIBC_NO_CLR_NO_DIS (0x0)
|
||||
|
||||
/*
|
||||
* The possible operating speeds of the MAC, currently supporting 10, 100 and
|
||||
* 1000Mb modes.
|
||||
*/
|
||||
enum mac_speed {PFE_MAC_SPEED_10M, PFE_MAC_SPEED_100M, PFE_MAC_SPEED_1000M,
|
||||
PFE_MAC_SPEED_1000M_PCS};
|
||||
|
||||
/* MII-related definitios */
|
||||
#define EMAC_MII_DATA_ST 0x40000000 /* Start of frame delimiter */
|
||||
#define EMAC_MII_DATA_OP_RD 0x20000000 /* Perform a read operation */
|
||||
#define EMAC_MII_DATA_OP_CL45_RD 0x30000000 /* Perform a read operation */
|
||||
#define EMAC_MII_DATA_OP_WR 0x10000000 /* Perform a write operation */
|
||||
#define EMAC_MII_DATA_OP_CL45_WR 0x10000000 /* Perform a write operation */
|
||||
#define EMAC_MII_DATA_PA_MSK 0x0f800000 /* PHY Address field mask */
|
||||
#define EMAC_MII_DATA_RA_MSK 0x007c0000 /* PHY Register field mask */
|
||||
#define EMAC_MII_DATA_TA 0x00020000 /* Turnaround */
|
||||
#define EMAC_MII_DATA_DATAMSK 0x0000ffff /* PHY data field */
|
||||
|
||||
#define EMAC_MII_DATA_RA_SHIFT 18 /* MII Register address bits */
|
||||
#define EMAC_MII_DATA_RA_MASK 0x1F /* MII Register address mask */
|
||||
#define EMAC_MII_DATA_PA_SHIFT 23 /* MII PHY address bits */
|
||||
#define EMAC_MII_DATA_PA_MASK 0x1F /* MII PHY address mask */
|
||||
|
||||
#define EMAC_MII_DATA_RA(v) ((v & EMAC_MII_DATA_RA_MASK) <<\
|
||||
EMAC_MII_DATA_RA_SHIFT)
|
||||
#define EMAC_MII_DATA_PA(v) ((v & EMAC_MII_DATA_RA_MASK) <<\
|
||||
EMAC_MII_DATA_PA_SHIFT)
|
||||
#define EMAC_MII_DATA(v) (v & 0xffff)
|
||||
|
||||
#define EMAC_MII_SPEED_SHIFT 1
|
||||
#define EMAC_HOLDTIME_SHIFT 8
|
||||
#define EMAC_HOLDTIME_MASK 0x7
|
||||
#define EMAC_HOLDTIME(v) ((v & EMAC_HOLDTIME_MASK) << EMAC_HOLDTIME_SHIFT)
|
||||
|
||||
/* 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
|
||||
#define PHY_SGMII_IF_MODE_SGMII_GBT 0x0008
|
||||
#define PHY_SGMII_ENABLE_AN 0x1000
|
||||
|
||||
#endif /* _EMAC_H_ */
|
62
include/net/pfe_eth/pfe/cbus/gpi.h
Normal file
62
include/net/pfe_eth/pfe/cbus/gpi.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _GPI_H_
|
||||
#define _GPI_H_
|
||||
|
||||
#define GPI_VERSION 0x00
|
||||
#define GPI_CTRL 0x04
|
||||
#define GPI_RX_CONFIG 0x08
|
||||
#define GPI_HDR_SIZE 0x0c
|
||||
#define GPI_BUF_SIZE 0x10
|
||||
#define GPI_LMEM_ALLOC_ADDR 0x14
|
||||
#define GPI_LMEM_FREE_ADDR 0x18
|
||||
#define GPI_DDR_ALLOC_ADDR 0x1c
|
||||
#define GPI_DDR_FREE_ADDR 0x20
|
||||
#define GPI_CLASS_ADDR 0x24
|
||||
#define GPI_DRX_FIFO 0x28
|
||||
#define GPI_TRX_FIFO 0x2c
|
||||
#define GPI_INQ_PKTPTR 0x30
|
||||
#define GPI_DDR_DATA_OFFSET 0x34
|
||||
#define GPI_LMEM_DATA_OFFSET 0x38
|
||||
#define GPI_TMLF_TX 0x4c
|
||||
#define GPI_DTX_ASEQ 0x50
|
||||
#define GPI_FIFO_STATUS 0x54
|
||||
#define GPI_FIFO_DEBUG 0x58
|
||||
#define GPI_TX_PAUSE_TIME 0x5c
|
||||
#define GPI_LMEM_SEC_BUF_DATA_OFFSET 0x60
|
||||
#define GPI_DDR_SEC_BUF_DATA_OFFSET 0x64
|
||||
#define GPI_TOE_CHKSUM_EN 0x68
|
||||
#define GPI_OVERRUN_DROPCNT 0x6c
|
||||
#define GPI_AXI_CTRL 0x70
|
||||
|
||||
struct gpi_cfg {
|
||||
u32 lmem_rtry_cnt;
|
||||
u32 tmlf_txthres;
|
||||
u32 aseq_len;
|
||||
};
|
||||
|
||||
/* GPI commons defines */
|
||||
#define GPI_LMEM_BUF_EN 0x1
|
||||
#define GPI_DDR_BUF_EN 0x1
|
||||
|
||||
/* EGPI 1 defines */
|
||||
#define EGPI1_LMEM_RTRY_CNT 0x40
|
||||
#define EGPI1_TMLF_TXTHRES 0xBC
|
||||
#define EGPI1_ASEQ_LEN 0x50
|
||||
|
||||
/* EGPI 2 defines */
|
||||
#define EGPI2_LMEM_RTRY_CNT 0x40
|
||||
#define EGPI2_TMLF_TXTHRES 0xBC
|
||||
#define EGPI2_ASEQ_LEN 0x40
|
||||
|
||||
/* HGPI defines */
|
||||
#define HGPI_LMEM_RTRY_CNT 0x40
|
||||
#define HGPI_TMLF_TXTHRES 0xBC
|
||||
#define HGPI_ASEQ_LEN 0x40
|
||||
|
||||
#endif /* _GPI_H_ */
|
68
include/net/pfe_eth/pfe/cbus/hif.h
Normal file
68
include/net/pfe_eth/pfe/cbus/hif.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _HIF_H_
|
||||
#define _HIF_H_
|
||||
|
||||
/*
|
||||
* @file hif.h.
|
||||
* hif - PFE hif block control and status register.
|
||||
* Mapped on CBUS and accessible from all PE's and ARM.
|
||||
*/
|
||||
#define HIF_VERSION (HIF_BASE_ADDR + 0x00)
|
||||
#define HIF_TX_CTRL (HIF_BASE_ADDR + 0x04)
|
||||
#define HIF_TX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x08)
|
||||
#define HIF_TX_ALLOC (HIF_BASE_ADDR + 0x0c)
|
||||
#define HIF_TX_BDP_ADDR (HIF_BASE_ADDR + 0x10)
|
||||
#define HIF_TX_STATUS (HIF_BASE_ADDR + 0x14)
|
||||
#define HIF_RX_CTRL (HIF_BASE_ADDR + 0x20)
|
||||
#define HIF_RX_BDP_ADDR (HIF_BASE_ADDR + 0x24)
|
||||
#define HIF_RX_STATUS (HIF_BASE_ADDR + 0x30)
|
||||
#define HIF_INT_SRC (HIF_BASE_ADDR + 0x34)
|
||||
#define HIF_INT_ENABLE (HIF_BASE_ADDR + 0x38)
|
||||
#define HIF_POLL_CTRL (HIF_BASE_ADDR + 0x3c)
|
||||
#define HIF_RX_CURR_BD_ADDR (HIF_BASE_ADDR + 0x40)
|
||||
#define HIF_RX_ALLOC (HIF_BASE_ADDR + 0x44)
|
||||
#define HIF_TX_DMA_STATUS (HIF_BASE_ADDR + 0x48)
|
||||
#define HIF_RX_DMA_STATUS (HIF_BASE_ADDR + 0x4c)
|
||||
#define HIF_INT_COAL (HIF_BASE_ADDR + 0x50)
|
||||
#define HIF_AXI_CTRL (HIF_BASE_ADDR + 0x54)
|
||||
|
||||
/* HIF_TX_CTRL bits */
|
||||
#define HIF_CTRL_DMA_EN BIT(0)
|
||||
#define HIF_CTRL_BDP_POLL_CTRL_EN BIT(1)
|
||||
#define HIF_CTRL_BDP_CH_START_WSTB BIT(2)
|
||||
|
||||
/* HIF_RX_STATUS bits */
|
||||
#define BDP_CSR_RX_DMA_ACTV BIT(16)
|
||||
|
||||
/* HIF_INT_ENABLE bits */
|
||||
#define HIF_INT_EN BIT(0)
|
||||
#define HIF_RXBD_INT_EN BIT(1)
|
||||
#define HIF_RXPKT_INT_EN BIT(2)
|
||||
#define HIF_TXBD_INT_EN BIT(3)
|
||||
#define HIF_TXPKT_INT_EN BIT(4)
|
||||
|
||||
/* HIF_POLL_CTRL bits*/
|
||||
#define HIF_RX_POLL_CTRL_CYCLE 0x0400
|
||||
#define HIF_TX_POLL_CTRL_CYCLE 0x0400
|
||||
|
||||
/* Buffer descriptor control bits */
|
||||
#define BD_CTRL_BUFLEN_MASK (0xffff)
|
||||
#define BD_BUF_LEN(x) (x & BD_CTRL_BUFLEN_MASK)
|
||||
#define BD_CTRL_CBD_INT_EN BIT(16)
|
||||
#define BD_CTRL_PKT_INT_EN BIT(17)
|
||||
#define BD_CTRL_LIFM BIT(18)
|
||||
#define BD_CTRL_LAST_BD BIT(19)
|
||||
#define BD_CTRL_DIR BIT(20)
|
||||
#define BD_CTRL_PKT_XFER BIT(24)
|
||||
#define BD_CTRL_DESC_EN BIT(31)
|
||||
#define BD_CTRL_PARSE_DISABLE BIT(25)
|
||||
#define BD_CTRL_BRFETCH_DISABLE BIT(26)
|
||||
#define BD_CTRL_RTFETCH_DISABLE BIT(27)
|
||||
|
||||
#endif /* _HIF_H_ */
|
40
include/net/pfe_eth/pfe/cbus/hif_nocpy.h
Normal file
40
include/net/pfe_eth/pfe/cbus/hif_nocpy.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _HIF_NOCPY_H_
|
||||
#define _HIF_NOCPY_H_
|
||||
|
||||
#define HIF_NOCPY_VERSION (HIF_NOCPY_BASE_ADDR + 0x00)
|
||||
#define HIF_NOCPY_TX_CTRL (HIF_NOCPY_BASE_ADDR + 0x04)
|
||||
#define HIF_NOCPY_TX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x08)
|
||||
#define HIF_NOCPY_TX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x0c)
|
||||
#define HIF_NOCPY_TX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x10)
|
||||
#define HIF_NOCPY_TX_STATUS (HIF_NOCPY_BASE_ADDR + 0x14)
|
||||
#define HIF_NOCPY_RX_CTRL (HIF_NOCPY_BASE_ADDR + 0x20)
|
||||
#define HIF_NOCPY_RX_BDP_ADDR (HIF_NOCPY_BASE_ADDR + 0x24)
|
||||
#define HIF_NOCPY_RX_STATUS (HIF_NOCPY_BASE_ADDR + 0x30)
|
||||
#define HIF_NOCPY_INT_SRC (HIF_NOCPY_BASE_ADDR + 0x34)
|
||||
#define HIF_NOCPY_INT_ENABLE (HIF_NOCPY_BASE_ADDR + 0x38)
|
||||
#define HIF_NOCPY_POLL_CTRL (HIF_NOCPY_BASE_ADDR + 0x3c)
|
||||
#define HIF_NOCPY_RX_CURR_BD_ADDR (HIF_NOCPY_BASE_ADDR + 0x40)
|
||||
#define HIF_NOCPY_RX_ALLOC (HIF_NOCPY_BASE_ADDR + 0x44)
|
||||
#define HIF_NOCPY_TX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x48)
|
||||
#define HIF_NOCPY_RX_DMA_STATUS (HIF_NOCPY_BASE_ADDR + 0x4c)
|
||||
#define HIF_NOCPY_RX_INQ0_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x50)
|
||||
#define HIF_NOCPY_RX_INQ1_PKTPTR (HIF_NOCPY_BASE_ADDR + 0x54)
|
||||
#define HIF_NOCPY_TX_PORT_NO (HIF_NOCPY_BASE_ADDR + 0x60)
|
||||
#define HIF_NOCPY_LMEM_ALLOC_ADDR (HIF_NOCPY_BASE_ADDR + 0x64)
|
||||
#define HIF_NOCPY_CLASS_ADDR (HIF_NOCPY_BASE_ADDR + 0x68)
|
||||
#define HIF_NOCPY_TMU_PORT0_ADDR (HIF_NOCPY_BASE_ADDR + 0x70)
|
||||
#define HIF_NOCPY_TMU_PORT1_ADDR (HIF_NOCPY_BASE_ADDR + 0x74)
|
||||
#define HIF_NOCPY_TMU_PORT2_ADDR (HIF_NOCPY_BASE_ADDR + 0x7c)
|
||||
#define HIF_NOCPY_TMU_PORT3_ADDR (HIF_NOCPY_BASE_ADDR + 0x80)
|
||||
#define HIF_NOCPY_TMU_PORT4_ADDR (HIF_NOCPY_BASE_ADDR + 0x84)
|
||||
#define HIF_NOCPY_INT_COAL (HIF_NOCPY_BASE_ADDR + 0x90)
|
||||
#define HIF_NOCPY_AXI_CTRL (HIF_NOCPY_BASE_ADDR + 0x94)
|
||||
|
||||
#endif /* _HIF_NOCPY_H_ */
|
148
include/net/pfe_eth/pfe/cbus/tmu_csr.h
Normal file
148
include/net/pfe_eth/pfe/cbus/tmu_csr.h
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _TMU_CSR_H_
|
||||
#define _TMU_CSR_H_
|
||||
|
||||
#define TMU_VERSION (TMU_CSR_BASE_ADDR + 0x000)
|
||||
#define TMU_INQ_WATERMARK (TMU_CSR_BASE_ADDR + 0x004)
|
||||
#define TMU_PHY_INQ_PKTPTR (TMU_CSR_BASE_ADDR + 0x008)
|
||||
#define TMU_PHY_INQ_PKTINFO (TMU_CSR_BASE_ADDR + 0x00c)
|
||||
#define TMU_PHY_INQ_FIFO_CNT (TMU_CSR_BASE_ADDR + 0x010)
|
||||
#define TMU_SYS_GENERIC_CONTROL (TMU_CSR_BASE_ADDR + 0x014)
|
||||
#define TMU_SYS_GENERIC_STATUS (TMU_CSR_BASE_ADDR + 0x018)
|
||||
#define TMU_SYS_GEN_CON0 (TMU_CSR_BASE_ADDR + 0x01c)
|
||||
#define TMU_SYS_GEN_CON1 (TMU_CSR_BASE_ADDR + 0x020)
|
||||
#define TMU_SYS_GEN_CON2 (TMU_CSR_BASE_ADDR + 0x024)
|
||||
#define TMU_SYS_GEN_CON3 (TMU_CSR_BASE_ADDR + 0x028)
|
||||
#define TMU_SYS_GEN_CON4 (TMU_CSR_BASE_ADDR + 0x02c)
|
||||
#define TMU_TEQ_DISABLE_DROPCHK (TMU_CSR_BASE_ADDR + 0x030)
|
||||
#define TMU_TEQ_CTRL (TMU_CSR_BASE_ADDR + 0x034)
|
||||
#define TMU_TEQ_QCFG (TMU_CSR_BASE_ADDR + 0x038)
|
||||
#define TMU_TEQ_DROP_STAT (TMU_CSR_BASE_ADDR + 0x03c)
|
||||
#define TMU_TEQ_QAVG (TMU_CSR_BASE_ADDR + 0x040)
|
||||
#define TMU_TEQ_WREG_PROB (TMU_CSR_BASE_ADDR + 0x044)
|
||||
#define TMU_TEQ_TRANS_STAT (TMU_CSR_BASE_ADDR + 0x048)
|
||||
#define TMU_TEQ_HW_PROB_CFG0 (TMU_CSR_BASE_ADDR + 0x04c)
|
||||
#define TMU_TEQ_HW_PROB_CFG1 (TMU_CSR_BASE_ADDR + 0x050)
|
||||
#define TMU_TEQ_HW_PROB_CFG2 (TMU_CSR_BASE_ADDR + 0x054)
|
||||
#define TMU_TEQ_HW_PROB_CFG3 (TMU_CSR_BASE_ADDR + 0x058)
|
||||
#define TMU_TEQ_HW_PROB_CFG4 (TMU_CSR_BASE_ADDR + 0x05c)
|
||||
#define TMU_TEQ_HW_PROB_CFG5 (TMU_CSR_BASE_ADDR + 0x060)
|
||||
#define TMU_TEQ_HW_PROB_CFG6 (TMU_CSR_BASE_ADDR + 0x064)
|
||||
#define TMU_TEQ_HW_PROB_CFG7 (TMU_CSR_BASE_ADDR + 0x068)
|
||||
#define TMU_TEQ_HW_PROB_CFG8 (TMU_CSR_BASE_ADDR + 0x06c)
|
||||
#define TMU_TEQ_HW_PROB_CFG9 (TMU_CSR_BASE_ADDR + 0x070)
|
||||
#define TMU_TEQ_HW_PROB_CFG10 (TMU_CSR_BASE_ADDR + 0x074)
|
||||
#define TMU_TEQ_HW_PROB_CFG11 (TMU_CSR_BASE_ADDR + 0x078)
|
||||
#define TMU_TEQ_HW_PROB_CFG12 (TMU_CSR_BASE_ADDR + 0x07c)
|
||||
#define TMU_TEQ_HW_PROB_CFG13 (TMU_CSR_BASE_ADDR + 0x080)
|
||||
#define TMU_TEQ_HW_PROB_CFG14 (TMU_CSR_BASE_ADDR + 0x084)
|
||||
#define TMU_TEQ_HW_PROB_CFG15 (TMU_CSR_BASE_ADDR + 0x088)
|
||||
#define TMU_TEQ_HW_PROB_CFG16 (TMU_CSR_BASE_ADDR + 0x08c)
|
||||
#define TMU_TEQ_HW_PROB_CFG17 (TMU_CSR_BASE_ADDR + 0x090)
|
||||
#define TMU_TEQ_HW_PROB_CFG18 (TMU_CSR_BASE_ADDR + 0x094)
|
||||
#define TMU_TEQ_HW_PROB_CFG19 (TMU_CSR_BASE_ADDR + 0x098)
|
||||
#define TMU_TEQ_HW_PROB_CFG20 (TMU_CSR_BASE_ADDR + 0x09c)
|
||||
#define TMU_TEQ_HW_PROB_CFG21 (TMU_CSR_BASE_ADDR + 0x0a0)
|
||||
#define TMU_TEQ_HW_PROB_CFG22 (TMU_CSR_BASE_ADDR + 0x0a4)
|
||||
#define TMU_TEQ_HW_PROB_CFG23 (TMU_CSR_BASE_ADDR + 0x0a8)
|
||||
#define TMU_TEQ_HW_PROB_CFG24 (TMU_CSR_BASE_ADDR + 0x0ac)
|
||||
#define TMU_TEQ_HW_PROB_CFG25 (TMU_CSR_BASE_ADDR + 0x0b0)
|
||||
#define TMU_TDQ_IIFG_CFG (TMU_CSR_BASE_ADDR + 0x0b4)
|
||||
/* [9:0] Scheduler Enable for each of the scheduler in the TDQ.
|
||||
* This is a global Enable for all schedulers in PHY0
|
||||
*/
|
||||
#define TMU_TDQ0_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x0b8)
|
||||
#define TMU_LLM_CTRL (TMU_CSR_BASE_ADDR + 0x0bc)
|
||||
#define TMU_LLM_BASE_ADDR (TMU_CSR_BASE_ADDR + 0x0c0)
|
||||
#define TMU_LLM_QUE_LEN (TMU_CSR_BASE_ADDR + 0x0c4)
|
||||
#define TMU_LLM_QUE_HEADPTR (TMU_CSR_BASE_ADDR + 0x0c8)
|
||||
#define TMU_LLM_QUE_TAILPTR (TMU_CSR_BASE_ADDR + 0x0cc)
|
||||
#define TMU_LLM_QUE_DROPCNT (TMU_CSR_BASE_ADDR + 0x0d0)
|
||||
#define TMU_INT_EN (TMU_CSR_BASE_ADDR + 0x0d4)
|
||||
#define TMU_INT_SRC (TMU_CSR_BASE_ADDR + 0x0d8)
|
||||
#define TMU_INQ_STAT (TMU_CSR_BASE_ADDR + 0x0dc)
|
||||
#define TMU_CTRL (TMU_CSR_BASE_ADDR + 0x0e0)
|
||||
|
||||
/* [31] Mem Access Command. 0 = Internal Memory Read, 1 = Internal
|
||||
* memory Write [27:24] Byte Enables of the Internal memory access [23:0]
|
||||
* Address of the internal memory. This address is used to access both the
|
||||
* PM and DM of all the PE's
|
||||
*/
|
||||
#define TMU_MEM_ACCESS_ADDR (TMU_CSR_BASE_ADDR + 0x0e4)
|
||||
|
||||
/* Internal Memory Access Write Data */
|
||||
#define TMU_MEM_ACCESS_WDATA (TMU_CSR_BASE_ADDR + 0x0e8)
|
||||
/* Internal Memory Access Read Data. The commands are blocked at the
|
||||
* mem_access only
|
||||
*/
|
||||
#define TMU_MEM_ACCESS_RDATA (TMU_CSR_BASE_ADDR + 0x0ec)
|
||||
|
||||
/* [31:0] PHY0 in queue address (must be initialized with one of the
|
||||
* xxx_INQ_PKTPTR cbus addresses)
|
||||
*/
|
||||
#define TMU_PHY0_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f0)
|
||||
/* [31:0] PHY1 in queue address (must be initialized with one of the
|
||||
* xxx_INQ_PKTPTR cbus addresses)
|
||||
*/
|
||||
#define TMU_PHY1_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0f4)
|
||||
/* [31:0] PHY3 in queue address (must be initialized with one of the
|
||||
* xxx_INQ_PKTPTR cbus addresses)
|
||||
*/
|
||||
#define TMU_PHY3_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x0fc)
|
||||
#define TMU_BMU_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x100)
|
||||
#define TMU_TX_CTRL (TMU_CSR_BASE_ADDR + 0x104)
|
||||
|
||||
#define TMU_PE_SYS_CLK_RATIO (TMU_CSR_BASE_ADDR + 0x114)
|
||||
#define TMU_PE_STATUS (TMU_CSR_BASE_ADDR + 0x118)
|
||||
#define TMU_TEQ_MAX_THRESHOLD (TMU_CSR_BASE_ADDR + 0x11c)
|
||||
|
||||
/* [31:0] PHY4 in queue address (must be initialized with one of the
|
||||
* xxx_INQ_PKTPTR cbus addresses)
|
||||
*/
|
||||
#define TMU_PHY4_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x134)
|
||||
|
||||
/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. This
|
||||
* is a global Enable for all schedulers in PHY1
|
||||
*/
|
||||
#define TMU_TDQ1_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x138)
|
||||
/* [9:0] Scheduler Enable for each of the scheduler in the TDQ. This
|
||||
* is a global Enable for all schedulers in PHY3
|
||||
*/
|
||||
#define TMU_TDQ3_SCH_CTRL (TMU_CSR_BASE_ADDR + 0x140)
|
||||
|
||||
#define TMU_BMU_BUF_SIZE (TMU_CSR_BASE_ADDR + 0x144)
|
||||
/* [31:0] PHY5 in queue address (must be initialized with one of the
|
||||
* xxx_INQ_PKTPTR cbus addresses)
|
||||
*/
|
||||
#define TMU_PHY5_INQ_ADDR (TMU_CSR_BASE_ADDR + 0x148)
|
||||
|
||||
#define TMU_AXI_CTRL (TMU_CSR_BASE_ADDR + 0x17c)
|
||||
|
||||
#define SW_RESET BIT(0) /* Global software reset */
|
||||
#define INQ_RESET BIT(2)
|
||||
#define TEQ_RESET BIT(3)
|
||||
#define TDQ_RESET BIT(4)
|
||||
#define PE_RESET BIT(5)
|
||||
#define MEM_INIT BIT(6)
|
||||
#define MEM_INIT_DONE BIT(7)
|
||||
#define LLM_INIT BIT(8)
|
||||
#define LLM_INIT_DONE BIT(9)
|
||||
#define ECC_MEM_INIT_DONE BIT(10)
|
||||
|
||||
struct tmu_cfg {
|
||||
u32 llm_base_addr;
|
||||
u32 llm_queue_len;
|
||||
};
|
||||
|
||||
/* Not HW related for pfe_ctrl/pfe common defines */
|
||||
#define DEFAULT_MAX_QDEPTH 80
|
||||
#define DEFAULT_Q0_QDEPTH 511 /* We keep 1 large queue for host tx qos */
|
||||
#define DEFAULT_TMU3_QDEPTH 127
|
||||
|
||||
#endif /* _TMU_CSR_H_ */
|
47
include/net/pfe_eth/pfe/cbus/util_csr.h
Normal file
47
include/net/pfe_eth/pfe/cbus/util_csr.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _UTIL_CSR_H_
|
||||
#define _UTIL_CSR_H_
|
||||
|
||||
#define UTIL_VERSION (UTIL_CSR_BASE_ADDR + 0x000)
|
||||
#define UTIL_TX_CTRL (UTIL_CSR_BASE_ADDR + 0x004)
|
||||
#define UTIL_INQ_PKTPTR (UTIL_CSR_BASE_ADDR + 0x010)
|
||||
|
||||
#define UTIL_HDR_SIZE (UTIL_CSR_BASE_ADDR + 0x014)
|
||||
|
||||
#define UTIL_PE0_QB_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x020)
|
||||
#define UTIL_PE0_QB_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x024)
|
||||
#define UTIL_PE0_RO_DM_ADDR0 (UTIL_CSR_BASE_ADDR + 0x060)
|
||||
#define UTIL_PE0_RO_DM_ADDR1 (UTIL_CSR_BASE_ADDR + 0x064)
|
||||
|
||||
#define UTIL_MEM_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x100)
|
||||
#define UTIL_MEM_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x104)
|
||||
#define UTIL_MEM_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x108)
|
||||
|
||||
#define UTIL_TM_INQ_ADDR (UTIL_CSR_BASE_ADDR + 0x114)
|
||||
#define UTIL_PE_STATUS (UTIL_CSR_BASE_ADDR + 0x118)
|
||||
|
||||
#define UTIL_PE_SYS_CLK_RATIO (UTIL_CSR_BASE_ADDR + 0x200)
|
||||
#define UTIL_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x204)
|
||||
#define UTIL_GAP_BETWEEN_READS (UTIL_CSR_BASE_ADDR + 0x208)
|
||||
#define UTIL_MAX_BUF_CNT (UTIL_CSR_BASE_ADDR + 0x20c)
|
||||
#define UTIL_TSQ_FIFO_THRES (UTIL_CSR_BASE_ADDR + 0x210)
|
||||
#define UTIL_TSQ_MAX_CNT (UTIL_CSR_BASE_ADDR + 0x214)
|
||||
#define UTIL_IRAM_DATA_0 (UTIL_CSR_BASE_ADDR + 0x218)
|
||||
#define UTIL_IRAM_DATA_1 (UTIL_CSR_BASE_ADDR + 0x21c)
|
||||
#define UTIL_IRAM_DATA_2 (UTIL_CSR_BASE_ADDR + 0x220)
|
||||
#define UTIL_IRAM_DATA_3 (UTIL_CSR_BASE_ADDR + 0x224)
|
||||
|
||||
#define UTIL_BUS_ACCESS_ADDR (UTIL_CSR_BASE_ADDR + 0x228)
|
||||
#define UTIL_BUS_ACCESS_WDATA (UTIL_CSR_BASE_ADDR + 0x22c)
|
||||
#define UTIL_BUS_ACCESS_RDATA (UTIL_CSR_BASE_ADDR + 0x230)
|
||||
|
||||
#define UTIL_INQ_AFULL_THRES (UTIL_CSR_BASE_ADDR + 0x234)
|
||||
#define UTIL_AXI_CTRL (UTIL_CSR_BASE_ADDR + 0x240)
|
||||
|
||||
#endif /* _UTIL_CSR_H_ */
|
163
include/net/pfe_eth/pfe/pfe_hw.h
Normal file
163
include/net/pfe_eth/pfe/pfe_hw.h
Normal file
|
@ -0,0 +1,163 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _PFE_H_
|
||||
#define _PFE_H_
|
||||
|
||||
#include <elf.h>
|
||||
#include "cbus.h"
|
||||
|
||||
#define PFE_RESET_WA
|
||||
|
||||
#define CLASS_DMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20))
|
||||
/* Only valid for mem access register interface */
|
||||
#define CLASS_IMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20))
|
||||
#define CLASS_DMEM_SIZE 0x00002000
|
||||
#define CLASS_IMEM_SIZE 0x00008000
|
||||
|
||||
#define TMU_DMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20))
|
||||
/* Only valid for mem access register interface */
|
||||
#define TMU_IMEM_BASE_ADDR(i) (0x00000000 + ((i) << 20))
|
||||
#define TMU_DMEM_SIZE 0x00000800
|
||||
#define TMU_IMEM_SIZE 0x00002000
|
||||
|
||||
#define UTIL_DMEM_BASE_ADDR 0x00000000
|
||||
#define UTIL_DMEM_SIZE 0x00002000
|
||||
|
||||
#define PE_LMEM_BASE_ADDR 0xc3010000
|
||||
#define PE_LMEM_SIZE 0x8000
|
||||
#define PE_LMEM_END (PE_LMEM_BASE_ADDR + PE_LMEM_SIZE)
|
||||
|
||||
#define DMEM_BASE_ADDR 0x00000000
|
||||
#define DMEM_SIZE 0x2000 /* TMU has less... */
|
||||
#define DMEM_END (DMEM_BASE_ADDR + DMEM_SIZE)
|
||||
|
||||
#define PMEM_BASE_ADDR 0x00010000
|
||||
#define PMEM_SIZE 0x8000 /* TMU has less... */
|
||||
#define PMEM_END (PMEM_BASE_ADDR + PMEM_SIZE)
|
||||
|
||||
/* Memory ranges check from PE point of view/memory map */
|
||||
#define IS_DMEM(addr, len) (((unsigned long)(addr) >= DMEM_BASE_ADDR) &&\
|
||||
(((unsigned long)(addr) +\
|
||||
(len)) <= DMEM_END))
|
||||
#define IS_PMEM(addr, len) (((unsigned long)(addr) >= PMEM_BASE_ADDR) &&\
|
||||
(((unsigned long)(addr) +\
|
||||
(len)) <= PMEM_END))
|
||||
#define IS_PE_LMEM(addr, len) (((unsigned long)(addr) >= PE_LMEM_BASE_ADDR\
|
||||
) && (((unsigned long)(addr)\
|
||||
+ (len)) <= PE_LMEM_END))
|
||||
|
||||
#define IS_PFE_LMEM(addr, len) (((unsigned long)(addr) >=\
|
||||
CBUS_VIRT_TO_PFE(LMEM_BASE_ADDR)) &&\
|
||||
(((unsigned long)(addr) + (len)) <=\
|
||||
CBUS_VIRT_TO_PFE(LMEM_END)))
|
||||
#define IS_PHYS_DDR(addr, len) (((unsigned long)(addr) >=\
|
||||
PFE_DDR_PHYS_BASE_ADDR) &&\
|
||||
(((unsigned long)(addr) + (len)) <=\
|
||||
PFE_DDR_PHYS_END))
|
||||
|
||||
/* Host View Address */
|
||||
extern void *ddr_pfe_base_addr;
|
||||
|
||||
/* PFE View Address */
|
||||
/* DDR physical base address as seen by PE's. */
|
||||
#define PFE_DDR_PHYS_BASE_ADDR 0x03800000
|
||||
#define PFE_DDR_PHYS_SIZE 0xC000000
|
||||
#define PFE_DDR_PHYS_END (PFE_DDR_PHYS_BASE_ADDR + PFE_DDR_PHYS_SIZE)
|
||||
/* CBUS physical base address as seen by PE's. */
|
||||
#define PFE_CBUS_PHYS_BASE_ADDR 0xc0000000
|
||||
|
||||
/* Host<->PFE Mapping */
|
||||
#define DDR_PFE_TO_VIRT(p) ((unsigned long int)((p) + 0x80000000))
|
||||
#define CBUS_VIRT_TO_PFE(v) (((v) - CBUS_BASE_ADDR) +\
|
||||
PFE_CBUS_PHYS_BASE_ADDR)
|
||||
#define CBUS_PFE_TO_VIRT(p) (((p) - PFE_CBUS_PHYS_BASE_ADDR) +\
|
||||
CBUS_BASE_ADDR)
|
||||
|
||||
enum {
|
||||
CLASS0_ID = 0,
|
||||
CLASS1_ID,
|
||||
CLASS2_ID,
|
||||
CLASS3_ID,
|
||||
CLASS4_ID,
|
||||
CLASS5_ID,
|
||||
|
||||
TMU0_ID,
|
||||
TMU1_ID,
|
||||
TMU2_ID,
|
||||
TMU3_ID,
|
||||
MAX_PE
|
||||
};
|
||||
|
||||
#define CLASS_MASK (BIT(CLASS0_ID) | BIT(CLASS1_ID) | BIT(CLASS2_ID)\
|
||||
| BIT(CLASS3_ID) | BIT(CLASS4_ID) |\
|
||||
BIT(CLASS5_ID))
|
||||
#define CLASS_MAX_ID CLASS5_ID
|
||||
|
||||
#define TMU_MASK (BIT(TMU0_ID) | BIT(TMU1_ID) | BIT(TMU3_ID))
|
||||
#define TMU_MAX_ID TMU3_ID
|
||||
|
||||
/*
|
||||
* PE information.
|
||||
* Structure containing PE's specific information. It is used to create
|
||||
* generic C functions common to all PEs.
|
||||
* Before using the library functions this structure needs to be
|
||||
* initialized with the different registers virtual addresses
|
||||
* (according to the ARM MMU mmaping). The default initialization supports a
|
||||
* virtual == physical mapping.
|
||||
*
|
||||
*/
|
||||
struct pe_info {
|
||||
u32 dmem_base_addr; /* PE's dmem base address */
|
||||
u32 pmem_base_addr; /* PE's pmem base address */
|
||||
u32 pmem_size; /* PE's pmem size */
|
||||
|
||||
void *mem_access_wdata; /* PE's _MEM_ACCESS_WDATA
|
||||
* register address
|
||||
*/
|
||||
void *mem_access_addr; /* PE's _MEM_ACCESS_ADDR
|
||||
* register address
|
||||
*/
|
||||
void *mem_access_rdata; /* PE's _MEM_ACCESS_RDATA
|
||||
* register address
|
||||
*/
|
||||
};
|
||||
|
||||
void pe_lmem_read(u32 *dst, u32 len, u32 offset);
|
||||
void pe_lmem_write(u32 *src, u32 len, u32 offset);
|
||||
|
||||
u32 pe_pmem_read(int id, u32 addr, u8 size);
|
||||
void pe_dmem_write(int id, u32 val, u32 addr, u8 size);
|
||||
u32 pe_dmem_read(int id, u32 addr, u8 size);
|
||||
|
||||
int pe_load_elf_section(int id, const void *data, Elf32_Shdr *shdr);
|
||||
|
||||
void pfe_lib_init(void);
|
||||
|
||||
void bmu_init(void *base, struct bmu_cfg *cfg);
|
||||
void bmu_enable(void *base);
|
||||
|
||||
void gpi_init(void *base, struct gpi_cfg *cfg);
|
||||
void gpi_enable(void *base);
|
||||
void gpi_disable(void *base);
|
||||
|
||||
void class_init(struct class_cfg *cfg);
|
||||
void class_enable(void);
|
||||
void class_disable(void);
|
||||
|
||||
void tmu_init(struct tmu_cfg *cfg);
|
||||
void tmu_enable(u32 pe_mask);
|
||||
void tmu_disable(u32 pe_mask);
|
||||
|
||||
void hif_init(void);
|
||||
void hif_tx_enable(void);
|
||||
void hif_tx_disable(void);
|
||||
void hif_rx_enable(void);
|
||||
void hif_rx_disable(void);
|
||||
void hif_rx_desc_disable(void);
|
||||
|
||||
#endif /* _PFE_H_ */
|
59
include/net/pfe_eth/pfe_driver.h
Normal file
59
include/net/pfe_eth/pfe_driver.h
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __PFE_DRIVER_H__
|
||||
#define __PFE_DRIVER_H__
|
||||
|
||||
#include <net/pfe_eth/pfe/pfe_hw.h>
|
||||
#include <dm/platform_data/pfe_dm_eth.h>
|
||||
|
||||
#define HIF_RX_DESC_NT 64
|
||||
#define HIF_TX_DESC_NT 64
|
||||
|
||||
#define RX_BD_BASEADDR (HIF_DESC_BASEADDR)
|
||||
#define TX_BD_BASEADDR (HIF_DESC_BASEADDR + HIF_TX_DESC_SIZE)
|
||||
|
||||
#define MIN_PKT_SIZE 56
|
||||
#define MAX_FRAME_SIZE 2048
|
||||
|
||||
struct __packed hif_header_s {
|
||||
u8 port_no; /* Carries input port no for host rx packets and
|
||||
* output port no for tx pkts
|
||||
*/
|
||||
u8 reserved0;
|
||||
u32 reserved2;
|
||||
};
|
||||
|
||||
struct __packed buf_desc {
|
||||
u32 ctrl;
|
||||
u32 status;
|
||||
u32 data;
|
||||
u32 next;
|
||||
};
|
||||
|
||||
struct rx_desc_s {
|
||||
struct buf_desc *rx_base;
|
||||
unsigned int rx_base_pa;
|
||||
int rx_to_read;
|
||||
int rx_ring_size;
|
||||
};
|
||||
|
||||
struct tx_desc_s {
|
||||
struct buf_desc *tx_base;
|
||||
unsigned int tx_base_pa;
|
||||
int tx_to_send;
|
||||
int tx_ring_size;
|
||||
};
|
||||
|
||||
int pfe_send(int phy_port, void *data, int length);
|
||||
int pfe_recv(uchar **pkt_ptr, int *phy_port);
|
||||
int pfe_tx_done(void);
|
||||
int pfe_eth_free_pkt(struct udevice *dev, uchar *packet, int length);
|
||||
int pfe_drv_init(struct pfe_ddr_address *pfe_addr);
|
||||
int pfe_eth_remove(struct udevice *dev);
|
||||
|
||||
#endif
|
104
include/net/pfe_eth/pfe_eth.h
Normal file
104
include/net/pfe_eth/pfe_eth.h
Normal file
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef __PFE_ETH_H__
|
||||
#define __PFE_ETH_H__
|
||||
|
||||
#include <linux/sizes.h>
|
||||
#include <asm/io.h>
|
||||
#include <miiphy.h>
|
||||
#include <malloc.h>
|
||||
#include "pfe_driver.h"
|
||||
|
||||
#define BMU2_DDR_BASEADDR 0
|
||||
#define BMU2_BUF_COUNT (3 * SZ_1K)
|
||||
#define BMU2_DDR_SIZE (DDR_BUF_SIZE * BMU2_BUF_COUNT)
|
||||
|
||||
#define HIF_RX_PKT_DDR_BASEADDR (BMU2_DDR_BASEADDR + BMU2_DDR_SIZE)
|
||||
#define HIF_RX_PKT_DDR_SIZE (HIF_RX_DESC_NT * DDR_BUF_SIZE)
|
||||
#define HIF_TX_PKT_DDR_BASEADDR (HIF_RX_PKT_DDR_BASEADDR + HIF_RX_PKT_DDR_SIZE)
|
||||
#define HIF_TX_PKT_DDR_SIZE (HIF_TX_DESC_NT * DDR_BUF_SIZE)
|
||||
|
||||
#define HIF_DESC_BASEADDR (HIF_TX_PKT_DDR_BASEADDR + HIF_TX_PKT_DDR_SIZE)
|
||||
#define HIF_RX_DESC_SIZE (16 * HIF_RX_DESC_NT)
|
||||
#define HIF_TX_DESC_SIZE (16 * HIF_TX_DESC_NT)
|
||||
|
||||
#define UTIL_CODE_BASEADDR 0x780000
|
||||
#define UTIL_CODE_SIZE (128 * SZ_1K)
|
||||
|
||||
#define UTIL_DDR_DATA_BASEADDR (UTIL_CODE_BASEADDR + UTIL_CODE_SIZE)
|
||||
#define UTIL_DDR_DATA_SIZE (64 * SZ_1K)
|
||||
|
||||
#define CLASS_DDR_DATA_BASEADDR (UTIL_DDR_DATA_BASEADDR + UTIL_DDR_DATA_SIZE)
|
||||
#define CLASS_DDR_DATA_SIZE (32 * SZ_1K)
|
||||
|
||||
#define TMU_DDR_DATA_BASEADDR (CLASS_DDR_DATA_BASEADDR + CLASS_DDR_DATA_SIZE)
|
||||
#define TMU_DDR_DATA_SIZE (32 * SZ_1K)
|
||||
|
||||
#define TMU_LLM_BASEADDR (TMU_DDR_DATA_BASEADDR + TMU_DDR_DATA_SIZE)
|
||||
#define TMU_LLM_QUEUE_LEN (16 * 256)
|
||||
/* Must be power of two and at least 16 * 8 = 128 bytes */
|
||||
#define TMU_LLM_SIZE (4 * 16 * TMU_LLM_QUEUE_LEN)
|
||||
/* (4 TMU's x 16 queues x queue_len) */
|
||||
|
||||
#define ROUTE_TABLE_BASEADDR 0x800000
|
||||
#define ROUTE_TABLE_HASH_BITS_MAX 15 /* 32K entries */
|
||||
#define ROUTE_TABLE_HASH_BITS 8 /* 256 entries */
|
||||
#define ROUTE_TABLE_SIZE (BIT(ROUTE_TABLE_HASH_BITS_MAX) \
|
||||
* CLASS_ROUTE_SIZE)
|
||||
|
||||
#define PFE_TOTAL_DATA_SIZE (ROUTE_TABLE_BASEADDR + ROUTE_TABLE_SIZE)
|
||||
|
||||
#if PFE_TOTAL_DATA_SIZE > (12 * SZ_1M)
|
||||
#error DDR mapping above 12MiB
|
||||
#endif
|
||||
|
||||
/* LMEM Mapping */
|
||||
#define BMU1_LMEM_BASEADDR 0
|
||||
#define BMU1_BUF_COUNT 256
|
||||
#define BMU1_LMEM_SIZE (LMEM_BUF_SIZE * BMU1_BUF_COUNT)
|
||||
|
||||
struct gemac_s {
|
||||
void *gemac_base;
|
||||
void *egpi_base;
|
||||
|
||||
/* GEMAC config */
|
||||
int gemac_mode;
|
||||
int gemac_speed;
|
||||
int gemac_duplex;
|
||||
int flags;
|
||||
/* phy iface */
|
||||
int phy_address;
|
||||
int phy_mode;
|
||||
struct mii_dev *bus;
|
||||
|
||||
};
|
||||
|
||||
struct pfe_mdio_info {
|
||||
void *reg_base;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct pfe_eth_dev {
|
||||
int gemac_port;
|
||||
struct gemac_s *gem;
|
||||
struct pfe_ddr_address pfe_addr;
|
||||
struct udevice *dev;
|
||||
#ifdef CONFIG_PHYLIB
|
||||
struct phy_device *phydev;
|
||||
#endif
|
||||
};
|
||||
|
||||
int pfe_remove(struct pfe_ddr_address *pfe_addr);
|
||||
struct mii_dev *pfe_mdio_init(struct pfe_mdio_info *mdio_info);
|
||||
void pfe_set_mdio(int dev_id, struct mii_dev *bus);
|
||||
void pfe_set_phy_address_mode(int dev_id, int phy_id, int phy_mode);
|
||||
int gemac_initialize(bd_t *bis, int dev_id, char *devname);
|
||||
int pfe_init(struct pfe_ddr_address *pfe_addr);
|
||||
int pfe_eth_board_init(struct udevice *dev);
|
||||
|
||||
#endif /* __PFE_ETH_H__ */
|
17
include/net/pfe_eth/pfe_firmware.h
Normal file
17
include/net/pfe_eth/pfe_firmware.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
/** @file
|
||||
* Contains all the defines to handle parsing and loading of PE firmware files.
|
||||
*/
|
||||
#ifndef __PFE_FIRMWARE_H__
|
||||
#define __PFE_FIRMWARE_H__
|
||||
|
||||
int pfe_firmware_init(void);
|
||||
void pfe_firmware_exit(void);
|
||||
|
||||
#endif
|
13
include/net/pfe_eth/pfe_mdio.h
Normal file
13
include/net/pfe_eth/pfe_mdio.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* Copyright 2015-2016 Freescale Semiconductor, Inc.
|
||||
* Copyright 2017 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*/
|
||||
|
||||
#ifndef _PFE_MDIO_H_
|
||||
#define _PFE_MDIO_H_
|
||||
|
||||
int pfe_phy_configure(struct pfe_eth_dev *priv, int dev_id, int phy_id);
|
||||
|
||||
#endif /* _PFE_MDIO_H_ */
|
|
@ -39,8 +39,6 @@ int dm9000_initialize(bd_t *bis);
|
|||
int dnet_eth_initialize(int id, void *regs, unsigned int phy_addr);
|
||||
int e1000_initialize(bd_t *bis);
|
||||
int eepro100_initialize(bd_t *bis);
|
||||
int enc28j60_initialize(unsigned int bus, unsigned int cs,
|
||||
unsigned int max_hz, unsigned int mode);
|
||||
int ep93xx_eth_initialize(u8 dev_num, int base_addr);
|
||||
int eth_3com_initialize (bd_t * bis);
|
||||
int ethoc_initialize(u8 dev_num, int base_addr);
|
||||
|
|
|
@ -336,7 +336,7 @@ int eth_send(void *packet, int length)
|
|||
if (!current)
|
||||
return -ENODEV;
|
||||
|
||||
if (!device_active(current))
|
||||
if (!eth_is_active(current))
|
||||
return -EINVAL;
|
||||
|
||||
ret = eth_get_ops(current)->send(current, packet, length);
|
||||
|
@ -359,7 +359,7 @@ int eth_rx(void)
|
|||
if (!current)
|
||||
return -ENODEV;
|
||||
|
||||
if (!device_active(current))
|
||||
if (!eth_is_active(current))
|
||||
return -EINVAL;
|
||||
|
||||
/* Process up to 32 packets at one time */
|
||||
|
|
|
@ -683,7 +683,7 @@ int net_start_again(void)
|
|||
retry_forever = 0;
|
||||
}
|
||||
|
||||
if ((!retry_forever) && (net_try_count >= retrycnt)) {
|
||||
if ((!retry_forever) && (net_try_count > retrycnt)) {
|
||||
eth_halt();
|
||||
net_set_state(NETLOOP_FAIL);
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue