~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/hwmon/sch5636.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************
 
2
 *   Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>                *
 
3
 *                                                                         *
 
4
 *   This program is free software; you can redistribute it and/or modify  *
 
5
 *   it under the terms of the GNU General Public License as published by  *
 
6
 *   the Free Software Foundation; either version 2 of the License, or     *
 
7
 *   (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                         *
 
16
 *   Free Software Foundation, Inc.,                                       *
 
17
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 
18
 ***************************************************************************/
 
19
 
 
20
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
21
 
 
22
#include <linux/module.h>
 
23
#include <linux/init.h>
 
24
#include <linux/slab.h>
 
25
#include <linux/jiffies.h>
 
26
#include <linux/platform_device.h>
 
27
#include <linux/hwmon.h>
 
28
#include <linux/hwmon-sysfs.h>
 
29
#include <linux/err.h>
 
30
#include <linux/mutex.h>
 
31
#include "sch56xx-common.h"
 
32
 
 
33
#define DRVNAME "sch5636"
 
34
#define DEVNAME "theseus" /* We only support one model for now */
 
35
 
 
36
#define SCH5636_REG_FUJITSU_ID          0x780
 
37
#define SCH5636_REG_FUJITSU_REV         0x783
 
38
 
 
39
#define SCH5636_NO_INS                  5
 
40
#define SCH5636_NO_TEMPS                16
 
41
#define SCH5636_NO_FANS                 8
 
42
 
 
43
static const u16 SCH5636_REG_IN_VAL[SCH5636_NO_INS] = {
 
44
        0x22, 0x23, 0x24, 0x25, 0x189 };
 
45
static const u16 SCH5636_REG_IN_FACTORS[SCH5636_NO_INS] = {
 
46
        4400, 1500, 4000, 4400, 16000 };
 
47
static const char * const SCH5636_IN_LABELS[SCH5636_NO_INS] = {
 
48
        "3.3V", "VREF", "VBAT", "3.3AUX", "12V" };
 
49
 
 
50
static const u16 SCH5636_REG_TEMP_VAL[SCH5636_NO_TEMPS] = {
 
51
        0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181,
 
52
        0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C };
 
53
#define SCH5636_REG_TEMP_CTRL(i)        (0x790 + (i))
 
54
#define SCH5636_TEMP_WORKING            0x01
 
55
#define SCH5636_TEMP_ALARM              0x02
 
56
#define SCH5636_TEMP_DEACTIVATED        0x80
 
57
 
 
58
static const u16 SCH5636_REG_FAN_VAL[SCH5636_NO_FANS] = {
 
59
        0x2C, 0x2E, 0x30, 0x32, 0x62, 0x64, 0x66, 0x68 };
 
60
#define SCH5636_REG_FAN_CTRL(i)         (0x880 + (i))
 
61
/* FAULT in datasheet, but acts as an alarm */
 
62
#define SCH5636_FAN_ALARM               0x04
 
63
#define SCH5636_FAN_NOT_PRESENT         0x08
 
64
#define SCH5636_FAN_DEACTIVATED         0x80
 
65
 
 
66
 
 
67
struct sch5636_data {
 
68
        unsigned short addr;
 
69
        struct device *hwmon_dev;
 
70
 
 
71
        struct mutex update_lock;
 
72
        char valid;                     /* !=0 if following fields are valid */
 
73
        unsigned long last_updated;     /* In jiffies */
 
74
        u8 in[SCH5636_NO_INS];
 
75
        u8 temp_val[SCH5636_NO_TEMPS];
 
76
        u8 temp_ctrl[SCH5636_NO_TEMPS];
 
77
        u16 fan_val[SCH5636_NO_FANS];
 
78
        u8 fan_ctrl[SCH5636_NO_FANS];
 
79
};
 
80
 
 
81
static struct sch5636_data *sch5636_update_device(struct device *dev)
 
82
{
 
83
        struct sch5636_data *data = dev_get_drvdata(dev);
 
84
        struct sch5636_data *ret = data;
 
85
        int i, val;
 
86
 
 
87
        mutex_lock(&data->update_lock);
 
88
 
 
89
        /* Cache the values for 1 second */
 
90
        if (data->valid && !time_after(jiffies, data->last_updated + HZ))
 
91
                goto abort;
 
92
 
 
93
        for (i = 0; i < SCH5636_NO_INS; i++) {
 
94
                val = sch56xx_read_virtual_reg(data->addr,
 
95
                                               SCH5636_REG_IN_VAL[i]);
 
96
                if (unlikely(val < 0)) {
 
97
                        ret = ERR_PTR(val);
 
98
                        goto abort;
 
99
                }
 
100
                data->in[i] = val;
 
101
        }
 
102
 
 
103
        for (i = 0; i < SCH5636_NO_TEMPS; i++) {
 
104
                if (data->temp_ctrl[i] & SCH5636_TEMP_DEACTIVATED)
 
105
                        continue;
 
106
 
 
107
                val = sch56xx_read_virtual_reg(data->addr,
 
108
                                               SCH5636_REG_TEMP_VAL[i]);
 
109
                if (unlikely(val < 0)) {
 
110
                        ret = ERR_PTR(val);
 
111
                        goto abort;
 
112
                }
 
113
                data->temp_val[i] = val;
 
114
 
 
115
                val = sch56xx_read_virtual_reg(data->addr,
 
116
                                               SCH5636_REG_TEMP_CTRL(i));
 
117
                if (unlikely(val < 0)) {
 
118
                        ret = ERR_PTR(val);
 
119
                        goto abort;
 
120
                }
 
121
                data->temp_ctrl[i] = val;
 
122
                /* Alarms need to be explicitly write-cleared */
 
123
                if (val & SCH5636_TEMP_ALARM) {
 
124
                        sch56xx_write_virtual_reg(data->addr,
 
125
                                                SCH5636_REG_TEMP_CTRL(i), val);
 
126
                }
 
127
        }
 
128
 
 
129
        for (i = 0; i < SCH5636_NO_FANS; i++) {
 
130
                if (data->fan_ctrl[i] & SCH5636_FAN_DEACTIVATED)
 
131
                        continue;
 
132
 
 
133
                val = sch56xx_read_virtual_reg16(data->addr,
 
134
                                                 SCH5636_REG_FAN_VAL[i]);
 
135
                if (unlikely(val < 0)) {
 
136
                        ret = ERR_PTR(val);
 
137
                        goto abort;
 
138
                }
 
139
                data->fan_val[i] = val;
 
140
 
 
141
                val = sch56xx_read_virtual_reg(data->addr,
 
142
                                               SCH5636_REG_FAN_CTRL(i));
 
143
                if (unlikely(val < 0)) {
 
144
                        ret = ERR_PTR(val);
 
145
                        goto abort;
 
146
                }
 
147
                data->fan_ctrl[i] = val;
 
148
                /* Alarms need to be explicitly write-cleared */
 
149
                if (val & SCH5636_FAN_ALARM) {
 
150
                        sch56xx_write_virtual_reg(data->addr,
 
151
                                                SCH5636_REG_FAN_CTRL(i), val);
 
152
                }
 
153
        }
 
154
 
 
155
        data->last_updated = jiffies;
 
156
        data->valid = 1;
 
157
abort:
 
158
        mutex_unlock(&data->update_lock);
 
159
        return ret;
 
160
}
 
161
 
 
162
static int reg_to_rpm(u16 reg)
 
163
{
 
164
        if (reg == 0)
 
165
                return -EIO;
 
166
        if (reg == 0xffff)
 
167
                return 0;
 
168
 
 
169
        return 5400540 / reg;
 
170
}
 
171
 
 
172
static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
 
173
        char *buf)
 
