15a14cf166
The QorIQ LS1012A processor, optimized for battery-backed or USB-powered, integrates a single ARM Cortex-A53 core with a hardware packet forwarding engine and high-speed interfaces to deliver line-rate networking performance. QorIQ LS1012A Reference Design System (LS1012ARDB) is a high-performance development platform, with a complete debugging environment. The LS1012ARDB board supports the QorIQ LS1012A processor and is optimized to support the high-bandwidth DDR3L memory and a full complement of high-speed SerDes ports. LEDE/OPENWRT will auto strip executable program file while make. So we need select CONFIG_NO_STRIP=y while make menuconfig to avoid the ppfe network fiemware be destroyed, then run make to build ls1012ardb firmware. The fsl-quadspi flash with jffs2 fs is unstable and arise some failed message. This issue have noticed the IP owner for investigate, hope he can solve it earlier. So the ls1012ardb now also provide a xx-firmware.ext4.bin as default firmware, and the uboot bootcmd will run wrtboot_ext4rfs for "rootfstype=ext4" bootargs. Signed-off-by: Yutang Jiang <yutang.jiang@nxp.com>
334 lines
10 KiB
Diff
334 lines
10 KiB
Diff
From b17d75d2c1dc6cd1d55bcddbf7d3d4242e85e88e Mon Sep 17 00:00:00 2001
|
|
From: Anji J <anji.jagarlmudi@freescale.com>
|
|
Date: Fri, 20 May 2016 15:25:12 +0530
|
|
Subject: [PATCH 43/93] DNCPE-296 PFE reset workaround
|
|
|
|
LS1012A PFE doesn't have global reset control.
|
|
Due to this Linux pfe doesn't work when it was started at U-boot
|
|
This patch provides U-boot command to stop pfe, that should be used before starting Linux.
|
|
|
|
Signed-off-by: Anjaneyulu Jagarlmudi <anji.jagarlmudi@nxp.com>>
|
|
Signed-off-by: Prabhakar Kushwaha <prabhakar.kushwaha@nxp.com>
|
|
---
|
|
common/cmd_pfe_commands.c | 83 +++++++++++++++++++++++++++++++++++-
|
|
drivers/net/pfe_eth/pfe/cbus/hif.h | 3 ++
|
|
drivers/net/pfe_eth/pfe/pfe.h | 2 +
|
|
drivers/net/pfe_eth/pfe_driver.c | 58 ++++++++++++++++++++-----
|
|
drivers/net/pfe_eth/pfe_eth.c | 6 +--
|
|
5 files changed, 136 insertions(+), 16 deletions(-)
|
|
|
|
diff --git a/common/cmd_pfe_commands.c b/common/cmd_pfe_commands.c
|
|
index f9f92c7..0e22097 100644
|
|
--- a/common/cmd_pfe_commands.c
|
|
+++ b/common/cmd_pfe_commands.c
|
|
@@ -35,6 +35,7 @@
|
|
#include "../drivers/net/pfe_eth/pfe/cbus/gpi.h"
|
|
DECLARE_GLOBAL_DATA_PTR;
|
|
|
|
+void hif_rx_desc_disable(void);
|
|
int pfe_load_elf(int pe_mask, const struct firmware *fw);
|
|
int ls1012a_gemac_initialize(bd_t * bis, int dev_id, char *devname);
|
|
|
|
@@ -593,7 +594,9 @@ void bmu(int id, void *base)
|
|
}
|
|
|
|
#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[])
|
|
@@ -857,7 +860,6 @@ void hif_rx_enable(void)
|
|
void hif_rx_disable(void)
|
|
}
|
|
#endif
|
|
-
|
|
#define ROUTE_TABLE_START (CONFIG_DDR_PHYS_BASEADDR+ROUTE_TABLE_BASEADDR)
|
|
static void pfe_command_fftest(int argc, char * const argv[])
|
|
{
|
|
@@ -865,7 +867,6 @@ static void pfe_command_fftest(int argc, char * const argv[])
|
|
struct eth_device *edev_eth0;
|
|
struct eth_device *edev_eth1;
|
|
|
|
-
|
|
// open eth0 and eth1
|
|
edev_eth0 = eth_get_dev_by_name("pfe_eth0");
|
|
if (!edev_eth0)
|
|
@@ -916,6 +917,80 @@ static void pfe_command_start(int argc, char * const argv[])
|
|
}
|
|
#endif
|
|
|
|
+#ifdef PFE_LS1012A_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);
|
|
+
|
|
+ printf("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 id;
|
|
+ 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 */
|
|
+ rx_status = readl(HIF_RX_STATUS);
|
|
+ printf("rx_status %x %x\n",rx_status, BDP_CSR_RX_DMA_ACTV);
|
|
+ if(rx_status & BDP_CSR_RX_DMA_ACTV)
|
|
+ send_dummy_pkt_to_hif();
|
|
+ udelay(10);
|
|
+
|
|
+ if(readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV)
|
|
+ printf("Unable to stop HIF\n");
|
|
+
|
|
+ /*Disable Class PEs */
|
|
+
|
|
+ for (id = CLASS0_ID; id <= CLASS_MAX_ID; id++)
|
|
+ {
|
|
+ printf("Stop %d\n", id);
|
|
+ /*Inform PE to stop */
|
|
+ pe_dmem_write(id, cpu_to_be32(1), PEMBOX_ADDR_CLASS, 4);
|
|
+ udelay(10);
|
|
+
|
|
+ printf("Reading %d\n", id);
|
|
+ /*Read status */
|
|
+ if(!pe_dmem_read(id, PEMBOX_ADDR_CLASS+4, 4))
|
|
+ printf("Failed to stop PE%d\n", id);
|
|
+ }
|
|
+ /*Disable TMU PEs */
|
|
+ for (id = TMU0_ID; id <= TMU_MAX_ID; id++)
|
|
+ {
|
|
+ if(id == TMU2_ID) continue;
|
|
+
|
|
+ printf("Stop %d\n", id);
|
|
+ /*Inform PE to stop */
|
|
+ pe_dmem_write(id, 1, PEMBOX_ADDR_TMU, 4);
|
|
+ udelay(10);
|
|
+
|
|
+ printf("Reading %d\n", id);
|
|
+ /*Read status */
|
|
+ if(!pe_dmem_read(id, PEMBOX_ADDR_TMU+4, 4))
|
|
+ printf("Failed to stop PE%d\n", id);
|
|
+ }
|
|
+}
|
|
+#endif
|
|
|
|
static int pfe_command(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
char * const argv[])
|
|
@@ -965,6 +1040,10 @@ static int pfe_command(cmd_tbl_t *cmdtp, int flag, int argc,
|
|
else if (strcmp(argv[1], "start") == 0)
|
|
pfe_command_start(argc, argv);
|
|
#endif
|
|
+#ifdef PFE_LS1012A_RESET_WA
|
|
+ else if (strcmp(argv[1], "stop") == 0)
|
|
+ pfe_command_stop(argc, argv);
|
|
+#endif
|
|
else
|
|
{
|
|
printf("Unknown option: %s\n", argv[1]);
|
|
diff --git a/drivers/net/pfe_eth/pfe/cbus/hif.h b/drivers/net/pfe_eth/pfe/cbus/hif.h
|
|
index a4dd7c2..2329faa 100644
|
|
--- a/drivers/net/pfe_eth/pfe/cbus/hif.h
|
|
+++ b/drivers/net/pfe_eth/pfe/cbus/hif.h
|
|
@@ -34,6 +34,9 @@
|
|
#define HIF_CTRL_BDP_POLL_CTRL_EN (1<<1)
|
|
#define HIF_CTRL_BDP_CH_START_WSTB (1<<2)
|
|
|
|
+/*HIF_RX_STATUS bits */
|
|
+#define BDP_CSR_RX_DMA_ACTV (1<<16)
|
|
+
|
|
/*HIF_INT_ENABLE bits */
|
|
#define HIF_INT_EN (1 << 0)
|
|
#define HIF_RXBD_INT_EN (1 << 1)
|
|
diff --git a/drivers/net/pfe_eth/pfe/pfe.h b/drivers/net/pfe_eth/pfe/pfe.h
|
|
index e8e2221..6994a20 100644
|
|
--- a/drivers/net/pfe_eth/pfe/pfe.h
|
|
+++ b/drivers/net/pfe_eth/pfe/pfe.h
|
|
@@ -1,6 +1,8 @@
|
|
#ifndef _PFE_H_
|
|
#define _PFE_H_
|
|
|
|
+#define PFE_LS1012A_RESET_WA
|
|
+
|
|
#define CLASS_DMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20))
|
|
#define CLASS_IMEM_BASE_ADDR(i) (0x00000000 | ((i) << 20)) /* Only valid for mem access register interface */
|
|
#define CLASS_DMEM_SIZE 0x00002000
|
|
diff --git a/drivers/net/pfe_eth/pfe_driver.c b/drivers/net/pfe_eth/pfe_driver.c
|
|
index ca00e98..b06a352 100644
|
|
--- a/drivers/net/pfe_eth/pfe_driver.c
|
|
+++ b/drivers/net/pfe_eth/pfe_driver.c
|
|
@@ -51,13 +51,18 @@ int pfe_recv(unsigned int *pkt_ptr, int *phy_port)
|
|
struct rx_desc_s *rx_desc = g_rx_desc;
|
|
struct bufDesc *bd;
|
|
int len = -1;
|
|
- //volatile u32 ctrl;
|
|
+ volatile u32 ctrl;
|
|
struct hif_header_s *hif_header;
|
|
|
|
bd = rx_desc->rxBase + rx_desc->rxToRead;
|
|
|
|
- if (bd->ctrl & BD_CTRL_DESC_EN)
|
|
+ if (bd->ctrl & BD_CTRL_DESC_EN) {
|
|
+ if(!(readl(HIF_RX_STATUS) & BDP_CSR_RX_DMA_ACTV)){
|
|
+ /*If BDP is not active give write strobe */
|
|
+ writel((readl(HIF_RX_CTRL) | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL);
|
|
+ }
|
|
return len; //No pending Rx packet
|
|
+ }
|
|
|
|
/* this len include hif_header(8bytes) */
|
|
len = bd->ctrl & 0xFFFF;
|
|
@@ -69,7 +74,7 @@ int pfe_recv(unsigned int *pkt_ptr, int *phy_port)
|
|
dprint("Pkt recv'd: Pkt ptr(%p), len(%d), gemac_port(%d) status(%08x)\n",
|
|
hif_header, len, hif_header->port_no, bd->status);
|
|
|
|
-#if 0
|
|
+#if DEBUG
|
|
{
|
|
int i;
|
|
unsigned char *p = (unsigned char *)hif_header;
|
|
@@ -85,20 +90,26 @@ int pfe_recv(unsigned int *pkt_ptr, int *phy_port)
|
|
*pkt_ptr = (unsigned int )(hif_header + 1);
|
|
*phy_port = hif_header->port_no;
|
|
len -= sizeof(struct hif_header_s);
|
|
-#if 0
|
|
+
|
|
+#if defined(PFE_LS1012A_RESET_WA)
|
|
/* reset bd control field */
|
|
- ctrl = (MAX_FRAME_SIZE | BD_CTRL_DESC_EN | BD_CTRL_DIR);
|
|
+ ctrl = (MAX_FRAME_SIZE | BD_CTRL_LAST_BD | BD_CTRL_LIFM | BD_CTRL_DESC_EN | BD_CTRL_DIR);
|
|
+#else
|
|
+ /* reset bd control field */
|
|
+ ctrl = (MAX_FRAME_SIZE | BD_CTRL_LIFM | BD_CTRL_DESC_EN | BD_CTRL_DIR);
|
|
+ /* If we use BD_CTRL_LAST_BD, rxToRead never changes */
|
|
+ rx_desc->rxToRead = (rx_desc->rxToRead + 1) & (rx_desc->rxRingSize - 1);
|
|
+#endif
|
|
bd->ctrl = ctrl;
|
|
bd->status = 0;
|
|
|
|
- rx_desc->rxToRead = (rx_desc->rxToRead + 1) & (rx_desc->rxRingSize - 1);
|
|
|
|
/* Give START_STROBE to BDP to fetch the descriptor __NOW__,
|
|
* BDP need not to 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(I think) */
|
|
writel((readl(HIF_RX_CTRL) | HIF_CTRL_BDP_CH_START_WSTB), HIF_RX_CTRL);
|
|
-#endif
|
|
+
|
|
return len;
|
|
}
|
|
|
|
@@ -298,14 +309,37 @@ void hif_rx_desc_dump(void)
|
|
rx_desc = g_rx_desc;
|
|
bd_va = rx_desc->rxBase;
|
|
|
|
- printf("HIF rx desc: base_va: %p, base_pa: %08x\n", rx_desc->rxBase, rx_desc->rxBase_pa);
|
|
+ dprint("HIF rx desc: base_va: %p, base_pa: %08x\n", rx_desc->rxBase, rx_desc->rxBase_pa);
|
|
for (i=0; i < rx_desc->rxRingSize; i++) {
|
|
-// printf("status: %08x, ctrl: %08x, data: %08x, next: %p\n",
|
|
-// bd_va->status, bd_va->ctrl, bd_va->data, bd_va->next);
|
|
+ dprint("status: %08x, ctrl: %08x, data: %08x, next: %p\n",
|
|
+ bd_va->status, bd_va->ctrl, bd_va->data, 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 bufDesc *bd_va;
|
|
+
|
|
+ if (g_rx_desc == NULL) {
|
|
+ printf("%s: HIF Rx desc not initialized \n", __func__);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ rx_desc = g_rx_desc;
|
|
+ bd_va = rx_desc->rxBase;
|
|
+
|
|
+ for (i=0; i < rx_desc->rxRingSize; i++) {
|
|
+ bd_va->ctrl |= BD_CTRL_LAST_BD;
|
|
bd_va++;
|
|
}
|
|
}
|
|
|
|
+
|
|
/** HIF Rx Desc initialization function.
|
|
*/
|
|
static int hif_rx_desc_init(struct pfe *pfe)
|
|
@@ -348,7 +382,11 @@ static int hif_rx_desc_init(struct pfe *pfe)
|
|
|
|
memset(bd_va, 0, sizeof(struct bufDesc) * rx_desc->rxRingSize);
|
|
|
|
+#if defined(PFE_LS1012A_RESET_WA)
|
|
+ ctrl = (MAX_FRAME_SIZE | BD_CTRL_LAST_BD | BD_CTRL_DESC_EN | BD_CTRL_DIR | BD_CTRL_LIFM);
|
|
+#else
|
|
ctrl = (MAX_FRAME_SIZE | BD_CTRL_DESC_EN | BD_CTRL_DIR | BD_CTRL_LIFM);
|
|
+#endif
|
|
for (i=0; i < rx_desc->rxRingSize; i++) {
|
|
bd_va->next = (u32 )(bd_pa + 1);
|
|
bd_va->ctrl = ctrl;
|
|
diff --git a/drivers/net/pfe_eth/pfe_eth.c b/drivers/net/pfe_eth/pfe_eth.c
|
|
index 40ac095..40f2c39 100644
|
|
--- a/drivers/net/pfe_eth/pfe_eth.c
|
|
+++ b/drivers/net/pfe_eth/pfe_eth.c
|
|
@@ -48,7 +48,7 @@ static void ls1012a_gemac_enable(void *gemac_base)
|
|
writel(readl(gemac_base + EMAC_ECNTRL_REG) | EMAC_ECNTRL_ETHER_EN, gemac_base + EMAC_ECNTRL_REG);
|
|
}
|
|
|
|
-static void ls1012a_gemac_dsable(void *gemac_base)
|
|
+static void ls1012a_gemac_disable(void *gemac_base)
|
|
{
|
|
writel(readl(gemac_base + EMAC_ECNTRL_REG) & ~EMAC_ECNTRL_ETHER_EN, gemac_base + EMAC_ECNTRL_REG);
|
|
}
|
|
@@ -113,7 +113,7 @@ static void ls1012a_eth_halt(struct eth_device *edev)
|
|
{
|
|
struct ls1012a_eth_dev *priv = (struct ls1012a_eth_dev *)edev->priv;
|
|
|
|
- ls1012a_gemac_enable(priv->gem->gemac_base);
|
|
+ ls1012a_gemac_disable(priv->gem->gemac_base);
|
|
|
|
gpi_disable(priv->gem->egpi_base);
|
|
|
|
@@ -216,14 +216,12 @@ static int ls1012a_eth_recv(struct eth_device *dev)
|
|
dprint("Rx pkt: pkt_buf(%08x), 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");
|
|
- pfe_recv_ack();
|
|
return 0;
|
|
}
|
|
|
|
// Pass the packet up to the protocol layers.
|
|
net_process_received_packet((uchar *)pkt_buf, len);
|
|
|
|
- pfe_recv_ack();
|
|
return 0;
|
|
}
|
|
|
|
--
|
|
1.7.9.5
|
|
|