View | Details | Raw Unified | Return to bug 204807 | Differences between
and this patch

Collapse All | Expand All

(-)a/Documentation/hwmon/asus_wmi_ec_sensors.rst (+35 lines)
Line 0 Link Here
1
Kernel driver asus-wmi-ec-sensors
2
=================================
3
4
Supported boards:
5
 * PRIME X570-PRO,
6
 * Pro WS X570-ACE,
7
 * ROG CROSSHAIR VIII DARK HERO,
8
 * ROG CROSSHAIR VIII FORMULA,
9
 * ROG CROSSHAIR VIII HERO,
10
 * ROG STRIX B550-E GAMING,
11
 * ROG STRIX X570-E GAMING.
12
13
Authors:
14
        Eugene Shalygin <eugene.shalygin@gmail.com>
15
16
Description:
17
------------
18
ASUS mainboards publish hardware monitoring information via Super I/O
19
chip and the ACPI embedded controller (EC) registers. Some of the sensors
20
are only available via the EC.
21
22
ASUS WMI interface provides a method (BREC) to read data from EC registers,
23
which is utilized by this driver to publish those sensor readings to the
24
HWMON system. The driver is aware of and reads the following sensors:
25
26
1. Chipset (PCH) temperature
27
2. CPU package temperature
28
3. Motherboard temperature
29
4. Readings from the T_Sensor header
30
5. VRM temperature
31
6. CPU_Opt fan RPM
32
7. Chipset fan RPM
33
8. Readings from the "Water flow meter" header (RPM)
34
9. Readings from the "Water In" and "Water Out" temperature headers
35
10. CPU current
(-)a/Documentation/hwmon/asus_wmi_sensors.rst (+62 lines)
Line 0 Link Here
1
Kernel driver asus-wmi-sensors
2
=================================
3
4
Supported boards:
5
 * PRIME X399-A,
6
 * PRIME X470-PRO,
7
 * ROG CROSSHAIR VI EXTREME,
8
 * ROG CROSSHAIR VI HERO,
9
 * ROG CROSSHAIR VI HERO (WI-FI AC),
10
 * ROG CROSSHAIR VII HERO,
11
 * ROG CROSSHAIR VII HERO (WI-FI),
12
 * ROG STRIX B450-E GAMING,
13
 * ROG STRIX B450-F GAMING,
14
 * ROG STRIX B450-I GAMING,
15
 * ROG STRIX X399-E GAMING,
16
 * ROG STRIX X470-F GAMING,
17
 * ROG STRIX X470-I GAMING,
18
 * ROG ZENITH EXTREME,
19
 * ROG ZENITH EXTREME ALPHA.
20
21
Authors:
22
        Ed Brindley <kernel@maidavale.org>
23
24
Description:
25
------------
26
ASUS mainboards publish hardware monitoring information via WMI interface.
27
28
ASUS WMI interface provides a methods to get list of sensors and values of
29
such, which is utilized by this driver to publish those sensor readings to the
30
HWMON system. The driver is aware of and reads the following sensors:
31
 * CPU Core Voltage,
32
 * CPU SOC Voltage,
33
 * DRAM Voltage,
34
 * VDDP Voltage,
35
 * 1.8V PLL Voltage,
36
 * +12V Voltage,
37
 * +5V Voltage,
38
 * 3VSB Voltage,
39
 * VBAT Voltage,
40
 * AVCC3 Voltage,
41
 * SB 1.05V Voltage,
42
 * CPU Core Voltage,
43
 * CPU SOC Voltage,
44
 * DRAM Voltage,
45
 * CPU Fan RPM,
46
 * Chassis Fan 1 RPM,
47
 * Chassis Fan 2 RPM,
48
 * Chassis Fan 3 RPM,
49
 * HAMP Fan RPM,
50
 * Water Pump RPM,
51
 * CPU OPT RPM,
52
 * Water Flow RPM,
53
 * AIO Pump RPM,
54
 * CPU Temperature,
55
 * CPU Socket Temperature,
56
 * Motherboard Temperature,
57
 * Chipset Temperature,
58
 * Tsensor 1 Temperature,
59
 * CPU VRM Temperature,
60
 * Water In,
61
 * Water Out,
62
 * CPU VRM Output Current.
(-)a/MAINTAINERS (+8 lines)
Lines 2937-2942 W: http://acpi4asus.sf.net Link Here
2937
F:	drivers/platform/x86/asus*.c
2937
F:	drivers/platform/x86/asus*.c
2938
F:	drivers/platform/x86/eeepc*.c
2938
F:	drivers/platform/x86/eeepc*.c
2939
2939
2940
ASUS WMI HARDWARE MONITOR DRIVER
2941
M:	Eugene Shalygin <eugene.shalygin@gmail.com>
2942
M:	Denis Pauk <pauk.denis@gmail.com>
2943
L:	linux-hwmon@vger.kernel.org
2944
S:	Maintained
2945
F:	drivers/hwmon/asus_wmi_ec_sensors.c
2946
F:	drivers/hwmon/asus_wmi_sensors.c
2947
2940
ASUS WIRELESS RADIO CONTROL DRIVER
2948
ASUS WIRELESS RADIO CONTROL DRIVER
2941
M:	João Paulo Rechi Vita <jprvita@gmail.com>
2949
M:	João Paulo Rechi Vita <jprvita@gmail.com>
2942
L:	platform-driver-x86@vger.kernel.org
2950
L:	platform-driver-x86@vger.kernel.org
(-)a/drivers/hwmon/Kconfig (+22 lines)
Lines 2215-2220 config SENSORS_ATK0110 Link Here
2215
	  This driver can also be built as a module. If so, the module
2215
	  This driver can also be built as a module. If so, the module
2216
	  will be called asus_atk0110.
2216
	  will be called asus_atk0110.
2217
2217
2218
config SENSORS_ASUS_WMI
2219
	tristate "ASUS WMI X370/X470/B450/X399"
2220
	help
2221
	  If you say yes here you get support for the ACPI hardware monitoring
2222
	  interface found in X370/X470/B450/X399 ASUS motherboards. This driver
2223
	  will provide readings of fans, voltages and temperatures through the system
2224
	  firmware.
2225
2226
	  This driver can also be built as a module. If so, the module
2227
	  will be called asus_wmi_sensors.
2228
2229
config SENSORS_ASUS_WMI_EC
2230
	tristate "ASUS WMI B550/X570"
2231
	help
2232
	  If you say yes here you get support for the ACPI embedded controller
2233
	  hardware monitoring interface found in B550/X570 ASUS motherboards.
2234
	  This driver will provide readings of fans, voltages and temperatures
2235
	  through the system firmware.
2236
2237
	  This driver can also be built as a module. If so, the module
2238
	  will be called asus_wmi_sensors_ec.
2239
2218
endif # ACPI
2240
endif # ACPI
2219
2241
2220
endif # HWMON
2242
endif # HWMON
(-)a/drivers/hwmon/Makefile (+2 lines)
Lines 9-14 obj-$(CONFIG_HWMON_VID) += hwmon-vid.o Link Here
9
# APCI drivers
9
# APCI drivers
10
obj-$(CONFIG_SENSORS_ACPI_POWER) += acpi_power_meter.o
10
obj-$(CONFIG_SENSORS_ACPI_POWER) += acpi_power_meter.o
11
obj-$(CONFIG_SENSORS_ATK0110)	+= asus_atk0110.o
11
obj-$(CONFIG_SENSORS_ATK0110)	+= asus_atk0110.o
12
obj-$(CONFIG_SENSORS_ASUS_WMI)	+= asus_wmi_sensors.o
13
obj-$(CONFIG_SENSORS_ASUS_WMI_EC)	+= asus_wmi_ec_sensors.o
12
14
13
# Native drivers
15
# Native drivers
14
# asb100, then w83781d go first, as they can override other drivers' addresses.
16
# asb100, then w83781d go first, as they can override other drivers' addresses.
(-)a/drivers/hwmon/asus_wmi_ec_sensors.c (+659 lines)
Line 0 Link Here
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * HWMON driver for ASUS B550/X570 motherboards that publish sensor
4
 * values via the embedded controller registers.
5
 *
6
 * Copyright (C) 2021 Eugene Shalygin <eugene.shalygin@gmail.com>
7
 * Copyright (C) 2018-2019 Ed Brindley <kernel@maidavale.org>
8
 *
9
 * EC provides:
10
 * Chipset temperature,
11
 * CPU temperature,
12
 * Motherboard temperature,
13
 * T_Sensor temperature,
14
 * VRM  temperature,
15
 * Water In temperature,
16
 * Water Out temperature,
17
 * CPU Optional Fan RPM,
18
 * Chipset Fan RPM,
19
 * Water Flow Fan RPM,
20
 * CPU current.
21
 *
22
 */