174
{
 
175
        return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
 
176
}
 
177
 
 
178
static ssize_t show_in_value(struct device *dev, struct device_attribute
 
179
        *devattr, char *buf)
 
180
{
 
181
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
182
        struct sch5636_data *data = sch5636_update_device(dev);
 
183
        int val;
 
184
 
 
185
        if (IS_ERR(data))
 
186
                return PTR_ERR(data);
 
187
 
 
188
        val = DIV_ROUND_CLOSEST(
 
189
                data->in[attr->index] * SCH5636_REG_IN_FACTORS[attr->index],
 
190
                255);
 
191
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 
192
}
 
193
 
 
194
static ssize_t show_in_label(struct device *dev, struct device_attribute
 
195
        *devattr, char *buf)
 
196
{
 
197
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
198
 
 
199
        return snprintf(buf, PAGE_SIZE, "%s\n",
 
200
                        SCH5636_IN_LABELS[attr->index]);
 
201
}
 
202
 
 
203
static ssize_t show_temp_value(struct device *dev, struct device_attribute
 
204
        *devattr, char *buf)
 
205
{
 
206
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
207
        struct sch5636_data *data = sch5636_update_device(dev);
 
208
        int val;
 
209
 
 
210
        if (IS_ERR(data))
 
211
                return PTR_ERR(data);
 
212
 
 
213
        val = (data->temp_val[attr->index] - 64) * 1000;
 
214
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 
215
}
 
