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

ltc4245.c (12065B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Driver for Linear Technology LTC4245 I2C Multiple Supply Hot Swap Controller
      4 *
      5 * Copyright (C) 2008 Ira W. Snyder <iws@ovro.caltech.edu>
      6 *
      7 * This driver is based on the ds1621 and ina209 drivers.
      8 *
      9 * Datasheet:
     10 * http://www.linear.com/pc/downloadDocument.do?navId=H0,C1,C1003,C1006,C1140,P19392,D13517
     11 */
     12
     13#include <linux/kernel.h>
     14#include <linux/module.h>
     15#include <linux/init.h>
     16#include <linux/bitops.h>
     17#include <linux/err.h>
     18#include <linux/slab.h>
     19#include <linux/i2c.h>
     20#include <linux/hwmon.h>
     21#include <linux/hwmon-sysfs.h>
     22#include <linux/jiffies.h>
     23#include <linux/platform_data/ltc4245.h>
     24
     25/* Here are names of the chip's registers (a.k.a. commands) */
     26enum ltc4245_cmd {
     27	LTC4245_STATUS			= 0x00, /* readonly */
     28	LTC4245_ALERT			= 0x01,
     29	LTC4245_CONTROL			= 0x02,
     30	LTC4245_ON			= 0x03,
     31	LTC4245_FAULT1			= 0x04,
     32	LTC4245_FAULT2			= 0x05,
     33	LTC4245_GPIO			= 0x06,
     34	LTC4245_ADCADR			= 0x07,
     35
     36	LTC4245_12VIN			= 0x10,
     37	LTC4245_12VSENSE		= 0x11,
     38	LTC4245_12VOUT			= 0x12,
     39	LTC4245_5VIN			= 0x13,
     40	LTC4245_5VSENSE			= 0x14,
     41	LTC4245_5VOUT			= 0x15,
     42	LTC4245_3VIN			= 0x16,
     43	LTC4245_3VSENSE			= 0x17,
     44	LTC4245_3VOUT			= 0x18,
     45	LTC4245_VEEIN			= 0x19,
     46	LTC4245_VEESENSE		= 0x1a,
     47	LTC4245_VEEOUT			= 0x1b,
     48	LTC4245_GPIOADC			= 0x1c,
     49};
     50
     51struct ltc4245_data {
     52	struct i2c_client *client;
     53
     54	struct mutex update_lock;
     55	bool valid;
     56	unsigned long last_updated; /* in jiffies */
     57
     58	/* Control registers */
     59	u8 cregs[0x08];
     60
     61	/* Voltage registers */
     62	u8 vregs[0x0d];
     63
     64	/* GPIO ADC registers */
     65	bool use_extra_gpios;
     66	int gpios[3];
     67};
     68
     69/*
     70 * Update the readings from the GPIO pins. If the driver has been configured to
     71 * sample all GPIO's as analog voltages, a round-robin sampling method is used.
     72 * Otherwise, only the configured GPIO pin is sampled.
     73 *
     74 * LOCKING: must hold data->update_lock
     75 */
     76static void ltc4245_update_gpios(struct device *dev)
     77{
     78	struct ltc4245_data *data = dev_get_drvdata(dev);
     79	struct i2c_client *client = data->client;
     80	u8 gpio_curr, gpio_next, gpio_reg;
     81	int i;
     82
     83	/* no extra gpio support, we're basically done */
     84	if (!data->use_extra_gpios) {
     85		data->gpios[0] = data->vregs[LTC4245_GPIOADC - 0x10];
     86		return;
     87	}
     88
     89	/*
     90	 * If the last reading was too long ago, then we mark all old GPIO
     91	 * readings as stale by setting them to -EAGAIN
     92	 */
     93	if (time_after(jiffies, data->last_updated + 5 * HZ)) {
     94		for (i = 0; i < ARRAY_SIZE(data->gpios); i++)
     95			data->gpios[i] = -EAGAIN;
     96	}
     97
     98	/*
     99	 * Get the current GPIO pin
    100	 *
    101	 * The datasheet calls these GPIO[1-3], but we'll calculate the zero
    102	 * based array index instead, and call them GPIO[0-2]. This is much
    103	 * easier to think about.
    104	 */
    105	gpio_curr = (data->cregs[LTC4245_GPIO] & 0xc0) >> 6;
    106	if (gpio_curr > 0)
    107		gpio_curr -= 1;
    108
    109	/* Read the GPIO voltage from the GPIOADC register */
    110	data->gpios[gpio_curr] = data->vregs[LTC4245_GPIOADC - 0x10];
    111
    112	/* Find the next GPIO pin to read */
    113	gpio_next = (gpio_curr + 1) % ARRAY_SIZE(data->gpios);
    114
    115	/*
    116	 * Calculate the correct setting for the GPIO register so it will
    117	 * sample the next GPIO pin
    118	 */
    119	gpio_reg = (data->cregs[LTC4245_GPIO] & 0x3f) | ((gpio_next + 1) << 6);
    120
    121	/* Update the GPIO register */
    122	i2c_smbus_write_byte_data(client, LTC4245_GPIO, gpio_reg);
    123
    124	/* Update saved data */
    125	data->cregs[LTC4245_GPIO] = gpio_reg;
    126}
    127
    128static struct ltc4245_data *ltc4245_update_device(struct device *dev)
    129{
    130	struct ltc4245_data *data = dev_get_drvdata(dev);
    131	struct i2c_client *client = data->client;
    132	s32 val;
    133	int i;
    134
    135	mutex_lock(&data->update_lock);
    136
    137	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
    138
    139		/* Read control registers -- 0x00 to 0x07 */
    140		for (i = 0; i < ARRAY_SIZE(data->cregs); i++) {
    141			val = i2c_smbus_read_byte_data(client, i);
    142			if (unlikely(val < 0))
    143				data->cregs[i] = 0;
    144			else
    145				data->cregs[i] = val;
    146		}
    147
    148		/* Read voltage registers -- 0x10 to 0x1c */
    149		for (i = 0; i < ARRAY_SIZE(data->vregs); i++) {
    150			val = i2c_smbus_read_byte_data(client, i+0x10);
    151			if (unlikely(val < 0))
    152				data->vregs[i] = 0;
    153			else
    154				data->vregs[i] = val;
    155		}
    156
    157		/* Update GPIO readings */
    158		ltc4245_update_gpios(dev);
    159
    160		data->last_updated = jiffies;
    161		data->valid = true;
    162	}
    163
    164	mutex_unlock(&data->update_lock);
    165
    166	return data;
    167}
    168
    169/* Return the voltage from the given register in millivolts */
    170static int ltc4245_get_voltage(struct device *dev, u8 reg)
    171{
    172	struct ltc4245_data *data = ltc4245_update_device(dev);
    173	const u8 regval = data->vregs[reg - 0x10];
    174	u32 voltage = 0;
    175
    176	switch (reg) {
    177	case LTC4245_12VIN:
    178	case LTC4245_12VOUT:
    179		voltage = regval * 55;
    180		break;
    181	case LTC4245_5VIN:
    182	case LTC4245_5VOUT:
    183		voltage = regval * 22;
    184		break;
    185	case LTC4245_3VIN:
    186	case LTC4245_3VOUT:
    187		voltage = regval * 15;
    188		break;
    189	case LTC4245_VEEIN:
    190	case LTC4245_VEEOUT:
    191		voltage = regval * -55;
    192		break;
    193	case LTC4245_GPIOADC:
    194		voltage = regval * 10;
    195		break;
    196	default:
    197		/* If we get here, the developer messed up */
    198		WARN_ON_ONCE(1);
    199		break;
    200	}
    201
    202	return voltage;
    203}
    204
    205/* Return the current in the given sense register in milliAmperes */
    206static unsigned int ltc4245_get_current(struct device *dev, u8 reg)
    207{
    208	struct ltc4245_data *data = ltc4245_update_device(dev);
    209	const u8 regval = data->vregs[reg - 0x10];
    210	unsigned int voltage;
    211	unsigned int curr;
    212
    213	/*
    214	 * The strange looking conversions that follow are fixed-point
    215	 * math, since we cannot do floating point in the kernel.
    216	 *
    217	 * Step 1: convert sense register to microVolts
    218	 * Step 2: convert voltage to milliAmperes
    219	 *
    220	 * If you play around with the V=IR equation, you come up with
    221	 * the following: X uV / Y mOhm == Z mA
    222	 *
    223	 * With the resistors that are fractions of a milliOhm, we multiply
    224	 * the voltage and resistance by 10, to shift the decimal point.
    225	 * Now we can use the normal division operator again.
    226	 */
    227
    228	switch (reg) {
    229	case LTC4245_12VSENSE:
    230		voltage = regval * 250; /* voltage in uV */
    231		curr = voltage / 50; /* sense resistor 50 mOhm */
    232		break;
    233	case LTC4245_5VSENSE:
    234		voltage = regval * 125; /* voltage in uV */
    235		curr = (voltage * 10) / 35; /* sense resistor 3.5 mOhm */
    236		break;
    237	case LTC4245_3VSENSE:
    238		voltage = regval * 125; /* voltage in uV */
    239		curr = (voltage * 10) / 25; /* sense resistor 2.5 mOhm */
    240		break;
    241	case LTC4245_VEESENSE:
    242		voltage = regval * 250; /* voltage in uV */
    243		curr = voltage / 100; /* sense resistor 100 mOhm */
    244		break;
    245	default:
    246		/* If we get here, the developer messed up */
    247		WARN_ON_ONCE(1);
    248		curr = 0;
    249		break;
    250	}
    251
    252	return curr;
    253}
    254
    255/* Map from voltage channel index to voltage register */
    256
    257static const s8 ltc4245_in_regs[] = {
    258	LTC4245_12VIN, LTC4245_5VIN, LTC4245_3VIN, LTC4245_VEEIN,
    259	LTC4245_12VOUT, LTC4245_5VOUT, LTC4245_3VOUT, LTC4245_VEEOUT,
    260};
    261
    262/* Map from current channel index to current register */
    263
    264static const s8 ltc4245_curr_regs[] = {
    265	LTC4245_12VSENSE, LTC4245_5VSENSE, LTC4245_3VSENSE, LTC4245_VEESENSE,
    266};
    267
    268static int ltc4245_read_curr(struct device *dev, u32 attr, int channel,
    269			     long *val)
    270{
    271	struct ltc4245_data *data = ltc4245_update_device(dev);
    272
    273	switch (attr) {
    274	case hwmon_curr_input:
    275		*val = ltc4245_get_current(dev, ltc4245_curr_regs[channel]);
    276		return 0;
    277	case hwmon_curr_max_alarm:
    278		*val = !!(data->cregs[LTC4245_FAULT1] & BIT(channel + 4));
    279		return 0;
    280	default:
    281		return -EOPNOTSUPP;
    282	}
    283}
    284
    285static int ltc4245_read_in(struct device *dev, u32 attr, int channel, long *val)
    286{
    287	struct ltc4245_data *data = ltc4245_update_device(dev);
    288
    289	switch (attr) {
    290	case hwmon_in_input:
    291		if (channel < 8) {
    292			*val = ltc4245_get_voltage(dev,
    293						ltc4245_in_regs[channel]);
    294		} else {
    295			int regval = data->gpios[channel - 8];
    296
    297			if (regval < 0)
    298				return regval;
    299			*val = regval * 10;
    300		}
    301		return 0;
    302	case hwmon_in_min_alarm:
    303		if (channel < 4)
    304			*val = !!(data->cregs[LTC4245_FAULT1] & BIT(channel));
    305		else
    306			*val = !!(data->cregs[LTC4245_FAULT2] &
    307				  BIT(channel - 4));
    308		return 0;
    309	default:
    310		return -EOPNOTSUPP;
    311	}
    312}
    313
    314static int ltc4245_read_power(struct device *dev, u32 attr, int channel,
    315			      long *val)
    316{
    317	unsigned long curr;
    318	long voltage;
    319
    320	switch (attr) {
    321	case hwmon_power_input:
    322		(void)ltc4245_update_device(dev);
    323		curr = ltc4245_get_current(dev, ltc4245_curr_regs[channel]);
    324		voltage = ltc4245_get_voltage(dev, ltc4245_in_regs[channel]);
    325		*val = abs(curr * voltage);
    326		return 0;
    327	default:
    328		return -EOPNOTSUPP;
    329	}
    330}
    331
    332static int ltc4245_read(struct device *dev, enum hwmon_sensor_types type,
    333			u32 attr, int channel, long *val)
    334{
    335
    336	switch (type) {
    337	case hwmon_curr:
    338		return ltc4245_read_curr(dev, attr, channel, val);
    339	case hwmon_power:
    340		return ltc4245_read_power(dev, attr, channel, val);
    341	case hwmon_in:
    342		return ltc4245_read_in(dev, attr, channel - 1, val);
    343	default:
    344		return -EOPNOTSUPP;
    345	}
    346}
    347
    348static umode_t ltc4245_is_visible(const void *_data,
    349				  enum hwmon_sensor_types type,
    350				  u32 attr, int channel)
    351{
    352	const struct ltc4245_data *data = _data;
    353
    354	switch (type) {
    355	case hwmon_in:
    356		if (channel == 0)
    357			return 0;
    358		switch (attr) {
    359		case hwmon_in_input:
    360			if (channel > 9 && !data->use_extra_gpios)
    361				return 0;
    362			return 0444;
    363		case hwmon_in_min_alarm:
    364			if (channel > 8)
    365				return 0;
    366			return 0444;
    367		default:
    368			return 0;
    369		}
    370	case hwmon_curr:
    371		switch (attr) {
    372		case hwmon_curr_input:
    373		case hwmon_curr_max_alarm:
    374			return 0444;
    375		default:
    376			return 0;
    377		}
    378	case hwmon_power:
    379		switch (attr) {
    380		case hwmon_power_input:
    381			return 0444;
    382		default:
    383			return 0;
    384		}
    385	default:
    386		return 0;
    387	}
    388}
    389
    390static const struct hwmon_channel_info *ltc4245_info[] = {
    391	HWMON_CHANNEL_INFO(in,
    392			   HWMON_I_INPUT,
    393			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    394			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    395			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    396			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    397			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    398			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    399			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    400			   HWMON_I_INPUT | HWMON_I_MIN_ALARM,
    401			   HWMON_I_INPUT,
    402			   HWMON_I_INPUT,
    403			   HWMON_I_INPUT),
    404	HWMON_CHANNEL_INFO(curr,
    405			   HWMON_C_INPUT | HWMON_C_MAX_ALARM,
    406			   HWMON_C_INPUT | HWMON_C_MAX_ALARM,
    407			   HWMON_C_INPUT | HWMON_C_MAX_ALARM,
    408			   HWMON_C_INPUT | HWMON_C_MAX_ALARM),
    409	HWMON_CHANNEL_INFO(power,
    410			   HWMON_P_INPUT,
    411			   HWMON_P_INPUT,
    412			   HWMON_P_INPUT,
    413			   HWMON_P_INPUT),
    414	NULL
    415};
    416
    417static const struct hwmon_ops ltc4245_hwmon_ops = {
    418	.is_visible = ltc4245_is_visible,
    419	.read = ltc4245_read,
    420};
    421
    422static const struct hwmon_chip_info ltc4245_chip_info = {
    423	.ops = &ltc4245_hwmon_ops,
    424	.info = ltc4245_info,
    425};
    426
    427static bool ltc4245_use_extra_gpios(struct i2c_client *client)
    428{
    429	struct ltc4245_platform_data *pdata = dev_get_platdata(&client->dev);
    430	struct device_node *np = client->dev.of_node;
    431
    432	/* prefer platform data */
    433	if (pdata)
    434		return pdata->use_extra_gpios;
    435
    436	/* fallback on OF */
    437	if (of_find_property(np, "ltc4245,use-extra-gpios", NULL))
    438		return true;
    439
    440	return false;
    441}
    442
    443static int ltc4245_probe(struct i2c_client *client)
    444{
    445	struct i2c_adapter *adapter = client->adapter;
    446	struct ltc4245_data *data;
    447	struct device *hwmon_dev;
    448
    449	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
    450		return -ENODEV;
    451
    452	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
    453	if (!data)
    454		return -ENOMEM;
    455
    456	data->client = client;
    457	mutex_init(&data->update_lock);
    458	data->use_extra_gpios = ltc4245_use_extra_gpios(client);
    459
    460	/* Initialize the LTC4245 chip */
    461	i2c_smbus_write_byte_data(client, LTC4245_FAULT1, 0x00);
    462	i2c_smbus_write_byte_data(client, LTC4245_FAULT2, 0x00);
    463
    464	hwmon_dev = devm_hwmon_device_register_with_info(&client->dev,
    465							 client->name, data,
    466							 &ltc4245_chip_info,
    467							 NULL);
    468	return PTR_ERR_OR_ZERO(hwmon_dev);
    469}
    470
    471static const struct i2c_device_id ltc4245_id[] = {
    472	{ "ltc4245", 0 },
    473	{ }
    474};
    475MODULE_DEVICE_TABLE(i2c, ltc4245_id);
    476
    477/* This is the driver that will be inserted */
    478static struct i2c_driver ltc4245_driver = {
    479	.driver = {
    480		.name	= "ltc4245",
    481	},
    482	.probe_new	= ltc4245_probe,
    483	.id_table	= ltc4245_id,
    484};
    485
    486module_i2c_driver(ltc4245_driver);
    487
    488MODULE_AUTHOR("Ira W. Snyder <iws@ovro.caltech.edu>");
    489MODULE_DESCRIPTION("LTC4245 driver");
    490MODULE_LICENSE("GPL");