patch-2.4.22 linux-2.4.22/drivers/i2c/i2c-max1617.c
Next file: linux-2.4.22/drivers/i2c/i2c-sibyte.c
Previous file: linux-2.4.22/drivers/i2c/i2c-dev.c
Back to the patch index
Back to the overall index
- Lines: 226
- Date:
2003-08-25 04:44:41.000000000 -0700
- Orig file:
linux-2.4.21/drivers/i2c/i2c-max1617.c
- Orig date:
1969-12-31 16:00:00.000000000 -0800
diff -urN linux-2.4.21/drivers/i2c/i2c-max1617.c linux-2.4.22/drivers/i2c/i2c-max1617.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * SMBus/I2C device driver for the MAX1617 temperature sensor
+ */
+
+#include <linux/config.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-algo-sibyte.h>
+
+#define IF_NAME "max1617"
+
+#define MAX1617_SMBUS_DEV 0x2A
+#define MAX1617_LOCAL 0
+#define MAX1617_REMOTE 1
+#define MAX1617_STATUS 2
+#define MAX1617_POLL_PERIOD 10
+
+static int max1617_verbose = 0;
+static int max1617_polling = 1;
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {MAX1617_SMBUS_DEV, I2C_CLIENT_END};
+static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
+static unsigned short probe[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short probe_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+static unsigned short force[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
+
+static struct i2c_client_address_data addr_data = {
+ normal_i2c, normal_i2c_range,
+ probe, probe_range,
+ ignore, ignore_range,
+ force
+};
+
+struct max1617_info {
+ struct i2c_client *client;
+ struct timer_list timer;
+ int local;
+ int remote;
+};
+
+static int max1617_probe(struct i2c_adapter *adap);
+static int max1617_detach(struct i2c_client *device);
+static int max1617_command(struct i2c_client *device, unsigned int cmd, void *arg);
+static void max1617_inc_use(struct i2c_client *device);
+static void max1617_dec_use(struct i2c_client *device);
+
+struct i2c_driver i2c_driver_max1617 = {
+ name: IF_NAME,
+ id: I2C_DRIVERID_MAX1617,
+ flags: I2C_DF_NOTIFY,
+ attach_adapter: max1617_probe,
+ detach_client: max1617_detach,
+ command: max1617_command,
+ inc_use: max1617_inc_use,
+ dec_use: max1617_dec_use
+};
+\
+static int max1617_read(struct i2c_client *client, unsigned char subaddr)
+{
+ return i2c_smbus_read_byte_data(client, subaddr);
+}
+
+/* poll the device, check for temperature/status changes */
+static void max1617_update(unsigned long arg)
+{
+ struct max1617_info *m = (struct max1617_info *)arg;
+ int status, remote, local;
+ char statstr[50];
+
+ status = max1617_read(m->client, MAX1617_STATUS);
+ remote = max1617_read(m->client, MAX1617_REMOTE);
+ local = max1617_read(m->client, MAX1617_LOCAL);
+ if (status < 0 || remote < 0 || local < 0) {
+ printk(KERN_ERR IF_NAME ": sensor device did not respond.\n");
+ } else {
+ statstr[0] = 0;
+ if (status & 0x80) strcat(statstr,"Busy ");
+ if (status & 0x40) strcat(statstr,"HiTempLcl ");
+ if (status & 0x20) strcat(statstr,"LoTempLcl ");
+ if (status & 0x10) strcat(statstr,"HiTempRem ");
+ if (status & 0x08) strcat(statstr,"LoTempRem ");
+ if (status & 0x04) strcat(statstr,"Fault ");
+
+ if (max1617_verbose || (local != m->local) || (remote != m->remote)) {
+ printk(KERN_DEBUG IF_NAME ": Temperature - CPU: %dC Board: %dC Status:%02X [ %s]\n",
+ remote, local, status, statstr);
+ }
+ m->local = local;
+ m->remote = remote;
+ mod_timer(&m->timer, jiffies + (HZ * MAX1617_POLL_PERIOD));
+ }
+}
+
+/* attach to an instance of the device that was probed on a bus */
+static int max1617_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
+{
+ struct max1617_info *m;
+ struct i2c_client *client;
+ int err;
+
+ client = kmalloc(sizeof(*client), GFP_KERNEL);
+ if (client == NULL)
+ return -ENOMEM;
+ client->adapter = adap;
+ client->addr = addr;
+ client->driver = &i2c_driver_max1617;
+ sprintf(client->name, "%s-%x", IF_NAME, addr);
+ if ((err = i2c_attach_client(client)) < 0) {
+ kfree(client);
+ return err;
+ }
+
+ m = kmalloc(sizeof(*m), GFP_KERNEL);
+ if (m == NULL) {
+ i2c_detach_client(client);
+ kfree(client);
+ return -ENOMEM;
+ }
+ m->client = client;
+ m->remote = m->local = 0;
+ init_timer(&m->timer);
+ m->timer.data = (unsigned long)m;
+ m->timer.function = max1617_update;
+ if (max1617_polling) {
+ m->timer.expires = jiffies + (HZ * MAX1617_POLL_PERIOD);
+ add_timer(&m->timer);
+ }
+ client->data = m;
+ return 0;
+}
+
+/* initiate probing on a particular bus */
+static int max1617_probe(struct i2c_adapter *adap)
+{
+ /* Look for this device on the given adapter (bus) */
+ if (adap->id == (I2C_ALGO_SIBYTE | I2C_HW_SIBYTE))
+ return i2c_probe(adap, &addr_data, &max1617_attach);
+ else
+ return 0;
+}
+
+static int max1617_detach(struct i2c_client *device)
+{
+ struct max1617_info *m = (struct max1617_info *)device->data;
+ int rc = 0;
+
+ if ((rc = i2c_detach_client(device)) != 0) {
+ printk(IF_NAME "detach failed: %d\n", rc);
+ } else {
+ kfree(device);
+ if (max1617_polling)
+ del_timer(&m->timer);
+ kfree(m);
+ }
+ return rc;
+}
+
+static int max1617_command(struct i2c_client *device, unsigned int cmd, void *arg)
+{
+ return 0;
+}
+
+static void max1617_inc_use(struct i2c_client *client)
+{
+#ifdef MODULE
+ MOD_INC_USE_COUNT;
+#endif
+}
+
+static void max1617_dec_use(struct i2c_client *client)
+{
+#ifdef MODULE
+ MOD_DEC_USE_COUNT;
+#endif
+}
+
+void i2c_max1617_init(void)
+{
+ i2c_add_driver(&i2c_driver_max1617);
+}
+
+EXPORT_NO_SYMBOLS;
+
+#ifdef MODULE
+MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
+MODULE_DESCRIPTION("Max 1617 temperature sensor for SiByte SOC boards");
+MODULE_LICENSE("GPL");
+
+int init_module(void)
+{
+ i2c_max1617_init();
+ return 0;
+}
+
+void cleanup_module(void)
+{
+ i2c_del_driver(&i2c_driver_max1617);
+}
+#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)