i2c-i801: Instantiate FSC hardware montioring chips
authorHans de Goede <hdegoede@redhat.com>
Mon, 30 Mar 2009 19:46:44 +0000 (21:46 +0200)
committerJean Delvare <khali@linux-fr.org>
Mon, 30 Mar 2009 19:46:44 +0000 (21:46 +0200)
Detect various FSC hwmon IC's based on DMI tables and then let
the i2c-i801 driver instantiate the i2c client devices. Note that
some of the info in the added table is indentical for all rows, still
this is kept in the table to keep the code general and thus (hopefully)
easily extensible in the future.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Jean Delvare <khali@linux-fr.org>
drivers/i2c/busses/i2c-i801.c

index 230238df56c4d238d3fd4e9d184c7e1d1f608968..10411848fd704f58e790cc3587a92e07bd6f22c6 100644 (file)
@@ -65,6 +65,7 @@
 #include <linux/i2c.h>
 #include <linux/acpi.h>
 #include <linux/io.h>
+#include <linux/dmi.h>
 
 /* I801 SMBus address offsets */
 #define SMBHSTSTS      (0 + i801_smba)
@@ -616,10 +617,81 @@ static void __init input_apanel_init(void)
 static void __init input_apanel_init(void) {}
 #endif
 
+#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
+struct dmi_onboard_device_info {
+       const char *name;
+       u8 type;
+       unsigned short i2c_addr;
+       const char *i2c_type;
+};
+
+static struct dmi_onboard_device_info __devinitdata dmi_devices[] = {
+       { "Syleus", DMI_DEV_TYPE_OTHER, 0x73, "fscsyl" },
+       { "Hermes", DMI_DEV_TYPE_OTHER, 0x73, "fscher" },
+       { "Hades",  DMI_DEV_TYPE_OTHER, 0x73, "fschds" },
+};
+
+static void __devinit dmi_check_onboard_device(u8 type, const char *name,
+                                              struct i2c_adapter *adap)
+{
+       int i;
+       struct i2c_board_info info;
+
+       for (i = 0; i < ARRAY_SIZE(dmi_devices); i++) {
+               /* & ~0x80, ignore enabled/disabled bit */
+               if ((type & ~0x80) != dmi_devices[i].type)
+                       continue;
+               if (strcmp(name, dmi_devices[i].name))
+                       continue;
+
+               memset(&info, 0, sizeof(struct i2c_board_info));
+               info.addr = dmi_devices[i].i2c_addr;
+               strlcpy(info.type, dmi_devices[i].i2c_type, I2C_NAME_SIZE);
+               i2c_new_device(adap, &info);
+               break;
+       }
+}
+
+/* We use our own function to check for onboard devices instead of
+   dmi_find_device() as some buggy BIOS's have the devices we are interested
+   in marked as disabled */
+static void __devinit dmi_check_onboard_devices(const struct dmi_header *dm,
+                                               void *adap)
+{
+       int i, count;
+
+       if (dm->type != 10)
+               return;
+
+       count = (dm->length - sizeof(struct dmi_header)) / 2;
+       for (i = 0; i < count; i++) {
+               const u8 *d = (char *)(dm + 1) + (i * 2);
+               const char *name = ((char *) dm) + dm->length;
+               u8 type = d[0];
+               u8 s = d[1];
+
+               if (!s)
+                       continue;
+               s--;
+               while (s > 0 && name[0]) {
+                       name += strlen(name) + 1;
+                       s--;
+               }
+               if (name[0] == 0) /* Bogus string reference */
+                       continue;
+
+               dmi_check_onboard_device(type, name, adap);
+       }
+}
+#endif
+
 static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
        unsigned char temp;
        int err;
+#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
+       const char *vendor;
+#endif
 
        I801_dev = dev;
        i801_features = 0;
@@ -712,6 +784,11 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
                i2c_new_device(&i801_adapter, &info);
        }
 #endif
+#if defined CONFIG_SENSORS_FSCHMD || defined CONFIG_SENSORS_FSCHMD_MODULE
+       vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+       if (vendor && !strcmp(vendor, "FUJITSU SIEMENS"))
+               dmi_walk(dmi_check_onboard_devices, &i801_adapter);
+#endif
 
        return 0;