brintos

brintos / linux-shallow public Read only

0
0
Text · 37.3 KiB · f71615e Raw
1517 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * nct6683 - Driver for the hardware monitoring functionality of4 *	     Nuvoton NCT6683D/NCT6686D/NCT6687D eSIO5 *6 * Copyright (C) 2013  Guenter Roeck <linux@roeck-us.net>7 *8 * Derived from nct6775 driver9 * Copyright (C) 2012, 2013  Guenter Roeck <linux@roeck-us.net>10 *11 * Supports the following chips:12 *13 * Chip        #vin    #fan    #pwm    #temp  chip ID14 * nct6683d     21(1)   16      8       32(1) 0xc73015 * nct6686d     21(1)   16      8       32(1) 0xd44016 * nct6687d     21(1)   16      8       32(1) 0xd59017 *18 * Notes:19 *	(1) Total number of vin and temp inputs is 32.20 */21 22#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt23 24#include <linux/acpi.h>25#include <linux/delay.h>26#include <linux/err.h>27#include <linux/init.h>28#include <linux/io.h>29#include <linux/jiffies.h>30#include <linux/hwmon.h>31#include <linux/hwmon-sysfs.h>32#include <linux/module.h>33#include <linux/mutex.h>34#include <linux/platform_device.h>35#include <linux/slab.h>36 37enum kinds { nct6683, nct6686, nct6687 };38 39static bool force;40module_param(force, bool, 0);41MODULE_PARM_DESC(force, "Set to one to enable support for unknown vendors");42 43static const char * const nct6683_device_names[] = {44	"nct6683",45	"nct6686",46	"nct6687",47};48 49static const char * const nct6683_chip_names[] = {50	"NCT6683D",51	"NCT6686D",52	"NCT6687D",53};54 55#define DRVNAME "nct6683"56 57/*58 * Super-I/O constants and functions59 */60 61#define NCT6683_LD_ACPI		0x0a62#define NCT6683_LD_HWM		0x0b63#define NCT6683_LD_VID		0x0d64 65#define SIO_REG_LDSEL		0x07	/* Logical device select */66#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */67#define SIO_REG_ENABLE		0x30	/* Logical device enable */68#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */69 70#define SIO_NCT6681_ID		0xb270	/* for later */71#define SIO_NCT6683_ID		0xc73072#define SIO_NCT6686_ID		0xd44073#define SIO_NCT6687_ID		0xd59074#define SIO_ID_MASK		0xFFF075 76static inline void77superio_outb(int ioreg, int reg, int val)78{79	outb(reg, ioreg);80	outb(val, ioreg + 1);81}82 83static inline int84superio_inb(int ioreg, int reg)85{86	outb(reg, ioreg);87	return inb(ioreg + 1);88}89 90static inline void91superio_select(int ioreg, int ld)92{93	outb(SIO_REG_LDSEL, ioreg);94	outb(ld, ioreg + 1);95}96 97static inline int98superio_enter(int ioreg)99{100	/*101	 * Try to reserve <ioreg> and <ioreg + 1> for exclusive access.102	 */103	if (!request_muxed_region(ioreg, 2, DRVNAME))104		return -EBUSY;105 106	outb(0x87, ioreg);107	outb(0x87, ioreg);108 109	return 0;110}111 112static inline void113superio_exit(int ioreg)114{115	outb(0xaa, ioreg);116	outb(0x02, ioreg);117	outb(0x02, ioreg + 1);118	release_region(ioreg, 2);119}120 121/*122 * ISA constants123 */124 125#define IOREGION_ALIGNMENT	(~7)126#define IOREGION_OFFSET		4	/* Use EC port 1 */127#define IOREGION_LENGTH		4128 129#define EC_PAGE_REG		0130#define EC_INDEX_REG		1131#define EC_DATA_REG		2132#define EC_EVENT_REG		3133 134/* Common and NCT6683 specific data */135 136#define NCT6683_NUM_REG_MON		32137#define NCT6683_NUM_REG_FAN		16138#define NCT6683_NUM_REG_PWM		8139 140#define NCT6683_REG_MON(x)		(0x100 + (x) * 2)141#define NCT6683_REG_FAN_RPM(x)		(0x140 + (x) * 2)142#define NCT6683_REG_PWM(x)		(0x160 + (x))143#define NCT6683_REG_PWM_WRITE(x)	(0xa28 + (x))144 145#define NCT6683_REG_MON_STS(x)		(0x174 + (x))146#define NCT6683_REG_IDLE(x)		(0x178 + (x))147 148#define NCT6683_REG_FAN_STS(x)		(0x17c + (x))149#define NCT6683_REG_FAN_ERRSTS		0x17e150#define NCT6683_REG_FAN_INITSTS		0x17f151 152#define NCT6683_HWM_CFG			0x180153 154#define NCT6683_REG_MON_CFG(x)		(0x1a0 + (x))155#define NCT6683_REG_FANIN_CFG(x)	(0x1c0 + (x))156#define NCT6683_REG_FANOUT_CFG(x)	(0x1d0 + (x))157 158#define NCT6683_REG_INTEL_TEMP_MAX(x)	(0x901 + (x) * 16)159#define NCT6683_REG_INTEL_TEMP_CRIT(x)	(0x90d + (x) * 16)160 161#define NCT6683_REG_TEMP_HYST(x)	(0x330 + (x))		/* 8 bit */162#define NCT6683_REG_TEMP_MAX(x)		(0x350 + (x))		/* 8 bit */163#define NCT6683_REG_MON_HIGH(x)		(0x370 + (x) * 2)	/* 8 bit */164#define NCT6683_REG_MON_LOW(x)		(0x371 + (x) * 2)	/* 8 bit */165 166#define NCT6683_REG_FAN_MIN(x)		(0x3b8 + (x) * 2)	/* 16 bit */167 168#define NCT6683_REG_FAN_CFG_CTRL	0xa01169#define NCT6683_FAN_CFG_REQ		0x80170#define NCT6683_FAN_CFG_DONE		0x40171 172#define NCT6683_REG_CUSTOMER_ID		0x602173#define NCT6683_CUSTOMER_ID_INTEL	0x805174#define NCT6683_CUSTOMER_ID_MITAC	0xa0e175#define NCT6683_CUSTOMER_ID_MSI		0x201176#define NCT6683_CUSTOMER_ID_MSI2	0x200177#define NCT6683_CUSTOMER_ID_MSI3	0x207178#define NCT6683_CUSTOMER_ID_ASROCK		0xe2c179#define NCT6683_CUSTOMER_ID_ASROCK2	0xe1b180#define NCT6683_CUSTOMER_ID_ASROCK3	0x1631181 182#define NCT6683_REG_BUILD_YEAR		0x604183#define NCT6683_REG_BUILD_MONTH		0x605184#define NCT6683_REG_BUILD_DAY		0x606185#define NCT6683_REG_SERIAL		0x607186#define NCT6683_REG_VERSION_HI		0x608187#define NCT6683_REG_VERSION_LO		0x609188 189#define NCT6683_REG_CR_CASEOPEN		0xe8190#define NCT6683_CR_CASEOPEN_MASK	(1 << 7)191 192#define NCT6683_REG_CR_BEEP		0xe0193#define NCT6683_CR_BEEP_MASK		(1 << 6)194 195static const char *const nct6683_mon_label[] = {196	NULL,	/* disabled */197	"Local",198	"Diode 0 (curr)",199	"Diode 1 (curr)",200	"Diode 2 (curr)",201	"Diode 0 (volt)",202	"Diode 1 (volt)",203	"Diode 2 (volt)",204	"Thermistor 14",205	"Thermistor 15",206	"Thermistor 16",207	"Thermistor 0",208	"Thermistor 1",209	"Thermistor 2",210	"Thermistor 3",211	"Thermistor 4",212	"Thermistor 5",		/* 0x10 */213	"Thermistor 6",214	"Thermistor 7",215	"Thermistor 8",216	"Thermistor 9",217	"Thermistor 10",218	"Thermistor 11",219	"Thermistor 12",220	"Thermistor 13",221	NULL, NULL, NULL, NULL, NULL, NULL, NULL,222	"PECI 0.0",		/* 0x20 */223	"PECI 1.0",224	"PECI 2.0",225	"PECI 3.0",226	"PECI 0.1",227	"PECI 1.1",228	"PECI 2.1",229	"PECI 3.1",230	"PECI DIMM 0",231	"PECI DIMM 1",232	"PECI DIMM 2",233	"PECI DIMM 3",234	NULL, NULL, NULL, NULL,235	"PCH CPU",		/* 0x30 */236	"PCH CHIP",237	"PCH CHIP CPU MAX",238	"PCH MCH",239	"PCH DIMM 0",240	"PCH DIMM 1",241	"PCH DIMM 2",242	"PCH DIMM 3",243	"SMBus 0",244	"SMBus 1",245	"SMBus 2",246	"SMBus 3",247	"SMBus 4",248	"SMBus 5",249	"DIMM 0",250	"DIMM 1",251	"DIMM 2",		/* 0x40 */252	"DIMM 3",253	"AMD TSI Addr 90h",254	"AMD TSI Addr 92h",255	"AMD TSI Addr 94h",256	"AMD TSI Addr 96h",257	"AMD TSI Addr 98h",258	"AMD TSI Addr 9ah",259	"AMD TSI Addr 9ch",260	"AMD TSI Addr 9dh",261	NULL, NULL, NULL, NULL, NULL, NULL,262	"Virtual 0",		/* 0x50 */263	"Virtual 1",264	"Virtual 2",265	"Virtual 3",266	"Virtual 4",267	"Virtual 5",268	"Virtual 6",269	"Virtual 7",270	NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,271	"VCC",			/* 0x60 voltage sensors */272	"VSB",273	"AVSB",274	"VTT",275	"VBAT",276	"VREF",277	"VIN0",278	"VIN1",279	"VIN2",280	"VIN3",281	"VIN4",282	"VIN5",283	"VIN6",284	"VIN7",285	"VIN8",286	"VIN9",287	"VIN10",288	"VIN11",289	"VIN12",290	"VIN13",291	"VIN14",292	"VIN15",293	"VIN16",294};295 296#define NUM_MON_LABELS		ARRAY_SIZE(nct6683_mon_label)297#define MON_VOLTAGE_START	0x60298 299/* ------------------------------------------------------- */300 301struct nct6683_data {302	int addr;		/* IO base of EC space */303	int sioreg;		/* SIO register */304	enum kinds kind;305	u16 customer_id;306 307	struct device *hwmon_dev;308	const struct attribute_group *groups[6];309 310	int temp_num;			/* number of temperature attributes */311	u8 temp_index[NCT6683_NUM_REG_MON];312	u8 temp_src[NCT6683_NUM_REG_MON];313 314	u8 in_num;			/* number of voltage attributes */315	u8 in_index[NCT6683_NUM_REG_MON];316	u8 in_src[NCT6683_NUM_REG_MON];317 318	struct mutex update_lock;	/* used to protect sensor updates */319	bool valid;			/* true if following fields are valid */320	unsigned long last_updated;	/* In jiffies */321 322	/* Voltage attribute values */323	u8 in[3][NCT6683_NUM_REG_MON];	/* [0]=in, [1]=in_max, [2]=in_min */324 325	/* Temperature attribute values */326	s16 temp_in[NCT6683_NUM_REG_MON];327	s8 temp[4][NCT6683_NUM_REG_MON];/* [0]=min, [1]=max, [2]=hyst,328					 * [3]=crit329					 */330 331	/* Fan attribute values */332	unsigned int rpm[NCT6683_NUM_REG_FAN];333	u16 fan_min[NCT6683_NUM_REG_FAN];334	u8 fanin_cfg[NCT6683_NUM_REG_FAN];335	u8 fanout_cfg[NCT6683_NUM_REG_FAN];336	u16 have_fan;			/* some fan inputs can be disabled */337 338	u8 have_pwm;339	u8 pwm[NCT6683_NUM_REG_PWM];340 341#ifdef CONFIG_PM342	/* Remember extra register values over suspend/resume */343	u8 hwm_cfg;344#endif345};346 347struct nct6683_sio_data {348	int sioreg;349	enum kinds kind;350};351 352struct sensor_device_template {353	struct device_attribute dev_attr;354	union {355		struct {356			u8 nr;357			u8 index;358		} s;359		int index;360	} u;361	bool s2;	/* true if both index and nr are used */362};363 364struct sensor_device_attr_u {365	union {366		struct sensor_device_attribute a1;367		struct sensor_device_attribute_2 a2;368	} u;369	char name[32];370};371 372#define __TEMPLATE_ATTR(_template, _mode, _show, _store) {	\373	.attr = {.name = _template, .mode = _mode },		\374	.show	= _show,					\375	.store	= _store,					\376}377 378#define SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store, _index)	\379	{ .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store),	\380	  .u.index = _index,						\381	  .s2 = false }382 383#define SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store,	\384				 _nr, _index)				\385	{ .dev_attr = __TEMPLATE_ATTR(_template, _mode, _show, _store),	\386	  .u.s.index = _index,						\387	  .u.s.nr = _nr,						\388	  .s2 = true }389 390#define SENSOR_TEMPLATE(_name, _template, _mode, _show, _store, _index)	\391static struct sensor_device_template sensor_dev_template_##_name	\392	= SENSOR_DEVICE_TEMPLATE(_template, _mode, _show, _store,	\393				 _index)394 395#define SENSOR_TEMPLATE_2(_name, _template, _mode, _show, _store,	\396			  _nr, _index)					\397static struct sensor_device_template sensor_dev_template_##_name	\398	= SENSOR_DEVICE_TEMPLATE_2(_template, _mode, _show, _store,	\399				 _nr, _index)400 401struct sensor_template_group {402	struct sensor_device_template **templates;403	umode_t (*is_visible)(struct kobject *, struct attribute *, int);404	int base;405};406 407static struct attribute_group *408nct6683_create_attr_group(struct device *dev,409			  const struct sensor_template_group *tg,410			  int repeat)411{412	struct sensor_device_attribute_2 *a2;413	struct sensor_device_attribute *a;414	struct sensor_device_template **t;415	struct sensor_device_attr_u *su;416	struct attribute_group *group;417	struct attribute **attrs;418	int i, count;419 420	if (repeat <= 0)421		return ERR_PTR(-EINVAL);422 423	t = tg->templates;424	for (count = 0; *t; t++, count++)425		;426 427	if (count == 0)428		return ERR_PTR(-EINVAL);429 430	group = devm_kzalloc(dev, sizeof(*group), GFP_KERNEL);431	if (group == NULL)432		return ERR_PTR(-ENOMEM);433 434	attrs = devm_kcalloc(dev, repeat * count + 1, sizeof(*attrs),435			     GFP_KERNEL);436	if (attrs == NULL)437		return ERR_PTR(-ENOMEM);438 439	su = devm_kzalloc(dev, array3_size(repeat, count, sizeof(*su)),440			  GFP_KERNEL);441	if (su == NULL)442		return ERR_PTR(-ENOMEM);443 444	group->attrs = attrs;445	group->is_visible = tg->is_visible;446 447	for (i = 0; i < repeat; i++) {448		t = tg->templates;449		while (*t) {450			snprintf(su->name, sizeof(su->name),451				 (*t)->dev_attr.attr.name, tg->base + i);452			if ((*t)->s2) {453				a2 = &su->u.a2;454				sysfs_attr_init(&a2->dev_attr.attr);455				a2->dev_attr.attr.name = su->name;456				a2->nr = (*t)->u.s.nr + i;457				a2->index = (*t)->u.s.index;458				a2->dev_attr.attr.mode =459				  (*t)->dev_attr.attr.mode;460				a2->dev_attr.show = (*t)->dev_attr.show;461				a2->dev_attr.store = (*t)->dev_attr.store;462				*attrs = &a2->dev_attr.attr;463			} else {464				a = &su->u.a1;465				sysfs_attr_init(&a->dev_attr.attr);466				a->dev_attr.attr.name = su->name;467				a->index = (*t)->u.index + i;468				a->dev_attr.attr.mode =469				  (*t)->dev_attr.attr.mode;470				a->dev_attr.show = (*t)->dev_attr.show;471				a->dev_attr.store = (*t)->dev_attr.store;472				*attrs = &a->dev_attr.attr;473			}474			attrs++;475			su++;476			t++;477		}478	}479 480	return group;481}482 483/* LSB is 16 mV, except for the following sources, where it is 32 mV */484#define MON_SRC_VCC	0x60485#define MON_SRC_VSB	0x61486#define MON_SRC_AVSB	0x62487#define MON_SRC_VBAT	0x64488 489static inline long in_from_reg(u16 reg, u8 src)490{491	int scale = 16;492 493	if (src == MON_SRC_VCC || src == MON_SRC_VSB || src == MON_SRC_AVSB ||494	    src == MON_SRC_VBAT)495		scale <<= 1;496	return reg * scale;497}498 499static u16 nct6683_read(struct nct6683_data *data, u16 reg)500{501	int res;502 503	outb_p(0xff, data->addr + EC_PAGE_REG);		/* unlock */504	outb_p(reg >> 8, data->addr + EC_PAGE_REG);505	outb_p(reg & 0xff, data->addr + EC_INDEX_REG);506	res = inb_p(data->addr + EC_DATA_REG);507	return res;508}509 510static u16 nct6683_read16(struct nct6683_data *data, u16 reg)511{512	return (nct6683_read(data, reg) << 8) | nct6683_read(data, reg + 1);513}514 515static void nct6683_write(struct nct6683_data *data, u16 reg, u16 value)516{517	outb_p(0xff, data->addr + EC_PAGE_REG);		/* unlock */518	outb_p(reg >> 8, data->addr + EC_PAGE_REG);519	outb_p(reg & 0xff, data->addr + EC_INDEX_REG);520	outb_p(value & 0xff, data->addr + EC_DATA_REG);521}522 523static int get_in_reg(struct nct6683_data *data, int nr, int index)524{525	int ch = data->in_index[index];526	int reg = -EINVAL;527 528	switch (nr) {529	case 0:530		reg = NCT6683_REG_MON(ch);531		break;532	case 1:533		if (data->customer_id != NCT6683_CUSTOMER_ID_INTEL)534			reg = NCT6683_REG_MON_LOW(ch);535		break;536	case 2:537		if (data->customer_id != NCT6683_CUSTOMER_ID_INTEL)538			reg = NCT6683_REG_MON_HIGH(ch);539		break;540	default:541		break;542	}543	return reg;544}545 546static int get_temp_reg(struct nct6683_data *data, int nr, int index)547{548	int ch = data->temp_index[index];549	int reg = -EINVAL;550 551	switch (data->customer_id) {552	case NCT6683_CUSTOMER_ID_INTEL:553		switch (nr) {554		default:555		case 1:	/* max */556			reg = NCT6683_REG_INTEL_TEMP_MAX(ch);557			break;558		case 3:	/* crit */559			reg = NCT6683_REG_INTEL_TEMP_CRIT(ch);560			break;561		}562		break;563	case NCT6683_CUSTOMER_ID_MITAC:564	default:565		switch (nr) {566		default:567		case 0:	/* min */568			reg = NCT6683_REG_MON_LOW(ch);569			break;570		case 1:	/* max */571			reg = NCT6683_REG_TEMP_MAX(ch);572			break;573		case 2:	/* hyst */574			reg = NCT6683_REG_TEMP_HYST(ch);575			break;576		case 3:	/* crit */577			reg = NCT6683_REG_MON_HIGH(ch);578			break;579		}580		break;581	}582	return reg;583}584 585static void nct6683_update_pwm(struct device *dev)586{587	struct nct6683_data *data = dev_get_drvdata(dev);588	int i;589 590	for (i = 0; i < NCT6683_NUM_REG_PWM; i++) {591		if (!(data->have_pwm & (1 << i)))592			continue;593		data->pwm[i] = nct6683_read(data, NCT6683_REG_PWM(i));594	}595}596 597static struct nct6683_data *nct6683_update_device(struct device *dev)598{599	struct nct6683_data *data = dev_get_drvdata(dev);600	int i, j;601 602	mutex_lock(&data->update_lock);603 604	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {605		/* Measured voltages and limits */606		for (i = 0; i < data->in_num; i++) {607			for (j = 0; j < 3; j++) {608				int reg = get_in_reg(data, j, i);609 610				if (reg >= 0)611					data->in[j][i] =612						nct6683_read(data, reg);613			}614		}615 616		/* Measured temperatures and limits */617		for (i = 0; i < data->temp_num; i++) {618			u8 ch = data->temp_index[i];619 620			data->temp_in[i] = nct6683_read16(data,621							  NCT6683_REG_MON(ch));622			for (j = 0; j < 4; j++) {623				int reg = get_temp_reg(data, j, i);624 625				if (reg >= 0)626					data->temp[j][i] =627						nct6683_read(data, reg);628			}629		}630 631		/* Measured fan speeds and limits */632		for (i = 0; i < ARRAY_SIZE(data->rpm); i++) {633			if (!(data->have_fan & (1 << i)))634				continue;635 636			data->rpm[i] = nct6683_read16(data,637						NCT6683_REG_FAN_RPM(i));638			data->fan_min[i] = nct6683_read16(data,639						NCT6683_REG_FAN_MIN(i));640		}641 642		nct6683_update_pwm(dev);643 644		data->last_updated = jiffies;645		data->valid = true;646	}647 648	mutex_unlock(&data->update_lock);649	return data;650}651 652/*653 * Sysfs callback functions654 */655static ssize_t656show_in_label(struct device *dev, struct device_attribute *attr, char *buf)657{658	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);659	struct nct6683_data *data = nct6683_update_device(dev);660	int nr = sattr->index;661 662	return sprintf(buf, "%s\n", nct6683_mon_label[data->in_src[nr]]);663}664 665static ssize_t666show_in_reg(struct device *dev, struct device_attribute *attr, char *buf)667{668	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);669	struct nct6683_data *data = nct6683_update_device(dev);670	int index = sattr->index;671	int nr = sattr->nr;672 673	return sprintf(buf, "%ld\n",674		       in_from_reg(data->in[index][nr], data->in_index[index]));675}676 677static umode_t nct6683_in_is_visible(struct kobject *kobj,678				     struct attribute *attr, int index)679{680	struct device *dev = kobj_to_dev(kobj);681	struct nct6683_data *data = dev_get_drvdata(dev);682	int nr = index % 4;	/* attribute */683 684	/*685	 * Voltage limits exist for Intel boards,686	 * but register location and encoding is unknown687	 */688	if ((nr == 2 || nr == 3) &&689	    data->customer_id == NCT6683_CUSTOMER_ID_INTEL)690		return 0;691 692	return attr->mode;693}694 695SENSOR_TEMPLATE(in_label, "in%d_label", S_IRUGO, show_in_label, NULL, 0);696SENSOR_TEMPLATE_2(in_input, "in%d_input", S_IRUGO, show_in_reg, NULL, 0, 0);697SENSOR_TEMPLATE_2(in_min, "in%d_min", S_IRUGO, show_in_reg, NULL, 0, 1);698SENSOR_TEMPLATE_2(in_max, "in%d_max", S_IRUGO, show_in_reg, NULL, 0, 2);699 700static struct sensor_device_template *nct6683_attributes_in_template[] = {701	&sensor_dev_template_in_label,702	&sensor_dev_template_in_input,703	&sensor_dev_template_in_min,704	&sensor_dev_template_in_max,705	NULL706};707 708static const struct sensor_template_group nct6683_in_template_group = {709	.templates = nct6683_attributes_in_template,710	.is_visible = nct6683_in_is_visible,711};712 713static ssize_t714show_fan(struct device *dev, struct device_attribute *attr, char *buf)715{716	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);717	struct nct6683_data *data = nct6683_update_device(dev);718 719	return sprintf(buf, "%d\n", data->rpm[sattr->index]);720}721 722static ssize_t723show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)724{725	struct nct6683_data *data = nct6683_update_device(dev);726	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);727	int nr = sattr->index;728 729	return sprintf(buf, "%d\n", data->fan_min[nr]);730}731 732static ssize_t733show_fan_pulses(struct device *dev, struct device_attribute *attr, char *buf)734{735	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);736	struct nct6683_data *data = nct6683_update_device(dev);737 738	return sprintf(buf, "%d\n",739		       ((data->fanin_cfg[sattr->index] >> 5) & 0x03) + 1);740}741 742static umode_t nct6683_fan_is_visible(struct kobject *kobj,743				      struct attribute *attr, int index)744{745	struct device *dev = kobj_to_dev(kobj);746	struct nct6683_data *data = dev_get_drvdata(dev);747	int fan = index / 3;	/* fan index */748	int nr = index % 3;	/* attribute index */749 750	if (!(data->have_fan & (1 << fan)))751		return 0;752 753	/*754	 * Intel may have minimum fan speed limits,755	 * but register location and encoding are unknown.756	 */757	if (nr == 2 && data->customer_id == NCT6683_CUSTOMER_ID_INTEL)758		return 0;759 760	return attr->mode;761}762 763SENSOR_TEMPLATE(fan_input, "fan%d_input", S_IRUGO, show_fan, NULL, 0);764SENSOR_TEMPLATE(fan_pulses, "fan%d_pulses", S_IRUGO, show_fan_pulses, NULL, 0);765SENSOR_TEMPLATE(fan_min, "fan%d_min", S_IRUGO, show_fan_min, NULL, 0);766 767/*768 * nct6683_fan_is_visible uses the index into the following array769 * to determine if attributes should be created or not.770 * Any change in order or content must be matched.771 */772static struct sensor_device_template *nct6683_attributes_fan_template[] = {773	&sensor_dev_template_fan_input,774	&sensor_dev_template_fan_pulses,775	&sensor_dev_template_fan_min,776	NULL777};778 779static const struct sensor_template_group nct6683_fan_template_group = {780	.templates = nct6683_attributes_fan_template,781	.is_visible = nct6683_fan_is_visible,782	.base = 1,783};784 785static ssize_t786show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)787{788	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);789	struct nct6683_data *data = nct6683_update_device(dev);790	int nr = sattr->index;791 792	return sprintf(buf, "%s\n", nct6683_mon_label[data->temp_src[nr]]);793}794 795static ssize_t796show_temp8(struct device *dev, struct device_attribute *attr, char *buf)797{798	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);799	struct nct6683_data *data = nct6683_update_device(dev);800	int index = sattr->index;801	int nr = sattr->nr;802 803	return sprintf(buf, "%d\n", data->temp[index][nr] * 1000);804}805 806static ssize_t807show_temp_hyst(struct device *dev, struct device_attribute *attr, char *buf)808{809	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);810	struct nct6683_data *data = nct6683_update_device(dev);811	int nr = sattr->index;812	int temp = data->temp[1][nr] - data->temp[2][nr];813 814	return sprintf(buf, "%d\n", temp * 1000);815}816 817static ssize_t818show_temp16(struct device *dev, struct device_attribute *attr, char *buf)819{820	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);821	struct nct6683_data *data = nct6683_update_device(dev);822	int index = sattr->index;823 824	return sprintf(buf, "%d\n", (data->temp_in[index] / 128) * 500);825}826 827/*828 * Temperature sensor type is determined by temperature source829 * and can not be modified.830 * 0x02..0x07: Thermal diode831 * 0x08..0x18: Thermistor832 * 0x20..0x2b: Intel PECI833 * 0x42..0x49: AMD TSI834 * Others are unspecified (not visible)835 */836 837static int get_temp_type(u8 src)838{839	if (src >= 0x02 && src <= 0x07)840		return 3;	/* thermal diode */841	else if (src >= 0x08 && src <= 0x18)842		return 4;	/* thermistor */843	else if (src >= 0x20 && src <= 0x2b)844		return 6;	/* PECI */845	else if (src >= 0x42 && src <= 0x49)846		return 5;847 848	return 0;849}850 851static ssize_t852show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)853{854	struct nct6683_data *data = nct6683_update_device(dev);855	struct sensor_device_attribute *sattr = to_sensor_dev_attr(attr);856	int nr = sattr->index;857	return sprintf(buf, "%d\n", get_temp_type(data->temp_src[nr]));858}859 860static umode_t nct6683_temp_is_visible(struct kobject *kobj,861				       struct attribute *attr, int index)862{863	struct device *dev = kobj_to_dev(kobj);864	struct nct6683_data *data = dev_get_drvdata(dev);865	int temp = index / 7;	/* temp index */866	int nr = index % 7;	/* attribute index */867 868	/*869	 * Intel does not have low temperature limits or temperature hysteresis870	 * registers, or at least register location and encoding is unknown.871	 */872	if ((nr == 2 || nr == 4) &&873	    data->customer_id == NCT6683_CUSTOMER_ID_INTEL)874		return 0;875 876	if (nr == 6 && get_temp_type(data->temp_src[temp]) == 0)877		return 0;				/* type */878 879	return attr->mode;880}881 882SENSOR_TEMPLATE(temp_input, "temp%d_input", S_IRUGO, show_temp16, NULL, 0);883SENSOR_TEMPLATE(temp_label, "temp%d_label", S_IRUGO, show_temp_label, NULL, 0);884SENSOR_TEMPLATE_2(temp_min, "temp%d_min", S_IRUGO, show_temp8, NULL, 0, 0);885SENSOR_TEMPLATE_2(temp_max, "temp%d_max", S_IRUGO, show_temp8, NULL, 0, 1);886SENSOR_TEMPLATE(temp_max_hyst, "temp%d_max_hyst", S_IRUGO, show_temp_hyst, NULL,887		0);888SENSOR_TEMPLATE_2(temp_crit, "temp%d_crit", S_IRUGO, show_temp8, NULL, 0, 3);889SENSOR_TEMPLATE(temp_type, "temp%d_type", S_IRUGO, show_temp_type, NULL, 0);890 891/*892 * nct6683_temp_is_visible uses the index into the following array893 * to determine if attributes should be created or not.894 * Any change in order or content must be matched.895 */896static struct sensor_device_template *nct6683_attributes_temp_template[] = {897	&sensor_dev_template_temp_input,898	&sensor_dev_template_temp_label,899	&sensor_dev_template_temp_min,		/* 2 */900	&sensor_dev_template_temp_max,		/* 3 */901	&sensor_dev_template_temp_max_hyst,	/* 4 */902	&sensor_dev_template_temp_crit,		/* 5 */903	&sensor_dev_template_temp_type,		/* 6 */904	NULL905};906 907static const struct sensor_template_group nct6683_temp_template_group = {908	.templates = nct6683_attributes_temp_template,909	.is_visible = nct6683_temp_is_visible,910	.base = 1,911};912 913static ssize_t914show_pwm(struct device *dev, struct device_attribute *attr, char *buf)915{916	struct nct6683_data *data = nct6683_update_device(dev);917	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);918	int index = sattr->index;919 920	return sprintf(buf, "%d\n", data->pwm[index]);921}922 923static ssize_t924store_pwm(struct device *dev, struct device_attribute *attr, const char *buf,925	  size_t count)926{927	struct sensor_device_attribute_2 *sattr = to_sensor_dev_attr_2(attr);928	struct nct6683_data *data = dev_get_drvdata(dev);929	int index = sattr->index;930	unsigned long val;931 932	if (kstrtoul(buf, 10, &val) || val > 255)933		return -EINVAL;934 935	mutex_lock(&data->update_lock);936	nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_REQ);937	usleep_range(1000, 2000);938	nct6683_write(data, NCT6683_REG_PWM_WRITE(index), val);939	nct6683_write(data, NCT6683_REG_FAN_CFG_CTRL, NCT6683_FAN_CFG_DONE);940	mutex_unlock(&data->update_lock);941 942	return count;943}944 945SENSOR_TEMPLATE(pwm, "pwm%d", S_IRUGO, show_pwm, store_pwm, 0);946 947static umode_t nct6683_pwm_is_visible(struct kobject *kobj,948				      struct attribute *attr, int index)949{950	struct device *dev = kobj_to_dev(kobj);951	struct nct6683_data *data = dev_get_drvdata(dev);952	int pwm = index;	/* pwm index */953 954	if (!(data->have_pwm & (1 << pwm)))955		return 0;956 957	/* Only update pwm values for Mitac boards */958	if (data->customer_id == NCT6683_CUSTOMER_ID_MITAC)959		return attr->mode | S_IWUSR;960 961	return attr->mode;962}963 964static struct sensor_device_template *nct6683_attributes_pwm_template[] = {965	&sensor_dev_template_pwm,966	NULL967};968 969static const struct sensor_template_group nct6683_pwm_template_group = {970	.templates = nct6683_attributes_pwm_template,971	.is_visible = nct6683_pwm_is_visible,972	.base = 1,973};974 975static ssize_t976beep_enable_show(struct device *dev, struct device_attribute *attr, char *buf)977{978	struct nct6683_data *data = dev_get_drvdata(dev);979	int ret;980	u8 reg;981 982	mutex_lock(&data->update_lock);983 984	ret = superio_enter(data->sioreg);985	if (ret)986		goto error;987	superio_select(data->sioreg, NCT6683_LD_HWM);988	reg = superio_inb(data->sioreg, NCT6683_REG_CR_BEEP);989	superio_exit(data->sioreg);990 991	mutex_unlock(&data->update_lock);992 993	return sprintf(buf, "%u\n", !!(reg & NCT6683_CR_BEEP_MASK));994 995error:996	mutex_unlock(&data->update_lock);997	return ret;998}999 1000static ssize_t1001beep_enable_store(struct device *dev, struct device_attribute *attr,1002		  const char *buf, size_t count)1003{1004	struct nct6683_data *data = dev_get_drvdata(dev);1005	unsigned long val;1006	u8 reg;1007	int ret;1008 1009	if (kstrtoul(buf, 10, &val) || (val != 0 && val != 1))1010		return -EINVAL;1011 1012	mutex_lock(&data->update_lock);1013 1014	ret = superio_enter(data->sioreg);1015	if (ret) {1016		count = ret;1017		goto error;1018	}1019 1020	superio_select(data->sioreg, NCT6683_LD_HWM);1021	reg = superio_inb(data->sioreg, NCT6683_REG_CR_BEEP);1022	if (val)1023		reg |= NCT6683_CR_BEEP_MASK;1024	else1025		reg &= ~NCT6683_CR_BEEP_MASK;1026	superio_outb(data->sioreg, NCT6683_REG_CR_BEEP, reg);1027	superio_exit(data->sioreg);1028error:1029	mutex_unlock(&data->update_lock);1030	return count;1031}1032 1033/* Case open detection */1034 1035static ssize_t1036intrusion0_alarm_show(struct device *dev, struct device_attribute *attr,1037		      char *buf)1038{1039	struct nct6683_data *data = dev_get_drvdata(dev);1040	int ret;1041	u8 reg;1042 1043	mutex_lock(&data->update_lock);1044 1045	ret = superio_enter(data->sioreg);1046	if (ret)1047		goto error;1048	superio_select(data->sioreg, NCT6683_LD_ACPI);1049	reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN);1050	superio_exit(data->sioreg);1051 1052	mutex_unlock(&data->update_lock);1053 1054	return sprintf(buf, "%u\n", !(reg & NCT6683_CR_CASEOPEN_MASK));1055 1056error:1057	mutex_unlock(&data->update_lock);1058	return ret;1059}1060 1061static ssize_t1062intrusion0_alarm_store(struct device *dev, struct device_attribute *attr,1063		       const char *buf, size_t count)1064{1065	struct nct6683_data *data = dev_get_drvdata(dev);1066	unsigned long val;1067	u8 reg;1068	int ret;1069 1070	if (kstrtoul(buf, 10, &val) || val != 0)1071		return -EINVAL;1072 1073	mutex_lock(&data->update_lock);1074 1075	/*1076	 * Use CR registers to clear caseopen status.1077	 * Caseopen is activ low, clear by writing 1 into the register.1078	 */1079 1080	ret = superio_enter(data->sioreg);1081	if (ret) {1082		count = ret;1083		goto error;1084	}1085 1086	superio_select(data->sioreg, NCT6683_LD_ACPI);1087	reg = superio_inb(data->sioreg, NCT6683_REG_CR_CASEOPEN);1088	reg |= NCT6683_CR_CASEOPEN_MASK;1089	superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg);1090	reg &= ~NCT6683_CR_CASEOPEN_MASK;1091	superio_outb(data->sioreg, NCT6683_REG_CR_CASEOPEN, reg);1092	superio_exit(data->sioreg);1093 1094	data->valid = false;	/* Force cache refresh */1095error:1096	mutex_unlock(&data->update_lock);1097	return count;1098}1099 1100static DEVICE_ATTR_RW(intrusion0_alarm);1101static DEVICE_ATTR_RW(beep_enable);1102 1103static struct attribute *nct6683_attributes_other[] = {1104	&dev_attr_intrusion0_alarm.attr,1105	&dev_attr_beep_enable.attr,1106	NULL1107};1108 1109static const struct attribute_group nct6683_group_other = {1110	.attrs = nct6683_attributes_other,1111};1112 1113/* Get the monitoring functions started */1114static inline void nct6683_init_device(struct nct6683_data *data)1115{1116	u8 tmp;1117 1118	/* Start hardware monitoring if needed */1119	tmp = nct6683_read(data, NCT6683_HWM_CFG);1120	if (!(tmp & 0x80))1121		nct6683_write(data, NCT6683_HWM_CFG, tmp | 0x80);1122}1123 1124/*1125 * There are a total of 24 fan inputs. Each can be configured as input1126 * or as output. A maximum of 16 inputs and 8 outputs is configurable.1127 */1128static void1129nct6683_setup_fans(struct nct6683_data *data)1130{1131	int i;1132	u8 reg;1133 1134	for (i = 0; i < NCT6683_NUM_REG_FAN; i++) {1135		reg = nct6683_read(data, NCT6683_REG_FANIN_CFG(i));1136		if (reg & 0x80)1137			data->have_fan |= 1 << i;1138		data->fanin_cfg[i] = reg;1139	}1140	for (i = 0; i < NCT6683_NUM_REG_PWM; i++) {1141		reg = nct6683_read(data, NCT6683_REG_FANOUT_CFG(i));1142		if (reg & 0x80)1143			data->have_pwm |= 1 << i;1144		data->fanout_cfg[i] = reg;1145	}1146}1147 1148/*1149 * Translation from monitoring register to temperature and voltage attributes1150 * ==========================================================================1151 *1152 * There are a total of 32 monitoring registers. Each can be assigned to either1153 * a temperature or voltage monitoring source.1154 * NCT6683_REG_MON_CFG(x) defines assignment for each monitoring source.1155 *1156 * Temperature and voltage attribute mapping is determined by walking through1157 * the NCT6683_REG_MON_CFG registers. If the assigned source is1158 * a temperature, temp_index[n] is set to the monitor register index, and1159 * temp_src[n] is set to the temperature source. If the assigned source is1160 * a voltage, the respective values are stored in in_index[] and in_src[],1161 * respectively.1162 */1163 1164static void nct6683_setup_sensors(struct nct6683_data *data)1165{1166	u8 reg;1167	int i;1168 1169	data->temp_num = 0;1170	data->in_num = 0;1171	for (i = 0; i < NCT6683_NUM_REG_MON; i++) {1172		reg = nct6683_read(data, NCT6683_REG_MON_CFG(i)) & 0x7f;1173		/* Ignore invalid assignments */1174		if (reg >= NUM_MON_LABELS)1175			continue;1176		/* Skip if disabled or reserved */1177		if (nct6683_mon_label[reg] == NULL)1178			continue;1179		if (reg < MON_VOLTAGE_START) {1180			data->temp_index[data->temp_num] = i;1181			data->temp_src[data->temp_num] = reg;1182			data->temp_num++;1183		} else {1184			data->in_index[data->in_num] = i;1185			data->in_src[data->in_num] = reg;1186			data->in_num++;1187		}1188	}1189}1190 1191static int nct6683_probe(struct platform_device *pdev)1192{1193	struct device *dev = &pdev->dev;1194	struct nct6683_sio_data *sio_data = dev->platform_data;1195	struct attribute_group *group;1196	struct nct6683_data *data;1197	struct device *hwmon_dev;1198	struct resource *res;1199	int groups = 0;1200	char build[16];1201 1202	res = platform_get_resource(pdev, IORESOURCE_IO, 0);1203	if (!devm_request_region(dev, res->start, IOREGION_LENGTH, DRVNAME))1204		return -EBUSY;1205 1206	data = devm_kzalloc(dev, sizeof(struct nct6683_data), GFP_KERNEL);1207	if (!data)1208		return -ENOMEM;1209 1210	data->kind = sio_data->kind;1211	data->sioreg = sio_data->sioreg;1212	data->addr = res->start;1213	mutex_init(&data->update_lock);1214	platform_set_drvdata(pdev, data);1215 1216	data->customer_id = nct6683_read16(data, NCT6683_REG_CUSTOMER_ID);1217 1218	/* By default only instantiate driver if the customer ID is known */1219	switch (data->customer_id) {1220	case NCT6683_CUSTOMER_ID_INTEL:1221		break;1222	case NCT6683_CUSTOMER_ID_MITAC:1223		break;1224	case NCT6683_CUSTOMER_ID_MSI:1225		break;1226	case NCT6683_CUSTOMER_ID_MSI2:1227		break;1228	case NCT6683_CUSTOMER_ID_MSI3:1229		break;1230	case NCT6683_CUSTOMER_ID_ASROCK:1231		break;1232	case NCT6683_CUSTOMER_ID_ASROCK2:1233		break;1234	case NCT6683_CUSTOMER_ID_ASROCK3:1235		break;1236	default:1237		if (!force)1238			return -ENODEV;1239		dev_warn(dev, "Enabling support for unknown customer ID 0x%04x\n", data->customer_id);1240		break;1241	}1242 1243	nct6683_init_device(data);1244	nct6683_setup_fans(data);1245	nct6683_setup_sensors(data);1246 1247	/* Register sysfs hooks */1248 1249	if (data->have_pwm) {1250		group = nct6683_create_attr_group(dev,1251						  &nct6683_pwm_template_group,1252						  fls(data->have_pwm));1253		if (IS_ERR(group))1254			return PTR_ERR(group);1255		data->groups[groups++] = group;1256	}1257 1258	if (data->in_num) {1259		group = nct6683_create_attr_group(dev,1260						  &nct6683_in_template_group,1261						  data->in_num);1262		if (IS_ERR(group))1263			return PTR_ERR(group);1264		data->groups[groups++] = group;1265	}1266 1267	if (data->have_fan) {1268		group = nct6683_create_attr_group(dev,1269						  &nct6683_fan_template_group,1270						  fls(data->have_fan));1271		if (IS_ERR(group))1272			return PTR_ERR(group);1273		data->groups[groups++] = group;1274	}1275 1276	if (data->temp_num) {1277		group = nct6683_create_attr_group(dev,1278						  &nct6683_temp_template_group,1279						  data->temp_num);1280		if (IS_ERR(group))1281			return PTR_ERR(group);1282		data->groups[groups++] = group;1283	}1284	data->groups[groups++] = &nct6683_group_other;1285 1286	if (data->customer_id == NCT6683_CUSTOMER_ID_INTEL)1287		scnprintf(build, sizeof(build), "%02x/%02x/%02x",1288			  nct6683_read(data, NCT6683_REG_BUILD_MONTH),1289			  nct6683_read(data, NCT6683_REG_BUILD_DAY),1290			  nct6683_read(data, NCT6683_REG_BUILD_YEAR));1291	else1292		scnprintf(build, sizeof(build), "%02d/%02d/%02d",1293			  nct6683_read(data, NCT6683_REG_BUILD_MONTH),1294			  nct6683_read(data, NCT6683_REG_BUILD_DAY),1295			  nct6683_read(data, NCT6683_REG_BUILD_YEAR));1296 1297	dev_info(dev, "%s EC firmware version %d.%d build %s\n",1298		 nct6683_chip_names[data->kind],1299		 nct6683_read(data, NCT6683_REG_VERSION_HI),1300		 nct6683_read(data, NCT6683_REG_VERSION_LO),1301		 build);1302 1303	hwmon_dev = devm_hwmon_device_register_with_groups(dev,1304			nct6683_device_names[data->kind], data, data->groups);1305	return PTR_ERR_OR_ZERO(hwmon_dev);1306}1307 1308#ifdef CONFIG_PM1309static int nct6683_suspend(struct device *dev)1310{1311	struct nct6683_data *data = nct6683_update_device(dev);1312 1313	mutex_lock(&data->update_lock);1314	data->hwm_cfg = nct6683_read(data, NCT6683_HWM_CFG);1315	mutex_unlock(&data->update_lock);1316 1317	return 0;1318}1319 1320static int nct6683_resume(struct device *dev)1321{1322	struct nct6683_data *data = dev_get_drvdata(dev);1323 1324	mutex_lock(&data->update_lock);1325 1326	nct6683_write(data, NCT6683_HWM_CFG, data->hwm_cfg);1327 1328	/* Force re-reading all values */1329	data->valid = false;1330	mutex_unlock(&data->update_lock);1331 1332	return 0;1333}1334 1335static const struct dev_pm_ops nct6683_dev_pm_ops = {1336	.suspend = nct6683_suspend,1337	.resume = nct6683_resume,1338	.freeze = nct6683_suspend,1339	.restore = nct6683_resume,1340};1341 1342#define NCT6683_DEV_PM_OPS	(&nct6683_dev_pm_ops)1343#else1344#define NCT6683_DEV_PM_OPS	NULL1345#endif /* CONFIG_PM */1346 1347static struct platform_driver nct6683_driver = {1348	.driver = {1349		.name	= DRVNAME,1350		.pm	= NCT6683_DEV_PM_OPS,1351	},1352	.probe		= nct6683_probe,1353};1354 1355static int __init nct6683_find(int sioaddr, struct nct6683_sio_data *sio_data)1356{1357	int addr;1358	u16 val;1359	int err;1360 1361	err = superio_enter(sioaddr);1362	if (err)1363		return err;1364 1365	val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)1366	       | superio_inb(sioaddr, SIO_REG_DEVID + 1);1367 1368	switch (val & SIO_ID_MASK) {1369	case SIO_NCT6683_ID:1370		sio_data->kind = nct6683;1371		break;1372	case SIO_NCT6686_ID:1373		sio_data->kind = nct6686;1374		break;1375	case SIO_NCT6687_ID:1376		sio_data->kind = nct6687;1377		break;1378	default:1379		if (val != 0xffff)1380			pr_debug("unsupported chip ID: 0x%04x\n", val);1381		goto fail;1382	}1383 1384	/* We have a known chip, find the HWM I/O address */1385	superio_select(sioaddr, NCT6683_LD_HWM);1386	val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)1387	    | superio_inb(sioaddr, SIO_REG_ADDR + 1);1388	addr = val & IOREGION_ALIGNMENT;1389	if (addr == 0) {1390		pr_err("EC base I/O port unconfigured\n");1391		goto fail;1392	}1393 1394	/* Activate logical device if needed */1395	val = superio_inb(sioaddr, SIO_REG_ENABLE);1396	if (!(val & 0x01)) {1397		pr_warn("Forcibly enabling EC access. Data may be unusable.\n");1398		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);1399	}1400 1401	superio_exit(sioaddr);1402	pr_info("Found %s or compatible chip at %#x:%#x\n",1403		nct6683_chip_names[sio_data->kind], sioaddr, addr);1404	sio_data->sioreg = sioaddr;1405 1406	return addr;1407 1408fail:1409	superio_exit(sioaddr);1410	return -ENODEV;1411}1412 1413/*1414 * when Super-I/O functions move to a separate file, the Super-I/O1415 * bus will manage the lifetime of the device and this module will only keep1416 * track of the nct6683 driver. But since we use platform_device_alloc(), we1417 * must keep track of the device1418 */1419static struct platform_device *pdev[2];1420 1421static int __init sensors_nct6683_init(void)1422{1423	struct nct6683_sio_data sio_data;1424	int sioaddr[2] = { 0x2e, 0x4e };1425	struct resource res;1426	bool found = false;1427	int address;1428	int i, err;1429 1430	err = platform_driver_register(&nct6683_driver);1431	if (err)1432		return err;1433 1434	/*1435	 * initialize sio_data->kind and sio_data->sioreg.1436	 *1437	 * when Super-I/O functions move to a separate file, the Super-I/O1438	 * driver will probe 0x2e and 0x4e and auto-detect the presence of a1439	 * nct6683 hardware monitor, and call probe()1440	 */1441	for (i = 0; i < ARRAY_SIZE(pdev); i++) {1442		address = nct6683_find(sioaddr[i], &sio_data);1443		if (address <= 0)1444			continue;1445 1446		found = true;1447 1448		pdev[i] = platform_device_alloc(DRVNAME, address);1449		if (!pdev[i]) {1450			err = -ENOMEM;1451			goto exit_device_unregister;1452		}1453 1454		err = platform_device_add_data(pdev[i], &sio_data,1455					       sizeof(struct nct6683_sio_data));1456		if (err)1457			goto exit_device_put;1458 1459		memset(&res, 0, sizeof(res));1460		res.name = DRVNAME;1461		res.start = address + IOREGION_OFFSET;1462		res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;1463		res.flags = IORESOURCE_IO;1464 1465		err = acpi_check_resource_conflict(&res);1466		if (err) {1467			platform_device_put(pdev[i]);1468			pdev[i] = NULL;1469			continue;1470		}1471 1472		err = platform_device_add_resources(pdev[i], &res, 1);1473		if (err)1474			goto exit_device_put;1475 1476		/* platform_device_add calls probe() */1477		err = platform_device_add(pdev[i]);1478		if (err)1479			goto exit_device_put;1480	}1481	if (!found) {1482		err = -ENODEV;1483		goto exit_unregister;1484	}1485 1486	return 0;1487 1488exit_device_put:1489	platform_device_put(pdev[i]);1490exit_device_unregister:1491	while (--i >= 0) {1492		if (pdev[i])1493			platform_device_unregister(pdev[i]);1494	}1495exit_unregister:1496	platform_driver_unregister(&nct6683_driver);1497	return err;1498}1499 1500static void __exit sensors_nct6683_exit(void)1501{1502	int i;1503 1504	for (i = 0; i < ARRAY_SIZE(pdev); i++) {1505		if (pdev[i])1506			platform_device_unregister(pdev[i]);1507	}1508	platform_driver_unregister(&nct6683_driver);1509}1510 1511MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");1512MODULE_DESCRIPTION("NCT6683D driver");1513MODULE_LICENSE("GPL");1514 1515module_init(sensors_nct6683_init);1516module_exit(sensors_nct6683_exit);1517