forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
....@@ -4,14 +4,18 @@
44 * stmmac XGMAC support.
55 */
66
7
+#include <linux/bitrev.h>
8
+#include <linux/crc32.h>
9
+#include <linux/iopoll.h>
710 #include "stmmac.h"
11
+#include "stmmac_ptp.h"
12
+#include "dwxlgmac2.h"
813 #include "dwxgmac2.h"
914
1015 static void dwxgmac2_core_init(struct mac_device_info *hw,
1116 struct net_device *dev)
1217 {
1318 void __iomem *ioaddr = hw->pcsr;
14
- int mtu = dev->mtu;
1519 u32 tx, rx;
1620
1721 tx = readl(ioaddr + XGMAC_TX_CONFIG);
....@@ -20,23 +24,13 @@
2024 tx |= XGMAC_CORE_INIT_TX;
2125 rx |= XGMAC_CORE_INIT_RX;
2226
23
- if (mtu >= 9000) {
24
- rx |= XGMAC_CONFIG_GPSLCE;
25
- rx |= XGMAC_JUMBO_LEN << XGMAC_CONFIG_GPSL_SHIFT;
26
- rx |= XGMAC_CONFIG_WD;
27
- } else if (mtu > 2000) {
28
- rx |= XGMAC_CONFIG_JE;
29
- } else if (mtu > 1500) {
30
- rx |= XGMAC_CONFIG_S2KP;
31
- }
32
-
3327 if (hw->ps) {
3428 tx |= XGMAC_CONFIG_TE;
3529 tx &= ~hw->link.speed_mask;
3630
3731 switch (hw->ps) {
3832 case SPEED_10000:
39
- tx |= hw->link.speed10000;
33
+ tx |= hw->link.xgmii.speed10000;
4034 break;
4135 case SPEED_2500:
4236 tx |= hw->link.speed2500;
....@@ -116,6 +110,23 @@
116110 writel(value, ioaddr + reg);
117111 }
118112
113
+static void dwxgmac2_tx_queue_prio(struct mac_device_info *hw, u32 prio,
114
+ u32 queue)
115
+{
116
+ void __iomem *ioaddr = hw->pcsr;
117
+ u32 value, reg;
118
+
119
+ reg = (queue < 4) ? XGMAC_TC_PRTY_MAP0 : XGMAC_TC_PRTY_MAP1;
120
+ if (queue >= 4)
121
+ queue -= 4;
122
+
123
+ value = readl(ioaddr + reg);
124
+ value &= ~XGMAC_PSTC(queue);
125
+ value |= (prio << XGMAC_PSTC_SHIFT(queue)) & XGMAC_PSTC(queue);
126
+
127
+ writel(value, ioaddr + reg);
128
+}
129
+
119130 static void dwxgmac2_prog_mtl_rx_algorithms(struct mac_device_info *hw,
120131 u32 rx_alg)
121132 {
....@@ -142,7 +153,9 @@
142153 u32 tx_alg)
143154 {
144155 void __iomem *ioaddr = hw->pcsr;
156
+ bool ets = true;
145157 u32 value;
158
+ int i;
146159
147160 value = readl(ioaddr + XGMAC_MTL_OPMODE);
148161 value &= ~XGMAC_ETSALG;
....@@ -158,10 +171,28 @@
158171 value |= XGMAC_DWRR;
159172 break;
160173 default:
174
+ ets = false;
161175 break;
162176 }
163177
164178 writel(value, ioaddr + XGMAC_MTL_OPMODE);
179
+
180
+ /* Set ETS if desired */
181
+ for (i = 0; i < MTL_MAX_TX_QUEUES; i++) {
182
+ value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(i));
183
+ value &= ~XGMAC_TSA;
184
+ if (ets)
185
+ value |= XGMAC_ETS;
186
+ writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(i));
187
+ }
188
+}
189
+
190
+static void dwxgmac2_set_mtl_tx_queue_weight(struct mac_device_info *hw,
191
+ u32 weight, u32 queue)
192
+{
193
+ void __iomem *ioaddr = hw->pcsr;
194
+
195
+ writel(weight, ioaddr + XGMAC_MTL_TCx_QUANTUM_WEIGHT(queue));
165196 }
166197
167198 static void dwxgmac2_map_mtl_to_dma(struct mac_device_info *hw, u32 queue,
....@@ -181,11 +212,39 @@
181212 writel(value, ioaddr + reg);
182213 }
183214
215
+static void dwxgmac2_config_cbs(struct mac_device_info *hw,
216
+ u32 send_slope, u32 idle_slope,
217
+ u32 high_credit, u32 low_credit, u32 queue)
218
+{
219
+ void __iomem *ioaddr = hw->pcsr;
220
+ u32 value;
221
+
222
+ writel(send_slope, ioaddr + XGMAC_MTL_TCx_SENDSLOPE(queue));
223
+ writel(idle_slope, ioaddr + XGMAC_MTL_TCx_QUANTUM_WEIGHT(queue));
224
+ writel(high_credit, ioaddr + XGMAC_MTL_TCx_HICREDIT(queue));
225
+ writel(low_credit, ioaddr + XGMAC_MTL_TCx_LOCREDIT(queue));
226
+
227
+ value = readl(ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue));
228
+ value &= ~XGMAC_TSA;
229
+ value |= XGMAC_CC | XGMAC_CBS;
230
+ writel(value, ioaddr + XGMAC_MTL_TCx_ETS_CONTROL(queue));
231
+}
232
+
233
+static void dwxgmac2_dump_regs(struct mac_device_info *hw, u32 *reg_space)
234
+{
235
+ void __iomem *ioaddr = hw->pcsr;
236
+ int i;
237
+
238
+ for (i = 0; i < XGMAC_MAC_REGSIZE; i++)
239
+ reg_space[i] = readl(ioaddr + i * 4);
240
+}
241
+
184242 static int dwxgmac2_host_irq_status(struct mac_device_info *hw,
185243 struct stmmac_extra_stats *x)
186244 {
187245 void __iomem *ioaddr = hw->pcsr;
188246 u32 stat, en;
247
+ int ret = 0;
189248
190249 en = readl(ioaddr + XGMAC_INT_EN);
191250 stat = readl(ioaddr + XGMAC_INT_STATUS);
....@@ -197,7 +256,24 @@
197256 readl(ioaddr + XGMAC_PMT);
198257 }
199258
200
- return 0;
259
+ if (stat & XGMAC_LPIIS) {
260
+ u32 lpi = readl(ioaddr + XGMAC_LPI_CTRL);
261
+
262
+ if (lpi & XGMAC_TLPIEN) {
263
+ ret |= CORE_IRQ_TX_PATH_IN_LPI_MODE;
264
+ x->irq_tx_path_in_lpi_mode_n++;
265
+ }
266
+ if (lpi & XGMAC_TLPIEX) {
267
+ ret |= CORE_IRQ_TX_PATH_EXIT_LPI_MODE;
268
+ x->irq_tx_path_exit_lpi_mode_n++;
269
+ }
270
+ if (lpi & XGMAC_RLPIEN)
271
+ x->irq_rx_path_in_lpi_mode_n++;
272
+ if (lpi & XGMAC_RLPIEX)
273
+ x->irq_rx_path_exit_lpi_mode_n++;
274
+ }
275
+
276
+ return ret;
201277 }
202278
203279 static int dwxgmac2_host_mtl_irq_status(struct mac_device_info *hw, u32 chan)
....@@ -265,10 +341,10 @@
265341 u32 value;
266342
267343 value = (addr[5] << 8) | addr[4];
268
- writel(value | XGMAC_AE, ioaddr + XGMAC_ADDR0_HIGH);
344
+ writel(value | XGMAC_AE, ioaddr + XGMAC_ADDRx_HIGH(reg_n));
269345
270346 value = (addr[3] << 24) | (addr[2] << 16) | (addr[1] << 8) | addr[0];
271
- writel(value, ioaddr + XGMAC_ADDR0_LOW);
347
+ writel(value, ioaddr + XGMAC_ADDRx_LOW(reg_n));
272348 }
273349
274350 static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
....@@ -278,8 +354,8 @@
278354 u32 hi_addr, lo_addr;
279355
280356 /* Read the MAC address from the hardware */
281
- hi_addr = readl(ioaddr + XGMAC_ADDR0_HIGH);
282
- lo_addr = readl(ioaddr + XGMAC_ADDR0_LOW);
357
+ hi_addr = readl(ioaddr + XGMAC_ADDRx_HIGH(reg_n));
358
+ lo_addr = readl(ioaddr + XGMAC_ADDRx_LOW(reg_n));
283359
284360 /* Extract the MAC address from the high and low words */
285361 addr[0] = lo_addr & 0xff;
....@@ -290,22 +366,1088 @@
290366 addr[5] = (hi_addr >> 8) & 0xff;
291367 }
292368
369
+static void dwxgmac2_set_eee_mode(struct mac_device_info *hw,
370
+ bool en_tx_lpi_clockgating)
371
+{
372
+ void __iomem *ioaddr = hw->pcsr;
373
+ u32 value;
374
+
375
+ value = readl(ioaddr + XGMAC_LPI_CTRL);
376
+
377
+ value |= XGMAC_LPITXEN | XGMAC_LPITXA;
378
+ if (en_tx_lpi_clockgating)
379
+ value |= XGMAC_TXCGE;
380
+
381
+ writel(value, ioaddr + XGMAC_LPI_CTRL);
382
+}
383
+
384
+static void dwxgmac2_reset_eee_mode(struct mac_device_info *hw)
385
+{
386
+ void __iomem *ioaddr = hw->pcsr;
387
+ u32 value;
388
+
389
+ value = readl(ioaddr + XGMAC_LPI_CTRL);
390
+ value &= ~(XGMAC_LPITXEN | XGMAC_LPITXA | XGMAC_TXCGE);
391
+ writel(value, ioaddr + XGMAC_LPI_CTRL);
392
+}
393
+
394
+static void dwxgmac2_set_eee_pls(struct mac_device_info *hw, int link)
395
+{
396
+ void __iomem *ioaddr = hw->pcsr;
397
+ u32 value;
398
+
399
+ value = readl(ioaddr + XGMAC_LPI_CTRL);
400
+ if (link)
401
+ value |= XGMAC_PLS;
402
+ else
403
+ value &= ~XGMAC_PLS;
404
+ writel(value, ioaddr + XGMAC_LPI_CTRL);
405
+}
406
+
407
+static void dwxgmac2_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
408
+{
409
+ void __iomem *ioaddr = hw->pcsr;
410
+ u32 value;
411
+
412
+ value = (tw & 0xffff) | ((ls & 0x3ff) << 16);
413
+ writel(value, ioaddr + XGMAC_LPI_TIMER_CTRL);
414
+}
415
+
416
+static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
417
+ int mcbitslog2)
418
+{
419
+ int numhashregs, regs;
420
+
421
+ switch (mcbitslog2) {
422
+ case 6:
423
+ numhashregs = 2;
424
+ break;
425
+ case 7:
426
+ numhashregs = 4;
427
+ break;
428
+ case 8:
429
+ numhashregs = 8;
430
+ break;
431
+ default:
432
+ return;
433
+ }
434
+
435
+ for (regs = 0; regs < numhashregs; regs++)
436
+ writel(mcfilterbits[regs], ioaddr + XGMAC_HASH_TABLE(regs));
437
+}
438
+
293439 static void dwxgmac2_set_filter(struct mac_device_info *hw,
294440 struct net_device *dev)
295441 {
296442 void __iomem *ioaddr = (void __iomem *)dev->base_addr;
297
- u32 value = XGMAC_FILTER_RA;
443
+ u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
444
+ int mcbitslog2 = hw->mcast_bits_log2;
445
+ u32 mc_filter[8];
446
+ int i;
447
+
448
+ value &= ~(XGMAC_FILTER_PR | XGMAC_FILTER_HMC | XGMAC_FILTER_PM);
449
+ value |= XGMAC_FILTER_HPF;
450
+
451
+ memset(mc_filter, 0, sizeof(mc_filter));
298452
299453 if (dev->flags & IFF_PROMISC) {
300454 value |= XGMAC_FILTER_PR;
455
+ value |= XGMAC_FILTER_PCF;
301456 } else if ((dev->flags & IFF_ALLMULTI) ||
302
- (netdev_mc_count(dev) > HASH_TABLE_SIZE)) {
457
+ (netdev_mc_count(dev) > hw->multicast_filter_bins)) {
303458 value |= XGMAC_FILTER_PM;
304
- writel(~0x0, ioaddr + XGMAC_HASH_TABLE(0));
305
- writel(~0x0, ioaddr + XGMAC_HASH_TABLE(1));
459
+
460
+ for (i = 0; i < XGMAC_MAX_HASH_TABLE; i++)
461
+ writel(~0x0, ioaddr + XGMAC_HASH_TABLE(i));
462
+ } else if (!netdev_mc_empty(dev) && (dev->flags & IFF_MULTICAST)) {
463
+ struct netdev_hw_addr *ha;
464
+
465
+ value |= XGMAC_FILTER_HMC;
466
+
467
+ netdev_for_each_mc_addr(ha, dev) {
468
+ u32 nr = (bitrev32(~crc32_le(~0, ha->addr, 6)) >>
469
+ (32 - mcbitslog2));
470
+ mc_filter[nr >> 5] |= (1 << (nr & 0x1F));
471
+ }
472
+ }
473
+
474
+ dwxgmac2_set_mchash(ioaddr, mc_filter, mcbitslog2);
475
+
476
+ /* Handle multiple unicast addresses */
477
+ if (netdev_uc_count(dev) > hw->unicast_filter_entries) {
478
+ value |= XGMAC_FILTER_PR;
479
+ } else {
480
+ struct netdev_hw_addr *ha;
481
+ int reg = 1;
482
+
483
+ netdev_for_each_uc_addr(ha, dev) {
484
+ dwxgmac2_set_umac_addr(hw, ha->addr, reg);
485
+ reg++;
486
+ }
487
+
488
+ for ( ; reg < XGMAC_ADDR_MAX; reg++) {
489
+ writel(0, ioaddr + XGMAC_ADDRx_HIGH(reg));
490
+ writel(0, ioaddr + XGMAC_ADDRx_LOW(reg));
491
+ }
306492 }
307493
308494 writel(value, ioaddr + XGMAC_PACKET_FILTER);
495
+}
496
+
497
+static void dwxgmac2_set_mac_loopback(void __iomem *ioaddr, bool enable)
498
+{
499
+ u32 value = readl(ioaddr + XGMAC_RX_CONFIG);
500
+
501
+ if (enable)
502
+ value |= XGMAC_CONFIG_LM;
503
+ else
504
+ value &= ~XGMAC_CONFIG_LM;
505
+
506
+ writel(value, ioaddr + XGMAC_RX_CONFIG);
507
+}
508
+
509
+static int dwxgmac2_rss_write_reg(void __iomem *ioaddr, bool is_key, int idx,
510
+ u32 val)
511
+{
512
+ u32 ctrl = 0;
513
+
514
+ writel(val, ioaddr + XGMAC_RSS_DATA);
515
+ ctrl |= idx << XGMAC_RSSIA_SHIFT;
516
+ ctrl |= is_key ? XGMAC_ADDRT : 0x0;
517
+ ctrl |= XGMAC_OB;
518
+ writel(ctrl, ioaddr + XGMAC_RSS_ADDR);
519
+
520
+ return readl_poll_timeout(ioaddr + XGMAC_RSS_ADDR, ctrl,
521
+ !(ctrl & XGMAC_OB), 100, 10000);
522
+}
523
+
524
+static int dwxgmac2_rss_configure(struct mac_device_info *hw,
525
+ struct stmmac_rss *cfg, u32 num_rxq)
526
+{
527
+ void __iomem *ioaddr = hw->pcsr;
528
+ u32 value, *key;
529
+ int i, ret;
530
+
531
+ value = readl(ioaddr + XGMAC_RSS_CTRL);
532
+ if (!cfg || !cfg->enable) {
533
+ value &= ~XGMAC_RSSE;
534
+ writel(value, ioaddr + XGMAC_RSS_CTRL);
535
+ return 0;
536
+ }
537
+
538
+ key = (u32 *)cfg->key;
539
+ for (i = 0; i < (ARRAY_SIZE(cfg->key) / sizeof(u32)); i++) {
540
+ ret = dwxgmac2_rss_write_reg(ioaddr, true, i, key[i]);
541
+ if (ret)
542
+ return ret;
543
+ }
544
+
545
+ for (i = 0; i < ARRAY_SIZE(cfg->table); i++) {
546
+ ret = dwxgmac2_rss_write_reg(ioaddr, false, i, cfg->table[i]);
547
+ if (ret)
548
+ return ret;
549
+ }
550
+
551
+ for (i = 0; i < num_rxq; i++)
552
+ dwxgmac2_map_mtl_to_dma(hw, i, XGMAC_QDDMACH);
553
+
554
+ value |= XGMAC_UDP4TE | XGMAC_TCP4TE | XGMAC_IP2TE | XGMAC_RSSE;
555
+ writel(value, ioaddr + XGMAC_RSS_CTRL);
556
+ return 0;
557
+}
558
+
559
+static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
560
+ __le16 perfect_match, bool is_double)
561
+{
562
+ void __iomem *ioaddr = hw->pcsr;
563
+
564
+ writel(hash, ioaddr + XGMAC_VLAN_HASH_TABLE);
565
+
566
+ if (hash) {
567
+ u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
568
+
569
+ value |= XGMAC_FILTER_VTFE;
570
+
571
+ writel(value, ioaddr + XGMAC_PACKET_FILTER);
572
+
573
+ value = readl(ioaddr + XGMAC_VLAN_TAG);
574
+
575
+ value |= XGMAC_VLAN_VTHM | XGMAC_VLAN_ETV;
576
+ if (is_double) {
577
+ value |= XGMAC_VLAN_EDVLP;
578
+ value |= XGMAC_VLAN_ESVL;
579
+ value |= XGMAC_VLAN_DOVLTC;
580
+ } else {
581
+ value &= ~XGMAC_VLAN_EDVLP;
582
+ value &= ~XGMAC_VLAN_ESVL;
583
+ value &= ~XGMAC_VLAN_DOVLTC;
584
+ }
585
+
586
+ value &= ~XGMAC_VLAN_VID;
587
+ writel(value, ioaddr + XGMAC_VLAN_TAG);
588
+ } else if (perfect_match) {
589
+ u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
590
+
591
+ value |= XGMAC_FILTER_VTFE;
592
+
593
+ writel(value, ioaddr + XGMAC_PACKET_FILTER);
594
+
595
+ value = readl(ioaddr + XGMAC_VLAN_TAG);
596
+
597
+ value &= ~XGMAC_VLAN_VTHM;
598
+ value |= XGMAC_VLAN_ETV;
599
+ if (is_double) {
600
+ value |= XGMAC_VLAN_EDVLP;
601
+ value |= XGMAC_VLAN_ESVL;
602
+ value |= XGMAC_VLAN_DOVLTC;
603
+ } else {
604
+ value &= ~XGMAC_VLAN_EDVLP;
605
+ value &= ~XGMAC_VLAN_ESVL;
606
+ value &= ~XGMAC_VLAN_DOVLTC;
607
+ }
608
+
609
+ value &= ~XGMAC_VLAN_VID;
610
+ writel(value | perfect_match, ioaddr + XGMAC_VLAN_TAG);
611
+ } else {
612
+ u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
613
+
614
+ value &= ~XGMAC_FILTER_VTFE;
615
+
616
+ writel(value, ioaddr + XGMAC_PACKET_FILTER);
617
+
618
+ value = readl(ioaddr + XGMAC_VLAN_TAG);
619
+
620
+ value &= ~(XGMAC_VLAN_VTHM | XGMAC_VLAN_ETV);
621
+ value &= ~(XGMAC_VLAN_EDVLP | XGMAC_VLAN_ESVL);
622
+ value &= ~XGMAC_VLAN_DOVLTC;
623
+ value &= ~XGMAC_VLAN_VID;
624
+
625
+ writel(value, ioaddr + XGMAC_VLAN_TAG);
626
+ }
627
+}
628
+
629
+struct dwxgmac3_error_desc {
630
+ bool valid;
631
+ const char *desc;
632
+ const char *detailed_desc;
633
+};
634
+
635
+#define STAT_OFF(field) offsetof(struct stmmac_safety_stats, field)
636
+
637
+static void dwxgmac3_log_error(struct net_device *ndev, u32 value, bool corr,
638
+ const char *module_name,
639
+ const struct dwxgmac3_error_desc *desc,
640
+ unsigned long field_offset,
641
+ struct stmmac_safety_stats *stats)
642
+{
643
+ unsigned long loc, mask;
644
+ u8 *bptr = (u8 *)stats;
645
+ unsigned long *ptr;
646
+
647
+ ptr = (unsigned long *)(bptr + field_offset);
648
+
649
+ mask = value;
650
+ for_each_set_bit(loc, &mask, 32) {
651
+ netdev_err(ndev, "Found %s error in %s: '%s: %s'\n", corr ?
652
+ "correctable" : "uncorrectable", module_name,
653
+ desc[loc].desc, desc[loc].detailed_desc);
654
+
655
+ /* Update counters */
656
+ ptr[loc]++;
657
+ }
658
+}
659
+
660
+static const struct dwxgmac3_error_desc dwxgmac3_mac_errors[32]= {
661
+ { true, "ATPES", "Application Transmit Interface Parity Check Error" },
662
+ { true, "DPES", "Descriptor Cache Data Path Parity Check Error" },
663
+ { true, "TPES", "TSO Data Path Parity Check Error" },
664
+ { true, "TSOPES", "TSO Header Data Path Parity Check Error" },
665
+ { true, "MTPES", "MTL Data Path Parity Check Error" },
666
+ { true, "MTSPES", "MTL TX Status Data Path Parity Check Error" },
667
+ { true, "MTBUPES", "MAC TBU Data Path Parity Check Error" },
668
+ { true, "MTFCPES", "MAC TFC Data Path Parity Check Error" },
669
+ { true, "ARPES", "Application Receive Interface Data Path Parity Check Error" },
670
+ { true, "MRWCPES", "MTL RWC Data Path Parity Check Error" },
671
+ { true, "MRRCPES", "MTL RCC Data Path Parity Check Error" },
672
+ { true, "CWPES", "CSR Write Data Path Parity Check Error" },
673
+ { true, "ASRPES", "AXI Slave Read Data Path Parity Check Error" },
674
+ { true, "TTES", "TX FSM Timeout Error" },
675
+ { true, "RTES", "RX FSM Timeout Error" },
676
+ { true, "CTES", "CSR FSM Timeout Error" },
677
+ { true, "ATES", "APP FSM Timeout Error" },
678
+ { true, "PTES", "PTP FSM Timeout Error" },
679
+ { false, "UNKNOWN", "Unknown Error" }, /* 18 */
680
+ { false, "UNKNOWN", "Unknown Error" }, /* 19 */
681
+ { false, "UNKNOWN", "Unknown Error" }, /* 20 */
682
+ { true, "MSTTES", "Master Read/Write Timeout Error" },
683
+ { true, "SLVTES", "Slave Read/Write Timeout Error" },
684
+ { true, "ATITES", "Application Timeout on ATI Interface Error" },
685
+ { true, "ARITES", "Application Timeout on ARI Interface Error" },
686
+ { true, "FSMPES", "FSM State Parity Error" },
687
+ { false, "UNKNOWN", "Unknown Error" }, /* 26 */
688
+ { false, "UNKNOWN", "Unknown Error" }, /* 27 */
689
+ { false, "UNKNOWN", "Unknown Error" }, /* 28 */
690
+ { false, "UNKNOWN", "Unknown Error" }, /* 29 */
691
+ { false, "UNKNOWN", "Unknown Error" }, /* 30 */
692
+ { true, "CPI", "Control Register Parity Check Error" },
693
+};
694
+
695
+static void dwxgmac3_handle_mac_err(struct net_device *ndev,
696
+ void __iomem *ioaddr, bool correctable,
697
+ struct stmmac_safety_stats *stats)
698
+{
699
+ u32 value;
700
+
701
+ value = readl(ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS);
702
+ writel(value, ioaddr + XGMAC_MAC_DPP_FSM_INT_STATUS);
703
+
704
+ dwxgmac3_log_error(ndev, value, correctable, "MAC",
705
+ dwxgmac3_mac_errors, STAT_OFF(mac_errors), stats);
706
+}
707
+
708
+static const struct dwxgmac3_error_desc dwxgmac3_mtl_errors[32]= {
709
+ { true, "TXCES", "MTL TX Memory Error" },
710
+ { true, "TXAMS", "MTL TX Memory Address Mismatch Error" },
711
+ { true, "TXUES", "MTL TX Memory Error" },
712
+ { false, "UNKNOWN", "Unknown Error" }, /* 3 */
713
+ { true, "RXCES", "MTL RX Memory Error" },
714
+ { true, "RXAMS", "MTL RX Memory Address Mismatch Error" },
715
+ { true, "RXUES", "MTL RX Memory Error" },
716
+ { false, "UNKNOWN", "Unknown Error" }, /* 7 */
717
+ { true, "ECES", "MTL EST Memory Error" },
718
+ { true, "EAMS", "MTL EST Memory Address Mismatch Error" },
719
+ { true, "EUES", "MTL EST Memory Error" },
720
+ { false, "UNKNOWN", "Unknown Error" }, /* 11 */
721
+ { true, "RPCES", "MTL RX Parser Memory Error" },
722
+ { true, "RPAMS", "MTL RX Parser Memory Address Mismatch Error" },
723
+ { true, "RPUES", "MTL RX Parser Memory Error" },
724
+ { false, "UNKNOWN", "Unknown Error" }, /* 15 */
725
+ { false, "UNKNOWN", "Unknown Error" }, /* 16 */
726
+ { false, "UNKNOWN", "Unknown Error" }, /* 17 */
727
+ { false, "UNKNOWN", "Unknown Error" }, /* 18 */
728
+ { false, "UNKNOWN", "Unknown Error" }, /* 19 */
729
+ { false, "UNKNOWN", "Unknown Error" }, /* 20 */
730
+ { false, "UNKNOWN", "Unknown Error" }, /* 21 */
731
+ { false, "UNKNOWN", "Unknown Error" }, /* 22 */
732
+ { false, "UNKNOWN", "Unknown Error" }, /* 23 */
733
+ { false, "UNKNOWN", "Unknown Error" }, /* 24 */
734
+ { false, "UNKNOWN", "Unknown Error" }, /* 25 */
735
+ { false, "UNKNOWN", "Unknown Error" }, /* 26 */
736
+ { false, "UNKNOWN", "Unknown Error" }, /* 27 */
737
+ { false, "UNKNOWN", "Unknown Error" }, /* 28 */
738
+ { false, "UNKNOWN", "Unknown Error" }, /* 29 */
739
+ { false, "UNKNOWN", "Unknown Error" }, /* 30 */
740
+ { false, "UNKNOWN", "Unknown Error" }, /* 31 */
741
+};
742
+
743
+static void dwxgmac3_handle_mtl_err(struct net_device *ndev,
744
+ void __iomem *ioaddr, bool correctable,
745
+ struct stmmac_safety_stats *stats)
746
+{
747
+ u32 value;
748
+
749
+ value = readl(ioaddr + XGMAC_MTL_ECC_INT_STATUS);
750
+ writel(value, ioaddr + XGMAC_MTL_ECC_INT_STATUS);
751
+
752
+ dwxgmac3_log_error(ndev, value, correctable, "MTL",
753
+ dwxgmac3_mtl_errors, STAT_OFF(mtl_errors), stats);
754
+}
755
+
756
+static const struct dwxgmac3_error_desc dwxgmac3_dma_errors[32]= {
757
+ { true, "TCES", "DMA TSO Memory Error" },
758
+ { true, "TAMS", "DMA TSO Memory Address Mismatch Error" },
759
+ { true, "TUES", "DMA TSO Memory Error" },
760
+ { false, "UNKNOWN", "Unknown Error" }, /* 3 */
761
+ { true, "DCES", "DMA DCACHE Memory Error" },
762
+ { true, "DAMS", "DMA DCACHE Address Mismatch Error" },
763
+ { true, "DUES", "DMA DCACHE Memory Error" },
764
+ { false, "UNKNOWN", "Unknown Error" }, /* 7 */
765
+ { false, "UNKNOWN", "Unknown Error" }, /* 8 */
766
+ { false, "UNKNOWN", "Unknown Error" }, /* 9 */
767
+ { false, "UNKNOWN", "Unknown Error" }, /* 10 */
768
+ { false, "UNKNOWN", "Unknown Error" }, /* 11 */
769
+ { false, "UNKNOWN", "Unknown Error" }, /* 12 */
770
+ { false, "UNKNOWN", "Unknown Error" }, /* 13 */
771
+ { false, "UNKNOWN", "Unknown Error" }, /* 14 */
772
+ { false, "UNKNOWN", "Unknown Error" }, /* 15 */
773
+ { false, "UNKNOWN", "Unknown Error" }, /* 16 */
774
+ { false, "UNKNOWN", "Unknown Error" }, /* 17 */
775
+ { false, "UNKNOWN", "Unknown Error" }, /* 18 */
776
+ { false, "UNKNOWN", "Unknown Error" }, /* 19 */
777
+ { false, "UNKNOWN", "Unknown Error" }, /* 20 */
778
+ { false, "UNKNOWN", "Unknown Error" }, /* 21 */
779
+ { false, "UNKNOWN", "Unknown Error" }, /* 22 */
780
+ { false, "UNKNOWN", "Unknown Error" }, /* 23 */
781
+ { false, "UNKNOWN", "Unknown Error" }, /* 24 */
782
+ { false, "UNKNOWN", "Unknown Error" }, /* 25 */
783
+ { false, "UNKNOWN", "Unknown Error" }, /* 26 */
784
+ { false, "UNKNOWN", "Unknown Error" }, /* 27 */
785
+ { false, "UNKNOWN", "Unknown Error" }, /* 28 */
786
+ { false, "UNKNOWN", "Unknown Error" }, /* 29 */
787
+ { false, "UNKNOWN", "Unknown Error" }, /* 30 */
788
+ { false, "UNKNOWN", "Unknown Error" }, /* 31 */
789
+};
790
+
791
+static void dwxgmac3_handle_dma_err(struct net_device *ndev,
792
+ void __iomem *ioaddr, bool correctable,
793
+ struct stmmac_safety_stats *stats)
794
+{
795
+ u32 value;
796
+
797
+ value = readl(ioaddr + XGMAC_DMA_ECC_INT_STATUS);
798
+ writel(value, ioaddr + XGMAC_DMA_ECC_INT_STATUS);
799
+
800
+ dwxgmac3_log_error(ndev, value, correctable, "DMA",
801
+ dwxgmac3_dma_errors, STAT_OFF(dma_errors), stats);
802
+}
803
+
804
+static int dwxgmac3_safety_feat_config(void __iomem *ioaddr, unsigned int asp)
805
+{
806
+ u32 value;
807
+
808
+ if (!asp)
809
+ return -EINVAL;
810
+
811
+ /* 1. Enable Safety Features */
812
+ writel(0x0, ioaddr + XGMAC_MTL_ECC_CONTROL);
813
+
814
+ /* 2. Enable MTL Safety Interrupts */
815
+ value = readl(ioaddr + XGMAC_MTL_ECC_INT_ENABLE);
816
+ value |= XGMAC_RPCEIE; /* RX Parser Memory Correctable Error */
817
+ value |= XGMAC_ECEIE; /* EST Memory Correctable Error */
818
+ value |= XGMAC_RXCEIE; /* RX Memory Correctable Error */
819
+ value |= XGMAC_TXCEIE; /* TX Memory Correctable Error */
820
+ writel(value, ioaddr + XGMAC_MTL_ECC_INT_ENABLE);
821
+
822
+ /* 3. Enable DMA Safety Interrupts */
823
+ value = readl(ioaddr + XGMAC_DMA_ECC_INT_ENABLE);
824
+ value |= XGMAC_DCEIE; /* Descriptor Cache Memory Correctable Error */
825
+ value |= XGMAC_TCEIE; /* TSO Memory Correctable Error */
826
+ writel(value, ioaddr + XGMAC_DMA_ECC_INT_ENABLE);
827
+
828
+ /* Only ECC Protection for External Memory feature is selected */
829
+ if (asp <= 0x1)
830
+ return 0;
831
+
832
+ /* 4. Enable Parity and Timeout for FSM */
833
+ value = readl(ioaddr + XGMAC_MAC_FSM_CONTROL);
834
+ value |= XGMAC_PRTYEN; /* FSM Parity Feature */
835
+ value |= XGMAC_TMOUTEN; /* FSM Timeout Feature */
836
+ writel(value, ioaddr + XGMAC_MAC_FSM_CONTROL);
837
+
838
+ return 0;
839
+}
840
+
841
+static int dwxgmac3_safety_feat_irq_status(struct net_device *ndev,
842
+ void __iomem *ioaddr,
843
+ unsigned int asp,
844
+ struct stmmac_safety_stats *stats)
845
+{
846
+ bool err, corr;
847
+ u32 mtl, dma;
848
+ int ret = 0;
849
+
850
+ if (!asp)
851
+ return -EINVAL;
852
+
853
+ mtl = readl(ioaddr + XGMAC_MTL_SAFETY_INT_STATUS);
854
+ dma = readl(ioaddr + XGMAC_DMA_SAFETY_INT_STATUS);
855
+
856
+ err = (mtl & XGMAC_MCSIS) || (dma & XGMAC_MCSIS);
857
+ corr = false;
858
+ if (err) {
859
+ dwxgmac3_handle_mac_err(ndev, ioaddr, corr, stats);
860
+ ret |= !corr;
861
+ }
862
+
863
+ err = (mtl & (XGMAC_MEUIS | XGMAC_MECIS)) ||
864
+ (dma & (XGMAC_MSUIS | XGMAC_MSCIS));
865
+ corr = (mtl & XGMAC_MECIS) || (dma & XGMAC_MSCIS);
866
+ if (err) {
867
+ dwxgmac3_handle_mtl_err(ndev, ioaddr, corr, stats);
868
+ ret |= !corr;
869
+ }
870
+
871
+ err = dma & (XGMAC_DEUIS | XGMAC_DECIS);
872
+ corr = dma & XGMAC_DECIS;
873
+ if (err) {
874
+ dwxgmac3_handle_dma_err(ndev, ioaddr, corr, stats);
875
+ ret |= !corr;
876
+ }
877
+
878
+ return ret;
879
+}
880
+
881
+static const struct dwxgmac3_error {
882
+ const struct dwxgmac3_error_desc *desc;
883
+} dwxgmac3_all_errors[] = {
884
+ { dwxgmac3_mac_errors },
885
+ { dwxgmac3_mtl_errors },
886
+ { dwxgmac3_dma_errors },
887
+};
888
+
889
+static int dwxgmac3_safety_feat_dump(struct stmmac_safety_stats *stats,
890
+ int index, unsigned long *count,
891
+ const char **desc)
892
+{
893
+ int module = index / 32, offset = index % 32;
894
+ unsigned long *ptr = (unsigned long *)stats;
895
+
896
+ if (module >= ARRAY_SIZE(dwxgmac3_all_errors))
897
+ return -EINVAL;
898
+ if (!dwxgmac3_all_errors[module].desc[offset].valid)
899
+ return -EINVAL;
900
+ if (count)
901
+ *count = *(ptr + index);
902
+ if (desc)
903
+ *desc = dwxgmac3_all_errors[module].desc[offset].desc;
904
+ return 0;
905
+}
906
+
907
+static int dwxgmac3_rxp_disable(void __iomem *ioaddr)
908
+{
909
+ u32 val = readl(ioaddr + XGMAC_MTL_OPMODE);
910
+
911
+ val &= ~XGMAC_FRPE;
912
+ writel(val, ioaddr + XGMAC_MTL_OPMODE);
913
+
914
+ return 0;
915
+}
916
+
917
+static void dwxgmac3_rxp_enable(void __iomem *ioaddr)
918
+{
919
+ u32 val;
920
+
921
+ val = readl(ioaddr + XGMAC_MTL_OPMODE);
922
+ val |= XGMAC_FRPE;
923
+ writel(val, ioaddr + XGMAC_MTL_OPMODE);
924
+}
925
+
926
+static int dwxgmac3_rxp_update_single_entry(void __iomem *ioaddr,
927
+ struct stmmac_tc_entry *entry,
928
+ int pos)
929
+{
930
+ int ret, i;
931
+
932
+ for (i = 0; i < (sizeof(entry->val) / sizeof(u32)); i++) {
933
+ int real_pos = pos * (sizeof(entry->val) / sizeof(u32)) + i;
934
+ u32 val;
935
+
936
+ /* Wait for ready */
937
+ ret = readl_poll_timeout(ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST,
938
+ val, !(val & XGMAC_STARTBUSY), 1, 10000);
939
+ if (ret)
940
+ return ret;
941
+
942
+ /* Write data */
943
+ val = *((u32 *)&entry->val + i);
944
+ writel(val, ioaddr + XGMAC_MTL_RXP_IACC_DATA);
945
+
946
+ /* Write pos */
947
+ val = real_pos & XGMAC_ADDR;
948
+ writel(val, ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST);
949
+
950
+ /* Write OP */
951
+ val |= XGMAC_WRRDN;
952
+ writel(val, ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST);
953
+
954
+ /* Start Write */
955
+ val |= XGMAC_STARTBUSY;
956
+ writel(val, ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST);
957
+
958
+ /* Wait for done */
959
+ ret = readl_poll_timeout(ioaddr + XGMAC_MTL_RXP_IACC_CTRL_ST,
960
+ val, !(val & XGMAC_STARTBUSY), 1, 10000);
961
+ if (ret)
962
+ return ret;
963
+ }
964
+
965
+ return 0;
966
+}
967
+
968
+static struct stmmac_tc_entry *
969
+dwxgmac3_rxp_get_next_entry(struct stmmac_tc_entry *entries,
970
+ unsigned int count, u32 curr_prio)
971
+{
972
+ struct stmmac_tc_entry *entry;
973
+ u32 min_prio = ~0x0;
974
+ int i, min_prio_idx;
975
+ bool found = false;
976
+
977
+ for (i = count - 1; i >= 0; i--) {
978
+ entry = &entries[i];
979
+
980
+ /* Do not update unused entries */
981
+ if (!entry->in_use)
982
+ continue;
983
+ /* Do not update already updated entries (i.e. fragments) */
984
+ if (entry->in_hw)
985
+ continue;
986
+ /* Let last entry be updated last */
987
+ if (entry->is_last)
988
+ continue;
989
+ /* Do not return fragments */
990
+ if (entry->is_frag)
991
+ continue;
992
+ /* Check if we already checked this prio */
993
+ if (entry->prio < curr_prio)
994
+ continue;
995
+ /* Check if this is the minimum prio */
996
+ if (entry->prio < min_prio) {
997
+ min_prio = entry->prio;
998
+ min_prio_idx = i;
999
+ found = true;
1000
+ }
1001
+ }
1002
+
1003
+ if (found)
1004
+ return &entries[min_prio_idx];
1005
+ return NULL;
1006
+}
1007
+
1008
+static int dwxgmac3_rxp_config(void __iomem *ioaddr,
1009
+ struct stmmac_tc_entry *entries,
1010
+ unsigned int count)
1011
+{
1012
+ struct stmmac_tc_entry *entry, *frag;
1013
+ int i, ret, nve = 0;
1014
+ u32 curr_prio = 0;
1015
+ u32 old_val, val;
1016
+
1017
+ /* Force disable RX */
1018
+ old_val = readl(ioaddr + XGMAC_RX_CONFIG);
1019
+ val = old_val & ~XGMAC_CONFIG_RE;
1020
+ writel(val, ioaddr + XGMAC_RX_CONFIG);
1021
+
1022
+ /* Disable RX Parser */
1023
+ ret = dwxgmac3_rxp_disable(ioaddr);
1024
+ if (ret)
1025
+ goto re_enable;
1026
+
1027
+ /* Set all entries as NOT in HW */
1028
+ for (i = 0; i < count; i++) {
1029
+ entry = &entries[i];
1030
+ entry->in_hw = false;
1031
+ }
1032
+
1033
+ /* Update entries by reverse order */
1034
+ while (1) {
1035
+ entry = dwxgmac3_rxp_get_next_entry(entries, count, curr_prio);
1036
+ if (!entry)
1037
+ break;
1038
+
1039
+ curr_prio = entry->prio;
1040
+ frag = entry->frag_ptr;
1041
+
1042
+ /* Set special fragment requirements */
1043
+ if (frag) {
1044
+ entry->val.af = 0;
1045
+ entry->val.rf = 0;
1046
+ entry->val.nc = 1;
1047
+ entry->val.ok_index = nve + 2;
1048
+ }
1049
+
1050
+ ret = dwxgmac3_rxp_update_single_entry(ioaddr, entry, nve);
1051
+ if (ret)
1052
+ goto re_enable;
1053
+
1054
+ entry->table_pos = nve++;
1055
+ entry->in_hw = true;
1056
+
1057
+ if (frag && !frag->in_hw) {
1058
+ ret = dwxgmac3_rxp_update_single_entry(ioaddr, frag, nve);
1059
+ if (ret)
1060
+ goto re_enable;
1061
+ frag->table_pos = nve++;
1062
+ frag->in_hw = true;
1063
+ }
1064
+ }
1065
+
1066
+ if (!nve)
1067
+ goto re_enable;
1068
+
1069
+ /* Update all pass entry */
1070
+ for (i = 0; i < count; i++) {
1071
+ entry = &entries[i];
1072
+ if (!entry->is_last)
1073
+ continue;
1074
+
1075
+ ret = dwxgmac3_rxp_update_single_entry(ioaddr, entry, nve);
1076
+ if (ret)
1077
+ goto re_enable;
1078
+
1079
+ entry->table_pos = nve++;
1080
+ }
1081
+
1082
+ /* Assume n. of parsable entries == n. of valid entries */
1083
+ val = (nve << 16) & XGMAC_NPE;
1084
+ val |= nve & XGMAC_NVE;
1085
+ writel(val, ioaddr + XGMAC_MTL_RXP_CONTROL_STATUS);
1086
+
1087
+ /* Enable RX Parser */
1088
+ dwxgmac3_rxp_enable(ioaddr);
1089
+
1090
+re_enable:
1091
+ /* Re-enable RX */
1092
+ writel(old_val, ioaddr + XGMAC_RX_CONFIG);
1093
+ return ret;
1094
+}
1095
+
1096
+static int dwxgmac2_get_mac_tx_timestamp(struct mac_device_info *hw, u64 *ts)
1097
+{
1098
+ void __iomem *ioaddr = hw->pcsr;
1099
+ u32 value;
1100
+
1101
+ if (readl_poll_timeout_atomic(ioaddr + XGMAC_TIMESTAMP_STATUS,
1102
+ value, value & XGMAC_TXTSC, 100, 10000))
1103
+ return -EBUSY;
1104
+
1105
+ *ts = readl(ioaddr + XGMAC_TXTIMESTAMP_NSEC) & XGMAC_TXTSSTSLO;
1106
+ *ts += readl(ioaddr + XGMAC_TXTIMESTAMP_SEC) * 1000000000ULL;
1107
+ return 0;
1108
+}
1109
+
1110
+static int dwxgmac2_flex_pps_config(void __iomem *ioaddr, int index,
1111
+ struct stmmac_pps_cfg *cfg, bool enable,
1112
+ u32 sub_second_inc, u32 systime_flags)
1113
+{
1114
+ u32 tnsec = readl(ioaddr + XGMAC_PPSx_TARGET_TIME_NSEC(index));
1115
+ u32 val = readl(ioaddr + XGMAC_PPS_CONTROL);
1116
+ u64 period;
1117
+
1118
+ if (!cfg->available)
1119
+ return -EINVAL;
1120
+ if (tnsec & XGMAC_TRGTBUSY0)
1121
+ return -EBUSY;
1122
+ if (!sub_second_inc || !systime_flags)
1123
+ return -EINVAL;
1124
+
1125
+ val &= ~XGMAC_PPSx_MASK(index);
1126
+
1127
+ if (!enable) {
1128
+ val |= XGMAC_PPSCMDx(index, XGMAC_PPSCMD_STOP);
1129
+ writel(val, ioaddr + XGMAC_PPS_CONTROL);
1130
+ return 0;
1131
+ }
1132
+
1133
+ val |= XGMAC_PPSCMDx(index, XGMAC_PPSCMD_START);
1134
+ val |= XGMAC_TRGTMODSELx(index, XGMAC_PPSCMD_START);
1135
+ val |= XGMAC_PPSEN0;
1136
+
1137
+ writel(cfg->start.tv_sec, ioaddr + XGMAC_PPSx_TARGET_TIME_SEC(index));
1138
+
1139
+ if (!(systime_flags & PTP_TCR_TSCTRLSSR))
1140
+ cfg->start.tv_nsec = (cfg->start.tv_nsec * 1000) / 465;
1141
+ writel(cfg->start.tv_nsec, ioaddr + XGMAC_PPSx_TARGET_TIME_NSEC(index));
1142
+
1143
+ period = cfg->period.tv_sec * 1000000000;
1144
+ period += cfg->period.tv_nsec;
1145
+
1146
+ do_div(period, sub_second_inc);
1147
+
1148
+ if (period <= 1)
1149
+ return -EINVAL;
1150
+
1151
+ writel(period - 1, ioaddr + XGMAC_PPSx_INTERVAL(index));
1152
+
1153
+ period >>= 1;
1154
+ if (period <= 1)
1155
+ return -EINVAL;
1156
+
1157
+ writel(period - 1, ioaddr + XGMAC_PPSx_WIDTH(index));
1158
+
1159
+ /* Finally, activate it */
1160
+ writel(val, ioaddr + XGMAC_PPS_CONTROL);
1161
+ return 0;
1162
+}
1163
+
1164
+static void dwxgmac2_sarc_configure(void __iomem *ioaddr, int val)
1165
+{
1166
+ u32 value = readl(ioaddr + XGMAC_TX_CONFIG);
1167
+
1168
+ value &= ~XGMAC_CONFIG_SARC;
1169
+ value |= val << XGMAC_CONFIG_SARC_SHIFT;
1170
+
1171
+ writel(value, ioaddr + XGMAC_TX_CONFIG);
1172
+}
1173
+
1174
+static void dwxgmac2_enable_vlan(struct mac_device_info *hw, u32 type)
1175
+{
1176
+ void __iomem *ioaddr = hw->pcsr;
1177
+ u32 value;
1178
+
1179
+ value = readl(ioaddr + XGMAC_VLAN_INCL);
1180
+ value |= XGMAC_VLAN_VLTI;
1181
+ value |= XGMAC_VLAN_CSVL; /* Only use SVLAN */
1182
+ value &= ~XGMAC_VLAN_VLC;
1183
+ value |= (type << XGMAC_VLAN_VLC_SHIFT) & XGMAC_VLAN_VLC;
1184
+ writel(value, ioaddr + XGMAC_VLAN_INCL);
1185
+}
1186
+
1187
+static int dwxgmac2_filter_wait(struct mac_device_info *hw)
1188
+{
1189
+ void __iomem *ioaddr = hw->pcsr;
1190
+ u32 value;
1191
+
1192
+ if (readl_poll_timeout(ioaddr + XGMAC_L3L4_ADDR_CTRL, value,
1193
+ !(value & XGMAC_XB), 100, 10000))
1194
+ return -EBUSY;
1195
+ return 0;
1196
+}
1197
+
1198
+static int dwxgmac2_filter_read(struct mac_device_info *hw, u32 filter_no,
1199
+ u8 reg, u32 *data)
1200
+{
1201
+ void __iomem *ioaddr = hw->pcsr;
1202
+ u32 value;
1203
+ int ret;
1204
+
1205
+ ret = dwxgmac2_filter_wait(hw);
1206
+ if (ret)
1207
+ return ret;
1208
+
1209
+ value = ((filter_no << XGMAC_IDDR_FNUM) | reg) << XGMAC_IDDR_SHIFT;
1210
+ value |= XGMAC_TT | XGMAC_XB;
1211
+ writel(value, ioaddr + XGMAC_L3L4_ADDR_CTRL);
1212
+
1213
+ ret = dwxgmac2_filter_wait(hw);
1214
+ if (ret)
1215
+ return ret;
1216
+
1217
+ *data = readl(ioaddr + XGMAC_L3L4_DATA);
1218
+ return 0;
1219
+}
1220
+
1221
+static int dwxgmac2_filter_write(struct mac_device_info *hw, u32 filter_no,
1222
+ u8 reg, u32 data)
1223
+{
1224
+ void __iomem *ioaddr = hw->pcsr;
1225
+ u32 value;
1226
+ int ret;
1227
+
1228
+ ret = dwxgmac2_filter_wait(hw);
1229
+ if (ret)
1230
+ return ret;
1231
+
1232
+ writel(data, ioaddr + XGMAC_L3L4_DATA);
1233
+
1234
+ value = ((filter_no << XGMAC_IDDR_FNUM) | reg) << XGMAC_IDDR_SHIFT;
1235
+ value |= XGMAC_XB;
1236
+ writel(value, ioaddr + XGMAC_L3L4_ADDR_CTRL);
1237
+
1238
+ return dwxgmac2_filter_wait(hw);
1239
+}
1240
+
1241
+static int dwxgmac2_config_l3_filter(struct mac_device_info *hw, u32 filter_no,
1242
+ bool en, bool ipv6, bool sa, bool inv,
1243
+ u32 match)
1244
+{
1245
+ void __iomem *ioaddr = hw->pcsr;
1246
+ u32 value;
1247
+ int ret;
1248
+
1249
+ value = readl(ioaddr + XGMAC_PACKET_FILTER);
1250
+ value |= XGMAC_FILTER_IPFE;
1251
+ writel(value, ioaddr + XGMAC_PACKET_FILTER);
1252
+
1253
+ ret = dwxgmac2_filter_read(hw, filter_no, XGMAC_L3L4_CTRL, &value);
1254
+ if (ret)
1255
+ return ret;
1256
+
1257
+ /* For IPv6 not both SA/DA filters can be active */
1258
+ if (ipv6) {
1259
+ value |= XGMAC_L3PEN0;
1260
+ value &= ~(XGMAC_L3SAM0 | XGMAC_L3SAIM0);
1261
+ value &= ~(XGMAC_L3DAM0 | XGMAC_L3DAIM0);
1262
+ if (sa) {
1263
+ value |= XGMAC_L3SAM0;
1264
+ if (inv)
1265
+ value |= XGMAC_L3SAIM0;
1266
+ } else {
1267
+ value |= XGMAC_L3DAM0;
1268
+ if (inv)
1269
+ value |= XGMAC_L3DAIM0;
1270
+ }
1271
+ } else {
1272
+ value &= ~XGMAC_L3PEN0;
1273
+ if (sa) {
1274
+ value |= XGMAC_L3SAM0;
1275
+ if (inv)
1276
+ value |= XGMAC_L3SAIM0;
1277
+ } else {
1278
+ value |= XGMAC_L3DAM0;
1279
+ if (inv)
1280
+ value |= XGMAC_L3DAIM0;
1281
+ }
1282
+ }
1283
+
1284
+ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, value);
1285
+ if (ret)
1286
+ return ret;
1287
+
1288
+ if (sa) {
1289
+ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L3_ADDR0, match);
1290
+ if (ret)
1291
+ return ret;
1292
+ } else {
1293
+ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L3_ADDR1, match);
1294
+ if (ret)
1295
+ return ret;
1296
+ }
1297
+
1298
+ if (!en)
1299
+ return dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, 0);
1300
+
1301
+ return 0;
1302
+}
1303
+
1304
+static int dwxgmac2_config_l4_filter(struct mac_device_info *hw, u32 filter_no,
1305
+ bool en, bool udp, bool sa, bool inv,
1306
+ u32 match)
1307
+{
1308
+ void __iomem *ioaddr = hw->pcsr;
1309
+ u32 value;
1310
+ int ret;
1311
+
1312
+ value = readl(ioaddr + XGMAC_PACKET_FILTER);
1313
+ value |= XGMAC_FILTER_IPFE;
1314
+ writel(value, ioaddr + XGMAC_PACKET_FILTER);
1315
+
1316
+ ret = dwxgmac2_filter_read(hw, filter_no, XGMAC_L3L4_CTRL, &value);
1317
+ if (ret)
1318
+ return ret;
1319
+
1320
+ if (udp) {
1321
+ value |= XGMAC_L4PEN0;
1322
+ } else {
1323
+ value &= ~XGMAC_L4PEN0;
1324
+ }
1325
+
1326
+ value &= ~(XGMAC_L4SPM0 | XGMAC_L4SPIM0);
1327
+ value &= ~(XGMAC_L4DPM0 | XGMAC_L4DPIM0);
1328
+ if (sa) {
1329
+ value |= XGMAC_L4SPM0;
1330
+ if (inv)
1331
+ value |= XGMAC_L4SPIM0;
1332
+ } else {
1333
+ value |= XGMAC_L4DPM0;
1334
+ if (inv)
1335
+ value |= XGMAC_L4DPIM0;
1336
+ }
1337
+
1338
+ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, value);
1339
+ if (ret)
1340
+ return ret;
1341
+
1342
+ if (sa) {
1343
+ value = match & XGMAC_L4SP0;
1344
+
1345
+ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value);
1346
+ if (ret)
1347
+ return ret;
1348
+ } else {
1349
+ value = (match << XGMAC_L4DP0_SHIFT) & XGMAC_L4DP0;
1350
+
1351
+ ret = dwxgmac2_filter_write(hw, filter_no, XGMAC_L4_ADDR, value);
1352
+ if (ret)
1353
+ return ret;
1354
+ }
1355
+
1356
+ if (!en)
1357
+ return dwxgmac2_filter_write(hw, filter_no, XGMAC_L3L4_CTRL, 0);
1358
+
1359
+ return 0;
1360
+}
1361
+
1362
+static void dwxgmac2_set_arp_offload(struct mac_device_info *hw, bool en,
1363
+ u32 addr)
1364
+{
1365
+ void __iomem *ioaddr = hw->pcsr;
1366
+ u32 value;
1367
+
1368
+ writel(addr, ioaddr + XGMAC_ARP_ADDR);
1369
+
1370
+ value = readl(ioaddr + XGMAC_RX_CONFIG);
1371
+ if (en)
1372
+ value |= XGMAC_CONFIG_ARPEN;
1373
+ else
1374
+ value &= ~XGMAC_CONFIG_ARPEN;
1375
+ writel(value, ioaddr + XGMAC_RX_CONFIG);
1376
+}
1377
+
1378
+static int dwxgmac3_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcl)
1379
+{
1380
+ u32 ctrl;
1381
+
1382
+ writel(val, ioaddr + XGMAC_MTL_EST_GCL_DATA);
1383
+
1384
+ ctrl = (reg << XGMAC_ADDR_SHIFT);
1385
+ ctrl |= gcl ? 0 : XGMAC_GCRR;
1386
+
1387
+ writel(ctrl, ioaddr + XGMAC_MTL_EST_GCL_CONTROL);
1388
+
1389
+ ctrl |= XGMAC_SRWO;
1390
+ writel(ctrl, ioaddr + XGMAC_MTL_EST_GCL_CONTROL);
1391
+
1392
+ return readl_poll_timeout_atomic(ioaddr + XGMAC_MTL_EST_GCL_CONTROL,
1393
+ ctrl, !(ctrl & XGMAC_SRWO), 100, 5000);
1394
+}
1395
+
1396
+static int dwxgmac3_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
1397
+ unsigned int ptp_rate)
1398
+{
1399
+ int i, ret = 0x0;
1400
+ u32 ctrl;
1401
+
1402
+ ret |= dwxgmac3_est_write(ioaddr, XGMAC_BTR_LOW, cfg->btr[0], false);
1403
+ ret |= dwxgmac3_est_write(ioaddr, XGMAC_BTR_HIGH, cfg->btr[1], false);
1404
+ ret |= dwxgmac3_est_write(ioaddr, XGMAC_TER, cfg->ter, false);
1405
+ ret |= dwxgmac3_est_write(ioaddr, XGMAC_LLR, cfg->gcl_size, false);
1406
+ ret |= dwxgmac3_est_write(ioaddr, XGMAC_CTR_LOW, cfg->ctr[0], false);
1407
+ ret |= dwxgmac3_est_write(ioaddr, XGMAC_CTR_HIGH, cfg->ctr[1], false);
1408
+ if (ret)
1409
+ return ret;
1410
+
1411
+ for (i = 0; i < cfg->gcl_size; i++) {
1412
+ ret = dwxgmac3_est_write(ioaddr, i, cfg->gcl[i], true);
1413
+ if (ret)
1414
+ return ret;
1415
+ }
1416
+
1417
+ ctrl = readl(ioaddr + XGMAC_MTL_EST_CONTROL);
1418
+ ctrl &= ~XGMAC_PTOV;
1419
+ ctrl |= ((1000000000 / ptp_rate) * 9) << XGMAC_PTOV_SHIFT;
1420
+ if (cfg->enable)
1421
+ ctrl |= XGMAC_EEST | XGMAC_SSWL;
1422
+ else
1423
+ ctrl &= ~XGMAC_EEST;
1424
+
1425
+ writel(ctrl, ioaddr + XGMAC_MTL_EST_CONTROL);
1426
+ return 0;
1427
+}
1428
+
1429
+static void dwxgmac3_fpe_configure(void __iomem *ioaddr, u32 num_txq,
1430
+ u32 num_rxq, bool enable)
1431
+{
1432
+ u32 value;
1433
+
1434
+ if (!enable) {
1435
+ value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
1436
+
1437
+ value &= ~XGMAC_EFPE;
1438
+
1439
+ writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
1440
+ return;
1441
+ }
1442
+
1443
+ value = readl(ioaddr + XGMAC_RXQ_CTRL1);
1444
+ value &= ~XGMAC_RQ;
1445
+ value |= (num_rxq - 1) << XGMAC_RQ_SHIFT;
1446
+ writel(value, ioaddr + XGMAC_RXQ_CTRL1);
1447
+
1448
+ value = readl(ioaddr + XGMAC_FPE_CTRL_STS);
1449
+ value |= XGMAC_EFPE;
1450
+ writel(value, ioaddr + XGMAC_FPE_CTRL_STS);
3091451 }
3101452
3111453 const struct stmmac_ops dwxgmac210_ops = {
....@@ -314,29 +1456,106 @@
3141456 .rx_ipc = dwxgmac2_rx_ipc,
3151457 .rx_queue_enable = dwxgmac2_rx_queue_enable,
3161458 .rx_queue_prio = dwxgmac2_rx_queue_prio,
317
- .tx_queue_prio = NULL,
1459
+ .tx_queue_prio = dwxgmac2_tx_queue_prio,
3181460 .rx_queue_routing = NULL,
3191461 .prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms,
3201462 .prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms,
321
- .set_mtl_tx_queue_weight = NULL,
1463
+ .set_mtl_tx_queue_weight = dwxgmac2_set_mtl_tx_queue_weight,
3221464 .map_mtl_to_dma = dwxgmac2_map_mtl_to_dma,
323
- .config_cbs = NULL,
324
- .dump_regs = NULL,
1465
+ .config_cbs = dwxgmac2_config_cbs,
1466
+ .dump_regs = dwxgmac2_dump_regs,
3251467 .host_irq_status = dwxgmac2_host_irq_status,
3261468 .host_mtl_irq_status = dwxgmac2_host_mtl_irq_status,
3271469 .flow_ctrl = dwxgmac2_flow_ctrl,
3281470 .pmt = dwxgmac2_pmt,
3291471 .set_umac_addr = dwxgmac2_set_umac_addr,
3301472 .get_umac_addr = dwxgmac2_get_umac_addr,
331
- .set_eee_mode = NULL,
332
- .reset_eee_mode = NULL,
333
- .set_eee_timer = NULL,
334
- .set_eee_pls = NULL,
1473
+ .set_eee_mode = dwxgmac2_set_eee_mode,
1474
+ .reset_eee_mode = dwxgmac2_reset_eee_mode,
1475
+ .set_eee_timer = dwxgmac2_set_eee_timer,
1476
+ .set_eee_pls = dwxgmac2_set_eee_pls,
3351477 .pcs_ctrl_ane = NULL,
3361478 .pcs_rane = NULL,
3371479 .pcs_get_adv_lp = NULL,
3381480 .debug = NULL,
3391481 .set_filter = dwxgmac2_set_filter,
1482
+ .safety_feat_config = dwxgmac3_safety_feat_config,
1483
+ .safety_feat_irq_status = dwxgmac3_safety_feat_irq_status,
1484
+ .safety_feat_dump = dwxgmac3_safety_feat_dump,
1485
+ .set_mac_loopback = dwxgmac2_set_mac_loopback,
1486
+ .rss_configure = dwxgmac2_rss_configure,
1487
+ .update_vlan_hash = dwxgmac2_update_vlan_hash,
1488
+ .rxp_config = dwxgmac3_rxp_config,
1489
+ .get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp,
1490
+ .flex_pps_config = dwxgmac2_flex_pps_config,
1491
+ .sarc_configure = dwxgmac2_sarc_configure,
1492
+ .enable_vlan = dwxgmac2_enable_vlan,
1493
+ .config_l3_filter = dwxgmac2_config_l3_filter,
1494
+ .config_l4_filter = dwxgmac2_config_l4_filter,
1495
+ .set_arp_offload = dwxgmac2_set_arp_offload,
1496
+ .est_configure = dwxgmac3_est_configure,
1497
+ .fpe_configure = dwxgmac3_fpe_configure,
1498
+};
1499
+
1500
+static void dwxlgmac2_rx_queue_enable(struct mac_device_info *hw, u8 mode,
1501
+ u32 queue)
1502
+{
1503
+ void __iomem *ioaddr = hw->pcsr;
1504
+ u32 value;
1505
+
1506
+ value = readl(ioaddr + XLGMAC_RXQ_ENABLE_CTRL0) & ~XGMAC_RXQEN(queue);
1507
+ if (mode == MTL_QUEUE_AVB)
1508
+ value |= 0x1 << XGMAC_RXQEN_SHIFT(queue);
1509
+ else if (mode == MTL_QUEUE_DCB)
1510
+ value |= 0x2 << XGMAC_RXQEN_SHIFT(queue);
1511
+ writel(value, ioaddr + XLGMAC_RXQ_ENABLE_CTRL0);
1512
+}
1513
+
1514
+const struct stmmac_ops dwxlgmac2_ops = {
1515
+ .core_init = dwxgmac2_core_init,
1516
+ .set_mac = dwxgmac2_set_mac,
1517
+ .rx_ipc = dwxgmac2_rx_ipc,
1518
+ .rx_queue_enable = dwxlgmac2_rx_queue_enable,
1519
+ .rx_queue_prio = dwxgmac2_rx_queue_prio,
1520
+ .tx_queue_prio = dwxgmac2_tx_queue_prio,
1521
+ .rx_queue_routing = NULL,
1522
+ .prog_mtl_rx_algorithms = dwxgmac2_prog_mtl_rx_algorithms,
1523
+ .prog_mtl_tx_algorithms = dwxgmac2_prog_mtl_tx_algorithms,
1524
+ .set_mtl_tx_queue_weight = dwxgmac2_set_mtl_tx_queue_weight,
1525
+ .map_mtl_to_dma = dwxgmac2_map_mtl_to_dma,
1526
+ .config_cbs = dwxgmac2_config_cbs,
1527
+ .dump_regs = dwxgmac2_dump_regs,
1528
+ .host_irq_status = dwxgmac2_host_irq_status,
1529
+ .host_mtl_irq_status = dwxgmac2_host_mtl_irq_status,
1530
+ .flow_ctrl = dwxgmac2_flow_ctrl,
1531
+ .pmt = dwxgmac2_pmt,
1532
+ .set_umac_addr = dwxgmac2_set_umac_addr,
1533
+ .get_umac_addr = dwxgmac2_get_umac_addr,
1534
+ .set_eee_mode = dwxgmac2_set_eee_mode,
1535
+ .reset_eee_mode = dwxgmac2_reset_eee_mode,
1536
+ .set_eee_timer = dwxgmac2_set_eee_timer,
1537
+ .set_eee_pls = dwxgmac2_set_eee_pls,
1538
+ .pcs_ctrl_ane = NULL,
1539
+ .pcs_rane = NULL,
1540
+ .pcs_get_adv_lp = NULL,
1541
+ .debug = NULL,
1542
+ .set_filter = dwxgmac2_set_filter,
1543
+ .safety_feat_config = dwxgmac3_safety_feat_config,
1544
+ .safety_feat_irq_status = dwxgmac3_safety_feat_irq_status,
1545
+ .safety_feat_dump = dwxgmac3_safety_feat_dump,
1546
+ .set_mac_loopback = dwxgmac2_set_mac_loopback,
1547
+ .rss_configure = dwxgmac2_rss_configure,
1548
+ .update_vlan_hash = dwxgmac2_update_vlan_hash,
1549
+ .rxp_config = dwxgmac3_rxp_config,
1550
+ .get_mac_tx_timestamp = dwxgmac2_get_mac_tx_timestamp,
1551
+ .flex_pps_config = dwxgmac2_flex_pps_config,
1552
+ .sarc_configure = dwxgmac2_sarc_configure,
1553
+ .enable_vlan = dwxgmac2_enable_vlan,
1554
+ .config_l3_filter = dwxgmac2_config_l3_filter,
1555
+ .config_l4_filter = dwxgmac2_config_l4_filter,
1556
+ .set_arp_offload = dwxgmac2_set_arp_offload,
1557
+ .est_configure = dwxgmac3_est_configure,
1558
+ .fpe_configure = dwxgmac3_fpe_configure,
3401559 };
3411560
3421561 int dwxgmac2_setup(struct stmmac_priv *priv)
....@@ -355,11 +1574,13 @@
3551574 mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
3561575
3571576 mac->link.duplex = 0;
358
- mac->link.speed10 = 0;
359
- mac->link.speed100 = 0;
360
- mac->link.speed1000 = XGMAC_CONFIG_SS_1000;
361
- mac->link.speed2500 = XGMAC_CONFIG_SS_2500;
362
- mac->link.speed10000 = XGMAC_CONFIG_SS_10000;
1577
+ mac->link.speed10 = XGMAC_CONFIG_SS_10_MII;
1578
+ mac->link.speed100 = XGMAC_CONFIG_SS_100_MII;
1579
+ mac->link.speed1000 = XGMAC_CONFIG_SS_1000_GMII;
1580
+ mac->link.speed2500 = XGMAC_CONFIG_SS_2500_GMII;
1581
+ mac->link.xgmii.speed2500 = XGMAC_CONFIG_SS_2500;
1582
+ mac->link.xgmii.speed5000 = XGMAC_CONFIG_SS_5000;
1583
+ mac->link.xgmii.speed10000 = XGMAC_CONFIG_SS_10000;
3631584 mac->link.speed_mask = XGMAC_CONFIG_SS_MASK;
3641585
3651586 mac->mii.addr = XGMAC_MDIO_ADDR;
....@@ -373,3 +1594,40 @@
3731594
3741595 return 0;
3751596 }
1597
+
1598
+int dwxlgmac2_setup(struct stmmac_priv *priv)
1599
+{
1600
+ struct mac_device_info *mac = priv->hw;
1601
+
1602
+ dev_info(priv->device, "\tXLGMAC\n");
1603
+
1604
+ priv->dev->priv_flags |= IFF_UNICAST_FLT;
1605
+ mac->pcsr = priv->ioaddr;
1606
+ mac->multicast_filter_bins = priv->plat->multicast_filter_bins;
1607
+ mac->unicast_filter_entries = priv->plat->unicast_filter_entries;
1608
+ mac->mcast_bits_log2 = 0;
1609
+
1610
+ if (mac->multicast_filter_bins)
1611
+ mac->mcast_bits_log2 = ilog2(mac->multicast_filter_bins);
1612
+
1613
+ mac->link.duplex = 0;
1614
+ mac->link.speed1000 = XLGMAC_CONFIG_SS_1000;
1615
+ mac->link.speed2500 = XLGMAC_CONFIG_SS_2500;
1616
+ mac->link.xgmii.speed10000 = XLGMAC_CONFIG_SS_10G;
1617
+ mac->link.xlgmii.speed25000 = XLGMAC_CONFIG_SS_25G;
1618
+ mac->link.xlgmii.speed40000 = XLGMAC_CONFIG_SS_40G;
1619
+ mac->link.xlgmii.speed50000 = XLGMAC_CONFIG_SS_50G;
1620
+ mac->link.xlgmii.speed100000 = XLGMAC_CONFIG_SS_100G;
1621
+ mac->link.speed_mask = XLGMAC_CONFIG_SS;
1622
+
1623
+ mac->mii.addr = XGMAC_MDIO_ADDR;
1624
+ mac->mii.data = XGMAC_MDIO_DATA;
1625
+ mac->mii.addr_shift = 16;
1626
+ mac->mii.addr_mask = GENMASK(20, 16);
1627
+ mac->mii.reg_shift = 0;
1628
+ mac->mii.reg_mask = GENMASK(15, 0);
1629
+ mac->mii.clk_csr_shift = 19;
1630
+ mac->mii.clk_csr_mask = GENMASK(21, 19);
1631
+
1632
+ return 0;
1633
+}