23
#include <asm/unaligned.h>
24
#include <linux/acpi.h>
25
#include <linux/dmi.h>
26
#include <linux/hwmon.h>
27
#include <linux/hwmon-sysfs.h>
28
#include <linux/init.h>
29
#include <linux/jiffies.h>
30
#include <linux/kernel.h>
31
#include <linux/module.h>
32
#include <linux/mutex.h>
33
#include <linux/nls.h>
34
#include <linux/platform_device.h>
35
#include <linux/units.h>
36
#include <linux/wmi.h>
37
38
#define ASUSWMI_MONITORING_GUID		"466747A0-70EC-11DE-8A39-0800200C9A66"
39
#define ASUSWMI_METHODID_BLOCK_READ_EC		0x42524543 /* BREC */
40
41
#define ASUS_WMI_BLOCK_READ_REGISTERS_MAX 0x10 /* from the ASUS DSDT source */
42
/* from the ASUS_WMI_BLOCK_READ_REGISTERS_MAX value */
43
#define ASUS_WMI_MAX_BUF_LEN 0x80
44
#define MAX_SENSOR_LABEL_LENGTH 0x10
45
46
static u32 hwmon_attributes[] = {
47
	[hwmon_chip] = HWMON_C_REGISTER_TZ,
48
	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
49
	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
50
	[hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
51
	[hwmon_fan] = HWMON_F_INPUT | HWMON_F_LABEL,
52
};
53
54
struct asus_wmi_ec_sensor_address {
55
	u8 index;
56
	u8 bank;
57
	u8 size;
58
};
59
60
#define MAKE_SENSOR_ADDRESS(size_i, bank_i, index_i) \
61
	{ .size = size_i,\
62
	   .bank = bank_i,\
63
	   .index = index_i}
64
65
struct ec_sensor_info {
66
	char label[MAX_SENSOR_LABEL_LENGTH];
67
	enum hwmon_sensor_types type;
68
	struct asus_wmi_ec_sensor_address addr;
69
};
70
71
#define EC_SENSOR(sensor_label, sensor_type, size, bank, index) \
72
	{ .label = sensor_label,\
73
	.type = sensor_type, \
74
	.addr = MAKE_SENSOR_ADDRESS(size, bank, index) \
75
	}
76
77
enum known_ec_sensor {
78
	SENSOR_TEMP_CHIPSET,
79
	SENSOR_TEMP_CPU,
80
	SENSOR_TEMP_MB,
81
	SENSOR_TEMP_T_SENSOR,
82
	SENSOR_TEMP_VRM,
83
	SENSOR_FAN_CPU_OPT,
84
	SENSOR_FAN_CHIPSET,
85
	SENSOR_FAN_WATER_FLOW,
86
	SENSOR_CURR_CPU,
87
	SENSOR_TEMP_WATER_IN,
88
	SENSOR_TEMP_WATER_OUT,
89
	SENSOR_MAX
90
};
91
92
/*
93
 * All the known sensors for ASUS EC controllers
94
 */
95
static const struct ec_sensor_info known_ec_sensors[] = {
96
	[SENSOR_TEMP_CHIPSET] = EC_SENSOR("Chipset", hwmon_temp, 1, 0x00, 0x3a),
97
	[SENSOR_TEMP_CPU] = EC_SENSOR("CPU", hwmon_temp, 1, 0x00, 0x3b),
98
	[SENSOR_TEMP_MB] = EC_SENSOR("Motherboard", hwmon_temp, 1, 0x00, 0x3c),
99
	[SENSOR_TEMP_T_SENSOR] = EC_SENSOR("T_Sensor", hwmon_temp, 1, 0x00, 0x3d),
100
	[SENSOR_TEMP_VRM] = EC_SENSOR("VRM", hwmon_temp, 1, 0x00, 0x3e),
101
	[SENSOR_FAN_CPU_OPT] = EC_SENSOR("CPU_Opt", hwmon_fan, 2, 0x00, 0xb0),
102
	[SENSOR_FAN_CHIPSET] = EC_SENSOR("Chipset", hwmon_fan, 2, 0x00, 0xb4),
103
	[SENSOR_FAN_WATER_FLOW] = EC_SENSOR("Water_Flow", hwmon_fan, 2, 0x00, 0xbc),
104
	[SENSOR_CURR_CPU] = EC_SENSOR("CPU", hwmon_curr, 1, 0x00, 0xf4),
105
	[SENSOR_TEMP_WATER_IN] = EC_SENSOR("Water_In", hwmon_temp, 1, 0x01, 0x00),
106
	[SENSOR_TEMP_WATER_OUT] = EC_SENSOR("Water_Out", hwmon_temp, 1, 0x01, 0x01),
107
};
108
109
struct asus_wmi_data {
110
	const enum known_ec_sensor known_board_sensors[SENSOR_MAX + 1];
111
};
112
113
/* boards with EC support */
114
static struct asus_wmi_data sensors_board_PW_X570_P = {
115
	.known_board_sensors = {
116
		SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU, SENSOR_TEMP_MB, SENSOR_TEMP_VRM,
117
		SENSOR_FAN_CHIPSET,
118
		SENSOR_MAX
119
	},
120
};
121
122
static struct asus_wmi_data sensors_board_PW_X570_A = {
123
	.known_board_sensors = {
124
		SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU, SENSOR_TEMP_MB, SENSOR_TEMP_VRM,
125
		SENSOR_FAN_CHIPSET,
126
		SENSOR_CURR_CPU,
127
		SENSOR_MAX
128
	},
129
};
130
131
static struct asus_wmi_data sensors_board_R_C8H = {
132
	.known_board_sensors = {
133
		SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU, SENSOR_TEMP_MB,
134
		SENSOR_TEMP_T_SENSOR, SENSOR_TEMP_VRM,
135
		SENSOR_TEMP_WATER_IN, SENSOR_TEMP_WATER_OUT,
136
		SENSOR_FAN_CPU_OPT, SENSOR_FAN_CHIPSET, SENSOR_FAN_WATER_FLOW,
137
		SENSOR_CURR_CPU,
138
		SENSOR_MAX
139
	},
140
};
141
142
/* Same as Hero but without chipset fan */
143
static struct asus_wmi_data sensors_board_R_C8DH = {
144
	.known_board_sensors = {
145
		SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU, SENSOR_TEMP_MB,
146
		SENSOR_TEMP_T_SENSOR, SENSOR_TEMP_VRM,
147
		SENSOR_TEMP_WATER_IN, SENSOR_TEMP_WATER_OUT,
148
		SENSOR_FAN_CPU_OPT, SENSOR_FAN_WATER_FLOW,
149
		SENSOR_CURR_CPU,
150
		SENSOR_MAX
151
	},
152
};
153
154
/* Same as Hero but without water */
155
static struct asus_wmi_data sensors_board_R_C8F = {
156
	.known_board_sensors = {
157
		SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU, SENSOR_TEMP_MB,
158
		SENSOR_TEMP_T_SENSOR, SENSOR_TEMP_VRM,
159
		SENSOR_FAN_CPU_OPT, SENSOR_FAN_CHIPSET,
160
		SENSOR_CURR_CPU,
161
		SENSOR_MAX
162
	},
163
};
164
165
static struct asus_wmi_data sensors_board_RS_B550_E_G = {
166
	.known_board_sensors = {
167
		SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU, SENSOR_TEMP_MB,
168
		SENSOR_TEMP_T_SENSOR, SENSOR_TEMP_VRM,
169
		SENSOR_FAN_CPU_OPT,
170
		SENSOR_CURR_CPU,
171
		SENSOR_MAX
172
	},
173
};
174
175
static struct asus_wmi_data sensors_board_RS_X570_E_G = {
176
	.known_board_sensors = {
177
		SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU, SENSOR_TEMP_MB,
178
		SENSOR_TEMP_T_SENSOR, SENSOR_TEMP_VRM,
179
		SENSOR_FAN_CHIPSET,
180
		SENSOR_CURR_CPU,
181
		SENSOR_MAX
182
	},
183
};
184
185
static struct asus_wmi_data *board_sensors;
186
187
static int __init asus_wmi_dmi_matched(const struct dmi_system_id *d)
188
{
189
	board_sensors = d->driver_data;
190
	return 0;
191
}
192
193
#define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name, sensors) \
194
	{ \
195
		.callback = asus_wmi_dmi_matched, \
196
		.matches = { \
197
			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, \
198
					"ASUSTeK COMPUTER INC."), \
199
			DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
200
		}, \
201
		.driver_data = sensors, \
202
	}
203
204
static const struct dmi_system_id asus_wmi_ec_dmi_table[] __initconst = {
205
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X570-PRO", &sensors_board_PW_X570_P),
206
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("Pro WS X570-ACE", &sensors_board_PW_X570_A),
207
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII DARK HERO", &sensors_board_R_C8DH),
208
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII FORMULA", &sensors_board_R_C8F),
209
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VIII HERO", &sensors_board_R_C8H),
210
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B550-E GAMING", &sensors_board_RS_B550_E_G),
211
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X570-E GAMING", &sensors_board_RS_X570_E_G),
212
	{}
213
};
214
MODULE_DEVICE_TABLE(dmi, asus_wmi_ec_dmi_table);
215
216
struct ec_sensor {
217
	enum known_ec_sensor info_index;
218
	u32 cached_value;
219
};
220
221
/**
222
 * struct asus_wmi_ec_info - sensor info.
223
 * @sensors: list of sensors.
224
 * @read_arg: UTF-16 string to pass to BRxx() WMI function.
225
 * @read_buffer: decoded output from WMI result.
226
 * @nr_sensors: number of board EC sensors.
227
 * @nr_registers: number of EC registers to read (sensor might span more than
228
 *                         1 register).
229
 * @last_updated: in jiffies.
230
 */
