From: Tony Nguyen <anthony.l.nguyen@intel.com>
To: davem@davemloft.net, kuba@kernel.org
Cc: "Jan Kundrát" <jan.kundrat@cesnet.cz>,
netdev@vger.kernel.org, anthony.l.nguyen@intel.com,
"Jesse Brandeburg" <jesse.brandeburg@intel.com>,
"Tony Brelinski" <tony.brelinski@intel.com>
Subject: [PATCH net-next 3/4] igb: unbreak I2C bit-banging on i350
Date: Mon, 25 Oct 2021 10:55:07 -0700 [thread overview]
Message-ID: <20211025175508.1461435-4-anthony.l.nguyen@intel.com> (raw)
In-Reply-To: <20211025175508.1461435-1-anthony.l.nguyen@intel.com>
From: Jan Kundrát <jan.kundrat@cesnet.cz>
The driver tried to use Linux' native software I2C bus master
(i2c-algo-bits) for exporting the I2C interface that talks to the SFP
cage(s) towards userspace. As-is, however, the physical SCL/SDA pins
were not moving at all, staying at logical 1 all the time.
The main culprit was the I2CPARAMS register where igb was not setting
the I2CBB_EN bit. That meant that all the careful signal bit-banging was
actually not being propagated to the chip pads (I verified this with a
scope).
The bit-banging was not correct either, because I2C is supposed to be an
open-collector bus, and the code was driving both lines via a totem
pole. The code was also trying to do operations which did not make any
sense with the i2c-algo-bits, namely manipulating both SDA and SCL from
igb_set_i2c_data (which is only supposed to set SDA). I'm not sure if
that was meant as an optimization, or was just flat out wrong, but given
that the i2c-algo-bits is set up to work with a totally dumb GPIO-ish
implementation underneath, there's no need for this code to be smart.
The open-drain vs. totem-pole is fixed by the usual trick where the
logical zero is implemented via regular output mode and outputting a
logical 0, and the logical high is implemented via the IO pad configured
as an input (thus floating), and letting the mandatory pull-up resistors
do the rest. Anything else is actually wrong on I2C where all devices
are supposed to have open-drain connection to the bus.
The missing I2CBB_EN is set (along with a safe initial value of the
GPIOs) just before registering this software I2C bus.
The chip datasheet mentions HW-implemented I2C transactions (SFP EEPROM
reads and writes) as well, but I'm not touching these for simplicity.
Tested on a LR-Link LRES2203PF-2SFP (which is an almost-miniPCIe form
factor card, a cable, and a module with two SFP cages). There was one
casualty, an old broken SFP we had laying around, which was used to
solder some thin wires as a DIY I2C breakout. Thanks for your service.
With this patch in place, I can `i2cdump -y 3 0x51 c` and read back data
which make sense. Yay.
Signed-off-by: Jan Kundrát <jan.kundrat@cesnet.cz>
See-also: https://www.spinics.net/lists/netdev/msg490554.html
Reviewed-by: Jesse Brandeburg <jesse.brandeburg@intel.com>
Tested-by: Tony Brelinski <tony.brelinski@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
---
drivers/net/ethernet/intel/igb/igb_main.c | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index e67a71c3f141..836be0d3b291 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -577,16 +577,15 @@ static void igb_set_i2c_data(void *data, int state)
struct e1000_hw *hw = &adapter->hw;
s32 i2cctl = rd32(E1000_I2CPARAMS);
- if (state)
- i2cctl |= E1000_I2C_DATA_OUT;
- else
+ if (state) {
+ i2cctl |= E1000_I2C_DATA_OUT | E1000_I2C_DATA_OE_N;
+ } else {
+ i2cctl &= ~E1000_I2C_DATA_OE_N;
i2cctl &= ~E1000_I2C_DATA_OUT;
+ }
- i2cctl &= ~E1000_I2C_DATA_OE_N;
- i2cctl |= E1000_I2C_CLK_OE_N;
wr32(E1000_I2CPARAMS, i2cctl);
wrfl();
-
}
/**
@@ -603,8 +602,7 @@ static void igb_set_i2c_clk(void *data, int state)
s32 i2cctl = rd32(E1000_I2CPARAMS);
if (state) {
- i2cctl |= E1000_I2C_CLK_OUT;
- i2cctl &= ~E1000_I2C_CLK_OE_N;
+ i2cctl |= E1000_I2C_CLK_OUT | E1000_I2C_CLK_OE_N;
} else {
i2cctl &= ~E1000_I2C_CLK_OUT;
i2cctl &= ~E1000_I2C_CLK_OE_N;
@@ -3116,12 +3114,21 @@ static void igb_init_mas(struct igb_adapter *adapter)
**/
static s32 igb_init_i2c(struct igb_adapter *adapter)
{
+ struct e1000_hw *hw = &adapter->hw;
s32 status = 0;
+ s32 i2cctl;
/* I2C interface supported on i350 devices */
if (adapter->hw.mac.type != e1000_i350)
return 0;
+ i2cctl = rd32(E1000_I2CPARAMS);
+ i2cctl |= E1000_I2CBB_EN
+ | E1000_I2C_CLK_OUT | E1000_I2C_CLK_OE_N
+ | E1000_I2C_DATA_OUT | E1000_I2C_DATA_OE_N;
+ wr32(E1000_I2CPARAMS, i2cctl);
+ wrfl();
+
/* Initialize the i2c bus which is controlled by the registers.
* This bus will use the i2c_algo_bit structure that implements
* the protocol through toggling of the 4 bits in the register.
--
2.31.1
next prev parent reply other threads:[~2021-10-25 17:56 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-10-25 17:55 [PATCH net-next 0/4][pull request] 40GbE Intel Wired LAN Driver Updates 2021-10-25 Tony Nguyen
2021-10-25 17:55 ` [PATCH net-next 1/4] i40e: avoid spin loop in i40e_asq_send_command() Tony Nguyen
2021-10-27 16:01 ` Jakub Kicinski
2021-10-28 11:49 ` Jörn Engel
2021-10-28 14:26 ` Jakub Kicinski
2021-10-28 14:44 ` Jörn Engel
2021-11-01 17:38 ` [PATCH v2] " Caleb Sander
2021-10-25 17:55 ` [PATCH net-next 2/4] intel: Simplify bool conversion Tony Nguyen
2021-10-25 17:55 ` Tony Nguyen [this message]
2021-10-27 16:30 ` [PATCH net-next 3/4] igb: unbreak I2C bit-banging on i350 Jakub Kicinski
2021-10-28 15:25 ` Nguyen, Anthony L
2021-10-28 15:32 ` Jakub Kicinski
2021-10-25 17:55 ` [PATCH net-next 4/4] net: ixgbevf: Remove redundant initialization of variable ret_val Tony Nguyen
2021-10-27 15:51 ` [PATCH net-next 0/4][pull request] 40GbE Intel Wired LAN Driver Updates 2021-10-25 Nguyen, Anthony L
2021-10-27 15:59 ` Jakub Kicinski
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20211025175508.1461435-4-anthony.l.nguyen@intel.com \
--to=anthony.l.nguyen@intel.com \
--cc=davem@davemloft.net \
--cc=jan.kundrat@cesnet.cz \
--cc=jesse.brandeburg@intel.com \
--cc=kuba@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=tony.brelinski@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).