dpdk/drivers/net/ixgbe/ixgbe_bypass_api.h
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2010-2014 Intel Corporation
   3 */
   4
   5#ifndef _IXGBE_BYPASS_API_H_
   6#define _IXGBE_BYPASS_API_H_
   7
   8#ifdef RTE_LIBRTE_IXGBE_BYPASS
   9
  10#include "ixgbe_bypass_defines.h"
  11/**
  12 *  ixgbe_bypass_rw_generic - Bit bang data into by_pass FW
  13 *
  14 *  @hw: pointer to hardware structure
  15 *  @cmd: Command we send to the FW
  16 *  @status: The reply from the FW
  17 *
  18 *  Bit-bangs the cmd to the by_pass FW status points to what is returned.
  19 **/
  20#define IXGBE_BYPASS_BB_WAIT 1
  21static s32 ixgbe_bypass_rw_generic(struct ixgbe_hw *hw, u32 cmd, u32 *status)
  22{
  23        int i;
  24        u32 sck, sdi, sdo, dir_sck, dir_sdi, dir_sdo;
  25        u32 esdp;
  26
  27        if (!status)
  28                return IXGBE_ERR_PARAM;
  29
  30        *status = 0;
  31
  32        /* SDP vary by MAC type */
  33        switch (hw->mac.type) {
  34        case ixgbe_mac_82599EB:
  35                sck = IXGBE_ESDP_SDP7;
  36                sdi = IXGBE_ESDP_SDP0;
  37                sdo = IXGBE_ESDP_SDP6;
  38                dir_sck = IXGBE_ESDP_SDP7_DIR;
  39                dir_sdi = IXGBE_ESDP_SDP0_DIR;
  40                dir_sdo = IXGBE_ESDP_SDP6_DIR;
  41                break;
  42        case ixgbe_mac_X540:
  43                sck = IXGBE_ESDP_SDP2;
  44                sdi = IXGBE_ESDP_SDP0;
  45                sdo = IXGBE_ESDP_SDP1;
  46                dir_sck = IXGBE_ESDP_SDP2_DIR;
  47                dir_sdi = IXGBE_ESDP_SDP0_DIR;
  48                dir_sdo = IXGBE_ESDP_SDP1_DIR;
  49                break;
  50        case ixgbe_mac_X550:
  51        case ixgbe_mac_X550EM_x:
  52        case ixgbe_mac_X550EM_a:
  53                sck = IXGBE_ESDP_SDP2;
  54                sdi = IXGBE_ESDP_SDP0;
  55                sdo = IXGBE_ESDP_SDP1;
  56                dir_sck = IXGBE_ESDP_SDP2_DIR;
  57                dir_sdi = IXGBE_ESDP_SDP0_DIR;
  58                dir_sdo = IXGBE_ESDP_SDP1_DIR;
  59                break;
  60        default:
  61                return IXGBE_ERR_DEVICE_NOT_SUPPORTED;
  62        }
  63
  64        /* Set SDP pins direction */
  65        esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
  66        esdp |= dir_sck;        /* SCK as output */
  67        esdp |= dir_sdi;        /* SDI as output */
  68        esdp &= ~dir_sdo;       /* SDO as input */
  69        esdp |= sck;
  70        esdp |= sdi;
  71        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
  72        IXGBE_WRITE_FLUSH(hw);
  73  //  TODO:
  74        msleep(IXGBE_BYPASS_BB_WAIT);
  75
  76        /* Generate start condition */
  77        esdp &= ~sdi;
  78        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
  79        IXGBE_WRITE_FLUSH(hw);
  80        msleep(IXGBE_BYPASS_BB_WAIT);
  81
  82        esdp &= ~sck;
  83        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
  84        IXGBE_WRITE_FLUSH(hw);
  85        msleep(IXGBE_BYPASS_BB_WAIT);
  86
  87        /* Clock out the new control word and clock in the status */
  88        for (i = 0; i < 32; i++) {
  89                if ((cmd >> (31 - i)) & 0x01) {
  90                        esdp |= sdi;
  91                        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
  92                } else {
  93                        esdp &= ~sdi;
  94                        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
  95                }
  96                IXGBE_WRITE_FLUSH(hw);
  97                msleep(IXGBE_BYPASS_BB_WAIT);
  98
  99                esdp |= sck;
 100                IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
 101                IXGBE_WRITE_FLUSH(hw);
 102                msleep(IXGBE_BYPASS_BB_WAIT);
 103
 104                esdp &= ~sck;
 105                IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
 106                IXGBE_WRITE_FLUSH(hw);
 107                msleep(IXGBE_BYPASS_BB_WAIT);
 108
 109                esdp = IXGBE_READ_REG(hw, IXGBE_ESDP);
 110                if (esdp & sdo)
 111                        *status = (*status << 1) | 0x01;
 112                else
 113                        *status = (*status << 1) | 0x00;
 114                msleep(IXGBE_BYPASS_BB_WAIT);
 115        }
 116
 117        /* stop condition */
 118        esdp |= sck;
 119        esdp &= ~sdi;
 120        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
 121        IXGBE_WRITE_FLUSH(hw);
 122        msleep(IXGBE_BYPASS_BB_WAIT);
 123
 124        esdp |= sdi;
 125        IXGBE_WRITE_REG(hw, IXGBE_ESDP, esdp);
 126        IXGBE_WRITE_FLUSH(hw);
 127
 128        /* set the page bits to match the cmd that the status it belongs to */
 129        *status = (*status & 0x3fffffff) | (cmd & 0xc0000000);
 130
 131        return 0;
 132}
 133
 134/**
 135 * ixgbe_bypass_valid_rd_generic - Verify valid return from bit-bang.
 136 *
 137 * If we send a write we can't be sure it took until we can read back
 138 * that same register.  It can be a problem as some of the feilds may
 139 * for valid reasons change between the time wrote the register and
 140 * we read it again to verify.  So this function check everything we
 141 * can check and then assumes it worked.
 142 *
 143 * @u32 in_reg - The register cmd for the bit-bang read.
 144 * @u32 out_reg - The register returned from a bit-bang read.
 145 **/
 146static bool ixgbe_bypass_valid_rd_generic(u32 in_reg, u32 out_reg)
 147{
 148        u32 mask;
 149
 150        /* Page must match for all control pages */
 151        if ((in_reg & BYPASS_PAGE_M) != (out_reg & BYPASS_PAGE_M))
 152                return false;
 153
 154        switch (in_reg & BYPASS_PAGE_M) {
 155        case BYPASS_PAGE_CTL0:
 156                /* All the following can't change since the last write
 157                 *  - All the event actions
 158                 *  - The timeout value
 159                 */
 160                mask = BYPASS_AUX_ON_M | BYPASS_MAIN_ON_M |
 161                       BYPASS_MAIN_OFF_M | BYPASS_AUX_OFF_M |
 162                       BYPASS_WDTIMEOUT_M |
 163                       BYPASS_WDT_VALUE_M;
 164                if ((out_reg & mask) != (in_reg & mask))
 165                        return false;
 166
 167                /* 0x0 is never a valid value for bypass status */
 168                if (!(out_reg & BYPASS_STATUS_OFF_M))
 169                        return false;
 170                break;
 171        case BYPASS_PAGE_CTL1:
 172                /* All the following can't change since the last write
 173                 *  - time valid bit
 174                 *  - time we last sent
 175                 */
 176                mask = BYPASS_CTL1_VALID_M | BYPASS_CTL1_TIME_M;
 177                if ((out_reg & mask) != (in_reg & mask))
 178                        return false;
 179                break;
 180        case BYPASS_PAGE_CTL2:
 181                /* All we can check in this page is control number
 182                 * which is already done above.
 183                 */
 184                break;
 185        }
 186
 187        /* We are as sure as we can be return true */
 188        return true;
 189}
 190
 191/**
 192 *  ixgbe_bypass_set_generic - Set a bypass field in the FW CTRL Regiter.
 193 *
 194 *  @hw: pointer to hardware structure
 195 *  @cmd: The control word we are setting.
 196 *  @event: The event we are setting in the FW.  This also happens to
 197 *          be the mask for the event we are setting (handy)
 198 *  @action: The action we set the event to in the FW. This is in a
 199 *           bit field that happens to be what we want to put in
 200 *           the event spot (also handy)
 201 **/
 202static s32 ixgbe_bypass_set_generic(struct ixgbe_hw *hw, u32 ctrl, u32 event,
 203                             u32 action)
 204{
 205        u32 by_ctl = 0;
 206        u32 cmd, verify;
 207        u32 count = 0;
 208
 209        /* Get current values */
 210        cmd = ctrl;     /* just reading only need control number */
 211        if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
 212                return IXGBE_ERR_INVALID_ARGUMENT;
 213
 214        /* Set to new action */
 215        cmd = (by_ctl & ~event) | BYPASS_WE | action;
 216        if (ixgbe_bypass_rw_generic(hw, cmd, &by_ctl))
 217                return IXGBE_ERR_INVALID_ARGUMENT;
 218
 219        /* Page 0 force a FW eeprom write which is slow so verify */
 220        if ((cmd & BYPASS_PAGE_M) == BYPASS_PAGE_CTL0) {
 221                verify = BYPASS_PAGE_CTL0;
 222                do {
 223                        if (count++ > 5)
 224                                return IXGBE_BYPASS_FW_WRITE_FAILURE;
 225
 226                        if (ixgbe_bypass_rw_generic(hw, verify, &by_ctl))
 227                                return IXGBE_ERR_INVALID_ARGUMENT;
 228                } while (!ixgbe_bypass_valid_rd_generic(cmd, by_ctl));
 229        } else {
 230                /* We have give the FW time for the write to stick */
 231                msleep(100);
 232        }
 233
 234        return 0;
 235}
 236
 237/**
 238 *  ixgbe_bypass_rd_eep_generic - Read the bypass FW eeprom address.
 239 *
 240 *  @hw: pointer to hardware structure
 241 *  @addr: The bypass eeprom address to read.
 242 *  @value: The 8b of data at the address above.
 243 **/
 244static s32 ixgbe_bypass_rd_eep_generic(struct ixgbe_hw *hw, u32 addr, u8 *value)
 245{
 246        u32 cmd;
 247        u32 status;
 248
 249
 250        /* send the request */
 251        cmd = BYPASS_PAGE_CTL2 | BYPASS_WE;
 252        cmd |= (addr << BYPASS_CTL2_OFFSET_SHIFT) & BYPASS_CTL2_OFFSET_M;
 253        if (ixgbe_bypass_rw_generic(hw, cmd, &status))
 254                return IXGBE_ERR_INVALID_ARGUMENT;
 255
 256        /* We have give the FW time for the write to stick */
 257        msleep(100);
 258
 259        /* now read the results */
 260        cmd &= ~BYPASS_WE;
 261        if (ixgbe_bypass_rw_generic(hw, cmd, &status))
 262                return IXGBE_ERR_INVALID_ARGUMENT;
 263
 264        *value = status & BYPASS_CTL2_DATA_M;
 265
 266        return 0;
 267}
 268
 269#endif /* RTE_LIBRTE_IXGBE_BYPASS */
 270
 271#endif /* _IXGBE_BYPASS_API_H_ */
 272