1731b4cace10f105a81d622b70f9a35f577612d63David George/*
2b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * Copyright (c) 2011 David George <david.george@ska.ac.za>
3b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck *
4b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * based on adm1021.c
5b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * some credit to Christoph Scheurer, but largely a rewrite
6b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck *
7b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * This program is free software; you can redistribute it and/or modify
8b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * it under the terms of the GNU General Public License as published by
9b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * the Free Software Foundation; either version 2 of the License, or
10b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * (at your option) any later version.
11b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck *
12b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * This program is distributed in the hope that it will be useful,
13b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * but WITHOUT ANY WARRANTY; without even the implied warranty of
14b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * GNU General Public License for more details.
16b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck *
17b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * You should have received a copy of the GNU General Public License
18b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * along with this program; if not, write to the Free Software
19b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20b6707b78ff3172f03ee197b7e638cf6bc81d4407Guenter Roeck */
21731b4cace10f105a81d622b70f9a35f577612d63David George
22731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/module.h>
23731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/init.h>
24731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/slab.h>
25731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/jiffies.h>
26731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/i2c.h>
27731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/hwmon.h>
28731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/hwmon-sysfs.h>
29731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/err.h>
30731b4cace10f105a81d622b70f9a35f577612d63David George#include <linux/mutex.h>
31731b4cace10f105a81d622b70f9a35f577612d63David George
32731b4cace10f105a81d622b70f9a35f577612d63David George/* Addresses to scan */
33731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic unsigned short max1668_addr_list[] = {
34731b4cace10f105a81d622b70f9a35f577612d63David George	0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b, 0x4c, 0x4d, 0x4e, I2C_CLIENT_END };
35731b4cace10f105a81d622b70f9a35f577612d63David George
36731b4cace10f105a81d622b70f9a35f577612d63David George/* max1668 registers */
37731b4cace10f105a81d622b70f9a35f577612d63David George
38731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_TEMP(nr)	(nr)
39731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_STAT1	0x05
40731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_STAT2	0x06
41731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_MAN_ID	0xfe
42731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_DEV_ID	0xff
43731b4cace10f105a81d622b70f9a35f577612d63David George
44731b4cace10f105a81d622b70f9a35f577612d63David George/* limits */
45731b4cace10f105a81d622b70f9a35f577612d63David George
46731b4cace10f105a81d622b70f9a35f577612d63David George/* write high limits */
47731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_LIMH_WR(nr)	(0x13 + 2 * (nr))
48731b4cace10f105a81d622b70f9a35f577612d63David George/* write low limits */
49731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_LIML_WR(nr)	(0x14 + 2 * (nr))
50731b4cace10f105a81d622b70f9a35f577612d63David George/* read high limits */
51731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_LIMH_RD(nr)	(0x08 + 2 * (nr))
52731b4cace10f105a81d622b70f9a35f577612d63David George/* read low limits */
53731b4cace10f105a81d622b70f9a35f577612d63David George#define MAX1668_REG_LIML_RD(nr)	(0x09 + 2 * (nr))
54731b4cace10f105a81d622b70f9a35f577612d63David George
55731b4cace10f105a81d622b70f9a35f577612d63David George/* manufacturer and device ID Constants */
56731b4cace10f105a81d622b70f9a35f577612d63David George#define MAN_ID_MAXIM		0x4d
57731b4cace10f105a81d622b70f9a35f577612d63David George#define DEV_ID_MAX1668		0x3
58731b4cace10f105a81d622b70f9a35f577612d63David George#define DEV_ID_MAX1805		0x5
59731b4cace10f105a81d622b70f9a35f577612d63David George#define DEV_ID_MAX1989		0xb
60731b4cace10f105a81d622b70f9a35f577612d63David George
61731b4cace10f105a81d622b70f9a35f577612d63David George/* read only mode module parameter */
6290ab5ee94171b3e28de6bb42ee30b527014e0be7Rusty Russellstatic bool read_only;
63731b4cace10f105a81d622b70f9a35f577612d63David Georgemodule_param(read_only, bool, 0);
64731b4cace10f105a81d622b70f9a35f577612d63David GeorgeMODULE_PARM_DESC(read_only, "Don't set any values, read only mode");
65731b4cace10f105a81d622b70f9a35f577612d63David George
66731b4cace10f105a81d622b70f9a35f577612d63David Georgeenum chips { max1668, max1805, max1989 };
67731b4cace10f105a81d622b70f9a35f577612d63David George
68731b4cace10f105a81d622b70f9a35f577612d63David Georgestruct max1668_data {
69731b4cace10f105a81d622b70f9a35f577612d63David George	struct device *hwmon_dev;
70731b4cace10f105a81d622b70f9a35f577612d63David George	enum chips type;
71731b4cace10f105a81d622b70f9a35f577612d63David George
72731b4cace10f105a81d622b70f9a35f577612d63David George	struct mutex update_lock;
73731b4cace10f105a81d622b70f9a35f577612d63David George	char valid;		/* !=0 if following fields are valid */
74731b4cace10f105a81d622b70f9a35f577612d63David George	unsigned long last_updated;	/* In jiffies */
75731b4cace10f105a81d622b70f9a35f577612d63David George
76731b4cace10f105a81d622b70f9a35f577612d63David George	/* 1x local and 4x remote */
77731b4cace10f105a81d622b70f9a35f577612d63David George	s8 temp_max[5];
78731b4cace10f105a81d622b70f9a35f577612d63David George	s8 temp_min[5];
79731b4cace10f105a81d622b70f9a35f577612d63David George	s8 temp[5];
80731b4cace10f105a81d622b70f9a35f577612d63David George	u16 alarms;
81731b4cace10f105a81d622b70f9a35f577612d63David George};
82731b4cace10f105a81d622b70f9a35f577612d63David George
83731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic struct max1668_data *max1668_update_device(struct device *dev)
84731b4cace10f105a81d622b70f9a35f577612d63David George{
85731b4cace10f105a81d622b70f9a35f577612d63David George	struct i2c_client *client = to_i2c_client(dev);
86731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = i2c_get_clientdata(client);
87731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *ret = data;
88731b4cace10f105a81d622b70f9a35f577612d63David George	s32 val;
89731b4cace10f105a81d622b70f9a35f577612d63David George	int i;
90731b4cace10f105a81d622b70f9a35f577612d63David George
91731b4cace10f105a81d622b70f9a35f577612d63David George	mutex_lock(&data->update_lock);
92731b4cace10f105a81d622b70f9a35f577612d63David George
93731b4cace10f105a81d622b70f9a35f577612d63David George	if (data->valid && !time_after(jiffies,
94731b4cace10f105a81d622b70f9a35f577612d63David George			data->last_updated + HZ + HZ / 2))
95731b4cace10f105a81d622b70f9a35f577612d63David George		goto abort;
96731b4cace10f105a81d622b70f9a35f577612d63David George
97731b4cace10f105a81d622b70f9a35f577612d63David George	for (i = 0; i < 5; i++) {
98731b4cace10f105a81d622b70f9a35f577612d63David George		val = i2c_smbus_read_byte_data(client, MAX1668_REG_TEMP(i));
99731b4cace10f105a81d622b70f9a35f577612d63David George		if (unlikely(val < 0)) {
100731b4cace10f105a81d622b70f9a35f577612d63David George			ret = ERR_PTR(val);
101731b4cace10f105a81d622b70f9a35f577612d63David George			goto abort;
102731b4cace10f105a81d622b70f9a35f577612d63David George		}
103731b4cace10f105a81d622b70f9a35f577612d63David George		data->temp[i] = (s8) val;
104731b4cace10f105a81d622b70f9a35f577612d63David George
105731b4cace10f105a81d622b70f9a35f577612d63David George		val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIMH_RD(i));
106731b4cace10f105a81d622b70f9a35f577612d63David George		if (unlikely(val < 0)) {
107731b4cace10f105a81d622b70f9a35f577612d63David George			ret = ERR_PTR(val);
108731b4cace10f105a81d622b70f9a35f577612d63David George			goto abort;
109731b4cace10f105a81d622b70f9a35f577612d63David George		}
110731b4cace10f105a81d622b70f9a35f577612d63David George		data->temp_max[i] = (s8) val;
111731b4cace10f105a81d622b70f9a35f577612d63David George
112731b4cace10f105a81d622b70f9a35f577612d63David George		val = i2c_smbus_read_byte_data(client, MAX1668_REG_LIML_RD(i));
113731b4cace10f105a81d622b70f9a35f577612d63David George		if (unlikely(val < 0)) {
114731b4cace10f105a81d622b70f9a35f577612d63David George			ret = ERR_PTR(val);
115731b4cace10f105a81d622b70f9a35f577612d63David George			goto abort;
116731b4cace10f105a81d622b70f9a35f577612d63David George		}
117731b4cace10f105a81d622b70f9a35f577612d63David George		data->temp_min[i] = (s8) val;
118731b4cace10f105a81d622b70f9a35f577612d63David George	}
119731b4cace10f105a81d622b70f9a35f577612d63David George
120731b4cace10f105a81d622b70f9a35f577612d63David George	val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT1);
121731b4cace10f105a81d622b70f9a35f577612d63David George	if (unlikely(val < 0)) {
122731b4cace10f105a81d622b70f9a35f577612d63David George		ret = ERR_PTR(val);
123731b4cace10f105a81d622b70f9a35f577612d63David George		goto abort;
124731b4cace10f105a81d622b70f9a35f577612d63David George	}
125dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	data->alarms = val << 8;
126731b4cace10f105a81d622b70f9a35f577612d63David George
127731b4cace10f105a81d622b70f9a35f577612d63David George	val = i2c_smbus_read_byte_data(client, MAX1668_REG_STAT2);
128731b4cace10f105a81d622b70f9a35f577612d63David George	if (unlikely(val < 0)) {
129731b4cace10f105a81d622b70f9a35f577612d63David George		ret = ERR_PTR(val);
130731b4cace10f105a81d622b70f9a35f577612d63David George		goto abort;
131731b4cace10f105a81d622b70f9a35f577612d63David George	}
132dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	data->alarms |= val;
133731b4cace10f105a81d622b70f9a35f577612d63David George
134731b4cace10f105a81d622b70f9a35f577612d63David George	data->last_updated = jiffies;
135731b4cace10f105a81d622b70f9a35f577612d63David George	data->valid = 1;
136731b4cace10f105a81d622b70f9a35f577612d63David Georgeabort:
137731b4cace10f105a81d622b70f9a35f577612d63David George	mutex_unlock(&data->update_lock);
138731b4cace10f105a81d622b70f9a35f577612d63David George
139731b4cace10f105a81d622b70f9a35f577612d63David George	return ret;
140731b4cace10f105a81d622b70f9a35f577612d63David George}
141731b4cace10f105a81d622b70f9a35f577612d63David George
142731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic ssize_t show_temp(struct device *dev,
143731b4cace10f105a81d622b70f9a35f577612d63David George			 struct device_attribute *devattr, char *buf)
144731b4cace10f105a81d622b70f9a35f577612d63David George{
145731b4cace10f105a81d622b70f9a35f577612d63David George	int index = to_sensor_dev_attr(devattr)->index;
146731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = max1668_update_device(dev);
147731b4cace10f105a81d622b70f9a35f577612d63David George
148731b4cace10f105a81d622b70f9a35f577612d63David George	if (IS_ERR(data))
149731b4cace10f105a81d622b70f9a35f577612d63David George		return PTR_ERR(data);
150731b4cace10f105a81d622b70f9a35f577612d63David George
151731b4cace10f105a81d622b70f9a35f577612d63David George	return sprintf(buf, "%d\n", data->temp[index] * 1000);
152731b4cace10f105a81d622b70f9a35f577612d63David George}
153731b4cace10f105a81d622b70f9a35f577612d63David George
154731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic ssize_t show_temp_max(struct device *dev,
155731b4cace10f105a81d622b70f9a35f577612d63David George			     struct device_attribute *devattr, char *buf)
156731b4cace10f105a81d622b70f9a35f577612d63David George{
157731b4cace10f105a81d622b70f9a35f577612d63David George	int index = to_sensor_dev_attr(devattr)->index;
158731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = max1668_update_device(dev);
159731b4cace10f105a81d622b70f9a35f577612d63David George
160731b4cace10f105a81d622b70f9a35f577612d63David George	if (IS_ERR(data))
161731b4cace10f105a81d622b70f9a35f577612d63David George		return PTR_ERR(data);
162731b4cace10f105a81d622b70f9a35f577612d63David George
163731b4cace10f105a81d622b70f9a35f577612d63David George	return sprintf(buf, "%d\n", data->temp_max[index] * 1000);
164731b4cace10f105a81d622b70f9a35f577612d63David George}
165731b4cace10f105a81d622b70f9a35f577612d63David George
166731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic ssize_t show_temp_min(struct device *dev,
167731b4cace10f105a81d622b70f9a35f577612d63David George			     struct device_attribute *devattr, char *buf)
168731b4cace10f105a81d622b70f9a35f577612d63David George{
169731b4cace10f105a81d622b70f9a35f577612d63David George	int index = to_sensor_dev_attr(devattr)->index;
170731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = max1668_update_device(dev);
171731b4cace10f105a81d622b70f9a35f577612d63David George
172731b4cace10f105a81d622b70f9a35f577612d63David George	if (IS_ERR(data))
173731b4cace10f105a81d622b70f9a35f577612d63David George		return PTR_ERR(data);
174731b4cace10f105a81d622b70f9a35f577612d63David George
175731b4cace10f105a81d622b70f9a35f577612d63David George	return sprintf(buf, "%d\n", data->temp_min[index] * 1000);
176731b4cace10f105a81d622b70f9a35f577612d63David George}
177731b4cace10f105a81d622b70f9a35f577612d63David George
178731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
179731b4cace10f105a81d622b70f9a35f577612d63David George			  char *buf)
180731b4cace10f105a81d622b70f9a35f577612d63David George{
181731b4cace10f105a81d622b70f9a35f577612d63David George	int index = to_sensor_dev_attr(attr)->index;
182731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = max1668_update_device(dev);
183731b4cace10f105a81d622b70f9a35f577612d63David George
184731b4cace10f105a81d622b70f9a35f577612d63David George	if (IS_ERR(data))
185731b4cace10f105a81d622b70f9a35f577612d63David George		return PTR_ERR(data);
186731b4cace10f105a81d622b70f9a35f577612d63David George
187731b4cace10f105a81d622b70f9a35f577612d63David George	return sprintf(buf, "%u\n", (data->alarms >> index) & 0x1);
188731b4cace10f105a81d622b70f9a35f577612d63David George}
189731b4cace10f105a81d622b70f9a35f577612d63David George
190dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeckstatic ssize_t show_fault(struct device *dev,
191dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck			  struct device_attribute *devattr, char *buf)
192dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck{
193dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	int index = to_sensor_dev_attr(devattr)->index;
194dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	struct max1668_data *data = max1668_update_device(dev);
195dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck
196dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	if (IS_ERR(data))
197dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck		return PTR_ERR(data);
198dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck
199dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	return sprintf(buf, "%u\n",
200dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck		       (data->alarms & (1 << 12)) && data->temp[index] == 127);
201dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck}
202dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck
203731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic ssize_t set_temp_max(struct device *dev,
204731b4cace10f105a81d622b70f9a35f577612d63David George			    struct device_attribute *devattr,
205731b4cace10f105a81d622b70f9a35f577612d63David George			    const char *buf, size_t count)
206731b4cace10f105a81d622b70f9a35f577612d63David George{
207731b4cace10f105a81d622b70f9a35f577612d63David George	int index = to_sensor_dev_attr(devattr)->index;
208731b4cace10f105a81d622b70f9a35f577612d63David George	struct i2c_client *client = to_i2c_client(dev);
209731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = i2c_get_clientdata(client);
210731b4cace10f105a81d622b70f9a35f577612d63David George	long temp;
211731b4cace10f105a81d622b70f9a35f577612d63David George	int ret;
212731b4cace10f105a81d622b70f9a35f577612d63David George
213731b4cace10f105a81d622b70f9a35f577612d63David George	ret = kstrtol(buf, 10, &temp);
214731b4cace10f105a81d622b70f9a35f577612d63David George	if (ret < 0)
215731b4cace10f105a81d622b70f9a35f577612d63David George		return ret;
216731b4cace10f105a81d622b70f9a35f577612d63David George
217731b4cace10f105a81d622b70f9a35f577612d63David George	mutex_lock(&data->update_lock);
218731b4cace10f105a81d622b70f9a35f577612d63David George	data->temp_max[index] = SENSORS_LIMIT(temp/1000, -128, 127);
219731b4cace10f105a81d622b70f9a35f577612d63David George	if (i2c_smbus_write_byte_data(client,
220731b4cace10f105a81d622b70f9a35f577612d63David George					MAX1668_REG_LIMH_WR(index),
221731b4cace10f105a81d622b70f9a35f577612d63David George					data->temp_max[index]))
222731b4cace10f105a81d622b70f9a35f577612d63David George		count = -EIO;
223731b4cace10f105a81d622b70f9a35f577612d63David George	mutex_unlock(&data->update_lock);
224731b4cace10f105a81d622b70f9a35f577612d63David George
225731b4cace10f105a81d622b70f9a35f577612d63David George	return count;
226731b4cace10f105a81d622b70f9a35f577612d63David George}
227731b4cace10f105a81d622b70f9a35f577612d63David George
228731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic ssize_t set_temp_min(struct device *dev,
229731b4cace10f105a81d622b70f9a35f577612d63David George			    struct device_attribute *devattr,
230731b4cace10f105a81d622b70f9a35f577612d63David George			    const char *buf, size_t count)
231731b4cace10f105a81d622b70f9a35f577612d63David George{
232731b4cace10f105a81d622b70f9a35f577612d63David George	int index = to_sensor_dev_attr(devattr)->index;
233731b4cace10f105a81d622b70f9a35f577612d63David George	struct i2c_client *client = to_i2c_client(dev);
234731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = i2c_get_clientdata(client);
235731b4cace10f105a81d622b70f9a35f577612d63David George	long temp;
236731b4cace10f105a81d622b70f9a35f577612d63David George	int ret;
237731b4cace10f105a81d622b70f9a35f577612d63David George
238731b4cace10f105a81d622b70f9a35f577612d63David George	ret = kstrtol(buf, 10, &temp);
239731b4cace10f105a81d622b70f9a35f577612d63David George	if (ret < 0)
240731b4cace10f105a81d622b70f9a35f577612d63David George		return ret;
241731b4cace10f105a81d622b70f9a35f577612d63David George
242731b4cace10f105a81d622b70f9a35f577612d63David George	mutex_lock(&data->update_lock);
243731b4cace10f105a81d622b70f9a35f577612d63David George	data->temp_min[index] = SENSORS_LIMIT(temp/1000, -128, 127);
244731b4cace10f105a81d622b70f9a35f577612d63David George	if (i2c_smbus_write_byte_data(client,
245731b4cace10f105a81d622b70f9a35f577612d63David George					MAX1668_REG_LIML_WR(index),
246731b4cace10f105a81d622b70f9a35f577612d63David George					data->temp_max[index]))
247731b4cace10f105a81d622b70f9a35f577612d63David George		count = -EIO;
248731b4cace10f105a81d622b70f9a35f577612d63David George	mutex_unlock(&data->update_lock);
249731b4cace10f105a81d622b70f9a35f577612d63David George
250731b4cace10f105a81d622b70f9a35f577612d63David George	return count;
251731b4cace10f105a81d622b70f9a35f577612d63David George}
252731b4cace10f105a81d622b70f9a35f577612d63David George
253731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
254731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max,
255731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_max, 0);
256731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp1_min, S_IRUGO, show_temp_min,
257731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_min, 0);
258731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
259731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max,
260731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_max, 1);
261731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp2_min, S_IRUGO, show_temp_min,
262731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_min, 1);
263731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
264731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max,
265731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_max, 2);
266731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp3_min, S_IRUGO, show_temp_min,
267731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_min, 2);
268731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
269731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max,
270731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_max, 3);
271731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp4_min, S_IRUGO, show_temp_min,
272731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_min, 3);
273731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
274731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max,
275731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_max, 4);
276731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp5_min, S_IRUGO, show_temp_min,
277731b4cace10f105a81d622b70f9a35f577612d63David George				set_temp_min, 4);
278731b4cace10f105a81d622b70f9a35f577612d63David George
279731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 14);
280731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 13);
281731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 7);
282731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 6);
283731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp3_min_alarm, S_IRUGO, show_alarm, NULL, 5);
284731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4);
285731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp4_min_alarm, S_IRUGO, show_alarm, NULL, 3);
286731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 2);
287731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp5_min_alarm, S_IRUGO, show_alarm, NULL, 1);
288731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic SENSOR_DEVICE_ATTR(temp5_max_alarm, S_IRUGO, show_alarm, NULL, 0);
289731b4cace10f105a81d622b70f9a35f577612d63David George
290dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
291dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
292dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
293dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeckstatic SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_fault, NULL, 4);
294dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck
295731b4cace10f105a81d622b70f9a35f577612d63David George/* Attributes common to MAX1668, MAX1989 and MAX1805 */
296731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic struct attribute *max1668_attribute_common[] = {
297731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp1_max.dev_attr.attr,
298731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp1_min.dev_attr.attr,
299731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp1_input.dev_attr.attr,
300731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp2_max.dev_attr.attr,
301731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp2_min.dev_attr.attr,
302731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp2_input.dev_attr.attr,
303731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp3_max.dev_attr.attr,
304731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp3_min.dev_attr.attr,
305731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp3_input.dev_attr.attr,
306731b4cace10f105a81d622b70f9a35f577612d63David George
307731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
308731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
309731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
310731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
311731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
312731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp3_min_alarm.dev_attr.attr,
313dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck
314dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	&sensor_dev_attr_temp2_fault.dev_attr.attr,
315dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	&sensor_dev_attr_temp3_fault.dev_attr.attr,
316731b4cace10f105a81d622b70f9a35f577612d63David George	NULL
317731b4cace10f105a81d622b70f9a35f577612d63David George};
318731b4cace10f105a81d622b70f9a35f577612d63David George
319731b4cace10f105a81d622b70f9a35f577612d63David George/* Attributes not present on MAX1805 */
320731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic struct attribute *max1668_attribute_unique[] = {
321731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp4_max.dev_attr.attr,
322731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp4_min.dev_attr.attr,
323731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp4_input.dev_attr.attr,
324731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp5_max.dev_attr.attr,
325731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp5_min.dev_attr.attr,
326731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp5_input.dev_attr.attr,
327731b4cace10f105a81d622b70f9a35f577612d63David George
328731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
329731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp4_min_alarm.dev_attr.attr,
330731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp5_max_alarm.dev_attr.attr,
331731b4cace10f105a81d622b70f9a35f577612d63David George	&sensor_dev_attr_temp5_min_alarm.dev_attr.attr,
332dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck
333dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	&sensor_dev_attr_temp4_fault.dev_attr.attr,
334dabaa0d2b4085a2037d80a40b86ba215f00b601eGuenter Roeck	&sensor_dev_attr_temp5_fault.dev_attr.attr,
335731b4cace10f105a81d622b70f9a35f577612d63David George	NULL
336731b4cace10f105a81d622b70f9a35f577612d63David George};
337731b4cace10f105a81d622b70f9a35f577612d63David George
338587a1f1659e8b330b8738ef4901832a2b63f0bedAl Virostatic umode_t max1668_attribute_mode(struct kobject *kobj,
339731b4cace10f105a81d622b70f9a35f577612d63David George				     struct attribute *attr, int index)
340731b4cace10f105a81d622b70f9a35f577612d63David George{
341587a1f1659e8b330b8738ef4901832a2b63f0bedAl Viro	umode_t ret = S_IRUGO;
342731b4cace10f105a81d622b70f9a35f577612d63David George	if (read_only)
343731b4cace10f105a81d622b70f9a35f577612d63David George		return ret;
344731b4cace10f105a81d622b70f9a35f577612d63David George	if (attr == &sensor_dev_attr_temp1_max.dev_attr.attr ||
345731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp2_max.dev_attr.attr ||
346731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp3_max.dev_attr.attr ||
347731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp4_max.dev_attr.attr ||
348731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp5_max.dev_attr.attr ||
349731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp1_min.dev_attr.attr ||
350731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp2_min.dev_attr.attr ||
351731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp3_min.dev_attr.attr ||
352731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp4_min.dev_attr.attr ||
353731b4cace10f105a81d622b70f9a35f577612d63David George	    attr == &sensor_dev_attr_temp5_min.dev_attr.attr)
354731b4cace10f105a81d622b70f9a35f577612d63David George		ret |= S_IWUSR;
355731b4cace10f105a81d622b70f9a35f577612d63David George	return ret;
356731b4cace10f105a81d622b70f9a35f577612d63David George}
357731b4cace10f105a81d622b70f9a35f577612d63David George
358731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic const struct attribute_group max1668_group_common = {
359731b4cace10f105a81d622b70f9a35f577612d63David George	.attrs = max1668_attribute_common,
360731b4cace10f105a81d622b70f9a35f577612d63David George	.is_visible = max1668_attribute_mode
361731b4cace10f105a81d622b70f9a35f577612d63David George};
362731b4cace10f105a81d622b70f9a35f577612d63David George
363731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic const struct attribute_group max1668_group_unique = {
364731b4cace10f105a81d622b70f9a35f577612d63David George	.attrs = max1668_attribute_unique,
365731b4cace10f105a81d622b70f9a35f577612d63David George	.is_visible = max1668_attribute_mode
366731b4cace10f105a81d622b70f9a35f577612d63David George};
367731b4cace10f105a81d622b70f9a35f577612d63David George
368731b4cace10f105a81d622b70f9a35f577612d63David George/* Return 0 if detection is successful, -ENODEV otherwise */
369731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic int max1668_detect(struct i2c_client *client,
370731b4cace10f105a81d622b70f9a35f577612d63David George			  struct i2c_board_info *info)
371731b4cace10f105a81d622b70f9a35f577612d63David George{
372731b4cace10f105a81d622b70f9a35f577612d63David George	struct i2c_adapter *adapter = client->adapter;
373731b4cace10f105a81d622b70f9a35f577612d63David George	const char *type_name;
374731b4cace10f105a81d622b70f9a35f577612d63David George	int man_id, dev_id;
375731b4cace10f105a81d622b70f9a35f577612d63David George
376731b4cace10f105a81d622b70f9a35f577612d63David George	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
377731b4cace10f105a81d622b70f9a35f577612d63David George		return -ENODEV;
378731b4cace10f105a81d622b70f9a35f577612d63David George
379731b4cace10f105a81d622b70f9a35f577612d63David George	/* Check for unsupported part */
380731b4cace10f105a81d622b70f9a35f577612d63David George	man_id = i2c_smbus_read_byte_data(client, MAX1668_REG_MAN_ID);
381731b4cace10f105a81d622b70f9a35f577612d63David George	if (man_id != MAN_ID_MAXIM)
382731b4cace10f105a81d622b70f9a35f577612d63David George		return -ENODEV;
383731b4cace10f105a81d622b70f9a35f577612d63David George
384731b4cace10f105a81d622b70f9a35f577612d63David George	dev_id = i2c_smbus_read_byte_data(client, MAX1668_REG_DEV_ID);
385731b4cace10f105a81d622b70f9a35f577612d63David George	if (dev_id < 0)
386731b4cace10f105a81d622b70f9a35f577612d63David George		return -ENODEV;
387731b4cace10f105a81d622b70f9a35f577612d63David George
388731b4cace10f105a81d622b70f9a35f577612d63David George	type_name = NULL;
389731b4cace10f105a81d622b70f9a35f577612d63David George	if (dev_id == DEV_ID_MAX1668)
390731b4cace10f105a81d622b70f9a35f577612d63David George		type_name = "max1668";
391731b4cace10f105a81d622b70f9a35f577612d63David George	else if (dev_id == DEV_ID_MAX1805)
392731b4cace10f105a81d622b70f9a35f577612d63David George		type_name = "max1805";
393731b4cace10f105a81d622b70f9a35f577612d63David George	else if (dev_id == DEV_ID_MAX1989)
394731b4cace10f105a81d622b70f9a35f577612d63David George		type_name = "max1989";
395731b4cace10f105a81d622b70f9a35f577612d63David George
396731b4cace10f105a81d622b70f9a35f577612d63David George	if (!type_name)
397731b4cace10f105a81d622b70f9a35f577612d63David George		return -ENODEV;
398731b4cace10f105a81d622b70f9a35f577612d63David George
399731b4cace10f105a81d622b70f9a35f577612d63David George	strlcpy(info->type, type_name, I2C_NAME_SIZE);
400731b4cace10f105a81d622b70f9a35f577612d63David George
401731b4cace10f105a81d622b70f9a35f577612d63David George	return 0;
402731b4cace10f105a81d622b70f9a35f577612d63David George}
403731b4cace10f105a81d622b70f9a35f577612d63David George
404731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic int max1668_probe(struct i2c_client *client,
405731b4cace10f105a81d622b70f9a35f577612d63David George			 const struct i2c_device_id *id)
406731b4cace10f105a81d622b70f9a35f577612d63David George{
407731b4cace10f105a81d622b70f9a35f577612d63David George	struct i2c_adapter *adapter = client->adapter;
408731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data;
409731b4cace10f105a81d622b70f9a35f577612d63David George	int err;
410731b4cace10f105a81d622b70f9a35f577612d63David George
411731b4cace10f105a81d622b70f9a35f577612d63David George	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
412731b4cace10f105a81d622b70f9a35f577612d63David George		return -ENODEV;
413731b4cace10f105a81d622b70f9a35f577612d63David George
414731b4cace10f105a81d622b70f9a35f577612d63David George	data = kzalloc(sizeof(struct max1668_data), GFP_KERNEL);
415731b4cace10f105a81d622b70f9a35f577612d63David George	if (!data)
416731b4cace10f105a81d622b70f9a35f577612d63David George		return -ENOMEM;
417731b4cace10f105a81d622b70f9a35f577612d63David George
418731b4cace10f105a81d622b70f9a35f577612d63David George	i2c_set_clientdata(client, data);
419731b4cace10f105a81d622b70f9a35f577612d63David George	data->type = id->driver_data;
420731b4cace10f105a81d622b70f9a35f577612d63David George	mutex_init(&data->update_lock);
421731b4cace10f105a81d622b70f9a35f577612d63David George
422731b4cace10f105a81d622b70f9a35f577612d63David George	/* Register sysfs hooks */
423731b4cace10f105a81d622b70f9a35f577612d63David George	err = sysfs_create_group(&client->dev.kobj, &max1668_group_common);
424731b4cace10f105a81d622b70f9a35f577612d63David George	if (err)
425731b4cace10f105a81d622b70f9a35f577612d63David George		goto error_free;
426731b4cace10f105a81d622b70f9a35f577612d63David George
427731b4cace10f105a81d622b70f9a35f577612d63David George	if (data->type == max1668 || data->type == max1989) {
428731b4cace10f105a81d622b70f9a35f577612d63David George		err = sysfs_create_group(&client->dev.kobj,
429731b4cace10f105a81d622b70f9a35f577612d63David George					 &max1668_group_unique);
430731b4cace10f105a81d622b70f9a35f577612d63David George		if (err)
431731b4cace10f105a81d622b70f9a35f577612d63David George			goto error_sysrem0;
432731b4cace10f105a81d622b70f9a35f577612d63David George	}
433731b4cace10f105a81d622b70f9a35f577612d63David George
434731b4cace10f105a81d622b70f9a35f577612d63David George	data->hwmon_dev = hwmon_device_register(&client->dev);
435731b4cace10f105a81d622b70f9a35f577612d63David George	if (IS_ERR(data->hwmon_dev)) {
436731b4cace10f105a81d622b70f9a35f577612d63David George		err = PTR_ERR(data->hwmon_dev);
437731b4cace10f105a81d622b70f9a35f577612d63David George		goto error_sysrem1;
438731b4cace10f105a81d622b70f9a35f577612d63David George	}
439731b4cace10f105a81d622b70f9a35f577612d63David George
440731b4cace10f105a81d622b70f9a35f577612d63David George	return 0;
441731b4cace10f105a81d622b70f9a35f577612d63David George
442731b4cace10f105a81d622b70f9a35f577612d63David Georgeerror_sysrem1:
443731b4cace10f105a81d622b70f9a35f577612d63David George	if (data->type == max1668 || data->type == max1989)
444731b4cace10f105a81d622b70f9a35f577612d63David George		sysfs_remove_group(&client->dev.kobj, &max1668_group_unique);
445731b4cace10f105a81d622b70f9a35f577612d63David Georgeerror_sysrem0:
446731b4cace10f105a81d622b70f9a35f577612d63David George	sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
447731b4cace10f105a81d622b70f9a35f577612d63David Georgeerror_free:
448731b4cace10f105a81d622b70f9a35f577612d63David George	kfree(data);
449731b4cace10f105a81d622b70f9a35f577612d63David George	return err;
450731b4cace10f105a81d622b70f9a35f577612d63David George}
451731b4cace10f105a81d622b70f9a35f577612d63David George
452731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic int max1668_remove(struct i2c_client *client)
453731b4cace10f105a81d622b70f9a35f577612d63David George{
454731b4cace10f105a81d622b70f9a35f577612d63David George	struct max1668_data *data = i2c_get_clientdata(client);
455731b4cace10f105a81d622b70f9a35f577612d63David George
456731b4cace10f105a81d622b70f9a35f577612d63David George	hwmon_device_unregister(data->hwmon_dev);
457731b4cace10f105a81d622b70f9a35f577612d63David George	if (data->type == max1668 || data->type == max1989)
458731b4cace10f105a81d622b70f9a35f577612d63David George		sysfs_remove_group(&client->dev.kobj, &max1668_group_unique);
459731b4cace10f105a81d622b70f9a35f577612d63David George
460731b4cace10f105a81d622b70f9a35f577612d63David George	sysfs_remove_group(&client->dev.kobj, &max1668_group_common);
461731b4cace10f105a81d622b70f9a35f577612d63David George
462731b4cace10f105a81d622b70f9a35f577612d63David George	kfree(data);
463731b4cace10f105a81d622b70f9a35f577612d63David George	return 0;
464731b4cace10f105a81d622b70f9a35f577612d63David George}
465731b4cace10f105a81d622b70f9a35f577612d63David George
466731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic const struct i2c_device_id max1668_id[] = {
467731b4cace10f105a81d622b70f9a35f577612d63David George	{ "max1668", max1668 },
468731b4cace10f105a81d622b70f9a35f577612d63David George	{ "max1805", max1805 },
469731b4cace10f105a81d622b70f9a35f577612d63David George	{ "max1989", max1989 },
470731b4cace10f105a81d622b70f9a35f577612d63David George	{ }
471731b4cace10f105a81d622b70f9a35f577612d63David George};
472731b4cace10f105a81d622b70f9a35f577612d63David GeorgeMODULE_DEVICE_TABLE(i2c, max1668_id);
473731b4cace10f105a81d622b70f9a35f577612d63David George
474731b4cace10f105a81d622b70f9a35f577612d63David George/* This is the driver that will be inserted */
475731b4cace10f105a81d622b70f9a35f577612d63David Georgestatic struct i2c_driver max1668_driver = {
476731b4cace10f105a81d622b70f9a35f577612d63David George	.class = I2C_CLASS_HWMON,
477731b4cace10f105a81d622b70f9a35f577612d63David George	.driver = {
478731b4cace10f105a81d622b70f9a35f577612d63David George		  .name	= "max1668",
479731b4cace10f105a81d622b70f9a35f577612d63David George		  },
480731b4cace10f105a81d622b70f9a35f577612d63David George	.probe = max1668_probe,
481731b4cace10f105a81d622b70f9a35f577612d63David George	.remove	= max1668_remove,
482731b4cace10f105a81d622b70f9a35f577612d63David George	.id_table = max1668_id,
483731b4cace10f105a81d622b70f9a35f577612d63David George	.detect	= max1668_detect,
484731b4cace10f105a81d622b70f9a35f577612d63David George	.address_list = max1668_addr_list,
485731b4cace10f105a81d622b70f9a35f577612d63David George};
486731b4cace10f105a81d622b70f9a35f577612d63David George
487f0967eea80ec2a19a4fe1ad27e3ff1b22c79a3c7Axel Linmodule_i2c_driver(max1668_driver);
488731b4cace10f105a81d622b70f9a35f577612d63David George
489731b4cace10f105a81d622b70f9a35f577612d63David GeorgeMODULE_AUTHOR("David George <david.george@ska.ac.za>");
490731b4cace10f105a81d622b70f9a35f577612d63David GeorgeMODULE_DESCRIPTION("MAX1668 remote temperature sensor driver");
491731b4cace10f105a81d622b70f9a35f577612d63David GeorgeMODULE_LICENSE("GPL");
492