27
27
#include "fsl_enetc.h"
28
28
#endif
29
29
30
+ #ifdef CONFIG_ARCH_IMX9
31
+ #define ENETC_DRV_DCACHE_OPS_EN 1
32
+ #endif
33
+
30
34
#define ENETC_DRIVER_NAME "enetc_eth"
31
35
36
+ static void enetc_inval_bd (void * desc , bool tx )
37
+ {
38
+ #ifdef ENETC_DRV_DCACHE_OPS_EN
39
+ unsigned long start = (unsigned long )desc & ~(ARCH_DMA_MINALIGN - 1 );
40
+ unsigned long size = tx ? sizeof (struct enetc_tx_bd ) : sizeof (union enetc_rx_bd );
41
+ unsigned long end = ALIGN (start + size , ARCH_DMA_MINALIGN );
42
+
43
+ invalidate_dcache_range (start , end );
44
+ #endif
45
+ }
46
+
47
+ static void enetc_flush_bd (void * desc , bool tx )
48
+ {
49
+ #ifdef ENETC_DRV_DCACHE_OPS_EN
50
+ unsigned long start = (unsigned long )desc & ~(ARCH_DMA_MINALIGN - 1 );
51
+ unsigned long size = tx ? sizeof (struct enetc_tx_bd ) : sizeof (union enetc_rx_bd );
52
+ unsigned long end = ALIGN (start + size , ARCH_DMA_MINALIGN );
53
+
54
+ flush_dcache_range (start , end );
55
+ #endif
56
+ }
57
+
58
+ static void enetc_inval_buffer (void * buf , size_t size )
59
+ {
60
+ #ifdef ENETC_DRV_DCACHE_OPS_EN
61
+ unsigned long start = rounddown ((unsigned long )buf , ARCH_DMA_MINALIGN );
62
+ unsigned long end = roundup ((unsigned long )buf + size ,
63
+ ARCH_DMA_MINALIGN );
64
+
65
+ invalidate_dcache_range (start , end );
66
+ #endif
67
+ }
68
+
69
+ static void enetc_flush_buffer (void * buf , size_t size )
70
+ {
71
+ #ifdef ENETC_DRV_DCACHE_OPS_EN
72
+ unsigned long start = rounddown ((unsigned long )buf , ARCH_DMA_MINALIGN );
73
+ unsigned long end = roundup ((unsigned long )buf + size ,
74
+ ARCH_DMA_MINALIGN );
75
+
76
+ flush_dcache_range (start , end );
77
+ #endif
78
+ }
79
+
32
80
static int enetc_remove (struct udevice * dev );
33
81
34
82
/*
@@ -384,11 +432,30 @@ static int enetc_probe(struct udevice *dev)
384
432
return - ENODEV ;
385
433
}
386
434
435
+ #ifdef ENETC_DRV_DCACHE_OPS_EN
436
+ if (ARCH_DMA_MINALIGN % sizeof (struct enetc_tx_bd ) ||
437
+ ARCH_DMA_MINALIGN % sizeof (union enetc_rx_bd )) {
438
+ printf ("Error: Cacheline size is not integral multiples of BD size\n" );
439
+ return - EINVAL ;
440
+ }
441
+
442
+ /* Only rx bdr uses the bd_num_in_cl */
443
+ priv -> tx_bdr .bd_num_in_cl = ARCH_DMA_MINALIGN / sizeof (struct enetc_tx_bd );
444
+ priv -> rx_bdr .bd_num_in_cl = ARCH_DMA_MINALIGN / sizeof (union enetc_rx_bd );
445
+
446
+ if (ENETC_BD_CNT % priv -> rx_bdr .bd_num_in_cl ) {
447
+ printf ("Error: BD CNT is not integral multiples of bd_num_in_cl\n" );
448
+ return - EINVAL ;
449
+ }
450
+ #else
451
+ priv -> tx_bdr .bd_num_in_cl = 1 ;
452
+ priv -> rx_bdr .bd_num_in_cl = 1 ;
453
+ #endif
454
+
387
455
priv -> enetc_txbd = memalign (ENETC_BD_ALIGN ,
388
456
sizeof (struct enetc_tx_bd ) * ENETC_BD_CNT );
389
457
priv -> enetc_rxbd = memalign (ENETC_BD_ALIGN ,
390
458
sizeof (union enetc_rx_bd ) * ENETC_BD_CNT );
391
-
392
459
if (!priv -> enetc_txbd || !priv -> enetc_rxbd ) {
393
460
/* free should be able to handle NULL, just free all pointers */
394
461
free (priv -> enetc_txbd );
@@ -618,10 +685,8 @@ static void enetc_setup_rx_bdr(struct udevice *dev)
618
685
priv -> enetc_rxbd [i ].w .addr = enetc_rxb_address (dev , i );
619
686
/* each RX buffer must be aligned to 64B */
620
687
WARN_ON (priv -> enetc_rxbd [i ].w .addr & (ARCH_DMA_MINALIGN - 1 ));
621
- #ifdef CONFIG_ARCH_IMX9
622
- flush_dcache_range ((ulong )& priv -> enetc_rxbd [i ],
623
- (ulong )& priv -> enetc_rxbd [i ] + sizeof (union enetc_rx_bd ));
624
- #endif
688
+
689
+ enetc_flush_bd ((void * )& priv -> enetc_rxbd [i ], false);
625
690
}
626
691
627
692
/* reset producer (ENETC owned) and consumer (SW owned) index */
@@ -705,27 +770,19 @@ static int enetc_send(struct udevice *dev, void *packet, int length)
705
770
enetc_dbg (dev , "TxBD[%d]send: pkt_len=%d, buff @0x%x%08x\n" , pi , length ,
706
771
upper_32_bits ((u64 )nv_packet ), lower_32_bits ((u64 )nv_packet ));
707
772
708
- #ifdef CONFIG_ARCH_IMX9
709
- ulong start ;
710
- ulong stop ;
773
+ enetc_flush_buffer (packet , length );
711
774
712
- start = (ulong )packet ;
713
- start &= ~(ARCH_DMA_MINALIGN - 1 );
714
- stop = roundup (start + length , ARCH_DMA_MINALIGN );
715
- flush_dcache_range (start , stop );
716
- #endif
717
775
/* prepare Tx BD */
718
776
memset (& priv -> enetc_txbd [pi ], 0x0 , sizeof (struct enetc_tx_bd ));
719
777
priv -> enetc_txbd [pi ].addr =
720
778
cpu_to_le64 (dm_pci_virt_to_mem (dev , nv_packet ));
721
779
priv -> enetc_txbd [pi ].buf_len = cpu_to_le16 (length );
722
780
priv -> enetc_txbd [pi ].frm_len = cpu_to_le16 (length );
723
781
priv -> enetc_txbd [pi ].flags = cpu_to_le16 (ENETC_TXBD_FLAGS_F );
724
- #ifdef CONFIG_ARCH_IMX9
725
- flush_dcache_range ((ulong )& priv -> enetc_txbd [pi ],
726
- (ulong )& priv -> enetc_txbd [pi ] + sizeof (struct enetc_tx_bd ));
727
- #endif
782
+
728
783
dmb ();
784
+ enetc_flush_bd ((void * )& priv -> enetc_txbd [pi ], true);
785
+
729
786
/* send frame: increment producer index */
730
787
pi = (pi + 1 ) % txr -> bd_count ;
731
788
txr -> next_prod_idx = pi ;
@@ -749,22 +806,13 @@ static int enetc_recv(struct udevice *dev, int flags, uchar **packetp)
749
806
struct bd_ring * rxr = & priv -> rx_bdr ;
750
807
int tries = ENETC_POLL_TRIES ;
751
808
int pi = rxr -> next_prod_idx ;
752
- int ci = rxr -> next_cons_idx ;
753
809
u32 status ;
754
810
int len ;
755
811
u8 rdy ;
756
812
757
813
do {
758
814
dmb ();
759
- #ifdef CONFIG_ARCH_IMX9
760
- ulong start ;
761
- ulong stop ;
762
-
763
- start = (ulong )& priv -> enetc_rxbd [pi ];
764
- start &= ~(ARCH_DMA_MINALIGN - 1 );
765
- stop = roundup (start + sizeof (union enetc_rx_bd ), ARCH_DMA_MINALIGN );
766
- invalidate_dcache_range (start , stop );
767
- #endif
815
+ enetc_inval_bd ((void * )& priv -> enetc_rxbd [pi ], false);
768
816
status = le32_to_cpu (priv -> enetc_rxbd [pi ].r .lstatus );
769
817
/* check if current BD is ready to be consumed */
770
818
rdy = ENETC_RXBD_STATUS_R (status );
@@ -775,35 +823,53 @@ static int enetc_recv(struct udevice *dev, int flags, uchar **packetp)
775
823
776
824
dmb ();
777
825
len = le16_to_cpu (priv -> enetc_rxbd [pi ].r .buf_len );
778
- #ifdef CONFIG_ARCH_IMX9
779
- ulong begin ;
780
- ulong end ;
781
-
782
- begin = (ulong )enetc_rxb_address (dev , pi );
783
- begin &= ~(ARCH_DMA_MINALIGN - 1 );
784
- end = roundup (begin + len , ARCH_DMA_MINALIGN );
785
- invalidate_dcache_range (begin , end );
786
- #endif
787
826
* packetp = (uchar * )enetc_rxb_address (dev , pi );
827
+ enetc_inval_buffer (* packetp , len );
788
828
enetc_dbg (dev , "RxBD[%d]: len=%d err=%d pkt=0x%x%08x\n" , pi , len ,
789
829
ENETC_RXBD_STATUS_ERRORS (status ),
790
830
upper_32_bits ((u64 )* packetp ), lower_32_bits ((u64 )* packetp ));
791
831
792
- /* BD clean up and advance to next in ring */
793
- memset (& priv -> enetc_rxbd [pi ], 0 , sizeof (union enetc_rx_bd ));
794
- priv -> enetc_rxbd [pi ].w .addr = enetc_rxb_address (dev , pi );
795
- #ifdef CONFIG_ARCH_IMX9
796
- flush_dcache_range ((ulong )& priv -> enetc_rxbd [pi ],
797
- (ulong )& priv -> enetc_rxbd [pi ] + sizeof (union enetc_rx_bd ));
798
- #endif
832
+ return len ;
833
+ }
834
+
835
+ static int enetc_free_pkt (struct udevice * dev , uchar * packet , int length )
836
+ {
837
+ struct enetc_priv * priv = dev_get_priv (dev );
838
+ struct bd_ring * rxr = & priv -> rx_bdr ;
839
+ int pi = rxr -> next_prod_idx ;
840
+ int ci = rxr -> next_cons_idx ;
841
+ uchar * packet_expected ;
842
+ int i ;
843
+
844
+ packet_expected = (uchar * )enetc_rxb_address (dev , pi );
845
+ if (packet != packet_expected ) {
846
+ printf ("%s: Unexpected packet (expected %p)\n" , __func__ ,
847
+ packet_expected );
848
+ return - EINVAL ;
849
+ }
850
+
799
851
rxr -> next_prod_idx = (pi + 1 ) % rxr -> bd_count ;
800
852
ci = (ci + 1 ) % rxr -> bd_count ;
801
853
rxr -> next_cons_idx = ci ;
802
854
dmb ();
803
- /* free up the slot in the ring for HW */
804
- enetc_write_reg (rxr -> cons_idx , ci );
805
855
806
- return len ;
856
+ if ((pi + 1 ) % rxr -> bd_num_in_cl == 0 ) {
857
+
858
+ /* BD clean up and advance to next in ring */
859
+ for (i = 0 ; i < rxr -> bd_num_in_cl ; i ++ ) {
860
+ memset (& priv -> enetc_rxbd [pi - i ], 0 , sizeof (union enetc_rx_bd ));
861
+ priv -> enetc_rxbd [pi - i ].w .addr = enetc_rxb_address (dev , pi - i );
862
+ }
863
+
864
+ /* Will flush all bds in one cacheline */
865
+ enetc_flush_bd ((void * )& priv -> enetc_rxbd [pi - rxr -> bd_num_in_cl + 1 ], false);
866
+
867
+ /* free up the slot in the ring for HW */
868
+ enetc_write_reg (rxr -> cons_idx , ci );
869
+
870
+ }
871
+
872
+ return 0 ;
807
873
}
808
874
809
875
#ifdef CONFIG_ARCH_IMX9
@@ -838,6 +904,7 @@ static const struct eth_ops enetc_ops = {
838
904
.send = enetc_send ,
839
905
.recv = enetc_recv ,
840
906
.stop = enetc_stop ,
907
+ .free_pkt = enetc_free_pkt ,
841
908
.write_hwaddr = enetc_write_hwaddr ,
842
909
#ifdef CONFIG_ARCH_IMX9
843
910
.read_rom_hwaddr = enetc_read_rom_hwaddr ,
0 commit comments