xref: /OK3568_Linux_fs/kernel/drivers/hwmon/sis5595.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * sis5595.c - Part of lm_sensors, Linux kernel modules
4*4882a593Smuzhiyun  *	       for hardware monitoring
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (C) 1998 - 2001 Frodo Looijaard <frodol@dds.nl>,
7*4882a593Smuzhiyun  *			     Kyösti Mälkki <kmalkki@cc.hut.fi>, and
8*4882a593Smuzhiyun  *			     Mark D. Studebaker <mdsxyz123@yahoo.com>
9*4882a593Smuzhiyun  * Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with
10*4882a593Smuzhiyun  * the help of Jean Delvare <jdelvare@suse.de>
11*4882a593Smuzhiyun  */
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun /*
14*4882a593Smuzhiyun  * SiS southbridge has a LM78-like chip integrated on the same IC.
15*4882a593Smuzhiyun  * This driver is a customized copy of lm78.c
16*4882a593Smuzhiyun  *
17*4882a593Smuzhiyun  * Supports following revisions:
18*4882a593Smuzhiyun  *	Version		PCI ID		PCI Revision
19*4882a593Smuzhiyun  *	1		1039/0008	AF or less
20*4882a593Smuzhiyun  *	2		1039/0008	B0 or greater
21*4882a593Smuzhiyun  *
22*4882a593Smuzhiyun  *  Note: these chips contain a 0008 device which is incompatible with the
23*4882a593Smuzhiyun  *	 5595. We recognize these by the presence of the listed
24*4882a593Smuzhiyun  *	 "blacklist" PCI ID and refuse to load.
25*4882a593Smuzhiyun  *
26*4882a593Smuzhiyun  * NOT SUPPORTED	PCI ID		BLACKLIST PCI ID
27*4882a593Smuzhiyun  *	 540		0008		0540
28*4882a593Smuzhiyun  *	 550		0008		0550
29*4882a593Smuzhiyun  *	5513		0008		5511
30*4882a593Smuzhiyun  *	5581		0008		5597
31*4882a593Smuzhiyun  *	5582		0008		5597
32*4882a593Smuzhiyun  *	5597		0008		5597
33*4882a593Smuzhiyun  *	5598		0008		5597/5598
34*4882a593Smuzhiyun  *	 630		0008		0630
35*4882a593Smuzhiyun  *	 645		0008		0645
36*4882a593Smuzhiyun  *	 730		0008		0730
37*4882a593Smuzhiyun  *	 735		0008		0735
38*4882a593Smuzhiyun  */
39*4882a593Smuzhiyun 
40*4882a593Smuzhiyun #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun #include <linux/module.h>
43*4882a593Smuzhiyun #include <linux/slab.h>
44*4882a593Smuzhiyun #include <linux/ioport.h>
45*4882a593Smuzhiyun #include <linux/pci.h>
46*4882a593Smuzhiyun #include <linux/platform_device.h>
47*4882a593Smuzhiyun #include <linux/hwmon.h>
48*4882a593Smuzhiyun #include <linux/hwmon-sysfs.h>
49*4882a593Smuzhiyun #include <linux/err.h>
50*4882a593Smuzhiyun #include <linux/init.h>
51*4882a593Smuzhiyun #include <linux/jiffies.h>
52*4882a593Smuzhiyun #include <linux/mutex.h>
53*4882a593Smuzhiyun #include <linux/sysfs.h>
54*4882a593Smuzhiyun #include <linux/acpi.h>
55*4882a593Smuzhiyun #include <linux/io.h>
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun /*
58*4882a593Smuzhiyun  * If force_addr is set to anything different from 0, we forcibly enable
59*4882a593Smuzhiyun  * the device at the given address.
60*4882a593Smuzhiyun  */
61*4882a593Smuzhiyun static u16 force_addr;
62*4882a593Smuzhiyun module_param(force_addr, ushort, 0);
63*4882a593Smuzhiyun MODULE_PARM_DESC(force_addr,
64*4882a593Smuzhiyun 		 "Initialize the base address of the sensors");
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun static struct platform_device *pdev;
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun /* Many SIS5595 constants specified below */
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun /* Length of ISA address segment */
71*4882a593Smuzhiyun #define SIS5595_EXTENT 8
72*4882a593Smuzhiyun /* PCI Config Registers */
73*4882a593Smuzhiyun #define SIS5595_BASE_REG 0x68
74*4882a593Smuzhiyun #define SIS5595_PIN_REG 0x7A
75*4882a593Smuzhiyun #define SIS5595_ENABLE_REG 0x7B
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun /* Where are the ISA address/data registers relative to the base address */
78*4882a593Smuzhiyun #define SIS5595_ADDR_REG_OFFSET 5
79*4882a593Smuzhiyun #define SIS5595_DATA_REG_OFFSET 6
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun /* The SIS5595 registers */
82*4882a593Smuzhiyun #define SIS5595_REG_IN_MAX(nr) (0x2b + (nr) * 2)
83*4882a593Smuzhiyun #define SIS5595_REG_IN_MIN(nr) (0x2c + (nr) * 2)
84*4882a593Smuzhiyun #define SIS5595_REG_IN(nr) (0x20 + (nr))
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun #define SIS5595_REG_FAN_MIN(nr) (0x3b + (nr))
87*4882a593Smuzhiyun #define SIS5595_REG_FAN(nr) (0x28 + (nr))
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun /*
90*4882a593Smuzhiyun  * On the first version of the chip, the temp registers are separate.
91*4882a593Smuzhiyun  * On the second version,
92*4882a593Smuzhiyun  * TEMP pin is shared with IN4, configured in PCI register 0x7A.
93*4882a593Smuzhiyun  * The registers are the same as well.
94*4882a593Smuzhiyun  * OVER and HYST are really MAX and MIN.
95*4882a593Smuzhiyun  */
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun #define REV2MIN	0xb0
98*4882a593Smuzhiyun #define SIS5595_REG_TEMP	(((data->revision) >= REV2MIN) ? \
99*4882a593Smuzhiyun 					SIS5595_REG_IN(4) : 0x27)
100*4882a593Smuzhiyun #define SIS5595_REG_TEMP_OVER	(((data->revision) >= REV2MIN) ? \
101*4882a593Smuzhiyun 					SIS5595_REG_IN_MAX(4) : 0x39)
102*4882a593Smuzhiyun #define SIS5595_REG_TEMP_HYST	(((data->revision) >= REV2MIN) ? \
103*4882a593Smuzhiyun 					SIS5595_REG_IN_MIN(4) : 0x3a)
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun #define SIS5595_REG_CONFIG 0x40
106*4882a593Smuzhiyun #define SIS5595_REG_ALARM1 0x41
107*4882a593Smuzhiyun #define SIS5595_REG_ALARM2 0x42
108*4882a593Smuzhiyun #define SIS5595_REG_FANDIV 0x47
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun /*
111*4882a593Smuzhiyun  * Conversions. Limit checking is only done on the TO_REG
112*4882a593Smuzhiyun  * variants.
113*4882a593Smuzhiyun  */
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun /*
116*4882a593Smuzhiyun  * IN: mV, (0V to 4.08V)
117*4882a593Smuzhiyun  * REG: 16mV/bit
118*4882a593Smuzhiyun  */
IN_TO_REG(unsigned long val)119*4882a593Smuzhiyun static inline u8 IN_TO_REG(unsigned long val)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun 	unsigned long nval = clamp_val(val, 0, 4080);
122*4882a593Smuzhiyun 	return (nval + 8) / 16;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun #define IN_FROM_REG(val) ((val) *  16)
125*4882a593Smuzhiyun 
FAN_TO_REG(long rpm,int div)126*4882a593Smuzhiyun static inline u8 FAN_TO_REG(long rpm, int div)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun 	if (rpm <= 0)
129*4882a593Smuzhiyun 		return 255;
130*4882a593Smuzhiyun 	if (rpm > 1350000)
131*4882a593Smuzhiyun 		return 1;
132*4882a593Smuzhiyun 	return clamp_val((1350000 + rpm * div / 2) / (rpm * div), 1, 254);
133*4882a593Smuzhiyun }
134*4882a593Smuzhiyun 
FAN_FROM_REG(u8 val,int div)135*4882a593Smuzhiyun static inline int FAN_FROM_REG(u8 val, int div)
136*4882a593Smuzhiyun {
137*4882a593Smuzhiyun 	return val == 0 ? -1 : val == 255 ? 0 : 1350000 / (val * div);
138*4882a593Smuzhiyun }
139*4882a593Smuzhiyun 
140*4882a593Smuzhiyun /*
141*4882a593Smuzhiyun  * TEMP: mC (-54.12C to +157.53C)
142*4882a593Smuzhiyun  * REG: 0.83C/bit + 52.12, two's complement
143*4882a593Smuzhiyun  */
TEMP_FROM_REG(s8 val)144*4882a593Smuzhiyun static inline int TEMP_FROM_REG(s8 val)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	return val * 830 + 52120;
147*4882a593Smuzhiyun }
TEMP_TO_REG(long val)148*4882a593Smuzhiyun static inline s8 TEMP_TO_REG(long val)
149*4882a593Smuzhiyun {
150*4882a593Smuzhiyun 	int nval = clamp_val(val, -54120, 157530) ;
151*4882a593Smuzhiyun 	return nval < 0 ? (nval - 5212 - 415) / 830 : (nval - 5212 + 415) / 830;
152*4882a593Smuzhiyun }
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun /*
155*4882a593Smuzhiyun  * FAN DIV: 1, 2, 4, or 8 (defaults to 2)
156*4882a593Smuzhiyun  * REG: 0, 1, 2, or 3 (respectively) (defaults to 1)
157*4882a593Smuzhiyun  */
DIV_TO_REG(int val)158*4882a593Smuzhiyun static inline u8 DIV_TO_REG(int val)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	return val == 8 ? 3 : val == 4 ? 2 : val == 1 ? 0 : 1;
161*4882a593Smuzhiyun }
162*4882a593Smuzhiyun #define DIV_FROM_REG(val) (1 << (val))
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun /*
165*4882a593Smuzhiyun  * For each registered chip, we need to keep some data in memory.
166*4882a593Smuzhiyun  * The structure is dynamically allocated.
167*4882a593Smuzhiyun  */
168*4882a593Smuzhiyun struct sis5595_data {
169*4882a593Smuzhiyun 	unsigned short addr;
170*4882a593Smuzhiyun 	const char *name;
171*4882a593Smuzhiyun 	struct device *hwmon_dev;
172*4882a593Smuzhiyun 	struct mutex lock;
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun 	struct mutex update_lock;
175*4882a593Smuzhiyun 	char valid;		/* !=0 if following fields are valid */
176*4882a593Smuzhiyun 	unsigned long last_updated;	/* In jiffies */
177*4882a593Smuzhiyun 	char maxins;		/* == 3 if temp enabled, otherwise == 4 */
178*4882a593Smuzhiyun 	u8 revision;		/* Reg. value */
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun 	u8 in[5];		/* Register value */
181*4882a593Smuzhiyun 	u8 in_max[5];		/* Register value */
182*4882a593Smuzhiyun 	u8 in_min[5];		/* Register value */
183*4882a593Smuzhiyun 	u8 fan[2];		/* Register value */
184*4882a593Smuzhiyun 	u8 fan_min[2];		/* Register value */
185*4882a593Smuzhiyun 	s8 temp;		/* Register value */
186*4882a593Smuzhiyun 	s8 temp_over;		/* Register value */
187*4882a593Smuzhiyun 	s8 temp_hyst;		/* Register value */
188*4882a593Smuzhiyun 	u8 fan_div[2];		/* Register encoding, shifted right */
189*4882a593Smuzhiyun 	u16 alarms;		/* Register encoding, combined */
190*4882a593Smuzhiyun };
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun static struct pci_dev *s_bridge;	/* pointer to the (only) sis5595 */
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun static int sis5595_probe(struct platform_device *pdev);
195*4882a593Smuzhiyun static int sis5595_remove(struct platform_device *pdev);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun static int sis5595_read_value(struct sis5595_data *data, u8 reg);
198*4882a593Smuzhiyun static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value);
199*4882a593Smuzhiyun static struct sis5595_data *sis5595_update_device(struct device *dev);
200*4882a593Smuzhiyun static void sis5595_init_device(struct sis5595_data *data);
201*4882a593Smuzhiyun 
202*4882a593Smuzhiyun static struct platform_driver sis5595_driver = {
203*4882a593Smuzhiyun 	.driver = {
204*4882a593Smuzhiyun 		.name	= "sis5595",
205*4882a593Smuzhiyun 	},
206*4882a593Smuzhiyun 	.probe		= sis5595_probe,
207*4882a593Smuzhiyun 	.remove		= sis5595_remove,
208*4882a593Smuzhiyun };
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun /* 4 Voltages */
in_show(struct device * dev,struct device_attribute * da,char * buf)211*4882a593Smuzhiyun static ssize_t in_show(struct device *dev, struct device_attribute *da,
212*4882a593Smuzhiyun 		       char *buf)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
215*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
216*4882a593Smuzhiyun 	int nr = attr->index;
217*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
218*4882a593Smuzhiyun }
219*4882a593Smuzhiyun 
in_min_show(struct device * dev,struct device_attribute * da,char * buf)220*4882a593Smuzhiyun static ssize_t in_min_show(struct device *dev, struct device_attribute *da,
221*4882a593Smuzhiyun 			   char *buf)
222*4882a593Smuzhiyun {
223*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
224*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
225*4882a593Smuzhiyun 	int nr = attr->index;
226*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun 
in_max_show(struct device * dev,struct device_attribute * da,char * buf)229*4882a593Smuzhiyun static ssize_t in_max_show(struct device *dev, struct device_attribute *da,
230*4882a593Smuzhiyun 			   char *buf)
231*4882a593Smuzhiyun {
232*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
233*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
234*4882a593Smuzhiyun 	int nr = attr->index;
235*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
236*4882a593Smuzhiyun }
237*4882a593Smuzhiyun 
in_min_store(struct device * dev,struct device_attribute * da,const char * buf,size_t count)238*4882a593Smuzhiyun static ssize_t in_min_store(struct device *dev, struct device_attribute *da,
239*4882a593Smuzhiyun 			    const char *buf, size_t count)
240*4882a593Smuzhiyun {
241*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
242*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
243*4882a593Smuzhiyun 	int nr = attr->index;
244*4882a593Smuzhiyun 	unsigned long val;
245*4882a593Smuzhiyun 	int err;
246*4882a593Smuzhiyun 
247*4882a593Smuzhiyun 	err = kstrtoul(buf, 10, &val);
248*4882a593Smuzhiyun 	if (err)
249*4882a593Smuzhiyun 		return err;
250*4882a593Smuzhiyun 
251*4882a593Smuzhiyun 	mutex_lock(&data->update_lock);
252*4882a593Smuzhiyun 	data->in_min[nr] = IN_TO_REG(val);
253*4882a593Smuzhiyun 	sis5595_write_value(data, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
254*4882a593Smuzhiyun 	mutex_unlock(&data->update_lock);
255*4882a593Smuzhiyun 	return count;
256*4882a593Smuzhiyun }
257*4882a593Smuzhiyun 
in_max_store(struct device * dev,struct device_attribute * da,const char * buf,size_t count)258*4882a593Smuzhiyun static ssize_t in_max_store(struct device *dev, struct device_attribute *da,
259*4882a593Smuzhiyun 			    const char *buf, size_t count)
260*4882a593Smuzhiyun {
261*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
262*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
263*4882a593Smuzhiyun 	int nr = attr->index;
264*4882a593Smuzhiyun 	unsigned long val;
265*4882a593Smuzhiyun 	int err;
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	err = kstrtoul(buf, 10, &val);
268*4882a593Smuzhiyun 	if (err)
269*4882a593Smuzhiyun 		return err;
270*4882a593Smuzhiyun 
271*4882a593Smuzhiyun 	mutex_lock(&data->update_lock);
272*4882a593Smuzhiyun 	data->in_max[nr] = IN_TO_REG(val);
273*4882a593Smuzhiyun 	sis5595_write_value(data, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
274*4882a593Smuzhiyun 	mutex_unlock(&data->update_lock);
275*4882a593Smuzhiyun 	return count;
276*4882a593Smuzhiyun }
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in0_input, in, 0);
279*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in0_min, in_min, 0);
280*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in0_max, in_max, 0);
281*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in1_input, in, 1);
282*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in1_min, in_min, 1);
283*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in1_max, in_max, 1);
284*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in2_input, in, 2);
285*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in2_min, in_min, 2);
286*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in2_max, in_max, 2);
287*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in3_input, in, 3);
288*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in3_min, in_min, 3);
289*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in3_max, in_max, 3);
290*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in4_input, in, 4);
291*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in4_min, in_min, 4);
292*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(in4_max, in_max, 4);
293*4882a593Smuzhiyun 
294*4882a593Smuzhiyun /* Temperature */
temp1_input_show(struct device * dev,struct device_attribute * attr,char * buf)295*4882a593Smuzhiyun static ssize_t temp1_input_show(struct device *dev,
296*4882a593Smuzhiyun 				struct device_attribute *attr, char *buf)
297*4882a593Smuzhiyun {
298*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
299*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp));
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun 
temp1_max_show(struct device * dev,struct device_attribute * attr,char * buf)302*4882a593Smuzhiyun static ssize_t temp1_max_show(struct device *dev, struct device_attribute *attr,
303*4882a593Smuzhiyun 			      char *buf)
304*4882a593Smuzhiyun {
305*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
306*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_over));
307*4882a593Smuzhiyun }
308*4882a593Smuzhiyun 
temp1_max_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)309*4882a593Smuzhiyun static ssize_t temp1_max_store(struct device *dev,
310*4882a593Smuzhiyun 			       struct device_attribute *attr, const char *buf,
311*4882a593Smuzhiyun 			       size_t count)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
314*4882a593Smuzhiyun 	long val;
315*4882a593Smuzhiyun 	int err;
316*4882a593Smuzhiyun 
317*4882a593Smuzhiyun 	err = kstrtol(buf, 10, &val);
318*4882a593Smuzhiyun 	if (err)
319*4882a593Smuzhiyun 		return err;
320*4882a593Smuzhiyun 
321*4882a593Smuzhiyun 	mutex_lock(&data->update_lock);
322*4882a593Smuzhiyun 	data->temp_over = TEMP_TO_REG(val);
323*4882a593Smuzhiyun 	sis5595_write_value(data, SIS5595_REG_TEMP_OVER, data->temp_over);
324*4882a593Smuzhiyun 	mutex_unlock(&data->update_lock);
325*4882a593Smuzhiyun 	return count;
326*4882a593Smuzhiyun }
327*4882a593Smuzhiyun 
temp1_max_hyst_show(struct device * dev,struct device_attribute * attr,char * buf)328*4882a593Smuzhiyun static ssize_t temp1_max_hyst_show(struct device *dev,
329*4882a593Smuzhiyun 				   struct device_attribute *attr, char *buf)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
332*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->temp_hyst));
333*4882a593Smuzhiyun }
334*4882a593Smuzhiyun 
temp1_max_hyst_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t count)335*4882a593Smuzhiyun static ssize_t temp1_max_hyst_store(struct device *dev,
336*4882a593Smuzhiyun 				    struct device_attribute *attr,
337*4882a593Smuzhiyun 				    const char *buf, size_t count)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
340*4882a593Smuzhiyun 	long val;
341*4882a593Smuzhiyun 	int err;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	err = kstrtol(buf, 10, &val);
344*4882a593Smuzhiyun 	if (err)
345*4882a593Smuzhiyun 		return err;
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	mutex_lock(&data->update_lock);
348*4882a593Smuzhiyun 	data->temp_hyst = TEMP_TO_REG(val);
349*4882a593Smuzhiyun 	sis5595_write_value(data, SIS5595_REG_TEMP_HYST, data->temp_hyst);
350*4882a593Smuzhiyun 	mutex_unlock(&data->update_lock);
351*4882a593Smuzhiyun 	return count;
352*4882a593Smuzhiyun }
353*4882a593Smuzhiyun 
354*4882a593Smuzhiyun static DEVICE_ATTR_RO(temp1_input);
355*4882a593Smuzhiyun static DEVICE_ATTR_RW(temp1_max);
356*4882a593Smuzhiyun static DEVICE_ATTR_RW(temp1_max_hyst);
357*4882a593Smuzhiyun 
358*4882a593Smuzhiyun /* 2 Fans */
fan_show(struct device * dev,struct device_attribute * da,char * buf)359*4882a593Smuzhiyun static ssize_t fan_show(struct device *dev, struct device_attribute *da,
360*4882a593Smuzhiyun 			char *buf)
361*4882a593Smuzhiyun {
362*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
363*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
364*4882a593Smuzhiyun 	int nr = attr->index;
365*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
366*4882a593Smuzhiyun 		DIV_FROM_REG(data->fan_div[nr])));
367*4882a593Smuzhiyun }
368*4882a593Smuzhiyun 
fan_min_show(struct device * dev,struct device_attribute * da,char * buf)369*4882a593Smuzhiyun static ssize_t fan_min_show(struct device *dev, struct device_attribute *da,
370*4882a593Smuzhiyun 			    char *buf)
371*4882a593Smuzhiyun {
372*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
373*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
374*4882a593Smuzhiyun 	int nr = attr->index;
375*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan_min[nr],
376*4882a593Smuzhiyun 		DIV_FROM_REG(data->fan_div[nr])));
377*4882a593Smuzhiyun }
378*4882a593Smuzhiyun 
fan_min_store(struct device * dev,struct device_attribute * da,const char * buf,size_t count)379*4882a593Smuzhiyun static ssize_t fan_min_store(struct device *dev, struct device_attribute *da,
380*4882a593Smuzhiyun 			     const char *buf, size_t count)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
383*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
384*4882a593Smuzhiyun 	int nr = attr->index;
385*4882a593Smuzhiyun 	unsigned long val;
386*4882a593Smuzhiyun 	int err;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun 	err = kstrtoul(buf, 10, &val);
389*4882a593Smuzhiyun 	if (err)
390*4882a593Smuzhiyun 		return err;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun 	mutex_lock(&data->update_lock);
393*4882a593Smuzhiyun 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
394*4882a593Smuzhiyun 	sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
395*4882a593Smuzhiyun 	mutex_unlock(&data->update_lock);
396*4882a593Smuzhiyun 	return count;
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun 
fan_div_show(struct device * dev,struct device_attribute * da,char * buf)399*4882a593Smuzhiyun static ssize_t fan_div_show(struct device *dev, struct device_attribute *da,
400*4882a593Smuzhiyun 			    char *buf)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
403*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
404*4882a593Smuzhiyun 	int nr = attr->index;
405*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]));
406*4882a593Smuzhiyun }
407*4882a593Smuzhiyun 
408*4882a593Smuzhiyun /*
409*4882a593Smuzhiyun  * Note: we save and restore the fan minimum here, because its value is
410*4882a593Smuzhiyun  * determined in part by the fan divisor.  This follows the principle of
411*4882a593Smuzhiyun  * least surprise; the user doesn't expect the fan minimum to change just
412*4882a593Smuzhiyun  * because the divisor changed.
413*4882a593Smuzhiyun  */
fan_div_store(struct device * dev,struct device_attribute * da,const char * buf,size_t count)414*4882a593Smuzhiyun static ssize_t fan_div_store(struct device *dev, struct device_attribute *da,
415*4882a593Smuzhiyun 			     const char *buf, size_t count)
416*4882a593Smuzhiyun {
417*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
418*4882a593Smuzhiyun 	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
419*4882a593Smuzhiyun 	int nr = attr->index;
420*4882a593Smuzhiyun 	unsigned long min;
421*4882a593Smuzhiyun 	int reg;
422*4882a593Smuzhiyun 	unsigned long val;
423*4882a593Smuzhiyun 	int err;
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	err = kstrtoul(buf, 10, &val);
426*4882a593Smuzhiyun 	if (err)
427*4882a593Smuzhiyun 		return err;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	mutex_lock(&data->update_lock);
430*4882a593Smuzhiyun 	min = FAN_FROM_REG(data->fan_min[nr],
431*4882a593Smuzhiyun 			DIV_FROM_REG(data->fan_div[nr]));
432*4882a593Smuzhiyun 	reg = sis5595_read_value(data, SIS5595_REG_FANDIV);
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	switch (val) {
435*4882a593Smuzhiyun 	case 1:
436*4882a593Smuzhiyun 		data->fan_div[nr] = 0;
437*4882a593Smuzhiyun 		break;
438*4882a593Smuzhiyun 	case 2:
439*4882a593Smuzhiyun 		data->fan_div[nr] = 1;
440*4882a593Smuzhiyun 		break;
441*4882a593Smuzhiyun 	case 4:
442*4882a593Smuzhiyun 		data->fan_div[nr] = 2;
443*4882a593Smuzhiyun 		break;
444*4882a593Smuzhiyun 	case 8:
445*4882a593Smuzhiyun 		data->fan_div[nr] = 3;
446*4882a593Smuzhiyun 		break;
447*4882a593Smuzhiyun 	default:
448*4882a593Smuzhiyun 		dev_err(dev,
449*4882a593Smuzhiyun 			"fan_div value %ld not supported. Choose one of 1, 2, 4 or 8!\n",
450*4882a593Smuzhiyun 			val);
451*4882a593Smuzhiyun 		mutex_unlock(&data->update_lock);
452*4882a593Smuzhiyun 		return -EINVAL;
453*4882a593Smuzhiyun 	}
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	switch (nr) {
456*4882a593Smuzhiyun 	case 0:
457*4882a593Smuzhiyun 		reg = (reg & 0xcf) | (data->fan_div[nr] << 4);
458*4882a593Smuzhiyun 		break;
459*4882a593Smuzhiyun 	case 1:
460*4882a593Smuzhiyun 		reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
461*4882a593Smuzhiyun 		break;
462*4882a593Smuzhiyun 	}
463*4882a593Smuzhiyun 	sis5595_write_value(data, SIS5595_REG_FANDIV, reg);
464*4882a593Smuzhiyun 	data->fan_min[nr] =
465*4882a593Smuzhiyun 		FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
466*4882a593Smuzhiyun 	sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
467*4882a593Smuzhiyun 	mutex_unlock(&data->update_lock);
468*4882a593Smuzhiyun 	return count;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
471*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(fan1_input, fan, 0);
472*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(fan1_min, fan_min, 0);
473*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(fan1_div, fan_div, 0);
474*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(fan2_input, fan, 1);
475*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(fan2_min, fan_min, 1);
476*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RW(fan2_div, fan_div, 1);
477*4882a593Smuzhiyun 
478*4882a593Smuzhiyun /* Alarms */
alarms_show(struct device * dev,struct device_attribute * attr,char * buf)479*4882a593Smuzhiyun static ssize_t alarms_show(struct device *dev, struct device_attribute *attr,
480*4882a593Smuzhiyun 			   char *buf)
481*4882a593Smuzhiyun {
482*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
483*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", data->alarms);
484*4882a593Smuzhiyun }
485*4882a593Smuzhiyun static DEVICE_ATTR_RO(alarms);
486*4882a593Smuzhiyun 
alarm_show(struct device * dev,struct device_attribute * da,char * buf)487*4882a593Smuzhiyun static ssize_t alarm_show(struct device *dev, struct device_attribute *da,
488*4882a593Smuzhiyun 			  char *buf)
489*4882a593Smuzhiyun {
490*4882a593Smuzhiyun 	struct sis5595_data *data = sis5595_update_device(dev);
491*4882a593Smuzhiyun 	int nr = to_sensor_dev_attr(da)->index;
492*4882a593Smuzhiyun 	return sprintf(buf, "%u\n", (data->alarms >> nr) & 1);
493*4882a593Smuzhiyun }
494*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in0_alarm, alarm, 0);
495*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in1_alarm, alarm, 1);
496*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in2_alarm, alarm, 2);
497*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in3_alarm, alarm, 3);
498*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(in4_alarm, alarm, 15);
499*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(fan1_alarm, alarm, 6);
500*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(fan2_alarm, alarm, 7);
501*4882a593Smuzhiyun static SENSOR_DEVICE_ATTR_RO(temp1_alarm, alarm, 15);
502*4882a593Smuzhiyun 
name_show(struct device * dev,struct device_attribute * attr,char * buf)503*4882a593Smuzhiyun static ssize_t name_show(struct device *dev, struct device_attribute *attr,
504*4882a593Smuzhiyun 			 char *buf)
505*4882a593Smuzhiyun {
506*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
507*4882a593Smuzhiyun 	return sprintf(buf, "%s\n", data->name);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun static DEVICE_ATTR_RO(name);
510*4882a593Smuzhiyun 
511*4882a593Smuzhiyun static struct attribute *sis5595_attributes[] = {
512*4882a593Smuzhiyun 	&sensor_dev_attr_in0_input.dev_attr.attr,
513*4882a593Smuzhiyun 	&sensor_dev_attr_in0_min.dev_attr.attr,
514*4882a593Smuzhiyun 	&sensor_dev_attr_in0_max.dev_attr.attr,
515*4882a593Smuzhiyun 	&sensor_dev_attr_in0_alarm.dev_attr.attr,
516*4882a593Smuzhiyun 	&sensor_dev_attr_in1_input.dev_attr.attr,
517*4882a593Smuzhiyun 	&sensor_dev_attr_in1_min.dev_attr.attr,
518*4882a593Smuzhiyun 	&sensor_dev_attr_in1_max.dev_attr.attr,
519*4882a593Smuzhiyun 	&sensor_dev_attr_in1_alarm.dev_attr.attr,
520*4882a593Smuzhiyun 	&sensor_dev_attr_in2_input.dev_attr.attr,
521*4882a593Smuzhiyun 	&sensor_dev_attr_in2_min.dev_attr.attr,
522*4882a593Smuzhiyun 	&sensor_dev_attr_in2_max.dev_attr.attr,
523*4882a593Smuzhiyun 	&sensor_dev_attr_in2_alarm.dev_attr.attr,
524*4882a593Smuzhiyun 	&sensor_dev_attr_in3_input.dev_attr.attr,
525*4882a593Smuzhiyun 	&sensor_dev_attr_in3_min.dev_attr.attr,
526*4882a593Smuzhiyun 	&sensor_dev_attr_in3_max.dev_attr.attr,
527*4882a593Smuzhiyun 	&sensor_dev_attr_in3_alarm.dev_attr.attr,
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun 	&sensor_dev_attr_fan1_input.dev_attr.attr,
530*4882a593Smuzhiyun 	&sensor_dev_attr_fan1_min.dev_attr.attr,
531*4882a593Smuzhiyun 	&sensor_dev_attr_fan1_div.dev_attr.attr,
532*4882a593Smuzhiyun 	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
533*4882a593Smuzhiyun 	&sensor_dev_attr_fan2_input.dev_attr.attr,
534*4882a593Smuzhiyun 	&sensor_dev_attr_fan2_min.dev_attr.attr,
535*4882a593Smuzhiyun 	&sensor_dev_attr_fan2_div.dev_attr.attr,
536*4882a593Smuzhiyun 	&sensor_dev_attr_fan2_alarm.dev_attr.attr,
537*4882a593Smuzhiyun 
538*4882a593Smuzhiyun 	&dev_attr_alarms.attr,
539*4882a593Smuzhiyun 	&dev_attr_name.attr,
540*4882a593Smuzhiyun 	NULL
541*4882a593Smuzhiyun };
542*4882a593Smuzhiyun 
543*4882a593Smuzhiyun static const struct attribute_group sis5595_group = {
544*4882a593Smuzhiyun 	.attrs = sis5595_attributes,
545*4882a593Smuzhiyun };
546*4882a593Smuzhiyun 
547*4882a593Smuzhiyun static struct attribute *sis5595_attributes_in4[] = {
548*4882a593Smuzhiyun 	&sensor_dev_attr_in4_input.dev_attr.attr,
549*4882a593Smuzhiyun 	&sensor_dev_attr_in4_min.dev_attr.attr,
550*4882a593Smuzhiyun 	&sensor_dev_attr_in4_max.dev_attr.attr,
551*4882a593Smuzhiyun 	&sensor_dev_attr_in4_alarm.dev_attr.attr,
552*4882a593Smuzhiyun 	NULL
553*4882a593Smuzhiyun };
554*4882a593Smuzhiyun 
555*4882a593Smuzhiyun static const struct attribute_group sis5595_group_in4 = {
556*4882a593Smuzhiyun 	.attrs = sis5595_attributes_in4,
557*4882a593Smuzhiyun };
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun static struct attribute *sis5595_attributes_temp1[] = {
560*4882a593Smuzhiyun 	&dev_attr_temp1_input.attr,
561*4882a593Smuzhiyun 	&dev_attr_temp1_max.attr,
562*4882a593Smuzhiyun 	&dev_attr_temp1_max_hyst.attr,
563*4882a593Smuzhiyun 	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
564*4882a593Smuzhiyun 	NULL
565*4882a593Smuzhiyun };
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun static const struct attribute_group sis5595_group_temp1 = {
568*4882a593Smuzhiyun 	.attrs = sis5595_attributes_temp1,
569*4882a593Smuzhiyun };
570*4882a593Smuzhiyun 
571*4882a593Smuzhiyun /* This is called when the module is loaded */
sis5595_probe(struct platform_device * pdev)572*4882a593Smuzhiyun static int sis5595_probe(struct platform_device *pdev)
573*4882a593Smuzhiyun {
574*4882a593Smuzhiyun 	int err = 0;
575*4882a593Smuzhiyun 	int i;
576*4882a593Smuzhiyun 	struct sis5595_data *data;
577*4882a593Smuzhiyun 	struct resource *res;
578*4882a593Smuzhiyun 	char val;
579*4882a593Smuzhiyun 
580*4882a593Smuzhiyun 	/* Reserve the ISA region */
581*4882a593Smuzhiyun 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
582*4882a593Smuzhiyun 	if (!devm_request_region(&pdev->dev, res->start, SIS5595_EXTENT,
583*4882a593Smuzhiyun 				 sis5595_driver.driver.name))
584*4882a593Smuzhiyun 		return -EBUSY;
585*4882a593Smuzhiyun 
586*4882a593Smuzhiyun 	data = devm_kzalloc(&pdev->dev, sizeof(struct sis5595_data),
587*4882a593Smuzhiyun 			    GFP_KERNEL);
588*4882a593Smuzhiyun 	if (!data)
589*4882a593Smuzhiyun 		return -ENOMEM;
590*4882a593Smuzhiyun 
591*4882a593Smuzhiyun 	mutex_init(&data->lock);
592*4882a593Smuzhiyun 	mutex_init(&data->update_lock);
593*4882a593Smuzhiyun 	data->addr = res->start;
594*4882a593Smuzhiyun 	data->name = "sis5595";
595*4882a593Smuzhiyun 	platform_set_drvdata(pdev, data);
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	/*
598*4882a593Smuzhiyun 	 * Check revision and pin registers to determine whether 4 or 5 voltages
599*4882a593Smuzhiyun 	 */
600*4882a593Smuzhiyun 	data->revision = s_bridge->revision;
601*4882a593Smuzhiyun 	/* 4 voltages, 1 temp */
602*4882a593Smuzhiyun 	data->maxins = 3;
603*4882a593Smuzhiyun 	if (data->revision >= REV2MIN) {
604*4882a593Smuzhiyun 		pci_read_config_byte(s_bridge, SIS5595_PIN_REG, &val);
605*4882a593Smuzhiyun 		if (!(val & 0x80))
606*4882a593Smuzhiyun 			/* 5 voltages, no temps */
607*4882a593Smuzhiyun 			data->maxins = 4;
608*4882a593Smuzhiyun 	}
609*4882a593Smuzhiyun 
610*4882a593Smuzhiyun 	/* Initialize the SIS5595 chip */
611*4882a593Smuzhiyun 	sis5595_init_device(data);
612*4882a593Smuzhiyun 
613*4882a593Smuzhiyun 	/* A few vars need to be filled upon startup */
614*4882a593Smuzhiyun 	for (i = 0; i < 2; i++) {
615*4882a593Smuzhiyun 		data->fan_min[i] = sis5595_read_value(data,
616*4882a593Smuzhiyun 					SIS5595_REG_FAN_MIN(i));
617*4882a593Smuzhiyun 	}
618*4882a593Smuzhiyun 
619*4882a593Smuzhiyun 	/* Register sysfs hooks */
620*4882a593Smuzhiyun 	err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group);
621*4882a593Smuzhiyun 	if (err)
622*4882a593Smuzhiyun 		return err;
623*4882a593Smuzhiyun 	if (data->maxins == 4) {
624*4882a593Smuzhiyun 		err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group_in4);
625*4882a593Smuzhiyun 		if (err)
626*4882a593Smuzhiyun 			goto exit_remove_files;
627*4882a593Smuzhiyun 	} else {
628*4882a593Smuzhiyun 		err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group_temp1);
629*4882a593Smuzhiyun 		if (err)
630*4882a593Smuzhiyun 			goto exit_remove_files;
631*4882a593Smuzhiyun 	}
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	data->hwmon_dev = hwmon_device_register(&pdev->dev);
634*4882a593Smuzhiyun 	if (IS_ERR(data->hwmon_dev)) {
635*4882a593Smuzhiyun 		err = PTR_ERR(data->hwmon_dev);
636*4882a593Smuzhiyun 		goto exit_remove_files;
637*4882a593Smuzhiyun 	}
638*4882a593Smuzhiyun 
639*4882a593Smuzhiyun 	return 0;
640*4882a593Smuzhiyun 
641*4882a593Smuzhiyun exit_remove_files:
642*4882a593Smuzhiyun 	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
643*4882a593Smuzhiyun 	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
644*4882a593Smuzhiyun 	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
645*4882a593Smuzhiyun 	return err;
646*4882a593Smuzhiyun }
647*4882a593Smuzhiyun 
sis5595_remove(struct platform_device * pdev)648*4882a593Smuzhiyun static int sis5595_remove(struct platform_device *pdev)
649*4882a593Smuzhiyun {
650*4882a593Smuzhiyun 	struct sis5595_data *data = platform_get_drvdata(pdev);
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	hwmon_device_unregister(data->hwmon_dev);
653*4882a593Smuzhiyun 	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
654*4882a593Smuzhiyun 	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_in4);
655*4882a593Smuzhiyun 	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_temp1);
656*4882a593Smuzhiyun 
657*4882a593Smuzhiyun 	return 0;
658*4882a593Smuzhiyun }
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun /* ISA access must be locked explicitly. */
sis5595_read_value(struct sis5595_data * data,u8 reg)661*4882a593Smuzhiyun static int sis5595_read_value(struct sis5595_data *data, u8 reg)
662*4882a593Smuzhiyun {
663*4882a593Smuzhiyun 	int res;
664*4882a593Smuzhiyun 
665*4882a593Smuzhiyun 	mutex_lock(&data->lock);
666*4882a593Smuzhiyun 	outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET);
667*4882a593Smuzhiyun 	res = inb_p(data->addr + SIS5595_DATA_REG_OFFSET);
668*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
669*4882a593Smuzhiyun 	return res;
670*4882a593Smuzhiyun }
671*4882a593Smuzhiyun 
sis5595_write_value(struct sis5595_data * data,u8 reg,u8 value)672*4882a593Smuzhiyun static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value)
673*4882a593Smuzhiyun {
674*4882a593Smuzhiyun 	mutex_lock(&data->lock);
675*4882a593Smuzhiyun 	outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET);
676*4882a593Smuzhiyun 	outb_p(value, data->addr + SIS5595_DATA_REG_OFFSET);
677*4882a593Smuzhiyun 	mutex_unlock(&data->lock);
678*4882a593Smuzhiyun }
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun /* Called when we have found a new SIS5595. */
sis5595_init_device(struct sis5595_data * data)681*4882a593Smuzhiyun static void sis5595_init_device(struct sis5595_data *data)
682*4882a593Smuzhiyun {
683*4882a593Smuzhiyun 	u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG);
684*4882a593Smuzhiyun 	if (!(config & 0x01))
685*4882a593Smuzhiyun 		sis5595_write_value(data, SIS5595_REG_CONFIG,
686*4882a593Smuzhiyun 				(config & 0xf7) | 0x01);
687*4882a593Smuzhiyun }
688*4882a593Smuzhiyun 
sis5595_update_device(struct device * dev)689*4882a593Smuzhiyun static struct sis5595_data *sis5595_update_device(struct device *dev)
690*4882a593Smuzhiyun {
691*4882a593Smuzhiyun 	struct sis5595_data *data = dev_get_drvdata(dev);
692*4882a593Smuzhiyun 	int i;
693*4882a593Smuzhiyun 
694*4882a593Smuzhiyun 	mutex_lock(&data->update_lock);
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
697*4882a593Smuzhiyun 	    || !data->valid) {
698*4882a593Smuzhiyun 
699*4882a593Smuzhiyun 		for (i = 0; i <= data->maxins; i++) {
700*4882a593Smuzhiyun 			data->in[i] =
701*4882a593Smuzhiyun 			    sis5595_read_value(data, SIS5595_REG_IN(i));
702*4882a593Smuzhiyun 			data->in_min[i] =
703*4882a593Smuzhiyun 			    sis5595_read_value(data,
704*4882a593Smuzhiyun 					       SIS5595_REG_IN_MIN(i));
705*4882a593Smuzhiyun 			data->in_max[i] =
706*4882a593Smuzhiyun 			    sis5595_read_value(data,
707*4882a593Smuzhiyun 					       SIS5595_REG_IN_MAX(i));
708*4882a593Smuzhiyun 		}
709*4882a593Smuzhiyun 		for (i = 0; i < 2; i++) {
710*4882a593Smuzhiyun 			data->fan[i] =
711*4882a593Smuzhiyun 			    sis5595_read_value(data, SIS5595_REG_FAN(i));
712*4882a593Smuzhiyun 			data->fan_min[i] =
713*4882a593Smuzhiyun 			    sis5595_read_value(data,
714*4882a593Smuzhiyun 					       SIS5595_REG_FAN_MIN(i));
715*4882a593Smuzhiyun 		}
716*4882a593Smuzhiyun 		if (data->maxins == 3) {
717*4882a593Smuzhiyun 			data->temp =
718*4882a593Smuzhiyun 			    sis5595_read_value(data, SIS5595_REG_TEMP);
719*4882a593Smuzhiyun 			data->temp_over =
720*4882a593Smuzhiyun 			    sis5595_read_value(data, SIS5595_REG_TEMP_OVER);
721*4882a593Smuzhiyun 			data->temp_hyst =
722*4882a593Smuzhiyun 			    sis5595_read_value(data, SIS5595_REG_TEMP_HYST);
723*4882a593Smuzhiyun 		}
724*4882a593Smuzhiyun 		i = sis5595_read_value(data, SIS5595_REG_FANDIV);
725*4882a593Smuzhiyun 		data->fan_div[0] = (i >> 4) & 0x03;
726*4882a593Smuzhiyun 		data->fan_div[1] = i >> 6;
727*4882a593Smuzhiyun 		data->alarms =
728*4882a593Smuzhiyun 		    sis5595_read_value(data, SIS5595_REG_ALARM1) |
729*4882a593Smuzhiyun 		    (sis5595_read_value(data, SIS5595_REG_ALARM2) << 8);
730*4882a593Smuzhiyun 		data->last_updated = jiffies;
731*4882a593Smuzhiyun 		data->valid = 1;
732*4882a593Smuzhiyun 	}
733*4882a593Smuzhiyun 
734*4882a593Smuzhiyun 	mutex_unlock(&data->update_lock);
735*4882a593Smuzhiyun 
736*4882a593Smuzhiyun 	return data;
737*4882a593Smuzhiyun }
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun static const struct pci_device_id sis5595_pci_ids[] = {
740*4882a593Smuzhiyun 	{ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_503) },
741*4882a593Smuzhiyun 	{ 0, }
742*4882a593Smuzhiyun };
743*4882a593Smuzhiyun 
744*4882a593Smuzhiyun MODULE_DEVICE_TABLE(pci, sis5595_pci_ids);
745*4882a593Smuzhiyun 
746*4882a593Smuzhiyun static int blacklist[] = {
747*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_540,
748*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_550,
749*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_630,
750*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_645,
751*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_730,
752*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_735,
753*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_5511, /*
754*4882a593Smuzhiyun 				* 5513 chip has the 0008 device but
755*4882a593Smuzhiyun 				* that ID shows up in other chips so we
756*4882a593Smuzhiyun 				* use the 5511 ID for recognition
757*4882a593Smuzhiyun 				*/
758*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_5597,
759*4882a593Smuzhiyun 	PCI_DEVICE_ID_SI_5598,
760*4882a593Smuzhiyun 	0 };
761*4882a593Smuzhiyun 
sis5595_device_add(unsigned short address)762*4882a593Smuzhiyun static int sis5595_device_add(unsigned short address)
763*4882a593Smuzhiyun {
764*4882a593Smuzhiyun 	struct resource res = {
765*4882a593Smuzhiyun 		.start	= address,
766*4882a593Smuzhiyun 		.end	= address + SIS5595_EXTENT - 1,
767*4882a593Smuzhiyun 		.name	= "sis5595",
768*4882a593Smuzhiyun 		.flags	= IORESOURCE_IO,
769*4882a593Smuzhiyun 	};
770*4882a593Smuzhiyun 	int err;
771*4882a593Smuzhiyun 
772*4882a593Smuzhiyun 	err = acpi_check_resource_conflict(&res);
773*4882a593Smuzhiyun 	if (err)
774*4882a593Smuzhiyun 		goto exit;
775*4882a593Smuzhiyun 
776*4882a593Smuzhiyun 	pdev = platform_device_alloc("sis5595", address);
777*4882a593Smuzhiyun 	if (!pdev) {
778*4882a593Smuzhiyun 		err = -ENOMEM;
779*4882a593Smuzhiyun 		pr_err("Device allocation failed\n");
780*4882a593Smuzhiyun 		goto exit;
781*4882a593Smuzhiyun 	}
782*4882a593Smuzhiyun 
783*4882a593Smuzhiyun 	err = platform_device_add_resources(pdev, &res, 1);
784*4882a593Smuzhiyun 	if (err) {
785*4882a593Smuzhiyun 		pr_err("Device resource addition failed (%d)\n", err);
786*4882a593Smuzhiyun 		goto exit_device_put;
787*4882a593Smuzhiyun 	}
788*4882a593Smuzhiyun 
789*4882a593Smuzhiyun 	err = platform_device_add(pdev);
790*4882a593Smuzhiyun 	if (err) {
791*4882a593Smuzhiyun 		pr_err("Device addition failed (%d)\n", err);
792*4882a593Smuzhiyun 		goto exit_device_put;
793*4882a593Smuzhiyun 	}
794*4882a593Smuzhiyun 
795*4882a593Smuzhiyun 	return 0;
796*4882a593Smuzhiyun 
797*4882a593Smuzhiyun exit_device_put:
798*4882a593Smuzhiyun 	platform_device_put(pdev);
799*4882a593Smuzhiyun exit:
800*4882a593Smuzhiyun 	return err;
801*4882a593Smuzhiyun }
802*4882a593Smuzhiyun 
sis5595_pci_probe(struct pci_dev * dev,const struct pci_device_id * id)803*4882a593Smuzhiyun static int sis5595_pci_probe(struct pci_dev *dev,
804*4882a593Smuzhiyun 				       const struct pci_device_id *id)
805*4882a593Smuzhiyun {
806*4882a593Smuzhiyun 	u16 address;
807*4882a593Smuzhiyun 	u8 enable;
808*4882a593Smuzhiyun 	int *i;
809*4882a593Smuzhiyun 
810*4882a593Smuzhiyun 	for (i = blacklist; *i != 0; i++) {
811*4882a593Smuzhiyun 		struct pci_dev *d;
812*4882a593Smuzhiyun 		d = pci_get_device(PCI_VENDOR_ID_SI, *i, NULL);
813*4882a593Smuzhiyun 		if (d) {
814*4882a593Smuzhiyun 			dev_err(&d->dev,
815*4882a593Smuzhiyun 				"Looked for SIS5595 but found unsupported device %.4x\n",
816*4882a593Smuzhiyun 				*i);
817*4882a593Smuzhiyun 			pci_dev_put(d);
818*4882a593Smuzhiyun 			return -ENODEV;
819*4882a593Smuzhiyun 		}
820*4882a593Smuzhiyun 	}
821*4882a593Smuzhiyun 
822*4882a593Smuzhiyun 	force_addr &= ~(SIS5595_EXTENT - 1);
823*4882a593Smuzhiyun 	if (force_addr) {
824*4882a593Smuzhiyun 		dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", force_addr);
825*4882a593Smuzhiyun 		pci_write_config_word(dev, SIS5595_BASE_REG, force_addr);
826*4882a593Smuzhiyun 	}
827*4882a593Smuzhiyun 
828*4882a593Smuzhiyun 	if (PCIBIOS_SUCCESSFUL !=
829*4882a593Smuzhiyun 	    pci_read_config_word(dev, SIS5595_BASE_REG, &address)) {
830*4882a593Smuzhiyun 		dev_err(&dev->dev, "Failed to read ISA address\n");
831*4882a593Smuzhiyun 		return -ENODEV;
832*4882a593Smuzhiyun 	}
833*4882a593Smuzhiyun 
834*4882a593Smuzhiyun 	address &= ~(SIS5595_EXTENT - 1);
835*4882a593Smuzhiyun 	if (!address) {
836*4882a593Smuzhiyun 		dev_err(&dev->dev,
837*4882a593Smuzhiyun 			"Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
838*4882a593Smuzhiyun 		return -ENODEV;
839*4882a593Smuzhiyun 	}
840*4882a593Smuzhiyun 	if (force_addr && address != force_addr) {
841*4882a593Smuzhiyun 		/* doesn't work for some chips? */
842*4882a593Smuzhiyun 		dev_err(&dev->dev, "Failed to force ISA address\n");
843*4882a593Smuzhiyun 		return -ENODEV;
844*4882a593Smuzhiyun 	}
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	if (PCIBIOS_SUCCESSFUL !=
847*4882a593Smuzhiyun 	    pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) {
848*4882a593Smuzhiyun 		dev_err(&dev->dev, "Failed to read enable register\n");
849*4882a593Smuzhiyun 		return -ENODEV;
850*4882a593Smuzhiyun 	}
851*4882a593Smuzhiyun 	if (!(enable & 0x80)) {
852*4882a593Smuzhiyun 		if ((PCIBIOS_SUCCESSFUL !=
853*4882a593Smuzhiyun 		     pci_write_config_byte(dev, SIS5595_ENABLE_REG,
854*4882a593Smuzhiyun 					   enable | 0x80))
855*4882a593Smuzhiyun 		 || (PCIBIOS_SUCCESSFUL !=
856*4882a593Smuzhiyun 		     pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable))
857*4882a593Smuzhiyun 		 || (!(enable & 0x80))) {
858*4882a593Smuzhiyun 			/* doesn't work for some chips! */
859*4882a593Smuzhiyun 			dev_err(&dev->dev, "Failed to enable HWM device\n");
860*4882a593Smuzhiyun 			return -ENODEV;
861*4882a593Smuzhiyun 		}
862*4882a593Smuzhiyun 	}
863*4882a593Smuzhiyun 
864*4882a593Smuzhiyun 	if (platform_driver_register(&sis5595_driver)) {
865*4882a593Smuzhiyun 		dev_dbg(&dev->dev, "Failed to register sis5595 driver\n");
866*4882a593Smuzhiyun 		goto exit;
867*4882a593Smuzhiyun 	}
868*4882a593Smuzhiyun 
869*4882a593Smuzhiyun 	s_bridge = pci_dev_get(dev);
870*4882a593Smuzhiyun 	/* Sets global pdev as a side effect */
871*4882a593Smuzhiyun 	if (sis5595_device_add(address))
872*4882a593Smuzhiyun 		goto exit_unregister;
873*4882a593Smuzhiyun 
874*4882a593Smuzhiyun 	/*
875*4882a593Smuzhiyun 	 * Always return failure here.  This is to allow other drivers to bind
876*4882a593Smuzhiyun 	 * to this pci device.  We don't really want to have control over the
877*4882a593Smuzhiyun 	 * pci device, we only wanted to read as few register values from it.
878*4882a593Smuzhiyun 	 */
879*4882a593Smuzhiyun 	return -ENODEV;
880*4882a593Smuzhiyun 
881*4882a593Smuzhiyun exit_unregister:
882*4882a593Smuzhiyun 	pci_dev_put(dev);
883*4882a593Smuzhiyun 	platform_driver_unregister(&sis5595_driver);
884*4882a593Smuzhiyun exit:
885*4882a593Smuzhiyun 	return -ENODEV;
886*4882a593Smuzhiyun }
887*4882a593Smuzhiyun 
888*4882a593Smuzhiyun static struct pci_driver sis5595_pci_driver = {
889*4882a593Smuzhiyun 	.name            = "sis5595",
890*4882a593Smuzhiyun 	.id_table        = sis5595_pci_ids,
891*4882a593Smuzhiyun 	.probe           = sis5595_pci_probe,
892*4882a593Smuzhiyun };
893*4882a593Smuzhiyun 
sm_sis5595_init(void)894*4882a593Smuzhiyun static int __init sm_sis5595_init(void)
895*4882a593Smuzhiyun {
896*4882a593Smuzhiyun 	return pci_register_driver(&sis5595_pci_driver);
897*4882a593Smuzhiyun }
898*4882a593Smuzhiyun 
sm_sis5595_exit(void)899*4882a593Smuzhiyun static void __exit sm_sis5595_exit(void)
900*4882a593Smuzhiyun {
901*4882a593Smuzhiyun 	pci_unregister_driver(&sis5595_pci_driver);
902*4882a593Smuzhiyun 	if (s_bridge != NULL) {
903*4882a593Smuzhiyun 		platform_device_unregister(pdev);
904*4882a593Smuzhiyun 		platform_driver_unregister(&sis5595_driver);
905*4882a593Smuzhiyun 		pci_dev_put(s_bridge);
906*4882a593Smuzhiyun 		s_bridge = NULL;
907*4882a593Smuzhiyun 	}
908*4882a593Smuzhiyun }
909*4882a593Smuzhiyun 
910*4882a593Smuzhiyun MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
911*4882a593Smuzhiyun MODULE_DESCRIPTION("SiS 5595 Sensor device");
912*4882a593Smuzhiyun MODULE_LICENSE("GPL");
913*4882a593Smuzhiyun 
914*4882a593Smuzhiyun module_init(sm_sis5595_init);
915*4882a593Smuzhiyun module_exit(sm_sis5595_exit);
916