brintos

brintos / linux-shallow public Read only

0
0
Text · 15.8 KiB · c459dce Raw
625 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * jc42.c - driver for Jedec JC42.4 compliant temperature sensors4 *5 * Copyright (c) 2010  Ericsson AB.6 *7 * Derived from lm77.c by Andras BALI <drewie@freemail.hu>.8 *9 * JC42.4 compliant temperature sensors are typically used on memory modules.10 */11 12#include <linux/bitops.h>13#include <linux/bitfield.h>14#include <linux/module.h>15#include <linux/init.h>16#include <linux/slab.h>17#include <linux/jiffies.h>18#include <linux/i2c.h>19#include <linux/hwmon.h>20#include <linux/err.h>21#include <linux/mutex.h>22#include <linux/of.h>23#include <linux/regmap.h>24 25/* Addresses to scan */26static const unsigned short normal_i2c[] = {27	0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, I2C_CLIENT_END };28 29/* JC42 registers. All registers are 16 bit. */30#define JC42_REG_CAP		0x0031#define JC42_REG_CONFIG		0x0132#define JC42_REG_TEMP_UPPER	0x0233#define JC42_REG_TEMP_LOWER	0x0334#define JC42_REG_TEMP_CRITICAL	0x0435#define JC42_REG_TEMP		0x0536#define JC42_REG_MANID		0x0637#define JC42_REG_DEVICEID	0x0738#define JC42_REG_SMBUS		0x22 /* NXP and Atmel, possibly others? */39 40/* Status bits in temperature register */41#define JC42_ALARM_CRIT		BIT(15)42#define JC42_ALARM_MAX		BIT(14)43#define JC42_ALARM_MIN		BIT(13)44 45/* Configuration register defines */46#define JC42_CFG_CRIT_ONLY	BIT(2)47#define JC42_CFG_TCRIT_LOCK	BIT(6)48#define JC42_CFG_EVENT_LOCK	BIT(7)49#define JC42_CFG_SHUTDOWN	BIT(8)50#define JC42_CFG_HYST_MASK	GENMASK(10, 9)51 52/* Capabilities */53#define JC42_CAP_RANGE		BIT(2)54 55/* Manufacturer IDs */56#define ADT_MANID		0x11d4  /* Analog Devices */57#define ATMEL_MANID		0x001f  /* Atmel */58#define ATMEL_MANID2		0x1114	/* Atmel */59#define MAX_MANID		0x004d  /* Maxim */60#define IDT_MANID		0x00b3  /* IDT */61#define MCP_MANID		0x0054  /* Microchip */62#define NXP_MANID		0x1131  /* NXP Semiconductors */63#define ONS_MANID		0x1b09  /* ON Semiconductor */64#define STM_MANID		0x104a  /* ST Microelectronics */65#define GT_MANID		0x1c68	/* Giantec */66#define GT_MANID2		0x132d	/* Giantec, 2nd mfg ID */67#define SI_MANID		0x1c85	/* Seiko Instruments */68 69/* SMBUS register */70#define SMBUS_STMOUT		BIT(7)  /* SMBus time-out, active low */71 72/* Supported chips */73 74/* Analog Devices */75#define ADT7408_DEVID		0x080176#define ADT7408_DEVID_MASK	0xffff77 78/* Atmel */79#define AT30TS00_DEVID		0x820180#define AT30TS00_DEVID_MASK	0xffff81 82#define GT34TS02_DEVID		0x330083#define GT34TS02_DEVID_MASK	0xff0084 85#define TS3000_DEVID		0x2900  /* Also matches TSE2002 */86#define TS3000_DEVID_MASK	0xff0087 88#define TS3001_DEVID		0x300089#define TS3001_DEVID_MASK	0xff0090 91/* Maxim */92#define MAX6604_DEVID		0x3e0093#define MAX6604_DEVID_MASK	0xffff94 95/* Microchip */96#define MCP9804_DEVID		0x020097#define MCP9804_DEVID_MASK	0xfffc98 99#define MCP9808_DEVID		0x0400100#define MCP9808_DEVID_MASK	0xfffc101 102#define MCP98242_DEVID		0x2000103#define MCP98242_DEVID_MASK	0xfffc104 105#define MCP98243_DEVID		0x2100106#define MCP98243_DEVID_MASK	0xfffc107 108#define MCP9843_DEVID		0x0000	/* Also matches mcp9805 */109#define MCP9843_DEVID_MASK	0xfffe110 111/* NXP */112#define SE97_DEVID		0xa200113#define SE97_DEVID_MASK		0xfffc114 115#define SE98_DEVID		0xa100116#define SE98_DEVID_MASK		0xfffc117 118/* ON Semiconductor */119#define CAT6095_DEVID		0x0800	/* Also matches CAT34TS02 */120#define CAT6095_DEVID_MASK	0xffe0121 122#define CAT34TS02C_DEVID	0x0a00123#define CAT34TS02C_DEVID_MASK	0xfff0124 125/* ST Microelectronics */126#define STTS424_DEVID		0x0101127#define STTS424_DEVID_MASK	0xffff128 129#define STTS424E_DEVID		0x0000130#define STTS424E_DEVID_MASK	0xfffe131 132#define STTS2002_DEVID		0x0300133#define STTS2002_DEVID_MASK	0xffff134 135#define STTS3000_DEVID		0x0200136#define STTS3000_DEVID_MASK	0xffff137 138/* TSE2004 compliant sensors */139#define TSE2004_DEVID		0x2200140#define TSE2004_DEVID_MASK	0xff00141 142static u16 jc42_hysteresis[] = { 0, 1500, 3000, 6000 };143 144struct jc42_chips {145	u16 manid;146	u16 devid;147	u16 devid_mask;148};149 150static struct jc42_chips jc42_chips[] = {151	{ ADT_MANID, ADT7408_DEVID, ADT7408_DEVID_MASK },152	{ ATMEL_MANID, AT30TS00_DEVID, AT30TS00_DEVID_MASK },153	{ ATMEL_MANID2, TSE2004_DEVID, TSE2004_DEVID_MASK },154	{ GT_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },155	{ GT_MANID2, GT34TS02_DEVID, GT34TS02_DEVID_MASK },156	{ IDT_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },157	{ IDT_MANID, TS3000_DEVID, TS3000_DEVID_MASK },158	{ IDT_MANID, TS3001_DEVID, TS3001_DEVID_MASK },159	{ MAX_MANID, MAX6604_DEVID, MAX6604_DEVID_MASK },160	{ MCP_MANID, MCP9804_DEVID, MCP9804_DEVID_MASK },161	{ MCP_MANID, MCP9808_DEVID, MCP9808_DEVID_MASK },162	{ MCP_MANID, MCP98242_DEVID, MCP98242_DEVID_MASK },163	{ MCP_MANID, MCP98243_DEVID, MCP98243_DEVID_MASK },164	{ MCP_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },165	{ MCP_MANID, MCP9843_DEVID, MCP9843_DEVID_MASK },166	{ NXP_MANID, SE97_DEVID, SE97_DEVID_MASK },167	{ ONS_MANID, CAT6095_DEVID, CAT6095_DEVID_MASK },168	{ ONS_MANID, CAT34TS02C_DEVID, CAT34TS02C_DEVID_MASK },169	{ ONS_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },170	{ ONS_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },171	{ NXP_MANID, SE98_DEVID, SE98_DEVID_MASK },172	{ SI_MANID,  TSE2004_DEVID, TSE2004_DEVID_MASK },173	{ STM_MANID, STTS424_DEVID, STTS424_DEVID_MASK },174	{ STM_MANID, STTS424E_DEVID, STTS424E_DEVID_MASK },175	{ STM_MANID, STTS2002_DEVID, STTS2002_DEVID_MASK },176	{ STM_MANID, TSE2004_DEVID, TSE2004_DEVID_MASK },177	{ STM_MANID, STTS3000_DEVID, STTS3000_DEVID_MASK },178};179 180/* Each client has this additional data */181struct jc42_data {182	struct mutex	update_lock;	/* protect register access */183	struct regmap	*regmap;184	bool		extended;	/* true if extended range supported */185	bool		valid;186	u16		orig_config;	/* original configuration */187	u16		config;		/* current configuration */188};189 190#define JC42_TEMP_MIN_EXTENDED	(-40000)191#define JC42_TEMP_MIN		0192#define JC42_TEMP_MAX		125000193 194static u16 jc42_temp_to_reg(long temp, bool extended)195{196	int ntemp = clamp_val(temp,197			      extended ? JC42_TEMP_MIN_EXTENDED :198			      JC42_TEMP_MIN, JC42_TEMP_MAX);199 200	/* convert from 0.001 to 0.0625 resolution */201	return (ntemp * 2 / 125) & 0x1fff;202}203 204static int jc42_temp_from_reg(s16 reg)205{206	reg = sign_extend32(reg, 12);207 208	/* convert from 0.0625 to 0.001 resolution */209	return reg * 125 / 2;210}211 212static int jc42_read(struct device *dev, enum hwmon_sensor_types type,213		     u32 attr, int channel, long *val)214{215	struct jc42_data *data = dev_get_drvdata(dev);216	unsigned int regval;217	int ret, temp, hyst;218 219	mutex_lock(&data->update_lock);220 221	switch (attr) {222	case hwmon_temp_input:223		ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);224		if (ret)225			break;226 227		*val = jc42_temp_from_reg(regval);228		break;229	case hwmon_temp_min:230		ret = regmap_read(data->regmap, JC42_REG_TEMP_LOWER, &regval);231		if (ret)232			break;233 234		*val = jc42_temp_from_reg(regval);235		break;236	case hwmon_temp_max:237		ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, &regval);238		if (ret)239			break;240 241		*val = jc42_temp_from_reg(regval);242		break;243	case hwmon_temp_crit:244		ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL,245				  &regval);246		if (ret)247			break;248 249		*val = jc42_temp_from_reg(regval);250		break;251	case hwmon_temp_max_hyst:252		ret = regmap_read(data->regmap, JC42_REG_TEMP_UPPER, &regval);253		if (ret)254			break;255 256		temp = jc42_temp_from_reg(regval);257		hyst = jc42_hysteresis[FIELD_GET(JC42_CFG_HYST_MASK,258						 data->config)];259		*val = temp - hyst;260		break;261	case hwmon_temp_crit_hyst:262		ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL,263				  &regval);264		if (ret)265			break;266 267		temp = jc42_temp_from_reg(regval);268		hyst = jc42_hysteresis[FIELD_GET(JC42_CFG_HYST_MASK,269						 data->config)];270		*val = temp - hyst;271		break;272	case hwmon_temp_min_alarm:273		ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);274		if (ret)275			break;276 277		*val = FIELD_GET(JC42_ALARM_MIN, regval);278		break;279	case hwmon_temp_max_alarm:280		ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);281		if (ret)282			break;283 284		*val = FIELD_GET(JC42_ALARM_MAX, regval);285		break;286	case hwmon_temp_crit_alarm:287		ret = regmap_read(data->regmap, JC42_REG_TEMP, &regval);288		if (ret)289			break;290 291		*val = FIELD_GET(JC42_ALARM_CRIT, regval);292		break;293	default:294		ret = -EOPNOTSUPP;295		break;296	}297 298	mutex_unlock(&data->update_lock);299 300	return ret;301}302 303static int jc42_write(struct device *dev, enum hwmon_sensor_types type,304		      u32 attr, int channel, long val)305{306	struct jc42_data *data = dev_get_drvdata(dev);307	unsigned int regval;308	int diff, hyst;309	int ret;310 311	mutex_lock(&data->update_lock);312 313	switch (attr) {314	case hwmon_temp_min:315		ret = regmap_write(data->regmap, JC42_REG_TEMP_LOWER,316				   jc42_temp_to_reg(val, data->extended));317		break;318	case hwmon_temp_max:319		ret = regmap_write(data->regmap, JC42_REG_TEMP_UPPER,320				   jc42_temp_to_reg(val, data->extended));321		break;322	case hwmon_temp_crit:323		ret = regmap_write(data->regmap, JC42_REG_TEMP_CRITICAL,324				   jc42_temp_to_reg(val, data->extended));325		break;326	case hwmon_temp_crit_hyst:327		ret = regmap_read(data->regmap, JC42_REG_TEMP_CRITICAL,328				  &regval);329		if (ret)330			break;331 332		/*333		 * JC42.4 compliant chips only support four hysteresis values.334		 * Pick best choice and go from there.335		 */336		val = clamp_val(val, (data->extended ? JC42_TEMP_MIN_EXTENDED337						     : JC42_TEMP_MIN) - 6000,338				JC42_TEMP_MAX);339		diff = jc42_temp_from_reg(regval) - val;340		hyst = 0;341		if (diff > 0) {342			if (diff < 2250)343				hyst = 1;	/* 1.5 degrees C */344			else if (diff < 4500)345				hyst = 2;	/* 3.0 degrees C */346			else347				hyst = 3;	/* 6.0 degrees C */348		}349		data->config = (data->config & ~JC42_CFG_HYST_MASK) |350				FIELD_PREP(JC42_CFG_HYST_MASK, hyst);351		ret = regmap_write(data->regmap, JC42_REG_CONFIG,352				   data->config);353		break;354	default:355		ret = -EOPNOTSUPP;356		break;357	}358 359	mutex_unlock(&data->update_lock);360 361	return ret;362}363 364static umode_t jc42_is_visible(const void *_data, enum hwmon_sensor_types type,365			       u32 attr, int channel)366{367	const struct jc42_data *data = _data;368	unsigned int config = data->config;369	umode_t mode = 0444;370 371	switch (attr) {372	case hwmon_temp_min:373	case hwmon_temp_max:374		if (!(config & JC42_CFG_EVENT_LOCK))375			mode |= 0200;376		break;377	case hwmon_temp_crit:378		if (!(config & JC42_CFG_TCRIT_LOCK))379			mode |= 0200;380		break;381	case hwmon_temp_crit_hyst:382		if (!(config & (JC42_CFG_EVENT_LOCK | JC42_CFG_TCRIT_LOCK)))383			mode |= 0200;384		break;385	case hwmon_temp_input:386	case hwmon_temp_max_hyst:387	case hwmon_temp_min_alarm:388	case hwmon_temp_max_alarm:389	case hwmon_temp_crit_alarm:390		break;391	default:392		mode = 0;393		break;394	}395	return mode;396}397 398/* Return 0 if detection is successful, -ENODEV otherwise */399static int jc42_detect(struct i2c_client *client, struct i2c_board_info *info)400{401	struct i2c_adapter *adapter = client->adapter;402	int i, config, cap, manid, devid;403 404	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |405				     I2C_FUNC_SMBUS_WORD_DATA))406		return -ENODEV;407 408	cap = i2c_smbus_read_word_swapped(client, JC42_REG_CAP);409	config = i2c_smbus_read_word_swapped(client, JC42_REG_CONFIG);410	manid = i2c_smbus_read_word_swapped(client, JC42_REG_MANID);411	devid = i2c_smbus_read_word_swapped(client, JC42_REG_DEVICEID);412 413	if (cap < 0 || config < 0 || manid < 0 || devid < 0)414		return -ENODEV;415 416	if ((cap & 0xff00) || (config & 0xf820))417		return -ENODEV;418 419	if ((devid & TSE2004_DEVID_MASK) == TSE2004_DEVID &&420	    (cap & 0x0062) != 0x0062)421		return -ENODEV;422 423	for (i = 0; i < ARRAY_SIZE(jc42_chips); i++) {424		struct jc42_chips *chip = &jc42_chips[i];425		if (manid == chip->manid &&426		    (devid & chip->devid_mask) == chip->devid) {427			strscpy(info->type, "jc42", I2C_NAME_SIZE);428			return 0;429		}430	}431	return -ENODEV;432}433 434static const struct hwmon_channel_info * const jc42_info[] = {435	HWMON_CHANNEL_INFO(chip,436			   HWMON_C_REGISTER_TZ | HWMON_C_UPDATE_INTERVAL),437	HWMON_CHANNEL_INFO(temp,438			   HWMON_T_INPUT | HWMON_T_MIN | HWMON_T_MAX |439			   HWMON_T_CRIT | HWMON_T_MAX_HYST |440			   HWMON_T_CRIT_HYST | HWMON_T_MIN_ALARM |441			   HWMON_T_MAX_ALARM | HWMON_T_CRIT_ALARM),442	NULL443};444 445static const struct hwmon_ops jc42_hwmon_ops = {446	.is_visible = jc42_is_visible,447	.read = jc42_read,448	.write = jc42_write,449};450 451static const struct hwmon_chip_info jc42_chip_info = {452	.ops = &jc42_hwmon_ops,453	.info = jc42_info,454};455 456static bool jc42_readable_reg(struct device *dev, unsigned int reg)457{458	return (reg >= JC42_REG_CAP && reg <= JC42_REG_DEVICEID) ||459		reg == JC42_REG_SMBUS;460}461 462static bool jc42_writable_reg(struct device *dev, unsigned int reg)463{464	return (reg >= JC42_REG_CONFIG && reg <= JC42_REG_TEMP_CRITICAL) ||465		reg == JC42_REG_SMBUS;466}467 468static bool jc42_volatile_reg(struct device *dev, unsigned int reg)469{470	return reg == JC42_REG_CONFIG || reg == JC42_REG_TEMP;471}472 473static const struct regmap_config jc42_regmap_config = {474	.reg_bits = 8,475	.val_bits = 16,476	.val_format_endian = REGMAP_ENDIAN_BIG,477	.max_register = JC42_REG_SMBUS,478	.writeable_reg = jc42_writable_reg,479	.readable_reg = jc42_readable_reg,480	.volatile_reg = jc42_volatile_reg,481	.cache_type = REGCACHE_MAPLE,482};483 484static int jc42_probe(struct i2c_client *client)485{486	struct device *dev = &client->dev;487	struct device *hwmon_dev;488	unsigned int config, cap;489	struct jc42_data *data;490	int ret;491 492	data = devm_kzalloc(dev, sizeof(struct jc42_data), GFP_KERNEL);493	if (!data)494		return -ENOMEM;495 496	data->regmap = devm_regmap_init_i2c(client, &jc42_regmap_config);497	if (IS_ERR(data->regmap))498		return PTR_ERR(data->regmap);499 500	i2c_set_clientdata(client, data);501	mutex_init(&data->update_lock);502 503	ret = regmap_read(data->regmap, JC42_REG_CAP, &cap);504	if (ret)505		return ret;506 507	data->extended = !!(cap & JC42_CAP_RANGE);508 509	if (device_property_read_bool(dev, "smbus-timeout-disable")) {510		/*511		 * Not all chips support this register, but from a512		 * quick read of various datasheets no chip appears513		 * incompatible with the below attempt to disable514		 * the timeout. And the whole thing is opt-in...515		 */516		ret = regmap_set_bits(data->regmap, JC42_REG_SMBUS,517				      SMBUS_STMOUT);518		if (ret)519			return ret;520	}521 522	ret = regmap_read(data->regmap, JC42_REG_CONFIG, &config);523	if (ret)524		return ret;525 526	data->orig_config = config;527	if (config & JC42_CFG_SHUTDOWN) {528		config &= ~JC42_CFG_SHUTDOWN;529		regmap_write(data->regmap, JC42_REG_CONFIG, config);530	}531	data->config = config;532 533	hwmon_dev = devm_hwmon_device_register_with_info(dev, "jc42",534							 data, &jc42_chip_info,535							 NULL);536	return PTR_ERR_OR_ZERO(hwmon_dev);537}538 539static void jc42_remove(struct i2c_client *client)540{541	struct jc42_data *data = i2c_get_clientdata(client);542 543	/* Restore original configuration except hysteresis */544	if ((data->config & ~JC42_CFG_HYST_MASK) !=545	    (data->orig_config & ~JC42_CFG_HYST_MASK)) {546		int config;547 548		config = (data->orig_config & ~JC42_CFG_HYST_MASK)549		  | (data->config & JC42_CFG_HYST_MASK);550		regmap_write(data->regmap, JC42_REG_CONFIG, config);551	}552}553 554#ifdef CONFIG_PM555 556static int jc42_suspend(struct device *dev)557{558	struct jc42_data *data = dev_get_drvdata(dev);559 560	data->config |= JC42_CFG_SHUTDOWN;561	regmap_write(data->regmap, JC42_REG_CONFIG, data->config);562 563	regcache_cache_only(data->regmap, true);564	regcache_mark_dirty(data->regmap);565 566	return 0;567}568 569static int jc42_resume(struct device *dev)570{571	struct jc42_data *data = dev_get_drvdata(dev);572 573	regcache_cache_only(data->regmap, false);574 575	data->config &= ~JC42_CFG_SHUTDOWN;576	regmap_write(data->regmap, JC42_REG_CONFIG, data->config);577 578	/* Restore cached register values to hardware */579	return regcache_sync(data->regmap);580}581 582static const struct dev_pm_ops jc42_dev_pm_ops = {583	.suspend = jc42_suspend,584	.resume = jc42_resume,585};586 587#define JC42_DEV_PM_OPS (&jc42_dev_pm_ops)588#else589#define JC42_DEV_PM_OPS NULL590#endif /* CONFIG_PM */591 592static const struct i2c_device_id jc42_id[] = {593	{ "jc42" },594	{ }595};596MODULE_DEVICE_TABLE(i2c, jc42_id);597 598#ifdef CONFIG_OF599static const struct of_device_id jc42_of_ids[] = {600	{ .compatible = "jedec,jc-42.4-temp", },601	{ }602};603MODULE_DEVICE_TABLE(of, jc42_of_ids);604#endif605 606static struct i2c_driver jc42_driver = {607	.class		= I2C_CLASS_HWMON,608	.driver = {609		.name	= "jc42",610		.pm = JC42_DEV_PM_OPS,611		.of_match_table = of_match_ptr(jc42_of_ids),612	},613	.probe		= jc42_probe,614	.remove		= jc42_remove,615	.id_table	= jc42_id,616	.detect		= jc42_detect,617	.address_list	= normal_i2c,618};619 620module_i2c_driver(jc42_driver);621 622MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");623MODULE_DESCRIPTION("JC42 driver");624MODULE_LICENSE("GPL");625