216
 
 
217
static ssize_t show_temp_fault(struct device *dev, struct device_attribute
 
218
        *devattr, char *buf)
 
219
{
 
220
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
221
        struct sch5636_data *data = sch5636_update_device(dev);
 
222
        int val;
 
223
 
 
224
        if (IS_ERR(data))
 
225
                return PTR_ERR(data);
 
226
 
 
227
        val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_WORKING) ? 0 : 1;
 
228
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 
229
}
 
230
 
 
231
static ssize_t show_temp_alarm(struct device *dev, struct device_attribute
 
232
        *devattr, char *buf)
 
233
{
 
234
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
235
        struct sch5636_data *data = sch5636_update_device(dev);
 
236
        int val;
 
237
 
 
238
        if (IS_ERR(data))
 
239
                return PTR_ERR(data);
 
240
 
 
241
        val = (data->temp_ctrl[attr->index] & SCH5636_TEMP_ALARM) ? 1 : 0;
 
242
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 
243
}
 
244
 
 
245
static ssize_t show_fan_value(struct device *dev, struct device_attribute
 
246
        *devattr, char *buf)
 
247
{
 
248
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
249
        struct sch5636_data *data = sch5636_update_device(dev);
 
250
        int val;
 
251
 
 
252
        if (IS_ERR(data))
 
253
                return PTR_ERR(data);
 
254
 
 
255
        val = reg_to_rpm(data->fan_val[attr->index]);
 
256
        if (val < 0)
 
257
                return val;
 
258
 
 
259
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 
260
}
 
261
 
 
262
static ssize_t show_fan_fault(struct device *dev, struct device_attribute
 
263
        *devattr, char *buf)
 
264
{
 
265
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
266
        struct sch5636_data *data = sch5636_update_device(dev);
 
267
        int val;
 
268
 
 
269
        if (IS_ERR(data))
 
270
                return PTR_ERR(data);
 
271
 
 
272
        val = (data->fan_ctrl[attr->index] & SCH5636_FAN_NOT_PRESENT) ? 1 : 0;
 
273
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 
274
}
 
275
 
 
276
static ssize_t show_fan_alarm(struct device *dev, struct device_attribute
 
277
        *devattr, char *buf)
 
278
{
 
279
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
 
280
        struct sch5636_data *data = sch5636_update_device(dev);
 
281
        int val;
 
282
 
 
283
        if (IS_ERR(data))
 
284
                return PTR_ERR(data);
 
285
 
 
286
        val = (data->fan_ctrl[attr->index] & SCH5636_FAN_ALARM) ? 1 : 0;
 
287
        return snprintf(buf, PAGE_SIZE, "%d\n", val);
 
288
}
 
