From 4a99a9e2e3f2cd239ea026568bf0eb8c109d2da8 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 25 Sep 2013 11:51:49 -0600 Subject: [PATCH] SAMA5 EMAC: Add some need D-Cache Flush/Invalidate operations. Add support for CONFIG_NET_DUMPPACKET --- arch/arm/src/sama5/sam_emac.c | 74 ++++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/arch/arm/src/sama5/sam_emac.c b/arch/arm/src/sama5/sam_emac.c index b0c0ad57ca4..0a4f3a3d28e 100644 --- a/arch/arm/src/sama5/sam_emac.c +++ b/arch/arm/src/sama5/sam_emac.c @@ -215,7 +215,11 @@ # undef CONFIG_SAMA5_EMAC_REGDEBUG #endif -/* Clocking *****************************************************************/ +#ifdef CONFIG_NET_DUMPPACKET +# define sam_dumppacket(m,a,n) lib_dumpbuffer(m,a,n) +#else +# define sam_dumppacket(m,a,n) +#endif /* Timing *******************************************************************/ /* TX poll delay = 1 seconds. CLK_TCK is the number of clock ticks per @@ -695,6 +699,7 @@ static int sam_transmit(struct sam_emac_s *priv) uint32_t status; nllvdbg("d_len: %d txhead: %d\n", dev->d_len, priv->txhead); + sam_dumppacket("Transmit packet", dev->d_buf, dev->d_len); /* Check parameter */ @@ -724,7 +729,7 @@ static int sam_transmit(struct sam_emac_s *priv) virtaddr = sam_virtramaddr(txdesc->addr); memcpy((void *)virtaddr, dev->d_buf, dev->d_len); - cp15_flush_dcache((uint32_t)virtaddr, ((uint32_t)virtaddr + dev->d_len)); + cp15_clean_dcache((uint32_t)virtaddr, (uint32_t)virtaddr + dev->d_len); } /* Update TX descriptor status. */ @@ -735,7 +740,11 @@ static int sam_transmit(struct sam_emac_s *priv) status |= EMACTXD_STA_WRAP; } + /* Update the descriptor status and flush the updated value to RAM */ + txdesc->status = status; + cp15_clean_dcache((uint32_t)txdesc, + (uint32_t)txdesc + sizeof(struct emac_txdesc_s)); /* Increment the head index */ @@ -867,7 +876,9 @@ static void sam_dopoll(struct sam_emac_s *priv) * further packets available * * Assumptions: - * Global interrupts are disabled by interrupt handling logic. + * - Global interrupts are disabled by interrupt handling logic. + * - The RX descriptor D-cache list has been invalided to force fetching + * from RAM. * ****************************************************************************/ @@ -894,7 +905,12 @@ static int sam_recvframe(struct sam_emac_s *priv) rxdesc = &priv->rxdesc[rxndx]; isframe = false; - nllvdbg("rxndx: %d: %d\n", rxndx); + /* Invalidate the RX descriptor to force re-fetching from RAM */ + + cp15_invalidate_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + sizeof(struct emac_rxdesc_s)); + + nllvdbg("rxndx: %d\n", rxndx); while ((rxdesc->addr & EMACRXD_ADDR_OWNER) != 0) { @@ -908,9 +924,17 @@ static int sam_recvframe(struct sam_emac_s *priv) while (rxndx != priv->rxndx) { + /* Give ownership back to the EMAC */ + rxdesc = &priv->rxdesc[priv->rxndx]; rxdesc->addr &= ~(EMACRXD_ADDR_OWNER); + /* Flush the modified RX descriptor to RAM */ + + cp15_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct emac_rxdesc_s)); + /* Increment the RX index */ if (++priv->rxndx >= CONFIG_SAMA5_EMAC_NRXBUFFERS) @@ -945,9 +969,17 @@ static int sam_recvframe(struct sam_emac_s *priv) nllvdbg("ERROR: No EOF (Invalid of buffers too small)\n"); do { + /* Give ownership back to the EMAC */ + rxdesc = &priv->rxdesc[priv->rxndx]; rxdesc->addr &= ~(EMACRXD_ADDR_OWNER); + /* Flush the modified RX descriptor to RAM */ + + cp15_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct emac_rxdesc_s)); + /* Increment the RX index */ if (++priv->rxndx >= CONFIG_SAMA5_EMAC_NRXBUFFERS) @@ -974,7 +1006,7 @@ static int sam_recvframe(struct sam_emac_s *priv) physaddr = (uintptr_t)(rxdesc->addr & EMACRXD_ADDR_MASK); src = (const uint8_t *)sam_virtramaddr(physaddr); - cp15_invalidate_dcache((uintptr_t)src, copylen); + cp15_invalidate_dcache((uintptr_t)src, (uintptr_t)src + copylen); /* And do the copy */ @@ -997,9 +1029,17 @@ static int sam_recvframe(struct sam_emac_s *priv) while (priv->rxndx != rxndx) { + /* Give ownership back to the EMAC */ + rxdesc = &priv->rxdesc[priv->rxndx]; rxdesc->addr &= ~(EMACRXD_ADDR_OWNER); + /* Flush the modified RX descriptor to RAM */ + + cp15_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct emac_rxdesc_s)); + /* Increment the RX index */ if (++priv->rxndx >= CONFIG_SAMA5_EMAC_NRXBUFFERS) @@ -1024,17 +1064,31 @@ static int sam_recvframe(struct sam_emac_s *priv) } } - /* We have not encount the SOF yet... discard this frament and keep looking */ + /* We have not encount the SOF yet... discard this fragment and keep looking */ else { + /* Give ownership back to the EMAC */ + rxdesc->addr &= ~(EMACRXD_ADDR_OWNER); + + /* Flush the modified RX descriptor to RAM */ + + cp15_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + sizeof(struct emac_rxdesc_s)); + priv->rxndx = rxndx; } /* Process the next buffer */ rxdesc = &priv->rxdesc[rxndx]; + + /* Invalidate the RX descriptor to force re-fetching from RAM */ + + cp15_invalidate_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + sizeof(struct emac_rxdesc_s)); } /* No packet was found */ @@ -1072,6 +1126,8 @@ static void sam_receive(struct sam_emac_s *priv) while (sam_recvframe(priv) == OK) { + sam_dumppacket("Received packet", dev->d_buf, dev->d_len); + /* Check if the packet is a valid size for the uIP buffer configuration * (this should not happen) */ @@ -2539,6 +2595,12 @@ static void sam_rxreset(struct sam_emac_s *priv) rxdesc[CONFIG_SAMA5_EMAC_NRXBUFFERS - 1].addr |= EMACRXD_ADDR_WRAP; + /* Flush the entire RX descriptor table to RAM */ + + cp15_clean_dcache((uintptr_t)rxdesc, + (uintptr_t)rxdesc + + CONFIG_SAMA5_EMAC_NRXBUFFERS * sizeof(struct emac_rxdesc_s)); + /* Set the Receive Buffer Queue Pointer Register */ physaddr = sam_physramaddr((uint32_t)rxdesc);