The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/ixl/ixl_pf_i2c.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /******************************************************************************
    2 
    3   Copyright (c) 2013-2018, Intel Corporation
    4   All rights reserved.
    5 
    6   Redistribution and use in source and binary forms, with or without
    7   modification, are permitted provided that the following conditions are met:
    8 
    9    1. Redistributions of source code must retain the above copyright notice,
   10       this list of conditions and the following disclaimer.
   11 
   12    2. Redistributions in binary form must reproduce the above copyright
   13       notice, this list of conditions and the following disclaimer in the
   14       documentation and/or other materials provided with the distribution.
   15 
   16    3. Neither the name of the Intel Corporation nor the names of its
   17       contributors may be used to endorse or promote products derived from
   18       this software without specific prior written permission.
   19 
   20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   30   POSSIBILITY OF SUCH DAMAGE.
   31 
   32 ******************************************************************************/
   33 /*$FreeBSD$*/
   34 
   35 #include "ixl_pf.h"
   36 
   37 #define IXL_I2C_T_RISE          1
   38 #define IXL_I2C_T_FALL          1
   39 #define IXL_I2C_T_SU_DATA       1
   40 #define IXL_I2C_T_SU_STA        5
   41 #define IXL_I2C_T_SU_STO        4
   42 #define IXL_I2C_T_HD_STA        4
   43 #define IXL_I2C_T_LOW           5
   44 #define IXL_I2C_T_HIGH          4
   45 #define IXL_I2C_T_BUF           5
   46 #define IXL_I2C_CLOCK_STRETCHING_TIMEOUT 500
   47 
   48 #define IXL_I2C_REG(_hw)        \
   49     I40E_GLGEN_I2CPARAMS(_hw->func_caps.mdio_port_num)
   50 
   51 /* I2C bit-banging functions */
   52 static s32      ixl_set_i2c_data(struct ixl_pf *pf, u32 *i2cctl, bool data);
   53 static bool     ixl_get_i2c_data(struct ixl_pf *pf, u32 *i2cctl);
   54 static void     ixl_raise_i2c_clk(struct ixl_pf *pf, u32 *i2cctl);
   55 static void     ixl_lower_i2c_clk(struct ixl_pf *pf, u32 *i2cctl);
   56 static s32      ixl_clock_out_i2c_bit(struct ixl_pf *pf, bool data);
   57 static s32      ixl_get_i2c_ack(struct ixl_pf *pf);
   58 static s32      ixl_clock_out_i2c_byte(struct ixl_pf *pf, u8 data);
   59 static s32      ixl_clock_in_i2c_bit(struct ixl_pf *pf, bool *data);
   60 static s32      ixl_clock_in_i2c_byte(struct ixl_pf *pf, u8 *data);
   61 static void     ixl_i2c_bus_clear(struct ixl_pf *pf);
   62 static void     ixl_i2c_start(struct ixl_pf *pf);
   63 static void     ixl_i2c_stop(struct ixl_pf *pf);
   64 
   65 static s32      ixl_wait_for_i2c_completion(struct i40e_hw *hw, u8 portnum);
   66 
   67 /**
   68  *  ixl_i2c_bus_clear - Clears the I2C bus
   69  *  @hw: pointer to hardware structure
   70  *
   71  *  Clears the I2C bus by sending nine clock pulses.
   72  *  Used when data line is stuck low.
   73  **/
   74 static void
   75 ixl_i2c_bus_clear(struct ixl_pf *pf)
   76 {
   77         struct i40e_hw *hw = &pf->hw;
   78         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
   79         u32 i;
   80 
   81         DEBUGFUNC("ixl_i2c_bus_clear");
   82 
   83         ixl_i2c_start(pf);
   84 
   85         ixl_set_i2c_data(pf, &i2cctl, 1);
   86 
   87         for (i = 0; i < 9; i++) {
   88                 ixl_raise_i2c_clk(pf, &i2cctl);
   89 
   90                 /* Min high period of clock is 4us */
   91                 i40e_usec_delay(IXL_I2C_T_HIGH);
   92 
   93                 ixl_lower_i2c_clk(pf, &i2cctl);
   94 
   95                 /* Min low period of clock is 4.7us*/
   96                 i40e_usec_delay(IXL_I2C_T_LOW);
   97         }
   98 
   99         ixl_i2c_start(pf);
  100 
  101         /* Put the i2c bus back to default state */
  102         ixl_i2c_stop(pf);
  103 }
  104 
  105 /**
  106  *  ixl_i2c_stop - Sets I2C stop condition
  107  *  @hw: pointer to hardware structure
  108  *
  109  *  Sets I2C stop condition (Low -> High on SDA while SCL is High)
  110  **/
  111 static void
  112 ixl_i2c_stop(struct ixl_pf *pf)
  113 {
  114         struct i40e_hw *hw = &pf->hw;
  115         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  116 
  117         DEBUGFUNC("ixl_i2c_stop");
  118 
  119         /* Stop condition must begin with data low and clock high */
  120         ixl_set_i2c_data(pf, &i2cctl, 0);
  121         ixl_raise_i2c_clk(pf, &i2cctl);
  122 
  123         /* Setup time for stop condition (4us) */
  124         i40e_usec_delay(IXL_I2C_T_SU_STO);
  125 
  126         ixl_set_i2c_data(pf, &i2cctl, 1);
  127 
  128         /* bus free time between stop and start (4.7us)*/
  129         i40e_usec_delay(IXL_I2C_T_BUF);
  130 }
  131 
  132 /**
  133  *  ixl_clock_in_i2c_byte - Clocks in one byte via I2C
  134  *  @hw: pointer to hardware structure
  135  *  @data: data byte to clock in
  136  *
  137  *  Clocks in one byte data via I2C data/clock
  138  **/
  139 static s32
  140 ixl_clock_in_i2c_byte(struct ixl_pf *pf, u8 *data)
  141 {
  142         s32 i;
  143         bool bit = 0;
  144 
  145         DEBUGFUNC("ixl_clock_in_i2c_byte");
  146 
  147         for (i = 7; i >= 0; i--) {
  148                 ixl_clock_in_i2c_bit(pf, &bit);
  149                 *data |= bit << i;
  150         }
  151 
  152         return I40E_SUCCESS;
  153 }
  154 
  155 /**
  156  *  ixl_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
  157  *  @hw: pointer to hardware structure
  158  *  @data: read data value
  159  *
  160  *  Clocks in one bit via I2C data/clock
  161  **/
  162 static s32
  163 ixl_clock_in_i2c_bit(struct ixl_pf *pf, bool *data)
  164 {
  165         struct i40e_hw *hw = &pf->hw;
  166         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  167 
  168         DEBUGFUNC("ixl_clock_in_i2c_bit");
  169 
  170         ixl_raise_i2c_clk(pf, &i2cctl);
  171 
  172         /* Minimum high period of clock is 4us */
  173         i40e_usec_delay(IXL_I2C_T_HIGH);
  174 
  175         i2cctl = rd32(hw, IXL_I2C_REG(hw));
  176         i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK;
  177         wr32(hw, IXL_I2C_REG(hw), i2cctl);
  178         ixl_flush(hw);
  179 
  180         i2cctl = rd32(hw, IXL_I2C_REG(hw));
  181         *data = ixl_get_i2c_data(pf, &i2cctl);
  182 
  183         ixl_lower_i2c_clk(pf, &i2cctl);
  184 
  185         /* Minimum low period of clock is 4.7 us */
  186         i40e_usec_delay(IXL_I2C_T_LOW);
  187 
  188         return I40E_SUCCESS;
  189 }
  190 
  191 /**
  192  *  ixl_get_i2c_ack - Polls for I2C ACK
  193  *  @hw: pointer to hardware structure
  194  *
  195  *  Clocks in/out one bit via I2C data/clock
  196  **/
  197 static s32
  198 ixl_get_i2c_ack(struct ixl_pf *pf)
  199 {
  200         struct i40e_hw *hw = &pf->hw;
  201         s32 status = I40E_SUCCESS;
  202         u32 i = 0;
  203         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  204         u32 timeout = 10;
  205         bool ack = 1;
  206 
  207         ixl_raise_i2c_clk(pf, &i2cctl);
  208 
  209         /* Minimum high period of clock is 4us */
  210         i40e_usec_delay(IXL_I2C_T_HIGH);
  211 
  212         i2cctl = rd32(hw, IXL_I2C_REG(hw));
  213         i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK;
  214         wr32(hw, IXL_I2C_REG(hw), i2cctl);
  215         ixl_flush(hw);
  216 
  217         /* Poll for ACK.  Note that ACK in I2C spec is
  218          * transition from 1 to 0 */
  219         for (i = 0; i < timeout; i++) {
  220                 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  221                 ack = ixl_get_i2c_data(pf, &i2cctl);
  222 
  223                 i40e_usec_delay(1);
  224                 if (!ack)
  225                         break;
  226         }
  227 
  228         if (ack) {
  229                 ixl_dbg(pf, IXL_DBG_I2C, "I2C ack was not received.\n");
  230                 status = I40E_ERR_PHY;
  231         }
  232 
  233         ixl_lower_i2c_clk(pf, &i2cctl);
  234 
  235         /* Minimum low period of clock is 4.7 us */
  236         i40e_usec_delay(IXL_I2C_T_LOW);
  237 
  238         return status;
  239 }
  240 
  241 /**
  242  *  ixl_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
  243  *  @hw: pointer to hardware structure
  244  *  @data: data value to write
  245  *
  246  *  Clocks out one bit via I2C data/clock
  247  **/
  248 static s32
  249 ixl_clock_out_i2c_bit(struct ixl_pf *pf, bool data)
  250 {
  251         struct i40e_hw *hw = &pf->hw;
  252         s32 status;
  253         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  254 
  255         status = ixl_set_i2c_data(pf, &i2cctl, data);
  256         if (status == I40E_SUCCESS) {
  257                 ixl_raise_i2c_clk(pf, &i2cctl);
  258 
  259                 /* Minimum high period of clock is 4us */
  260                 i40e_usec_delay(IXL_I2C_T_HIGH);
  261 
  262                 ixl_lower_i2c_clk(pf, &i2cctl);
  263 
  264                 /* Minimum low period of clock is 4.7 us.
  265                  * This also takes care of the data hold time.
  266                  */
  267                 i40e_usec_delay(IXL_I2C_T_LOW);
  268         } else {
  269                 status = I40E_ERR_PHY;
  270                 ixl_dbg(pf, IXL_DBG_I2C, "I2C data was not set to %#x\n", data);
  271         }
  272 
  273         return status;
  274 }
  275 
  276 /**
  277  *  ixl_clock_out_i2c_byte - Clocks out one byte via I2C
  278  *  @hw: pointer to hardware structure
  279  *  @data: data byte clocked out
  280  *
  281  *  Clocks out one byte data via I2C data/clock
  282  **/
  283 static s32
  284 ixl_clock_out_i2c_byte(struct ixl_pf *pf, u8 data)
  285 {
  286         struct i40e_hw *hw = &pf->hw;
  287         s32 status = I40E_SUCCESS;
  288         s32 i;
  289         u32 i2cctl;
  290         bool bit;
  291 
  292         DEBUGFUNC("ixl_clock_out_i2c_byte");
  293 
  294         for (i = 7; i >= 0; i--) {
  295                 bit = (data >> i) & 0x1;
  296                 status = ixl_clock_out_i2c_bit(pf, bit);
  297 
  298                 if (status != I40E_SUCCESS)
  299                         break;
  300         }
  301 
  302         /* Release SDA line (set high) */
  303         i2cctl = rd32(hw, IXL_I2C_REG(hw));
  304         i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK;
  305         i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK);
  306         wr32(hw, IXL_I2C_REG(hw), i2cctl);
  307         ixl_flush(hw);
  308 
  309         return status;
  310 }
  311 
  312 /**
  313  *  ixl_lower_i2c_clk - Lowers the I2C SCL clock
  314  *  @hw: pointer to hardware structure
  315  *  @i2cctl: Current value of I2CCTL register
  316  *
  317  *  Lowers the I2C clock line '1'->''
  318  **/
  319 static void
  320 ixl_lower_i2c_clk(struct ixl_pf *pf, u32 *i2cctl)
  321 {
  322         struct i40e_hw *hw = &pf->hw;
  323 
  324         *i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_MASK);
  325         *i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK);
  326 
  327         wr32(hw, IXL_I2C_REG(hw), *i2cctl);
  328         ixl_flush(hw);
  329 
  330         /* SCL fall time (300ns) */
  331         i40e_usec_delay(IXL_I2C_T_FALL);
  332 }
  333 
  334 /**
  335  *  ixl_raise_i2c_clk - Raises the I2C SCL clock
  336  *  @hw: pointer to hardware structure
  337  *  @i2cctl: Current value of I2CCTL register
  338  *
  339  *  Raises the I2C clock line ''->'1'
  340  **/
  341 static void
  342 ixl_raise_i2c_clk(struct ixl_pf *pf, u32 *i2cctl)
  343 {
  344         struct i40e_hw *hw = &pf->hw;
  345         u32 i = 0;
  346         u32 timeout = IXL_I2C_CLOCK_STRETCHING_TIMEOUT;
  347         u32 i2cctl_r = 0;
  348 
  349         for (i = 0; i < timeout; i++) {
  350                 *i2cctl |= I40E_GLGEN_I2CPARAMS_CLK_MASK;
  351                 *i2cctl &= ~(I40E_GLGEN_I2CPARAMS_CLK_OE_N_MASK);
  352 
  353                 wr32(hw, IXL_I2C_REG(hw), *i2cctl);
  354                 ixl_flush(hw);
  355                 /* SCL rise time (1000ns) */
  356                 i40e_usec_delay(IXL_I2C_T_RISE);
  357 
  358                 i2cctl_r = rd32(hw, IXL_I2C_REG(hw));
  359                 if (i2cctl_r & I40E_GLGEN_I2CPARAMS_CLK_IN_MASK)
  360                         break;
  361         }
  362 }
  363 
  364 /**
  365  *  ixl_get_i2c_data - Reads the I2C SDA data bit
  366  *  @hw: pointer to hardware structure
  367  *  @i2cctl: Current value of I2CCTL register
  368  *
  369  *  Returns the I2C data bit value
  370  **/
  371 static bool
  372 ixl_get_i2c_data(struct ixl_pf *pf, u32 *i2cctl)
  373 {
  374         bool data;
  375 
  376         if (*i2cctl & I40E_GLGEN_I2CPARAMS_DATA_IN_MASK)
  377                 data = 1;
  378         else
  379                 data = 0;
  380 
  381         return data;
  382 }
  383 
  384 /**
  385  *  ixl_set_i2c_data - Sets the I2C data bit
  386  *  @hw: pointer to hardware structure
  387  *  @i2cctl: Current value of I2CCTL register
  388  *  @data: I2C data value (0 or 1) to set
  389  *
  390  *  Sets the I2C data bit
  391  **/
  392 static s32
  393 ixl_set_i2c_data(struct ixl_pf *pf, u32 *i2cctl, bool data)
  394 {
  395         struct i40e_hw *hw = &pf->hw;
  396         s32 status = I40E_SUCCESS;
  397 
  398         DEBUGFUNC("ixl_set_i2c_data");
  399 
  400         if (data)
  401                 *i2cctl |= I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK;
  402         else
  403                 *i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OUT_MASK);
  404         *i2cctl &= ~(I40E_GLGEN_I2CPARAMS_DATA_OE_N_MASK);
  405 
  406         wr32(hw, IXL_I2C_REG(hw), *i2cctl);
  407         ixl_flush(hw);
  408 
  409         /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
  410         i40e_usec_delay(IXL_I2C_T_RISE + IXL_I2C_T_FALL + IXL_I2C_T_SU_DATA);
  411 
  412         /* Verify data was set correctly */
  413         *i2cctl = rd32(hw, IXL_I2C_REG(hw));
  414         if (data != ixl_get_i2c_data(pf, i2cctl)) {
  415                 status = I40E_ERR_PHY;
  416                 ixl_dbg(pf, IXL_DBG_I2C, "Error - I2C data was not set to %X.\n", data);
  417         }
  418 
  419         return status;
  420 }
  421 
  422 /**
  423  *  ixl_i2c_start - Sets I2C start condition
  424  *  Sets I2C start condition (High -> Low on SDA while SCL is High)
  425  **/
  426 static void
  427 ixl_i2c_start(struct ixl_pf *pf)
  428 {
  429         struct i40e_hw *hw = &pf->hw;
  430         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  431 
  432         DEBUGFUNC("ixl_i2c_start");
  433 
  434         /* Start condition must begin with data and clock high */
  435         ixl_set_i2c_data(pf, &i2cctl, 1);
  436         ixl_raise_i2c_clk(pf, &i2cctl);
  437 
  438         /* Setup time for start condition (4.7us) */
  439         i40e_usec_delay(IXL_I2C_T_SU_STA);
  440 
  441         ixl_set_i2c_data(pf, &i2cctl, 0);
  442 
  443         /* Hold time for start condition (4us) */
  444         i40e_usec_delay(IXL_I2C_T_HD_STA);
  445 
  446         ixl_lower_i2c_clk(pf, &i2cctl);
  447 
  448         /* Minimum low period of clock is 4.7 us */
  449         i40e_usec_delay(IXL_I2C_T_LOW);
  450 
  451 }
  452 
  453 /**
  454  *  ixl_read_i2c_byte_bb - Reads 8 bit word over I2C
  455  **/
  456 s32
  457 ixl_read_i2c_byte_bb(struct ixl_pf *pf, u8 byte_offset,
  458                   u8 dev_addr, u8 *data)
  459 {
  460         struct i40e_hw *hw = &pf->hw;
  461         u32 max_retry = 10;
  462         u32 retry = 0;
  463         bool nack = 1;
  464         s32 status;
  465         *data = 0;
  466 
  467         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  468         i2cctl |= I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
  469         wr32(hw, IXL_I2C_REG(hw), i2cctl);
  470         ixl_flush(hw);
  471 
  472         do {
  473                 ixl_i2c_start(pf);
  474 
  475                 /* Device Address and write indication */
  476                 status = ixl_clock_out_i2c_byte(pf, dev_addr);
  477                 if (status != I40E_SUCCESS) {
  478                         ixl_dbg(pf, IXL_DBG_I2C, "dev_addr clock out error\n");
  479                         goto fail;
  480                 }
  481 
  482                 status = ixl_get_i2c_ack(pf);
  483                 if (status != I40E_SUCCESS) {
  484                         ixl_dbg(pf, IXL_DBG_I2C, "dev_addr i2c ack error\n");
  485                         goto fail;
  486                 }
  487 
  488                 status = ixl_clock_out_i2c_byte(pf, byte_offset);
  489                 if (status != I40E_SUCCESS) {
  490                         ixl_dbg(pf, IXL_DBG_I2C, "byte_offset clock out error\n");
  491                         goto fail;
  492                 }
  493 
  494                 status = ixl_get_i2c_ack(pf);
  495                 if (status != I40E_SUCCESS) {
  496                         ixl_dbg(pf, IXL_DBG_I2C, "byte_offset i2c ack error\n");
  497                         goto fail;
  498                 }
  499 
  500                 ixl_i2c_start(pf);
  501 
  502                 /* Device Address and read indication */
  503                 status = ixl_clock_out_i2c_byte(pf, (dev_addr | 0x1));
  504                 if (status != I40E_SUCCESS)
  505                         goto fail;
  506 
  507                 status = ixl_get_i2c_ack(pf);
  508                 if (status != I40E_SUCCESS)
  509                         goto fail;
  510 
  511                 status = ixl_clock_in_i2c_byte(pf, data);
  512                 if (status != I40E_SUCCESS)
  513                         goto fail;
  514 
  515                 status = ixl_clock_out_i2c_bit(pf, nack);
  516                 if (status != I40E_SUCCESS)
  517                         goto fail;
  518 
  519                 ixl_i2c_stop(pf);
  520                 status = I40E_SUCCESS;
  521                 goto done;
  522 
  523 fail:
  524                 ixl_i2c_bus_clear(pf);
  525                 i40e_msec_delay(100);
  526                 retry++;
  527                 if (retry < max_retry)
  528                         ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error - Retrying\n");
  529                 else
  530                         ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error\n");
  531 
  532         } while (retry < max_retry);
  533 done:
  534         i2cctl = rd32(hw, IXL_I2C_REG(hw));
  535         i2cctl &= ~I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
  536         wr32(hw, IXL_I2C_REG(hw), i2cctl);
  537         ixl_flush(hw);
  538 
  539         return status;
  540 }
  541 
  542 /**
  543  *  ixl_write_i2c_byte_bb - Writes 8 bit word over I2C
  544  **/
  545 s32
  546 ixl_write_i2c_byte_bb(struct ixl_pf *pf, u8 byte_offset,
  547                        u8 dev_addr, u8 data)
  548 {
  549         struct i40e_hw *hw = &pf->hw;
  550         s32 status = I40E_SUCCESS;
  551         u32 max_retry = 1;
  552         u32 retry = 0;
  553 
  554         u32 i2cctl = rd32(hw, IXL_I2C_REG(hw));
  555         i2cctl |= I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
  556         wr32(hw, IXL_I2C_REG(hw), i2cctl);
  557         ixl_flush(hw);
  558 
  559         do {
  560                 ixl_i2c_start(pf);
  561 
  562                 status = ixl_clock_out_i2c_byte(pf, dev_addr);
  563                 if (status != I40E_SUCCESS)
  564                         goto fail;
  565 
  566                 status = ixl_get_i2c_ack(pf);
  567                 if (status != I40E_SUCCESS)
  568                         goto fail;
  569 
  570                 status = ixl_clock_out_i2c_byte(pf, byte_offset);
  571                 if (status != I40E_SUCCESS)
  572                         goto fail;
  573 
  574                 status = ixl_get_i2c_ack(pf);
  575                 if (status != I40E_SUCCESS)
  576                         goto fail;
  577 
  578                 status = ixl_clock_out_i2c_byte(pf, data);
  579                 if (status != I40E_SUCCESS)
  580                         goto fail;
  581 
  582                 status = ixl_get_i2c_ack(pf);
  583                 if (status != I40E_SUCCESS)
  584                         goto fail;
  585 
  586                 ixl_i2c_stop(pf);
  587                 goto write_byte_out;
  588 
  589 fail:
  590                 ixl_i2c_bus_clear(pf);
  591                 i40e_msec_delay(100);
  592                 retry++;
  593                 if (retry < max_retry)
  594                         ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error - Retrying\n");
  595                 else
  596                         ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error\n");
  597         } while (retry < max_retry);
  598 
  599 write_byte_out:
  600         i2cctl = rd32(hw, IXL_I2C_REG(hw));
  601         i2cctl &= ~I40E_GLGEN_I2CPARAMS_I2CBB_EN_MASK;
  602         wr32(hw, IXL_I2C_REG(hw), i2cctl);
  603         ixl_flush(hw);
  604 
  605         return status;
  606 }
  607 
  608 /**
  609  *  ixl_read_i2c_byte_reg - Reads 8 bit word over I2C using a hardware register
  610  **/
  611 s32
  612 ixl_read_i2c_byte_reg(struct ixl_pf *pf, u8 byte_offset,
  613                   u8 dev_addr, u8 *data)
  614 {
  615         struct i40e_hw *hw = &pf->hw;
  616         u32 reg = 0;
  617         s32 status;
  618         *data = 0;
  619 
  620         reg |= (byte_offset << I40E_GLGEN_I2CCMD_REGADD_SHIFT);
  621         reg |= (((dev_addr >> 1) & 0x7) << I40E_GLGEN_I2CCMD_PHYADD_SHIFT);
  622         reg |= I40E_GLGEN_I2CCMD_OP_MASK;
  623         wr32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num), reg);
  624 
  625         status = ixl_wait_for_i2c_completion(hw, hw->func_caps.mdio_port_num);
  626 
  627         /* Get data from I2C register */
  628         reg = rd32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num));
  629 
  630         /* Retrieve data read from EEPROM */
  631         *data = (u8)(reg & 0xff);
  632 
  633         if (status)
  634                 ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read error\n");
  635         return status;
  636 }
  637 
  638 /**
  639  *  ixl_write_i2c_byte_reg - Writes 8 bit word over I2C using a hardware register
  640  **/
  641 s32
  642 ixl_write_i2c_byte_reg(struct ixl_pf *pf, u8 byte_offset,
  643                        u8 dev_addr, u8 data)
  644 {
  645         struct i40e_hw *hw = &pf->hw;
  646         s32 status = I40E_SUCCESS;
  647         u32 reg = 0;
  648         u8 upperbyte = 0;
  649         u16 datai2c = 0;
  650 
  651         status = ixl_read_i2c_byte_reg(pf, byte_offset + 1, dev_addr, &upperbyte);
  652         datai2c = ((u16)upperbyte << 8) | (u16)data;
  653         reg = rd32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num));
  654 
  655         /* Form write command */
  656         reg &= ~I40E_GLGEN_I2CCMD_PHYADD_MASK;
  657         reg |= (((dev_addr >> 1) & 0x7) << I40E_GLGEN_I2CCMD_PHYADD_SHIFT);
  658         reg &= ~I40E_GLGEN_I2CCMD_REGADD_MASK;
  659         reg |= (byte_offset << I40E_GLGEN_I2CCMD_REGADD_SHIFT);
  660         reg &= ~I40E_GLGEN_I2CCMD_DATA_MASK;
  661         reg |= (datai2c << I40E_GLGEN_I2CCMD_DATA_SHIFT);
  662         reg &= ~I40E_GLGEN_I2CCMD_OP_MASK;
  663 
  664         /* Write command to registers controlling I2C - data and address. */
  665         wr32(hw, I40E_GLGEN_I2CCMD(hw->func_caps.mdio_port_num), reg);
  666 
  667         status = ixl_wait_for_i2c_completion(hw, hw->func_caps.mdio_port_num);
  668 
  669         if (status)
  670                 ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write error\n");
  671         return status;
  672 }
  673 
  674 /**
  675  *  ixl_wait_for_i2c_completion
  676  **/
  677 static s32
  678 ixl_wait_for_i2c_completion(struct i40e_hw *hw, u8 portnum)
  679 {
  680         s32 status = 0;
  681         u32 timeout = 100;
  682         u32 reg;
  683         do {
  684                 reg = rd32(hw, I40E_GLGEN_I2CCMD(portnum));
  685                 if ((reg & I40E_GLGEN_I2CCMD_R_MASK) != 0)
  686                         break;
  687                 i40e_usec_delay(10);
  688         } while (timeout-- > 0);
  689 
  690         if (timeout == 0)
  691                 return I40E_ERR_TIMEOUT;
  692         else
  693                 return status;
  694 }
  695 
  696 /**
  697  *  ixl_read_i2c_byte_aq - Reads 8 bit word over I2C using an AQ command
  698  **/
  699 s32
  700 ixl_read_i2c_byte_aq(struct ixl_pf *pf, u8 byte_offset,
  701                   u8 dev_addr, u8 *data)
  702 {
  703         struct i40e_hw *hw = &pf->hw;
  704         s32 status = I40E_SUCCESS;
  705         u32 reg;
  706 
  707         status = i40e_aq_get_phy_register(hw,
  708                                         I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
  709                                         dev_addr, false,
  710                                         byte_offset,
  711                                         &reg, NULL);
  712 
  713         if (status)
  714                 ixl_dbg(pf, IXL_DBG_I2C, "I2C byte read status %s, error %s\n",
  715                     i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
  716         else
  717                 *data = (u8)reg;
  718 
  719         return status;
  720 }
  721 
  722 /**
  723  *  ixl_write_i2c_byte_aq - Writes 8 bit word over I2C using an AQ command
  724  **/
  725 s32
  726 ixl_write_i2c_byte_aq(struct ixl_pf *pf, u8 byte_offset,
  727                        u8 dev_addr, u8 data)
  728 {
  729         struct i40e_hw *hw = &pf->hw;
  730         s32 status = I40E_SUCCESS;
  731 
  732         status = i40e_aq_set_phy_register(hw,
  733                                         I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE,
  734                                         dev_addr, false,
  735                                         byte_offset,
  736                                         data, NULL);
  737 
  738         if (status)
  739                 ixl_dbg(pf, IXL_DBG_I2C, "I2C byte write status %s, error %s\n",
  740                     i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status));
  741 
  742         return status;
  743 }

Cache object: 0437f44e6641e393fdbb43675d4b8a1f


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.