1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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
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
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
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
159static int max1617_probe(struct i2c_adapter *adap)
160{
161
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