cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

max6621.c (14337B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Hardware monitoring driver for Maxim MAX6621
      4 *
      5 * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
      6 * Copyright (c) 2017 Vadim Pasternak <vadimp@mellanox.com>
      7 */
      8
      9#include <linux/bitops.h>
     10#include <linux/hwmon.h>
     11#include <linux/hwmon-sysfs.h>
     12#include <linux/i2c.h>
     13#include <linux/init.h>
     14#include <linux/module.h>
     15#include <linux/of_device.h>
     16#include <linux/regmap.h>
     17
     18#define MAX6621_DRV_NAME		"max6621"
     19#define MAX6621_TEMP_INPUT_REG_NUM	9
     20#define MAX6621_TEMP_INPUT_MIN		-127000
     21#define MAX6621_TEMP_INPUT_MAX		128000
     22#define MAX6621_TEMP_ALERT_CHAN_SHIFT	1
     23
     24#define MAX6621_TEMP_S0D0_REG		0x00
     25#define MAX6621_TEMP_S0D1_REG		0x01
     26#define MAX6621_TEMP_S1D0_REG		0x02
     27#define MAX6621_TEMP_S1D1_REG		0x03
     28#define MAX6621_TEMP_S2D0_REG		0x04
     29#define MAX6621_TEMP_S2D1_REG		0x05
     30#define MAX6621_TEMP_S3D0_REG		0x06
     31#define MAX6621_TEMP_S3D1_REG		0x07
     32#define MAX6621_TEMP_MAX_REG		0x08
     33#define MAX6621_TEMP_MAX_ADDR_REG	0x0a
     34#define MAX6621_TEMP_ALERT_CAUSE_REG	0x0b
     35#define MAX6621_CONFIG0_REG		0x0c
     36#define MAX6621_CONFIG1_REG		0x0d
     37#define MAX6621_CONFIG2_REG		0x0e
     38#define MAX6621_CONFIG3_REG		0x0f
     39#define MAX6621_TEMP_S0_ALERT_REG	0x10
     40#define MAX6621_TEMP_S1_ALERT_REG	0x11
     41#define MAX6621_TEMP_S2_ALERT_REG	0x12
     42#define MAX6621_TEMP_S3_ALERT_REG	0x13
     43#define MAX6621_CLEAR_ALERT_REG		0x15
     44#define MAX6621_REG_MAX			(MAX6621_CLEAR_ALERT_REG + 1)
     45#define MAX6621_REG_TEMP_SHIFT		0x06
     46
     47#define MAX6621_ENABLE_TEMP_ALERTS_BIT	4
     48#define MAX6621_ENABLE_I2C_CRC_BIT	5
     49#define MAX6621_ENABLE_ALTERNATE_DATA	6
     50#define MAX6621_ENABLE_LOCKUP_TO	7
     51#define MAX6621_ENABLE_S0D0_BIT		8
     52#define MAX6621_ENABLE_S3D1_BIT		15
     53#define MAX6621_ENABLE_TEMP_ALL		GENMASK(MAX6621_ENABLE_S3D1_BIT, \
     54						MAX6621_ENABLE_S0D0_BIT)
     55#define MAX6621_POLL_DELAY_MASK		0x5
     56#define MAX6621_CONFIG0_INIT		(MAX6621_ENABLE_TEMP_ALL | \
     57					 BIT(MAX6621_ENABLE_LOCKUP_TO) | \
     58					 BIT(MAX6621_ENABLE_I2C_CRC_BIT) | \
     59					 MAX6621_POLL_DELAY_MASK)
     60#define MAX6621_PECI_BIT_TIME		0x2
     61#define MAX6621_PECI_RETRY_NUM		0x3
     62#define MAX6621_CONFIG1_INIT		((MAX6621_PECI_BIT_TIME << 8) | \
     63					 MAX6621_PECI_RETRY_NUM)
     64
     65/* Error codes */
     66#define MAX6621_TRAN_FAILED	0x8100	/*
     67					 * PECI transaction failed for more
     68					 * than the configured number of
     69					 * consecutive retries.
     70					 */
     71#define MAX6621_POOL_DIS	0x8101	/*
     72					 * Polling disabled for requested
     73					 * socket/domain.
     74					 */
     75#define MAX6621_POOL_UNCOMPLETE	0x8102	/*
     76					 * First poll not yet completed for
     77					 * requested socket/domain (on
     78					 * startup).
     79					 */
     80#define MAX6621_SD_DIS		0x8103	/*
     81					 * Read maximum temperature requested,
     82					 * but no sockets/domains enabled or
     83					 * all enabled sockets/domains have
     84					 * errors; or read maximum temperature
     85					 * address requested, but read maximum
     86					 * temperature was not called.
     87					 */
     88#define MAX6621_ALERT_DIS	0x8104	/*
     89					 * Get alert socket/domain requested,
     90					 * but no alert active.
     91					 */
     92#define MAX6621_PECI_ERR_MIN	0x8000	/* Intel spec PECI error min value. */
     93#define MAX6621_PECI_ERR_MAX	0x80ff	/* Intel spec PECI error max value. */
     94
     95static const u32 max6621_temp_regs[] = {
     96	MAX6621_TEMP_MAX_REG, MAX6621_TEMP_S0D0_REG, MAX6621_TEMP_S1D0_REG,
     97	MAX6621_TEMP_S2D0_REG, MAX6621_TEMP_S3D0_REG, MAX6621_TEMP_S0D1_REG,
     98	MAX6621_TEMP_S1D1_REG, MAX6621_TEMP_S2D1_REG, MAX6621_TEMP_S3D1_REG,
     99};
    100
    101static const char *const max6621_temp_labels[] = {
    102	"maximum",
    103	"socket0_0",
    104	"socket1_0",
    105	"socket2_0",
    106	"socket3_0",
    107	"socket0_1",
    108	"socket1_1",
    109	"socket2_1",
    110	"socket3_1",
    111};
    112
    113static const int max6621_temp_alert_chan2reg[] = {
    114	MAX6621_TEMP_S0_ALERT_REG,
    115	MAX6621_TEMP_S1_ALERT_REG,
    116	MAX6621_TEMP_S2_ALERT_REG,
    117	MAX6621_TEMP_S3_ALERT_REG,
    118};
    119
    120/**
    121 * struct max6621_data - private data:
    122 *
    123 * @client: I2C client;
    124 * @regmap: register map handle;
    125 * @input_chan2reg: mapping from channel to register;
    126 */
    127struct max6621_data {
    128	struct i2c_client	*client;
    129	struct regmap		*regmap;
    130	int			input_chan2reg[MAX6621_TEMP_INPUT_REG_NUM + 1];
    131};
    132
    133static long max6621_temp_mc2reg(long val)
    134{
    135	return (val / 1000L) << MAX6621_REG_TEMP_SHIFT;
    136}
    137
    138static umode_t
    139max6621_is_visible(const void *data, enum hwmon_sensor_types type, u32 attr,
    140		   int channel)
    141{
    142	/* Skip channels which are not physically conncted. */
    143	if (((struct max6621_data *)data)->input_chan2reg[channel] < 0)
    144		return 0;
    145
    146	switch (type) {
    147	case hwmon_temp:
    148		switch (attr) {
    149		case hwmon_temp_input:
    150		case hwmon_temp_label:
    151		case hwmon_temp_crit_alarm:
    152			return 0444;
    153		case hwmon_temp_offset:
    154		case hwmon_temp_crit:
    155			return 0644;
    156		default:
    157			break;
    158		}
    159		break;
    160	default:
    161		break;
    162	}
    163
    164	return 0;
    165}
    166
    167static int max6621_verify_reg_data(struct device *dev, int regval)
    168{
    169	if (regval >= MAX6621_PECI_ERR_MIN &&
    170	    regval <= MAX6621_PECI_ERR_MAX) {
    171		dev_dbg(dev, "PECI error code - err 0x%04x.\n",
    172			regval);
    173
    174		return -EIO;
    175	}
    176
    177	switch (regval) {
    178	case MAX6621_TRAN_FAILED:
    179		dev_dbg(dev, "PECI transaction failed - err 0x%04x.\n",
    180			regval);
    181		return -EIO;
    182	case MAX6621_POOL_DIS:
    183		dev_dbg(dev, "Polling disabled - err 0x%04x.\n", regval);
    184		return -EOPNOTSUPP;
    185	case MAX6621_POOL_UNCOMPLETE:
    186		dev_dbg(dev, "First poll not completed on startup - err 0x%04x.\n",
    187			regval);
    188		return -EIO;
    189	case MAX6621_SD_DIS:
    190		dev_dbg(dev, "Resource is disabled - err 0x%04x.\n", regval);
    191		return -EOPNOTSUPP;
    192	case MAX6621_ALERT_DIS:
    193		dev_dbg(dev, "No alert active - err 0x%04x.\n", regval);
    194		return -EOPNOTSUPP;
    195	default:
    196		return 0;
    197	}
    198}
    199
    200static int
    201max6621_read(struct device *dev, enum hwmon_sensor_types type, u32 attr,
    202	     int channel, long *val)
    203{
    204	struct max6621_data *data = dev_get_drvdata(dev);
    205	u32 regval;
    206	int reg;
    207	s8 temp;
    208	int ret;
    209
    210	switch (type) {
    211	case hwmon_temp:
    212		switch (attr) {
    213		case hwmon_temp_input:
    214			reg = data->input_chan2reg[channel];
    215			ret = regmap_read(data->regmap, reg, &regval);
    216			if (ret)
    217				return ret;
    218
    219			ret = max6621_verify_reg_data(dev, regval);
    220			if (ret)
    221				return ret;
    222
    223			/*
    224			 * Bit MAX6621_REG_TEMP_SHIFT represents 1 degree step.
    225			 * The temperature is given in two's complement and 8
    226			 * bits is used for the register conversion.
    227			 */
    228			temp = (regval >> MAX6621_REG_TEMP_SHIFT);
    229			*val = temp * 1000L;
    230
    231			break;
    232		case hwmon_temp_offset:
    233			ret = regmap_read(data->regmap, MAX6621_CONFIG2_REG,
    234					  &regval);
    235			if (ret)
    236				return ret;
    237
    238			ret = max6621_verify_reg_data(dev, regval);
    239			if (ret)
    240				return ret;
    241
    242			*val = (regval >> MAX6621_REG_TEMP_SHIFT) *
    243			       1000L;
    244
    245			break;
    246		case hwmon_temp_crit:
    247			channel -= MAX6621_TEMP_ALERT_CHAN_SHIFT;
    248			reg = max6621_temp_alert_chan2reg[channel];
    249			ret = regmap_read(data->regmap, reg, &regval);
    250			if (ret)
    251				return ret;
    252
    253			ret = max6621_verify_reg_data(dev, regval);
    254			if (ret)
    255				return ret;
    256
    257			*val = regval * 1000L;
    258
    259			break;
    260		case hwmon_temp_crit_alarm:
    261			/*
    262			 * Set val to zero to recover the case, when reading
    263			 * MAX6621_TEMP_ALERT_CAUSE_REG results in for example
    264			 * MAX6621_ALERT_DIS. Reading will return with error,
    265			 * but in such case alarm should be returned as 0.
    266			 */
    267			*val = 0;
    268			ret = regmap_read(data->regmap,
    269					  MAX6621_TEMP_ALERT_CAUSE_REG,
    270					  &regval);
    271			if (ret)
    272				return ret;
    273
    274			ret = max6621_verify_reg_data(dev, regval);
    275			if (ret) {
    276				/* Do not report error if alert is disabled. */
    277				if (regval == MAX6621_ALERT_DIS)
    278					return 0;
    279				else
    280					return ret;
    281			}
    282
    283			/*
    284			 * Clear the alert automatically, using send-byte
    285			 * smbus protocol for clearing alert.
    286			 */
    287			if (regval) {
    288				ret = i2c_smbus_write_byte(data->client,
    289						MAX6621_CLEAR_ALERT_REG);
    290				if (ret)
    291					return ret;
    292			}
    293
    294			*val = !!regval;
    295
    296			break;
    297		default:
    298			return -EOPNOTSUPP;
    299		}
    300		break;
    301
    302	default:
    303		return -EOPNOTSUPP;
    304	}
    305
    306	return 0;
    307}
    308
    309static int
    310max6621_write(struct device *dev, enum hwmon_sensor_types type, u32 attr,
    311	      int channel, long val)
    312{
    313	struct max6621_data *data = dev_get_drvdata(dev);
    314	u32 reg;
    315
    316	switch (type) {
    317	case hwmon_temp:
    318		switch (attr) {
    319		case hwmon_temp_offset:
    320			/* Clamp to allowed range to prevent overflow. */
    321			val = clamp_val(val, MAX6621_TEMP_INPUT_MIN,
    322					MAX6621_TEMP_INPUT_MAX);
    323			val = max6621_temp_mc2reg(val);
    324
    325			return regmap_write(data->regmap,
    326					    MAX6621_CONFIG2_REG, val);
    327		case hwmon_temp_crit:
    328			channel -= MAX6621_TEMP_ALERT_CHAN_SHIFT;
    329			reg = max6621_temp_alert_chan2reg[channel];
    330			/* Clamp to allowed range to prevent overflow. */
    331			val = clamp_val(val, MAX6621_TEMP_INPUT_MIN,
    332					MAX6621_TEMP_INPUT_MAX);
    333			val = val / 1000L;
    334
    335			return regmap_write(data->regmap, reg, val);
    336		default:
    337			return -EOPNOTSUPP;
    338		}
    339		break;
    340
    341	default:
    342		return -EOPNOTSUPP;
    343	}
    344
    345	return -EOPNOTSUPP;
    346}
    347
    348static int
    349max6621_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
    350		    int channel, const char **str)
    351{
    352	switch (type) {
    353	case hwmon_temp:
    354		switch (attr) {
    355		case hwmon_temp_label:
    356			*str = max6621_temp_labels[channel];
    357			return 0;
    358		default:
    359			return -EOPNOTSUPP;
    360		}
    361		break;
    362	default:
    363		return -EOPNOTSUPP;
    364	}
    365
    366	return -EOPNOTSUPP;
    367}
    368
    369static bool max6621_writeable_reg(struct device *dev, unsigned int reg)
    370{
    371	switch (reg) {
    372	case MAX6621_CONFIG0_REG:
    373	case MAX6621_CONFIG1_REG:
    374	case MAX6621_CONFIG2_REG:
    375	case MAX6621_CONFIG3_REG:
    376	case MAX6621_TEMP_S0_ALERT_REG:
    377	case MAX6621_TEMP_S1_ALERT_REG:
    378	case MAX6621_TEMP_S2_ALERT_REG:
    379	case MAX6621_TEMP_S3_ALERT_REG:
    380	case MAX6621_TEMP_ALERT_CAUSE_REG:
    381		return true;
    382	}
    383	return false;
    384}
    385
    386static bool max6621_readable_reg(struct device *dev, unsigned int reg)
    387{
    388	switch (reg) {
    389	case MAX6621_TEMP_S0D0_REG:
    390	case MAX6621_TEMP_S0D1_REG:
    391	case MAX6621_TEMP_S1D0_REG:
    392	case MAX6621_TEMP_S1D1_REG:
    393	case MAX6621_TEMP_S2D0_REG:
    394	case MAX6621_TEMP_S2D1_REG:
    395	case MAX6621_TEMP_S3D0_REG:
    396	case MAX6621_TEMP_S3D1_REG:
    397	case MAX6621_TEMP_MAX_REG:
    398	case MAX6621_TEMP_MAX_ADDR_REG:
    399	case MAX6621_CONFIG0_REG:
    400	case MAX6621_CONFIG1_REG:
    401	case MAX6621_CONFIG2_REG:
    402	case MAX6621_CONFIG3_REG:
    403	case MAX6621_TEMP_S0_ALERT_REG:
    404	case MAX6621_TEMP_S1_ALERT_REG:
    405	case MAX6621_TEMP_S2_ALERT_REG:
    406	case MAX6621_TEMP_S3_ALERT_REG:
    407		return true;
    408	}
    409	return false;
    410}
    411
    412static bool max6621_volatile_reg(struct device *dev, unsigned int reg)
    413{
    414	switch (reg) {
    415	case MAX6621_TEMP_S0D0_REG:
    416	case MAX6621_TEMP_S0D1_REG:
    417	case MAX6621_TEMP_S1D0_REG:
    418	case MAX6621_TEMP_S1D1_REG:
    419	case MAX6621_TEMP_S2D0_REG:
    420	case MAX6621_TEMP_S2D1_REG:
    421	case MAX6621_TEMP_S3D0_REG:
    422	case MAX6621_TEMP_S3D1_REG:
    423	case MAX6621_TEMP_MAX_REG:
    424	case MAX6621_TEMP_S0_ALERT_REG:
    425	case MAX6621_TEMP_S1_ALERT_REG:
    426	case MAX6621_TEMP_S2_ALERT_REG:
    427	case MAX6621_TEMP_S3_ALERT_REG:
    428	case MAX6621_TEMP_ALERT_CAUSE_REG:
    429		return true;
    430	}
    431	return false;
    432}
    433
    434static const struct reg_default max6621_regmap_default[] = {
    435	{ MAX6621_CONFIG0_REG, MAX6621_CONFIG0_INIT },
    436	{ MAX6621_CONFIG1_REG, MAX6621_CONFIG1_INIT },
    437};
    438
    439static const struct regmap_config max6621_regmap_config = {
    440	.reg_bits = 8,
    441	.val_bits = 16,
    442	.max_register = MAX6621_REG_MAX,
    443	.val_format_endian = REGMAP_ENDIAN_LITTLE,
    444	.cache_type = REGCACHE_FLAT,
    445	.writeable_reg = max6621_writeable_reg,
    446	.readable_reg = max6621_readable_reg,
    447	.volatile_reg = max6621_volatile_reg,
    448	.reg_defaults = max6621_regmap_default,
    449	.num_reg_defaults = ARRAY_SIZE(max6621_regmap_default),
    450};
    451
    452static const struct hwmon_channel_info *max6621_info[] = {
    453	HWMON_CHANNEL_INFO(chip,
    454			   HWMON_C_REGISTER_TZ),
    455	HWMON_CHANNEL_INFO(temp,
    456			   HWMON_T_INPUT | HWMON_T_LABEL | HWMON_T_OFFSET,
    457			   HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
    458			   HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
    459			   HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
    460			   HWMON_T_INPUT | HWMON_T_CRIT | HWMON_T_CRIT_ALARM | HWMON_T_LABEL,
    461			   HWMON_T_INPUT | HWMON_T_LABEL,
    462			   HWMON_T_INPUT | HWMON_T_LABEL,
    463			   HWMON_T_INPUT | HWMON_T_LABEL,
    464			   HWMON_T_INPUT | HWMON_T_LABEL),
    465	NULL
    466};
    467
    468static const struct hwmon_ops max6621_hwmon_ops = {
    469	.read = max6621_read,
    470	.write = max6621_write,
    471	.read_string = max6621_read_string,
    472	.is_visible = max6621_is_visible,
    473};
    474
    475static const struct hwmon_chip_info max6621_chip_info = {
    476	.ops = &max6621_hwmon_ops,
    477	.info = max6621_info,
    478};
    479
    480static int max6621_probe(struct i2c_client *client)
    481{
    482	struct device *dev = &client->dev;
    483	struct max6621_data *data;
    484	struct device *hwmon_dev;
    485	int i;
    486	int ret;
    487
    488	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
    489	if (!data)
    490		return -ENOMEM;
    491
    492	data->regmap = devm_regmap_init_i2c(client, &max6621_regmap_config);
    493	if (IS_ERR(data->regmap))
    494		return PTR_ERR(data->regmap);
    495
    496	i2c_set_clientdata(client, data);
    497	data->client = client;
    498
    499	/* Set CONFIG0 register masking temperature alerts and PEC. */
    500	ret = regmap_write(data->regmap, MAX6621_CONFIG0_REG,
    501			   MAX6621_CONFIG0_INIT);
    502	if (ret)
    503		return ret;
    504
    505	/* Set CONFIG1 register for PEC access retry number. */
    506	ret = regmap_write(data->regmap, MAX6621_CONFIG1_REG,
    507			   MAX6621_CONFIG1_INIT);
    508	if (ret)
    509		return ret;
    510
    511	/* Sync registers with hardware. */
    512	regcache_mark_dirty(data->regmap);
    513	ret = regcache_sync(data->regmap);
    514	if (ret)
    515		return ret;
    516
    517	/* Verify which temperature input registers are enabled. */
    518	for (i = 0; i < MAX6621_TEMP_INPUT_REG_NUM; i++) {
    519		ret = i2c_smbus_read_word_data(client, max6621_temp_regs[i]);
    520		if (ret < 0)
    521			return ret;
    522		ret = max6621_verify_reg_data(dev, ret);
    523		if (ret) {
    524			data->input_chan2reg[i] = -1;
    525			continue;
    526		}
    527
    528		data->input_chan2reg[i] = max6621_temp_regs[i];
    529	}
    530
    531	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
    532							 data,
    533							 &max6621_chip_info,
    534							 NULL);
    535
    536	return PTR_ERR_OR_ZERO(hwmon_dev);
    537}
    538
    539static const struct i2c_device_id max6621_id[] = {
    540	{ MAX6621_DRV_NAME, 0 },
    541	{ }
    542};
    543MODULE_DEVICE_TABLE(i2c, max6621_id);
    544
    545static const struct of_device_id __maybe_unused max6621_of_match[] = {
    546	{ .compatible = "maxim,max6621" },
    547	{ }
    548};
    549MODULE_DEVICE_TABLE(of, max6621_of_match);
    550
    551static struct i2c_driver max6621_driver = {
    552	.class		= I2C_CLASS_HWMON,
    553	.driver = {
    554		.name = MAX6621_DRV_NAME,
    555		.of_match_table = of_match_ptr(max6621_of_match),
    556	},
    557	.probe_new	= max6621_probe,
    558	.id_table	= max6621_id,
    559};
    560
    561module_i2c_driver(max6621_driver);
    562
    563MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
    564MODULE_DESCRIPTION("Driver for Maxim MAX6621");
    565MODULE_LICENSE("GPL");