LCOV - code coverage report
Current view: top level - drivers/net/ethernet/stmicro/stmmac - dwmac5.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 299 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 12 0.0 %
Branches: 0 132 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: (GPL-2.0 OR MIT)
       2                 :            : // Copyright (c) 2017 Synopsys, Inc. and/or its affiliates.
       3                 :            : // stmmac Support for 5.xx Ethernet QoS cores
       4                 :            : 
       5                 :            : #include <linux/bitops.h>
       6                 :            : #include <linux/iopoll.h>
       7                 :            : #include "common.h"
       8                 :            : #include "dwmac4.h"
       9                 :            : #include "dwmac5.h"
      10                 :            : #include "stmmac.h"
      11                 :            : #include "stmmac_ptp.h"
      12                 :            : 
      13                 :            : struct dwmac5_error_desc {
      14                 :            :         bool valid;
      15                 :            :         const char *desc;
      16                 :            :         const char *detailed_desc;
      17                 :            : };
      18                 :            : 
      19                 :            : #define STAT_OFF(field)         offsetof(struct stmmac_safety_stats, field)
      20                 :            : 
      21                 :          0 : static void dwmac5_log_error(struct net_device *ndev, u32 value, bool corr,
      22                 :            :                 const char *module_name, const struct dwmac5_error_desc *desc,
      23                 :            :                 unsigned long field_offset, struct stmmac_safety_stats *stats)
      24                 :            : {
      25                 :          0 :         unsigned long loc, mask;
      26                 :          0 :         u8 *bptr = (u8 *)stats;
      27                 :          0 :         unsigned long *ptr;
      28                 :            : 
      29                 :          0 :         ptr = (unsigned long *)(bptr + field_offset);
      30                 :            : 
      31                 :          0 :         mask = value;
      32         [ #  # ]:          0 :         for_each_set_bit(loc, &mask, 32) {
      33                 :          0 :                 netdev_err(ndev, "Found %s error in %s: '%s: %s'\n", corr ?
      34                 :            :                                 "correctable" : "uncorrectable", module_name,
      35         [ #  # ]:          0 :                                 desc[loc].desc, desc[loc].detailed_desc);
      36                 :            : 
      37                 :            :                 /* Update counters */
      38                 :          0 :                 ptr[loc]++;
      39                 :            :         }
      40                 :          0 : }
      41                 :            : 
      42                 :            : static const struct dwmac5_error_desc dwmac5_mac_errors[32]= {
      43                 :            :         { true, "ATPES", "Application Transmit Interface Parity Check Error" },
      44                 :            :         { true, "TPES", "TSO Data Path Parity Check Error" },
      45                 :            :         { true, "RDPES", "Read Descriptor Parity Check Error" },
      46                 :            :         { true, "MPES", "MTL Data Path Parity Check Error" },
      47                 :            :         { true, "MTSPES", "MTL TX Status Data Path Parity Check Error" },
      48                 :            :         { true, "ARPES", "Application Receive Interface Data Path Parity Check Error" },
      49                 :            :         { true, "CWPES", "CSR Write Data Path Parity Check Error" },
      50                 :            :         { true, "ASRPES", "AXI Slave Read Data Path Parity Check Error" },
      51                 :            :         { true, "TTES", "TX FSM Timeout Error" },
      52                 :            :         { true, "RTES", "RX FSM Timeout Error" },
      53                 :            :         { true, "CTES", "CSR FSM Timeout Error" },
      54                 :            :         { true, "ATES", "APP FSM Timeout Error" },
      55                 :            :         { true, "PTES", "PTP FSM Timeout Error" },
      56                 :            :         { true, "T125ES", "TX125 FSM Timeout Error" },
      57                 :            :         { true, "R125ES", "RX125 FSM Timeout Error" },
      58                 :            :         { true, "RVCTES", "REV MDC FSM Timeout Error" },
      59                 :            :         { true, "MSTTES", "Master Read/Write Timeout Error" },
      60                 :            :         { true, "SLVTES", "Slave Read/Write Timeout Error" },
      61                 :            :         { true, "ATITES", "Application Timeout on ATI Interface Error" },
      62                 :            :         { true, "ARITES", "Application Timeout on ARI Interface Error" },
      63                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 20 */
      64                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 21 */
      65                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 22 */
      66                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 23 */
      67                 :            :         { true, "FSMPES", "FSM State Parity Error" },
      68                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 25 */
      69                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 26 */
      70                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 27 */
      71                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 28 */
      72                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 29 */
      73                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 30 */
      74                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 31 */
      75                 :            : };
      76                 :            : 
      77                 :          0 : static void dwmac5_handle_mac_err(struct net_device *ndev,
      78                 :            :                 void __iomem *ioaddr, bool correctable,
      79                 :            :                 struct stmmac_safety_stats *stats)
      80                 :            : {
      81                 :          0 :         u32 value;
      82                 :            : 
      83                 :          0 :         value = readl(ioaddr + MAC_DPP_FSM_INT_STATUS);
      84                 :          0 :         writel(value, ioaddr + MAC_DPP_FSM_INT_STATUS);
      85                 :            : 
      86                 :          0 :         dwmac5_log_error(ndev, value, correctable, "MAC", dwmac5_mac_errors,
      87                 :            :                         STAT_OFF(mac_errors), stats);
      88                 :            : }
      89                 :            : 
      90                 :            : static const struct dwmac5_error_desc dwmac5_mtl_errors[32]= {
      91                 :            :         { true, "TXCES", "MTL TX Memory Error" },
      92                 :            :         { true, "TXAMS", "MTL TX Memory Address Mismatch Error" },
      93                 :            :         { true, "TXUES", "MTL TX Memory Error" },
      94                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 3 */
      95                 :            :         { true, "RXCES", "MTL RX Memory Error" },
      96                 :            :         { true, "RXAMS", "MTL RX Memory Address Mismatch Error" },
      97                 :            :         { true, "RXUES", "MTL RX Memory Error" },
      98                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 7 */
      99                 :            :         { true, "ECES", "MTL EST Memory Error" },
     100                 :            :         { true, "EAMS", "MTL EST Memory Address Mismatch Error" },
     101                 :            :         { true, "EUES", "MTL EST Memory Error" },
     102                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 11 */
     103                 :            :         { true, "RPCES", "MTL RX Parser Memory Error" },
     104                 :            :         { true, "RPAMS", "MTL RX Parser Memory Address Mismatch Error" },
     105                 :            :         { true, "RPUES", "MTL RX Parser Memory Error" },
     106                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 15 */
     107                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 16 */
     108                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 17 */
     109                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 18 */
     110                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 19 */
     111                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 20 */
     112                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 21 */
     113                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 22 */
     114                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 23 */
     115                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 24 */
     116                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 25 */
     117                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 26 */
     118                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 27 */
     119                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 28 */
     120                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 29 */
     121                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 30 */
     122                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 31 */
     123                 :            : };
     124                 :            : 
     125                 :          0 : static void dwmac5_handle_mtl_err(struct net_device *ndev,
     126                 :            :                 void __iomem *ioaddr, bool correctable,
     127                 :            :                 struct stmmac_safety_stats *stats)
     128                 :            : {
     129                 :          0 :         u32 value;
     130                 :            : 
     131                 :          0 :         value = readl(ioaddr + MTL_ECC_INT_STATUS);
     132                 :          0 :         writel(value, ioaddr + MTL_ECC_INT_STATUS);
     133                 :            : 
     134                 :          0 :         dwmac5_log_error(ndev, value, correctable, "MTL", dwmac5_mtl_errors,
     135                 :            :                         STAT_OFF(mtl_errors), stats);
     136                 :            : }
     137                 :            : 
     138                 :            : static const struct dwmac5_error_desc dwmac5_dma_errors[32]= {
     139                 :            :         { true, "TCES", "DMA TSO Memory Error" },
     140                 :            :         { true, "TAMS", "DMA TSO Memory Address Mismatch Error" },
     141                 :            :         { true, "TUES", "DMA TSO Memory Error" },
     142                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 3 */
     143                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 4 */
     144                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 5 */
     145                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 6 */
     146                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 7 */
     147                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 8 */
     148                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 9 */
     149                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 10 */
     150                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 11 */
     151                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 12 */
     152                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 13 */
     153                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 14 */
     154                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 15 */
     155                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 16 */
     156                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 17 */
     157                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 18 */
     158                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 19 */
     159                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 20 */
     160                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 21 */
     161                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 22 */
     162                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 23 */
     163                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 24 */
     164                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 25 */
     165                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 26 */
     166                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 27 */
     167                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 28 */
     168                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 29 */
     169                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 30 */
     170                 :            :         { false, "UNKNOWN", "Unknown Error" }, /* 31 */
     171                 :            : };
     172                 :            : 
     173                 :          0 : static void dwmac5_handle_dma_err(struct net_device *ndev,
     174                 :            :                 void __iomem *ioaddr, bool correctable,
     175                 :            :                 struct stmmac_safety_stats *stats)
     176                 :            : {
     177                 :          0 :         u32 value;
     178                 :            : 
     179                 :          0 :         value = readl(ioaddr + DMA_ECC_INT_STATUS);
     180                 :          0 :         writel(value, ioaddr + DMA_ECC_INT_STATUS);
     181                 :            : 
     182                 :          0 :         dwmac5_log_error(ndev, value, correctable, "DMA", dwmac5_dma_errors,
     183                 :            :                         STAT_OFF(dma_errors), stats);
     184                 :            : }
     185                 :            : 
     186                 :          0 : int dwmac5_safety_feat_config(void __iomem *ioaddr, unsigned int asp)
     187                 :            : {
     188                 :          0 :         u32 value;
     189                 :            : 
     190         [ #  # ]:          0 :         if (!asp)
     191                 :            :                 return -EINVAL;
     192                 :            : 
     193                 :            :         /* 1. Enable Safety Features */
     194                 :          0 :         value = readl(ioaddr + MTL_ECC_CONTROL);
     195                 :          0 :         value |= TSOEE; /* TSO ECC */
     196                 :          0 :         value |= MRXPEE; /* MTL RX Parser ECC */
     197                 :          0 :         value |= MESTEE; /* MTL EST ECC */
     198                 :          0 :         value |= MRXEE; /* MTL RX FIFO ECC */
     199                 :          0 :         value |= MTXEE; /* MTL TX FIFO ECC */
     200                 :          0 :         writel(value, ioaddr + MTL_ECC_CONTROL);
     201                 :            : 
     202                 :            :         /* 2. Enable MTL Safety Interrupts */
     203                 :          0 :         value = readl(ioaddr + MTL_ECC_INT_ENABLE);
     204                 :          0 :         value |= RPCEIE; /* RX Parser Memory Correctable Error */
     205                 :          0 :         value |= ECEIE; /* EST Memory Correctable Error */
     206                 :          0 :         value |= RXCEIE; /* RX Memory Correctable Error */
     207                 :          0 :         value |= TXCEIE; /* TX Memory Correctable Error */
     208                 :          0 :         writel(value, ioaddr + MTL_ECC_INT_ENABLE);
     209                 :            : 
     210                 :            :         /* 3. Enable DMA Safety Interrupts */
     211                 :          0 :         value = readl(ioaddr + DMA_ECC_INT_ENABLE);
     212                 :          0 :         value |= TCEIE; /* TSO Memory Correctable Error */
     213                 :          0 :         writel(value, ioaddr + DMA_ECC_INT_ENABLE);
     214                 :            : 
     215                 :            :         /* Only ECC Protection for External Memory feature is selected */
     216         [ #  # ]:          0 :         if (asp <= 0x1)
     217                 :            :                 return 0;
     218                 :            : 
     219                 :            :         /* 5. Enable Parity and Timeout for FSM */
     220                 :          0 :         value = readl(ioaddr + MAC_FSM_CONTROL);
     221                 :          0 :         value |= PRTYEN; /* FSM Parity Feature */
     222                 :          0 :         value |= TMOUTEN; /* FSM Timeout Feature */
     223                 :          0 :         writel(value, ioaddr + MAC_FSM_CONTROL);
     224                 :            : 
     225                 :            :         /* 4. Enable Data Parity Protection */
     226                 :          0 :         value = readl(ioaddr + MTL_DPP_CONTROL);
     227                 :          0 :         value |= EDPP;
     228                 :          0 :         writel(value, ioaddr + MTL_DPP_CONTROL);
     229                 :            : 
     230                 :            :         /*
     231                 :            :          * All the Automotive Safety features are selected without the "Parity
     232                 :            :          * Port Enable for external interface" feature.
     233                 :            :          */
     234         [ #  # ]:          0 :         if (asp <= 0x2)
     235                 :            :                 return 0;
     236                 :            : 
     237                 :          0 :         value |= EPSI;
     238                 :          0 :         writel(value, ioaddr + MTL_DPP_CONTROL);
     239                 :          0 :         return 0;
     240                 :            : }
     241                 :            : 
     242                 :          0 : int dwmac5_safety_feat_irq_status(struct net_device *ndev,
     243                 :            :                 void __iomem *ioaddr, unsigned int asp,
     244                 :            :                 struct stmmac_safety_stats *stats)
     245                 :            : {
     246                 :          0 :         bool err, corr;
     247                 :          0 :         u32 mtl, dma;
     248                 :          0 :         int ret = 0;
     249                 :            : 
     250         [ #  # ]:          0 :         if (!asp)
     251                 :            :                 return -EINVAL;
     252                 :            : 
     253                 :          0 :         mtl = readl(ioaddr + MTL_SAFETY_INT_STATUS);
     254                 :          0 :         dma = readl(ioaddr + DMA_SAFETY_INT_STATUS);
     255                 :            : 
     256   [ #  #  #  # ]:          0 :         err = (mtl & MCSIS) || (dma & MCSIS);
     257                 :          0 :         corr = false;
     258         [ #  # ]:          0 :         if (err) {
     259                 :          0 :                 dwmac5_handle_mac_err(ndev, ioaddr, corr, stats);
     260                 :          0 :                 ret |= !corr;
     261                 :            :         }
     262                 :            : 
     263   [ #  #  #  # ]:          0 :         err = (mtl & (MEUIS | MECIS)) || (dma & (MSUIS | MSCIS));
     264   [ #  #  #  # ]:          0 :         corr = (mtl & MECIS) || (dma & MSCIS);
     265         [ #  # ]:          0 :         if (err) {
     266                 :          0 :                 dwmac5_handle_mtl_err(ndev, ioaddr, corr, stats);
     267                 :          0 :                 ret |= !corr;
     268                 :            :         }
     269                 :            : 
     270                 :          0 :         err = dma & (DEUIS | DECIS);
     271                 :          0 :         corr = dma & DECIS;
     272         [ #  # ]:          0 :         if (err) {
     273                 :          0 :                 dwmac5_handle_dma_err(ndev, ioaddr, corr, stats);
     274                 :          0 :                 ret |= !corr;
     275                 :            :         }
     276                 :            : 
     277                 :            :         return ret;
     278                 :            : }
     279                 :            : 
     280                 :            : static const struct dwmac5_error {
     281                 :            :         const struct dwmac5_error_desc *desc;
     282                 :            : } dwmac5_all_errors[] = {
     283                 :            :         { dwmac5_mac_errors },
     284                 :            :         { dwmac5_mtl_errors },
     285                 :            :         { dwmac5_dma_errors },
     286                 :            : };
     287                 :            : 
     288                 :          0 : int dwmac5_safety_feat_dump(struct stmmac_safety_stats *stats,
     289                 :            :                         int index, unsigned long *count, const char **desc)
     290                 :            : {
     291                 :          0 :         int module = index / 32, offset = index % 32;
     292                 :          0 :         unsigned long *ptr = (unsigned long *)stats;
     293                 :            : 
     294         [ #  # ]:          0 :         if (module >= ARRAY_SIZE(dwmac5_all_errors))
     295                 :            :                 return -EINVAL;
     296         [ #  # ]:          0 :         if (!dwmac5_all_errors[module].desc[offset].valid)
     297                 :            :                 return -EINVAL;
     298         [ #  # ]:          0 :         if (count)
     299                 :          0 :                 *count = *(ptr + index);
     300         [ #  # ]:          0 :         if (desc)
     301                 :          0 :                 *desc = dwmac5_all_errors[module].desc[offset].desc;
     302                 :            :         return 0;
     303                 :            : }
     304                 :            : 
     305                 :          0 : static int dwmac5_rxp_disable(void __iomem *ioaddr)
     306                 :            : {
     307                 :          0 :         u32 val;
     308                 :          0 :         int ret;
     309                 :            : 
     310                 :          0 :         val = readl(ioaddr + MTL_OPERATION_MODE);
     311                 :          0 :         val &= ~MTL_FRPE;
     312                 :          0 :         writel(val, ioaddr + MTL_OPERATION_MODE);
     313                 :            : 
     314   [ #  #  #  # ]:          0 :         ret = readl_poll_timeout(ioaddr + MTL_RXP_CONTROL_STATUS, val,
     315                 :            :                         val & RXPI, 1, 10000);
     316                 :          0 :         if (ret)
     317                 :          0 :                 return ret;
     318                 :            :         return 0;
     319                 :            : }
     320                 :            : 
     321                 :          0 : static void dwmac5_rxp_enable(void __iomem *ioaddr)
     322                 :            : {
     323                 :          0 :         u32 val;
     324                 :            : 
     325                 :          0 :         val = readl(ioaddr + MTL_OPERATION_MODE);
     326                 :          0 :         val |= MTL_FRPE;
     327                 :          0 :         writel(val, ioaddr + MTL_OPERATION_MODE);
     328                 :          0 : }
     329                 :            : 
     330                 :          0 : static int dwmac5_rxp_update_single_entry(void __iomem *ioaddr,
     331                 :            :                                           struct stmmac_tc_entry *entry,
     332                 :            :                                           int pos)
     333                 :            : {
     334                 :          0 :         int ret, i;
     335                 :            : 
     336         [ #  # ]:          0 :         for (i = 0; i < (sizeof(entry->val) / sizeof(u32)); i++) {
     337                 :          0 :                 int real_pos = pos * (sizeof(entry->val) / sizeof(u32)) + i;
     338                 :          0 :                 u32 val;
     339                 :            : 
     340                 :            :                 /* Wait for ready */
     341   [ #  #  #  # ]:          0 :                 ret = readl_poll_timeout(ioaddr + MTL_RXP_IACC_CTRL_STATUS,
     342                 :            :                                 val, !(val & STARTBUSY), 1, 10000);
     343                 :          0 :                 if (ret)
     344                 :            :                         return ret;
     345                 :            : 
     346                 :            :                 /* Write data */
     347                 :          0 :                 val = *((u32 *)&entry->val + i);
     348                 :          0 :                 writel(val, ioaddr + MTL_RXP_IACC_DATA);
     349                 :            : 
     350                 :            :                 /* Write pos */
     351                 :          0 :                 val = real_pos & ADDR;
     352                 :          0 :                 writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
     353                 :            : 
     354                 :            :                 /* Write OP */
     355                 :          0 :                 val |= WRRDN;
     356                 :          0 :                 writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
     357                 :            : 
     358                 :            :                 /* Start Write */
     359                 :          0 :                 val |= STARTBUSY;
     360                 :          0 :                 writel(val, ioaddr + MTL_RXP_IACC_CTRL_STATUS);
     361                 :            : 
     362                 :            :                 /* Wait for done */
     363   [ #  #  #  # ]:          0 :                 ret = readl_poll_timeout(ioaddr + MTL_RXP_IACC_CTRL_STATUS,
     364                 :            :                                 val, !(val & STARTBUSY), 1, 10000);
     365                 :          0 :                 if (ret)
     366                 :            :                         return ret;
     367                 :            :         }
     368                 :            : 
     369                 :            :         return 0;
     370                 :            : }
     371                 :            : 
     372                 :            : static struct stmmac_tc_entry *
     373                 :          0 : dwmac5_rxp_get_next_entry(struct stmmac_tc_entry *entries, unsigned int count,
     374                 :            :                           u32 curr_prio)
     375                 :            : {
     376                 :          0 :         struct stmmac_tc_entry *entry;
     377                 :          0 :         u32 min_prio = ~0x0;
     378                 :          0 :         int i, min_prio_idx;
     379                 :          0 :         bool found = false;
     380                 :            : 
     381         [ #  # ]:          0 :         for (i = count - 1; i >= 0; i--) {
     382                 :          0 :                 entry = &entries[i];
     383                 :            : 
     384                 :            :                 /* Do not update unused entries */
     385         [ #  # ]:          0 :                 if (!entry->in_use)
     386                 :          0 :                         continue;
     387                 :            :                 /* Do not update already updated entries (i.e. fragments) */
     388         [ #  # ]:          0 :                 if (entry->in_hw)
     389                 :          0 :                         continue;
     390                 :            :                 /* Let last entry be updated last */
     391         [ #  # ]:          0 :                 if (entry->is_last)
     392                 :          0 :                         continue;
     393                 :            :                 /* Do not return fragments */
     394         [ #  # ]:          0 :                 if (entry->is_frag)
     395                 :          0 :                         continue;
     396                 :            :                 /* Check if we already checked this prio */
     397         [ #  # ]:          0 :                 if (entry->prio < curr_prio)
     398                 :          0 :                         continue;
     399                 :            :                 /* Check if this is the minimum prio */
     400         [ #  # ]:          0 :                 if (entry->prio < min_prio) {
     401                 :          0 :                         min_prio = entry->prio;
     402                 :          0 :                         min_prio_idx = i;
     403                 :          0 :                         found = true;
     404                 :            :                 }
     405                 :            :         }
     406                 :            : 
     407         [ #  # ]:          0 :         if (found)
     408                 :          0 :                 return &entries[min_prio_idx];
     409                 :            :         return NULL;
     410                 :            : }
     411                 :            : 
     412                 :          0 : int dwmac5_rxp_config(void __iomem *ioaddr, struct stmmac_tc_entry *entries,
     413                 :            :                       unsigned int count)
     414                 :            : {
     415                 :          0 :         struct stmmac_tc_entry *entry, *frag;
     416                 :          0 :         int i, ret, nve = 0;
     417                 :          0 :         u32 curr_prio = 0;
     418                 :          0 :         u32 old_val, val;
     419                 :            : 
     420                 :            :         /* Force disable RX */
     421                 :          0 :         old_val = readl(ioaddr + GMAC_CONFIG);
     422                 :          0 :         val = old_val & ~GMAC_CONFIG_RE;
     423                 :          0 :         writel(val, ioaddr + GMAC_CONFIG);
     424                 :            : 
     425                 :            :         /* Disable RX Parser */
     426                 :          0 :         ret = dwmac5_rxp_disable(ioaddr);
     427         [ #  # ]:          0 :         if (ret)
     428                 :          0 :                 goto re_enable;
     429                 :            : 
     430                 :            :         /* Set all entries as NOT in HW */
     431         [ #  # ]:          0 :         for (i = 0; i < count; i++) {
     432                 :          0 :                 entry = &entries[i];
     433                 :          0 :                 entry->in_hw = false;
     434                 :            :         }
     435                 :            : 
     436                 :            :         /* Update entries by reverse order */
     437                 :          0 :         while (1) {
     438                 :          0 :                 entry = dwmac5_rxp_get_next_entry(entries, count, curr_prio);
     439         [ #  # ]:          0 :                 if (!entry)
     440                 :            :                         break;
     441                 :            : 
     442                 :          0 :                 curr_prio = entry->prio;
     443                 :          0 :                 frag = entry->frag_ptr;
     444                 :            : 
     445                 :            :                 /* Set special fragment requirements */
     446         [ #  # ]:          0 :                 if (frag) {
     447                 :          0 :                         entry->val.af = 0;
     448                 :          0 :                         entry->val.rf = 0;
     449                 :          0 :                         entry->val.nc = 1;
     450                 :          0 :                         entry->val.ok_index = nve + 2;
     451                 :            :                 }
     452                 :            : 
     453                 :          0 :                 ret = dwmac5_rxp_update_single_entry(ioaddr, entry, nve);
     454         [ #  # ]:          0 :                 if (ret)
     455                 :          0 :                         goto re_enable;
     456                 :            : 
     457                 :          0 :                 entry->table_pos = nve++;
     458                 :          0 :                 entry->in_hw = true;
     459                 :            : 
     460   [ #  #  #  # ]:          0 :                 if (frag && !frag->in_hw) {
     461                 :          0 :                         ret = dwmac5_rxp_update_single_entry(ioaddr, frag, nve);
     462         [ #  # ]:          0 :                         if (ret)
     463                 :          0 :                                 goto re_enable;
     464                 :          0 :                         frag->table_pos = nve++;
     465                 :          0 :                         frag->in_hw = true;
     466                 :            :                 }
     467                 :            :         }
     468                 :            : 
     469         [ #  # ]:          0 :         if (!nve)
     470                 :          0 :                 goto re_enable;
     471                 :            : 
     472                 :            :         /* Update all pass entry */
     473         [ #  # ]:          0 :         for (i = 0; i < count; i++) {
     474                 :          0 :                 entry = &entries[i];
     475         [ #  # ]:          0 :                 if (!entry->is_last)
     476                 :          0 :                         continue;
     477                 :            : 
     478                 :          0 :                 ret = dwmac5_rxp_update_single_entry(ioaddr, entry, nve);
     479         [ #  # ]:          0 :                 if (ret)
     480                 :          0 :                         goto re_enable;
     481                 :            : 
     482                 :          0 :                 entry->table_pos = nve++;
     483                 :            :         }
     484                 :            : 
     485                 :            :         /* Assume n. of parsable entries == n. of valid entries */
     486                 :          0 :         val = (nve << 16) & NPE;
     487                 :          0 :         val |= nve & NVE;
     488                 :          0 :         writel(val, ioaddr + MTL_RXP_CONTROL_STATUS);
     489                 :            : 
     490                 :            :         /* Enable RX Parser */
     491                 :          0 :         dwmac5_rxp_enable(ioaddr);
     492                 :            : 
     493                 :          0 : re_enable:
     494                 :            :         /* Re-enable RX */
     495                 :          0 :         writel(old_val, ioaddr + GMAC_CONFIG);
     496                 :          0 :         return ret;
     497                 :            : }
     498                 :            : 
     499                 :          0 : int dwmac5_flex_pps_config(void __iomem *ioaddr, int index,
     500                 :            :                            struct stmmac_pps_cfg *cfg, bool enable,
     501                 :            :                            u32 sub_second_inc, u32 systime_flags)
     502                 :            : {
     503                 :          0 :         u32 tnsec = readl(ioaddr + MAC_PPSx_TARGET_TIME_NSEC(index));
     504                 :          0 :         u32 val = readl(ioaddr + MAC_PPS_CONTROL);
     505                 :          0 :         u64 period;
     506                 :            : 
     507         [ #  # ]:          0 :         if (!cfg->available)
     508                 :            :                 return -EINVAL;
     509         [ #  # ]:          0 :         if (tnsec & TRGTBUSY0)
     510                 :            :                 return -EBUSY;
     511   [ #  #  #  # ]:          0 :         if (!sub_second_inc || !systime_flags)
     512                 :            :                 return -EINVAL;
     513                 :            : 
     514                 :          0 :         val &= ~PPSx_MASK(index);
     515                 :            : 
     516         [ #  # ]:          0 :         if (!enable) {
     517                 :          0 :                 val |= PPSCMDx(index, 0x5);
     518                 :          0 :                 val |= PPSEN0;
     519                 :          0 :                 writel(val, ioaddr + MAC_PPS_CONTROL);
     520                 :          0 :                 return 0;
     521                 :            :         }
     522                 :            : 
     523                 :          0 :         val |= PPSCMDx(index, 0x2);
     524                 :          0 :         val |= TRGTMODSELx(index, 0x2);
     525                 :          0 :         val |= PPSEN0;
     526                 :            : 
     527                 :          0 :         writel(cfg->start.tv_sec, ioaddr + MAC_PPSx_TARGET_TIME_SEC(index));
     528                 :            : 
     529         [ #  # ]:          0 :         if (!(systime_flags & PTP_TCR_TSCTRLSSR))
     530                 :          0 :                 cfg->start.tv_nsec = (cfg->start.tv_nsec * 1000) / 465;
     531                 :          0 :         writel(cfg->start.tv_nsec, ioaddr + MAC_PPSx_TARGET_TIME_NSEC(index));
     532                 :            : 
     533                 :          0 :         period = cfg->period.tv_sec * 1000000000;
     534                 :          0 :         period += cfg->period.tv_nsec;
     535                 :            : 
     536                 :          0 :         do_div(period, sub_second_inc);
     537                 :            : 
     538         [ #  # ]:          0 :         if (period <= 1)
     539                 :            :                 return -EINVAL;
     540                 :            : 
     541                 :          0 :         writel(period - 1, ioaddr + MAC_PPSx_INTERVAL(index));
     542                 :            : 
     543                 :          0 :         period >>= 1;
     544         [ #  # ]:          0 :         if (period <= 1)
     545                 :            :                 return -EINVAL;
     546                 :            : 
     547                 :          0 :         writel(period - 1, ioaddr + MAC_PPSx_WIDTH(index));
     548                 :            : 
     549                 :            :         /* Finally, activate it */
     550                 :          0 :         writel(val, ioaddr + MAC_PPS_CONTROL);
     551                 :          0 :         return 0;
     552                 :            : }
     553                 :            : 
     554                 :          0 : static int dwmac5_est_write(void __iomem *ioaddr, u32 reg, u32 val, bool gcl)
     555                 :            : {
     556                 :          0 :         u32 ctrl;
     557                 :            : 
     558                 :          0 :         writel(val, ioaddr + MTL_EST_GCL_DATA);
     559                 :            : 
     560                 :          0 :         ctrl = (reg << ADDR_SHIFT);
     561         [ #  # ]:          0 :         ctrl |= gcl ? 0 : GCRR;
     562                 :            : 
     563                 :          0 :         writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
     564                 :            : 
     565                 :          0 :         ctrl |= SRWO;
     566                 :          0 :         writel(ctrl, ioaddr + MTL_EST_GCL_CONTROL);
     567                 :            : 
     568   [ #  #  #  # ]:          0 :         return readl_poll_timeout(ioaddr + MTL_EST_GCL_CONTROL,
     569                 :            :                                   ctrl, !(ctrl & SRWO), 100, 5000);
     570                 :            : }
     571                 :            : 
     572                 :          0 : int dwmac5_est_configure(void __iomem *ioaddr, struct stmmac_est *cfg,
     573                 :            :                          unsigned int ptp_rate)
     574                 :            : {
     575                 :          0 :         u32 speed, total_offset, offset, ctrl, ctr_low;
     576                 :          0 :         u32 extcfg = readl(ioaddr + GMAC_EXT_CONFIG);
     577                 :          0 :         u32 mac_cfg = readl(ioaddr + GMAC_CONFIG);
     578                 :          0 :         int i, ret = 0x0;
     579                 :          0 :         u64 total_ctr;
     580                 :            : 
     581         [ #  # ]:          0 :         if (extcfg & GMAC_CONFIG_EIPG_EN) {
     582                 :          0 :                 offset = (extcfg & GMAC_CONFIG_EIPG) >> GMAC_CONFIG_EIPG_SHIFT;
     583                 :          0 :                 offset = 104 + (offset * 8);
     584                 :            :         } else {
     585                 :          0 :                 offset = (mac_cfg & GMAC_CONFIG_IPG) >> GMAC_CONFIG_IPG_SHIFT;
     586                 :          0 :                 offset = 96 - (offset * 8);
     587                 :            :         }
     588                 :            : 
     589                 :          0 :         speed = mac_cfg & (GMAC_CONFIG_PS | GMAC_CONFIG_FES);
     590                 :          0 :         speed = speed >> GMAC_CONFIG_FES_SHIFT;
     591                 :            : 
     592   [ #  #  #  # ]:          0 :         switch (speed) {
     593                 :          0 :         case 0x0:
     594                 :          0 :                 offset = offset * 1000; /* 1G */
     595                 :          0 :                 break;
     596                 :          0 :         case 0x1:
     597                 :          0 :                 offset = offset * 400; /* 2.5G */
     598                 :          0 :                 break;
     599                 :          0 :         case 0x2:
     600                 :          0 :                 offset = offset * 100000; /* 10M */
     601                 :          0 :                 break;
     602                 :          0 :         case 0x3:
     603                 :          0 :                 offset = offset * 10000; /* 100M */
     604                 :          0 :                 break;
     605                 :            :         default:
     606                 :            :                 return -EINVAL;
     607                 :            :         }
     608                 :            : 
     609                 :          0 :         offset = offset / 1000;
     610                 :            : 
     611                 :          0 :         ret |= dwmac5_est_write(ioaddr, BTR_LOW, cfg->btr[0], false);
     612                 :          0 :         ret |= dwmac5_est_write(ioaddr, BTR_HIGH, cfg->btr[1], false);
     613                 :          0 :         ret |= dwmac5_est_write(ioaddr, TER, cfg->ter, false);
     614                 :          0 :         ret |= dwmac5_est_write(ioaddr, LLR, cfg->gcl_size, false);
     615         [ #  # ]:          0 :         if (ret)
     616                 :            :                 return ret;
     617                 :            : 
     618                 :            :         total_offset = 0;
     619         [ #  # ]:          0 :         for (i = 0; i < cfg->gcl_size; i++) {
     620                 :          0 :                 ret = dwmac5_est_write(ioaddr, i, cfg->gcl[i] + offset, true);
     621         [ #  # ]:          0 :                 if (ret)
     622                 :          0 :                         return ret;
     623                 :            : 
     624                 :          0 :                 total_offset += offset;
     625                 :            :         }
     626                 :            : 
     627                 :          0 :         total_ctr = cfg->ctr[0] + cfg->ctr[1] * 1000000000;
     628                 :          0 :         total_ctr += total_offset;
     629                 :            : 
     630                 :          0 :         ctr_low = do_div(total_ctr, 1000000000);
     631                 :            : 
     632                 :          0 :         ret |= dwmac5_est_write(ioaddr, CTR_LOW, ctr_low, false);
     633                 :          0 :         ret |= dwmac5_est_write(ioaddr, CTR_HIGH, total_ctr, false);
     634         [ #  # ]:          0 :         if (ret)
     635                 :            :                 return ret;
     636                 :            : 
     637                 :          0 :         ctrl = readl(ioaddr + MTL_EST_CONTROL);
     638                 :          0 :         ctrl &= ~PTOV;
     639                 :          0 :         ctrl |= ((1000000000 / ptp_rate) * 6) << PTOV_SHIFT;
     640         [ #  # ]:          0 :         if (cfg->enable)
     641                 :          0 :                 ctrl |= EEST | SSWL;
     642                 :            :         else
     643                 :          0 :                 ctrl &= ~EEST;
     644                 :            : 
     645                 :          0 :         writel(ctrl, ioaddr + MTL_EST_CONTROL);
     646                 :          0 :         return 0;
     647                 :            : }
     648                 :            : 
     649                 :          0 : void dwmac5_fpe_configure(void __iomem *ioaddr, u32 num_txq, u32 num_rxq,
     650                 :            :                           bool enable)
     651                 :            : {
     652                 :          0 :         u32 value;
     653                 :            : 
     654         [ #  # ]:          0 :         if (!enable) {
     655                 :          0 :                 value = readl(ioaddr + MAC_FPE_CTRL_STS);
     656                 :            : 
     657                 :          0 :                 value &= ~EFPE;
     658                 :            : 
     659                 :          0 :                 writel(value, ioaddr + MAC_FPE_CTRL_STS);
     660                 :          0 :                 return;
     661                 :            :         }
     662                 :            : 
     663                 :          0 :         value = readl(ioaddr + GMAC_RXQ_CTRL1);
     664                 :          0 :         value &= ~GMAC_RXQCTRL_FPRQ;
     665                 :          0 :         value |= (num_rxq - 1) << GMAC_RXQCTRL_FPRQ_SHIFT;
     666                 :          0 :         writel(value, ioaddr + GMAC_RXQ_CTRL1);
     667                 :            : 
     668                 :          0 :         value = readl(ioaddr + MAC_FPE_CTRL_STS);
     669                 :          0 :         value |= EFPE;
     670                 :          0 :         writel(value, ioaddr + MAC_FPE_CTRL_STS);
     671                 :            : }

Generated by: LCOV version 1.14