231
struct asus_wmi_ec_info {
232
	struct ec_sensor sensors[SENSOR_MAX];
233
	char read_arg[((ASUS_WMI_BLOCK_READ_REGISTERS_MAX * 4) + 1) * 2];
234
	u8 read_buffer[ASUS_WMI_BLOCK_READ_REGISTERS_MAX];
235
	unsigned int nr_sensors;
236
	unsigned int nr_registers;
237
	unsigned long last_updated;
238
};
239
240
struct asus_wmi_sensors {
241
	/* lock access to instrnal cache */
242
	struct mutex lock;
243
	struct asus_wmi_ec_info ec;
244
};
245
246
static int asus_wmi_ec_fill_board_sensors(struct asus_wmi_ec_info *ec)
247
{
248
	const enum known_ec_sensor *bsi;
249
	struct ec_sensor *s = ec->sensors;
250
	int i;
251
252
	if (!board_sensors)
253
		return -ENODEV;
254
255
	bsi = board_sensors->known_board_sensors;
256
	ec->nr_sensors = 0;
257
	ec->nr_registers = 0;
258
259
	for (i = 0; i < SENSOR_MAX && bsi[i] != SENSOR_MAX; i++) {
260
		s[i].info_index = bsi[i];
261
		s[i].cached_value = 0;
262
		ec->nr_sensors++;
263
		ec->nr_registers += known_ec_sensors[bsi[i]].addr.size;
264
	}
265
266
	return 0;
267
}
268
269
/*
270
 * The next four functions converts to/from BRxx string argument format
271
 * The format of the string is as follows:
272
 * The string consists of two-byte UTF-16 characters
273
 * The value of the very first byte int the string is equal to the total length
274
 * of the next string in bytes, thus excluding the first two-byte character
275
 * The rest of the string encodes pairs of (bank, index) pairs, where both
276
 * values are byte-long (0x00 to 0xFF)
277
 * Numbers are encoded as UTF-16 hex values
278
 */
279
static void asus_wmi_ec_decode_reply_buffer(const u8 *inp, u8 *out)
280
{
281
	unsigned int len = ACPI_MIN(ASUS_WMI_MAX_BUF_LEN, inp[0] / 4);
282
	char buffer[ASUS_WMI_MAX_BUF_LEN * 2];
283
	const char *pos = buffer;
284
	const u8 *data = inp + 2;
285
	unsigned int i;
286
287
	utf16s_to_utf8s((wchar_t *)data, len * 2,  UTF16_LITTLE_ENDIAN, buffer, len * 2);
288
289
	for (i = 0; i < len; i++, pos += 2)
290
		out[i] = (hex_to_bin(pos[0]) << 4) + hex_to_bin(pos[1]);
291
}
292
293
static void asus_wmi_ec_encode_registers(u16 *registers, u8 len, char *out)
294
{
295
	char buffer[ASUS_WMI_MAX_BUF_LEN * 2];
296
	char *pos = buffer;
297
	unsigned int i;
298
	u8 byte;
299
300
	*out++ = len * 8;
301
	*out++ = 0;
302
303
	for (i = 0; i < len; i++) {
304
		byte = registers[i] >> 8;
305
		*pos = hex_asc_hi(byte);
306
		pos++;
307
		*pos = hex_asc_lo(byte);
308
		pos++;
309
		byte = registers[i];
310
		*pos = hex_asc_hi(byte);
311
		pos++;
312
		*pos = hex_asc_lo(byte);
313
		pos++;
314
	}
315
316
	utf8s_to_utf16s(buffer, len * 4, UTF16_LITTLE_ENDIAN, (wchar_t *)out, len * 4);
317
}
318
319
static void asus_wmi_ec_make_block_read_query(struct asus_wmi_ec_info *ec)
320
{
321
	u16 registers[ASUS_WMI_BLOCK_READ_REGISTERS_MAX];
322
	const struct ec_sensor_info *si;
323
	int i, j, register_idx = 0;
324
325
	/*
326
	 * if we can get values for all the registers in a single query,
327
	 * the query will not change from call to call
328
	 */
329
	if (ec->nr_registers <= ASUS_WMI_BLOCK_READ_REGISTERS_MAX &&
330
	    ec->read_arg[0] > 0) {
331
		/* no need to update */
332
		return;
333
	}
334
335
	for (i = 0; i < ec->nr_sensors; i++) {
336
		si = &known_ec_sensors[ec->sensors[i].info_index];
337
		for (j = 0; j < si->addr.size;
338
		     j++, register_idx++) {
339
			registers[register_idx] = (si->addr.bank << 8) + si->addr.index + j;
340
		}
341
	}
342
343
	asus_wmi_ec_encode_registers(registers, ec->nr_registers, ec->read_arg);
344
}
345
346
static int asus_wmi_ec_block_read(u32 method_id, char *query, u8 *out)
347
{
348
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER,
349
				      NULL };
350
	struct acpi_buffer input;
351
	union acpi_object *obj;
352
	acpi_status status;
353
354
	/* the first byte of the BRxx() argument string has to be the string size */
355
	input.length = (acpi_size)query[0] + 2;
356
	input.pointer = query;
357
	status = wmi_evaluate_method(ASUSWMI_MONITORING_GUID, 0, method_id, &input,
358
				     &output);
359
	if (ACPI_FAILURE(status))
360
		return -EIO;
361
362
	obj = output.pointer;
363
	if (!obj || obj->type != ACPI_TYPE_BUFFER) {
364
		if (!obj)
365
			acpi_os_free(output.pointer);
366
367
		return -EIO;
368
	}
369
	asus_wmi_ec_decode_reply_buffer(obj->buffer.pointer, out);
370
	acpi_os_free(output.pointer);
371
	return 0;
372
}
373
374
static int asus_wmi_ec_update_ec_sensors(struct asus_wmi_ec_info *ec)
375
{
376
	const struct ec_sensor_info *si;
377
	struct ec_sensor *s;
378
379
	int status;
380
	u8 i_sensor, read_reg_ct;
381
382
	asus_wmi_ec_make_block_read_query(ec);
383
	status = asus_wmi_ec_block_read(ASUSWMI_METHODID_BLOCK_READ_EC,
384
					ec->read_arg,
385
					ec->read_buffer);
386
	if (status)
387
		return status;
388
389
	read_reg_ct = 0;
390
	for (i_sensor = 0; i_sensor < ec->nr_sensors; i_sensor++) {
391
		s = &ec->sensors[i_sensor];
392
		si = &known_ec_sensors[s->info_index];
393
394
		switch (si->addr.size) {
395
		case 1:
396
			s->cached_value = ec->read_buffer[read_reg_ct];
397
			break;
398
		case 2:
399
			s->cached_value = get_unaligned_be16(&ec->read_buffer[read_reg_ct]);
400
			break;
401
		case 4:
402
			s->cached_value = get_unaligned_be32(&ec->read_buffer[read_reg_ct]);
403
			break;
404
		default:
405
			s->cached_value =  0;
406
		}
407
		read_reg_ct += si->addr.size;
408
	}
409
	return 0;
410
}
411
412
static int asus_wmi_ec_scale_sensor_value(u32 value, int data_type)
413
{
414
	switch (data_type) {
415
	case hwmon_curr:
416
	case hwmon_temp:
417
	case hwmon_in:
418
		return value * KILO;
419
	default:
420
		return value;
421
	}
422
}
423
424
static int asus_wmi_ec_find_sensor_index(const struct asus_wmi_ec_info *ec,
425
					 enum hwmon_sensor_types type, int channel)
426
{
427
	int i;
428
429
	for (i = 0; i < ec->nr_sensors; i++) {
430
		if (known_ec_sensors[ec->sensors[i].info_index].type == type) {
431
			if (channel == 0)
432
				return i;
433
434
			channel--;
435
		}
436
	}
437
	return -EINVAL;
438
}
439
440
static int asus_wmi_ec_get_cached_value_or_update(int sensor_index,
441
						  struct asus_wmi_sensors *state,
442
						  u32 *value)
443
{
444
	int ret;
445
446
	if (time_after(jiffies, state->ec.last_updated + HZ)) {
447
		ret = asus_wmi_ec_update_ec_sensors(&state->ec);
448
		if (ret)
449
			return ret;
450
451
		state->ec.last_updated = jiffies;
452
	}
453
454
	*value = state->ec.sensors[sensor_index].cached_value;
455
	return 0;
456
}
457
458
/*
459
 * Now follow the functions that implement the hwmon interface
460
 */
461
462
static int asus_wmi_ec_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
463
				  u32 attr, int channel, long *val)
464
{
465
	struct asus_wmi_sensors *sensor_data = dev_get_drvdata(dev);
466
	int ret, sidx, info_index;
467
	u32 value = 0;
468
469
	sidx = asus_wmi_ec_find_sensor_index(&sensor_data->ec, type, channel);
470
	if (sidx < 0)
471
		return sidx;
472
473
	mutex_lock(&sensor_data->lock);
474
	ret = asus_wmi_ec_get_cached_value_or_update(sidx, sensor_data, &value);
475
	mutex_unlock(&sensor_data->lock);
476
	if (ret)
477
		return ret;
478
479
	info_index = sensor_data->ec.sensors[sidx].info_index;
480
	*val = asus_wmi_ec_scale_sensor_value(value,
481
					      known_ec_sensors[info_index].type);
482
483
	return ret;
484
}
485
486
static int asus_wmi_ec_hwmon_read_string(struct device *dev,
487
					 enum hwmon_sensor_types type, u32 attr,
488
					 int channel, const char **str)
