1b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
2b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * emc6w201.c - Hardware monitoring driver for the SMSC EMC6W201
3b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Copyright (C) 2011  Jean Delvare <khali@linux-fr.org>
4b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare *
5b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * This program is free software; you can redistribute it and/or modify
6b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * it under the terms of the GNU General Public License as published by
7b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * the Free Software Foundation; either version 2 of the License, or
8b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * (at your option) any later version.
9b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare *
10b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * This program is distributed in the hope that it will be useful,
11b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * but WITHOUT ANY WARRANTY; without even the implied warranty of
12b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * GNU General Public License for more details.
14b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare *
15b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * You should have received a copy of the GNU General Public License
16b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * along with this program; if not, write to the Free Software
17b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
19b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
20b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/module.h>
21b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/delay.h>
22b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/init.h>
23b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/slab.h>
24b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/jiffies.h>
25b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/i2c.h>
26b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/hwmon.h>
27b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/hwmon-sysfs.h>
28b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/err.h>
29b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#include <linux/mutex.h>
30b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
31b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
32b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Addresses to scan
33b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
34b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
35b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic const unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
36b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
37b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
38b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * The EMC6W201 registers
39b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
40b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
41b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_IN(nr)		(0x20 + (nr))
42b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_TEMP(nr)		(0x26 + (nr))
43b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_FAN(nr)		(0x2C + (nr) * 2)
44b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_COMPANY		0x3E
45b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_VERSTEP		0x3F
46b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_CONFIG		0x40
47b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_IN_LOW(nr)		(0x4A + (nr) * 2)
48b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_IN_HIGH(nr)	(0x4B + (nr) * 2)
49b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_TEMP_LOW(nr)	(0x56 + (nr) * 2)
50b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_TEMP_HIGH(nr)	(0x57 + (nr) * 2)
51b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare#define EMC6W201_REG_FAN_MIN(nr)	(0x62 + (nr) * 2)
52b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
53b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvareenum { input, min, max } subfeature;
54b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
55b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
56b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Per-device data
57b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
58b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
59b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestruct emc6w201_data {
60b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct device *hwmon_dev;
61b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct mutex update_lock;
62b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	char valid; /* zero until following fields are valid */
63b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	unsigned long last_updated; /* in jiffies */
64b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
65b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	/* registers values */
66b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	u8 in[3][6];
67b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	s8 temp[3][6];
68b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	u16 fan[2][5];
69b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare};
70b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
71b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
72b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Combine LSB and MSB registers in a single value
73b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Locking: must be called with data->update_lock held
74b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
75b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic u16 emc6w201_read16(struct i2c_client *client, u8 reg)
76b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
77b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int lsb, msb;
78b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
79b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	lsb = i2c_smbus_read_byte_data(client, reg);
80b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	msb = i2c_smbus_read_byte_data(client, reg + 1);
81b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	if (unlikely(lsb < 0 || msb < 0)) {
82b6b2a1e8068684baf67307a994180976b7c443edJean Delvare		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
83b6b2a1e8068684baf67307a994180976b7c443edJean Delvare			16, "read", reg);
84b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return 0xFFFF;	/* Arbitrary value */
85b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	}
86b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
87b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return (msb << 8) | lsb;
88b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
89b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
90b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
91b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Write 16-bit value to LSB and MSB registers
92b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Locking: must be called with data->update_lock held
93b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
94b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic int emc6w201_write16(struct i2c_client *client, u8 reg, u16 val)
95b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
96b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int err;
97b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
98b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	err = i2c_smbus_write_byte_data(client, reg, val & 0xff);
99b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	if (likely(!err))
100b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		err = i2c_smbus_write_byte_data(client, reg + 1, val >> 8);
101b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	if (unlikely(err < 0))
102b6b2a1e8068684baf67307a994180976b7c443edJean Delvare		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
103b6b2a1e8068684baf67307a994180976b7c443edJean Delvare			16, "write", reg);
104b6b2a1e8068684baf67307a994180976b7c443edJean Delvare
105b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	return err;
106b6b2a1e8068684baf67307a994180976b7c443edJean Delvare}
107b6b2a1e8068684baf67307a994180976b7c443edJean Delvare
108b6b2a1e8068684baf67307a994180976b7c443edJean Delvare/* Read 8-bit value from register */
109b6b2a1e8068684baf67307a994180976b7c443edJean Delvarestatic u8 emc6w201_read8(struct i2c_client *client, u8 reg)
110b6b2a1e8068684baf67307a994180976b7c443edJean Delvare{
111b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	int val;
112b6b2a1e8068684baf67307a994180976b7c443edJean Delvare
113b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	val = i2c_smbus_read_byte_data(client, reg);
114b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	if (unlikely(val < 0)) {
115b6b2a1e8068684baf67307a994180976b7c443edJean Delvare		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
116b6b2a1e8068684baf67307a994180976b7c443edJean Delvare			8, "read", reg);
117b6b2a1e8068684baf67307a994180976b7c443edJean Delvare		return 0x00;	/* Arbitrary value */
118b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	}
119b6b2a1e8068684baf67307a994180976b7c443edJean Delvare
120b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	return val;
121b6b2a1e8068684baf67307a994180976b7c443edJean Delvare}
122b6b2a1e8068684baf67307a994180976b7c443edJean Delvare
123b6b2a1e8068684baf67307a994180976b7c443edJean Delvare/* Write 8-bit value to register */
124b6b2a1e8068684baf67307a994180976b7c443edJean Delvarestatic int emc6w201_write8(struct i2c_client *client, u8 reg, u8 val)
125b6b2a1e8068684baf67307a994180976b7c443edJean Delvare{
126b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	int err;
127b6b2a1e8068684baf67307a994180976b7c443edJean Delvare
128b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	err = i2c_smbus_write_byte_data(client, reg, val);
129b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	if (unlikely(err < 0))
130b6b2a1e8068684baf67307a994180976b7c443edJean Delvare		dev_err(&client->dev, "%d-bit %s failed at 0x%02x\n",
131b6b2a1e8068684baf67307a994180976b7c443edJean Delvare			8, "write", reg);
132b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
133b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return err;
134b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
135b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
136b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic struct emc6w201_data *emc6w201_update_device(struct device *dev)
137b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
138b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct i2c_client *client = to_i2c_client(dev);
139b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = i2c_get_clientdata(client);
140b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int nr;
141b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
142b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_lock(&data->update_lock);
143b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
144b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
145b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		for (nr = 0; nr < 6; nr++) {
146b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->in[input][nr] =
147b6b2a1e8068684baf67307a994180976b7c443edJean Delvare				emc6w201_read8(client,
148b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_IN(nr));
149b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->in[min][nr] =
150b6b2a1e8068684baf67307a994180976b7c443edJean Delvare				emc6w201_read8(client,
151b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_IN_LOW(nr));
152b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->in[max][nr] =
153b6b2a1e8068684baf67307a994180976b7c443edJean Delvare				emc6w201_read8(client,
154b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_IN_HIGH(nr));
155b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		}
156b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
157b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		for (nr = 0; nr < 6; nr++) {
158b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->temp[input][nr] =
159b6b2a1e8068684baf67307a994180976b7c443edJean Delvare				emc6w201_read8(client,
160b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_TEMP(nr));
161b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->temp[min][nr] =
162b6b2a1e8068684baf67307a994180976b7c443edJean Delvare				emc6w201_read8(client,
163b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_TEMP_LOW(nr));
164b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->temp[max][nr] =
165b6b2a1e8068684baf67307a994180976b7c443edJean Delvare				emc6w201_read8(client,
166b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_TEMP_HIGH(nr));
167b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		}
168b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
169b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		for (nr = 0; nr < 5; nr++) {
170b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->fan[input][nr] =
171b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare				emc6w201_read16(client,
172b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_FAN(nr));
173b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			data->fan[min][nr] =
174b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare				emc6w201_read16(client,
175b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare						EMC6W201_REG_FAN_MIN(nr));
176b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		}
177b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
178b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		data->last_updated = jiffies;
179b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		data->valid = 1;
180b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	}
181b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
182b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_unlock(&data->update_lock);
183b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
184b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return data;
185b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
186b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
187b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
188b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Sysfs callback functions
189b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
190b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
191b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic const u16 nominal_mv[6] = { 2500, 1500, 3300, 5000, 1500, 1500 };
192b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
193b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic ssize_t show_in(struct device *dev, struct device_attribute *devattr,
194b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	char *buf)
195b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
196b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = emc6w201_update_device(dev);
197b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int sf = to_sensor_dev_attr_2(devattr)->index;
198b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int nr = to_sensor_dev_attr_2(devattr)->nr;
199b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
200b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return sprintf(buf, "%u\n",
201b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		       (unsigned)data->in[sf][nr] * nominal_mv[nr] / 0xC0);
202b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
203b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
204b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic ssize_t set_in(struct device *dev, struct device_attribute *devattr,
205b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		      const char *buf, size_t count)
206b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
207b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct i2c_client *client = to_i2c_client(dev);
208b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = i2c_get_clientdata(client);
209b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int sf = to_sensor_dev_attr_2(devattr)->index;
210b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int nr = to_sensor_dev_attr_2(devattr)->nr;
211b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int err;
212b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	long val;
213b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	u8 reg;
214b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
215179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	err = kstrtol(buf, 10, &val);
216b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (err < 0)
217b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return err;
218b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
219b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	val = DIV_ROUND_CLOSEST(val * 0xC0, nominal_mv[nr]);
220b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	reg = (sf == min) ? EMC6W201_REG_IN_LOW(nr)
221b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			  : EMC6W201_REG_IN_HIGH(nr);
222b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
223b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_lock(&data->update_lock);
224b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	data->in[sf][nr] = SENSORS_LIMIT(val, 0, 255);
225b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	err = emc6w201_write8(client, reg, data->in[sf][nr]);
226b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_unlock(&data->update_lock);
227b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
228b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return err < 0 ? err : count;
229b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
230b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
231b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
232b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	char *buf)
233b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
234b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = emc6w201_update_device(dev);
235b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int sf = to_sensor_dev_attr_2(devattr)->index;
236b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int nr = to_sensor_dev_attr_2(devattr)->nr;
237b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
238b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return sprintf(buf, "%d\n", (int)data->temp[sf][nr] * 1000);
239b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
240b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
241b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic ssize_t set_temp(struct device *dev, struct device_attribute *devattr,
242b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			const char *buf, size_t count)
243b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
244b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct i2c_client *client = to_i2c_client(dev);
245b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = i2c_get_clientdata(client);
246b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int sf = to_sensor_dev_attr_2(devattr)->index;
247b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int nr = to_sensor_dev_attr_2(devattr)->nr;
248b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int err;
249b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	long val;
250b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	u8 reg;
251b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
252179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	err = kstrtol(buf, 10, &val);
253b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (err < 0)
254b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return err;
255b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
256b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	val /= 1000;
257b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	reg = (sf == min) ? EMC6W201_REG_TEMP_LOW(nr)
258b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			  : EMC6W201_REG_TEMP_HIGH(nr);
259b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
260b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_lock(&data->update_lock);
261b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	data->temp[sf][nr] = SENSORS_LIMIT(val, -127, 128);
262b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	err = emc6w201_write8(client, reg, data->temp[sf][nr]);
263b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_unlock(&data->update_lock);
264b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
265b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return err < 0 ? err : count;
266b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
267b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
268b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
269b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	char *buf)
270b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
271b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = emc6w201_update_device(dev);
272b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int sf = to_sensor_dev_attr_2(devattr)->index;
273b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int nr = to_sensor_dev_attr_2(devattr)->nr;
274b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	unsigned rpm;
275b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
276b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (data->fan[sf][nr] == 0 || data->fan[sf][nr] == 0xFFFF)
277b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		rpm = 0;
278b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	else
279b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		rpm = 5400000U / data->fan[sf][nr];
280b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
281b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return sprintf(buf, "%u\n", rpm);
282b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
283b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
284b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic ssize_t set_fan(struct device *dev, struct device_attribute *devattr,
285b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		       const char *buf, size_t count)
286b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
287b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct i2c_client *client = to_i2c_client(dev);
288b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = i2c_get_clientdata(client);
289b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int sf = to_sensor_dev_attr_2(devattr)->index;
290b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int nr = to_sensor_dev_attr_2(devattr)->nr;
291b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int err;
292b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	unsigned long val;
293b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
294179c4fdb565dd2157e5dfe89318b74868e3b523dFrans Meulenbroeks	err = kstrtoul(buf, 10, &val);
295b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (err < 0)
296b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return err;
297b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
298b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (val == 0) {
299b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		val = 0xFFFF;
300b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	} else {
301b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		val = DIV_ROUND_CLOSEST(5400000U, val);
302b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		val = SENSORS_LIMIT(val, 0, 0xFFFE);
303b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	}
304b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
305b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_lock(&data->update_lock);
306b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	data->fan[sf][nr] = val;
307b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	err = emc6w201_write16(client, EMC6W201_REG_FAN_MIN(nr),
308b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			       data->fan[sf][nr]);
309b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_unlock(&data->update_lock);
310b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
311b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return err < 0 ? err : count;
312b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
313b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
314b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in0_input, S_IRUGO, show_in, NULL, 0, input);
315b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in0_min, S_IRUGO | S_IWUSR, show_in, set_in,
316b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    0, min);
317b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in0_max, S_IRUGO | S_IWUSR, show_in, set_in,
318b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    0, max);
319b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in1_input, S_IRUGO, show_in, NULL, 1, input);
320b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in1_min, S_IRUGO | S_IWUSR, show_in, set_in,
321b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    1, min);
322b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in1_max, S_IRUGO | S_IWUSR, show_in, set_in,
323b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    1, max);
324b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in2_input, S_IRUGO, show_in, NULL, 2, input);
325b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in2_min, S_IRUGO | S_IWUSR, show_in, set_in,
326b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    2, min);
327b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in2_max, S_IRUGO | S_IWUSR, show_in, set_in,
328b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    2, max);
329b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in3_input, S_IRUGO, show_in, NULL, 3, input);
330b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in3_min, S_IRUGO | S_IWUSR, show_in, set_in,
331b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    3, min);
332b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in3_max, S_IRUGO | S_IWUSR, show_in, set_in,
333b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    3, max);
334b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 4, input);
335b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in4_min, S_IRUGO | S_IWUSR, show_in, set_in,
336b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    4, min);
337b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in4_max, S_IRUGO | S_IWUSR, show_in, set_in,
338b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    4, max);
339b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 5, input);
340b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in5_min, S_IRUGO | S_IWUSR, show_in, set_in,
341b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    5, min);
342b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(in5_max, S_IRUGO | S_IWUSR, show_in, set_in,
343b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    5, max);
344b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
345b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, input);
346b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp1_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
347b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    0, min);
348b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp1_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
349b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    0, max);
350b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 1, input);
351b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp2_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
352b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    1, min);
353b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp2_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
354b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    1, max);
355b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 2, input);
356b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp3_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
357b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    2, min);
358b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp3_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
359b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    2, max);
360b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp4_input, S_IRUGO, show_temp, NULL, 3, input);
361b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp4_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
362b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    3, min);
363b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp4_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
364b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    3, max);
365b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp5_input, S_IRUGO, show_temp, NULL, 4, input);
366b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp5_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
367b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    4, min);
368b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp5_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
369b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    4, max);
370b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp6_input, S_IRUGO, show_temp, NULL, 5, input);
371b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp6_min, S_IRUGO | S_IWUSR, show_temp, set_temp,
372b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    5, min);
373b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(temp6_max, S_IRUGO | S_IWUSR, show_temp, set_temp,
374b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    5, max);
375b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
376b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, input);
377b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan1_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
378b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    0, min);
379b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan2_input, S_IRUGO, show_fan, NULL, 1, input);
380b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan2_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
381b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    1, min);
382b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan3_input, S_IRUGO, show_fan, NULL, 2, input);
383b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan3_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
384b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    2, min);
385b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan4_input, S_IRUGO, show_fan, NULL, 3, input);
386b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan4_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
387b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    3, min);
388b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan5_input, S_IRUGO, show_fan, NULL, 4, input);
389b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic SENSOR_DEVICE_ATTR_2(fan5_min, S_IRUGO | S_IWUSR, show_fan, set_fan,
390b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			    4, min);
391b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
392b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic struct attribute *emc6w201_attributes[] = {
393b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in0_input.dev_attr.attr,
394b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in0_min.dev_attr.attr,
395b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in0_max.dev_attr.attr,
396b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in1_input.dev_attr.attr,
397b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in1_min.dev_attr.attr,
398b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in1_max.dev_attr.attr,
399b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in2_input.dev_attr.attr,
400b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in2_min.dev_attr.attr,
401b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in2_max.dev_attr.attr,
402b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in3_input.dev_attr.attr,
403b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in3_min.dev_attr.attr,
404b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in3_max.dev_attr.attr,
405b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in4_input.dev_attr.attr,
406b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in4_min.dev_attr.attr,
407b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in4_max.dev_attr.attr,
408b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in5_input.dev_attr.attr,
409b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in5_min.dev_attr.attr,
410b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_in5_max.dev_attr.attr,
411b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
412b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp1_input.dev_attr.attr,
413b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp1_min.dev_attr.attr,
414b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp1_max.dev_attr.attr,
415b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp2_input.dev_attr.attr,
416b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp2_min.dev_attr.attr,
417b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp2_max.dev_attr.attr,
418b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp3_input.dev_attr.attr,
419b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp3_min.dev_attr.attr,
420b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp3_max.dev_attr.attr,
421b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp4_input.dev_attr.attr,
422b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp4_min.dev_attr.attr,
423b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp4_max.dev_attr.attr,
424b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp5_input.dev_attr.attr,
425b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp5_min.dev_attr.attr,
426b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp5_max.dev_attr.attr,
427b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp6_input.dev_attr.attr,
428b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp6_min.dev_attr.attr,
429b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_temp6_max.dev_attr.attr,
430b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
431b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan1_input.dev_attr.attr,
432b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan1_min.dev_attr.attr,
433b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan2_input.dev_attr.attr,
434b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan2_min.dev_attr.attr,
435b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan3_input.dev_attr.attr,
436b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan3_min.dev_attr.attr,
437b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan4_input.dev_attr.attr,
438b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan4_min.dev_attr.attr,
439b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan5_input.dev_attr.attr,
440b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	&sensor_dev_attr_fan5_min.dev_attr.attr,
441b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	NULL
442b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare};
443b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
444b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic const struct attribute_group emc6w201_group = {
445b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.attrs = emc6w201_attributes,
446b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare};
447b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
448b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/*
449b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare * Driver interface
450b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare */
451b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
452b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare/* Return 0 if detection is successful, -ENODEV otherwise */
453b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic int emc6w201_detect(struct i2c_client *client,
454b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			   struct i2c_board_info *info)
455b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
456b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct i2c_adapter *adapter = client->adapter;
457b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int company, verstep, config;
458b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
459b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
460b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return -ENODEV;
461b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
462b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	/* Identification */
463b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	company = i2c_smbus_read_byte_data(client, EMC6W201_REG_COMPANY);
464b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (company != 0x5C)
465b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return -ENODEV;
466b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	verstep = i2c_smbus_read_byte_data(client, EMC6W201_REG_VERSTEP);
467b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (verstep < 0 || (verstep & 0xF0) != 0xB0)
468b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return -ENODEV;
469b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if ((verstep & 0x0F) > 2) {
470b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		dev_dbg(&client->dev, "Unknwown EMC6W201 stepping %d\n",
471b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			verstep & 0x0F);
472b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return -ENODEV;
473b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	}
474b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
475b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	/* Check configuration */
476b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	config = i2c_smbus_read_byte_data(client, EMC6W201_REG_CONFIG);
477b6b2a1e8068684baf67307a994180976b7c443edJean Delvare	if (config < 0 || (config & 0xF4) != 0x04)
478b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return -ENODEV;
479b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (!(config & 0x01)) {
480b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		dev_err(&client->dev, "Monitoring not enabled\n");
481b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		return -ENODEV;
482b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	}
483b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
484b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	strlcpy(info->type, "emc6w201", I2C_NAME_SIZE);
485b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
486b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return 0;
487b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
488b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
489b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic int emc6w201_probe(struct i2c_client *client,
490b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare			  const struct i2c_device_id *id)
491b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
492b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data;
493b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	int err;
494b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
495b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	data = kzalloc(sizeof(struct emc6w201_data), GFP_KERNEL);
496b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (!data) {
497b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		err = -ENOMEM;
498b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		goto exit;
499b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	}
500b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
501b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	i2c_set_clientdata(client, data);
502b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	mutex_init(&data->update_lock);
503b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
504b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	/* Create sysfs attribute */
505b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	err = sysfs_create_group(&client->dev.kobj, &emc6w201_group);
506b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (err)
507b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		goto exit_free;
508b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
509b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	/* Expose as a hwmon device */
510b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	data->hwmon_dev = hwmon_device_register(&client->dev);
511b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	if (IS_ERR(data->hwmon_dev)) {
512b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		err = PTR_ERR(data->hwmon_dev);
513b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		goto exit_remove;
514b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	}
515b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
516b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return 0;
517b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
518b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare exit_remove:
519b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
520b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare exit_free:
521b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	kfree(data);
522b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare exit:
523b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return err;
524b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
525b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
526b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic int emc6w201_remove(struct i2c_client *client)
527b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare{
528b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	struct emc6w201_data *data = i2c_get_clientdata(client);
529b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
530b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	hwmon_device_unregister(data->hwmon_dev);
531b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	sysfs_remove_group(&client->dev.kobj, &emc6w201_group);
532b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	kfree(data);
533b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
534b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	return 0;
535b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare}
536b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
537b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic const struct i2c_device_id emc6w201_id[] = {
538b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	{ "emc6w201", 0 },
539b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	{ }
540b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare};
541b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean DelvareMODULE_DEVICE_TABLE(i2c, emc6w201_id);
542b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
543b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvarestatic struct i2c_driver emc6w201_driver = {
544b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.class		= I2C_CLASS_HWMON,
545b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.driver = {
546b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare		.name	= "emc6w201",
547b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	},
548b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.probe		= emc6w201_probe,
549b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.remove		= emc6w201_remove,
550b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.id_table	= emc6w201_id,
551b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.detect		= emc6w201_detect,
552b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare	.address_list	= normal_i2c,
553b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare};
554b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
555f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(emc6w201_driver);
556b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean Delvare
557b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean DelvareMODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
558b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean DelvareMODULE_DESCRIPTION("SMSC EMC6W201 hardware monitoring driver");
559b0b349a85d3df00a40a8bd398e4a151fd8e91bbeJean DelvareMODULE_LICENSE("GPL");
560