summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2009-03-30 23:46:44 +0400
committerJean Delvare <khali@linux-fr.org>2009-03-30 23:46:44 +0400
commitfa5bfab7128e58c31448fca83a288a86e7d476cc (patch)
treede05e1b02bed9414ebeab03f4ee15d6052c70017
parente7a19c5624c66afa8118b10cd59f87ee407646bc (diff)
downloadlinux-fa5bfab7128e58c31448fca83a288a86e7d476cc.tar.xz
i2c-i801: Instantiate FSC hardware montioring chips
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>
-rw-r--r--drivers/i2c/busses/i2c-i801.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 230238df56c4..10411848fd70 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -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;