0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <linux/types.h>
0010 #include <linux/errno.h>
0011 #include <linux/kernel.h>
0012 #include <linux/delay.h>
0013 #include <linux/slab.h>
0014 #include <linux/init.h>
0015 #include <linux/wait.h>
0016 #include <linux/i2c.h>
0017 #include <linux/of_device.h>
0018 #include <asm/machdep.h>
0019 #include <asm/io.h>
0020 #include <asm/sections.h>
0021 #include <asm/pmac_low_i2c.h>
0022
0023 #include "windfarm.h"
0024
0025 #define VERSION "1.0"
0026
0027 #undef DEBUG
0028
0029 #ifdef DEBUG
0030 #define DBG(args...) printk(args)
0031 #else
0032 #define DBG(args...) do { } while(0)
0033 #endif
0034
0035 struct wf_lm75_sensor {
0036 int ds1775 : 1;
0037 int inited : 1;
0038 struct i2c_client *i2c;
0039 struct wf_sensor sens;
0040 };
0041 #define wf_to_lm75(c) container_of(c, struct wf_lm75_sensor, sens)
0042
0043 static int wf_lm75_get(struct wf_sensor *sr, s32 *value)
0044 {
0045 struct wf_lm75_sensor *lm = wf_to_lm75(sr);
0046 s32 data;
0047
0048 if (lm->i2c == NULL)
0049 return -ENODEV;
0050
0051
0052 if (!lm->inited) {
0053 u8 cfg_new, cfg = (u8)i2c_smbus_read_byte_data(lm->i2c, 1);
0054
0055 DBG("wf_lm75: Initializing %s, cfg was: %02x\n",
0056 sr->name, cfg);
0057
0058
0059
0060
0061 cfg_new = cfg & ~0x01;
0062 i2c_smbus_write_byte_data(lm->i2c, 1, cfg_new);
0063 lm->inited = 1;
0064
0065
0066 msleep(200);
0067 }
0068
0069
0070 data = (s32)le16_to_cpu(i2c_smbus_read_word_data(lm->i2c, 0));
0071 data <<= 8;
0072 *value = data;
0073
0074 return 0;
0075 }
0076
0077 static void wf_lm75_release(struct wf_sensor *sr)
0078 {
0079 struct wf_lm75_sensor *lm = wf_to_lm75(sr);
0080
0081 kfree(lm);
0082 }
0083
0084 static const struct wf_sensor_ops wf_lm75_ops = {
0085 .get_value = wf_lm75_get,
0086 .release = wf_lm75_release,
0087 .owner = THIS_MODULE,
0088 };
0089
0090 static int wf_lm75_probe(struct i2c_client *client,
0091 const struct i2c_device_id *id)
0092 {
0093 struct wf_lm75_sensor *lm;
0094 int rc, ds1775;
0095 const char *name, *loc;
0096
0097 if (id)
0098 ds1775 = id->driver_data;
0099 else
0100 ds1775 = !!of_device_get_match_data(&client->dev);
0101
0102 DBG("wf_lm75: creating %s device at address 0x%02x\n",
0103 ds1775 ? "ds1775" : "lm75", client->addr);
0104
0105 loc = of_get_property(client->dev.of_node, "hwsensor-location", NULL);
0106 if (!loc) {
0107 dev_warn(&client->dev, "Missing hwsensor-location property!\n");
0108 return -ENXIO;
0109 }
0110
0111
0112
0113
0114
0115 if (!strcmp(loc, "Hard drive") || !strcmp(loc, "DRIVE BAY"))
0116 name = "hd-temp";
0117 else if (!strcmp(loc, "Incoming Air Temp"))
0118 name = "incoming-air-temp";
0119 else if (!strcmp(loc, "ODD Temp"))
0120 name = "optical-drive-temp";
0121 else if (!strcmp(loc, "HD Temp"))
0122 name = "hard-drive-temp";
0123 else if (!strcmp(loc, "PCI SLOTS"))
0124 name = "slots-temp";
0125 else if (!strcmp(loc, "CPU A INLET"))
0126 name = "cpu-inlet-temp-0";
0127 else if (!strcmp(loc, "CPU B INLET"))
0128 name = "cpu-inlet-temp-1";
0129 else
0130 return -ENXIO;
0131
0132
0133 lm = kzalloc(sizeof(struct wf_lm75_sensor), GFP_KERNEL);
0134 if (lm == NULL)
0135 return -ENODEV;
0136
0137 lm->inited = 0;
0138 lm->ds1775 = ds1775;
0139 lm->i2c = client;
0140 lm->sens.name = name;
0141 lm->sens.ops = &wf_lm75_ops;
0142 i2c_set_clientdata(client, lm);
0143
0144 rc = wf_register_sensor(&lm->sens);
0145 if (rc)
0146 kfree(lm);
0147 return rc;
0148 }
0149
0150 static int wf_lm75_remove(struct i2c_client *client)
0151 {
0152 struct wf_lm75_sensor *lm = i2c_get_clientdata(client);
0153
0154
0155 lm->i2c = NULL;
0156
0157
0158 wf_unregister_sensor(&lm->sens);
0159
0160 return 0;
0161 }
0162
0163 static const struct i2c_device_id wf_lm75_id[] = {
0164 { "MAC,lm75", 0 },
0165 { "MAC,ds1775", 1 },
0166 { }
0167 };
0168 MODULE_DEVICE_TABLE(i2c, wf_lm75_id);
0169
0170 static const struct of_device_id wf_lm75_of_id[] = {
0171 { .compatible = "lm75", .data = (void *)0},
0172 { .compatible = "ds1775", .data = (void *)1 },
0173 { }
0174 };
0175 MODULE_DEVICE_TABLE(of, wf_lm75_of_id);
0176
0177 static struct i2c_driver wf_lm75_driver = {
0178 .driver = {
0179 .name = "wf_lm75",
0180 .of_match_table = wf_lm75_of_id,
0181 },
0182 .probe = wf_lm75_probe,
0183 .remove = wf_lm75_remove,
0184 .id_table = wf_lm75_id,
0185 };
0186
0187 module_i2c_driver(wf_lm75_driver);
0188
0189 MODULE_AUTHOR("Benjamin Herrenschmidt <benh@kernel.crashing.org>");
0190 MODULE_DESCRIPTION("LM75 sensor objects for PowerMacs thermal control");
0191 MODULE_LICENSE("GPL");
0192