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

powr1220.c (7322B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * powr1220.c - Driver for the Lattice POWR1220 programmable power supply
      4 * and monitor. Users can read all ADC inputs along with their labels
      5 * using the sysfs nodes.
      6 *
      7 * Copyright (c) 2014 Echo360 https://www.echo360.com
      8 * Scott Kanowitz <skanowitz@echo360.com> <scott.kanowitz@gmail.com>
      9 */
     10
     11#include <linux/module.h>
     12#include <linux/init.h>
     13#include <linux/slab.h>
     14#include <linux/jiffies.h>
     15#include <linux/i2c.h>
     16#include <linux/hwmon.h>
     17#include <linux/hwmon-sysfs.h>
     18#include <linux/err.h>
     19#include <linux/mutex.h>
     20#include <linux/delay.h>
     21
     22#define ADC_STEP_MV			2
     23#define ADC_MAX_LOW_MEASUREMENT_MV	2000
     24
     25enum powr1xxx_chips { powr1014, powr1220 };
     26
     27enum powr1220_regs {
     28	VMON_STATUS0,
     29	VMON_STATUS1,
     30	VMON_STATUS2,
     31	OUTPUT_STATUS0,
     32	OUTPUT_STATUS1,
     33	OUTPUT_STATUS2,
     34	INPUT_STATUS,
     35	ADC_VALUE_LOW,
     36	ADC_VALUE_HIGH,
     37	ADC_MUX,
     38	UES_BYTE0,
     39	UES_BYTE1,
     40	UES_BYTE2,
     41	UES_BYTE3,
     42	GP_OUTPUT1,
     43	GP_OUTPUT2,
     44	GP_OUTPUT3,
     45	INPUT_VALUE,
     46	RESET,
     47	TRIM1_TRIM,
     48	TRIM2_TRIM,
     49	TRIM3_TRIM,
     50	TRIM4_TRIM,
     51	TRIM5_TRIM,
     52	TRIM6_TRIM,
     53	TRIM7_TRIM,
     54	TRIM8_TRIM,
     55	MAX_POWR1220_REGS
     56};
     57
     58enum powr1220_adc_values {
     59	VMON1,
     60	VMON2,
     61	VMON3,
     62	VMON4,
     63	VMON5,
     64	VMON6,
     65	VMON7,
     66	VMON8,
     67	VMON9,
     68	VMON10,
     69	VMON11,
     70	VMON12,
     71	VCCA,
     72	VCCINP,
     73	MAX_POWR1220_ADC_VALUES
     74};
     75
     76struct powr1220_data {
     77	struct i2c_client *client;
     78	struct mutex update_lock;
     79	u8 max_channels;
     80	bool adc_valid[MAX_POWR1220_ADC_VALUES];
     81	 /* the next value is in jiffies */
     82	unsigned long adc_last_updated[MAX_POWR1220_ADC_VALUES];
     83
     84	/* values */
     85	int adc_maxes[MAX_POWR1220_ADC_VALUES];
     86	int adc_values[MAX_POWR1220_ADC_VALUES];
     87};
     88
     89static const char * const input_names[] = {
     90	[VMON1]    = "vmon1",
     91	[VMON2]    = "vmon2",
     92	[VMON3]    = "vmon3",
     93	[VMON4]    = "vmon4",
     94	[VMON5]    = "vmon5",
     95	[VMON6]    = "vmon6",
     96	[VMON7]    = "vmon7",
     97	[VMON8]    = "vmon8",
     98	[VMON9]    = "vmon9",
     99	[VMON10]   = "vmon10",
    100	[VMON11]   = "vmon11",
    101	[VMON12]   = "vmon12",
    102	[VCCA]     = "vcca",
    103	[VCCINP]   = "vccinp",
    104};
    105
    106/* Reads the specified ADC channel */
    107static int powr1220_read_adc(struct device *dev, int ch_num)
    108{
    109	struct powr1220_data *data = dev_get_drvdata(dev);
    110	int reading;
    111	int result;
    112	int adc_range = 0;
    113
    114	mutex_lock(&data->update_lock);
    115
    116	if (time_after(jiffies, data->adc_last_updated[ch_num] + HZ) ||
    117	    !data->adc_valid[ch_num]) {
    118		/*
    119		 * figure out if we need to use the attenuator for
    120		 * high inputs or inputs that we don't yet have a measurement
    121		 * for. We dynamically set the attenuator depending on the
    122		 * max reading.
    123		 */
    124		if (data->adc_maxes[ch_num] > ADC_MAX_LOW_MEASUREMENT_MV ||
    125		    data->adc_maxes[ch_num] == 0)
    126			adc_range = 1 << 4;
    127
    128		/* set the attenuator and mux */
    129		result = i2c_smbus_write_byte_data(data->client, ADC_MUX,
    130						   adc_range | ch_num);
    131		if (result)
    132			goto exit;
    133
    134		/*
    135		 * wait at least Tconvert time (200 us) for the
    136		 * conversion to complete
    137		 */
    138		udelay(200);
    139
    140		/* get the ADC reading */
    141		result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_LOW);
    142		if (result < 0)
    143			goto exit;
    144
    145		reading = result >> 4;
    146
    147		/* get the upper half of the reading */
    148		result = i2c_smbus_read_byte_data(data->client, ADC_VALUE_HIGH);
    149		if (result < 0)
    150			goto exit;
    151
    152		reading |= result << 4;
    153
    154		/* now convert the reading to a voltage */
    155		reading *= ADC_STEP_MV;
    156		data->adc_values[ch_num] = reading;
    157		data->adc_valid[ch_num] = true;
    158		data->adc_last_updated[ch_num] = jiffies;
    159		result = reading;
    160
    161		if (reading > data->adc_maxes[ch_num])
    162			data->adc_maxes[ch_num] = reading;
    163	} else {
    164		result = data->adc_values[ch_num];
    165	}
    166
    167exit:
    168	mutex_unlock(&data->update_lock);
    169
    170	return result;
    171}
    172
    173static umode_t
    174powr1220_is_visible(const void *data, enum hwmon_sensor_types type, u32
    175		    attr, int channel)
    176{
    177	struct powr1220_data *chip_data = (struct powr1220_data *)data;
    178
    179	if (channel >= chip_data->max_channels)
    180		return 0;
    181
    182	switch (type) {
    183	case hwmon_in:
    184		switch (attr) {
    185		case hwmon_in_input:
    186		case hwmon_in_highest:
    187		case hwmon_in_label:
    188			return 0444;
    189		default:
    190			break;
    191		}
    192		break;
    193	default:
    194		break;
    195	}
    196
    197	return 0;
    198}
    199
    200static int
    201powr1220_read_string(struct device *dev, enum hwmon_sensor_types type, u32 attr,
    202		     int channel, const char **str)
    203{
    204	switch (type) {
    205	case hwmon_in:
    206		switch (attr) {
    207		case hwmon_in_label:
    208			*str = input_names[channel];
    209			return 0;
    210		default:
    211			return -EOPNOTSUPP;
    212		}
    213		break;
    214	default:
    215		return -EOPNOTSUPP;
    216	}
    217
    218	return -EOPNOTSUPP;
    219}
    220
    221static int
    222powr1220_read(struct device *dev, enum hwmon_sensor_types type, u32
    223	      attr, int channel, long *val)
    224{
    225	struct powr1220_data *data = dev_get_drvdata(dev);
    226	int ret;
    227
    228	switch (type) {
    229	case hwmon_in:
    230		switch (attr) {
    231		case hwmon_in_input:
    232			ret = powr1220_read_adc(dev, channel);
    233			if (ret < 0)
    234				return ret;
    235			*val = ret;
    236			break;
    237		case hwmon_in_highest:
    238			*val = data->adc_maxes[channel];
    239			break;
    240		default:
    241			return -EOPNOTSUPP;
    242		}
    243		break;
    244	default:
    245		return -EOPNOTSUPP;
    246}
    247
    248	return 0;
    249}
    250
    251static const struct hwmon_channel_info *powr1220_info[] = {
    252	HWMON_CHANNEL_INFO(in,
    253			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    254			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    255			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    256			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    257			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    258			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    259			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    260			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    261			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    262			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    263			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    264			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    265			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL,
    266			   HWMON_I_INPUT | HWMON_I_HIGHEST | HWMON_I_LABEL),
    267
    268	NULL
    269};
    270
    271static const struct hwmon_ops powr1220_hwmon_ops = {
    272	.read = powr1220_read,
    273	.read_string = powr1220_read_string,
    274	.is_visible = powr1220_is_visible,
    275};
    276
    277static const struct hwmon_chip_info powr1220_chip_info = {
    278	.ops = &powr1220_hwmon_ops,
    279	.info = powr1220_info,
    280};
    281
    282static const struct i2c_device_id powr1220_ids[];
    283
    284static int powr1220_probe(struct i2c_client *client)
    285{
    286	struct powr1220_data *data;
    287	struct device *hwmon_dev;
    288
    289	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    290		return -ENODEV;
    291
    292	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
    293	if (!data)
    294		return -ENOMEM;
    295
    296	switch (i2c_match_id(powr1220_ids, client)->driver_data) {
    297	case powr1014:
    298		data->max_channels = 10;
    299		break;
    300	default:
    301		data->max_channels = 12;
    302		break;
    303	}
    304
    305	mutex_init(&data->update_lock);
    306	data->client = client;
    307
    308	hwmon_dev = devm_hwmon_device_register_with_info(&client->dev,
    309							 client->name,
    310							 data,
    311							 &powr1220_chip_info,
    312							 NULL);
    313
    314	return PTR_ERR_OR_ZERO(hwmon_dev);
    315}
    316
    317static const struct i2c_device_id powr1220_ids[] = {
    318	{ "powr1014", powr1014, },
    319	{ "powr1220", powr1220, },
    320	{ }
    321};
    322
    323MODULE_DEVICE_TABLE(i2c, powr1220_ids);
    324
    325static struct i2c_driver powr1220_driver = {
    326	.class		= I2C_CLASS_HWMON,
    327	.driver = {
    328		.name	= "powr1220",
    329	},
    330	.probe_new	= powr1220_probe,
    331	.id_table	= powr1220_ids,
    332};
    333
    334module_i2c_driver(powr1220_driver);
    335
    336MODULE_AUTHOR("Scott Kanowitz");
    337MODULE_DESCRIPTION("POWR1220 driver");
    338MODULE_LICENSE("GPL");