289
 
 
290
static struct sensor_device_attribute sch5636_attr[] = {
 
291
        SENSOR_ATTR(name, 0444, show_name, NULL, 0),
 
292
        SENSOR_ATTR(in0_input, 0444, show_in_value, NULL, 0),
 
293
        SENSOR_ATTR(in0_label, 0444, show_in_label, NULL, 0),
 
294
        SENSOR_ATTR(in1_input, 0444, show_in_value, NULL, 1),
 
295
        SENSOR_ATTR(in1_label, 0444, show_in_label, NULL, 1),
 
296
        SENSOR_ATTR(in2_input, 0444, show_in_value, NULL, 2),
 
297
        SENSOR_ATTR(in2_label, 0444, show_in_label, NULL, 2),
 
298
        SENSOR_ATTR(in3_input, 0444, show_in_value, NULL, 3),
 
299
        SENSOR_ATTR(in3_label, 0444, show_in_label, NULL, 3),
 
300
        SENSOR_ATTR(in4_input, 0444, show_in_value, NULL, 4),
 
301
        SENSOR_ATTR(in4_label, 0444, show_in_label, NULL, 4),
 
302
};
 
303
 
 
304
static struct sensor_device_attribute sch5636_temp_attr[] = {
 
305
        SENSOR_ATTR(temp1_input, 0444, show_temp_value, NULL, 0),
 
306
        SENSOR_ATTR(temp1_fault, 0444, show_temp_fault, NULL, 0),
 
307
        SENSOR_ATTR(temp1_alarm, 0444, show_temp_alarm, NULL, 0),
 
308
        SENSOR_ATTR(temp2_input, 0444, show_temp_value, NULL, 1),
 
309
        SENSOR_ATTR(temp2_fault, 0444, show_temp_fault, NULL, 1),
 
310
        SENSOR_ATTR(temp2_alarm, 0444, show_temp_alarm, NULL, 1),
 
311
        SENSOR_ATTR(temp3_input, 0444, show_temp_value, NULL, 2),
 
312
        SENSOR_ATTR(temp3_fault, 0444, show_temp_fault, NULL, 2),
 
313
        SENSOR_ATTR(temp3_alarm, 0444, show_temp_alarm, NULL, 2),
 
314
        SENSOR_ATTR(temp4_input, 0444, show_temp_value, NULL, 3),
 
315
        SENSOR_ATTR(temp4_fault, 0444, show_temp_fault, NULL, 3),
 
316
        SENSOR_ATTR(temp4_alarm, 0444, show_temp_alarm, NULL, 3),
 
317
        SENSOR_ATTR(temp5_input, 0444, show_temp_value, NULL, 4),
 
318
        SENSOR_ATTR(temp5_fault, 0444, show_temp_fault, NULL, 4),
 
319
        SENSOR_ATTR(temp5_alarm, 0444, show_temp_alarm, NULL, 4),
 
320
        SENSOR_ATTR(temp6_input, 0444, show_temp_value, NULL, 5),
 
321
        SENSOR_ATTR(temp6_fault, 0444, show_temp_fault, NULL, 5),
 
322
        SENSOR_ATTR(temp6_alarm, 0444, show_temp_alarm, NULL, 5),
 
323
        SENSOR_ATTR(temp7_input, 0444, show_temp_value, NULL, 6),
 
324
        SENSOR_ATTR(temp7_fault, 0444, show_temp_fault, NULL, 6),
 
325
        SENSOR_ATTR(temp7_alarm, 0444, show_temp_alarm, NULL, 6),
 
326
        SENSOR_ATTR(temp8_input, 0444, show_temp_value, NULL, 7),
 
327
        SENSOR_ATTR(temp8_fault, 0444, show_temp_fault, NULL, 7),
 
328
        SENSOR_ATTR(temp8_alarm, 0444, show_temp_alarm, NULL, 7),
 
329
        SENSOR_ATTR(temp9_input, 0444, show_temp_value, NULL, 8),
 
330
        SENSOR_ATTR(temp9_fault, 0444, show_temp_fault, NULL, 8),
 
331
        SENSOR_ATTR(temp9_alarm, 0444, show_temp_alarm, NULL, 8),
 
332
        SENSOR_ATTR(temp10_input, 0444, show_temp_value, NULL, 9),
 
333
        SENSOR_ATTR(temp10_fault, 0444, show_temp_fault, NULL, 9),
 
334
        SENSOR_ATTR(temp10_alarm, 0444, show_temp_alarm, NULL, 9),
 
335
        SENSOR_ATTR(temp11_input, 0444, show_temp_value, NULL, 10),
 
336
        SENSOR_ATTR(temp11_fault, 0444, show_temp_fault, NULL, 10),
 
337
        SENSOR_ATTR(temp11_alarm, 0444, show_temp_alarm, NULL, 10),
 
338
        SENSOR_ATTR(temp12_input, 0444, show_temp_value, NULL, 11),
 
339
        SENSOR_ATTR(temp12_fault, 0444, show_temp_fault, NULL, 11),
 
340
        SENSOR_ATTR(temp12_alarm, 0444, show_temp_alarm, NULL, 11),
 
341
        SENSOR_ATTR(temp13_input, 0444, show_temp_value, NULL, 12),
 
342
        SENSOR_ATTR(temp13_fault, 0444, show_temp_fault, NULL, 12),
 
343
        SENSOR_ATTR(temp13_alarm, 0444, show_temp_alarm, NULL, 12),
 
344
        SENSOR_ATTR(temp14_input, 0444, show_temp_value, NULL, 13),
 
345
        SENSOR_ATTR(temp14_fault, 0444, show_temp_fault, NULL, 13),
 
346
        SENSOR_ATTR(temp14_alarm, 0444, show_temp_alarm, NULL, 13),
 
347
        SENSOR_ATTR(temp15_input, 0444, show_temp_value, NULL, 14),
 
348
        SENSOR_ATTR(temp15_fault, 0444, show_temp_fault, NULL, 14),
 
349
        SENSOR_ATTR(temp15_alarm, 0444, show_temp_alarm, NULL, 14),
 
350
        SENSOR_ATTR(temp16_input, 0444, show_temp_value, NULL, 15),
 
351
        SENSOR_ATTR(temp16_fault, 0444, show_temp_fault, NULL, 15),
 
352
        SENSOR_ATTR(temp16_alarm, 0444, show_temp_alarm, NULL, 15),
 
353
};
 
