Re: [PATCH] i2c multiplexer driver for Proliant microserver N36L

2012-02-24 Thread Thomas Brandon
Here is the modified patch. As this is my first attempt at submitting
a patch while it obviously isn't ready for inclusion given the errors
any feedback on general style would be welcome.

Tom.

--- linux-3.2.1-gentoo-r2/drivers/i2c/busses/i2c-piix4.c2012-01-05
10:55:44.0 +1100
+++ dev/drivers/i2c/busses/i2c-piix4.c  2012-02-25 04:53:04.743198258 +1100
@@ -25,7 +25,10 @@
AMD Hudson-2
SMSC Victory66

-   Note: we assume there can only be one device, with one SMBus interface.
+   Note: we assume there can only be one device.
+   The device can register multiple i2c_adapters (up to PIIX4_MAX_ADAPTERS).
+   For devices supporting multiple ports the i2c_adapter should provide
+   an i2c_algorithm to access them.
 */

 #include 
@@ -40,6 +43,7 @@
 #include 
 #include 
 #include 
+#include 


 /* PIIX4 SMBus address offsets */
@@ -78,6 +82,9 @@
 #define PIIX4_WORD_DATA0x0C
 #define PIIX4_BLOCK_DATA   0x14

+/* Multi-port constants */
+#define PIIX4_MAX_ADAPTERS 4
+
 /* insmod parameters */

 /* If force is set to anything different from 0, we forcibly enable the
@@ -97,7 +104,15 @@ MODULE_PARM_DESC(force_addr,
 static unsigned short piix4_smba;
 static int srvrworks_csb5_delay;
 static struct pci_driver piix4_driver;
-static struct i2c_adapter piix4_adapter;
+static struct i2c_adapter *piix4_adapters[PIIX4_MAX_ADAPTERS];
+
+/* SB800 globals */
+DEFINE_MUTEX(piix4_mutex_sb800);
+static u8 piix4_adapter_ports_sb800[4];
+static u8 piix4_sel_port_sb800 = -1;
+static const char *piix4_port_names_sb800[4] = {
+   "SDA0", "SDA2", "SDA3", "SDA4"
+};

 static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = {
{
@@ -284,6 +299,8 @@ static int __devinit piix4_setup_sb800(s
else
dev_dbg(&PIIX4_dev->dev, "Using SMI# for SMBus.\n");

+   mutex_init(&piix4_mutex_sb800);
+
dev_info(&PIIX4_dev->dev,
 "SMBus Host Controller at 0x%x, revision %d\n",
 piix4_smba, i2ccfg >> 4);
@@ -291,27 +308,27 @@ static int __devinit piix4_setup_sb800(s
return 0;
 }

-static int piix4_transaction(void)
+static int piix4_transaction(struct i2c_adapter *adap)
 {
int temp;
int result = 0;
int timeout = 0;

-   dev_dbg(&piix4_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
+   dev_dbg(&adap->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
inb_p(SMBHSTDAT1));

/* Make sure the SMBus host is ready to start transmitting */
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
-   dev_dbg(&piix4_adapter.dev, "SMBus busy (%02x). "
+   dev_dbg(&adap->dev, "SMBus busy (%02x). "
"Resetting...\n", temp);
outb_p(temp, SMBHSTSTS);
if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
-   dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
+   dev_err(&adap->dev, "Failed! (%02x)\n", temp);
return -EBUSY;
} else {
-   dev_dbg(&piix4_adapter.dev, "Successful!\n");
+   dev_dbg(&adap->dev, "Successful!\n");
}
}

@@ -330,35 +347,35 @@ static int piix4_transaction(void)

/* If the SMBus is still busy, we give up */
if (timeout == MAX_TIMEOUT) {
-   dev_err(&piix4_adapter.dev, "SMBus Timeout!\n");
+   dev_err(&adap->dev, "SMBus Timeout!\n");
result = -ETIMEDOUT;
}

if (temp & 0x10) {
result = -EIO;
-   dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n");
+   dev_err(&adap->dev, "Error: Failed bus transaction\n");
}

if (temp & 0x08) {
result = -EIO;
-   dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be "
+   dev_dbg(&adap->dev, "Bus collision! SMBus may be "
"locked until next hard reset. (sorry!)\n");
/* Clock stops and slave is stuck in mid-transmission */
}

if (temp & 0x04) {
result = -ENXIO;
-   dev_dbg(&piix4_adapter.dev, "Error: no response!\n");
+   dev_dbg(&adap->dev, "Error: no response!\n");
}

if (inb_p(SMBHSTSTS) != 0x00)
outb_p(inb(SMBHSTSTS), SMBHSTSTS);

if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
-   dev_err(&piix4_adapter.dev, "Failed reset at end of "
+   dev_err(&adap->dev, "Failed reset at end of "
"transaction (%02x)\n", temp);
}
-   dev_dbg(&piix4_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
+   dev_dbg(&adap->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
"ADD=%02x, DAT0=%02x, DAT1=%02x\n", i

Re: [PATCH] i2c multiplexer driver for Proliant microserver N36L

2012-02-24 Thread Thomas Brandon
Jean Delvare  writes:
> You don't need a multiplexer device at all. Please just have i2c-piix4
> driver register 4 i2c_adapter devices for the SB800. This would be a
> 3-step process:
> 
> 1* Turn piix4_adapter to an array, so that it can hold up to 4
>i2c_adapter structures.
> 2* Add a mutex to prevent concurrent access to the register set. It
>should be initialized in piix4_setup_sb800(), taken at the very
>beginning of piix4_access() and released at the very end of this
>function.
> 3* Add support for ports 1, 2 and 3 of the SB800.
> 
> This would ideally be 3 incremental patches to make testing and review
> easy. I can help with parts 1 and 2 if you want, as this can be tested
> without a SB800. But it should be fairly easy overall.
> 
I have reworked the original patch to (hopefully) fit the structure you suggest.
However I have encountered issues with it that I'm not sure how to solve. The
behaviour is the same under both the original and the modified version of the
patch. When running sensors-detect, SDA0 (i2c-0) and SDA2 (i2c-1) (SDA1 is
reserved for ASF devices and accessed through a seperate controller) scan fine
with the following (edited) output:
Next adapter: SMBus piix4 adapter (SDA0) (i2c-0)
Do you want to scan it? (YES/no/selectively): y
Client found at address 0x18
Probing for `Microchip MCP98243'... Success!
(confidence 5, driver `jc42')
Client found at address 0x19
Probing for `Microchip MCP98243'... Success!
(confidence 5, driver `jc42')
Client found at address 0x50
Probing for `SPD EEPROM'... Yes
(confidence 8, not a hardware monitoring chip)
Client found at address 0x51
Probing for `SPD EEPROM'... Yes
(confidence 8, not a hardware monitoring chip)
Next adapter: SMBus piix4 adapter (SDA2) (i2c-1)
Do you want to scan it? (YES/no/selectively): y
Client found at address 0x2f
Probing for `Nuvoton W83795G/ADG'...Success!
(confidence 8, driver `w83795')

However while scanning SDA3 (i2c-2) sensors-detect finds a client at address
0x4c but no probes are successful and you get kernel output like:
i2c i2c-2: Transaction (pre): CNT=04, CMD=00, ADD=99, DAT0=ff, DAT1=01
i2c i2c-2: Transaction (post): CNT=04, CMD=00, ADD=99, DAT0=00, DAT1=01
i2c i2c-2: Transaction (pre): CNT=04, CMD=00, ADD=99, DAT0=00, DAT1=01
i2c i2c-2: Transaction (post): CNT=04, CMD=00, ADD=99, DAT0=00, DAT1=01
[SNIP]
i2c i2c-2: Transaction (pre): CNT=08, CMD=ac, ADD=99, DAT0=00, DAT1=01
i2c i2c-2: Transaction (post): CNT=08, CMD=ac, ADD=99, DAT0=00, DAT1=01
i2c i2c-2: Transaction (pre): CNT=0c, CMD=aa, ADD=99, DAT0=00, DAT1=01
i2c i2c-2: Transaction (pre): CNT=0c, CMD=aa, ADD=99, DAT0=00, DAT1=01
i2c i2c-2: SMBus Timeout!
i2c i2c-2: Bus collision! SMBus may be locked until next hard reset. (sorry!)
i2c i2c-2: Failed reset at end of transaction (01)
i2c i2c-2: Transaction (post): CNT=0c, CMD=aa, ADD=99, DAT0=00, DAT1=80

Then all subsequent access attempts before a hard reset result in output like:
i2c i2c-2: Transaction (pre): CNT=08, CMD=03, ADD=99, DAT0=00, DAT1=80
i2c i2c-2: SMBus busy (01). Resetting...
i2c i2c-2: Failed! (01)

Additionally, shutdown/restart commands now fail, as does using the power button
on the machine (it turns off but on powering back up the screen doesn't return).
The power cord must be removed before the server will restart. This is as
reported by the original submitter and another tester when the thread was posted
on the lm_sensors list
(http://lists.lm-sensors.org/pipermail/lm-sensors/2011-November/034259.html).
After restarting sensors now work as reported by others.

I'm not quite sure how best to proceed. Any tips on debugging/fixing this are
welcome.

Thomas Brandon

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html