diff mbox

[v3,1/4] i2c: Add DIMM bus code

Message ID b8e50b55358b4f0cd1db96174a9e6a2e69780359.1374093761.git.luto@amacapital.net
State Superseded
Headers show

Commit Message

Andy Lutomirski July 17, 2013, 8:53 p.m. UTC
Add i2c_scan_dimm_bus to declare that a particular i2c_adapter
contains DIMMs.  This will probe (and autoload modules!) for useful
SMBUS devices that live on DIMMs.

As more SMBUS-addressable DIMM components become supported, this
code can be extended to probe for them.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 drivers/i2c/busses/Kconfig    |  4 +++
 drivers/i2c/busses/Makefile   |  4 +++
 drivers/i2c/busses/dimm-bus.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 include/linux/i2c/dimm-bus.h  | 24 +++++++++++++
 4 files changed, 116 insertions(+)
 create mode 100644 drivers/i2c/busses/dimm-bus.c
 create mode 100644 include/linux/i2c/dimm-bus.h

Comments

Guenter Roeck July 17, 2013, 10:23 p.m. UTC | #1
On Wed, Jul 17, 2013 at 01:53:05PM -0700, Andy Lutomirski wrote:
> Add i2c_scan_dimm_bus to declare that a particular i2c_adapter
> contains DIMMs.  This will probe (and autoload modules!) for useful
> SMBUS devices that live on DIMMs.
> 
> As more SMBUS-addressable DIMM components become supported, this
> code can be extended to probe for them.
> 
I don't think this code is necessary. The temperature sensor would be
auto-detected if you mark the bus driver as I2C_CLASS_HWMON, and DIM eeprom
auto-detection should not be needed.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andy Lutomirski July 17, 2013, 11:04 p.m. UTC | #2
On Wed, Jul 17, 2013 at 3:23 PM, Guenter Roeck <linux@roeck-us.net> wrote:
> On Wed, Jul 17, 2013 at 01:53:05PM -0700, Andy Lutomirski wrote:
>> Add i2c_scan_dimm_bus to declare that a particular i2c_adapter
>> contains DIMMs.  This will probe (and autoload modules!) for useful
>> SMBUS devices that live on DIMMs.
>>
>> As more SMBUS-addressable DIMM components become supported, this
>> code can be extended to probe for them.
>>
> I don't think this code is necessary. The temperature sensor would be
> auto-detected if you mark the bus driver as I2C_CLASS_HWMON, and DIM eeprom
> auto-detection should not be needed.

I'm not at all sure I want to mark this thing I2C_CLASS_HWMON.  I
don't want random hwmon drivers probing the bus.  (Although I wouldn't
need to -- jc42 is looking for I2C_CLASS_SPD.)

Also, my code is IMO better than the i2c core probing code for several reasons:

 - i2c_imc is incompatible with the i2c core class-based detection
code because it can't do a read byte operation.  I believe that,
because of exactly this limitation, devices soldered onto DIMMs are
unlikely to ever require this operation.  (LGA2011 is the premier
platform for interesting DIMM-like devices right now.)  So I'd have to
modify the i2c core with more nasty hard-coded lists of what can be
safely probed how, and ISTM that kind of thing is better handled in
code that runs on busses that are really known to contain DIMMs (and
not, say, i2c-gpio).

 - The eventual goal is to write a driver for NVDIMMs, which will also
appear on this bus, and I want them to pull in the right drivers via
modalias and udev, which the i2c core code can't do.  To do this well,
I'll want the SMBUS driver to pass in (via platform-data) information
on which DIMM channel is which, and I don't know any way to do
anything like that without using i2c_new_device.

 - Busses like i2c_i801 may or may not contain DIMMs.  They do on some
