0001
0002
0003
0004
0005 #include <linux/bitops.h>
0006 #include <linux/iopoll.h>
0007 #include "common.h"
0008 #include "dwmac4.h"
0009 #include "dwmac5.h"
0010 #include "stmmac.h"
0011 #include "stmmac_ptp.h"
0012
0013 struct dwmac5_error_desc {
0014 bool valid;
0015 const char *desc;
0016 const char *detailed_desc;
0017 };
0018
0019 #define STAT_OFF(field) offsetof(struct stmmac_safety_stats, field)
0020
0021 static void dwmac5_log_error(struct net_device *ndev, u32 value, bool corr,
0022 const char *module_name, const struct dwmac5_error_desc *desc,
0023 unsigned long field_offset, struct stmmac_safety_stats *stats)
0024 {
0025 unsigned long loc, mask;
0026 u8 *bptr = (u8 *)stats;
0027 unsigned long *ptr;
0028
0029 ptr = (unsigned long *)(bptr + field_offset);
0030
0031 mask = value;
0032 for_each_set_bit(loc, &mask, 32) {
0033 netdev_err(ndev, "Found %s error in %s: '%s: %s'\n", corr ?
0034 "correctable" : "uncorrectable", module_name,
0035 desc[loc].desc, desc[loc].detailed_desc);
0036
0037
0038 ptr[loc]++;
0039 }
0040 }
0041
0042 static const struct dwmac5_error_desc dwmac5_mac_errors[32]= {
0043 { true, "ATPES", "Application Transmit Interface Parity Check Error" },
0044 { true, "TPES", "TSO Data Path Parity Check Error" },
0045 { true, "RDPES", "Read Descriptor Parity Check Error" },
0046 { true, "MPES", "MTL Data Path Parity Check Error" },
0047 { true, "MTSPES", "MTL TX Status Data Path Parity Check Error" },
0048 { true, "ARPES", "Application Receive Interface Data Path Parity Check Error" },
0049 { true, "CWPES", "CSR Write Data Path Parity Check Error" },
0050 { true, "ASRPES", "AXI Slave Read Data Path Parity Check Error" },
0051 { true, "TTES", "TX FSM Timeout Error" },
0052 { true, "RTES", "RX FSM Timeout Error" },
0053 { true, "CTES", "CSR FSM Timeout Error" },
0054 { true, "ATES", "APP FSM Timeout Error" },
0055 { true, "PTES", "PTP FSM Timeout Error" },
0056 { true, "T125ES", "TX125 FSM Timeout Error" },
0057 { true, "R125ES", "RX125 FSM Timeout Error" },
0058 { true, "RVCTES", "REV MDC FSM Timeout Error" },
0059 { true, "MSTTES", "Master Read/Write Timeout Error" },
0060 { true, "SLVTES", "Slave Read/Write Timeout Error" },
0061 { true, "ATITES", "Application Timeout on ATI Interface Error" },
0062 { true, "ARITES", "Application Timeout on ARI Interface Error" },
0063 { false, "UNKNOWN", "Unknown Error" },
0064 { false, "UNKNOWN", "Unknown Error" },
0065 { false, "UNKNOWN", "Unknown Error" },
0066 { false, "UNKNOWN", "Unknown Error" },
0067 { true, "FSMPES", "FSM State Parity Error" },
0068 { false, "UNKNOWN", "Unknown Error" },
0069 { false, "UNKNOWN", "Unknown Error" },
0070 { false, "UNKNOWN", "Unknown Error" },
0071 { false, "UNKNOWN", "Unknown Error" },
0072 { false, "UNKNOWN", "Unknown Error" },
0073 { false, "UNKNOWN", "Unknown Error" },
0074 { false, "UNKNOWN", "Unknown Error" },
0075 };
0076
0077 static void dwmac5_handle_mac_err(struct net_device *ndev,
0078 void __iomem *ioaddr, bool correctable,
0079 struct stmmac_safety_stats *stats)
0080 {
0081 u32 value;
0082
0083 value = readl(ioaddr + MAC_DPP_FSM_INT_STATUS);
0084 writel(value, ioaddr + MAC_DPP_FSM_INT_STATUS);
0085
0086 dwmac5_log_error(ndev, value, correctable, "MAC", dwmac5_mac_errors,
0087 STAT_OFF(mac_errors), stats);
0088 }
0089
0090 static const struct dwmac5_error_desc dwmac5_mtl_errors[32]= {
0091 { true, "TXCES", "MTL TX Memory Error" },
0092 { true, "TXAMS", "MTL TX Memory Address Mismatch Error" },
0093 { true, "TXUES", "MTL TX Memory Error" },
0094 { false, "UNKNOWN", "Unknown Error" },
0095 { true, "RXCES", "MTL RX Memory Error" },
0096 { true, "RXAMS", "MTL RX Memory Address Mismatch Error" },
0097 { true, "RXUES", "MTL RX Memory Error" },
0098 { false, "UNKNOWN", "Unknown Error" },
0099 { true, "ECES", "MTL EST Memory Error" },
0100 { true, "EAMS", "MTL EST Memory Address Mismatch Error" },
0101 { true, "EUES", "MTL EST Memory Error" },
0102 { false, "UNKNOWN", "Unknown Error" },
0103 { true, "RPCES", "MTL RX Parser Memory Error" },
0104 { true, "RPAMS", "MTL RX Parser Memory Address Mismatch Error" },
0105 { true, "RPUES", "MTL RX Parser Memory Error" },
0106 { false, "UNKNOWN", "Unknown Error" },
0107 { false, "UNKNOWN", "Unknown Error" },
0108 { false, "UNKNOWN", "Unknown Error" },
0109 { false, "UNKNOWN", "Unknown Error" },
0110 { false, "UNKNOWN", "Unknown Error" },
0111 { false, "UNKNOWN", "Unknown Error" },
0112 { false, "UNKNOWN", "Unknown Error" },
0113 { false, "UNKNOWN", "Unknown Error" },
0114 { false, "UNKNOWN", "Unknown Error" },
0115 { false, "UNKNOWN", "Unknown Error" },
0116 { false, "UNKNOWN", "Unknown Error" },
0117 { false, "UNKNOWN", "Unknown Error" },
0118 { false, "UNKNOWN", "Unknown Error" },
0119 { false, "UNKNOWN", "Unknown Error" },
0120 { false, "UNKNOWN", "Unknown Error" },
0121 { false, "UNKNOWN", "Unknown Error" },
0122 { false, "UNKNOWN", "Unknown Error" },
0123 };
0124
0125 static void dwmac5_handle_mtl_err(struct net_device *ndev,
0126 void __iomem *ioaddr, bool correctable,
0127 struct stmmac_safety_stats *stats)
0128 {
0129 u32 value;
0130
0131 value = readl(ioaddr + MTL_ECC_INT_STATUS);
0132 writel(value, ioaddr + MTL_ECC_INT_STATUS);
0133
0134 dwmac5_log_error(ndev, value, correctable, "MTL", dwmac5_mtl_errors,
0135 STAT_OFF(mtl_errors), stats);
0136 }
0137
0138 static const struct dwmac5_error_desc dwmac5_dma_errors[32]= {
0139 { true, "TCES", "DMA TSO Memory Error" },
0140 { true, "TAMS", "DMA TSO Memory Address Mismatch Error" },
0141 { true, "TUES", "DMA TSO Memory Error" },
0142 { false, "UNKNOWN", "Unknown Error" },
0143 { false, "UNKNOWN", "Unknown Error" },
0144 { false, "UNKNOWN", "Unknown Error" },
0145 { false, "UNKNOWN", "Unknown Error" },
0146 { false, "UNKNOWN", "Unknown Error" },
0147 { false, "UNKNOWN", "Unknown Error" },
0148 { false, "UNKNOWN", "Unknown Error" },
0149 { false, "UNKNOWN", "Unknown Error" },
0150 { false, "UNKNOWN", "Unknown Error" },
0151 { false, "UNKNOWN", "Unknown Error" },
0152 { false, "UNKNOWN", "Unknown Error" },
0153 { false, "UNKNOWN", "Unknown Error" },
0154 { false, "UNKNOWN", "Unknown Error" },
0155 { false, "UNKNOWN", "Unknown Error" },
0156 { false, "UNKNOWN", "Unknown Error" },
0157 { false, "UNKNOWN", "Unknown Error" },
0158 { false, "UNKNOWN", "Unknown Error" },
0159 { false, "UNKNOWN", "Unknown Error" },
0160 { false, "UNKNOWN", "Unknown Error" },
0161 { false, "UNKNOWN", "Unknown Error" },
0162 { false, "UNKNOWN", "Unknown Error" },
0163 { false, "UNKNOWN", "Unknown Error" },
0164 { false, "UNKNOWN", "Unknown Error" },
0165 { false, "UNKNOWN", "Unknown Error" },
0166 { false, "UNKNOWN", "Unknown Error" },
0167 { false, "UNKNOWN", "Unknown Error" },
0168 { false, "UNKNOWN", "Unknown Error" },
0169 { false, "UNKNOWN", "Unknown Error" },
0170 { false, "UNKNOWN", "Unknown Error" },
0171 };
0172
0173 static void dwmac5_handle_dma_err(struct net_device *ndev,
0174 void __iomem *ioaddr, bool correctable,
0175 struct stmmac_safety_stats *stats)
0176 {
0177 u32 value;
0178
0179 value = readl(ioaddr + DMA_ECC_INT_STATUS);
0180 writel(value, ioaddr + DMA_ECC_INT_STATUS);
0181
0182 dwmac5_log_error(ndev, value, correctable, "DMA", dwmac5_dma_errors,
0183 STAT_OFF(dma_errors), stats);
0184 }
0185
0186 int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp,
0187 struct stmmac_safety_feature_cfg *safety_feat_cfg)
0188 {
0189 u32 value;
0190
0191 if (!asp)
0192 return -EINVAL;
0193
0194
0195 value = readl(ioaddr + MTL_ECC_CONTROL);
0196 value |= MEEAO;
0197 if (safety_feat_cfg->tsoee)
0198 value |= TSOEE;
0199 if (safety_feat_cfg->mrxpee)
0200 value |= MRXPEE;
0201 if (safety_feat_cfg->mestee)
0202 value |= MESTEE;
0203 if (safety_feat_cfg->mrxee)
0204 value |= MRXEE;
0205 if (safety_feat_cfg->mtxee)
0206 value |= MTXEE;
0207 writel(value, ioaddr + MTL_ECC_CONTROL);
0208
0209
0210 value = readl(ioaddr + MTL_ECC_INT_ENABLE);
0211 value |= RPCEIE;
0212 value |= ECEIE;
0213 value |= RXCEIE;
0214 value |= TXCEIE;
0215 writel(value, ioaddr + MTL_ECC_INT_ENABLE);
0216
0217
0218 value = readl(ioaddr + DMA_ECC_INT_ENABLE);
0219 value |= TCEIE;
0220 writel(value, ioaddr + DMA_ECC_INT_ENABLE);
0221
0222
0223 if (asp <= 0x1)
0224 return 0;
0225
0226
0227 value = readl(ioaddr + MAC_FSM_CONTROL);
0228 if (safety_feat_cfg->prtyen)
0229 value |= PRTYEN;
0230 if (safety_feat_cfg->tmouten)
0231 value |= TMOUTEN;
0232 writel(value, ioaddr + MAC_FSM_CONTROL);
0233
0234
0235 value = readl(ioaddr + MTL_DPP_CONTROL);
0236 if (safety_feat_cfg->edpp)
0237 value |= EDPP;
0238 writel(value, ioaddr + MTL_DPP_CONTROL);
0239
0240
0241
0242
0243
0244 if (asp <= 0x2)
0245 return 0;
0246
0247 if (safety_feat_cfg->epsi)
0248 value |= EPSI;
0249 writel(value, ioaddr + MTL_DPP_CONTROL);
0250 return 0;
0251 }
0252
0253 int dwmac5_safety_feat_irq_status(struct net_device *ndev,
0254 void __iomem *ioaddr, unsigned int asp,
0255 struct stmmac_safety_stats *stats)
0256 {
0257 bool err, corr;
0258 u32 mtl, dma;
0259 int ret = 0;
0260
0261 if (!asp)
0262 return -EINVAL;
0263
0264 mtl = readl(ioaddr + MTL_SAFETY_INT_STATUS);
0265 dma = readl(ioaddr + DMA_SAFETY_INT_STATUS);
0266
0267 err = (mtl & MCSIS) || (dma & MCSIS);
0268 corr = false;
0269 if (err) {
0270 dwmac5_handle_mac_err(ndev, ioaddr, corr, stats);
0271 ret |= !corr;
0272 }
0273
0274 err = (mtl & (MEUIS | MECIS)) || (dma & (MSUIS | MSCIS));
0275 corr = (mtl & MECIS) || (dma & MSCIS);
0276 if (err) {
0277 dwmac5_handle_mtl_err(ndev, ioaddr, corr, stats);
0278 ret |= !corr;
0279 }
0280
0281 err = dma & (DEUIS | DECIS);
0282 corr = dma & DECIS;
0283 if (err) {
0284 dwmac5_handle_dma_err(ndev, ioaddr, corr, stats);
0285 ret |= !corr;
0286 }
0287
0288 return ret;
0289 }
0290
0291 static const struct dwmac5_error {
0292 const struct dwmac5_error_desc *desc;
0293 } dwmac5_all_errors[] = {
0294 { dwmac5_mac_errors },
0295 { dwmac5_mtl_errors },
0296 { dwmac5_dma_errors },
0297 };
0298
0299 int dwmac5_safety_feat_dump(struct stmmac_safety_stats *stats,
0300 int index, unsigned long *count, const char **desc)
0301 {
0302 int module = index / 32, offset = index % 32;
0303 unsigned long *ptr = (unsigned long *)stats;
0304
0305 if (module >= ARRAY_SIZE(dwmac5_all_errors))
0306 return -EINVAL;
0307 if (!dwmac5_all_errors[module].desc[offset].valid)
0308 return -EINVAL;
0309 if (count)
0310 *count = *(ptr + index);
0311 if (desc)
0312 *desc = dwmac5_all_errors[module].desc[offset].desc;
0313 return 0;
0314 }
0315
0316 static int dwmac5_rxp_disable(void __iomem *ioaddr)
0317 {
0318 u32 val;
0319
0320 val = readl(ioaddr + MTL_OPERATION_MODE);
0321 val &= ~MTL_FRPE;
0322 writel(val, ioaddr + MTL_OPERATION_MODE);
0323
0324 return readl_poll_timeout(ioaddr + MTL_RXP_CONTROL_STATUS, val,
0325 val & RXPI, 1, 10000);
0326 }
0327
0328 static void dwmac5_rxp_enable(void __iomem *ioaddr)
0329 {
0330 u32 val;
0331
0332 val = readl(ioaddr + MTL_OPERATION_MODE);
0333 val |= MTL_FRPE;
0334 writel(val, ioaddr + MTL_OPERATION_MODE);
0335 }
0336
0337 static int dwmac5_rxp_update_single_entry(void __iomem *ioaddr,
0338 struct stmmac_tc_entry *entry,
0339 int pos)
0340 {
0341 int ret, i;
0342
0343 for (i = 0; i < (sizeof(entry->val) / sizeof(u32)); i++) {
0344 int real_pos = pos * (sizeof(entry->val) / sizeof(u32)) + i;
0345 u32 val;
0346
0347
0348 ret = readl_poll_timeout(ioaddr + MTL_RXP_IACC_CTRL_STATUS,
0349 val, !(val & STARTBUSY), 1, 10000);
0350 if (ret)
0351 return ret;
0352
0353
0354 val = *((u32 *)&entry->val + i);
0355 writel(val, ioaddr + MTL_RXP_IACC_DATA);
0356
0357
0358 val = real_pos & ADDR;
0359 writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
0360
0361
0362 val |= WRRDN;
0363 writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
0364
0365
0366 val |= STARTBUSY;
0367 writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
0368
0369
0370 ret = readl_poll_timeout(ioaddr + MTL_RXP_IACC_CTRL_STATUS,
0371 val, !(val & STARTBUSY), 1, 10000);
0372 if (ret)
0373 return ret;
0374 }
0375
0376 return 0;
0377 }
0378
0379 static struct stmmac_tc_entry *
0380 dwmac5_rxp_get_next_entry(struct stmmac_tc_entry *entries, unsigned int count,
0381 u32 curr_prio)
0382 {
0383 struct stmmac_tc_entry *entry;
0384 u32 min_prio = ~0x0;
0385 int i, min_prio_idx;
0386 bool found = false;
0387
0388 for (i = count - 1; i >= 0; i--) {
0389 entry = &entries[i];
0390
0391
0392 if (!entry->in_use)
0393 continue;
0394
0395 if (entry->in_hw)
0396 continue;
0397
0398 if (entry->is_last)
0399 continue;
0400
0401 if (entry->is_frag)
0402 continue;
0403
0404 if (entry->prio < curr_prio)
0405 continue;
0406
0407 if (entry->prio < min_prio) {
0408 min_prio = entry->prio;
0409 min_prio_idx = i;
0410 found = true;
0411 }
0412 }
0413
0414 if (found)
0415 return &entries[min_prio_idx];
0416 return NULL;
0417 }
0418
0419 int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
0420 unsigned int count)
0421 {
0422 struct stmmac_tc_entry *entry, *frag;
0423 int i, ret, nve = 0;
0424 u32 curr_prio = 0;
0425 u32 old_val, val;
0426
0427
0428 old_val = readl(ioaddr + GMAC_CONFIG);
0429 val = old_val & ~GMAC_CONFIG_RE;
0430 writel(val, ioaddr + GMAC_CONFIG);
0431
0432
0433 ret = dwmac5_rxp_disable(ioaddr);
0434 if (ret)
0435 goto re_enable;
0436
0437
0438 for (i = 0; i < count; i++) {
0439 entry = &entries[i];
0440 entry->in_hw = false;
0441 }
0442
0443
0444 while (1) {
0445 entry = dwmac5_rxp_get_next_entry(entries, count, curr_prio);
0446 if (!entry)
0447 break;
0448
0449 curr_prio = entry->prio;
0450 frag = entry->frag_ptr;
0451
0452
0453 if (frag) {
0454 entry->val.af = 0;
0455 entry->val.rf = 0;
0456 entry->val.nc = 1;
0457 entry->val.ok_index = nve + 2;
0458 }
0459
0460 ret = dwmac5_rxp_update_single_entry(ioaddr, entry, nve);
0461 if (ret)
0462 goto re_enable;
0463
0464 entry->table_pos = nve++;
0465 entry->in_hw = true;
0466
0467 if (frag && !frag->in_hw) {
0468 ret = dwmac5_rxp_update_single_entry(ioaddr, frag, nve);
0469 if (ret)
0470 goto re_enable;
0471 frag->table_pos = nve++;
0472 frag->in_hw = true;
0473 }
0474 }
0475
0476 if (!nve)
0477 goto re_enable;
0478
0479
0480 for (i = 0; i < count; i++) {
0481 entry = &entries[i];
0482 if (!entry->is_last)
0483 continue;
0484
0485 ret = dwmac5_rxp_update_single_entry(ioaddr, entry, nve);
0486 if (ret)
0487 goto re_enable;
0488
0489 entry->table_pos = nve++;
0490 }
0491
0492
0493 val = (nve << 16) & NPE;
0494 val |= nve & NVE;
0495 writel(val, ioaddr + MTL_RXP_CONTROL_STATUS);
0496
0497
0498 dwmac5_rxp_enable(ioaddr);
0499
0500 re_enable:
0501
0502 writel(old_val, ioaddr + GMAC_CONFIG);
0503 return ret;
0504 }
0505
0506 int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
0507 struct stmmac_pps_cfg *cfg, bool enable,
0508 u32 sub_second_inc, u32 systime_flags)
0509 {
0510 u32 tnsec = readl(ioaddr + MAC_PPSx_TARGET_TIME_NSEC(index));
0511 u32 val = readl(ioaddr + MAC_PPS_CONTROL);
0512 u64 period;
0513
0514 if (!cfg->available)
0515 return -EINVAL;
0516 if (tnsec & TRGTBUSY0)
0517 return -EBUSY;
0518 if (!sub_second_inc || !systime_flags)
0519 return -EINVAL;
0520
0521 val &= ~PPSx_MASK(index);
0522
0523 if (!enable) {
0524 val |= PPSCMDx(index, 0x5);
0525 val |= PPSEN0;
0526 writel(val, ioaddr + MAC_PPS_CONTROL);
0527 return 0;
0528 }
0529
0530 val |= PPSCMDx(index, 0x2);
0531 val |= TRGTMODSELx(index, 0x2);
0532 val |= PPSEN0;
0533
0534 writel(cfg->start.tv_sec, ioaddr + MAC_PPSx_TARGET_TIME_SEC(index));
0535
0536 if (!(systime_flags & PTP_TCR_TSCTRLSSR))
0537 cfg->start.tv_nsec = (cfg->start.tv_nsec * 1000) / 465;
0538 writel(cfg->start.tv_nsec, ioaddr + MAC_PPSx_TARGET_TIME_NSEC(index));
0539
0540 period = cfg->period.tv_sec * 1000000000;
0541 period += cfg->period.tv_nsec;
0542
0543 do_div(period, sub_second_inc);
0544
0545 if (period <= 1)
0546 return -EINVAL;
0547
0548 writel(period - 1, ioaddr + MAC_PPSx_INTERVAL(index));
0549
0550 period >>= 1;
0551 if (period <= 1)
0552 return -EINVAL;
0553
0554 writel(period - 1, ioaddr + MAC_PPSx_WIDTH(index));
0555
0556
0557 writel(val, ioaddr + MAC_PPS_CONTROL);
0558 return 0;
0559 }
0560
0561 static int dwmac5_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcl)
0562 {
0563 u32 ctrl;
0564
0565 writel(val, ioaddr + MTL_EST_GCL_DATA);
0566
0567 ctrl = (reg << ADDR_SHIFT);
0568 ctrl |= gcl ? 0 : GCRR;
0569
0570 writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
0571
0572 ctrl |= SRWO;
0573 writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
0574
0575 return readl_poll_timeout(ioaddr + MTL_EST_GCL_CONTROL,
0576 ctrl, !(ctrl & SRWO), 100, 5000);
0577 }
0578
0579 int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
0580 unsigned int ptp_rate)
0581 {
0582 int i, ret = 0x0;
0583 u32 ctrl;
0584
0585 ret |= dwmac5_est_write(ioaddr, BTR_LOW, cfg->btr[0], false);
0586 ret |= dwmac5_est_write(ioaddr, BTR_HIGH, cfg->btr[1], false);
0587 ret |= dwmac5_est_write(ioaddr, TER, cfg->ter, false);
0588 ret |= dwmac5_est_write(ioaddr, LLR, cfg->gcl_size, false);
0589 ret |= dwmac5_est_write(ioaddr, CTR_LOW, cfg->ctr[0], false);
0590 ret |= dwmac5_est_write(ioaddr, CTR_HIGH, cfg->ctr[1], false);
0591 if (ret)
0592 return ret;
0593
0594 for (i = 0; i < cfg->gcl_size; i++) {
0595 ret = dwmac5_est_write(ioaddr, i, cfg->gcl[i], true);
0596 if (ret)
0597 return ret;
0598 }
0599
0600 ctrl = readl(ioaddr + MTL_EST_CONTROL);
0601 ctrl &= ~PTOV;
0602 ctrl |= ((1000000000 / ptp_rate) * 6) << PTOV_SHIFT;
0603 if (cfg->enable)
0604 ctrl |= EEST | SSWL;
0605 else
0606 ctrl &= ~EEST;
0607
0608 writel(ctrl, ioaddr + MTL_EST_CONTROL);
0609
0610
0611 if (cfg->enable)
0612 ctrl = (IECGCE | IEHS | IEHF | IEBE | IECC);
0613 else
0614 ctrl = 0;
0615
0616 writel(ctrl, ioaddr + MTL_EST_INT_EN);
0617
0618 return 0;
0619 }
0620
0621 void dwmac5_est_irq_status(void __iomem *ioaddr, struct net_device *dev,
0622 struct stmmac_extra_stats *x, u32 txqcnt)
0623 {
0624 u32 status, value, feqn, hbfq, hbfs, btrl;
0625 u32 txqcnt_mask = (1 << txqcnt) - 1;
0626
0627 status = readl(ioaddr + MTL_EST_STATUS);
0628
0629 value = (CGCE | HLBS | HLBF | BTRE | SWLC);
0630
0631
0632 if (!(status & value))
0633 return;
0634
0635 if (status & CGCE) {
0636
0637 writel(CGCE, ioaddr + MTL_EST_STATUS);
0638
0639 x->mtl_est_cgce++;
0640 }
0641
0642 if (status & HLBS) {
0643 value = readl(ioaddr + MTL_EST_SCH_ERR);
0644 value &= txqcnt_mask;
0645
0646 x->mtl_est_hlbs++;
0647
0648
0649 writel(value, ioaddr + MTL_EST_SCH_ERR);
0650
0651
0652
0653
0654
0655 if (net_ratelimit())
0656 netdev_err(dev, "EST: HLB(sched) Queue 0x%x\n", value);
0657 }
0658
0659 if (status & HLBF) {
0660 value = readl(ioaddr + MTL_EST_FRM_SZ_ERR);
0661 feqn = value & txqcnt_mask;
0662
0663 value = readl(ioaddr + MTL_EST_FRM_SZ_CAP);
0664 hbfq = (value & SZ_CAP_HBFQ_MASK(txqcnt)) >> SZ_CAP_HBFQ_SHIFT;
0665 hbfs = value & SZ_CAP_HBFS_MASK;
0666
0667 x->mtl_est_hlbf++;
0668
0669
0670 writel(feqn, ioaddr + MTL_EST_FRM_SZ_ERR);
0671
0672 if (net_ratelimit())
0673 netdev_err(dev, "EST: HLB(size) Queue %u Size %u\n",
0674 hbfq, hbfs);
0675 }
0676
0677 if (status & BTRE) {
0678 if ((status & BTRL) == BTRL_MAX)
0679 x->mtl_est_btrlm++;
0680 else
0681 x->mtl_est_btre++;
0682
0683 btrl = (status & BTRL) >> BTRL_SHIFT;
0684
0685 if (net_ratelimit())
0686 netdev_info(dev, "EST: BTR Error Loop Count %u\n",
0687 btrl);
0688
0689 writel(BTRE, ioaddr + MTL_EST_STATUS);
0690 }
0691
0692 if (status & SWLC) {
0693 writel(SWLC, ioaddr + MTL_EST_STATUS);
0694 netdev_info(dev, "EST: SWOL has been switched\n");
0695 }
0696 }
0697
0698 void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
0699 bool enable)
0700 {
0701 u32 value;
0702
0703 if (!enable) {
0704 value = readl(ioaddr + MAC_FPE_CTRL_STS);
0705
0706 value &= ~EFPE;
0707
0708 writel(value, ioaddr + MAC_FPE_CTRL_STS);
0709 return;
0710 }
0711
0712 value = readl(ioaddr + GMAC_RXQ_CTRL1);
0713 value &= ~GMAC_RXQCTRL_FPRQ;
0714 value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
0715 writel(value, ioaddr + GMAC_RXQ_CTRL1);
0716
0717 value = readl(ioaddr + MAC_FPE_CTRL_STS);
0718 value |= EFPE;
0719 writel(value, ioaddr + MAC_FPE_CTRL_STS);
0720 }
0721
0722 int dwmac5_fpe_irq_status(void __iomem *ioaddr, struct net_device *dev)
0723 {
0724 u32 value;
0725 int status;
0726
0727 status = FPE_EVENT_UNKNOWN;
0728
0729 value = readl(ioaddr + MAC_FPE_CTRL_STS);
0730
0731 if (value & TRSP) {
0732 status |= FPE_EVENT_TRSP;
0733 netdev_info(dev, "FPE: Respond mPacket is transmitted\n");
0734 }
0735
0736 if (value & TVER) {
0737 status |= FPE_EVENT_TVER;
0738 netdev_info(dev, "FPE: Verify mPacket is transmitted\n");
0739 }
0740
0741 if (value & RRSP) {
0742 status |= FPE_EVENT_RRSP;
0743 netdev_info(dev, "FPE: Respond mPacket is received\n");
0744 }
0745
0746 if (value & RVER) {
0747 status |= FPE_EVENT_RVER;
0748 netdev_info(dev, "FPE: Verify mPacket is received\n");
0749 }
0750
0751 return status;
0752 }
0753
0754 void dwmac5_fpe_send_mpacket(void __iomem *ioaddr, enum stmmac_mpacket_type type)
0755 {
0756 u32 value;
0757
0758 value = readl(ioaddr + MAC_FPE_CTRL_STS);
0759
0760 if (type == MPACKET_VERIFY) {
0761 value &= ~SRSP;
0762 value |= SVER;
0763 } else {
0764 value &= ~SVER;
0765 value |= SRSP;
0766 }
0767
0768 writel(value, ioaddr + MAC_FPE_CTRL_STS);
0769 }