xref: /openbmc/linux/drivers/hwmon/asus_atk0110.c (revision 2c03d07ad54db03b813bb98c469790c07ca9f5dd)
1*2c03d07aSLuca Tettamanti /*
2*2c03d07aSLuca Tettamanti  * Copyright (C) 2007-2009 Luca Tettamanti <kronos.it@gmail.com>
3*2c03d07aSLuca Tettamanti  *
4*2c03d07aSLuca Tettamanti  * This file is released under the GPLv2
5*2c03d07aSLuca Tettamanti  * See COPYING in the top level directory of the kernel tree.
6*2c03d07aSLuca Tettamanti  */
7*2c03d07aSLuca Tettamanti 
8*2c03d07aSLuca Tettamanti #include <linux/kernel.h>
9*2c03d07aSLuca Tettamanti #include <linux/hwmon.h>
10*2c03d07aSLuca Tettamanti #include <linux/list.h>
11*2c03d07aSLuca Tettamanti #include <linux/module.h>
12*2c03d07aSLuca Tettamanti 
13*2c03d07aSLuca Tettamanti #include <acpi/acpi.h>
14*2c03d07aSLuca Tettamanti #include <acpi/acpixf.h>
15*2c03d07aSLuca Tettamanti #include <acpi/acpi_drivers.h>
16*2c03d07aSLuca Tettamanti #include <acpi/acpi_bus.h>
17*2c03d07aSLuca Tettamanti 
18*2c03d07aSLuca Tettamanti 
19*2c03d07aSLuca Tettamanti #define ATK_HID "ATK0110"
20*2c03d07aSLuca Tettamanti 
21*2c03d07aSLuca Tettamanti /* Minimum time between readings, enforced in order to avoid
22*2c03d07aSLuca Tettamanti  * hogging the CPU.
23*2c03d07aSLuca Tettamanti  */
24*2c03d07aSLuca Tettamanti #define CACHE_TIME		HZ
25*2c03d07aSLuca Tettamanti 
26*2c03d07aSLuca Tettamanti #define BOARD_ID		"MBIF"
27*2c03d07aSLuca Tettamanti #define METHOD_ENUMERATE	"GGRP"
28*2c03d07aSLuca Tettamanti #define METHOD_READ		"GITM"
29*2c03d07aSLuca Tettamanti #define METHOD_WRITE		"SITM"
30*2c03d07aSLuca Tettamanti #define METHOD_OLD_READ_TMP	"RTMP"
31*2c03d07aSLuca Tettamanti #define METHOD_OLD_READ_VLT	"RVLT"
32*2c03d07aSLuca Tettamanti #define METHOD_OLD_READ_FAN	"RFAN"
33*2c03d07aSLuca Tettamanti #define METHOD_OLD_ENUM_TMP	"TSIF"
34*2c03d07aSLuca Tettamanti #define METHOD_OLD_ENUM_VLT	"VSIF"
35*2c03d07aSLuca Tettamanti #define METHOD_OLD_ENUM_FAN	"FSIF"
36*2c03d07aSLuca Tettamanti 
37*2c03d07aSLuca Tettamanti #define ATK_MUX_HWMON		0x00000006ULL
38*2c03d07aSLuca Tettamanti 
39*2c03d07aSLuca Tettamanti #define ATK_CLASS_MASK		0xff000000ULL
40*2c03d07aSLuca Tettamanti #define ATK_CLASS_FREQ_CTL	0x03000000ULL
41*2c03d07aSLuca Tettamanti #define ATK_CLASS_FAN_CTL	0x04000000ULL
42*2c03d07aSLuca Tettamanti #define ATK_CLASS_HWMON		0x06000000ULL
43*2c03d07aSLuca Tettamanti 
44*2c03d07aSLuca Tettamanti #define ATK_TYPE_MASK		0x00ff0000ULL
45*2c03d07aSLuca Tettamanti #define HWMON_TYPE_VOLT		0x00020000ULL
46*2c03d07aSLuca Tettamanti #define HWMON_TYPE_TEMP		0x00030000ULL
47*2c03d07aSLuca Tettamanti #define HWMON_TYPE_FAN		0x00040000ULL
48*2c03d07aSLuca Tettamanti 
49*2c03d07aSLuca Tettamanti #define HWMON_SENSOR_ID_MASK	0x0000ffffULL
50*2c03d07aSLuca Tettamanti 
51*2c03d07aSLuca Tettamanti enum atk_pack_member {
52*2c03d07aSLuca Tettamanti 	HWMON_PACK_FLAGS,
53*2c03d07aSLuca Tettamanti 	HWMON_PACK_NAME,
54*2c03d07aSLuca Tettamanti 	HWMON_PACK_LIMIT1,
55*2c03d07aSLuca Tettamanti 	HWMON_PACK_LIMIT2,
56*2c03d07aSLuca Tettamanti 	HWMON_PACK_ENABLE
57*2c03d07aSLuca Tettamanti };
58*2c03d07aSLuca Tettamanti 
59*2c03d07aSLuca Tettamanti /* New package format */
60*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_SIZE	7
61*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_FLAGS	0
62*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_NAME	1
63*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_UNK1	2
64*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_UNK2	3
65*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_LIMIT1	4
66*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_LIMIT2	5
67*2c03d07aSLuca Tettamanti #define _HWMON_NEW_PACK_ENABLE	6
68*2c03d07aSLuca Tettamanti 
69*2c03d07aSLuca Tettamanti /* Old package format */
70*2c03d07aSLuca Tettamanti #define _HWMON_OLD_PACK_SIZE	5
71*2c03d07aSLuca Tettamanti #define _HWMON_OLD_PACK_FLAGS	0
72*2c03d07aSLuca Tettamanti #define _HWMON_OLD_PACK_NAME	1
73*2c03d07aSLuca Tettamanti #define _HWMON_OLD_PACK_LIMIT1	2
74*2c03d07aSLuca Tettamanti #define _HWMON_OLD_PACK_LIMIT2	3
75*2c03d07aSLuca Tettamanti #define _HWMON_OLD_PACK_ENABLE	4
76*2c03d07aSLuca Tettamanti 
77*2c03d07aSLuca Tettamanti 
78*2c03d07aSLuca Tettamanti struct atk_data {
79*2c03d07aSLuca Tettamanti 	struct device *hwmon_dev;
80*2c03d07aSLuca Tettamanti 	acpi_handle atk_handle;
81*2c03d07aSLuca Tettamanti 	struct acpi_device *acpi_dev;
82*2c03d07aSLuca Tettamanti 
83*2c03d07aSLuca Tettamanti 	bool old_interface;
84*2c03d07aSLuca Tettamanti 
85*2c03d07aSLuca Tettamanti 	/* old interface */
86*2c03d07aSLuca Tettamanti 	acpi_handle rtmp_handle;
87*2c03d07aSLuca Tettamanti 	acpi_handle rvlt_handle;
88*2c03d07aSLuca Tettamanti 	acpi_handle rfan_handle;
89*2c03d07aSLuca Tettamanti 	/* new inteface */
90*2c03d07aSLuca Tettamanti 	acpi_handle enumerate_handle;
91*2c03d07aSLuca Tettamanti 	acpi_handle read_handle;
92*2c03d07aSLuca Tettamanti 
93*2c03d07aSLuca Tettamanti 	int voltage_count;
94*2c03d07aSLuca Tettamanti 	int temperature_count;
95*2c03d07aSLuca Tettamanti 	int fan_count;
96*2c03d07aSLuca Tettamanti 	struct list_head sensor_list;
97*2c03d07aSLuca Tettamanti };
98*2c03d07aSLuca Tettamanti 
99*2c03d07aSLuca Tettamanti 
100*2c03d07aSLuca Tettamanti typedef ssize_t (*sysfs_show_func)(struct device *dev,
101*2c03d07aSLuca Tettamanti 			struct device_attribute *attr, char *buf);
102*2c03d07aSLuca Tettamanti 
103*2c03d07aSLuca Tettamanti static const struct acpi_device_id atk_ids[] = {
104*2c03d07aSLuca Tettamanti 	{ATK_HID, 0},
105*2c03d07aSLuca Tettamanti 	{"", 0},
106*2c03d07aSLuca Tettamanti };
107*2c03d07aSLuca Tettamanti MODULE_DEVICE_TABLE(acpi, atk_ids);
108*2c03d07aSLuca Tettamanti 
109*2c03d07aSLuca Tettamanti #define ATTR_NAME_SIZE 16 /* Worst case is "tempN_input" */
110*2c03d07aSLuca Tettamanti 
111*2c03d07aSLuca Tettamanti struct atk_sensor_data {
112*2c03d07aSLuca Tettamanti 	struct list_head list;
113*2c03d07aSLuca Tettamanti 	struct atk_data *data;
114*2c03d07aSLuca Tettamanti 	struct device_attribute label_attr;
115*2c03d07aSLuca Tettamanti 	struct device_attribute input_attr;
116*2c03d07aSLuca Tettamanti 	struct device_attribute limit1_attr;
117*2c03d07aSLuca Tettamanti 	struct device_attribute limit2_attr;
118*2c03d07aSLuca Tettamanti 	char label_attr_name[ATTR_NAME_SIZE];
119*2c03d07aSLuca Tettamanti 	char input_attr_name[ATTR_NAME_SIZE];
120*2c03d07aSLuca Tettamanti 	char limit1_attr_name[ATTR_NAME_SIZE];
121*2c03d07aSLuca Tettamanti 	char limit2_attr_name[ATTR_NAME_SIZE];
122*2c03d07aSLuca Tettamanti 	u64 id;
123*2c03d07aSLuca Tettamanti 	u64 type;
124*2c03d07aSLuca Tettamanti 	u64 limit1;
125*2c03d07aSLuca Tettamanti 	u64 limit2;
126*2c03d07aSLuca Tettamanti 	u64 cached_value;
127*2c03d07aSLuca Tettamanti 	unsigned long last_updated; /* in jiffies */
128*2c03d07aSLuca Tettamanti 	bool is_valid;
129*2c03d07aSLuca Tettamanti 	char const *acpi_name;
130*2c03d07aSLuca Tettamanti };
131*2c03d07aSLuca Tettamanti 
132*2c03d07aSLuca Tettamanti struct atk_acpi_buffer_u64 {
133*2c03d07aSLuca Tettamanti 	union acpi_object buf;
134*2c03d07aSLuca Tettamanti 	u64 value;
135*2c03d07aSLuca Tettamanti };
136*2c03d07aSLuca Tettamanti 
137*2c03d07aSLuca Tettamanti static int atk_add(struct acpi_device *device);
138*2c03d07aSLuca Tettamanti static int atk_remove(struct acpi_device *device, int type);
139*2c03d07aSLuca Tettamanti static void atk_print_sensor(struct atk_data *data, union acpi_object *obj);
140*2c03d07aSLuca Tettamanti static int atk_read_value(struct atk_sensor_data *sensor, u64 *value);
141*2c03d07aSLuca Tettamanti static void atk_free_sensors(struct atk_data *data);
142*2c03d07aSLuca Tettamanti 
143*2c03d07aSLuca Tettamanti static struct acpi_driver atk_driver = {
144*2c03d07aSLuca Tettamanti 	.name	= ATK_HID,
145*2c03d07aSLuca Tettamanti 	.class	= "hwmon",
146*2c03d07aSLuca Tettamanti 	.ids	= atk_ids,
147*2c03d07aSLuca Tettamanti 	.ops	= {
148*2c03d07aSLuca Tettamanti 		.add	= atk_add,
149*2c03d07aSLuca Tettamanti 		.remove	= atk_remove,
150*2c03d07aSLuca Tettamanti 	},
151*2c03d07aSLuca Tettamanti };
152*2c03d07aSLuca Tettamanti 
153*2c03d07aSLuca Tettamanti #define input_to_atk_sensor(attr) \
154*2c03d07aSLuca Tettamanti 	container_of(attr, struct atk_sensor_data, input_attr)
155*2c03d07aSLuca Tettamanti 
156*2c03d07aSLuca Tettamanti #define label_to_atk_sensor(attr) \
157*2c03d07aSLuca Tettamanti 	container_of(attr, struct atk_sensor_data, label_attr)
158*2c03d07aSLuca Tettamanti 
159*2c03d07aSLuca Tettamanti #define limit1_to_atk_sensor(attr) \
160*2c03d07aSLuca Tettamanti 	container_of(attr, struct atk_sensor_data, limit1_attr)
161*2c03d07aSLuca Tettamanti 
162*2c03d07aSLuca Tettamanti #define limit2_to_atk_sensor(attr) \
163*2c03d07aSLuca Tettamanti 	container_of(attr, struct atk_sensor_data, limit2_attr)
164*2c03d07aSLuca Tettamanti 
165*2c03d07aSLuca Tettamanti static ssize_t atk_input_show(struct device *dev,
166*2c03d07aSLuca Tettamanti 		struct device_attribute *attr, char *buf)
167*2c03d07aSLuca Tettamanti {
168*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *s = input_to_atk_sensor(attr);
169*2c03d07aSLuca Tettamanti 	u64 value;
170*2c03d07aSLuca Tettamanti 	int err;
171*2c03d07aSLuca Tettamanti 
172*2c03d07aSLuca Tettamanti 	err = atk_read_value(s, &value);
173*2c03d07aSLuca Tettamanti 	if (err)
174*2c03d07aSLuca Tettamanti 		return err;
175*2c03d07aSLuca Tettamanti 
176*2c03d07aSLuca Tettamanti 	if (s->type == HWMON_TYPE_TEMP)
177*2c03d07aSLuca Tettamanti 		/* ACPI returns decidegree */
178*2c03d07aSLuca Tettamanti 		value *= 100;
179*2c03d07aSLuca Tettamanti 
180*2c03d07aSLuca Tettamanti 	return sprintf(buf, "%llu\n", value);
181*2c03d07aSLuca Tettamanti }
182*2c03d07aSLuca Tettamanti 
183*2c03d07aSLuca Tettamanti static ssize_t atk_label_show(struct device *dev,
184*2c03d07aSLuca Tettamanti 		struct device_attribute *attr, char *buf)
185*2c03d07aSLuca Tettamanti {
186*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *s = label_to_atk_sensor(attr);
187*2c03d07aSLuca Tettamanti 
188*2c03d07aSLuca Tettamanti 	return sprintf(buf, "%s\n", s->acpi_name);
189*2c03d07aSLuca Tettamanti }
190*2c03d07aSLuca Tettamanti 
191*2c03d07aSLuca Tettamanti static ssize_t atk_limit1_show(struct device *dev,
192*2c03d07aSLuca Tettamanti 		struct device_attribute *attr, char *buf)
193*2c03d07aSLuca Tettamanti {
194*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *s = limit1_to_atk_sensor(attr);
195*2c03d07aSLuca Tettamanti 	u64 value = s->limit1;
196*2c03d07aSLuca Tettamanti 
197*2c03d07aSLuca Tettamanti 	if (s->type == HWMON_TYPE_TEMP)
198*2c03d07aSLuca Tettamanti 		value *= 100;
199*2c03d07aSLuca Tettamanti 
200*2c03d07aSLuca Tettamanti 	return sprintf(buf, "%lld\n", value);
201*2c03d07aSLuca Tettamanti }
202*2c03d07aSLuca Tettamanti 
203*2c03d07aSLuca Tettamanti static ssize_t atk_limit2_show(struct device *dev,
204*2c03d07aSLuca Tettamanti 		struct device_attribute *attr, char *buf)
205*2c03d07aSLuca Tettamanti {
206*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *s = limit2_to_atk_sensor(attr);
207*2c03d07aSLuca Tettamanti 	u64 value = s->limit2;
208*2c03d07aSLuca Tettamanti 
209*2c03d07aSLuca Tettamanti 	if (s->type == HWMON_TYPE_TEMP)
210*2c03d07aSLuca Tettamanti 		value *= 100;
211*2c03d07aSLuca Tettamanti 
212*2c03d07aSLuca Tettamanti 	return sprintf(buf, "%lld\n", value);
213*2c03d07aSLuca Tettamanti }
214*2c03d07aSLuca Tettamanti 
215*2c03d07aSLuca Tettamanti static ssize_t atk_name_show(struct device *dev,
216*2c03d07aSLuca Tettamanti 				struct device_attribute *attr, char *buf)
217*2c03d07aSLuca Tettamanti {
218*2c03d07aSLuca Tettamanti 	return sprintf(buf, "atk0110\n");
219*2c03d07aSLuca Tettamanti }
220*2c03d07aSLuca Tettamanti static struct device_attribute atk_name_attr =
221*2c03d07aSLuca Tettamanti 		__ATTR(name, 0444, atk_name_show, NULL);
222*2c03d07aSLuca Tettamanti 
223*2c03d07aSLuca Tettamanti static void atk_init_attribute(struct device_attribute *attr, char *name,
224*2c03d07aSLuca Tettamanti 		sysfs_show_func show)
225*2c03d07aSLuca Tettamanti {
226*2c03d07aSLuca Tettamanti 	attr->attr.name = name;
227*2c03d07aSLuca Tettamanti 	attr->attr.mode = 0444;
228*2c03d07aSLuca Tettamanti 	attr->show = show;
229*2c03d07aSLuca Tettamanti 	attr->store = NULL;
230*2c03d07aSLuca Tettamanti }
231*2c03d07aSLuca Tettamanti 
232*2c03d07aSLuca Tettamanti 
233*2c03d07aSLuca Tettamanti static union acpi_object *atk_get_pack_member(struct atk_data *data,
234*2c03d07aSLuca Tettamanti 						union acpi_object *pack,
235*2c03d07aSLuca Tettamanti 						enum atk_pack_member m)
236*2c03d07aSLuca Tettamanti {
237*2c03d07aSLuca Tettamanti 	bool old_if = data->old_interface;
238*2c03d07aSLuca Tettamanti 	int offset;
239*2c03d07aSLuca Tettamanti 
240*2c03d07aSLuca Tettamanti 	switch (m) {
241*2c03d07aSLuca Tettamanti 	case HWMON_PACK_FLAGS:
242*2c03d07aSLuca Tettamanti 		offset = old_if ? _HWMON_OLD_PACK_FLAGS : _HWMON_NEW_PACK_FLAGS;
243*2c03d07aSLuca Tettamanti 		break;
244*2c03d07aSLuca Tettamanti 	case HWMON_PACK_NAME:
245*2c03d07aSLuca Tettamanti 		offset = old_if ? _HWMON_OLD_PACK_NAME : _HWMON_NEW_PACK_NAME;
246*2c03d07aSLuca Tettamanti 		break;
247*2c03d07aSLuca Tettamanti 	case HWMON_PACK_LIMIT1:
248*2c03d07aSLuca Tettamanti 		offset = old_if ? _HWMON_OLD_PACK_LIMIT1 :
249*2c03d07aSLuca Tettamanti 				  _HWMON_NEW_PACK_LIMIT1;
250*2c03d07aSLuca Tettamanti 		break;
251*2c03d07aSLuca Tettamanti 	case HWMON_PACK_LIMIT2:
252*2c03d07aSLuca Tettamanti 		offset = old_if ? _HWMON_OLD_PACK_LIMIT2 :
253*2c03d07aSLuca Tettamanti 				  _HWMON_NEW_PACK_LIMIT2;
254*2c03d07aSLuca Tettamanti 		break;
255*2c03d07aSLuca Tettamanti 	case HWMON_PACK_ENABLE:
256*2c03d07aSLuca Tettamanti 		offset = old_if ? _HWMON_OLD_PACK_ENABLE :
257*2c03d07aSLuca Tettamanti 				  _HWMON_NEW_PACK_ENABLE;
258*2c03d07aSLuca Tettamanti 		break;
259*2c03d07aSLuca Tettamanti 	default:
260*2c03d07aSLuca Tettamanti 		return NULL;
261*2c03d07aSLuca Tettamanti 	}
262*2c03d07aSLuca Tettamanti 
263*2c03d07aSLuca Tettamanti 	return &pack->package.elements[offset];
264*2c03d07aSLuca Tettamanti }
265*2c03d07aSLuca Tettamanti 
266*2c03d07aSLuca Tettamanti 
267*2c03d07aSLuca Tettamanti /* New package format is:
268*2c03d07aSLuca Tettamanti  * - flag (int)
269*2c03d07aSLuca Tettamanti  *	class - used for de-muxing the request to the correct GITn
270*2c03d07aSLuca Tettamanti  *	type (volt, temp, fan)
271*2c03d07aSLuca Tettamanti  *	sensor id |
272*2c03d07aSLuca Tettamanti  *	sensor id - used for de-muxing the request _inside_ the GITn
273*2c03d07aSLuca Tettamanti  * - name (str)
274*2c03d07aSLuca Tettamanti  * - unknown (int)
275*2c03d07aSLuca Tettamanti  * - unknown (int)
276*2c03d07aSLuca Tettamanti  * - limit1 (int)
277*2c03d07aSLuca Tettamanti  * - limit2 (int)
278*2c03d07aSLuca Tettamanti  * - enable (int)
279*2c03d07aSLuca Tettamanti  *
280*2c03d07aSLuca Tettamanti  * The old package has the same format but it's missing the two unknown fields.
281*2c03d07aSLuca Tettamanti  */
282*2c03d07aSLuca Tettamanti static int validate_hwmon_pack(struct atk_data *data, union acpi_object *obj)
283*2c03d07aSLuca Tettamanti {
284*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
285*2c03d07aSLuca Tettamanti 	union acpi_object *tmp;
286*2c03d07aSLuca Tettamanti 	bool old_if = data->old_interface;
287*2c03d07aSLuca Tettamanti 	int const expected_size = old_if ? _HWMON_OLD_PACK_SIZE :
288*2c03d07aSLuca Tettamanti 					   _HWMON_NEW_PACK_SIZE;
289*2c03d07aSLuca Tettamanti 
290*2c03d07aSLuca Tettamanti 	if (obj->type != ACPI_TYPE_PACKAGE) {
291*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type: %d\n", obj->type);
292*2c03d07aSLuca Tettamanti 		return -EINVAL;
293*2c03d07aSLuca Tettamanti 	}
294*2c03d07aSLuca Tettamanti 
295*2c03d07aSLuca Tettamanti 	if (obj->package.count != expected_size) {
296*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid package size: %d, expected: %d\n",
297*2c03d07aSLuca Tettamanti 				obj->package.count, expected_size);
298*2c03d07aSLuca Tettamanti 		return -EINVAL;
299*2c03d07aSLuca Tettamanti 	}
300*2c03d07aSLuca Tettamanti 
301*2c03d07aSLuca Tettamanti 	tmp = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS);
302*2c03d07aSLuca Tettamanti 	if (tmp->type != ACPI_TYPE_INTEGER) {
303*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type (flag): %d\n", tmp->type);
304*2c03d07aSLuca Tettamanti 		return -EINVAL;
305*2c03d07aSLuca Tettamanti 	}
306*2c03d07aSLuca Tettamanti 
307*2c03d07aSLuca Tettamanti 	tmp = atk_get_pack_member(data, obj, HWMON_PACK_NAME);
308*2c03d07aSLuca Tettamanti 	if (tmp->type != ACPI_TYPE_STRING) {
309*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type (name): %d\n", tmp->type);
310*2c03d07aSLuca Tettamanti 		return -EINVAL;
311*2c03d07aSLuca Tettamanti 	}
312*2c03d07aSLuca Tettamanti 
313*2c03d07aSLuca Tettamanti 	/* Don't check... we don't know what they're useful for anyway */
314*2c03d07aSLuca Tettamanti #if 0
315*2c03d07aSLuca Tettamanti 	tmp = &obj->package.elements[HWMON_PACK_UNK1];
316*2c03d07aSLuca Tettamanti 	if (tmp->type != ACPI_TYPE_INTEGER) {
317*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type (unk1): %d\n", tmp->type);
318*2c03d07aSLuca Tettamanti 		return -EINVAL;
319*2c03d07aSLuca Tettamanti 	}
320*2c03d07aSLuca Tettamanti 
321*2c03d07aSLuca Tettamanti 	tmp = &obj->package.elements[HWMON_PACK_UNK2];
322*2c03d07aSLuca Tettamanti 	if (tmp->type != ACPI_TYPE_INTEGER) {
323*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type (unk2): %d\n", tmp->type);
324*2c03d07aSLuca Tettamanti 		return -EINVAL;
325*2c03d07aSLuca Tettamanti 	}
326*2c03d07aSLuca Tettamanti #endif
327*2c03d07aSLuca Tettamanti 
328*2c03d07aSLuca Tettamanti 	tmp = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1);
329*2c03d07aSLuca Tettamanti 	if (tmp->type != ACPI_TYPE_INTEGER) {
330*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type (limit1): %d\n", tmp->type);
331*2c03d07aSLuca Tettamanti 		return -EINVAL;
332*2c03d07aSLuca Tettamanti 	}
333*2c03d07aSLuca Tettamanti 
334*2c03d07aSLuca Tettamanti 	tmp = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2);
335*2c03d07aSLuca Tettamanti 	if (tmp->type != ACPI_TYPE_INTEGER) {
336*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type (limit2): %d\n", tmp->type);
337*2c03d07aSLuca Tettamanti 		return -EINVAL;
338*2c03d07aSLuca Tettamanti 	}
339*2c03d07aSLuca Tettamanti 
340*2c03d07aSLuca Tettamanti 	tmp = atk_get_pack_member(data, obj, HWMON_PACK_ENABLE);
341*2c03d07aSLuca Tettamanti 	if (tmp->type != ACPI_TYPE_INTEGER) {
342*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Invalid type (enable): %d\n", tmp->type);
343*2c03d07aSLuca Tettamanti 		return -EINVAL;
344*2c03d07aSLuca Tettamanti 	}
345*2c03d07aSLuca Tettamanti 
346*2c03d07aSLuca Tettamanti 	atk_print_sensor(data, obj);
347*2c03d07aSLuca Tettamanti 
348*2c03d07aSLuca Tettamanti 	return 0;
349*2c03d07aSLuca Tettamanti }
350*2c03d07aSLuca Tettamanti 
351*2c03d07aSLuca Tettamanti static char const *atk_sensor_type(union acpi_object *flags)
352*2c03d07aSLuca Tettamanti {
353*2c03d07aSLuca Tettamanti 	u64 type = flags->integer.value & ATK_TYPE_MASK;
354*2c03d07aSLuca Tettamanti 	char const *what;
355*2c03d07aSLuca Tettamanti 
356*2c03d07aSLuca Tettamanti 	switch (type) {
357*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_VOLT:
358*2c03d07aSLuca Tettamanti 		what = "voltage";
359*2c03d07aSLuca Tettamanti 		break;
360*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_TEMP:
361*2c03d07aSLuca Tettamanti 		what = "temperature";
362*2c03d07aSLuca Tettamanti 		break;
363*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_FAN:
364*2c03d07aSLuca Tettamanti 		what = "fan";
365*2c03d07aSLuca Tettamanti 		break;
366*2c03d07aSLuca Tettamanti 	default:
367*2c03d07aSLuca Tettamanti 		what = "unknown";
368*2c03d07aSLuca Tettamanti 		break;
369*2c03d07aSLuca Tettamanti 	}
370*2c03d07aSLuca Tettamanti 
371*2c03d07aSLuca Tettamanti 	return what;
372*2c03d07aSLuca Tettamanti }
373*2c03d07aSLuca Tettamanti 
374*2c03d07aSLuca Tettamanti static void atk_print_sensor(struct atk_data *data, union acpi_object *obj)
375*2c03d07aSLuca Tettamanti {
376*2c03d07aSLuca Tettamanti #ifdef DEBUG
377*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
378*2c03d07aSLuca Tettamanti 	union acpi_object *flags;
379*2c03d07aSLuca Tettamanti 	union acpi_object *name;
380*2c03d07aSLuca Tettamanti 	union acpi_object *limit1;
381*2c03d07aSLuca Tettamanti 	union acpi_object *limit2;
382*2c03d07aSLuca Tettamanti 	union acpi_object *enable;
383*2c03d07aSLuca Tettamanti 	char const *what;
384*2c03d07aSLuca Tettamanti 
385*2c03d07aSLuca Tettamanti 	flags = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS);
386*2c03d07aSLuca Tettamanti 	name = atk_get_pack_member(data, obj, HWMON_PACK_NAME);
387*2c03d07aSLuca Tettamanti 	limit1 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1);
388*2c03d07aSLuca Tettamanti 	limit2 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2);
389*2c03d07aSLuca Tettamanti 	enable = atk_get_pack_member(data, obj, HWMON_PACK_ENABLE);
390*2c03d07aSLuca Tettamanti 
391*2c03d07aSLuca Tettamanti 	what = atk_sensor_type(flags);
392*2c03d07aSLuca Tettamanti 
393*2c03d07aSLuca Tettamanti 	dev_dbg(dev, "%s: %#llx %s [%llu-%llu] %s\n", what,
394*2c03d07aSLuca Tettamanti 			flags->integer.value,
395*2c03d07aSLuca Tettamanti 			name->string.pointer,
396*2c03d07aSLuca Tettamanti 			limit1->integer.value, limit2->integer.value,
397*2c03d07aSLuca Tettamanti 			enable->integer.value ? "enabled" : "disabled");
398*2c03d07aSLuca Tettamanti #endif
399*2c03d07aSLuca Tettamanti }
400*2c03d07aSLuca Tettamanti 
401*2c03d07aSLuca Tettamanti static int atk_read_value_old(struct atk_sensor_data *sensor, u64 *value)
402*2c03d07aSLuca Tettamanti {
403*2c03d07aSLuca Tettamanti 	struct atk_data *data = sensor->data;
404*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
405*2c03d07aSLuca Tettamanti 	struct acpi_object_list params;
406*2c03d07aSLuca Tettamanti 	union acpi_object id;
407*2c03d07aSLuca Tettamanti 	acpi_status status;
408*2c03d07aSLuca Tettamanti 	acpi_handle method;
409*2c03d07aSLuca Tettamanti 
410*2c03d07aSLuca Tettamanti 	switch (sensor->type) {
411*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_VOLT:
412*2c03d07aSLuca Tettamanti 		method = data->rvlt_handle;
413*2c03d07aSLuca Tettamanti 		break;
414*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_TEMP:
415*2c03d07aSLuca Tettamanti 		method = data->rtmp_handle;
416*2c03d07aSLuca Tettamanti 		break;
417*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_FAN:
418*2c03d07aSLuca Tettamanti 		method = data->rfan_handle;
419*2c03d07aSLuca Tettamanti 		break;
420*2c03d07aSLuca Tettamanti 	default:
421*2c03d07aSLuca Tettamanti 		return -EINVAL;
422*2c03d07aSLuca Tettamanti 	}
423*2c03d07aSLuca Tettamanti 
424*2c03d07aSLuca Tettamanti 	id.type = ACPI_TYPE_INTEGER;
425*2c03d07aSLuca Tettamanti 	id.integer.value = sensor->id;
426*2c03d07aSLuca Tettamanti 
427*2c03d07aSLuca Tettamanti 	params.count = 1;
428*2c03d07aSLuca Tettamanti 	params.pointer = &id;
429*2c03d07aSLuca Tettamanti 
430*2c03d07aSLuca Tettamanti 	status = acpi_evaluate_integer(method, NULL, &params, value);
431*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
432*2c03d07aSLuca Tettamanti 		dev_warn(dev, "%s: ACPI exception: %s\n", __func__,
433*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
434*2c03d07aSLuca Tettamanti 		return -EIO;
435*2c03d07aSLuca Tettamanti 	}
436*2c03d07aSLuca Tettamanti 
437*2c03d07aSLuca Tettamanti 	return 0;
438*2c03d07aSLuca Tettamanti }
439*2c03d07aSLuca Tettamanti 
440*2c03d07aSLuca Tettamanti static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value)
441*2c03d07aSLuca Tettamanti {
442*2c03d07aSLuca Tettamanti 	struct atk_data *data = sensor->data;
443*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
444*2c03d07aSLuca Tettamanti 	struct acpi_object_list params;
445*2c03d07aSLuca Tettamanti 	struct acpi_buffer ret;
446*2c03d07aSLuca Tettamanti 	union acpi_object id;
447*2c03d07aSLuca Tettamanti 	struct atk_acpi_buffer_u64 tmp;
448*2c03d07aSLuca Tettamanti 	acpi_status status;
449*2c03d07aSLuca Tettamanti 
450*2c03d07aSLuca Tettamanti 	id.type = ACPI_TYPE_INTEGER;
451*2c03d07aSLuca Tettamanti 	id.integer.value = sensor->id;
452*2c03d07aSLuca Tettamanti 
453*2c03d07aSLuca Tettamanti 	params.count = 1;
454*2c03d07aSLuca Tettamanti 	params.pointer = &id;
455*2c03d07aSLuca Tettamanti 
456*2c03d07aSLuca Tettamanti 	tmp.buf.type = ACPI_TYPE_BUFFER;
457*2c03d07aSLuca Tettamanti 	tmp.buf.buffer.pointer = (u8 *)&tmp.value;
458*2c03d07aSLuca Tettamanti 	tmp.buf.buffer.length = sizeof(u64);
459*2c03d07aSLuca Tettamanti 	ret.length = sizeof(tmp);
460*2c03d07aSLuca Tettamanti 	ret.pointer = &tmp;
461*2c03d07aSLuca Tettamanti 
462*2c03d07aSLuca Tettamanti 	status = acpi_evaluate_object_typed(data->read_handle, NULL, &params,
463*2c03d07aSLuca Tettamanti 			&ret, ACPI_TYPE_BUFFER);
464*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
465*2c03d07aSLuca Tettamanti 		dev_warn(dev, "%s: ACPI exception: %s\n", __func__,
466*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
467*2c03d07aSLuca Tettamanti 		return -EIO;
468*2c03d07aSLuca Tettamanti 	}
469*2c03d07aSLuca Tettamanti 
470*2c03d07aSLuca Tettamanti 	/* Return buffer format:
471*2c03d07aSLuca Tettamanti 	 * [0-3] "value" is valid flag
472*2c03d07aSLuca Tettamanti 	 * [4-7] value
473*2c03d07aSLuca Tettamanti 	 */
474*2c03d07aSLuca Tettamanti 	if (!(tmp.value & 0xffffffff)) {
475*2c03d07aSLuca Tettamanti 		/* The reading is not valid, possible causes:
476*2c03d07aSLuca Tettamanti 		 * - sensor failure
477*2c03d07aSLuca Tettamanti 		 * - enumeration was FUBAR (and we didn't notice)
478*2c03d07aSLuca Tettamanti 		 */
479*2c03d07aSLuca Tettamanti 		dev_info(dev, "Failure: %#llx\n", tmp.value);
480*2c03d07aSLuca Tettamanti 		return -EIO;
481*2c03d07aSLuca Tettamanti 	}
482*2c03d07aSLuca Tettamanti 
483*2c03d07aSLuca Tettamanti 	*value = (tmp.value & 0xffffffff00000000ULL) >> 32;
484*2c03d07aSLuca Tettamanti 
485*2c03d07aSLuca Tettamanti 	return 0;
486*2c03d07aSLuca Tettamanti }
487*2c03d07aSLuca Tettamanti 
488*2c03d07aSLuca Tettamanti static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
489*2c03d07aSLuca Tettamanti {
490*2c03d07aSLuca Tettamanti 	int err;
491*2c03d07aSLuca Tettamanti 
492*2c03d07aSLuca Tettamanti 	if (!sensor->is_valid ||
493*2c03d07aSLuca Tettamanti 	    time_after(jiffies, sensor->last_updated + CACHE_TIME)) {
494*2c03d07aSLuca Tettamanti 		if (sensor->data->old_interface)
495*2c03d07aSLuca Tettamanti 			err = atk_read_value_old(sensor, value);
496*2c03d07aSLuca Tettamanti 		else
497*2c03d07aSLuca Tettamanti 			err = atk_read_value_new(sensor, value);
498*2c03d07aSLuca Tettamanti 
499*2c03d07aSLuca Tettamanti 		sensor->is_valid = true;
500*2c03d07aSLuca Tettamanti 		sensor->last_updated = jiffies;
501*2c03d07aSLuca Tettamanti 		sensor->cached_value = *value;
502*2c03d07aSLuca Tettamanti 	} else {
503*2c03d07aSLuca Tettamanti 		*value = sensor->cached_value;
504*2c03d07aSLuca Tettamanti 		err = 0;
505*2c03d07aSLuca Tettamanti 	}
506*2c03d07aSLuca Tettamanti 
507*2c03d07aSLuca Tettamanti 	return err;
508*2c03d07aSLuca Tettamanti }
509*2c03d07aSLuca Tettamanti 
510*2c03d07aSLuca Tettamanti static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
511*2c03d07aSLuca Tettamanti {
512*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
513*2c03d07aSLuca Tettamanti 	union acpi_object *flags;
514*2c03d07aSLuca Tettamanti 	union acpi_object *name;
515*2c03d07aSLuca Tettamanti 	union acpi_object *limit1;
516*2c03d07aSLuca Tettamanti 	union acpi_object *limit2;
517*2c03d07aSLuca Tettamanti 	union acpi_object *enable;
518*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *sensor;
519*2c03d07aSLuca Tettamanti 	char const *base_name;
520*2c03d07aSLuca Tettamanti 	char const *limit1_name;
521*2c03d07aSLuca Tettamanti 	char const *limit2_name;
522*2c03d07aSLuca Tettamanti 	u64 type;
523*2c03d07aSLuca Tettamanti 	int err;
524*2c03d07aSLuca Tettamanti 	int *num;
525*2c03d07aSLuca Tettamanti 	int start;
526*2c03d07aSLuca Tettamanti 
527*2c03d07aSLuca Tettamanti 	if (obj->type != ACPI_TYPE_PACKAGE) {
528*2c03d07aSLuca Tettamanti 		/* wft is this? */
529*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Unknown type for ACPI object: (%d)\n",
530*2c03d07aSLuca Tettamanti 				obj->type);
531*2c03d07aSLuca Tettamanti 		return -EINVAL;
532*2c03d07aSLuca Tettamanti 	}
533*2c03d07aSLuca Tettamanti 
534*2c03d07aSLuca Tettamanti 	err = validate_hwmon_pack(data, obj);
535*2c03d07aSLuca Tettamanti 	if (err)
536*2c03d07aSLuca Tettamanti 		return err;
537*2c03d07aSLuca Tettamanti 
538*2c03d07aSLuca Tettamanti 	/* Ok, we have a valid hwmon package */
539*2c03d07aSLuca Tettamanti 	type = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS)->integer.value
540*2c03d07aSLuca Tettamanti 	       & ATK_TYPE_MASK;
541*2c03d07aSLuca Tettamanti 
542*2c03d07aSLuca Tettamanti 	switch (type) {
543*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_VOLT:
544*2c03d07aSLuca Tettamanti 		base_name = "in";
545*2c03d07aSLuca Tettamanti 		limit1_name = "min";
546*2c03d07aSLuca Tettamanti 		limit2_name = "max";
547*2c03d07aSLuca Tettamanti 		num = &data->voltage_count;
548*2c03d07aSLuca Tettamanti 		start = 0;
549*2c03d07aSLuca Tettamanti 		break;
550*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_TEMP:
551*2c03d07aSLuca Tettamanti 		base_name = "temp";
552*2c03d07aSLuca Tettamanti 		limit1_name = "max";
553*2c03d07aSLuca Tettamanti 		limit2_name = "crit";
554*2c03d07aSLuca Tettamanti 		num = &data->temperature_count;
555*2c03d07aSLuca Tettamanti 		start = 1;
556*2c03d07aSLuca Tettamanti 		break;
557*2c03d07aSLuca Tettamanti 	case HWMON_TYPE_FAN:
558*2c03d07aSLuca Tettamanti 		base_name = "fan";
559*2c03d07aSLuca Tettamanti 		limit1_name = "min";
560*2c03d07aSLuca Tettamanti 		limit2_name = "max";
561*2c03d07aSLuca Tettamanti 		num = &data->fan_count;
562*2c03d07aSLuca Tettamanti 		start = 1;
563*2c03d07aSLuca Tettamanti 		break;
564*2c03d07aSLuca Tettamanti 	default:
565*2c03d07aSLuca Tettamanti 		dev_warn(dev, "Unknown sensor type: %#llx\n", type);
566*2c03d07aSLuca Tettamanti 		return -EINVAL;
567*2c03d07aSLuca Tettamanti 	}
568*2c03d07aSLuca Tettamanti 
569*2c03d07aSLuca Tettamanti 	enable = atk_get_pack_member(data, obj, HWMON_PACK_ENABLE);
570*2c03d07aSLuca Tettamanti 	if (!enable->integer.value)
571*2c03d07aSLuca Tettamanti 		/* sensor is disabled */
572*2c03d07aSLuca Tettamanti 		return 0;
573*2c03d07aSLuca Tettamanti 
574*2c03d07aSLuca Tettamanti 	flags = atk_get_pack_member(data, obj, HWMON_PACK_FLAGS);
575*2c03d07aSLuca Tettamanti 	name = atk_get_pack_member(data, obj, HWMON_PACK_NAME);
576*2c03d07aSLuca Tettamanti 	limit1 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT1);
577*2c03d07aSLuca Tettamanti 	limit2 = atk_get_pack_member(data, obj, HWMON_PACK_LIMIT2);
578*2c03d07aSLuca Tettamanti 
579*2c03d07aSLuca Tettamanti 	sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
580*2c03d07aSLuca Tettamanti 	if (!sensor)
581*2c03d07aSLuca Tettamanti 		return -ENOMEM;
582*2c03d07aSLuca Tettamanti 
583*2c03d07aSLuca Tettamanti 	sensor->acpi_name = kstrdup(name->string.pointer, GFP_KERNEL);
584*2c03d07aSLuca Tettamanti 	if (!sensor->acpi_name) {
585*2c03d07aSLuca Tettamanti 		err = -ENOMEM;
586*2c03d07aSLuca Tettamanti 		goto out;
587*2c03d07aSLuca Tettamanti 	}
588*2c03d07aSLuca Tettamanti 
589*2c03d07aSLuca Tettamanti 	INIT_LIST_HEAD(&sensor->list);
590*2c03d07aSLuca Tettamanti 	sensor->type = type;
591*2c03d07aSLuca Tettamanti 	sensor->data = data;
592*2c03d07aSLuca Tettamanti 	sensor->id = flags->integer.value;
593*2c03d07aSLuca Tettamanti 	sensor->limit1 = limit1->integer.value;
594*2c03d07aSLuca Tettamanti 	sensor->limit2 = limit2->integer.value;
595*2c03d07aSLuca Tettamanti 
596*2c03d07aSLuca Tettamanti 	snprintf(sensor->input_attr_name, ATTR_NAME_SIZE,
597*2c03d07aSLuca Tettamanti 			"%s%d_input", base_name, start + *num);
598*2c03d07aSLuca Tettamanti 	atk_init_attribute(&sensor->input_attr,
599*2c03d07aSLuca Tettamanti 			sensor->input_attr_name,
600*2c03d07aSLuca Tettamanti 			atk_input_show);
601*2c03d07aSLuca Tettamanti 
602*2c03d07aSLuca Tettamanti 	snprintf(sensor->label_attr_name, ATTR_NAME_SIZE,
603*2c03d07aSLuca Tettamanti 			"%s%d_label", base_name, start + *num);
604*2c03d07aSLuca Tettamanti 	atk_init_attribute(&sensor->label_attr,
605*2c03d07aSLuca Tettamanti 			sensor->label_attr_name,
606*2c03d07aSLuca Tettamanti 			atk_label_show);
607*2c03d07aSLuca Tettamanti 
608*2c03d07aSLuca Tettamanti 	snprintf(sensor->limit1_attr_name, ATTR_NAME_SIZE,
609*2c03d07aSLuca Tettamanti 			"%s%d_%s", base_name, start + *num, limit1_name);
610*2c03d07aSLuca Tettamanti 	atk_init_attribute(&sensor->limit1_attr,
611*2c03d07aSLuca Tettamanti 			sensor->limit1_attr_name,
612*2c03d07aSLuca Tettamanti 			atk_limit1_show);
613*2c03d07aSLuca Tettamanti 
614*2c03d07aSLuca Tettamanti 	snprintf(sensor->limit2_attr_name, ATTR_NAME_SIZE,
615*2c03d07aSLuca Tettamanti 			"%s%d_%s", base_name, start + *num, limit2_name);
616*2c03d07aSLuca Tettamanti 	atk_init_attribute(&sensor->limit2_attr,
617*2c03d07aSLuca Tettamanti 			sensor->limit2_attr_name,
618*2c03d07aSLuca Tettamanti 			atk_limit2_show);
619*2c03d07aSLuca Tettamanti 
620*2c03d07aSLuca Tettamanti 	list_add(&sensor->list, &data->sensor_list);
621*2c03d07aSLuca Tettamanti 	(*num)++;
622*2c03d07aSLuca Tettamanti 
623*2c03d07aSLuca Tettamanti 	return 1;
624*2c03d07aSLuca Tettamanti out:
625*2c03d07aSLuca Tettamanti 	kfree(sensor->acpi_name);
626*2c03d07aSLuca Tettamanti 	kfree(sensor);
627*2c03d07aSLuca Tettamanti 	return err;
628*2c03d07aSLuca Tettamanti }
629*2c03d07aSLuca Tettamanti 
630*2c03d07aSLuca Tettamanti static int atk_enumerate_old_hwmon(struct atk_data *data)
631*2c03d07aSLuca Tettamanti {
632*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
633*2c03d07aSLuca Tettamanti 	struct acpi_buffer buf;
634*2c03d07aSLuca Tettamanti 	union acpi_object *pack;
635*2c03d07aSLuca Tettamanti 	acpi_status status;
636*2c03d07aSLuca Tettamanti 	int i, ret;
637*2c03d07aSLuca Tettamanti 	int count = 0;
638*2c03d07aSLuca Tettamanti 
639*2c03d07aSLuca Tettamanti 	/* Voltages */
640*2c03d07aSLuca Tettamanti 	buf.length = ACPI_ALLOCATE_BUFFER;
641*2c03d07aSLuca Tettamanti 	status = acpi_evaluate_object_typed(data->atk_handle,
642*2c03d07aSLuca Tettamanti 			METHOD_OLD_ENUM_VLT, NULL, &buf, ACPI_TYPE_PACKAGE);
643*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
644*2c03d07aSLuca Tettamanti 		dev_warn(dev, METHOD_OLD_ENUM_VLT ": ACPI exception: %s\n",
645*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
646*2c03d07aSLuca Tettamanti 
647*2c03d07aSLuca Tettamanti 		return -ENODEV;
648*2c03d07aSLuca Tettamanti 	}
649*2c03d07aSLuca Tettamanti 
650*2c03d07aSLuca Tettamanti 	pack = buf.pointer;
651*2c03d07aSLuca Tettamanti 	for (i = 1; i < pack->package.count; i++) {
652*2c03d07aSLuca Tettamanti 		union acpi_object *obj = &pack->package.elements[i];
653*2c03d07aSLuca Tettamanti 
654*2c03d07aSLuca Tettamanti 		ret = atk_add_sensor(data, obj);
655*2c03d07aSLuca Tettamanti 		if (ret > 0)
656*2c03d07aSLuca Tettamanti 			count++;
657*2c03d07aSLuca Tettamanti 	}
658*2c03d07aSLuca Tettamanti 	ACPI_FREE(buf.pointer);
659*2c03d07aSLuca Tettamanti 
660*2c03d07aSLuca Tettamanti 	/* Temperatures */
661*2c03d07aSLuca Tettamanti 	buf.length = ACPI_ALLOCATE_BUFFER;
662*2c03d07aSLuca Tettamanti 	status = acpi_evaluate_object_typed(data->atk_handle,
663*2c03d07aSLuca Tettamanti 			METHOD_OLD_ENUM_TMP, NULL, &buf, ACPI_TYPE_PACKAGE);
664*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
665*2c03d07aSLuca Tettamanti 		dev_warn(dev, METHOD_OLD_ENUM_TMP ": ACPI exception: %s\n",
666*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
667*2c03d07aSLuca Tettamanti 
668*2c03d07aSLuca Tettamanti 		ret = -ENODEV;
669*2c03d07aSLuca Tettamanti 		goto cleanup;
670*2c03d07aSLuca Tettamanti 	}
671*2c03d07aSLuca Tettamanti 
672*2c03d07aSLuca Tettamanti 	pack = buf.pointer;
673*2c03d07aSLuca Tettamanti 	for (i = 1; i < pack->package.count; i++) {
674*2c03d07aSLuca Tettamanti 		union acpi_object *obj = &pack->package.elements[i];
675*2c03d07aSLuca Tettamanti 
676*2c03d07aSLuca Tettamanti 		ret = atk_add_sensor(data, obj);
677*2c03d07aSLuca Tettamanti 		if (ret > 0)
678*2c03d07aSLuca Tettamanti 			count++;
679*2c03d07aSLuca Tettamanti 	}
680*2c03d07aSLuca Tettamanti 	ACPI_FREE(buf.pointer);
681*2c03d07aSLuca Tettamanti 
682*2c03d07aSLuca Tettamanti 	/* Fans */
683*2c03d07aSLuca Tettamanti 	buf.length = ACPI_ALLOCATE_BUFFER;
684*2c03d07aSLuca Tettamanti 	status = acpi_evaluate_object_typed(data->atk_handle,
685*2c03d07aSLuca Tettamanti 			METHOD_OLD_ENUM_FAN, NULL, &buf, ACPI_TYPE_PACKAGE);
686*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
687*2c03d07aSLuca Tettamanti 		dev_warn(dev, METHOD_OLD_ENUM_FAN ": ACPI exception: %s\n",
688*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
689*2c03d07aSLuca Tettamanti 
690*2c03d07aSLuca Tettamanti 		ret = -ENODEV;
691*2c03d07aSLuca Tettamanti 		goto cleanup;
692*2c03d07aSLuca Tettamanti 	}
693*2c03d07aSLuca Tettamanti 
694*2c03d07aSLuca Tettamanti 	pack = buf.pointer;
695*2c03d07aSLuca Tettamanti 	for (i = 1; i < pack->package.count; i++) {
696*2c03d07aSLuca Tettamanti 		union acpi_object *obj = &pack->package.elements[i];
697*2c03d07aSLuca Tettamanti 
698*2c03d07aSLuca Tettamanti 		ret = atk_add_sensor(data, obj);
699*2c03d07aSLuca Tettamanti 		if (ret > 0)
700*2c03d07aSLuca Tettamanti 			count++;
701*2c03d07aSLuca Tettamanti 	}
702*2c03d07aSLuca Tettamanti 	ACPI_FREE(buf.pointer);
703*2c03d07aSLuca Tettamanti 
704*2c03d07aSLuca Tettamanti 	return count;
705*2c03d07aSLuca Tettamanti cleanup:
706*2c03d07aSLuca Tettamanti 	atk_free_sensors(data);
707*2c03d07aSLuca Tettamanti 	return ret;
708*2c03d07aSLuca Tettamanti }
709*2c03d07aSLuca Tettamanti 
710*2c03d07aSLuca Tettamanti static int atk_enumerate_new_hwmon(struct atk_data *data)
711*2c03d07aSLuca Tettamanti {
712*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
713*2c03d07aSLuca Tettamanti 	struct acpi_buffer buf;
714*2c03d07aSLuca Tettamanti 	acpi_status ret;
715*2c03d07aSLuca Tettamanti 	struct acpi_object_list params;
716*2c03d07aSLuca Tettamanti 	union acpi_object id;
717*2c03d07aSLuca Tettamanti 	union acpi_object *pack;
718*2c03d07aSLuca Tettamanti 	int err;
719*2c03d07aSLuca Tettamanti 	int i;
720*2c03d07aSLuca Tettamanti 
721*2c03d07aSLuca Tettamanti 	dev_dbg(dev, "Enumerating hwmon sensors\n");
722*2c03d07aSLuca Tettamanti 
723*2c03d07aSLuca Tettamanti 	id.type = ACPI_TYPE_INTEGER;
724*2c03d07aSLuca Tettamanti 	id.integer.value = ATK_MUX_HWMON;
725*2c03d07aSLuca Tettamanti 	params.count = 1;
726*2c03d07aSLuca Tettamanti 	params.pointer = &id;
727*2c03d07aSLuca Tettamanti 
728*2c03d07aSLuca Tettamanti 	buf.length = ACPI_ALLOCATE_BUFFER;
729*2c03d07aSLuca Tettamanti 	ret = acpi_evaluate_object_typed(data->enumerate_handle, NULL, &params,
730*2c03d07aSLuca Tettamanti 			&buf, ACPI_TYPE_PACKAGE);
731*2c03d07aSLuca Tettamanti 	if (ret != AE_OK) {
732*2c03d07aSLuca Tettamanti 		dev_warn(dev, METHOD_ENUMERATE ": ACPI exception: %s\n",
733*2c03d07aSLuca Tettamanti 				acpi_format_exception(ret));
734*2c03d07aSLuca Tettamanti 		return -ENODEV;
735*2c03d07aSLuca Tettamanti 	}
736*2c03d07aSLuca Tettamanti 
737*2c03d07aSLuca Tettamanti 	/* Result must be a package */
738*2c03d07aSLuca Tettamanti 	pack = buf.pointer;
739*2c03d07aSLuca Tettamanti 
740*2c03d07aSLuca Tettamanti 	if (pack->package.count < 1) {
741*2c03d07aSLuca Tettamanti 		dev_dbg(dev, "%s: hwmon package is too small: %d\n", __func__,
742*2c03d07aSLuca Tettamanti 				pack->package.count);
743*2c03d07aSLuca Tettamanti 		err = -EINVAL;
744*2c03d07aSLuca Tettamanti 		goto out;
745*2c03d07aSLuca Tettamanti 	}
746*2c03d07aSLuca Tettamanti 
747*2c03d07aSLuca Tettamanti 	for (i = 0; i < pack->package.count; i++) {
748*2c03d07aSLuca Tettamanti 		union acpi_object *obj = &pack->package.elements[i];
749*2c03d07aSLuca Tettamanti 
750*2c03d07aSLuca Tettamanti 		atk_add_sensor(data, obj);
751*2c03d07aSLuca Tettamanti 	}
752*2c03d07aSLuca Tettamanti 
753*2c03d07aSLuca Tettamanti 	err = data->voltage_count + data->temperature_count + data->fan_count;
754*2c03d07aSLuca Tettamanti 
755*2c03d07aSLuca Tettamanti out:
756*2c03d07aSLuca Tettamanti 	ACPI_FREE(buf.pointer);
757*2c03d07aSLuca Tettamanti 	return err;
758*2c03d07aSLuca Tettamanti }
759*2c03d07aSLuca Tettamanti 
760*2c03d07aSLuca Tettamanti static int atk_create_files(struct atk_data *data)
761*2c03d07aSLuca Tettamanti {
762*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *s;
763*2c03d07aSLuca Tettamanti 	int err;
764*2c03d07aSLuca Tettamanti 
765*2c03d07aSLuca Tettamanti 	list_for_each_entry(s, &data->sensor_list, list) {
766*2c03d07aSLuca Tettamanti 		err = device_create_file(data->hwmon_dev, &s->input_attr);
767*2c03d07aSLuca Tettamanti 		if (err)
768*2c03d07aSLuca Tettamanti 			return err;
769*2c03d07aSLuca Tettamanti 		err = device_create_file(data->hwmon_dev, &s->label_attr);
770*2c03d07aSLuca Tettamanti 		if (err)
771*2c03d07aSLuca Tettamanti 			return err;
772*2c03d07aSLuca Tettamanti 		err = device_create_file(data->hwmon_dev, &s->limit1_attr);
773*2c03d07aSLuca Tettamanti 		if (err)
774*2c03d07aSLuca Tettamanti 			return err;
775*2c03d07aSLuca Tettamanti 		err = device_create_file(data->hwmon_dev, &s->limit2_attr);
776*2c03d07aSLuca Tettamanti 		if (err)
777*2c03d07aSLuca Tettamanti 			return err;
778*2c03d07aSLuca Tettamanti 	}
779*2c03d07aSLuca Tettamanti 
780*2c03d07aSLuca Tettamanti 	err = device_create_file(data->hwmon_dev, &atk_name_attr);
781*2c03d07aSLuca Tettamanti 
782*2c03d07aSLuca Tettamanti 	return err;
783*2c03d07aSLuca Tettamanti }
784*2c03d07aSLuca Tettamanti 
785*2c03d07aSLuca Tettamanti static void atk_remove_files(struct atk_data *data)
786*2c03d07aSLuca Tettamanti {
787*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *s;
788*2c03d07aSLuca Tettamanti 
789*2c03d07aSLuca Tettamanti 	list_for_each_entry(s, &data->sensor_list, list) {
790*2c03d07aSLuca Tettamanti 		device_remove_file(data->hwmon_dev, &s->input_attr);
791*2c03d07aSLuca Tettamanti 		device_remove_file(data->hwmon_dev, &s->label_attr);
792*2c03d07aSLuca Tettamanti 		device_remove_file(data->hwmon_dev, &s->limit1_attr);
793*2c03d07aSLuca Tettamanti 		device_remove_file(data->hwmon_dev, &s->limit2_attr);
794*2c03d07aSLuca Tettamanti 	}
795*2c03d07aSLuca Tettamanti 	device_remove_file(data->hwmon_dev, &atk_name_attr);
796*2c03d07aSLuca Tettamanti }
797*2c03d07aSLuca Tettamanti 
798*2c03d07aSLuca Tettamanti static void atk_free_sensors(struct atk_data *data)
799*2c03d07aSLuca Tettamanti {
800*2c03d07aSLuca Tettamanti 	struct list_head *head = &data->sensor_list;
801*2c03d07aSLuca Tettamanti 	struct atk_sensor_data *s, *tmp;
802*2c03d07aSLuca Tettamanti 
803*2c03d07aSLuca Tettamanti 	list_for_each_entry_safe(s, tmp, head, list) {
804*2c03d07aSLuca Tettamanti 		kfree(s->acpi_name);
805*2c03d07aSLuca Tettamanti 		kfree(s);
806*2c03d07aSLuca Tettamanti 	}
807*2c03d07aSLuca Tettamanti }
808*2c03d07aSLuca Tettamanti 
809*2c03d07aSLuca Tettamanti static int atk_register_hwmon(struct atk_data *data)
810*2c03d07aSLuca Tettamanti {
811*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
812*2c03d07aSLuca Tettamanti 	int err;
813*2c03d07aSLuca Tettamanti 
814*2c03d07aSLuca Tettamanti 	dev_dbg(dev, "registering hwmon device\n");
815*2c03d07aSLuca Tettamanti 	data->hwmon_dev = hwmon_device_register(dev);
816*2c03d07aSLuca Tettamanti 	if (IS_ERR(data->hwmon_dev))
817*2c03d07aSLuca Tettamanti 		return PTR_ERR(data->hwmon_dev);
818*2c03d07aSLuca Tettamanti 
819*2c03d07aSLuca Tettamanti 	dev_dbg(dev, "populating sysfs directory\n");
820*2c03d07aSLuca Tettamanti 	err = atk_create_files(data);
821*2c03d07aSLuca Tettamanti 	if (err)
822*2c03d07aSLuca Tettamanti 		goto remove;
823*2c03d07aSLuca Tettamanti 
824*2c03d07aSLuca Tettamanti 	return 0;
825*2c03d07aSLuca Tettamanti remove:
826*2c03d07aSLuca Tettamanti 	/* Cleanup the registered files */
827*2c03d07aSLuca Tettamanti 	atk_remove_files(data);
828*2c03d07aSLuca Tettamanti 	hwmon_device_unregister(data->hwmon_dev);
829*2c03d07aSLuca Tettamanti 	return err;
830*2c03d07aSLuca Tettamanti }
831*2c03d07aSLuca Tettamanti 
832*2c03d07aSLuca Tettamanti static int atk_check_old_if(struct atk_data *data)
833*2c03d07aSLuca Tettamanti {
834*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
835*2c03d07aSLuca Tettamanti 	acpi_handle ret;
836*2c03d07aSLuca Tettamanti 	acpi_status status;
837*2c03d07aSLuca Tettamanti 
838*2c03d07aSLuca Tettamanti 	/* RTMP: read temperature */
839*2c03d07aSLuca Tettamanti 	status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret);
840*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
841*2c03d07aSLuca Tettamanti 		dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n",
842*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
843*2c03d07aSLuca Tettamanti 		return -ENODEV;
844*2c03d07aSLuca Tettamanti 	}
845*2c03d07aSLuca Tettamanti 	data->rtmp_handle = ret;
846*2c03d07aSLuca Tettamanti 
847*2c03d07aSLuca Tettamanti 	/* RVLT: read voltage */
848*2c03d07aSLuca Tettamanti 	status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret);
849*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
850*2c03d07aSLuca Tettamanti 		dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n",
851*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
852*2c03d07aSLuca Tettamanti 		return -ENODEV;
853*2c03d07aSLuca Tettamanti 	}
854*2c03d07aSLuca Tettamanti 	data->rvlt_handle = ret;
855*2c03d07aSLuca Tettamanti 
856*2c03d07aSLuca Tettamanti 	/* RFAN: read fan status */
857*2c03d07aSLuca Tettamanti 	status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret);
858*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
859*2c03d07aSLuca Tettamanti 		dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n",
860*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
861*2c03d07aSLuca Tettamanti 		return -ENODEV;
862*2c03d07aSLuca Tettamanti 	}
863*2c03d07aSLuca Tettamanti 	data->rfan_handle = ret;
864*2c03d07aSLuca Tettamanti 
865*2c03d07aSLuca Tettamanti 	return 0;
866*2c03d07aSLuca Tettamanti }
867*2c03d07aSLuca Tettamanti 
868*2c03d07aSLuca Tettamanti static int atk_check_new_if(struct atk_data *data)
869*2c03d07aSLuca Tettamanti {
870*2c03d07aSLuca Tettamanti 	struct device *dev = &data->acpi_dev->dev;
871*2c03d07aSLuca Tettamanti 	acpi_handle ret;
872*2c03d07aSLuca Tettamanti 	acpi_status status;
873*2c03d07aSLuca Tettamanti 
874*2c03d07aSLuca Tettamanti 	/* Enumeration */
875*2c03d07aSLuca Tettamanti 	status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret);
876*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
877*2c03d07aSLuca Tettamanti 		dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n",
878*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
879*2c03d07aSLuca Tettamanti 		return -ENODEV;
880*2c03d07aSLuca Tettamanti 	}
881*2c03d07aSLuca Tettamanti 	data->enumerate_handle = ret;
882*2c03d07aSLuca Tettamanti 
883*2c03d07aSLuca Tettamanti 	/* De-multiplexer (read) */
884*2c03d07aSLuca Tettamanti 	status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret);
885*2c03d07aSLuca Tettamanti 	if (status != AE_OK) {
886*2c03d07aSLuca Tettamanti 		dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
887*2c03d07aSLuca Tettamanti 				acpi_format_exception(status));
888*2c03d07aSLuca Tettamanti 		return -ENODEV;
889*2c03d07aSLuca Tettamanti 	}
890*2c03d07aSLuca Tettamanti 	data->read_handle = ret;
891*2c03d07aSLuca Tettamanti 
892*2c03d07aSLuca Tettamanti 	return 0;
893*2c03d07aSLuca Tettamanti }
894*2c03d07aSLuca Tettamanti 
895*2c03d07aSLuca Tettamanti static int atk_add(struct acpi_device *device)
896*2c03d07aSLuca Tettamanti {
897*2c03d07aSLuca Tettamanti 	acpi_status ret;
898*2c03d07aSLuca Tettamanti 	int err;
899*2c03d07aSLuca Tettamanti 	struct acpi_buffer buf;
900*2c03d07aSLuca Tettamanti 	union acpi_object *obj;
901*2c03d07aSLuca Tettamanti 	struct atk_data *data;
902*2c03d07aSLuca Tettamanti 
903*2c03d07aSLuca Tettamanti 	dev_dbg(&device->dev, "adding...\n");
904*2c03d07aSLuca Tettamanti 
905*2c03d07aSLuca Tettamanti 	data = kzalloc(sizeof(*data), GFP_KERNEL);
906*2c03d07aSLuca Tettamanti 	if (!data)
907*2c03d07aSLuca Tettamanti 		return -ENOMEM;
908*2c03d07aSLuca Tettamanti 
909*2c03d07aSLuca Tettamanti 	data->acpi_dev = device;
910*2c03d07aSLuca Tettamanti 	data->atk_handle = device->handle;
911*2c03d07aSLuca Tettamanti 	INIT_LIST_HEAD(&data->sensor_list);
912*2c03d07aSLuca Tettamanti 
913*2c03d07aSLuca Tettamanti 	buf.length = ACPI_ALLOCATE_BUFFER;
914*2c03d07aSLuca Tettamanti 	ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL,
915*2c03d07aSLuca Tettamanti 			&buf, ACPI_TYPE_PACKAGE);
916*2c03d07aSLuca Tettamanti 	if (ret != AE_OK) {
917*2c03d07aSLuca Tettamanti 		dev_dbg(&device->dev, "atk: method MBIF not found\n");
918*2c03d07aSLuca Tettamanti 		err = -ENODEV;
919*2c03d07aSLuca Tettamanti 		goto out;
920*2c03d07aSLuca Tettamanti 	}
921*2c03d07aSLuca Tettamanti 
922*2c03d07aSLuca Tettamanti 	obj = buf.pointer;
923*2c03d07aSLuca Tettamanti 	if (obj->package.count >= 2 &&
924*2c03d07aSLuca Tettamanti 			obj->package.elements[1].type == ACPI_TYPE_STRING) {
925*2c03d07aSLuca Tettamanti 		dev_dbg(&device->dev, "board ID = %s\n",
926*2c03d07aSLuca Tettamanti 				obj->package.elements[1].string.pointer);
927*2c03d07aSLuca Tettamanti 	}
928*2c03d07aSLuca Tettamanti 	ACPI_FREE(buf.pointer);
929*2c03d07aSLuca Tettamanti 
930*2c03d07aSLuca Tettamanti 	/* Check for hwmon methods: first check "old" style methods; note that
931*2c03d07aSLuca Tettamanti 	 * both may be present: in this case we stick to the old interface;
932*2c03d07aSLuca Tettamanti 	 * analysis of multiple DSDTs indicates that when both interfaces
933*2c03d07aSLuca Tettamanti 	 * are present the new one (GGRP/GITM) is not functional.
934*2c03d07aSLuca Tettamanti 	 */
935*2c03d07aSLuca Tettamanti 	err = atk_check_old_if(data);
936*2c03d07aSLuca Tettamanti 	if (!err) {
937*2c03d07aSLuca Tettamanti 		dev_dbg(&device->dev, "Using old hwmon interface\n");
938*2c03d07aSLuca Tettamanti 		data->old_interface = true;
939*2c03d07aSLuca Tettamanti 	} else {
940*2c03d07aSLuca Tettamanti 		err = atk_check_new_if(data);
941*2c03d07aSLuca Tettamanti 		if (err)
942*2c03d07aSLuca Tettamanti 			goto out;
943*2c03d07aSLuca Tettamanti 
944*2c03d07aSLuca Tettamanti 		dev_dbg(&device->dev, "Using new hwmon interface\n");
945*2c03d07aSLuca Tettamanti 		data->old_interface = false;
946*2c03d07aSLuca Tettamanti 	}
947*2c03d07aSLuca Tettamanti 
948*2c03d07aSLuca Tettamanti 	if (data->old_interface)
949*2c03d07aSLuca Tettamanti 		err = atk_enumerate_old_hwmon(data);
950*2c03d07aSLuca Tettamanti 	else
951*2c03d07aSLuca Tettamanti 		err = atk_enumerate_new_hwmon(data);
952*2c03d07aSLuca Tettamanti 	if (err < 0)
953*2c03d07aSLuca Tettamanti 		goto out;
954*2c03d07aSLuca Tettamanti 	if (err == 0) {
955*2c03d07aSLuca Tettamanti 		dev_info(&device->dev,
956*2c03d07aSLuca Tettamanti 			 "No usable sensor detected, bailing out\n");
957*2c03d07aSLuca Tettamanti 		err = -ENODEV;
958*2c03d07aSLuca Tettamanti 		goto out;
959*2c03d07aSLuca Tettamanti 	}
960*2c03d07aSLuca Tettamanti 
961*2c03d07aSLuca Tettamanti 	err = atk_register_hwmon(data);
962*2c03d07aSLuca Tettamanti 	if (err)
963*2c03d07aSLuca Tettamanti 		goto cleanup;
964*2c03d07aSLuca Tettamanti 
965*2c03d07aSLuca Tettamanti 	device->driver_data = data;
966*2c03d07aSLuca Tettamanti 	return 0;
967*2c03d07aSLuca Tettamanti cleanup:
968*2c03d07aSLuca Tettamanti 	atk_free_sensors(data);
969*2c03d07aSLuca Tettamanti out:
970*2c03d07aSLuca Tettamanti 	kfree(data);
971*2c03d07aSLuca Tettamanti 	return err;
972*2c03d07aSLuca Tettamanti }
973*2c03d07aSLuca Tettamanti 
974*2c03d07aSLuca Tettamanti static int atk_remove(struct acpi_device *device, int type)
975*2c03d07aSLuca Tettamanti {
976*2c03d07aSLuca Tettamanti 	struct atk_data *data = device->driver_data;
977*2c03d07aSLuca Tettamanti 	dev_dbg(&device->dev, "removing...\n");
978*2c03d07aSLuca Tettamanti 
979*2c03d07aSLuca Tettamanti 	device->driver_data = NULL;
980*2c03d07aSLuca Tettamanti 
981*2c03d07aSLuca Tettamanti 	atk_remove_files(data);
982*2c03d07aSLuca Tettamanti 	atk_free_sensors(data);
983*2c03d07aSLuca Tettamanti 	hwmon_device_unregister(data->hwmon_dev);
984*2c03d07aSLuca Tettamanti 
985*2c03d07aSLuca Tettamanti 	kfree(data);
986*2c03d07aSLuca Tettamanti 
987*2c03d07aSLuca Tettamanti 	return 0;
988*2c03d07aSLuca Tettamanti }
989*2c03d07aSLuca Tettamanti 
990*2c03d07aSLuca Tettamanti static int __init atk0110_init(void)
991*2c03d07aSLuca Tettamanti {
992*2c03d07aSLuca Tettamanti 	int ret;
993*2c03d07aSLuca Tettamanti 
994*2c03d07aSLuca Tettamanti 	ret = acpi_bus_register_driver(&atk_driver);
995*2c03d07aSLuca Tettamanti 	if (ret)
996*2c03d07aSLuca Tettamanti 		pr_info("atk: acpi_bus_register_driver failed: %d\n", ret);
997*2c03d07aSLuca Tettamanti 
998*2c03d07aSLuca Tettamanti 	return ret;
999*2c03d07aSLuca Tettamanti }
1000*2c03d07aSLuca Tettamanti 
1001*2c03d07aSLuca Tettamanti static void __exit atk0110_exit(void)
1002*2c03d07aSLuca Tettamanti {
1003*2c03d07aSLuca Tettamanti 	acpi_bus_unregister_driver(&atk_driver);
1004*2c03d07aSLuca Tettamanti }
1005*2c03d07aSLuca Tettamanti 
1006*2c03d07aSLuca Tettamanti module_init(atk0110_init);
1007*2c03d07aSLuca Tettamanti module_exit(atk0110_exit);
1008*2c03d07aSLuca Tettamanti 
1009*2c03d07aSLuca Tettamanti MODULE_LICENSE("GPL");
1010