machines I have.  But on my Core i7 Extreme box, there are no DIMMs on
that bus, and there are no SPDs on that bus (i.e. addresses 0x50
through 0x57 don't answer), but there is an unknown device at address
0x19.  I don't really want to think about whether it's safe to probe
by, say, read_word_data(0).  When NVDIMMs show up, even more bizarre
addresses may be populated.  My code can probe *carefully* by looking
for SPDs first, whereas the i2c-core code is not nearly as careful.

One option would be to move code like this into the core and replace
I2C_CLASS_SPD with something like it.  That way everything could get
the benefit of DIMM-specific probing.

--Andy
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Andy Lutomirski July 18, 2013, 12:57 a.m. UTC | #3
Some thoughts on an alternative solution below:

On Wed, Jul 17, 2013 at 4:04 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> On Wed, Jul 17, 2013 at 3:23 PM, Guenter Roeck <linux@roeck-us.net> wrote:
>> On Wed, Jul 17, 2013 at 01:53:05PM -0700, Andy Lutomirski wrote:
>>> Add i2c_scan_dimm_bus to declare that a particular i2c_adapter
>>> contains DIMMs.  This will probe (and autoload modules!) for useful
>>> SMBUS devices that live on DIMMs.
>>>
>>> As more SMBUS-addressable DIMM components become supported, this
>>> code can be extended to probe for them.
>>>
>> I don't think this code is necessary. The temperature sensor would be
>> auto-detected if you mark the bus driver as I2C_CLASS_HWMON, and DIM eeprom
>> auto-detection should not be needed.
>
> I'm not at all sure I want to mark this thing I2C_CLASS_HWMON.  I
> don't want random hwmon drivers probing the bus.  (Although I wouldn't
> need to -- jc42 is looking for I2C_CLASS_SPD.)
>
> Also, my code is IMO better than the i2c core probing code for several reasons:
>
>  - i2c_imc is incompatible with the i2c core class-based detection
> code because it can't do a read byte operation.  I believe that,
> because of exactly this limitation, devices soldered onto DIMMs are
> unlikely to ever require this operation.  (LGA2011 is the premier
> platform for interesting DIMM-like devices right now.)  So I'd have to
> modify the i2c core with more nasty hard-coded lists of what can be
> safely probed how, and ISTM that kind of thing is better handled in
> code that runs on busses that are really known to contain DIMMs (and
> not, say, i2c-gpio).
>
>  - The eventual goal is to write a driver for NVDIMMs, which will also
> appear on this bus, and I want them to pull in the right drivers via
> modalias and udev, which the i2c core code can't do.  To do this well,
> I'll want the SMBUS driver to pass in (via platform-data) information
> on which DIMM channel is which, and I don't know any way to do
> anything like that without using i2c_new_device.

Perhaps i2c_adapter could have a new field for this purpose.  For DIMM
busses it could store topology information.  Then any clients
instantiated on the bus could read it to figure out where they are.

>
>  - Busses like i2c_i801 may or may not contain DIMMs.  They do on some
> machines I have.  But on my Core i7 Extreme box, there are no DIMMs on
> that bus, and there are no SPDs on that bus (i.e. addresses 0x50
> through 0x57 don't answer), but there is an unknown device at address
> 0x19.  I don't really want to think about whether it's safe to probe
> by, say, read_word_data(0).  When NVDIMMs show up, even more bizarre
> addresses may be populated.  My code can probe *carefully* by looking
> for SPDs first, whereas the i2c-core code is not nearly as careful.
>
> One option would be to move code like this into the core and replace
> I2C_CLASS_SPD with something like it.  That way everything could get
> the benefit of DIMM-specific probing.

What if the core code got a little smarter than just matching
arbitrary bits in the class?  For example, if the adapter is
I2C_CLASS_SPD, then the core could look for eeproms (and optionally
instantiate them itself instead of relying on the eeprom driver being
loaded).  Or, more generally, adapters could have a list of named
classes, and there could be a module or something for each class that
knows how to probe and instantiate devices of that class.  So the
class "nvdimm" could instantiate whatever it needs to instantiate, the
class "tsod" could instantiate jc42 instances, etc.  (I'm pretty sure
I'll eventually want nvdimm to be autoloaded, it may want to depend on
the eeprom driver somehow in case I need to read the SPD data -- I'm
not sure yet.)

I guess the logic of "probe 0x50, then, if there's an eeprom there,
probe 0x18 for jc42" isn't perfect.  For example, lm90 can live at
0x18 or 0x19, and if there are DIMMs on the same segment as an lm90,
then it's possible for a jc42 and an lm90 to collide.  So if my bus
were I2C_CLASS_SPD | I2C_CLASS_DIMM, then perhaps the jc42 (and core)
code could probe more aggressively.

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

Patch

diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index adfee98..e837f0e 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -133,6 +133,10 @@  config I2C_ISMT
 	  This driver can also be built as a module.  If so, the module will be
 	  called i2c-ismt.
 
+config I2C_DIMM_BUS
+       tristate
+       default n
+
 config I2C_PIIX4
 	tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)"
 	depends on PCI
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 8f4fc23..226bb2e 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -24,6 +24,10 @@  obj-$(CONFIG_I2C_SIS96X)	+= i2c-sis96x.o
 obj-$(CONFIG_I2C_VIA)		+= i2c-via.o
 obj-$(CONFIG_I2C_VIAPRO)	+= i2c-viapro.o
 