489
{
490
	struct asus_wmi_sensors *sensor_data = dev_get_drvdata(dev);
491
	int sensor_index;
492
493
	sensor_index = asus_wmi_ec_find_sensor_index(&sensor_data->ec, type, channel);
494
	*str = known_ec_sensors[sensor_data->ec.sensors[sensor_index].info_index].label;
495
496
	return 0;
497
}
498
499
static umode_t asus_wmi_ec_hwmon_is_visible(const void *drvdata,
500
					    enum hwmon_sensor_types type, u32 attr,
501
					    int channel)
502
{
503
	int index;
504
	const struct asus_wmi_sensors *sensor_data = drvdata;
505
506
	index = asus_wmi_ec_find_sensor_index(&sensor_data->ec, type, channel);
507
508
	return index == 0xff ? 0 : 0444;
509
}
510
511
static int asus_wmi_hwmon_add_chan_info(struct hwmon_channel_info *asus_wmi_hwmon_chan,
512
					struct device *dev, int num,
513
					enum hwmon_sensor_types type, u32 config)
514
{
515
	u32 *cfg;
516
517
	cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
518
	if (!cfg)
519
		return -ENOMEM;
520
521
	asus_wmi_hwmon_chan->type = type;
522
	asus_wmi_hwmon_chan->config = cfg;
523
	memset32(cfg, config, num);
524
525
	return 0;
526
}
527
528
static const struct hwmon_ops asus_wmi_ec_hwmon_ops = {
529
	.is_visible = asus_wmi_ec_hwmon_is_visible,
530
	.read = asus_wmi_ec_hwmon_read,
531
	.read_string = asus_wmi_ec_hwmon_read_string,
532
};
533
534
static struct hwmon_chip_info asus_wmi_ec_chip_info = {
535
	.ops = &asus_wmi_ec_hwmon_ops,
536
};
537
538
static int asus_wmi_ec_configure_sensor_setup(struct platform_device *pdev,
539
					      struct asus_wmi_sensors *sensor_data)
540
{
541
	struct hwmon_channel_info *asus_wmi_hwmon_chan;
542
	const struct hwmon_channel_info **ptr_asus_wmi_ci;
543
	int nr_count[hwmon_max] = { 0 }, nr_types = 0;
544
	const struct hwmon_chip_info *chip_info;
545
	struct device *dev = &pdev->dev;
546
	const struct ec_sensor_info *si;
547
	enum hwmon_sensor_types type;
548
	struct device *hwdev;
549
	int i, ret;
550
551
	ret = asus_wmi_ec_fill_board_sensors(&sensor_data->ec);
552
	if (ret)
553
		return ret;
554
555
	if (!sensor_data->ec.nr_sensors)
556
		return -ENODEV;
557
558
	for (i = 0; i < sensor_data->ec.nr_sensors; i++) {
559
		si = &known_ec_sensors[sensor_data->ec.sensors[i].info_index];
560
		if (!nr_count[si->type])
561
			nr_types++;
562
		nr_count[si->type]++;
563
	}
564
565
	if (nr_count[hwmon_temp]) {
566
		nr_count[hwmon_chip]++;
567
		nr_types++;
568
	}
569
570
	asus_wmi_hwmon_chan = devm_kcalloc(dev, nr_types,
571
					   sizeof(*asus_wmi_hwmon_chan),
572
					   GFP_KERNEL);
573
	if (!asus_wmi_hwmon_chan)
574
		return -ENOMEM;
575
576
	ptr_asus_wmi_ci = devm_kcalloc(dev, nr_types + 1,
577
				       sizeof(*ptr_asus_wmi_ci), GFP_KERNEL);
578
	if (!ptr_asus_wmi_ci)
579
		return -ENOMEM;
580
581
	asus_wmi_ec_chip_info.info = ptr_asus_wmi_ci;
582
	chip_info = &asus_wmi_ec_chip_info;
583
584
	for (type = 0; type < hwmon_max; type++) {
585
		if (!nr_count[type])
586
			continue;
587
588
		ret = asus_wmi_hwmon_add_chan_info(asus_wmi_hwmon_chan, dev,
589
						   nr_count[type], type,
590
						   hwmon_attributes[type]);
591
		if (ret)
592
			return ret;
593
594
		*ptr_asus_wmi_ci++ = asus_wmi_hwmon_chan++;
595
	}
596
597
	dev_dbg(&pdev->dev, "board has %d EC sensors that span %d registers",
598
		sensor_data->ec.nr_sensors,
599
		sensor_data->ec.nr_registers);
600
601
	hwdev = devm_hwmon_device_register_with_info(dev, KBUILD_MODNAME,
602
						     sensor_data, chip_info, NULL);
603
604
	return PTR_ERR_OR_ZERO(hwdev);
605
}
606
607
static int asus_wmi_probe(struct platform_device *pdev)
608
{
609
	struct asus_wmi_sensors *sensor_data;
610
	struct device *dev = &pdev->dev;
611
612
	sensor_data = devm_kzalloc(dev, sizeof(struct asus_wmi_sensors),
613
				   GFP_KERNEL);
614
	if (!sensor_data)
615
		return -ENOMEM;
616
617
	mutex_init(&sensor_data->lock);
618
619
	platform_set_drvdata(pdev, sensor_data);
620
621
	/* ec init */
622
	return asus_wmi_ec_configure_sensor_setup(pdev,
623
						  sensor_data);
624
}
625
626
static struct platform_driver asus_wmi_sensors_platform_driver = {
627
	.driver = {
628
		.name	= "asus-wmi-sensors",
629
	},
630
	.probe = asus_wmi_probe,
631
};
632
633
static struct platform_device *sensors_pdev;
634
635
static int __init asus_wmi_init(void)
636
{
637
	if (!dmi_check_system(asus_wmi_ec_dmi_table))
638
		return -ENODEV;
639
640
	sensors_pdev = platform_create_bundle(&asus_wmi_sensors_platform_driver,
641
					      asus_wmi_probe,
642
					      NULL, 0,
643
					      NULL, 0);
644
645
	return PTR_ERR_OR_ZERO(sensors_pdev);
646
}
647
module_init(asus_wmi_init);
648
649
static void __exit asus_wmi_exit(void)
650
{
651
	platform_device_unregister(sensors_pdev);
652
	platform_driver_unregister(&asus_wmi_sensors_platform_driver);
653
}
654
module_exit(asus_wmi_exit);
655
656
MODULE_AUTHOR("Ed Brindley <kernel@maidavale.org>");
657
MODULE_AUTHOR("Eugene Shalygin <eugene.shalygin@gmail.com>");
658
MODULE_DESCRIPTION("Asus WMI Sensors Driver");
659
MODULE_LICENSE("GPL");
(-)a/drivers/hwmon/asus_wmi_sensors.c (+635 lines)
Line 0 Link Here
1
// SPDX-License-Identifier: GPL-2.0+
2
/*
3
 * HWMON driver for ASUS motherboards that provides sensor readouts via WMI
4
 * interface present in the UEFI of the X370/X470/B450/X399 Ryzen motherboards.
5
 *
6
 * Copyright (C) 2018-2019 Ed Brindley <kernel@maidavale.org>
7
 *
8
 * WMI interface provides:
9
 * CPU Core Voltage,
10
 * CPU SOC Voltage,
11
 * DRAM Voltage,
12
 * VDDP Voltage,
13
 * 1.8V PLL Voltage,
14
 * +12V Voltage,
15
 * +5V Voltage,
16
 * 3VSB Voltage,
17
 * VBAT Voltage,
18
 * AVCC3 Voltage,
19
 * SB 1.05V Voltage,
20
 * CPU Core Voltage,
21
 * CPU SOC Voltage,
22
 * DRAM Voltage,
23
 * CPU Fan RPM,
24
 * Chassis Fan 1 RPM,
25
 * Chassis Fan 2 RPM,
26
 * Chassis Fan 3 RPM,
27
 * HAMP Fan RPM,
28
 * Water Pump RPM,
29
 * CPU OPT RPM,
30
 * Water Flow RPM,
31
 * AIO Pump RPM,
32
 * CPU Temperature,
33
 * CPU Socket Temperature,
34
 * Motherboard Temperature,
35
 * Chipset Temperature,
36
 * Tsensor 1 Temperature,
37
 * CPU VRM Temperature,
38
 * Water In,
39
 * Water Out,
40
 * CPU VRM Output Current.
41
 *
42
 */
43
#include <linux/acpi.h>
44
#include <linux/dmi.h>
45
#include <linux/hwmon.h>
46
#include <linux/hwmon-sysfs.h>
47
#include <linux/init.h>
48
#include <linux/jiffies.h>
49
#include <linux/kernel.h>
50
#include <linux/module.h>
51
#include <linux/mutex.h>
52
#include <linux/platform_device.h>
53
#include <linux/units.h>
54
#include <linux/wmi.h>
55
56
#define ASUSWMI_MONITORING_GUID		"466747A0-70EC-11DE-8A39-0800200C9A66"
57
#define ASUSWMI_METHODID_GET_VALUE	0x52574543
58
#define ASUSWMI_METHODID_UPDATE_BUFFER	0x51574543
59
#define ASUSWMI_METHODID_GET_INFO	0x50574543
60
#define ASUSWMI_METHODID_GET_NUMBER		0x50574572
61
#define ASUSWMI_METHODID_GET_VERSION		0x50574574
62
63
#define ASUS_WMI_MAX_STR_SIZE	32
64
65
#define DMI_EXACT_MATCH_ASUS_BOARD_NAME(name) \
66
	{ \
67
		.matches = { \
68
			DMI_EXACT_MATCH(DMI_BOARD_VENDOR, \
69
					"ASUSTeK COMPUTER INC."), \
70
			DMI_EXACT_MATCH(DMI_BOARD_NAME, name), \
71
		}, \
72
	}