354
 
 
355
static struct sensor_device_attribute sch5636_fan_attr[] = {
 
356
        SENSOR_ATTR(fan1_input, 0444, show_fan_value, NULL, 0),
 
357
        SENSOR_ATTR(fan1_fault, 0444, show_fan_fault, NULL, 0),
 
358
        SENSOR_ATTR(fan1_alarm, 0444, show_fan_alarm, NULL, 0),
 
359
        SENSOR_ATTR(fan2_input, 0444, show_fan_value, NULL, 1),
 
360
        SENSOR_ATTR(fan2_fault, 0444, show_fan_fault, NULL, 1),
 
361
        SENSOR_ATTR(fan2_alarm, 0444, show_fan_alarm, NULL, 1),
 
362
        SENSOR_ATTR(fan3_input, 0444, show_fan_value, NULL, 2),
 
363
        SENSOR_ATTR(fan3_fault, 0444, show_fan_fault, NULL, 2),
 
364
        SENSOR_ATTR(fan3_alarm, 0444, show_fan_alarm, NULL, 2),
 
365
        SENSOR_ATTR(fan4_input, 0444, show_fan_value, NULL, 3),
 
366
        SENSOR_ATTR(fan4_fault, 0444, show_fan_fault, NULL, 3),
 
367
        SENSOR_ATTR(fan4_alarm, 0444, show_fan_alarm, NULL, 3),
 
368
        SENSOR_ATTR(fan5_input, 0444, show_fan_value, NULL, 4),
 
369
        SENSOR_ATTR(fan5_fault, 0444, show_fan_fault, NULL, 4),
 
370
        SENSOR_ATTR(fan5_alarm, 0444, show_fan_alarm, NULL, 4),
 
371
        SENSOR_ATTR(fan6_input, 0444, show_fan_value, NULL, 5),
 
372
        SENSOR_ATTR(fan6_fault, 0444, show_fan_fault, NULL, 5),
 
373
        SENSOR_ATTR(fan6_alarm, 0444, show_fan_alarm, NULL, 5),
 
374
        SENSOR_ATTR(fan7_input, 0444, show_fan_value, NULL, 6),
 
375
        SENSOR_ATTR(fan7_fault, 0444, show_fan_fault, NULL, 6),
 
376
        SENSOR_ATTR(fan7_alarm, 0444, show_fan_alarm, NULL, 6),
 
377
        SENSOR_ATTR(fan8_input, 0444, show_fan_value, NULL, 7),
 
378
        SENSOR_ATTR(fan8_fault, 0444, show_fan_fault, NULL, 7),
 
379
        SENSOR_ATTR(fan8_alarm, 0444, show_fan_alarm, NULL, 7),
 
380
};
 