+# DIMM busses
+obj-$(CONFIG_I2C_DIMM_BUS)	+= dimm-bus.o
+obj-$(CONFIG_I2C_IMC)		+= i2c-imc.o
+
 # Mac SMBus host controller drivers
 obj-$(CONFIG_I2C_HYDRA)		+= i2c-hydra.o
 obj-$(CONFIG_I2C_POWERMAC)	+= i2c-powermac.o
diff --git a/drivers/i2c/busses/dimm-bus.c b/drivers/i2c/busses/dimm-bus.c
new file mode 100644
index 0000000..9012638
--- /dev/null
+++ b/drivers/i2c/busses/dimm-bus.c
@@ -0,0 +1,84 @@ 
+/*
+ * Copyright (c) 2013 Andrew Lutomirski <luto@amacapital.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/i2c.h>
+#include <linux/bug.h>
+#include <linux/module.h>
+#include <linux/i2c/dimm-bus.h>
+
+static bool probe_addr(struct i2c_adapter *adapter, int addr)
+{
+	/*
+	 * So far, all known devices that live on DIMMs can be safely
+	 * and reliably detected by trying to read a byte at address
+	 * zero.
+	 */
+	union i2c_smbus_data dummy;
+	return i2c_smbus_xfer(adapter, addr, 0, I2C_SMBUS_READ, 0,
+			      I2C_SMBUS_BYTE_DATA, &dummy) >= 0;
+}
+
+/**
+ * i2c_scan_dimm_bus() - Scans an SMBUS segment known to contain DIMMs
+ * @adapter: The SMBUS adapter to scan
+ *
+ * This function tells the DIMM-bus code that the adapter is known to
+ * contain DIMMs.  i2c_scan_dimm_bus will probe for devices known to
+ * live on DIMMs.
+ *
+ * Do NOT call this function on general-purpose system SMBUS segments
+ * unless you know that the only things on the bus are DIMMs.
+ * Otherwise is it very likely to mis-identify other things on the
+ * bus.
+ *
+ * Callers are advised not to set adapter->class = I2C_CLASS_SPD.
+ */
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter)
+{
+	struct i2c_board_info info = {};
+	int slot;
+
+	/*
+	 * We probe with "read byte data".  If any DIMM SMBUS driver can't
+	 * support that access type, this function should be updated.
+	 */
+	if (WARN_ON(!i2c_check_functionality(adapter,
+					  I2C_FUNC_SMBUS_READ_BYTE_DATA)))
+		return;
+
+	for (slot = 0; slot < 8; slot++) {
+		/* If there's no SPD, then assume there's no DIMM here. */
+		if (!probe_addr(adapter, 0x50 | slot))
+			continue;
+
+		strcpy(info.type, "eeprom");
+		info.addr = 0x50 | slot;
+		i2c_new_device(adapter, &info);
+
+		if (probe_addr(adapter, 0x18 | slot)) {
+			/* This is a temperature sensor. */
+			strcpy(info.type, "tsod");
+			info.addr = 0x18 | slot;
+			i2c_new_device(adapter, &info);
+		}
+	}
+}
+EXPORT_SYMBOL(i2c_scan_dimm_bus);
+
+MODULE_AUTHOR("Andrew Lutomirski <luto@amacapital.net>");
+MODULE_DESCRIPTION("i2c DIMM bus support");
+MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c/dimm-bus.h b/include/linux/i2c/dimm-bus.h
new file mode 100644
index 0000000..3d44df4
--- /dev/null
+++ b/include/linux/i2c/dimm-bus.h
@@ -0,0 +1,24 @@ 
+/*
+ * Copyright (c) 2013 Andrew Lutomirski <luto@amacapital.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef _I2C_DIMM_BUS
+#define _I2C_DIMM_BUS
+
+struct i2c_adapter;
+void i2c_scan_dimm_bus(struct i2c_adapter *adapter);
+
+#endif /* _I2C_DIMM_BUS */