73
74
static const struct dmi_system_id asus_wmi_dmi_table[] __initconst = {
75
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X399-A"),
76
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("PRIME X470-PRO"),
77
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI EXTREME"),
78
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI HERO"),
79
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VI HERO (WI-FI AC)"),
80
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VII HERO"),
81
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG CROSSHAIR VII HERO (WI-FI)"),
82
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B450-E GAMING"),
83
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B450-F GAMING"),
84
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX B450-I GAMING"),
85
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X399-E GAMING"),
86
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X470-F GAMING"),
87
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG STRIX X470-I GAMING"),
88
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH EXTREME"),
89
	DMI_EXACT_MATCH_ASUS_BOARD_NAME("ROG ZENITH EXTREME ALPHA"),
90
	{}
91
};
92
MODULE_DEVICE_TABLE(dmi, asus_wmi_dmi_table);
93
94
enum asus_wmi_sensor_class {
95
	VOLTAGE = 0x0,
96
	TEMPERATURE_C = 0x1,
97
	FAN_RPM = 0x2,
98
	CURRENT = 0x3,
99
	WATER_FLOW = 0x4,
100
};
101
102
enum asus_wmi_location {
103
	CPU = 0x0,
104
	CPU_SOC = 0x1,
105
	DRAM = 0x2,
106
	MOTHERBOARD = 0x3,
107
	CHIPSET = 0x4,
108
	AUX = 0x5,
109
	VRM = 0x6,
110
	COOLER = 0x7
111
};
112
113
enum asus_wmi_type {
114
	SIGNED_INT = 0x0,
115
	UNSIGNED_INT = 0x1,
116
	SCALED = 0x3,
117
};
118
119
enum asus_wmi_source {
120
	SIO = 0x1,
121
	EC = 0x2
122
};
123
124
static enum hwmon_sensor_types asus_data_types[] = {
125
	[VOLTAGE] = hwmon_in,
126
	[TEMPERATURE_C] = hwmon_temp,
127
	[FAN_RPM] = hwmon_fan,
128
	[CURRENT] = hwmon_curr,
129
	[WATER_FLOW] = hwmon_fan,
130
};
131
132
static u32 hwmon_attributes[] = {
133
	[hwmon_chip] = HWMON_C_REGISTER_TZ,
134
	[hwmon_temp] = HWMON_T_INPUT | HWMON_T_LABEL,
135
	[hwmon_in] = HWMON_I_INPUT | HWMON_I_LABEL,
136
	[hwmon_curr] = HWMON_C_INPUT | HWMON_C_LABEL,
137
	[hwmon_fan] = HWMON_F_INPUT | HWMON_F_LABEL,
138
};
139
140
/**
141
 * struct asus_wmi_sensor_info - sensor info.
142
 * @id: sensor id.
143
 * @data_type: sensor class e.g. voltage, temp etc.
144
 * @location: sensor location.
145
 * @name: sensor name.
146
 * @source: sensor source.
147
 * @type: sensor type signed, unsigned etc.
148
 * @cached_value: cached sensor value.
149
 */
150
struct asus_wmi_sensor_info {
151
	u32 id;
152
	int data_type;
153
	int location;
154
	char name[ASUS_WMI_MAX_STR_SIZE];
155
	int source;
156
	int type;
157
	u32 cached_value;
158
};
159
160
struct asus_wmi_wmi_info {
161
	u8 buffer;
162
	unsigned long source_last_updated[3];	/* in jiffies */
163
	int sensor_count;
164
165
	const struct asus_wmi_sensor_info **info[hwmon_max];
166
	struct asus_wmi_sensor_info **info_by_id;
167
};
168
169
struct asus_wmi_sensors {
170
	/* lock access to instrnal cache */
171
	struct mutex lock;
172
	struct asus_wmi_wmi_info wmi;
173
};
174
175
/*
176
 * Universal method for calling WMI method
177
 */
178
static int asus_wmi_call_method(u32 method_id, u32 *args, struct acpi_buffer *output)
179
{
180
	struct acpi_buffer input = {(acpi_size) sizeof(*args), args };
181
	acpi_status status;
182
183
	status = wmi_evaluate_method(ASUSWMI_MONITORING_GUID, 0, method_id, &input, output);
184
	if (ACPI_FAILURE(status))
185
		return -EIO;
186
187
	return 0;
188
}
189
190
/*
191
 * Gets the version of the ASUS sensors interface implemented
192
 */
193
static int asus_wmi_get_version(u32 *version)
194
{
195
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
196
	u32 args[] = {0, 0, 0};
197
	union acpi_object *obj;
198
	int err;
199
200
	err = asus_wmi_call_method(ASUSWMI_METHODID_GET_VERSION, args, &output);
201
	if (err)
202
		return err;
203
204
	obj = output.pointer;
205
	if (!obj || obj->type != ACPI_TYPE_INTEGER)
206
		return -EIO;
207
208
	*version = obj->integer.value;
209
210
	return 0;
211
}
212
213
/*
214
 * Gets the number of sensor items
215
 */
216
static int asus_wmi_get_item_count(u32 *count)
217
{
218
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
219
	u32 args[] = {0, 0, 0};
220
	union acpi_object *obj;
221
	int err;
222
223
	err = asus_wmi_call_method(ASUSWMI_METHODID_GET_NUMBER, args, &output);
224
	if (err)
225
		return err;
226
227
	obj = output.pointer;
228
	if (!obj || obj->type != ACPI_TYPE_INTEGER)
229
		return -EIO;
230
231
	*count = obj->integer.value;
232
233
	return 0;
234
}
235
236
static int asus_wmi_hwmon_add_chan_info(struct hwmon_channel_info *asus_wmi_hwmon_chan,
237
					struct device *dev, int num,
238
					enum hwmon_sensor_types type, u32 config)
239
{
240
	u32 *cfg;
241
242
	cfg = devm_kcalloc(dev, num + 1, sizeof(*cfg), GFP_KERNEL);
243
	if (!cfg)
244
		return -ENOMEM;
245
246
	asus_wmi_hwmon_chan->type = type;
247
	asus_wmi_hwmon_chan->config = cfg;
248
	memset32(cfg, config, num);
249
250
	return 0;
251
}
252
253
/*
254
 * For a given sensor item returns details e.g. type (voltage/temperature/fan speed etc), bank etc
255
 */
256
static int asus_wmi_sensor_info(int index, struct asus_wmi_sensor_info *s)
257
{
258
	union acpi_object name_obj, data_type_obj, location_obj, source_obj, type_obj;
259
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
260
	u32 args[] = {index, 0};
261
	union acpi_object *obj;
262
	int err;
263
264
	err = asus_wmi_call_method(ASUSWMI_METHODID_GET_INFO, args, &output);
265
	if (err)
266
		return err;
267
268
	s->id = index;
269
270
	obj = output.pointer;
271
	if (!obj || obj->type != ACPI_TYPE_PACKAGE)
272
		return -EIO;
273
274
	if (obj->package.count != 5)
275
		return 1;
276
277
	name_obj = obj->package.elements[0];
278
279
	if (name_obj.type != ACPI_TYPE_STRING)
280
		return 1;
281
282
	strncpy(s->name, name_obj.string.pointer, sizeof(s->name) - 1);
283
284
	data_type_obj = obj->package.elements[1];
285
286
	if (data_type_obj.type != ACPI_TYPE_INTEGER)
287
		return 1;
288
289
	s->data_type = data_type_obj.integer.value;
290
291
	location_obj = obj->package.elements[2];
292
293
	if (location_obj.type != ACPI_TYPE_INTEGER)
294
		return 1;
295
296
	s->location = location_obj.integer.value;
297
298
	source_obj = obj->package.elements[3];
299
300
	if (source_obj.type != ACPI_TYPE_INTEGER)
301
		return 1;
302
303
	s->source = source_obj.integer.value;
304
305
	type_obj = obj->package.elements[4];
306
307
	if (type_obj.type != ACPI_TYPE_INTEGER)
308
		return 1;
309
310
	s->type = type_obj.integer.value;
311
312
	return 0;
313
}
314
315
static int asus_wmi_update_buffer(u8 source)
316
{
317
	u32 args[] = {source, 0};
318
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
319
320
	return asus_wmi_call_method(ASUSWMI_METHODID_UPDATE_BUFFER, args, &output);
321
}
322
323
static int asus_wmi_get_sensor_value(u8 index, u32 *value)
324
{
325
	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
326
	u32 args[] = {index, 0};
327
	union acpi_object *obj;
328
	int err;
329
330
	err = asus_wmi_call_method(ASUSWMI_METHODID_GET_VALUE, args, &output);
331
	if (err)
332
		return err;
333
334
	obj = output.pointer;
335
	if (!obj || obj->type != ACPI_TYPE_INTEGER)
336
		return -EIO;
337
338
	*value = obj->integer.value;
339
340
	return 0;
341
}
342
343
static void asus_wmi_update_values_for_source(u8 source, struct asus_wmi_sensors *sensor_data)
344
{
345
	int ret = 0;
346
	int value = 0;
347
	int i;
348
	struct asus_wmi_sensor_info *sensor;
349
350
	for (i = 0; i < sensor_data->wmi.sensor_count; i++) {
351
		sensor = sensor_data->wmi.info_by_id[i];
352
		if (sensor && sensor->source == source) {
353
			ret = asus_wmi_get_sensor_value(sensor->id, &value);
354
			if (!ret)
355
				sensor->cached_value = value;
356
		}
357
	}
358
}
359
360
static int asus_wmi_scale_sensor_value(u32 value, int data_type)
361
{
362
	/* FAN_RPM and WATER_FLOW don't need scaling */
363
	switch (data_type) {
364
	case VOLTAGE:
365
		return DIV_ROUND_CLOSEST(value, 1000);
366
	case TEMPERATURE_C:
367
		return value * 1000;
368
	case CURRENT:
369
		return value * 1000;
370
	}
371
	return value;
372
}
373
374
static int asus_wmi_get_cached_value_or_update(const struct asus_wmi_sensor_info *sensor,
375
					       struct asus_wmi_sensors *sensor_data,
376
					       u32 *value)
