linux-old/drivers/i2c/i2c-max1617.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2001,2002,2003 Broadcom Corporation
   3 *
   4 * This program is free software; you can redistribute it and/or
   5 * modify it under the terms of the GNU General Public License
   6 * as published by the Free Software Foundation; either version 2
   7 * of the License, or (at your option) any later version.
   8 *
   9 * This program is distributed in the hope that it will be useful,
  10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12 * GNU General Public License for more details.
  13 * 
  14 * You should have received a copy of the GNU General Public License
  15 * along with this program; if not, write to the Free Software
  16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17 */
  18
  19/*
  20 * SMBus/I2C device driver for the MAX1617 temperature sensor
  21 */
  22
  23#include <linux/config.h>
  24#include <linux/kernel.h>
  25#include <linux/module.h>
  26#include <linux/slab.h>
  27#include <linux/timer.h>
  28#include <linux/errno.h>
  29
  30#include <linux/i2c.h>
  31#include <linux/i2c-algo-sibyte.h>
  32
  33#define IF_NAME "max1617"
  34
  35#define MAX1617_SMBUS_DEV       0x2A
  36#define MAX1617_LOCAL           0
  37#define MAX1617_REMOTE          1
  38#define MAX1617_STATUS          2
  39#define MAX1617_POLL_PERIOD    10
  40
  41static int max1617_verbose = 0;
  42static int max1617_polling = 1;
  43
  44/* Addresses to scan */
  45static unsigned short normal_i2c[] = {MAX1617_SMBUS_DEV, I2C_CLIENT_END};
  46static unsigned short normal_i2c_range[] = {I2C_CLIENT_END};
  47static unsigned short probe[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
  48static unsigned short probe_range[2]  = { I2C_CLIENT_END, I2C_CLIENT_END };
  49static unsigned short ignore[2]       = { I2C_CLIENT_END, I2C_CLIENT_END };
  50static unsigned short ignore_range[2] = { I2C_CLIENT_END, I2C_CLIENT_END };
  51static unsigned short force[2]        = { I2C_CLIENT_END, I2C_CLIENT_END };
  52
  53static struct i2c_client_address_data addr_data = {
  54        normal_i2c, normal_i2c_range,
  55        probe, probe_range,
  56        ignore, ignore_range,
  57        force
  58};
  59
  60struct max1617_info {
  61        struct i2c_client *client;
  62        struct timer_list  timer;
  63        int                local;
  64        int                remote;
  65};
  66
  67static int max1617_probe(struct i2c_adapter *adap);
  68static int max1617_detach(struct i2c_client *device);
  69static int max1617_command(struct i2c_client *device, unsigned int cmd, void *arg);
  70static void max1617_inc_use(struct i2c_client *device);
  71static void max1617_dec_use(struct i2c_client *device);
  72
  73struct i2c_driver i2c_driver_max1617 = {
  74        name:           IF_NAME,
  75        id:             I2C_DRIVERID_MAX1617,
  76        flags:          I2C_DF_NOTIFY,
  77        attach_adapter: max1617_probe,
  78        detach_client:  max1617_detach,
  79        command:        max1617_command,
  80        inc_use:        max1617_inc_use,
  81        dec_use:        max1617_dec_use
  82};
  83\
  84static int max1617_read(struct i2c_client *client, unsigned char subaddr)
  85{
  86        return i2c_smbus_read_byte_data(client, subaddr);
  87}
  88
  89/* poll the device, check for temperature/status changes */
  90static void max1617_update(unsigned long arg)
  91{
  92        struct max1617_info *m = (struct max1617_info *)arg;
  93        int status, remote, local;
  94        char statstr[50];
  95
  96        status = max1617_read(m->client, MAX1617_STATUS);
  97        remote = max1617_read(m->client, MAX1617_REMOTE);
  98        local  = max1617_read(m->client, MAX1617_LOCAL);
  99        if (status < 0 || remote < 0 || local < 0) {
 100                printk(KERN_ERR IF_NAME ": sensor device did not respond.\n");
 101        } else {
 102                statstr[0] = 0;
 103                if (status & 0x80) strcat(statstr,"Busy ");
 104                if (status & 0x40) strcat(statstr,"HiTempLcl ");
 105                if (status & 0x20) strcat(statstr,"LoTempLcl ");
 106                if (status & 0x10) strcat(statstr,"HiTempRem ");
 107                if (status & 0x08) strcat(statstr,"LoTempRem ");
 108                if (status & 0x04) strcat(statstr,"Fault ");
 109
 110                if (max1617_verbose || (local != m->local) || (remote != m->remote)) {
 111                        printk(KERN_DEBUG IF_NAME ": Temperature - CPU: %dC  Board: %dC  Status:%02X [ %s]\n",
 112                               remote, local, status, statstr);
 113                }
 114                m->local = local;
 115                m->remote = remote;
 116                mod_timer(&m->timer, jiffies + (HZ * MAX1617_POLL_PERIOD));
 117        }
 118}
 119
 120/* attach to an instance of the device that was probed on a bus */
 121static int max1617_attach(struct i2c_adapter *adap, int addr, unsigned short flags, int kind)
 122{
 123        struct max1617_info *m;
 124        struct i2c_client   *client;
 125        int err;
 126
 127        client = kmalloc(sizeof(*client), GFP_KERNEL);
 128        if (client == NULL)
 129                return -ENOMEM;
 130        client->adapter = adap;
 131        client->addr = addr;
 132        client->driver = &i2c_driver_max1617;
 133        sprintf(client->name, "%s-%x", IF_NAME, addr);
 134        if ((err = i2c_attach_client(client)) < 0) {
 135                kfree(client);
 136                return err;
 137        }
 138
 139        m = kmalloc(sizeof(*m), GFP_KERNEL);
 140        if (m == NULL) {
 141                i2c_detach_client(client);
 142                kfree(client);
 143                return -ENOMEM;
 144        }
 145        m->client = client;
 146        m->remote = m->local = 0;
 147        init_timer(&m->timer);
 148        m->timer.data = (unsigned long)m;
 149        m->timer.function = max1617_update;
 150        if (max1617_polling) {
 151                m->timer.expires = jiffies + (HZ * MAX1617_POLL_PERIOD);
 152                add_timer(&m->timer);
 153        }
 154        client->data = m;
 155        return 0;
 156}
 157
 158/* initiate probing on a particular bus */
 159static int max1617_probe(struct i2c_adapter *adap)
 160{
 161        /* Look for this device on the given adapter (bus) */
 162        if (adap->id == (I2C_ALGO_SIBYTE | I2C_HW_SIBYTE))
 163                return i2c_probe(adap, &addr_data, &max1617_attach);
 164        else
 165                return 0;
 166}
 167
 168static int max1617_detach(struct i2c_client *device)
 169{
 170        struct max1617_info *m = (struct max1617_info *)device->data;
 171        int rc = 0;
 172
 173        if ((rc = i2c_detach_client(device)) != 0) {
 174                printk(IF_NAME "detach failed: %d\n", rc);
 175        } else {
 176                kfree(device);
 177                if (max1617_polling)
 178                        del_timer(&m->timer);
 179                kfree(m);
 180        }
 181        return rc;
 182}
 183
 184static int max1617_command(struct i2c_client *device, unsigned int cmd, void *arg)
 185{
 186        return 0;
 187}
 188
 189static void max1617_inc_use(struct i2c_client *client)
 190{
 191#ifdef MODULE
 192        MOD_INC_USE_COUNT;
 193#endif
 194}
 195
 196static void max1617_dec_use(struct i2c_client *client)
 197{
 198#ifdef MODULE
 199        MOD_DEC_USE_COUNT;
 200#endif
 201}
 202
 203void i2c_max1617_init(void)
 204{
 205        i2c_add_driver(&i2c_driver_max1617);
 206}
 207
 208EXPORT_NO_SYMBOLS;
 209
 210#ifdef MODULE
 211MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
 212MODULE_DESCRIPTION("Max 1617 temperature sensor for SiByte SOC boards");
 213MODULE_LICENSE("GPL");
 214
 215int init_module(void)
 216{
 217        i2c_max1617_init();
 218        return 0;
 219}
 220
 221void cleanup_module(void)
 222{
 223        i2c_del_driver(&i2c_driver_max1617);
 224}
 225#endif
 226
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.