LCOV - code coverage report
Current view: top level - drivers/net/axgbe - axgbe_i2c.c (source / functions) Hit Total Coverage
Test: Code coverage Lines: 0 125 0.0 %
Date: 2024-12-01 18:57:19 Functions: 0 11 0.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0 60 0.0 %

           Branch data     Line data    Source code
       1                 :            : /*   SPDX-License-Identifier: BSD-3-Clause
       2                 :            :  *   Copyright(c) 2018 Advanced Micro Devices, Inc. All rights reserved.
       3                 :            :  *   Copyright(c) 2018 Synopsys, Inc. All rights reserved.
       4                 :            :  */
       5                 :            : 
       6                 :            : #include "axgbe_ethdev.h"
       7                 :            : #include "axgbe_common.h"
       8                 :            : 
       9                 :            : #define AXGBE_ABORT_COUNT       500
      10                 :            : #define AXGBE_DISABLE_COUNT     1000
      11                 :            : 
      12                 :            : #define AXGBE_STD_SPEED         1
      13                 :            : 
      14                 :            : #define AXGBE_INTR_RX_FULL      BIT(IC_RAW_INTR_STAT_RX_FULL_INDEX)
      15                 :            : #define AXGBE_INTR_TX_EMPTY     BIT(IC_RAW_INTR_STAT_TX_EMPTY_INDEX)
      16                 :            : #define AXGBE_INTR_TX_ABRT      BIT(IC_RAW_INTR_STAT_TX_ABRT_INDEX)
      17                 :            : #define AXGBE_INTR_STOP_DET     BIT(IC_RAW_INTR_STAT_STOP_DET_INDEX)
      18                 :            : #define AXGBE_DEFAULT_INT_MASK  (AXGBE_INTR_RX_FULL  |  \
      19                 :            :                                  AXGBE_INTR_TX_EMPTY |  \
      20                 :            :                                  AXGBE_INTR_TX_ABRT  |  \
      21                 :            :                                  AXGBE_INTR_STOP_DET)
      22                 :            : 
      23                 :            : #define AXGBE_I2C_READ          BIT(8)
      24                 :            : #define AXGBE_I2C_STOP          BIT(9)
      25                 :            : 
      26                 :          0 : static int axgbe_i2c_abort(struct axgbe_port *pdata)
      27                 :            : {
      28                 :            :         unsigned int wait = AXGBE_ABORT_COUNT;
      29                 :            : 
      30                 :            :         /* Must be enabled to recognize the abort request */
      31                 :          0 :         XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, 1);
      32                 :            : 
      33                 :            :         /* Issue the abort */
      34                 :          0 :         XI2C_IOWRITE_BITS(pdata, IC_ENABLE, ABORT, 1);
      35                 :            : 
      36         [ #  # ]:          0 :         while (wait--) {
      37         [ #  # ]:          0 :                 if (!XI2C_IOREAD_BITS(pdata, IC_ENABLE, ABORT))
      38                 :            :                         return 0;
      39                 :          0 :                 rte_delay_us(500);
      40                 :            :         }
      41                 :            : 
      42                 :            :         return -EBUSY;
      43                 :            : }
      44                 :            : 
      45                 :          0 : static int axgbe_i2c_set_enable(struct axgbe_port *pdata, bool enable)
      46                 :            : {
      47                 :            :         unsigned int wait = AXGBE_DISABLE_COUNT;
      48                 :          0 :         unsigned int mode = enable ? 1 : 0;
      49                 :            : 
      50         [ #  # ]:          0 :         while (wait--) {
      51                 :          0 :                 XI2C_IOWRITE_BITS(pdata, IC_ENABLE, EN, mode);
      52         [ #  # ]:          0 :                 if (XI2C_IOREAD_BITS(pdata, IC_ENABLE_STATUS, EN) == mode)
      53                 :            :                         return 0;
      54                 :            : 
      55                 :          0 :                 rte_delay_us(100);
      56                 :            :         }
      57                 :            : 
      58                 :            :         return -EBUSY;
      59                 :            : }
      60                 :            : 
      61                 :          0 : static int axgbe_i2c_disable(struct axgbe_port *pdata)
      62                 :            : {
      63                 :            :         unsigned int ret;
      64                 :            : 
      65                 :          0 :         ret = axgbe_i2c_set_enable(pdata, false);
      66         [ #  # ]:          0 :         if (ret) {
      67                 :            :                 /* Disable failed, try an abort */
      68                 :          0 :                 ret = axgbe_i2c_abort(pdata);
      69         [ #  # ]:          0 :                 if (ret)
      70                 :            :                         return ret;
      71                 :            : 
      72                 :            :                 /* Abort succeeded, try to disable again */
      73                 :          0 :                 ret = axgbe_i2c_set_enable(pdata, false);
      74                 :            :         }
      75                 :            : 
      76                 :          0 :         return ret;
      77                 :            : }
      78                 :            : 
      79                 :            : static int axgbe_i2c_enable(struct axgbe_port *pdata)
      80                 :            : {
      81                 :          0 :         return axgbe_i2c_set_enable(pdata, true);
      82                 :            : }
      83                 :            : 
      84                 :            : static void axgbe_i2c_clear_all_interrupts(struct axgbe_port *pdata)
      85                 :            : {
      86                 :          0 :         XI2C_IOREAD(pdata, IC_CLR_INTR);
      87                 :          0 : }
      88                 :            : 
      89                 :            : static void axgbe_i2c_disable_interrupts(struct axgbe_port *pdata)
      90                 :            : {
      91                 :          0 :         XI2C_IOWRITE(pdata, IC_INTR_MASK, 0);
      92                 :            : }
      93                 :            : 
      94                 :            : static void axgbe_i2c_enable_interrupts(struct axgbe_port *pdata)
      95                 :            : {
      96                 :          0 :         XI2C_IOWRITE(pdata, IC_INTR_MASK, AXGBE_DEFAULT_INT_MASK);
      97                 :            : }
      98                 :            : 
      99                 :          0 : static void axgbe_i2c_write(struct axgbe_port *pdata)
     100                 :            : {
     101                 :            :         struct axgbe_i2c_op_state *state = &pdata->i2c.op_state;
     102                 :            :         unsigned int tx_slots;
     103                 :            :         unsigned int cmd;
     104                 :            : 
     105                 :            :         /* Configured to never receive Rx overflows, so fill up Tx fifo */
     106                 :          0 :         tx_slots = pdata->i2c.tx_fifo_size - XI2C_IOREAD(pdata, IC_TXFLR);
     107   [ #  #  #  # ]:          0 :         while (tx_slots && state->tx_len) {
     108         [ #  # ]:          0 :                 if (state->op->cmd == AXGBE_I2C_CMD_READ)
     109                 :            :                         cmd = AXGBE_I2C_READ;
     110                 :            :                 else
     111                 :          0 :                         cmd = *state->tx_buf++;
     112                 :            : 
     113         [ #  # ]:          0 :                 if (state->tx_len == 1)
     114                 :          0 :                         XI2C_SET_BITS(cmd, IC_DATA_CMD, STOP, 1);
     115                 :            : 
     116                 :          0 :                 XI2C_IOWRITE(pdata, IC_DATA_CMD, cmd);
     117                 :            : 
     118                 :          0 :                 tx_slots--;
     119                 :          0 :                 state->tx_len--;
     120                 :            :         }
     121                 :            : 
     122                 :            :         /* No more Tx operations, so ignore TX_EMPTY and return */
     123         [ #  # ]:          0 :         if (!state->tx_len)
     124                 :          0 :                 XI2C_IOWRITE_BITS(pdata, IC_INTR_MASK, TX_EMPTY, 0);
     125                 :          0 : }
     126                 :            : 
     127                 :          0 : static void axgbe_i2c_read(struct axgbe_port *pdata)
     128                 :            : {
     129                 :            :         struct axgbe_i2c_op_state *state = &pdata->i2c.op_state;
     130                 :            :         unsigned int rx_slots;
     131                 :            : 
     132                 :            :         /* Anything to be read? */
     133         [ #  # ]:          0 :         if (state->op->cmd != AXGBE_I2C_CMD_READ)
     134                 :            :                 return;
     135                 :            : 
     136                 :          0 :         rx_slots = XI2C_IOREAD(pdata, IC_RXFLR);
     137   [ #  #  #  # ]:          0 :         while (rx_slots && state->rx_len) {
     138                 :          0 :                 *state->rx_buf++ = XI2C_IOREAD(pdata, IC_DATA_CMD);
     139                 :          0 :                 state->rx_len--;
     140                 :          0 :                 rx_slots--;
     141                 :            :         }
     142                 :            : }
     143                 :            : 
     144                 :            : static void axgbe_i2c_clear_isr_interrupts(struct axgbe_port *pdata,
     145                 :            :                                           unsigned int isr)
     146                 :            : {
     147                 :            :         struct axgbe_i2c_op_state *state = &pdata->i2c.op_state;
     148                 :            : 
     149         [ #  # ]:          0 :         if (isr & AXGBE_INTR_TX_ABRT) {
     150                 :          0 :                 state->tx_abort_source = XI2C_IOREAD(pdata, IC_TX_ABRT_SOURCE);
     151                 :          0 :                 XI2C_IOREAD(pdata, IC_CLR_TX_ABRT);
     152                 :            :         }
     153                 :            : 
     154         [ #  # ]:          0 :         if (isr & AXGBE_INTR_STOP_DET)
     155                 :          0 :                 XI2C_IOREAD(pdata, IC_CLR_STOP_DET);
     156                 :            : }
     157                 :            : 
     158                 :          0 : static int axgbe_i2c_isr(struct axgbe_port *pdata)
     159                 :            : {
     160                 :            :         struct axgbe_i2c_op_state *state = &pdata->i2c.op_state;
     161                 :            :         unsigned int isr;
     162                 :            : 
     163                 :          0 :         isr = XI2C_IOREAD(pdata, IC_RAW_INTR_STAT);
     164                 :            : 
     165                 :          0 :         PMD_DRV_LOG_LINE(DEBUG, "I2C interrupt received: status=%#010x", isr);
     166                 :            : 
     167                 :            :         axgbe_i2c_clear_isr_interrupts(pdata, isr);
     168                 :            : 
     169         [ #  # ]:          0 :         if (isr & AXGBE_INTR_TX_ABRT) {
     170                 :          0 :                 PMD_DRV_LOG_LINE(DEBUG,
     171                 :            :                             "I2C TX_ABRT received (%#010x) for target %#04x",
     172                 :            :                             state->tx_abort_source, state->op->target);
     173                 :            : 
     174                 :            :                 axgbe_i2c_disable_interrupts(pdata);
     175                 :            : 
     176                 :          0 :                 state->ret = -EIO;
     177                 :          0 :                 goto out;
     178                 :            :         }
     179                 :            : 
     180                 :            :         /* Check for data in the Rx fifo */
     181                 :          0 :         axgbe_i2c_read(pdata);
     182                 :            : 
     183                 :            :         /* Fill up the Tx fifo next */
     184                 :          0 :         axgbe_i2c_write(pdata);
     185                 :            : 
     186                 :          0 : out:
     187                 :            :         /* Complete on an error or STOP condition */
     188   [ #  #  #  # ]:          0 :         if (state->ret || XI2C_GET_BITS(isr, IC_RAW_INTR_STAT, STOP_DET))
     189                 :          0 :                 return 1;
     190                 :            : 
     191                 :            :         return 0;
     192                 :            : }
     193                 :            : 
     194                 :            : static void axgbe_i2c_set_mode(struct axgbe_port *pdata)
     195                 :            : {
     196                 :            :         unsigned int reg;
     197                 :            : 
     198                 :          0 :         reg = XI2C_IOREAD(pdata, IC_CON);
     199                 :            :         XI2C_SET_BITS(reg, IC_CON, MASTER_MODE, 1);
     200                 :            :         XI2C_SET_BITS(reg, IC_CON, SLAVE_DISABLE, 1);
     201                 :            :         XI2C_SET_BITS(reg, IC_CON, RESTART_EN, 1);
     202                 :            :         XI2C_SET_BITS(reg, IC_CON, SPEED, AXGBE_STD_SPEED);
     203                 :          0 :         XI2C_SET_BITS(reg, IC_CON, RX_FIFO_FULL_HOLD, 1);
     204                 :          0 :         XI2C_IOWRITE(pdata, IC_CON, reg);
     205                 :            : }
     206                 :            : 
     207                 :            : static void axgbe_i2c_get_features(struct axgbe_port *pdata)
     208                 :            : {
     209                 :            :         struct axgbe_i2c *i2c = &pdata->i2c;
     210                 :            :         unsigned int reg;
     211                 :            : 
     212                 :          0 :         reg = XI2C_IOREAD(pdata, IC_COMP_PARAM_1);
     213                 :          0 :         i2c->max_speed_mode = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
     214                 :            :                                             MAX_SPEED_MODE);
     215                 :          0 :         i2c->rx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
     216                 :            :                                           RX_BUFFER_DEPTH);
     217                 :          0 :         i2c->tx_fifo_size = XI2C_GET_BITS(reg, IC_COMP_PARAM_1,
     218                 :            :                                           TX_BUFFER_DEPTH);
     219                 :            : }
     220                 :            : 
     221                 :            : static void axgbe_i2c_set_target(struct axgbe_port *pdata, unsigned int addr)
     222                 :            : {
     223                 :          0 :         XI2C_IOWRITE(pdata, IC_TAR, addr);
     224                 :            : }
     225                 :            : 
     226                 :          0 : static int axgbe_i2c_xfer(struct axgbe_port *pdata, struct axgbe_i2c_op *op)
     227                 :            : {
     228                 :          0 :         struct axgbe_i2c_op_state *state = &pdata->i2c.op_state;
     229                 :            :         int ret;
     230                 :            :         uint64_t timeout;
     231                 :            : 
     232                 :          0 :         pthread_mutex_lock(&pdata->i2c_mutex);
     233                 :          0 :         ret = axgbe_i2c_disable(pdata);
     234         [ #  # ]:          0 :         if (ret) {
     235                 :          0 :                 PMD_DRV_LOG_LINE(ERR, "failed to disable i2c master");
     236                 :          0 :                 pthread_mutex_unlock(&pdata->i2c_mutex);
     237                 :          0 :                 return ret;
     238                 :            :         }
     239                 :            : 
     240                 :          0 :         axgbe_i2c_set_target(pdata, op->target);
     241                 :            : 
     242                 :            :         memset(state, 0, sizeof(*state));
     243                 :          0 :         state->op = op;
     244                 :          0 :         state->tx_len = op->len;
     245                 :          0 :         state->tx_buf = (unsigned char *)op->buf;
     246                 :          0 :         state->rx_len = op->len;
     247                 :          0 :         state->rx_buf = (unsigned char *)op->buf;
     248                 :            : 
     249                 :            :         axgbe_i2c_clear_all_interrupts(pdata);
     250                 :            :         ret = axgbe_i2c_enable(pdata);
     251         [ #  # ]:          0 :         if (ret) {
     252                 :          0 :                 PMD_DRV_LOG_LINE(ERR, "failed to enable i2c master");
     253                 :          0 :                 pthread_mutex_unlock(&pdata->i2c_mutex);
     254                 :          0 :                 return ret;
     255                 :            :         }
     256                 :            : 
     257                 :            :         /* Enabling the interrupts will cause the TX FIFO empty interrupt to
     258                 :            :          * fire and begin to process the command via the ISR.
     259                 :            :          */
     260                 :            :         axgbe_i2c_enable_interrupts(pdata);
     261                 :          0 :         timeout = rte_get_timer_cycles() + rte_get_timer_hz();
     262                 :            : 
     263         [ #  # ]:          0 :         while (time_before(rte_get_timer_cycles(), timeout)) {
     264                 :          0 :                 rte_delay_us(100);
     265         [ #  # ]:          0 :                 if (XI2C_IOREAD(pdata, IC_RAW_INTR_STAT)) {
     266         [ #  # ]:          0 :                         if (axgbe_i2c_isr(pdata))
     267                 :          0 :                                 goto success;
     268                 :            :                 }
     269                 :            :         }
     270                 :            : 
     271                 :          0 :         PMD_DRV_LOG_LINE(ERR, "i2c operation timed out");
     272                 :            :         axgbe_i2c_disable_interrupts(pdata);
     273                 :          0 :         axgbe_i2c_disable(pdata);
     274                 :            :         ret = -ETIMEDOUT;
     275                 :          0 :         goto unlock;
     276                 :            : 
     277                 :            : success:
     278                 :          0 :         ret = state->ret;
     279         [ #  # ]:          0 :         if (ret) {
     280         [ #  # ]:          0 :                 if (state->tx_abort_source & IC_TX_ABRT_7B_ADDR_NOACK)
     281                 :            :                         ret = -ENOTCONN;
     282         [ #  # ]:          0 :                 else if (state->tx_abort_source & IC_TX_ABRT_ARB_LOST)
     283                 :            :                         ret = -EAGAIN;
     284                 :            :         }
     285                 :            : 
     286                 :          0 : unlock:
     287                 :          0 :         pthread_mutex_unlock(&pdata->i2c_mutex);
     288                 :          0 :         return ret;
     289                 :            : }
     290                 :            : 
     291                 :          0 : static void axgbe_i2c_stop(struct axgbe_port *pdata)
     292                 :            : {
     293         [ #  # ]:          0 :         if (!pdata->i2c.started)
     294                 :            :                 return;
     295                 :            : 
     296                 :          0 :         PMD_DRV_LOG_LINE(DEBUG, "stopping I2C");
     297                 :            : 
     298                 :          0 :         pdata->i2c.started = 0;
     299                 :            :         axgbe_i2c_disable_interrupts(pdata);
     300                 :          0 :         axgbe_i2c_disable(pdata);
     301                 :            :         axgbe_i2c_clear_all_interrupts(pdata);
     302                 :            : }
     303                 :            : 
     304                 :          0 : static int axgbe_i2c_start(struct axgbe_port *pdata)
     305                 :            : {
     306         [ #  # ]:          0 :         if (pdata->i2c.started)
     307                 :            :                 return 0;
     308                 :            : 
     309                 :          0 :         PMD_DRV_LOG_LINE(DEBUG, "starting I2C");
     310                 :            : 
     311                 :          0 :         pdata->i2c.started = 1;
     312                 :            : 
     313                 :          0 :         return 0;
     314                 :            : }
     315                 :            : 
     316                 :          0 : static int axgbe_i2c_init(struct axgbe_port *pdata)
     317                 :            : {
     318                 :            :         int ret;
     319                 :            : 
     320                 :            :         axgbe_i2c_disable_interrupts(pdata);
     321                 :            : 
     322                 :          0 :         ret = axgbe_i2c_disable(pdata);
     323         [ #  # ]:          0 :         if (ret) {
     324                 :          0 :                 PMD_DRV_LOG_LINE(ERR, "failed to disable i2c master");
     325                 :          0 :                 return ret;
     326                 :            :         }
     327                 :            : 
     328                 :            :         axgbe_i2c_get_features(pdata);
     329                 :            : 
     330                 :            :         axgbe_i2c_set_mode(pdata);
     331                 :            : 
     332                 :            :         axgbe_i2c_clear_all_interrupts(pdata);
     333                 :            : 
     334                 :          0 :         return 0;
     335                 :            : }
     336                 :            : 
     337                 :          0 : void axgbe_init_function_ptrs_i2c(struct axgbe_i2c_if *i2c_if)
     338                 :            : {
     339                 :          0 :         i2c_if->i2c_init             = axgbe_i2c_init;
     340                 :          0 :         i2c_if->i2c_start            = axgbe_i2c_start;
     341                 :          0 :         i2c_if->i2c_stop             = axgbe_i2c_stop;
     342                 :          0 :         i2c_if->i2c_xfer             = axgbe_i2c_xfer;
     343                 :          0 : }

Generated by: LCOV version 1.14