377
{
378
	int ret;
379
380
	if (time_after(jiffies, sensor_data->wmi.source_last_updated[sensor->source] + HZ)) {
381
		ret = asus_wmi_update_buffer(sensor->source);
382
		if (ret)
383
			return -EIO;
384
385
		sensor_data->wmi.buffer = sensor->source;
386
387
		asus_wmi_update_values_for_source(sensor->source, sensor_data);
388
		sensor_data->wmi.source_last_updated[sensor->source] = jiffies;
389
	}
390
391
	*value = sensor->cached_value;
392
	return 0;
393
}
394
395
/*
396
 * Now follow the functions that implement the hwmon interface
397
 */
398
399
static int asus_wmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
400
			       u32 attr, int channel, long *val)
401
{
402
	int ret;
403
	u32 value = 0;
404
	const struct asus_wmi_sensor_info *sensor;
405
406
	struct asus_wmi_sensors *sensor_data = dev_get_drvdata(dev);
407
408
	sensor = *(sensor_data->wmi.info[type] + channel);
409
410
	mutex_lock(&sensor_data->lock);
411
	ret = asus_wmi_get_cached_value_or_update(sensor, sensor_data, &value);
412
	mutex_unlock(&sensor_data->lock);
413
	if (!ret)
414
		*val = asus_wmi_scale_sensor_value(value, sensor->data_type);
415
416
	return ret;
417
}
418
419
static int asus_wmi_hwmon_read_string(struct device *dev,
420
				      enum hwmon_sensor_types type, u32 attr,
421
				      int channel, const char **str)
422
{
423
	const struct asus_wmi_sensor_info *sensor;
424
	struct asus_wmi_sensors *sensor_data = dev_get_drvdata(dev);
425
426
	sensor = *(sensor_data->wmi.info[type] + channel);
427
	*str = sensor->name;
428
429
	return 0;
430
}
431
432
static umode_t asus_wmi_hwmon_is_visible(const void *drvdata,
433
					 enum hwmon_sensor_types type, u32 attr,
434
					 int channel)
435
{
436
	const struct asus_wmi_sensor_info *sensor;
437
	const struct asus_wmi_sensors *sensor_data = drvdata;
438
439
	sensor = *(sensor_data->wmi.info[type] + channel);
440
	if (sensor && sensor->name)
441
		return 0444;
442
443
	return 0;
444
}
445
446
static const struct hwmon_ops asus_wmi_hwmon_ops = {
447
	.is_visible = asus_wmi_hwmon_is_visible,
448
	.read = asus_wmi_hwmon_read,
449
	.read_string = asus_wmi_hwmon_read_string,
450
};
451
452
static struct hwmon_chip_info asus_wmi_chip_info = {
453
	.ops = &asus_wmi_hwmon_ops,
454
	.info = NULL,
455
};
456
457
static int asus_wmi_configure_sensor_setup(struct platform_device *pdev,
458
					   struct asus_wmi_sensors *sensor_data)
459
{
460
	int err;
461
	int i, idx;
462
	int nr_count[hwmon_max] = {0}, nr_types = 0;
463
	struct device *hwdev;
464
	struct device *dev = &pdev->dev;
465
	struct hwmon_channel_info *asus_wmi_hwmon_chan;
466
	struct asus_wmi_sensor_info *temp_sensor;
467
	enum hwmon_sensor_types type;
468
	const struct hwmon_channel_info **ptr_asus_wmi_ci;
469
	const struct hwmon_chip_info *chip_info;
470
471
	sensor_data->wmi.buffer = -1;
472
	temp_sensor = devm_kcalloc(dev, 1, sizeof(*temp_sensor), GFP_KERNEL);
473
	if (!temp_sensor)
474
		return -ENOMEM;
475
476
	for (i = 0; i < sensor_data->wmi.sensor_count; i++) {
477
		err = asus_wmi_sensor_info(i, temp_sensor);
478
		if (err)
479
			return -EINVAL;
480
481
		switch (temp_sensor->data_type) {
482
		case TEMPERATURE_C:
483
		case VOLTAGE:
484
		case CURRENT:
485
		case FAN_RPM:
486
		case WATER_FLOW:
487
			type = asus_data_types[temp_sensor->data_type];
488
			if (!nr_count[type])
489
				nr_types++;
490
			nr_count[type]++;
491
			break;
492
		}
493
	}
494
495
	if (nr_count[hwmon_temp])
496
		nr_count[hwmon_chip]++, nr_types++;
497
498
	asus_wmi_hwmon_chan = devm_kcalloc(dev, nr_types,
499
					   sizeof(*asus_wmi_hwmon_chan),
500
					   GFP_KERNEL);
501
	if (!asus_wmi_hwmon_chan)
502
		return -ENOMEM;
503
504
	ptr_asus_wmi_ci = devm_kcalloc(dev, nr_types + 1,
505
				       sizeof(*ptr_asus_wmi_ci), GFP_KERNEL);
506
	if (!ptr_asus_wmi_ci)
507
		return -ENOMEM;
508
509
	asus_wmi_chip_info.info = ptr_asus_wmi_ci;
510
	chip_info = &asus_wmi_chip_info;
511
512
	sensor_data->wmi.info_by_id = devm_kcalloc(dev, sensor_data->wmi.sensor_count,
513
						   sizeof(*sensor_data->wmi.info_by_id),
514
						   GFP_KERNEL);
515
516
	if (!sensor_data->wmi.info_by_id)
517
		return -ENOMEM;
518
519
	for (type = 0; type < hwmon_max; type++) {
520
		if (!nr_count[type])
521
			continue;
522
523
		asus_wmi_hwmon_add_chan_info(asus_wmi_hwmon_chan, dev,
524
					     nr_count[type], type,
525
					     hwmon_attributes[type]);
526
		*ptr_asus_wmi_ci++ = asus_wmi_hwmon_chan++;
527
528
		sensor_data->wmi.info[type] = devm_kcalloc(dev,
529
							   nr_count[type],
530
							   sizeof(*sensor_data->wmi.info),
531
							   GFP_KERNEL);
532
		if (!sensor_data->wmi.info[type])
533
			return -ENOMEM;
534
	}
535
536
	for (i = sensor_data->wmi.sensor_count - 1; i >= 0 ; i--) {
537
		temp_sensor = devm_kzalloc(dev, sizeof(*temp_sensor), GFP_KERNEL);
538
		if (!temp_sensor)
539
			return -ENOMEM;
540
541
		err = asus_wmi_sensor_info(i, temp_sensor);
542
		if (err)
543
			continue;
544
545
		switch (temp_sensor->data_type) {
546
		case TEMPERATURE_C:
547
		case VOLTAGE:
548
		case CURRENT:
549
		case FAN_RPM:
550
		case WATER_FLOW:
551
			type = asus_data_types[temp_sensor->data_type];
552
			idx = --nr_count[type];
553
			*(sensor_data->wmi.info[type] + idx) = temp_sensor;
554
			sensor_data->wmi.info_by_id[i] = temp_sensor;
555
			break;
556
		}
557
	}
558
559
	dev_dbg(&pdev->dev, "board has %d sensors",
560
		sensor_data->wmi.sensor_count);
561
562
	hwdev = devm_hwmon_device_register_with_info(dev, KBUILD_MODNAME,
563
						     sensor_data, chip_info, NULL);
564
565
	return PTR_ERR_OR_ZERO(hwdev);
566
}
567
568
static int asus_wmi_probe(struct platform_device *pdev)
569
{
570
	struct asus_wmi_sensors *sensor_data;
571
	struct device *dev = &pdev->dev;
572
	u32 version = 0;
573
574
	sensor_data = devm_kzalloc(dev, sizeof(struct asus_wmi_sensors),
575
				   GFP_KERNEL);
576
	if (!sensor_data)
577
		return -ENOMEM;
578
579
	if (!wmi_has_guid(ASUSWMI_MONITORING_GUID))
580
		return -ENODEV;
581
582
	if (asus_wmi_get_version(&version))
583
		return -ENODEV;
584
585
	if (asus_wmi_get_item_count(&sensor_data->wmi.sensor_count))
586
		return -ENODEV;
587
588
	if (sensor_data->wmi.sensor_count  <= 0 || version < 2) {
589
		dev_info(dev, "version: %u with %d sensors is unsupported\n",
590
			 version, sensor_data->wmi.sensor_count);
591
592
		return -ENODEV;
593
	}
594
595
	mutex_init(&sensor_data->lock);
596
597
	platform_set_drvdata(pdev, sensor_data);
598
599
	return asus_wmi_configure_sensor_setup(pdev,
600
					       sensor_data);
601
}
602
603
static struct platform_driver asus_wmi_sensors_platform_driver = {
604
	.driver = {
605
		.name	= "asus-wmi-sensors",
606
	},
607
	.probe = asus_wmi_probe,
608
};
609
610
static struct platform_device *sensors_pdev;
611
612
static int __init asus_wmi_init(void)
613
{
614
	if (!dmi_check_system(asus_wmi_dmi_table))
615
		return -ENODEV;
616
617
	sensors_pdev = platform_create_bundle(&asus_wmi_sensors_platform_driver,
618
					      asus_wmi_probe,
619
					      NULL, 0,
620
					      NULL, 0);
621
622
	return PTR_ERR_OR_ZERO(sensors_pdev);
623
}
624
module_init(asus_wmi_init);
625
626
static void __exit asus_wmi_exit(void)
627
{
628
	platform_device_unregister(sensors_pdev);
629
	platform_driver_unregister(&asus_wmi_sensors_platform_driver);
630
}
631
module_exit(asus_wmi_exit);
632
633
MODULE_AUTHOR("Ed Brindley <kernel@maidavale.org>");
634
MODULE_DESCRIPTION("Asus WMI Sensors Driver");
635
MODULE_LICENSE("GPL");
(-)a/drivers/hwmon/nct6775.c (+307 lines)
Lines 56-61 Link Here
56
#include <linux/io.h>
56
#include <linux/io.h>
57
#include <linux/nospec.h>
57
#include <linux/nospec.h>
58
#include <linux/wmi.h>
58
#include <linux/wmi.h>
59
#include <linux/i2c.h>
60
#include <linux/delay.h>
59
#include "lm75.h"
61
#include "lm75.h"
60
62
61
#define USE_ALTERNATE
63
#define USE_ALTERNATE
Lines 140-145 struct nct6775_sio_data { Link Here
140
	int ld;
142
	int ld;
141
	enum kinds kind;
143
	enum kinds kind;
142
	enum sensor_access access;
144
	enum sensor_access access;
145
	bool i2c_enabled;
143
146
144
	/* superio_() callbacks  */
147
	/* superio_() callbacks  */
145
	void (*sio_outb)(struct nct6775_sio_data *sio_data, int reg, int val);
148
	void (*sio_outb)(struct nct6775_sio_data *sio_data, int reg, int val);
Lines 1323-1328 struct nct6775_data { Link Here
1323
	u8 fandiv2;
1326
	u8 fandiv2;
1324
	u8 sio_reg_enable;
1327
	u8 sio_reg_enable;
1325
1328
1329
	/* ASUS boards specific i2c connected to nct6775 */
1330
	struct i2c_adapter *i2c_adapter;
1331
1326
	/* nct6775_*() callbacks  */
1332
	/* nct6775_*() callbacks  */
1327
	u16 (*read_value)(struct nct6775_data *data, u16 reg);
1333
	u16 (*read_value)(struct nct6775_data *data, u16 reg);
1328
	int (*write_value)(struct nct6775_data *data, u16 reg, u16 value);
1334
	int (*write_value)(struct nct6775_data *data, u16 reg, u16 value);
Lines 3939-3944 static void add_temp_sensors(struct nct6775_data *data, const u16 *regp, Link Here
3939
	}
3945
	}
3940
}
3946
}
3941
3947
3948
struct i2c_nct6775_adapdata {
3949
	unsigned short smba;
3950
};
3951
3952
/* Nuvoton SMBus address offsets */
3953
#define SMBHSTDAT	(0 + nuvoton_nct6793d_smba)
3954
#define SMBBLKSZ		(1 + nuvoton_nct6793d_smba)
3955
#define SMBHSTCMD	(2 + nuvoton_nct6793d_smba)
3956
//Index field is the Command field on other controllers
3957
#define SMBHSTIDX	(3 + nuvoton_nct6793d_smba)
3958
#define SMBHSTCTL	(4 + nuvoton_nct6793d_smba)
3959
#define SMBHSTADD	(5 + nuvoton_nct6793d_smba)
3960
#define SMBHSTERR	(9 + nuvoton_nct6793d_smba)
3961
#define SMBHSTSTS	(0xE + nuvoton_nct6793d_smba)
3962
3963
/* Command register */
3964
#define NCT6793D_READ_BYTE	0
3965
#define NCT6793D_READ_WORD	1
3966
#define NCT6793D_WRITE_BYTE	8
3967
#define NCT6793D_WRITE_WORD	9
3968
#define NCT6793D_WRITE_BLOCK	10
3969
3970
/* Control register */
3971
#define NCT6793D_MANUAL_START	128
3972
#define NCT6793D_SOFT_RESET	64
3973
3974
/* Error register */
3975
#define NCT6793D_NO_ACK	32
3976
3977
/* Status register */
3978
#define NCT6793D_FIFO_EMPTY	1
3979
#define NCT6793D_MANUAL_ACTIVE	4
3980
3981
/* Other settings */
3982
#define MAX_RETRIES		400
3983
3984
/* Return negative errno on error. */
3985
static s32 nct6775_access(struct i2c_adapter *adap, u16 addr,
3986
			  unsigned short flags, char read_write,
3987
			  u8 command, int size, union i2c_smbus_data *data)
