root/lm-sensors/trunk/kernel/chips/lm63.c @ 2994

Revision 2994, 19.1 KB (checked in by khali, 8 years ago)

Spelling fixes. Contributed by Steven Cole.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * lm63.c - driver for the National Semiconductor LM63 temperature sensor
3 *          with integrated fan control
4 * Copyright (C) 2004  Jean Delvare <khali@linux-fr.org>
5 * Based on the lm90 driver.
6 *
7 * The LM63 is a sensor chip made by National Semiconductor. It measures
8 * two temperatures (its own and one external one) and the speed of one
9 * fan, those speed it can additionally control. Complete datasheet can be
10 * obtained from National's website at:
11 *   http://www.national.com/pf/LM/LM63.html
12 *
13 * The LM63 is basically an LM86 with fan speed monitoring and control
14 * capabilities added. It misses some of the LM86 features though:
15 *  - No low limit for local temperature.
16 *  - No critical limit for local temperature.
17 *  - Critical limit for remote temperature can be changed only once. We
18 *    will consider that the critical limit is read-only.
19 *
20 * The datasheet isn't very clear about what the tachometer reading is.
21 * I had a explanation from National Semiconductor though. The two lower
22 * bits of the read value have to be masked out. The value is still 16 bit
23 * in width.
24 *
25 * This program is free software; you can redistribute it and/or modify
26 * it under the terms of the GNU General Public License as published by
27 * the Free Software Foundation; either version 2 of the License, or
28 * (at your option) any later version.
29 *
30 * This program is distributed in the hope that it will be useful,
31 * but WITHOUT ANY WARRANTY; without even the implied warranty of
32 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
33 * GNU General Public License for more details.
34 *
35 * You should have received a copy of the GNU General Public License
36 * along with this program; if not, write to the Free Software
37 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38 */
39
40#include <linux/module.h>
41#include <linux/slab.h>
42#include <linux/i2c.h>
43#include <linux/i2c-proc.h>
44#include <linux/init.h>
45#include "version.h"
46
47/*
48 * Addresses to scan
49 * Address is fully defined internally and cannot be changed.
50 */
51
52static unsigned short normal_i2c[] = { 0x4c, SENSORS_I2C_END };
53static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
54static unsigned int normal_isa[] = { SENSORS_ISA_END };
55static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
56/*
57 * Insmod parameters
58 */
59
60SENSORS_INSMOD_1(lm63);
61
62/*
63 * The LM63 registers
64 */
65
66#define LM63_REG_CONFIG1                0x03
67#define LM63_REG_CONFIG2                0xBF
68#define LM63_REG_CONFIG_FAN             0x4A
69
70#define LM63_REG_TACH_COUNT_MSB         0x47
71#define LM63_REG_TACH_COUNT_LSB         0x46
72#define LM63_REG_TACH_LIMIT_MSB         0x49
73#define LM63_REG_TACH_LIMIT_LSB         0x48
74
75#define LM63_REG_PWM_VALUE              0x4C
76#define LM63_REG_PWM_FREQ               0x4D
77
78#define LM63_REG_LOCAL_TEMP             0x00
79#define LM63_REG_LOCAL_HIGH             0x05
80
81#define LM63_REG_REMOTE_TEMP_MSB        0x01
82#define LM63_REG_REMOTE_TEMP_LSB        0x10
83#define LM63_REG_REMOTE_OFFSET_MSB      0x11
84#define LM63_REG_REMOTE_OFFSET_LSB      0x12
85#define LM63_REG_REMOTE_HIGH_MSB        0x07
86#define LM63_REG_REMOTE_HIGH_LSB        0x13
87#define LM63_REG_REMOTE_LOW_MSB         0x08
88#define LM63_REG_REMOTE_LOW_LSB         0x14
89#define LM63_REG_REMOTE_TCRIT           0x19
90#define LM63_REG_REMOTE_TCRIT_HYST      0x21
91
92#define LM63_REG_ALERT_STATUS           0x02
93#define LM63_REG_ALERT_MASK             0x16
94
95#define LM63_REG_MAN_ID                 0xFE
96#define LM63_REG_CHIP_ID                0xFF
97
98/*
99 * Conversions and various macros
100 * For tachometer counts, the LM63 uses 16-bit values.
101 * For local temperature and high limit, remote critical limit and hysteresis
102 * value, it uses signed 8-bit values with LSB = 1 degree Celsius.
103 * For remote temperature, low and high limits, it uses signed 11-bit values
104 * with LSB = 0.125 degree Celsius, left-justified in 16-bit registers.
105 */
106
107#define FAN_FROM_REG(reg)       ((reg) == 0xFFFC || (reg) == 0 ? 0 : \
108                                 5400000 / (reg))
109#define FAN_TO_REG(val)         ((val) <= 82 ? 0xFFFF : \
110                                 (5400000 / (val)) & 0xFFFC)
111#define TEMP8_FROM_REG(reg)     (reg)
112#define TEMP8_TO_REG(val)       ((val) <= -128 ? -128 : \
113                                 (val) >= 127 ? 127 : \
114                                 val)
115#define TEMP11_FROM_REG(reg)    ((reg) / 32 * 125)
116#define TEMP11_TO_REG(val)      ((val) <= -128000 ? 0x8000 : \
117                                 (val) >= 127875 ? 0x7FE0 : \
118                                 (val) < 0 ? ((val) - 62) / 125 * 32 : \
119                                 ((val) + 62) / 125 * 32)
120#define HYST_TO_REG(val)        ((val) <= 0 ? 0 : \
121                                 (val) >= 127 ? 127 : \
122                                 val)
123
124/*
125 * Functions declaration
126 */
127
128static int lm63_attach_adapter(struct i2c_adapter *adapter);
129static int lm63_detect(struct i2c_adapter *adapter, int address,
130        unsigned short flags, int kind);
131static void lm63_init_client(struct i2c_client *client);
132static int lm63_detach_client(struct i2c_client *client);
133
134static void lm63_local_temp(struct i2c_client *client, int operation,
135        int ctl_name, int *nrels_mag, long *results);
136static void lm63_remote_temp(struct i2c_client *client, int operation,
137        int ctl_name, int *nrels_mag, long *results);
138static void lm63_remote_tcrit(struct i2c_client *client, int operation,
139        int ctl_name, int *nrels_mag, long *results);
140static void lm63_remote_tcrit_hyst(struct i2c_client *client, int operation,
141        int ctl_name, int *nrels_mag, long *results);
142static void lm63_alarms(struct i2c_client *client, int operation,
143        int ctl_name, int *nrels_mag, long *results);
144static void lm63_fan(struct i2c_client *client, int operation,
145        int ctl_name, int *nrels_mag, long *results);
146static void lm63_pwm(struct i2c_client *client, int operation,
147        int ctl_name, int *nrels_mag, long *results);
148
149/*
150 * Driver data (common to all clients)
151 */
152
153static struct i2c_driver lm63_driver = {
154        .name           = "LM63 sensor driver",
155        .flags          = I2C_DF_NOTIFY,
156        .attach_adapter = lm63_attach_adapter,
157        .detach_client  = lm63_detach_client,
158};
159
160/*
161 * Client data (each client gets its own)
162 */
163
164struct lm63_data {
165        struct i2c_client client;
166        int sysctl_id;
167
168        struct semaphore update_lock;
169        char valid; /* zero until following fields are valid */
170        unsigned long last_updated; /* in jiffies */
171
172        /* registers values */
173        u8 config, config_fan;
174        u16 fan1_input;
175        u16 fan1_low;
176        u8 pwm1_freq;
177        u8 pwm1_value;
178        s8 temp1_input;
179        s8 temp1_high;
180        s16 temp2_input;
181        s16 temp2_high;
182        s16 temp2_low;
183        s8 temp2_crit;
184        u8 temp2_crit_hyst;
185        u8 alarms;
186};
187
188/*
189 * Proc entries
190 * These files are created for each detected LM63.
191 */
192
193/* -- SENSORS SYSCTL START -- */
194
195#define LM63_SYSCTL_TEMP1               1200
196#define LM63_SYSCTL_TEMP2               1201
197#define LM63_SYSCTL_TEMP2_TCRIT         1205
198#define LM63_SYSCTL_TEMP2_TCRIT_HYST    1208
199#define LM63_SYSCTL_ALARMS              1210
200#define LM63_SYSCTL_FAN1                1220
201#define LM63_SYSCTL_PWM1                1230
202
203#define LM63_ALARM_LOCAL_HIGH           0x40
204#define LM63_ALARM_REMOTE_HIGH          0x10
205#define LM63_ALARM_REMOTE_LOW           0x08
206#define LM63_ALARM_REMOTE_CRIT          0x02
207#define LM63_ALARM_REMOTE_OPEN          0x04
208#define LM63_ALARM_FAN_LOW              0x01
209
210/* -- SENSORS SYSCTL END -- */
211
212static ctl_table lm63_dir_table_template[] =
213{
214        {LM63_SYSCTL_TEMP1, "temp1", NULL, 0, 0644, NULL,
215         &i2c_proc_real, &i2c_sysctl_real, NULL, &lm63_local_temp},
216        {LM63_SYSCTL_TEMP2, "temp2", NULL, 0, 0644, NULL,
217         &i2c_proc_real, &i2c_sysctl_real, NULL, &lm63_remote_temp},
218        {LM63_SYSCTL_TEMP2_TCRIT, "temp2_crit", NULL, 0, 0444, NULL,
219         &i2c_proc_real, &i2c_sysctl_real, NULL, &lm63_remote_tcrit},
220        {LM63_SYSCTL_TEMP2_TCRIT_HYST, "temp2_crit_hyst", NULL, 0, 0644, NULL,
221         &i2c_proc_real, &i2c_sysctl_real, NULL, &lm63_remote_tcrit_hyst},
222        {LM63_SYSCTL_ALARMS, "alarms", NULL, 0, 0444, NULL,
223         &i2c_proc_real, &i2c_sysctl_real, NULL, &lm63_alarms},
224        {LM63_SYSCTL_FAN1, "fan1", NULL, 0, 0644, NULL,
225         &i2c_proc_real, &i2c_sysctl_real, NULL, &lm63_fan},
226        {LM63_SYSCTL_PWM1, "pwm1", NULL, 0, 0644, NULL,
227         &i2c_proc_real, &i2c_sysctl_real, NULL, &lm63_pwm},
228        {0}
229};
230
231/*
232 * Real code
233 */
234
235static int lm63_attach_adapter(struct i2c_adapter *adapter)
236{
237        return i2c_detect(adapter, &addr_data, lm63_detect);
238}
239
240/*
241 * The following function does more than just detection. If detection
242 * succeeds, it also registers the new chip.
243 */
244static int lm63_detect(struct i2c_adapter *adapter, int address,
245        unsigned short flags, int kind)
246{
247        struct i2c_client *new_client;
248        struct lm63_data *data;
249        int err = 0;
250
251        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
252#ifdef DEBUG
253                printk(KERN_DEBUG "lm63: adapter doesn't support SMBus byte "
254                       "data mode, skipping.\n");
255#endif
256                return 0;
257        }
258
259        if (!(data = kmalloc(sizeof(struct lm63_data), GFP_KERNEL))) {
260                printk(KERN_ERR "lm63: Out of memory in lm63_detect\n");
261                return -ENOMEM;
262        }
263
264        /*
265         * The common I2C client data is placed right before the
266         * LM63-specific data. The LM63-specific data is pointed to by the
267         * data field from the i2c_client structure.
268         */
269        new_client = &data->client;
270        new_client->addr = address;
271        new_client->data = data;
272        new_client->adapter = adapter;
273        new_client->driver = &lm63_driver;
274        new_client->flags = 0;
275
276        /* Default to an LM63 if forced */
277        if (kind == 0)
278                kind = lm63;
279
280        if (kind < 0) { /* must identify */
281                u8 man_id, chip_id, reg_config1, reg_config2;
282                u8 reg_alert_status, reg_alert_mask;
283
284                man_id = i2c_smbus_read_byte_data(new_client,
285                         LM63_REG_MAN_ID);
286                chip_id = i2c_smbus_read_byte_data(new_client,
287                          LM63_REG_CHIP_ID);
288                reg_config1 = i2c_smbus_read_byte_data(new_client,
289                              LM63_REG_CONFIG1);
290                reg_config2 = i2c_smbus_read_byte_data(new_client,
291                              LM63_REG_CONFIG2);
292                reg_alert_status = i2c_smbus_read_byte_data(new_client,
293                                   LM63_REG_ALERT_STATUS);
294                reg_alert_mask = i2c_smbus_read_byte_data(new_client,
295                                 LM63_REG_ALERT_MASK);
296
297                if (man_id == 0x01 /* National Semiconductor */
298                 && chip_id == 0x41 /* LM63 */
299                 && (reg_config1 & 0x18) == 0x00
300                 && (reg_config2 & 0xF8) == 0x00
301                 && (reg_alert_status & 0x20) == 0x00
302                 && (reg_alert_mask & 0xA4) == 0xA4) {
303                        kind = lm63;
304                } else {
305#ifdef DEBUG
306                        printk(KERN_DEBUG "lm63: Unsupported chip "
307                               "(man_id=0x%02X, chip_id=0x%02X)\n",
308                               man_id, chip_id);
309#endif                 
310                        goto ERROR1;
311                }
312        }
313
314        /* Fill in the remaining client fields */
315        strcpy(new_client->name, "LM63 chip");
316        data->valid = 0;
317        init_MUTEX(&data->update_lock);
318
319        /* Tell the I2C layer a new client has arrived */
320        if ((err = i2c_attach_client(new_client))) {
321                printk(KERN_ERR "lm63: Failed attaching client\n");
322                goto ERROR1;
323        }
324
325        /* Register a new directory entry */
326        if ((err = i2c_register_entry(new_client, "lm63",
327             lm63_dir_table_template, THIS_MODULE)) < 0) {
328                printk(KERN_ERR "lm63: Failed registering directory entry\n");
329                goto ERROR2;
330        }
331        data->sysctl_id = err;
332
333
334        /* Initialize the LM63 chip */
335        lm63_init_client(new_client);
336
337        return 0;
338
339ERROR2:
340        i2c_detach_client(new_client);
341ERROR1:
342        kfree(data);
343        return err;
344}
345
346/* Idealy we shouldn't have to initialize anything, since the BIOS
347   should have taken care of everything */
348static void lm63_init_client(struct i2c_client *client)
349{
350        struct lm63_data *data = client->data;
351
352        data->config = i2c_smbus_read_byte_data(client, LM63_REG_CONFIG1);
353        data->config_fan = i2c_smbus_read_byte_data(client,
354                                                    LM63_REG_CONFIG_FAN);
355
356        /* Start converting if needed */
357        if (data->config & 0x40) { /* standby */
358#ifdef DEBUG
359                printk(KERN_DEBUG "lm63: Switching to operational mode");
360#endif
361                data->config &= 0xA7;
362                i2c_smbus_write_byte_data(client, LM63_REG_CONFIG1,
363                                          data->config);
364        }
365
366        /* We may need pwm1_freq before ever updating the client data */
367        data->pwm1_freq = i2c_smbus_read_byte_data(client, LM63_REG_PWM_FREQ);
368        if (data->pwm1_freq == 0)
369                data->pwm1_freq = 1;
370
371#ifdef DEBUG
372        /* Show some debug info about the LM63 configuration */
373        printk(KERN_DEBUG "lm63: Alert/tach pin configured for %s\n",
374                (data->config & 0x04) ? "tachometer input" :
375                "alert output");
376        printk(KERN_DEBUG "lm63: PWM clock %s kHz, output frequency %u Hz\n",
377                (data->config_fan & 0x08) ? "1.4" : "360",
378                ((data->config_fan & 0x08) ? 700 : 180000) / data->pwm1_freq);
379        printk(KERN_DEBUG "lm63: PWM output active %s, %s mode\n",
380                (data->config_fan & 0x10) ? "low" : "high",
381                (data->config_fan & 0x20) ? "manual" : "auto");
382#endif
383}
384
385static int lm63_detach_client(struct i2c_client *client)
386{
387        struct lm63_data *data = client->data;
388        int err;
389
390        i2c_deregister_entry(data->sysctl_id);
391        if ((err = i2c_detach_client(client))) {
392                printk(KERN_ERR "lm63: Client deregistration failed, client "
393                       "not detached.\n");
394                return err;
395        }
396
397        kfree(data);
398        return 0;
399}
400
401static  void lm63_update_client(struct i2c_client *client)
402{
403        struct lm63_data *data = client->data;
404
405        down(&data->update_lock);
406
407        if ((jiffies - data->last_updated > HZ) ||
408            (jiffies < data->last_updated) ||
409            !data->valid) {
410                if (data->config & 0x04) { /* tachometer enabled  */
411                        /* order matters for fan1_input */
412                        data->fan1_input = i2c_smbus_read_byte_data(client,
413                                           LM63_REG_TACH_COUNT_LSB) & 0xFC;
414                        data->fan1_input |= i2c_smbus_read_byte_data(client,
415                                            LM63_REG_TACH_COUNT_MSB) << 8;
416                        data->fan1_low = (i2c_smbus_read_byte_data(client,
417                                          LM63_REG_TACH_LIMIT_LSB) & 0xFC)
418                                       | (i2c_smbus_read_byte_data(client,
419                                          LM63_REG_TACH_LIMIT_MSB) << 8);
420                }
421
422                data->pwm1_freq = i2c_smbus_read_byte_data(client,
423                                  LM63_REG_PWM_FREQ);
424                if (data->pwm1_freq == 0)
425                        data->pwm1_freq = 1;
426                data->pwm1_value = i2c_smbus_read_byte_data(client,
427                                   LM63_REG_PWM_VALUE);
428
429                data->temp1_input = i2c_smbus_read_byte_data(client,
430                                    LM63_REG_LOCAL_TEMP);
431                data->temp1_high = i2c_smbus_read_byte_data(client,
432                                   LM63_REG_LOCAL_HIGH);
433
434                /* order matters for temp2_input */
435                data->temp2_input = i2c_smbus_read_byte_data(client,
436                                    LM63_REG_REMOTE_TEMP_MSB) << 8;
437                data->temp2_input |= i2c_smbus_read_byte_data(client,
438                                     LM63_REG_REMOTE_TEMP_LSB);
439                data->temp2_high = (i2c_smbus_read_byte_data(client,
440                                   LM63_REG_REMOTE_HIGH_MSB) << 8)
441                                 | i2c_smbus_read_byte_data(client,
442                                   LM63_REG_REMOTE_HIGH_LSB);
443                data->temp2_low = (i2c_smbus_read_byte_data(client,
444                                  LM63_REG_REMOTE_LOW_MSB) << 8)
445                                | i2c_smbus_read_byte_data(client,
446                                  LM63_REG_REMOTE_LOW_LSB);
447                data->temp2_crit = i2c_smbus_read_byte_data(client,
448                                   LM63_REG_REMOTE_TCRIT);
449                data->temp2_crit_hyst = i2c_smbus_read_byte_data(client,
450                                        LM63_REG_REMOTE_TCRIT_HYST);
451
452                /* Mask out Busy bit in status register */
453                data->alarms = i2c_smbus_read_byte_data(client,
454                               LM63_REG_ALERT_STATUS) & 0x7F;
455
456                data->last_updated = jiffies;
457                data->valid = 1;
458        }
459
460        up(&data->update_lock);
461}
462
463static void lm63_local_temp(struct i2c_client *client, int operation,
464        int ctl_name, int *nrels_mag, long *results)
465{
466        struct lm63_data *data = client->data;
467
468        if (operation == SENSORS_PROC_REAL_INFO)
469                *nrels_mag = 0; /* magnitude */
470        else if (operation == SENSORS_PROC_REAL_READ) {
471                lm63_update_client(client);
472                results[0] = TEMP8_FROM_REG(data->temp1_high);
473                results[1] = TEMP8_FROM_REG(data->temp1_input);
474                *nrels_mag = 2;
475        } else if (operation == SENSORS_PROC_REAL_WRITE) {
476                if (*nrels_mag >= 1) {
477                        data->temp1_high = TEMP8_TO_REG(results[0]);
478                        i2c_smbus_write_byte_data(client, LM63_REG_LOCAL_HIGH,
479                                data->temp1_high);
480                }
481        }
482}
483
484static void lm63_remote_temp(struct i2c_client *client, int operation,
485        int ctl_name, int *nrels_mag, long *results)
486{
487        struct lm63_data *data = client->data;
488
489        if (operation == SENSORS_PROC_REAL_INFO)
490                *nrels_mag = 3; /* magnitude */
491        else if (operation == SENSORS_PROC_REAL_READ) {
492                lm63_update_client(client);
493                results[0] = TEMP11_FROM_REG(data->temp2_high);
494                results[1] = TEMP11_FROM_REG(data->temp2_low);
495                results[2] = TEMP11_FROM_REG(data->temp2_input);
496                *nrels_mag = 3;
497        } else if (operation == SENSORS_PROC_REAL_WRITE) {
498                if (*nrels_mag >= 1) {
499                        data->temp2_high = TEMP11_TO_REG(results[0]);
500                        i2c_smbus_write_byte_data(client,
501                                LM63_REG_REMOTE_HIGH_MSB,
502                                data->temp2_high >> 8);
503                        i2c_smbus_write_byte_data(client,
504                                LM63_REG_REMOTE_HIGH_LSB,
505                                data->temp2_high & 0xFF);
506                }
507                if (*nrels_mag >= 2) {
508                        data->temp2_low = TEMP11_TO_REG(results[1]);
509                        i2c_smbus_write_byte_data(client,
510                                LM63_REG_REMOTE_LOW_MSB,
511                                data->temp2_low >> 8);
512                        i2c_smbus_write_byte_data(client,
513                                LM63_REG_REMOTE_LOW_LSB,
514                                data->temp2_low & 0xFF);
515                }
516        }
517}
518
519static void lm63_remote_tcrit(struct i2c_client *client, int operation,
520        int ctl_name, int *nrels_mag, long *results)
521{
522        struct lm63_data *data = client->data;
523
524        if (operation == SENSORS_PROC_REAL_INFO)
525                *nrels_mag = 0; /* magnitude */
526        else if (operation == SENSORS_PROC_REAL_READ) {
527                lm63_update_client(client);
528                results[0] = TEMP8_FROM_REG(data->temp2_crit);
529                *nrels_mag = 1;
530        }
531}
532
533static void lm63_remote_tcrit_hyst(struct i2c_client *client, int operation,
534        int ctl_name, int *nrels_mag, long *results)
535{
536        struct lm63_data *data = client->data;
537
538        if (operation == SENSORS_PROC_REAL_INFO)
539                *nrels_mag = 0; /* magnitude */
540        else if (operation == SENSORS_PROC_REAL_READ) {
541                lm63_update_client(client);
542                results[0] = TEMP8_FROM_REG(data->temp2_crit) -
543                             TEMP8_FROM_REG(data->temp2_crit_hyst);
544                *nrels_mag = 1;
545        } else if (operation == SENSORS_PROC_REAL_WRITE) {
546                if (*nrels_mag >= 1) {
547                        data->temp2_crit_hyst = HYST_TO_REG(data->temp2_crit -
548                                                results[0]);
549                        i2c_smbus_write_byte_data(client,
550                                LM63_REG_REMOTE_TCRIT_HYST,
551                                data->temp2_crit_hyst);
552                }
553        }
554}
555
556static void lm63_alarms(struct i2c_client *client, int operation,
557        int ctl_name, int *nrels_mag, long *results)
558{
559        struct lm63_data *data = client->data;
560
561        if (operation == SENSORS_PROC_REAL_INFO)
562                *nrels_mag = 0; /* magnitude */
563        else if (operation == SENSORS_PROC_REAL_READ) {
564                lm63_update_client(client);
565                results[0] = data->alarms;
566                *nrels_mag = 1;
567        }
568}
569
570static void lm63_fan(struct i2c_client *client, int operation,
571        int ctl_name, int *nrels_mag, long *results)
572{
573        struct lm63_data *data = client->data;
574
575        if (operation == SENSORS_PROC_REAL_INFO)
576                *nrels_mag = 0; /* magnitude */
577        else if (operation == SENSORS_PROC_REAL_READ) {
578                if (!(data->config & 0x04)) { /* tachometer disabled */
579                        results[0] = 0;
580                        *nrels_mag = 1;
581                        return;
582                }
583
584                lm63_update_client(client);
585                results[0] = FAN_FROM_REG(data->fan1_low);
586                results[1] = FAN_FROM_REG(data->fan1_input);
587                *nrels_mag = 2;
588        } else if (operation == SENSORS_PROC_REAL_WRITE) {
589                if (!(data->config & 0x04)) /* tachometer disabled */
590                        return;
591
592                if (*nrels_mag >= 1) {
593                        data->fan1_low = FAN_TO_REG(results[0]);
594                        i2c_smbus_write_byte_data(client,
595                                LM63_REG_TACH_LIMIT_LSB,
596                                data->fan1_low & 0xFF);
597                        i2c_smbus_write_byte_data(client,
598                                LM63_REG_TACH_LIMIT_MSB,
599                                data->fan1_low >> 8);
600                }
601        }
602}
603
604static void lm63_pwm(struct i2c_client *client, int operation,
605        int ctl_name, int *nrels_mag, long *results)
606{
607        struct lm63_data *data = client->data;
608
609        if (operation == SENSORS_PROC_REAL_INFO)
610                *nrels_mag = 0; /* magnitude */
611        else if (operation == SENSORS_PROC_REAL_READ) {
612                lm63_update_client(client);
613                results[0] = data->pwm1_value >= 2 * data->pwm1_freq ? 255 :
614                             (data->pwm1_value * 255 + data->pwm1_freq) /
615                             (2 * data->pwm1_freq);
616                results[1] = data->config_fan & 0x20 ? 1 : 2;
617                *nrels_mag = 2;
618        } else if (operation == SENSORS_PROC_REAL_WRITE) {
619                if (*nrels_mag >= 1 && (data->config_fan & 0x20)) {
620                        data->pwm1_value = results[0] <= 0 ? 0 :
621                                results[0] >= 255 ? 2 * data->pwm1_freq :
622                                (results[0] * data->pwm1_freq * 2 + 127) / 255;
623                        i2c_smbus_write_byte_data(client, LM63_REG_PWM_VALUE,
624                                data->pwm1_value);
625                }
626        }
627}
628
629static int __init lm63_init(void)
630{
631        printk(KERN_INFO "lm63 version %s (%s)\n", LM_VERSION, LM_DATE);
632        return i2c_add_driver(&lm63_driver);
633}
634
635static void __exit lm63_exit(void)
636{
637        i2c_del_driver(&lm63_driver);
638}
639
640MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
641MODULE_DESCRIPTION("LM63 sensor driver");
642MODULE_LICENSE("GPL");
643
644module_init(lm63_init);
645module_exit(lm63_exit);
Note: See TracBrowser for help on using the browser.