brintos

brintos / linux-shallow public Read only

0
0
Text · 40.8 KiB · 096f1da Raw
1627 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * nct6775 - Platform driver for the hardware monitoring4 *	     functionality of Nuvoton NCT677x Super-I/O chips5 *6 * Copyright (C) 2012  Guenter Roeck <linux@roeck-us.net>7 */8 9#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt10 11#include <linux/acpi.h>12#include <linux/dmi.h>13#include <linux/hwmon-sysfs.h>14#include <linux/hwmon-vid.h>15#include <linux/init.h>16#include <linux/io.h>17#include <linux/module.h>18#include <linux/platform_device.h>19#include <linux/regmap.h>20 21#include "nct6775.h"22 23enum sensor_access { access_direct, access_asuswmi };24 25static const char * const nct6775_sio_names[] __initconst = {26	[nct6106] = "NCT6106D",27	[nct6116] = "NCT6116D",28	[nct6775] = "NCT6775F",29	[nct6776] = "NCT6776D/F",30	[nct6779] = "NCT6779D",31	[nct6791] = "NCT6791D",32	[nct6792] = "NCT6792D",33	[nct6793] = "NCT6793D",34	[nct6795] = "NCT6795D",35	[nct6796] = "NCT6796D",36	[nct6797] = "NCT6797D",37	[nct6798] = "NCT6798D",38	[nct6799] = "NCT6796D-S/NCT6799D-R",39};40 41static unsigned short force_id;42module_param(force_id, ushort, 0);43MODULE_PARM_DESC(force_id, "Override the detected device ID");44 45static unsigned short fan_debounce;46module_param(fan_debounce, ushort, 0);47MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");48 49#define DRVNAME "nct6775"50 51#define NCT6775_PORT_CHIPID	0x5852 53/*54 * ISA constants55 */56 57#define IOREGION_ALIGNMENT	(~7)58#define IOREGION_OFFSET		559#define IOREGION_LENGTH		260#define ADDR_REG_OFFSET		061#define DATA_REG_OFFSET		162 63/*64 * Super-I/O constants and functions65 */66 67#define NCT6775_LD_ACPI		0x0a68#define NCT6775_LD_HWM		0x0b69#define NCT6775_LD_VID		0x0d70#define NCT6775_LD_12		0x1271 72#define SIO_REG_LDSEL		0x07	/* Logical device select */73#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */74#define SIO_REG_ENABLE		0x30	/* Logical device enable */75#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */76 77#define SIO_NCT6106_ID		0xc45078#define SIO_NCT6116_ID		0xd28079#define SIO_NCT6775_ID		0xb47080#define SIO_NCT6776_ID		0xc33081#define SIO_NCT6779_ID		0xc56082#define SIO_NCT6791_ID		0xc80083#define SIO_NCT6792_ID		0xc91084#define SIO_NCT6793_ID		0xd12085#define SIO_NCT6795_ID		0xd35086#define SIO_NCT6796_ID		0xd42087#define SIO_NCT6797_ID		0xd45088#define SIO_NCT6798_ID		0xd42889#define SIO_NCT6799_ID		0xd80090#define SIO_ID_MASK		0xFFF891 92/*93 * Control registers94 */95#define NCT6775_REG_CR_FAN_DEBOUNCE	0xf096 97struct nct6775_sio_data {98	int sioreg;99	int ld;100	enum kinds kind;101	enum sensor_access access;102 103	/* superio_() callbacks  */104	void (*sio_outb)(struct nct6775_sio_data *sio_data, int reg, int val);105	int (*sio_inb)(struct nct6775_sio_data *sio_data, int reg);106	void (*sio_select)(struct nct6775_sio_data *sio_data, int ld);107	int (*sio_enter)(struct nct6775_sio_data *sio_data);108	void (*sio_exit)(struct nct6775_sio_data *sio_data);109};110 111#define ASUSWMI_METHOD			"WMBD"112#define ASUSWMI_METHODID_RSIO		0x5253494F113#define ASUSWMI_METHODID_WSIO		0x5753494F114#define ASUSWMI_METHODID_RHWM		0x5248574D115#define ASUSWMI_METHODID_WHWM		0x5748574D116#define ASUSWMI_UNSUPPORTED_METHOD	0xFFFFFFFE117#define ASUSWMI_DEVICE_HID		"PNP0C14"118#define ASUSWMI_DEVICE_UID		"ASUSWMI"119#define ASUSMSI_DEVICE_UID		"AsusMbSwInterface"120 121#if IS_ENABLED(CONFIG_ACPI)122/*123 * ASUS boards have only one device with WMI "WMBD" method and have provided124 * access to only one SuperIO chip at 0x0290.125 */126static struct acpi_device *asus_acpi_dev;127#endif128 129static int nct6775_asuswmi_evaluate_method(u32 method_id, u8 bank, u8 reg, u8 val, u32 *retval)130{131#if IS_ENABLED(CONFIG_ACPI)132	acpi_handle handle = acpi_device_handle(asus_acpi_dev);133	u32 args = bank | (reg << 8) | (val << 16);134	struct acpi_object_list input;135	union acpi_object params[3];136	unsigned long long result;137	acpi_status status;138 139	params[0].type = ACPI_TYPE_INTEGER;140	params[0].integer.value = 0;141	params[1].type = ACPI_TYPE_INTEGER;142	params[1].integer.value = method_id;143	params[2].type = ACPI_TYPE_BUFFER;144	params[2].buffer.length = sizeof(args);145	params[2].buffer.pointer = (void *)&args;146	input.count = 3;147	input.pointer = params;148 149	status = acpi_evaluate_integer(handle, ASUSWMI_METHOD, &input, &result);150	if (ACPI_FAILURE(status))151		return -EIO;152 153	if (retval)154		*retval = result;155 156	return 0;157#else158	return -EOPNOTSUPP;159#endif160}161 162static inline int nct6775_asuswmi_write(u8 bank, u8 reg, u8 val)163{164	return nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_WHWM, bank,165					      reg, val, NULL);166}167 168static inline int nct6775_asuswmi_read(u8 bank, u8 reg, u8 *val)169{170	u32 ret, tmp = 0;171 172	ret = nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_RHWM, bank,173					      reg, 0, &tmp);174	*val = tmp;175	return ret;176}177 178static int superio_wmi_inb(struct nct6775_sio_data *sio_data, int reg)179{180	int tmp = 0;181 182	nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_RSIO, sio_data->ld,183					reg, 0, &tmp);184	return tmp;185}186 187static void superio_wmi_outb(struct nct6775_sio_data *sio_data, int reg, int val)188{189	nct6775_asuswmi_evaluate_method(ASUSWMI_METHODID_WSIO, sio_data->ld,190					reg, val, NULL);191}192 193static void superio_wmi_select(struct nct6775_sio_data *sio_data, int ld)194{195	sio_data->ld = ld;196}197 198static int superio_wmi_enter(struct nct6775_sio_data *sio_data)199{200	return 0;201}202 203static void superio_wmi_exit(struct nct6775_sio_data *sio_data)204{205}206 207static void superio_outb(struct nct6775_sio_data *sio_data, int reg, int val)208{209	int ioreg = sio_data->sioreg;210 211	outb(reg, ioreg);212	outb(val, ioreg + 1);213}214 215static int superio_inb(struct nct6775_sio_data *sio_data, int reg)216{217	int ioreg = sio_data->sioreg;218 219	outb(reg, ioreg);220	return inb(ioreg + 1);221}222 223static void superio_select(struct nct6775_sio_data *sio_data, int ld)224{225	int ioreg = sio_data->sioreg;226 227	outb(SIO_REG_LDSEL, ioreg);228	outb(ld, ioreg + 1);229}230 231static int superio_enter(struct nct6775_sio_data *sio_data)232{233	int ioreg = sio_data->sioreg;234 235	/*236	 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.237	 */238	if (!request_muxed_region(ioreg, 2, DRVNAME))239		return -EBUSY;240 241	outb(0x87, ioreg);242	outb(0x87, ioreg);243 244	return 0;245}246 247static void superio_exit(struct nct6775_sio_data *sio_data)248{249	int ioreg = sio_data->sioreg;250 251	outb(0xaa, ioreg);252	outb(0x02, ioreg);253	outb(0x02, ioreg + 1);254	release_region(ioreg, 2);255}256 257static inline void nct6775_wmi_set_bank(struct nct6775_data *data, u16 reg)258{259	u8 bank = reg >> 8;260 261	data->bank = bank;262}263 264static int nct6775_wmi_reg_read(void *ctx, unsigned int reg, unsigned int *val)265{266	struct nct6775_data *data = ctx;267	int err, word_sized = nct6775_reg_is_word_sized(data, reg);268	u8 tmp = 0;269	u16 res;270 271	nct6775_wmi_set_bank(data, reg);272 273	err = nct6775_asuswmi_read(data->bank, reg & 0xff, &tmp);274	if (err)275		return err;276 277	res = tmp;278	if (word_sized) {279		err = nct6775_asuswmi_read(data->bank, (reg & 0xff) + 1, &tmp);280		if (err)281			return err;282 283		res = (res << 8) + tmp;284	}285	*val = res;286	return 0;287}288 289static int nct6775_wmi_reg_write(void *ctx, unsigned int reg, unsigned int value)290{291	struct nct6775_data *data = ctx;292	int res, word_sized = nct6775_reg_is_word_sized(data, reg);293 294	nct6775_wmi_set_bank(data, reg);295 296	if (word_sized) {297		res = nct6775_asuswmi_write(data->bank, reg & 0xff, value >> 8);298		if (res)299			return res;300 301		res = nct6775_asuswmi_write(data->bank, (reg & 0xff) + 1, value);302	} else {303		res = nct6775_asuswmi_write(data->bank, reg & 0xff, value);304	}305 306	return res;307}308 309/*310 * On older chips, only registers 0x50-0x5f are banked.311 * On more recent chips, all registers are banked.312 * Assume that is the case and set the bank number for each access.313 * Cache the bank number so it only needs to be set if it changes.314 */315static inline void nct6775_set_bank(struct nct6775_data *data, u16 reg)316{317	u8 bank = reg >> 8;318 319	if (data->bank != bank) {320		outb_p(NCT6775_REG_BANK, data->addr + ADDR_REG_OFFSET);321		outb_p(bank, data->addr + DATA_REG_OFFSET);322		data->bank = bank;323	}324}325 326static int nct6775_reg_read(void *ctx, unsigned int reg, unsigned int *val)327{328	struct nct6775_data *data = ctx;329	int word_sized = nct6775_reg_is_word_sized(data, reg);330 331	nct6775_set_bank(data, reg);332	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);333	*val = inb_p(data->addr + DATA_REG_OFFSET);334	if (word_sized) {335		outb_p((reg & 0xff) + 1,336		       data->addr + ADDR_REG_OFFSET);337		*val = (*val << 8) + inb_p(data->addr + DATA_REG_OFFSET);338	}339	return 0;340}341 342static int nct6775_reg_write(void *ctx, unsigned int reg, unsigned int value)343{344	struct nct6775_data *data = ctx;345	int word_sized = nct6775_reg_is_word_sized(data, reg);346 347	nct6775_set_bank(data, reg);348	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);349	if (word_sized) {350		outb_p(value >> 8, data->addr + DATA_REG_OFFSET);351		outb_p((reg & 0xff) + 1,352		       data->addr + ADDR_REG_OFFSET);353	}354	outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);355	return 0;356}357 358static void nct6791_enable_io_mapping(struct nct6775_sio_data *sio_data)359{360	int val;361 362	val = sio_data->sio_inb(sio_data, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE);363	if (val & 0x10) {364		pr_info("Enabling hardware monitor logical device mappings.\n");365		sio_data->sio_outb(sio_data, NCT6791_REG_HM_IO_SPACE_LOCK_ENABLE,366			       val & ~0x10);367	}368}369 370static int nct6775_suspend(struct device *dev)371{372	int err;373	u16 tmp;374	struct nct6775_data *data = nct6775_update_device(dev);375 376	if (IS_ERR(data))377		return PTR_ERR(data);378 379	mutex_lock(&data->update_lock);380	err = nct6775_read_value(data, data->REG_VBAT, &tmp);381	if (err)382		goto out;383	data->vbat = tmp;384	if (data->kind == nct6775) {385		err = nct6775_read_value(data, NCT6775_REG_FANDIV1, &tmp);386		if (err)387			goto out;388		data->fandiv1 = tmp;389 390		err = nct6775_read_value(data, NCT6775_REG_FANDIV2, &tmp);391		if (err)392			goto out;393		data->fandiv2 = tmp;394	}395out:396	mutex_unlock(&data->update_lock);397 398	return err;399}400 401static int nct6775_resume(struct device *dev)402{403	struct nct6775_data *data = dev_get_drvdata(dev);404	struct nct6775_sio_data *sio_data = dev_get_platdata(dev);405	int i, j, err = 0;406	u8 reg;407 408	mutex_lock(&data->update_lock);409	data->bank = 0xff;		/* Force initial bank selection */410 411	err = sio_data->sio_enter(sio_data);412	if (err)413		goto abort;414 415	sio_data->sio_select(sio_data, NCT6775_LD_HWM);416	reg = sio_data->sio_inb(sio_data, SIO_REG_ENABLE);417	if (reg != data->sio_reg_enable)418		sio_data->sio_outb(sio_data, SIO_REG_ENABLE, data->sio_reg_enable);419 420	if (data->kind == nct6791 || data->kind == nct6792 ||421	    data->kind == nct6793 || data->kind == nct6795 ||422	    data->kind == nct6796 || data->kind == nct6797 ||423	    data->kind == nct6798 || data->kind == nct6799)424		nct6791_enable_io_mapping(sio_data);425 426	sio_data->sio_exit(sio_data);427 428	/* Restore limits */429	for (i = 0; i < data->in_num; i++) {430		if (!(data->have_in & BIT(i)))431			continue;432 433		err = nct6775_write_value(data, data->REG_IN_MINMAX[0][i], data->in[i][1]);434		if (err)435			goto abort;436		err = nct6775_write_value(data, data->REG_IN_MINMAX[1][i], data->in[i][2]);437		if (err)438			goto abort;439	}440 441	for (i = 0; i < ARRAY_SIZE(data->fan_min); i++) {442		if (!(data->has_fan_min & BIT(i)))443			continue;444 445		err = nct6775_write_value(data, data->REG_FAN_MIN[i], data->fan_min[i]);446		if (err)447			goto abort;448	}449 450	for (i = 0; i < NUM_TEMP; i++) {451		if (!(data->have_temp & BIT(i)))452			continue;453 454		for (j = 1; j < ARRAY_SIZE(data->reg_temp); j++)455			if (data->reg_temp[j][i]) {456				err = nct6775_write_temp(data, data->reg_temp[j][i],457							 data->temp[j][i]);458				if (err)459					goto abort;460			}461	}462 463	/* Restore other settings */464	err = nct6775_write_value(data, data->REG_VBAT, data->vbat);465	if (err)466		goto abort;467	if (data->kind == nct6775) {468		err = nct6775_write_value(data, NCT6775_REG_FANDIV1, data->fandiv1);469		if (err)470			goto abort;471		err = nct6775_write_value(data, NCT6775_REG_FANDIV2, data->fandiv2);472	}473 474abort:475	/* Force re-reading all values */476	data->valid = false;477	mutex_unlock(&data->update_lock);478 479	return err;480}481 482static DEFINE_SIMPLE_DEV_PM_OPS(nct6775_dev_pm_ops, nct6775_suspend, nct6775_resume);483 484static void485nct6775_check_fan_inputs(struct nct6775_data *data, struct nct6775_sio_data *sio_data)486{487	bool fan3pin = false, fan4pin = false, fan4min = false;488	bool fan5pin = false, fan6pin = false, fan7pin = false;489	bool pwm3pin = false, pwm4pin = false, pwm5pin = false;490	bool pwm6pin = false, pwm7pin = false;491 492	/* Store SIO_REG_ENABLE for use during resume */493	sio_data->sio_select(sio_data, NCT6775_LD_HWM);494	data->sio_reg_enable = sio_data->sio_inb(sio_data, SIO_REG_ENABLE);495 496	/* fan4 and fan5 share some pins with the GPIO and serial flash */497	if (data->kind == nct6775) {498		int cr2c = sio_data->sio_inb(sio_data, 0x2c);499 500		fan3pin = cr2c & BIT(6);501		pwm3pin = cr2c & BIT(7);502 503		/* On NCT6775, fan4 shares pins with the fdc interface */504		fan4pin = !(sio_data->sio_inb(sio_data, 0x2A) & 0x80);505	} else if (data->kind == nct6776) {506		bool gpok = sio_data->sio_inb(sio_data, 0x27) & 0x80;507		const char *board_vendor, *board_name;508 509		board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);510		board_name = dmi_get_system_info(DMI_BOARD_NAME);511 512		if (board_name && board_vendor &&513		    !strcmp(board_vendor, "ASRock")) {514			/*515			 * Auxiliary fan monitoring is not enabled on ASRock516			 * Z77 Pro4-M if booted in UEFI Ultra-FastBoot mode.517			 * Observed with BIOS version 2.00.518			 */519			if (!strcmp(board_name, "Z77 Pro4-M")) {520				if ((data->sio_reg_enable & 0xe0) != 0xe0) {521					data->sio_reg_enable |= 0xe0;522					sio_data->sio_outb(sio_data, SIO_REG_ENABLE,523						     data->sio_reg_enable);524				}525			}526		}527 528		if (data->sio_reg_enable & 0x80)529			fan3pin = gpok;530		else531			fan3pin = !(sio_data->sio_inb(sio_data, 0x24) & 0x40);532 533		if (data->sio_reg_enable & 0x40)534			fan4pin = gpok;535		else536			fan4pin = sio_data->sio_inb(sio_data, 0x1C) & 0x01;537 538		if (data->sio_reg_enable & 0x20)539			fan5pin = gpok;540		else541			fan5pin = sio_data->sio_inb(sio_data, 0x1C) & 0x02;542 543		fan4min = fan4pin;544		pwm3pin = fan3pin;545	} else if (data->kind == nct6106) {546		int cr24 = sio_data->sio_inb(sio_data, 0x24);547 548		fan3pin = !(cr24 & 0x80);549		pwm3pin = cr24 & 0x08;550	} else if (data->kind == nct6116) {551		int cr1a = sio_data->sio_inb(sio_data, 0x1a);552		int cr1b = sio_data->sio_inb(sio_data, 0x1b);553		int cr24 = sio_data->sio_inb(sio_data, 0x24);554		int cr2a = sio_data->sio_inb(sio_data, 0x2a);555		int cr2b = sio_data->sio_inb(sio_data, 0x2b);556		int cr2f = sio_data->sio_inb(sio_data, 0x2f);557 558		fan3pin = !(cr2b & 0x10);559		fan4pin = (cr2b & 0x80) ||			// pin 1(2)560			(!(cr2f & 0x10) && (cr1a & 0x04));	// pin 65(66)561		fan5pin = (cr2b & 0x80) ||			// pin 126(127)562			(!(cr1b & 0x03) && (cr2a & 0x02));	// pin 94(96)563 564		pwm3pin = fan3pin && (cr24 & 0x08);565		pwm4pin = fan4pin;566		pwm5pin = fan5pin;567	} else {568		/*569		 * NCT6779D, NCT6791D, NCT6792D, NCT6793D, NCT6795D, NCT6796D,570		 * NCT6797D, NCT6798D, NCT6799D571		 */572		int cr1a = sio_data->sio_inb(sio_data, 0x1a);573		int cr1b = sio_data->sio_inb(sio_data, 0x1b);574		int cr1c = sio_data->sio_inb(sio_data, 0x1c);575		int cr1d = sio_data->sio_inb(sio_data, 0x1d);576		int cr2a = sio_data->sio_inb(sio_data, 0x2a);577		int cr2b = sio_data->sio_inb(sio_data, 0x2b);578		int cr2d = sio_data->sio_inb(sio_data, 0x2d);579		int cr2f = sio_data->sio_inb(sio_data, 0x2f);580		bool vsb_ctl_en = cr2f & BIT(0);581		bool dsw_en = cr2f & BIT(3);582		bool ddr4_en = cr2f & BIT(4);583		bool as_seq1_en = cr2f & BIT(7);584		int cre0;585		int cre6;586		int creb;587		int cred;588 589		cre6 = sio_data->sio_inb(sio_data, 0xe6);590 591		sio_data->sio_select(sio_data, NCT6775_LD_12);592		cre0 = sio_data->sio_inb(sio_data, 0xe0);593		creb = sio_data->sio_inb(sio_data, 0xeb);594		cred = sio_data->sio_inb(sio_data, 0xed);595 596		fan3pin = !(cr1c & BIT(5));597		fan4pin = !(cr1c & BIT(6));598		fan5pin = !(cr1c & BIT(7));599 600		pwm3pin = !(cr1c & BIT(0));601		pwm4pin = !(cr1c & BIT(1));602		pwm5pin = !(cr1c & BIT(2));603 604		switch (data->kind) {605		case nct6791:606			fan6pin = cr2d & BIT(1);607			pwm6pin = cr2d & BIT(0);608			break;609		case nct6792:610			fan6pin = !dsw_en && (cr2d & BIT(1));611			pwm6pin = !dsw_en && (cr2d & BIT(0));612			break;613		case nct6793:614			fan5pin |= cr1b & BIT(5);615			fan5pin |= creb & BIT(5);616 617			fan6pin = !dsw_en && (cr2d & BIT(1));618			fan6pin |= creb & BIT(3);619 620			pwm5pin |= cr2d & BIT(7);621			pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));622 623			pwm6pin = !dsw_en && (cr2d & BIT(0));624			pwm6pin |= creb & BIT(2);625			break;626		case nct6795:627			fan5pin |= cr1b & BIT(5);628			fan5pin |= creb & BIT(5);629 630			fan6pin = (cr2a & BIT(4)) &&631					(!dsw_en || (cred & BIT(4)));632			fan6pin |= creb & BIT(3);633 634			pwm5pin |= cr2d & BIT(7);635			pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));636 637			pwm6pin = (cr2a & BIT(3)) && (cred & BIT(2));638			pwm6pin |= creb & BIT(2);639			break;640		case nct6796:641			fan5pin |= cr1b & BIT(5);642			fan5pin |= (cre0 & BIT(3)) && !(cr1b & BIT(0));643			fan5pin |= creb & BIT(5);644 645			fan6pin = (cr2a & BIT(4)) &&646					(!dsw_en || (cred & BIT(4)));647			fan6pin |= creb & BIT(3);648 649			fan7pin = !(cr2b & BIT(2));650 651			pwm5pin |= cr2d & BIT(7);652			pwm5pin |= (cre0 & BIT(4)) && !(cr1b & BIT(0));653			pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));654 655			pwm6pin = (cr2a & BIT(3)) && (cred & BIT(2));656			pwm6pin |= creb & BIT(2);657 658			pwm7pin = !(cr1d & (BIT(2) | BIT(3)));659			break;660		case nct6797:661			fan5pin |= !ddr4_en && (cr1b & BIT(5));662			fan5pin |= creb & BIT(5);663 664			fan6pin = cr2a & BIT(4);665			fan6pin |= creb & BIT(3);666 667			fan7pin = cr1a & BIT(1);668 669			pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));670			pwm5pin |= !ddr4_en && (cr2d & BIT(7));671 672			pwm6pin = creb & BIT(2);673			pwm6pin |= cred & BIT(2);674 675			pwm7pin = cr1d & BIT(4);676			break;677		case nct6798:678			fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3));679			fan6pin |= cr2a & BIT(4);680			fan6pin |= creb & BIT(5);681 682			fan7pin = cr1b & BIT(5);683			fan7pin |= !(cr2b & BIT(2));684			fan7pin |= creb & BIT(3);685 686			pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4));687			pwm6pin |= !(cred & BIT(2)) && (cr2a & BIT(3));688			pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0));689 690			pwm7pin = !(cr1d & (BIT(2) | BIT(3)));691			pwm7pin |= cr2d & BIT(7);692			pwm7pin |= creb & BIT(2);693			break;694		case nct6799:695			fan4pin = cr1c & BIT(6);696			fan5pin = cr1c & BIT(7);697 698			fan6pin = !(cr1b & BIT(0)) && (cre0 & BIT(3));699			fan6pin |= cre6 & BIT(5);700			fan6pin |= creb & BIT(5);701			fan6pin |= !as_seq1_en && (cr2a & BIT(4));702 703			fan7pin = cr1b & BIT(5);704			fan7pin |= !vsb_ctl_en && !(cr2b & BIT(2));705			fan7pin |= creb & BIT(3);706 707			pwm6pin = !(cr1b & BIT(0)) && (cre0 & BIT(4));708			pwm6pin |= !as_seq1_en && !(cred & BIT(2)) && (cr2a & BIT(3));709			pwm6pin |= (creb & BIT(4)) && !(cr2a & BIT(0));710			pwm6pin |= cre6 & BIT(3);711 712			pwm7pin = !vsb_ctl_en && !(cr1d & (BIT(2) | BIT(3)));713			pwm7pin |= creb & BIT(2);714			pwm7pin |= cr2d & BIT(7);715 716			break;717		default:	/* NCT6779D */718			break;719		}720 721		fan4min = fan4pin;722	}723 724	/* fan 1 and 2 (0x03) are always present */725	data->has_fan = 0x03 | (fan3pin << 2) | (fan4pin << 3) |726		(fan5pin << 4) | (fan6pin << 5) | (fan7pin << 6);727	data->has_fan_min = 0x03 | (fan3pin << 2) | (fan4min << 3) |728		(fan5pin << 4) | (fan6pin << 5) | (fan7pin << 6);729	data->has_pwm = 0x03 | (pwm3pin << 2) | (pwm4pin << 3) |730		(pwm5pin << 4) | (pwm6pin << 5) | (pwm7pin << 6);731}732 733static ssize_t734cpu0_vid_show(struct device *dev, struct device_attribute *attr, char *buf)735{736	struct nct6775_data *data = dev_get_drvdata(dev);737 738	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));739}740 741static DEVICE_ATTR_RO(cpu0_vid);742 743/* Case open detection */744 745static const u8 NCT6775_REG_CR_CASEOPEN_CLR[] = { 0xe6, 0xee };746static const u8 NCT6775_CR_CASEOPEN_CLR_MASK[] = { 0x20, 0x01 };747 748static ssize_t749clear_caseopen(struct device *dev, struct device_attribute *attr,750	       const char *buf, size_t count)751{752	struct nct6775_data *data = dev_get_drvdata(dev);753	struct nct6775_sio_data *sio_data = data->driver_data;754	int nr = to_sensor_dev_attr(attr)->index - INTRUSION_ALARM_BASE;755	unsigned long val;756	u8 reg;757	int ret;758 759	if (kstrtoul(buf, 10, &val) || val != 0)760		return -EINVAL;761 762	mutex_lock(&data->update_lock);763 764	/*765	 * Use CR registers to clear caseopen status.766	 * The CR registers are the same for all chips, and not all chips767	 * support clearing the caseopen status through "regular" registers.768	 */769	ret = sio_data->sio_enter(sio_data);770	if (ret) {771		count = ret;772		goto error;773	}774 775	sio_data->sio_select(sio_data, NCT6775_LD_ACPI);776	reg = sio_data->sio_inb(sio_data, NCT6775_REG_CR_CASEOPEN_CLR[nr]);777	reg |= NCT6775_CR_CASEOPEN_CLR_MASK[nr];778	sio_data->sio_outb(sio_data, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);779	reg &= ~NCT6775_CR_CASEOPEN_CLR_MASK[nr];780	sio_data->sio_outb(sio_data, NCT6775_REG_CR_CASEOPEN_CLR[nr], reg);781	sio_data->sio_exit(sio_data);782 783	data->valid = false;	/* Force cache refresh */784error:785	mutex_unlock(&data->update_lock);786	return count;787}788 789static SENSOR_DEVICE_ATTR(intrusion0_alarm, 0644, nct6775_show_alarm,790			  clear_caseopen, INTRUSION_ALARM_BASE);791static SENSOR_DEVICE_ATTR(intrusion1_alarm, 0644, nct6775_show_alarm,792			  clear_caseopen, INTRUSION_ALARM_BASE + 1);793static SENSOR_DEVICE_ATTR(intrusion0_beep, 0644, nct6775_show_beep,794			  nct6775_store_beep, INTRUSION_ALARM_BASE);795static SENSOR_DEVICE_ATTR(intrusion1_beep, 0644, nct6775_show_beep,796			  nct6775_store_beep, INTRUSION_ALARM_BASE + 1);797static SENSOR_DEVICE_ATTR(beep_enable, 0644, nct6775_show_beep,798			  nct6775_store_beep, BEEP_ENABLE_BASE);799 800static umode_t nct6775_other_is_visible(struct kobject *kobj,801					struct attribute *attr, int index)802{803	struct device *dev = kobj_to_dev(kobj);804	struct nct6775_data *data = dev_get_drvdata(dev);805 806	if (index == 0 && !data->have_vid)807		return 0;808 809	if (index == 1 || index == 2) {810		if (data->ALARM_BITS[INTRUSION_ALARM_BASE + index - 1] < 0)811			return 0;812	}813 814	if (index == 3 || index == 4) {815		if (data->BEEP_BITS[INTRUSION_ALARM_BASE + index - 3] < 0)816			return 0;817	}818 819	return nct6775_attr_mode(data, attr);820}821 822/*823 * nct6775_other_is_visible uses the index into the following array824 * to determine if attributes should be created or not.825 * Any change in order or content must be matched.826 */827static struct attribute *nct6775_attributes_other[] = {828	&dev_attr_cpu0_vid.attr,				/* 0 */829	&sensor_dev_attr_intrusion0_alarm.dev_attr.attr,	/* 1 */830	&sensor_dev_attr_intrusion1_alarm.dev_attr.attr,	/* 2 */831	&sensor_dev_attr_intrusion0_beep.dev_attr.attr,		/* 3 */832	&sensor_dev_attr_intrusion1_beep.dev_attr.attr,		/* 4 */833	&sensor_dev_attr_beep_enable.dev_attr.attr,		/* 5 */834 835	NULL836};837 838static const struct attribute_group nct6775_group_other = {839	.attrs = nct6775_attributes_other,840	.is_visible = nct6775_other_is_visible,841};842 843static int nct6775_platform_probe_init(struct nct6775_data *data)844{845	int err;846	u8 cr2a;847	struct nct6775_sio_data *sio_data = data->driver_data;848 849	err = sio_data->sio_enter(sio_data);850	if (err)851		return err;852 853	cr2a = sio_data->sio_inb(sio_data, 0x2a);854	switch (data->kind) {855	case nct6775:856		data->have_vid = (cr2a & 0x40);857		break;858	case nct6776:859		data->have_vid = (cr2a & 0x60) == 0x40;860		break;861	case nct6106:862	case nct6116:863	case nct6779:864	case nct6791:865	case nct6792:866	case nct6793:867	case nct6795:868	case nct6796:869	case nct6797:870	case nct6798:871	case nct6799:872		break;873	}874 875	/*876	 * Read VID value877	 * We can get the VID input values directly at logical device D 0xe3.878	 */879	if (data->have_vid) {880		sio_data->sio_select(sio_data, NCT6775_LD_VID);881		data->vid = sio_data->sio_inb(sio_data, 0xe3);882		data->vrm = vid_which_vrm();883	}884 885	if (fan_debounce) {886		u8 tmp;887 888		sio_data->sio_select(sio_data, NCT6775_LD_HWM);889		tmp = sio_data->sio_inb(sio_data,890				    NCT6775_REG_CR_FAN_DEBOUNCE);891		switch (data->kind) {892		case nct6106:893		case nct6116:894			tmp |= 0xe0;895			break;896		case nct6775:897			tmp |= 0x1e;898			break;899		case nct6776:900		case nct6779:901			tmp |= 0x3e;902			break;903		case nct6791:904		case nct6792:905		case nct6793:906		case nct6795:907		case nct6796:908		case nct6797:909		case nct6798:910		case nct6799:911			tmp |= 0x7e;912			break;913		}914		sio_data->sio_outb(sio_data, NCT6775_REG_CR_FAN_DEBOUNCE,915			     tmp);916		pr_info("Enabled fan debounce for chip %s\n", data->name);917	}918 919	nct6775_check_fan_inputs(data, sio_data);920 921	sio_data->sio_exit(sio_data);922 923	return nct6775_add_attr_group(data, &nct6775_group_other);924}925 926static const struct regmap_config nct6775_regmap_config = {927	.reg_bits = 16,928	.val_bits = 16,929	.reg_read = nct6775_reg_read,930	.reg_write = nct6775_reg_write,931};932 933static const struct regmap_config nct6775_wmi_regmap_config = {934	.reg_bits = 16,935	.val_bits = 16,936	.reg_read = nct6775_wmi_reg_read,937	.reg_write = nct6775_wmi_reg_write,938};939 940static int nct6775_platform_probe(struct platform_device *pdev)941{942	struct device *dev = &pdev->dev;943	struct nct6775_sio_data *sio_data = dev_get_platdata(dev);944	struct nct6775_data *data;945	struct resource *res;946	const struct regmap_config *regmapcfg;947 948	if (sio_data->access == access_direct) {949		res = platform_get_resource(pdev, IORESOURCE_IO, 0);950		if (!devm_request_region(&pdev->dev, res->start, IOREGION_LENGTH, DRVNAME))951			return -EBUSY;952	}953 954	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);955	if (!data)956		return -ENOMEM;957 958	data->kind = sio_data->kind;959	data->sioreg = sio_data->sioreg;960 961	if (sio_data->access == access_direct) {962		data->addr = res->start;963		regmapcfg = &nct6775_regmap_config;964	} else {965		regmapcfg = &nct6775_wmi_regmap_config;966	}967 968	platform_set_drvdata(pdev, data);969 970	data->driver_data = sio_data;971	data->driver_init = nct6775_platform_probe_init;972 973	return nct6775_probe(&pdev->dev, data, regmapcfg);974}975 976static struct platform_driver nct6775_driver = {977	.driver = {978		.name	= DRVNAME,979		.pm	= pm_sleep_ptr(&nct6775_dev_pm_ops),980	},981	.probe		= nct6775_platform_probe,982};983 984/* nct6775_find() looks for a '627 in the Super-I/O config space */985static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)986{987	u16 val;988	int err;989	int addr;990 991	sio_data->access = access_direct;992	sio_data->sioreg = sioaddr;993 994	err = sio_data->sio_enter(sio_data);995	if (err)996		return err;997 998	val = (sio_data->sio_inb(sio_data, SIO_REG_DEVID) << 8) |999		sio_data->sio_inb(sio_data, SIO_REG_DEVID + 1);1000	if (force_id && val != 0xffff)1001		val = force_id;1002 1003	switch (val & SIO_ID_MASK) {1004	case SIO_NCT6106_ID:1005		sio_data->kind = nct6106;1006		break;1007	case SIO_NCT6116_ID:1008		sio_data->kind = nct6116;1009		break;1010	case SIO_NCT6775_ID:1011		sio_data->kind = nct6775;1012		break;1013	case SIO_NCT6776_ID:1014		sio_data->kind = nct6776;1015		break;1016	case SIO_NCT6779_ID:1017		sio_data->kind = nct6779;1018		break;1019	case SIO_NCT6791_ID:1020		sio_data->kind = nct6791;1021		break;1022	case SIO_NCT6792_ID:1023		sio_data->kind = nct6792;1024		break;1025	case SIO_NCT6793_ID:1026		sio_data->kind = nct6793;1027		break;1028	case SIO_NCT6795_ID:1029		sio_data->kind = nct6795;1030		break;1031	case SIO_NCT6796_ID:1032		sio_data->kind = nct6796;1033		break;1034	case SIO_NCT6797_ID:1035		sio_data->kind = nct6797;1036		break;1037	case SIO_NCT6798_ID:1038		sio_data->kind = nct6798;1039		break;1040	case SIO_NCT6799_ID:1041		sio_data->kind = nct6799;1042		break;1043	default:1044		if (val != 0xffff)1045			pr_debug("unsupported chip ID: 0x%04x\n", val);1046		sio_data->sio_exit(sio_data);1047		return -ENODEV;1048	}1049 1050	/* We have a known chip, find the HWM I/O address */1051	sio_data->sio_select(sio_data, NCT6775_LD_HWM);1052	val = (sio_data->sio_inb(sio_data, SIO_REG_ADDR) << 8)1053	    | sio_data->sio_inb(sio_data, SIO_REG_ADDR + 1);1054	addr = val & IOREGION_ALIGNMENT;1055	if (addr == 0) {1056		pr_err("Refusing to enable a Super-I/O device with a base I/O port 0\n");1057		sio_data->sio_exit(sio_data);1058		return -ENODEV;1059	}1060 1061	/* Activate logical device if needed */1062	val = sio_data->sio_inb(sio_data, SIO_REG_ENABLE);1063	if (!(val & 0x01)) {1064		pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");1065		sio_data->sio_outb(sio_data, SIO_REG_ENABLE, val | 0x01);1066	}1067 1068	if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||1069	    sio_data->kind == nct6793 || sio_data->kind == nct6795 ||1070	    sio_data->kind == nct6796 || sio_data->kind == nct6797 ||1071	    sio_data->kind == nct6798 || sio_data->kind == nct6799)1072		nct6791_enable_io_mapping(sio_data);1073 1074	sio_data->sio_exit(sio_data);1075	pr_info("Found %s or compatible chip at %#x:%#x\n",1076		nct6775_sio_names[sio_data->kind], sioaddr, addr);1077 1078	return addr;1079}1080 1081/*1082 * when Super-I/O functions move to a separate file, the Super-I/O1083 * bus will manage the lifetime of the device and this module will only keep1084 * track of the nct6775 driver. But since we use platform_device_alloc(), we1085 * must keep track of the device1086 */1087static struct platform_device *pdev[2];1088 1089static const char * const asus_wmi_boards[] = {1090	"B360M-BASALT",1091	"B360M-D3H",1092	"EX-B360M-V",1093	"EX-B360M-V3",1094	"EX-B360M-V5",1095	"EX-B460M-V5",1096	"EX-H410M-V3",1097	"PRIME A520M-A",1098	"PRIME A520M-A II",1099	"PRIME A520M-E",1100	"PRIME A520M-K",1101	"PRIME B360-PLUS",1102	"PRIME B360M-A",1103	"PRIME B360M-C",1104	"PRIME B360M-D",1105	"PRIME B360M-K",1106	"PRIME B460-PLUS",1107	"PRIME B460I-PLUS",1108	"PRIME B460M-A",1109	"PRIME B460M-A R2.0",1110	"PRIME B460M-K",1111	"PRIME B550-PLUS",1112	"PRIME B550-PLUS AC-HES",1113	"PRIME B550M-A",1114	"PRIME B550M-A (WI-FI)",1115	"PRIME B550M-A AC",1116	"PRIME B550M-A WIFI II",1117	"PRIME B550M-K",1118	"PRIME H310-PLUS",1119	"PRIME H310I-PLUS",1120	"PRIME H310M-A",1121	"PRIME H310M-C",1122	"PRIME H310M-D",1123	"PRIME H310M-DASH",1124	"PRIME H310M-E",1125	"PRIME H310M-E/BR",1126	"PRIME H310M-F",1127	"PRIME H310M-K",1128	"PRIME H310T",1129	"PRIME H370-A",1130	"PRIME H370-PLUS",1131	"PRIME H370M-PLUS",1132	"PRIME H410I-PLUS",1133	"PRIME H410M-A",1134	"PRIME H410M-D",1135	"PRIME H410M-E",1136	"PRIME H410M-F",1137	"PRIME H410M-K",1138	"PRIME H410M-K R2.0",1139	"PRIME H410M-R",1140	"PRIME H470-PLUS",1141	"PRIME H470M-PLUS",1142	"PRIME H510M-K R2.0",1143	"PRIME Q370M-C",1144	"PRIME X570-P",1145	"PRIME X570-PRO",1146	"PRIME Z390-A",1147	"PRIME Z390-A/H10",1148	"PRIME Z390-P",1149	"PRIME Z390M-PLUS",1150	"PRIME Z490-A",1151	"PRIME Z490-P",1152	"PRIME Z490-V",1153	"PRIME Z490M-PLUS",1154	"PRO B460M-C",1155	"PRO H410M-C",1156	"PRO H410T",1157	"PRO Q470M-C",1158	"Pro A520M-C",1159	"Pro A520M-C II",1160	"Pro B550M-C",1161	"Pro WS X570-ACE",1162	"ProArt B550-CREATOR",1163	"ProArt X570-CREATOR WIFI",1164	"ProArt Z490-CREATOR 10G",1165	"ROG CROSSHAIR VIII DARK HERO",1166	"ROG CROSSHAIR VIII EXTREME",1167	"ROG CROSSHAIR VIII FORMULA",1168	"ROG CROSSHAIR VIII HERO",1169	"ROG CROSSHAIR VIII HERO (WI-FI)",1170	"ROG CROSSHAIR VIII IMPACT",1171	"ROG MAXIMUS XI APEX",1172	"ROG MAXIMUS XI CODE",1173	"ROG MAXIMUS XI EXTREME",1174	"ROG MAXIMUS XI FORMULA",1175	"ROG MAXIMUS XI GENE",1176	"ROG MAXIMUS XI HERO",1177	"ROG MAXIMUS XI HERO (WI-FI)",1178	"ROG MAXIMUS XII APEX",1179	"ROG MAXIMUS XII EXTREME",1180	"ROG MAXIMUS XII FORMULA",1181	"ROG MAXIMUS XII HERO (WI-FI)",1182	"ROG STRIX B360-F GAMING",1183	"ROG STRIX B360-G GAMING",1184	"ROG STRIX B360-H GAMING",1185	"ROG STRIX B360-H GAMING/OPTANE",1186	"ROG STRIX B360-I GAMING",1187	"ROG STRIX B460-F GAMING",1188	"ROG STRIX B460-G GAMING",1189	"ROG STRIX B460-H GAMING",1190	"ROG STRIX B460-I GAMING",1191	"ROG STRIX B550-A GAMING",1192	"ROG STRIX B550-E GAMING",1193	"ROG STRIX B550-F GAMING",1194	"ROG STRIX B550-F GAMING (WI-FI)",1195	"ROG STRIX B550-F GAMING WIFI II",1196	"ROG STRIX B550-I GAMING",1197	"ROG STRIX B550-XE GAMING WIFI",1198	"ROG STRIX H370-F GAMING",1199	"ROG STRIX H370-I GAMING",1200	"ROG STRIX H470-I GAMING",1201	"ROG STRIX X570-E GAMING",1202	"ROG STRIX X570-E GAMING WIFI II",1203	"ROG STRIX X570-F GAMING",1204	"ROG STRIX X570-I GAMING",1205	"ROG STRIX Z390-E GAMING",1206	"ROG STRIX Z390-F GAMING",1207	"ROG STRIX Z390-H GAMING",1208	"ROG STRIX Z390-I GAMING",1209	"ROG STRIX Z490-A GAMING",1210	"ROG STRIX Z490-E GAMING",1211	"ROG STRIX Z490-F GAMING",1212	"ROG STRIX Z490-G GAMING",1213	"ROG STRIX Z490-G GAMING (WI-FI)",1214	"ROG STRIX Z490-H GAMING",1215	"ROG STRIX Z490-I GAMING",1216	"TUF B360-PLUS GAMING",1217	"TUF B360-PRO GAMING",1218	"TUF B360-PRO GAMING (WI-FI)",1219	"TUF B360M-E GAMING",1220	"TUF B360M-PLUS GAMING",1221	"TUF B360M-PLUS GAMING S",1222	"TUF B360M-PLUS GAMING/BR",1223	"TUF GAMING A520M-PLUS",1224	"TUF GAMING A520M-PLUS II",1225	"TUF GAMING A520M-PLUS WIFI",1226	"TUF GAMING B460-PLUS",1227	"TUF GAMING B460-PRO (WI-FI)",1228	"TUF GAMING B460M-PLUS",1229	"TUF GAMING B460M-PLUS (WI-FI)",1230	"TUF GAMING B460M-PRO",1231	"TUF GAMING B550-PLUS",1232	"TUF GAMING B550-PLUS (WI-FI)",1233	"TUF GAMING B550-PLUS WIFI II",1234	"TUF GAMING B550-PRO",1235	"TUF GAMING B550M ZAKU (WI-FI)",1236	"TUF GAMING B550M-E",1237	"TUF GAMING B550M-E WIFI",1238	"TUF GAMING B550M-PLUS",1239	"TUF GAMING B550M-PLUS (WI-FI)",1240	"TUF GAMING B550M-PLUS WIFI II",1241	"TUF GAMING H470-PRO",1242	"TUF GAMING H470-PRO (WI-FI)",1243	"TUF GAMING X570-PLUS",1244	"TUF GAMING X570-PLUS (WI-FI)",1245	"TUF GAMING X570-PLUS_BR",1246	"TUF GAMING X570-PRO (WI-FI)",1247	"TUF GAMING X570-PRO WIFI II",1248	"TUF GAMING Z490-PLUS",1249	"TUF GAMING Z490-PLUS (WI-FI)",1250	"TUF H310-PLUS GAMING",1251	"TUF H310M-PLUS GAMING",1252	"TUF H310M-PLUS GAMING/BR",1253	"TUF H370-PRO GAMING",1254	"TUF H370-PRO GAMING (WI-FI)",1255	"TUF Z390-PLUS GAMING",1256	"TUF Z390-PLUS GAMING (WI-FI)",1257	"TUF Z390-PRO GAMING",1258	"TUF Z390M-PRO GAMING",1259	"TUF Z390M-PRO GAMING (WI-FI)",1260	"WS Z390 PRO",1261	"Z490-GUNDAM (WI-FI)",1262};1263 1264static const char * const asus_msi_boards[] = {1265	"B560M-P",1266	"EX-B560M-V5",1267	"EX-B660M-V5 D4",1268	"EX-B660M-V5 PRO D4",1269	"EX-B760M-V5 D4",1270	"EX-H510M-V3",1271	"EX-H610M-V3 D4",1272	"G15CF",1273	"PRIME A620M-A",1274	"PRIME B560-PLUS",1275	"PRIME B560-PLUS AC-HES",1276	"PRIME B560M-A",1277	"PRIME B560M-A AC",1278	"PRIME B560M-K",1279	"PRIME B650-PLUS",1280	"PRIME B650M-A",1281	"PRIME B650M-A AX",1282	"PRIME B650M-A AX II",1283	"PRIME B650M-A II",1284	"PRIME B650M-A WIFI",1285	"PRIME B650M-A WIFI II",1286	"PRIME B660-PLUS D4",1287	"PRIME B660M-A AC D4",1288	"PRIME B660M-A D4",1289	"PRIME B660M-A WIFI D4",1290	"PRIME B760-PLUS",1291	"PRIME B760-PLUS D4",1292	"PRIME B760M-A",1293	"PRIME B760M-A AX D4",1294	"PRIME B760M-A D4",1295	"PRIME B760M-A WIFI",1296	"PRIME B760M-A WIFI D4",1297	"PRIME B760M-AJ D4",1298	"PRIME B760M-K D4",1299	"PRIME H510M-A",1300	"PRIME H510M-A WIFI",1301	"PRIME H510M-D",1302	"PRIME H510M-E",1303	"PRIME H510M-F",1304	"PRIME H510M-K",1305	"PRIME H510M-R",1306	"PRIME H510T2/CSM",1307	"PRIME H570-PLUS",1308	"PRIME H570M-PLUS",1309	"PRIME H610I-PLUS D4",1310	"PRIME H610M-A D4",1311	"PRIME H610M-A WIFI D4",1312	"PRIME H610M-D D4",1313	"PRIME H610M-E D4",1314	"PRIME H610M-F D4",1315	"PRIME H610M-K D4",1316	"PRIME H610M-R D4",1317	"PRIME H670-PLUS D4",1318	"PRIME H770-PLUS D4",1319	"PRIME X670-P",1320	"PRIME X670-P WIFI",1321	"PRIME X670E-PRO WIFI",1322	"PRIME Z590-A",1323	"PRIME Z590-P",1324	"PRIME Z590-P WIFI",1325	"PRIME Z590-V",1326	"PRIME Z590M-PLUS",1327	"PRIME Z690-A",1328	"PRIME Z690-P",1329	"PRIME Z690-P D4",1330	"PRIME Z690-P WIFI",1331	"PRIME Z690-P WIFI D4",1332	"PRIME Z690M-PLUS D4",1333	"PRIME Z790-A WIFI",1334	"PRIME Z790-P",1335	"PRIME Z790-P D4",1336	"PRIME Z790-P WIFI",1337	"PRIME Z790-P WIFI D4",1338	"PRIME Z790M-PLUS",1339	"PRIME Z790M-PLUS D4",1340	"Pro B560M-C",1341	"Pro B560M-CT",1342	"Pro B660M-C",1343	"Pro B660M-C D4",1344	"Pro B760M-C",1345	"Pro B760M-CT",1346	"Pro H510M-C",1347	"Pro H510M-CT",1348	"Pro H610M-C",1349	"Pro H610M-C D4",1350	"Pro H610M-CT D4",1351	"Pro H610T D4",1352	"Pro Q670M-C",1353	"Pro WS W680-ACE",1354	"Pro WS W680-ACE IPMI",1355	"Pro WS W790-ACE",1356	"Pro WS W790E-SAGE SE",1357	"ProArt B650-CREATOR",1358	"ProArt B660-CREATOR D4",1359	"ProArt B760-CREATOR D4",1360	"ProArt X670E-CREATOR WIFI",1361	"ProArt Z690-CREATOR WIFI",1362	"ProArt Z790-CREATOR WIFI",1363	"ROG CROSSHAIR X670E EXTREME",1364	"ROG CROSSHAIR X670E GENE",1365	"ROG CROSSHAIR X670E HERO",1366	"ROG MAXIMUS XIII APEX",1367	"ROG MAXIMUS XIII EXTREME",1368	"ROG MAXIMUS XIII EXTREME GLACIAL",1369	"ROG MAXIMUS XIII HERO",1370	"ROG MAXIMUS Z690 APEX",1371	"ROG MAXIMUS Z690 EXTREME",1372	"ROG MAXIMUS Z690 EXTREME GLACIAL",1373	"ROG MAXIMUS Z690 FORMULA",1374	"ROG MAXIMUS Z690 HERO",1375	"ROG MAXIMUS Z690 HERO EVA",1376	"ROG MAXIMUS Z790 APEX",1377	"ROG MAXIMUS Z790 EXTREME",1378	"ROG MAXIMUS Z790 HERO",1379	"ROG STRIX B560-A GAMING WIFI",1380	"ROG STRIX B560-E GAMING WIFI",1381	"ROG STRIX B560-F GAMING WIFI",1382	"ROG STRIX B560-G GAMING WIFI",1383	"ROG STRIX B560-I GAMING WIFI",1384	"ROG STRIX B650-A GAMING WIFI",1385	"ROG STRIX B650E-E GAMING WIFI",1386	"ROG STRIX B650E-F GAMING WIFI",1387	"ROG STRIX B650E-I GAMING WIFI",1388	"ROG STRIX B660-A GAMING WIFI",1389	"ROG STRIX B660-A GAMING WIFI D4",1390	"ROG STRIX B660-F GAMING WIFI",1391	"ROG STRIX B660-G GAMING WIFI",1392	"ROG STRIX B660-I GAMING WIFI",1393	"ROG STRIX B760-A GAMING WIFI",1394	"ROG STRIX B760-A GAMING WIFI D4",1395	"ROG STRIX B760-F GAMING WIFI",1396	"ROG STRIX B760-G GAMING WIFI",1397	"ROG STRIX B760-G GAMING WIFI D4",1398	"ROG STRIX B760-I GAMING WIFI",1399	"ROG STRIX X670E-A GAMING WIFI",1400	"ROG STRIX X670E-E GAMING WIFI",1401	"ROG STRIX X670E-F GAMING WIFI",1402	"ROG STRIX X670E-I GAMING WIFI",1403	"ROG STRIX Z590-A GAMING WIFI",1404	"ROG STRIX Z590-A GAMING WIFI II",1405	"ROG STRIX Z590-E GAMING WIFI",1406	"ROG STRIX Z590-F GAMING WIFI",1407	"ROG STRIX Z590-I GAMING WIFI",1408	"ROG STRIX Z690-A GAMING WIFI",1409	"ROG STRIX Z690-A GAMING WIFI D4",1410	"ROG STRIX Z690-E GAMING WIFI",1411	"ROG STRIX Z690-F GAMING WIFI",1412	"ROG STRIX Z690-G GAMING WIFI",1413	"ROG STRIX Z690-I GAMING WIFI",1414	"ROG STRIX Z790-A GAMING WIFI",1415	"ROG STRIX Z790-A GAMING WIFI D4",1416	"ROG STRIX Z790-E GAMING WIFI",1417	"ROG STRIX Z790-F GAMING WIFI",1418	"ROG STRIX Z790-H GAMING WIFI",1419	"ROG STRIX Z790-I GAMING WIFI",1420	"TUF GAMING A620M-PLUS",1421	"TUF GAMING A620M-PLUS WIFI",1422	"TUF GAMING B560-PLUS WIFI",1423	"TUF GAMING B560M-E",1424	"TUF GAMING B560M-PLUS",1425	"TUF GAMING B560M-PLUS WIFI",1426	"TUF GAMING B650-PLUS",1427	"TUF GAMING B650-PLUS WIFI",1428	"TUF GAMING B650M-PLUS",1429	"TUF GAMING B650M-PLUS WIFI",1430	"TUF GAMING B660-PLUS WIFI D4",1431	"TUF GAMING B660M-E D4",1432	"TUF GAMING B660M-PLUS D4",1433	"TUF GAMING B660M-PLUS WIFI",1434	"TUF GAMING B660M-PLUS WIFI D4",1435	"TUF GAMING B760-PLUS WIFI",1436	"TUF GAMING B760-PLUS WIFI D4",1437	"TUF GAMING B760M-BTF WIFI D4",1438	"TUF GAMING B760M-E D4",1439	"TUF GAMING B760M-PLUS",1440	"TUF GAMING B760M-PLUS D4",1441	"TUF GAMING B760M-PLUS WIFI",1442	"TUF GAMING B760M-PLUS WIFI D4",1443	"TUF GAMING H570-PRO",1444	"TUF GAMING H570-PRO WIFI",1445	"TUF GAMING H670-PRO WIFI D4",1446	"TUF GAMING H770-PRO WIFI",1447	"TUF GAMING X670E-PLUS",1448	"TUF GAMING X670E-PLUS WIFI",1449	"TUF GAMING Z590-PLUS",1450	"TUF GAMING Z590-PLUS WIFI",1451	"TUF GAMING Z690-PLUS",1452	"TUF GAMING Z690-PLUS D4",1453	"TUF GAMING Z690-PLUS WIFI",1454	"TUF GAMING Z690-PLUS WIFI D4",1455	"TUF GAMING Z790-PLUS D4",1456	"TUF GAMING Z790-PLUS WIFI",1457	"TUF GAMING Z790-PLUS WIFI D4",1458	"Z590 WIFI GUNDAM EDITION",1459};1460 1461#if IS_ENABLED(CONFIG_ACPI)1462/*1463 * Callback for acpi_bus_for_each_dev() to find the right device1464 * by _UID and _HID and return 1 to stop iteration.1465 */1466static int nct6775_asuswmi_device_match(struct device *dev, void *data)1467{1468	struct acpi_device *adev = to_acpi_device(dev);1469 1470	if (acpi_dev_hid_uid_match(adev, ASUSWMI_DEVICE_HID, data)) {1471		asus_acpi_dev = adev;1472		return 1;1473	}1474 1475	return 0;1476}1477#endif1478 1479static enum sensor_access nct6775_determine_access(const char *device_uid)1480{1481#if IS_ENABLED(CONFIG_ACPI)1482	u8 tmp;1483 1484	acpi_bus_for_each_dev(nct6775_asuswmi_device_match, (void *)device_uid);1485	if (!asus_acpi_dev)1486		return access_direct;1487 1488	/* if reading chip id via ACPI succeeds, use WMI "WMBD" method for access */1489	if (!nct6775_asuswmi_read(0, NCT6775_PORT_CHIPID, &tmp) && tmp) {1490		pr_debug("Using Asus WMBD method of %s to access %#x chip.\n", device_uid, tmp);1491		return access_asuswmi;1492	}1493#endif1494 1495	return access_direct;1496}1497 1498static int __init sensors_nct6775_platform_init(void)1499{1500	int i, err;1501	bool found = false;1502	int address;1503	struct resource res;1504	struct nct6775_sio_data sio_data;1505	int sioaddr[2] = { 0x2e, 0x4e };1506	enum sensor_access access = access_direct;1507	const char *board_vendor, *board_name;1508 1509	err = platform_driver_register(&nct6775_driver);1510	if (err)1511		return err;1512 1513	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);1514	board_name = dmi_get_system_info(DMI_BOARD_NAME);1515 1516	if (board_name && board_vendor &&1517	    !strcmp(board_vendor, "ASUSTeK COMPUTER INC.")) {1518		err = match_string(asus_wmi_boards, ARRAY_SIZE(asus_wmi_boards),1519				   board_name);1520		if (err >= 0)1521			access = nct6775_determine_access(ASUSWMI_DEVICE_UID);1522 1523		err = match_string(asus_msi_boards, ARRAY_SIZE(asus_msi_boards),1524				   board_name);1525		if (err >= 0)1526			access = nct6775_determine_access(ASUSMSI_DEVICE_UID);1527	}1528 1529	/*1530	 * initialize sio_data->kind and sio_data->sioreg.1531	 *1532	 * when Super-I/O functions move to a separate file, the Super-I/O1533	 * driver will probe 0x2e and 0x4e and auto-detect the presence of a1534	 * nct6775 hardware monitor, and call probe()1535	 */1536	for (i = 0; i < ARRAY_SIZE(pdev); i++) {1537		sio_data.sio_outb = superio_outb;1538		sio_data.sio_inb = superio_inb;1539		sio_data.sio_select = superio_select;1540		sio_data.sio_enter = superio_enter;1541		sio_data.sio_exit = superio_exit;1542 1543		address = nct6775_find(sioaddr[i], &sio_data);1544		if (address <= 0)1545			continue;1546 1547		found = true;1548 1549		sio_data.access = access;1550 1551		if (access == access_asuswmi) {1552			sio_data.sio_outb = superio_wmi_outb;1553			sio_data.sio_inb = superio_wmi_inb;1554			sio_data.sio_select = superio_wmi_select;1555			sio_data.sio_enter = superio_wmi_enter;1556			sio_data.sio_exit = superio_wmi_exit;1557		}1558 1559		pdev[i] = platform_device_alloc(DRVNAME, address);1560		if (!pdev[i]) {1561			err = -ENOMEM;1562			goto exit_device_unregister;1563		}1564 1565		err = platform_device_add_data(pdev[i], &sio_data,1566					       sizeof(struct nct6775_sio_data));1567		if (err)1568			goto exit_device_put;1569 1570		if (sio_data.access == access_direct) {1571			memset(&res, 0, sizeof(res));1572			res.name = DRVNAME;1573			res.start = address + IOREGION_OFFSET;1574			res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;1575			res.flags = IORESOURCE_IO;1576 1577			err = acpi_check_resource_conflict(&res);1578			if (err) {1579				platform_device_put(pdev[i]);1580				pdev[i] = NULL;1581				continue;1582			}1583 1584			err = platform_device_add_resources(pdev[i], &res, 1);1585			if (err)1586				goto exit_device_put;1587		}1588 1589		/* platform_device_add calls probe() */1590		err = platform_device_add(pdev[i]);1591		if (err)1592			goto exit_device_put;1593	}1594	if (!found) {1595		err = -ENODEV;1596		goto exit_unregister;1597	}1598 1599	return 0;1600 1601exit_device_put:1602	platform_device_put(pdev[i]);1603exit_device_unregister:1604	while (i--)1605		platform_device_unregister(pdev[i]);1606exit_unregister:1607	platform_driver_unregister(&nct6775_driver);1608	return err;1609}1610 1611static void __exit sensors_nct6775_platform_exit(void)1612{1613	int i;1614 1615	for (i = 0; i < ARRAY_SIZE(pdev); i++)1616		platform_device_unregister(pdev[i]);1617	platform_driver_unregister(&nct6775_driver);1618}1619 1620MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");1621MODULE_DESCRIPTION("Platform driver for NCT6775F and compatible chips");1622MODULE_LICENSE("GPL");1623MODULE_IMPORT_NS(HWMON_NCT6775);1624 1625module_init(sensors_nct6775_platform_init);1626module_exit(sensors_nct6775_platform_exit);1627