3988
{
3989
	struct i2c_nct6775_adapdata *adapdata = i2c_get_adapdata(adap);
3990
	unsigned short nuvoton_nct6793d_smba = adapdata->smba;
3991
	int i, len, cnt;
3992
	union i2c_smbus_data tmp_data;
3993
	int timeout = 0;
3994
3995
	tmp_data.word = 0;
3996
	cnt = 0;
3997
	len = 0;
3998
3999
	outb_p(NCT6793D_SOFT_RESET, SMBHSTCTL);
4000
4001
	switch (size) {
4002
	case I2C_SMBUS_QUICK:
4003
		outb_p((addr << 1) | read_write,
4004
		       SMBHSTADD);
4005
		break;
4006
	case I2C_SMBUS_BYTE_DATA:
4007
		tmp_data.byte = data->byte;
4008
		outb_p((addr << 1) | read_write,
4009
		       SMBHSTADD);
4010
		outb_p(command, SMBHSTIDX);
4011
		if (read_write == I2C_SMBUS_WRITE) {
4012
			outb_p(tmp_data.byte, SMBHSTDAT);
4013
			outb_p(NCT6793D_WRITE_BYTE, SMBHSTCMD);
4014
		} else {
4015
			outb_p(NCT6793D_READ_BYTE, SMBHSTCMD);
4016
		}
4017
		break;
4018
	case I2C_SMBUS_BYTE:
4019
		outb_p((addr << 1) | read_write,
4020
		       SMBHSTADD);
4021
		outb_p(command, SMBHSTIDX);
4022
		if (read_write == I2C_SMBUS_WRITE) {
4023
			outb_p(tmp_data.byte, SMBHSTDAT);
4024
			outb_p(NCT6793D_WRITE_BYTE, SMBHSTCMD);
4025
		} else {
4026
			outb_p(NCT6793D_READ_BYTE, SMBHSTCMD);
4027
		}
4028
		break;
4029
	case I2C_SMBUS_WORD_DATA:
4030
		outb_p((addr << 1) | read_write,
4031
		       SMBHSTADD);
4032
		outb_p(command, SMBHSTIDX);
4033
		if (read_write == I2C_SMBUS_WRITE) {
4034
			outb_p(data->word & 0xff, SMBHSTDAT);
4035
			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT);
4036
			outb_p(NCT6793D_WRITE_WORD, SMBHSTCMD);
4037
		} else {
4038
			outb_p(NCT6793D_READ_WORD, SMBHSTCMD);
4039
		}
4040
		break;
4041
	case I2C_SMBUS_BLOCK_DATA:
4042
		outb_p((addr << 1) | read_write,
4043
		       SMBHSTADD);
4044
		outb_p(command, SMBHSTIDX);
4045
		if (read_write == I2C_SMBUS_WRITE) {
4046
			len = data->block[0];
4047
4048
			if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
4049
				return -EINVAL;
4050
4051
			outb_p(len, SMBBLKSZ);
4052
4053
			cnt = 1;
4054
			if (len >= 4) {
4055
				for (i = cnt; i <= 4; i++)
4056
					outb_p(data->block[i], SMBHSTDAT);
4057
4058
				len -= 4;
4059
				cnt += 4;
4060
			} else {
4061
				for (i = cnt; i <= len; i++)
4062
					outb_p(data->block[i], SMBHSTDAT);
4063
4064
				len = 0;
4065
			}
4066
4067
			outb_p(NCT6793D_WRITE_BLOCK, SMBHSTCMD);
4068
		} else {
4069
			return -EOPNOTSUPP;
4070
		}
4071
		break;
4072
	default:
4073
		dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
4074
		return -EOPNOTSUPP;
4075
	}
4076
4077
	outb_p(NCT6793D_MANUAL_START, SMBHSTCTL);