381
 
 
382
static int sch5636_remove(struct platform_device *pdev)
 
383
{
 
384
        struct sch5636_data *data = platform_get_drvdata(pdev);
 
385
        int i;
 
386
 
 
387
        if (data->hwmon_dev)
 
388
                hwmon_device_unregister(data->hwmon_dev);
 
389
 
 
390
        for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++)
 
391
                device_remove_file(&pdev->dev, &sch5636_attr[i].dev_attr);
 
392
 
 
393
        for (i = 0; i < SCH5636_NO_TEMPS * 3; i++)
 
394
                device_remove_file(&pdev->dev,
 
395
                                   &sch5636_temp_attr[i].dev_attr);
 
396
 
 
397
        for (i = 0; i < SCH5636_NO_FANS * 3; i++)
 
398
                device_remove_file(&pdev->dev,
 
399
                                   &sch5636_fan_attr[i].dev_attr);
 
400
 
 
401
        platform_set_drvdata(pdev, NULL);
 
402
        kfree(data);
 
403
 
 
404
        return 0;
 
405
}
 
406
 
 
407
static int __devinit sch5636_probe(struct platform_device *pdev)
 
408
{
 
409
        struct sch5636_data *data;
 
410
        int i, err, val, revision[2];
 
411
        char id[4];
 
412
 
 
413
        data = kzalloc(sizeof(struct sch5636_data), GFP_KERNEL);
 
414
        if (!data)
 
415
                return -ENOMEM;
 
416
 
 
417
        data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
 
418
        mutex_init(&data->update_lock);
 
419
        platform_set_drvdata(pdev, data);
 
420
 
 
421
        for (i = 0; i < 3; i++) {
 
422
                val = sch56xx_read_virtual_reg(data->addr,
 
423
                                               SCH5636_REG_FUJITSU_ID + i);
 
424
                if (val < 0) {
 
425
                        pr_err("Could not read Fujitsu id byte at %#x\n",
 
426
                                SCH5636_REG_FUJITSU_ID + i);
 
427
                        err = val;
 
428
                        goto error;
 
429
                }
 
430
                id[i] = val;
 
431
        }
 
432
        id[i] = '\0';
 
433
 
 
434
        if (strcmp(id, "THS")) {
 
435
                pr_err("Unknown Fujitsu id: %02x%02x%02x\n",
 
436
                       id[0], id[1], id[2]);
 
437
                err = -ENODEV;
 
438
                goto error;
 
439
        }
 
440
 
 
441
        for (i = 0; i < 2; i++) {
 
442
                val = sch56xx_read_virtual_reg(data->addr,
 
443
                                               SCH5636_REG_FUJITSU_REV + i);
 
444
                if (val < 0) {
 
445
                        err = val;
 
446
                        goto error;
 
447
                }
 
448
                revision[i] = val;
 
449
        }
 
450
        pr_info("Found %s chip at %#hx, revison: %d.%02d\n", DEVNAME,
 
451
                data->addr, revision[0], revision[1]);
 
452
 
 
453
        /* Read all temp + fan ctrl registers to determine which are active */
 
454
        for (i = 0; i < SCH5636_NO_TEMPS; i++) {
 
455
                val = sch56xx_read_virtual_reg(data->addr,
 
456
                                               SCH5636_REG_TEMP_CTRL(i));
 
457
                if (unlikely(val < 0)) {
 
458
                        err = val;
 
459
                        goto error;
 
460
                }
 
461
                data->temp_ctrl[i] = val;
 
462
        }
 
463
 
 
464
        for (i = 0; i < SCH5636_NO_FANS; i++) {
 
465
                val = sch56xx_read_virtual_reg(data->addr,
 
466
                                               SCH5636_REG_FAN_CTRL(i));
 
467
                if (unlikely(val < 0)) {
 
468
                        err = val;
 
469
                        goto error;
 
470
                }
 
471
                data->fan_ctrl[i] = val;
 
472
        }
 
473
 
 
474
        for (i = 0; i < ARRAY_SIZE(sch5636_attr); i++) {
 
475
                err = device_create_file(&pdev->dev,
 
476
                                         &sch5636_attr[i].dev_attr);
 
477
                if (err)
 
478
                        goto error;
 
479
        }
 
480
 
 
481
        for (i = 0; i < (SCH5636_NO_TEMPS * 3); i++) {
 
482
                if (data->temp_ctrl[i/3] & SCH5636_TEMP_DEACTIVATED)
 
483
                        continue;
 
484
 
 
485
                err = device_create_file(&pdev->dev,
 
486
                                        &sch5636_temp_attr[i].dev_attr);
 
487
                if (err)
 
488
                        goto error;
 
489
        }
 
490
 
 
491
        for (i = 0; i < (SCH5636_NO_FANS * 3); i++) {
 
492
                if (data->fan_ctrl[i/3] & SCH5636_FAN_DEACTIVATED)
 
493
                        continue;
 
494
 
 
495
                err = device_create_file(&pdev->dev,
 
496
                                        &sch5636_fan_attr[i].dev_attr);
 
497
                if (err)
 
498
                        goto error;
 
499
        }
 
500
 
 
501
        data->hwmon_dev = hwmon_device_register(&pdev->dev);
 
502
        if (IS_ERR(data->hwmon_dev)) {
 
503
                err = PTR_ERR(data->hwmon_dev);
 
504
                data->hwmon_dev = NULL;
 
505
                goto error;
 
506
        }
 
507
 
 
508
        return 0;
 
509
 
 
510
error:
 
511
        sch5636_remove(pdev);
 
512
        return err;
 
513
}
 
514
 
 
515
static struct platform_driver sch5636_driver = {
 
516
        .driver = {
 
517
                .owner  = THIS_MODULE,
 
518
                .name   = DRVNAME,
 
519
        },
 
520
        .probe          = sch5636_probe,
 
521
        .remove         = sch5636_remove,
 
522
};
 
523
 
 
524
module_platform_driver(sch5636_driver);
 
525
 
 
526
MODULE_DESCRIPTION("SMSC SCH5636 Hardware Monitoring Driver");
 
527
MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 
528
MODULE_LICENSE("GPL");