4078
4079
	while ((size == I2C_SMBUS_BLOCK_DATA) && (len > 0)) {
4080
		if (read_write == I2C_SMBUS_WRITE) {
4081
			timeout = 0;
4082
4083
			while ((inb_p(SMBHSTSTS) & NCT6793D_FIFO_EMPTY) == 0) {
4084
				if (timeout > MAX_RETRIES)
4085
					return -ETIMEDOUT;
4086
4087
				usleep_range(250, 500);
4088
				timeout++;
4089
			}
4090
4091
			//Load more bytes into FIFO
4092
			if (len >= 4) {
4093
				for (i = cnt; i <= (cnt + 4); i++)
4094
					outb_p(data->block[i], SMBHSTDAT);
4095
4096
				len -= 4;
4097
				cnt += 4;
4098
			} else {
4099
				for (i = cnt; i <= (cnt + len); i++)
4100
					outb_p(data->block[i], SMBHSTDAT);
4101
4102
				len = 0;
4103
			}
4104
		} else {
4105
			return -EOPNOTSUPP;
4106
		}
4107
	}
4108
4109
	//wait for manual mode to complete
4110
	timeout = 0;
4111
	while ((inb_p(SMBHSTSTS) & NCT6793D_MANUAL_ACTIVE) != 0) {
4112
		if (timeout > MAX_RETRIES)
4113
			return -ETIMEDOUT;
4114
4115
		usleep_range(250, 500);
4116
		timeout++;
4117
	}
4118
4119
	if ((inb_p(SMBHSTERR) & NCT6793D_NO_ACK) != 0)
4120
		return -ENXIO;
4121
4122
	if (read_write == I2C_SMBUS_WRITE || size == I2C_SMBUS_QUICK)
4123
		return 0;
4124
4125
	switch (size) {
4126
	case I2C_SMBUS_QUICK:
4127
	case I2C_SMBUS_BYTE_DATA:
4128
		data->byte = inb_p(SMBHSTDAT);
4129
		break;
4130
	case I2C_SMBUS_WORD_DATA:
4131
		data->word = inb_p(SMBHSTDAT) + (inb_p(SMBHSTDAT) << 8);
4132
		break;
4133
	}
4134
	return 0;
4135
}
4136
4137
static u32 nct6775_func(struct i2c_adapter *adapter)
4138
{
4139
	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
4140
	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
4141
	    I2C_FUNC_SMBUS_BLOCK_DATA;
4142
}
4143
4144
static const struct i2c_algorithm smbus_algorithm = {
4145
	.smbus_xfer	= nct6775_access,
4146
	.functionality	= nct6775_func,
4147
};
4148
4149
static int nct6775_add_adapter(unsigned short smba, const char *name, struct i2c_adapter **padap)
4150
{
4151
	struct i2c_adapter *adap;
4152
	struct i2c_nct6775_adapdata *adapdata;
4153
	int retval;
4154
4155
	adap = kzalloc(sizeof(*adap), GFP_KERNEL);
4156
	if (!adap)
4157
		return -ENOMEM;
4158
4159
	adap->owner = THIS_MODULE;
4160
	adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
4161
	adap->algo = &smbus_algorithm;
4162
4163
	adapdata = kzalloc(sizeof(*adapdata), GFP_KERNEL);
4164
	if (!adapdata) {
4165
		kfree(adap);
4166
		return -ENOMEM;
4167
	}
4168
4169
	adapdata->smba = smba;
4170
4171
	snprintf(adap->name, sizeof(adap->name),
4172
		 "SMBus NCT67xx adapter%s at %04x", name, smba);
4173
4174
	i2c_set_adapdata(adap, adapdata);
4175
4176
	retval = i2c_add_adapter(adap);
4177
	if (retval) {
4178
		kfree(adapdata);
4179
		kfree(adap);
4180
		return retval;
4181
	}
4182
4183
	*padap = adap;
4184
	return 0;
4185
}
4186
4187
static void nct6775_remove_adapter(struct i2c_adapter *adap)
4188
{
4189
	struct i2c_nct6775_adapdata *adapdata = i2c_get_adapdata(adap);
4190
4191
	i2c_del_adapter(adap);
4192
	kfree(adapdata);
4193
	kfree(adap);
4194
}
4195
3942
static int nct6775_probe(struct platform_device *pdev)
4196
static int nct6775_probe(struct platform_device *pdev)
3943
{
4197
{
3944
	struct device *dev = &pdev->dev;
4198
	struct device *dev = &pdev->dev;
Lines 3985-3990 static int nct6775_probe(struct platform_device *pdev) Link Here
3985
	data->bank = 0xff;		/* Force initial bank selection */
4239
	data->bank = 0xff;		/* Force initial bank selection */
3986
	platform_set_drvdata(pdev, data);
4240
	platform_set_drvdata(pdev, data);
3987
4241
4242
	if (sio_data->i2c_enabled) {
4243
		switch (sio_data->kind) {
4244
		case nct6791:
4245
		case nct6792:
4246
		case nct6793:
4247
		case nct6795:
4248
		case nct6796:
4249
		case nct6798:
4250
			nct6775_add_adapter(data->addr, "", &data->i2c_adapter);
4251
			break;
4252
		default:
4253
			pr_err("i2c have not found");
4254
		}
4255
	}
4256
3988
	switch (data->kind) {
4257
	switch (data->kind) {
3989
	case nct6106:
4258
	case nct6106:
3990
		data->in_num = 9;
4259
		data->in_num = 9;
Lines 4775-4780 static int nct6775_probe(struct platform_device *pdev) Link Here
4775
	return PTR_ERR_OR_ZERO(hwmon_dev);
5044
	return PTR_ERR_OR_ZERO(hwmon_dev);
4776
}
5045
}
4777
5046
5047
static int nct6775_remove(struct platform_device *pdev)
5048
{
5049
	struct nct6775_data *data = platform_get_drvdata(pdev);
5050
5051
	if (data->i2c_adapter)
5052
		nct6775_remove_adapter(data->i2c_adapter);
5053
5054
	return 0;
5055
}
5056
4778
static void nct6791_enable_io_mapping(struct nct6775_sio_data *sio_data)
5057
static void nct6791_enable_io_mapping(struct nct6775_sio_data *sio_data)
4779
{
5058
{
4780
	int val;
5059
	int val;
Lines 4881-4886 static struct platform_driver nct6775_driver = { Link Here
4881
		.pm	= &nct6775_dev_pm_ops,
5160
		.pm	= &nct6775_dev_pm_ops,
4882
	},
5161
	},
4883
	.probe		= nct6775_probe,
5162
	.probe		= nct6775_probe,
5163
	.remove		= nct6775_remove,
4884
};
5164
};
4885
5165
4886
/* nct6775_find() looks for a '627 in the Super-I/O config space */
5166
/* nct6775_find() looks for a '627 in the Super-I/O config space */
Lines 4985-4990 static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data) Link Here
4985
 */
5265
 */
4986
static struct platform_device *pdev[2];
5266
static struct platform_device *pdev[2];
4987
5267
5268
/* unchecked at all */
5269
static const char * const asus_i2c_boards[] = {
5270
	"PRIME B450M-GAMING",
5271
	"PRIME X370-PRO",
5272
	"PRIME X399-A",
5273
	"PRIME X470-PRO",
5274
	"PRIME Z270-A",
5275
	"PRIME Z370-A",
5276
	"ROG CROSSHAIR VI HERO",
5277
	"ROG STRIX B350-F GAMING",
5278
	"ROG STRIX B450-F GAMING",
5279
	"ROG STRIX X399-E GAMING",
5280
	"ROG STRIX Z270-E",
5281
	"ROG STRIX Z370-E",
5282
	"ROG STRIX Z490-E GAMING",
5283
	"TUF B450 PLUS GAMING",
5284
};
5285
4988
static const char * const asus_wmi_boards[] = {
5286
static const char * const asus_wmi_boards[] = {
4989
	"Pro WS X570-ACE",
5287
	"Pro WS X570-ACE",
4990
	"PRIME B360-PLUS",
5288
	"PRIME B360-PLUS",
Lines 5021-5026 static int __init sensors_nct6775_init(void) Link Here
5021
	struct nct6775_sio_data sio_data;
5319
	struct nct6775_sio_data sio_data;
5022
	int sioaddr[2] = { 0x2e, 0x4e };
5320
	int sioaddr[2] = { 0x2e, 0x4e };
5023
	enum sensor_access access = access_direct;
5321
	enum sensor_access access = access_direct;
5322
	bool i2c_enabled = false;
5024
	const char *board_vendor, *board_name;
5323
	const char *board_vendor, *board_name;
5025
	u8 tmp;
5324
	u8 tmp;
5026
5325
Lines 5044-5049 static int __init sensors_nct6775_init(void) Link Here
5044
				pr_err("Can't read ChipID by Asus WMI.\n");
5343
				pr_err("Can't read ChipID by Asus WMI.\n");
5045
			}
5344
			}
5046
		}
5345
		}
5346
5347
		err = match_string(asus_i2c_boards, ARRAY_SIZE(asus_i2c_boards),
5348
				   board_name);
5349
		if (err >= 0) {
5350
			i2c_enabled = true;
5351
			pr_info("Asus i2c adapter can be enabled nct6775.\n");
5352
		}
5047
	}
5353
	}
5048
5354
5049
	/*
5355
	/*
Lines 5067-5072 static int __init sensors_nct6775_init(void) Link Here
5067
		found = true;
5373
		found = true;
5068
5374
5069
		sio_data.access = access;
5375
		sio_data.access = access;
5376
		sio_data.i2c_enabled = i2c_enabled;
5070
5377
5071
		if (access == access_asuswmi) {
5378
		if (access == access_asuswmi) {
5072
			sio_data.sio_outb = superio_wmi_outb;
5379
			sio_data.sio_outb = superio_wmi_outb;

Return to bug 204807