brintos

brintos / linux-shallow public Read only

0
0
Text · 13.3 KiB · c36c124 Raw
573 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Hardware monitoring driver for LM25056 / LM25066 / LM5064 / LM50664 *5 * Copyright (c) 2011 Ericsson AB.6 * Copyright (c) 2013 Guenter Roeck7 */8 9#include <linux/bitops.h>10#include <linux/kernel.h>11#include <linux/module.h>12#include <linux/init.h>13#include <linux/err.h>14#include <linux/slab.h>15#include <linux/i2c.h>16#include <linux/log2.h>17#include <linux/of.h>18#include "pmbus.h"19 20enum chips { lm25056, lm25066, lm5064, lm5066, lm5066i };21 22#define LM25066_READ_VAUX		0xd023#define LM25066_MFR_READ_IIN		0xd124#define LM25066_MFR_READ_PIN		0xd225#define LM25066_MFR_IIN_OC_WARN_LIMIT	0xd326#define LM25066_MFR_PIN_OP_WARN_LIMIT	0xd427#define LM25066_READ_PIN_PEAK		0xd528#define LM25066_CLEAR_PIN_PEAK		0xd629#define LM25066_DEVICE_SETUP		0xd930#define LM25066_READ_AVG_VIN		0xdc31#define LM25066_SAMPLES_FOR_AVG		0xdb32#define LM25066_READ_AVG_VOUT		0xdd33#define LM25066_READ_AVG_IIN		0xde34#define LM25066_READ_AVG_PIN		0xdf35 36#define LM25066_DEV_SETUP_CL		BIT(4)	/* Current limit */37 38#define LM25066_SAMPLES_FOR_AVG_MAX	409639 40/* LM25056 only */41 42#define LM25056_VAUX_OV_WARN_LIMIT	0xe343#define LM25056_VAUX_UV_WARN_LIMIT	0xe444 45#define LM25056_MFR_STS_VAUX_OV_WARN	BIT(1)46#define LM25056_MFR_STS_VAUX_UV_WARN	BIT(0)47 48struct __coeff {49	short m, b, R;50};51 52#define PSC_CURRENT_IN_L	(PSC_NUM_CLASSES)53#define PSC_POWER_L		(PSC_NUM_CLASSES + 1)54 55static const struct __coeff lm25066_coeff[][PSC_NUM_CLASSES + 2] = {56	[lm25056] = {57		[PSC_VOLTAGE_IN] = {58			.m = 16296,59			.b = 1343,60			.R = -2,61		},62		[PSC_CURRENT_IN] = {63			.m = 13797,64			.b = -1833,65			.R = -2,66		},67		[PSC_CURRENT_IN_L] = {68			.m = 6726,69			.b = -537,70			.R = -2,71		},72		[PSC_POWER] = {73			.m = 5501,74			.b = -2908,75			.R = -3,76		},77		[PSC_POWER_L] = {78			.m = 26882,79			.b = -5646,80			.R = -4,81		},82		[PSC_TEMPERATURE] = {83			.m = 1580,84			.b = -14500,85			.R = -2,86		},87	},88	[lm25066] = {89		[PSC_VOLTAGE_IN] = {90			.m = 22070,91			.b = -1800,92			.R = -2,93		},94		[PSC_VOLTAGE_OUT] = {95			.m = 22070,96			.b = -1800,97			.R = -2,98		},99		[PSC_CURRENT_IN] = {100			.m = 13661,101			.b = -5200,102			.R = -2,103		},104		[PSC_CURRENT_IN_L] = {105			.m = 6854,106			.b = -3100,107			.R = -2,108		},109		[PSC_POWER] = {110			.m = 736,111			.b = -3300,112			.R = -2,113		},114		[PSC_POWER_L] = {115			.m = 369,116			.b = -1900,117			.R = -2,118		},119		[PSC_TEMPERATURE] = {120			.m = 16,121		},122	},123	[lm5064] = {124		[PSC_VOLTAGE_IN] = {125			.m = 4611,126			.b = -642,127			.R = -2,128		},129		[PSC_VOLTAGE_OUT] = {130			.m = 4621,131			.b = 423,132			.R = -2,133		},134		[PSC_CURRENT_IN] = {135			.m = 10742,136			.b = 1552,137			.R = -2,138		},139		[PSC_CURRENT_IN_L] = {140			.m = 5456,141			.b = 2118,142			.R = -2,143		},144		[PSC_POWER] = {145			.m = 1204,146			.b = 8524,147			.R = -3,148		},149		[PSC_POWER_L] = {150			.m = 612,151			.b = 11202,152			.R = -3,153		},154		[PSC_TEMPERATURE] = {155			.m = 16,156		},157	},158	[lm5066] = {159		[PSC_VOLTAGE_IN] = {160			.m = 4587,161			.b = -1200,162			.R = -2,163		},164		[PSC_VOLTAGE_OUT] = {165			.m = 4587,166			.b = -2400,167			.R = -2,168		},169		[PSC_CURRENT_IN] = {170			.m = 10753,171			.b = -1200,172			.R = -2,173		},174		[PSC_CURRENT_IN_L] = {175			.m = 5405,176			.b = -600,177			.R = -2,178		},179		[PSC_POWER] = {180			.m = 1204,181			.b = -6000,182			.R = -3,183		},184		[PSC_POWER_L] = {185			.m = 605,186			.b = -8000,187			.R = -3,188		},189		[PSC_TEMPERATURE] = {190			.m = 16,191		},192	},193	[lm5066i] = {194		[PSC_VOLTAGE_IN] = {195			.m = 4617,196			.b = -140,197			.R = -2,198		},199		[PSC_VOLTAGE_OUT] = {200			.m = 4602,201			.b = 500,202			.R = -2,203		},204		[PSC_CURRENT_IN] = {205			.m = 15076,206			.b = -504,207			.R = -2,208		},209		[PSC_CURRENT_IN_L] = {210			.m = 7645,211			.b = 100,212			.R = -2,213		},214		[PSC_POWER] = {215			.m = 1701,216			.b = -4000,217			.R = -3,218		},219		[PSC_POWER_L] = {220			.m = 861,221			.b = -965,222			.R = -3,223		},224		[PSC_TEMPERATURE] = {225			.m = 16,226		},227	},228};229 230struct lm25066_data {231	int id;232	u16 rlimit;			/* Maximum register value */233	struct pmbus_driver_info info;234};235 236#define to_lm25066_data(x)  container_of(x, struct lm25066_data, info)237 238static int lm25066_read_word_data(struct i2c_client *client, int page,239				  int phase, int reg)240{241	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);242	const struct lm25066_data *data = to_lm25066_data(info);243	int ret;244 245	switch (reg) {246	case PMBUS_VIRT_READ_VMON:247		ret = pmbus_read_word_data(client, 0, 0xff, LM25066_READ_VAUX);248		if (ret < 0)249			break;250		/* Adjust returned value to match VIN coefficients */251		switch (data->id) {252		case lm25056:253			/* VIN: 6.14 mV VAUX: 293 uV LSB */254			ret = DIV_ROUND_CLOSEST(ret * 293, 6140);255			break;256		case lm25066:257			/* VIN: 4.54 mV VAUX: 283.2 uV LSB */258			ret = DIV_ROUND_CLOSEST(ret * 2832, 45400);259			break;260		case lm5064:261			/* VIN: 4.53 mV VAUX: 700 uV LSB */262			ret = DIV_ROUND_CLOSEST(ret * 70, 453);263			break;264		case lm5066:265		case lm5066i:266			/* VIN: 2.18 mV VAUX: 725 uV LSB */267			ret = DIV_ROUND_CLOSEST(ret * 725, 2180);268			break;269		}270		break;271	case PMBUS_READ_IIN:272		ret = pmbus_read_word_data(client, 0, 0xff,273					   LM25066_MFR_READ_IIN);274		break;275	case PMBUS_READ_PIN:276		ret = pmbus_read_word_data(client, 0, 0xff,277					   LM25066_MFR_READ_PIN);278		break;279	case PMBUS_IIN_OC_WARN_LIMIT:280		ret = pmbus_read_word_data(client, 0, 0xff,281					   LM25066_MFR_IIN_OC_WARN_LIMIT);282		break;283	case PMBUS_PIN_OP_WARN_LIMIT:284		ret = pmbus_read_word_data(client, 0, 0xff,285					   LM25066_MFR_PIN_OP_WARN_LIMIT);286		break;287	case PMBUS_VIRT_READ_VIN_AVG:288		ret = pmbus_read_word_data(client, 0, 0xff,289					   LM25066_READ_AVG_VIN);290		break;291	case PMBUS_VIRT_READ_VOUT_AVG:292		ret = pmbus_read_word_data(client, 0, 0xff,293					   LM25066_READ_AVG_VOUT);294		break;295	case PMBUS_VIRT_READ_IIN_AVG:296		ret = pmbus_read_word_data(client, 0, 0xff,297					   LM25066_READ_AVG_IIN);298		break;299	case PMBUS_VIRT_READ_PIN_AVG:300		ret = pmbus_read_word_data(client, 0, 0xff,301					   LM25066_READ_AVG_PIN);302		break;303	case PMBUS_VIRT_READ_PIN_MAX:304		ret = pmbus_read_word_data(client, 0, 0xff,305					   LM25066_READ_PIN_PEAK);306		break;307	case PMBUS_VIRT_RESET_PIN_HISTORY:308		ret = 0;309		break;310	case PMBUS_VIRT_SAMPLES:311		ret = pmbus_read_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG);312		if (ret < 0)313			break;314		ret = 1 << ret;315		break;316	default:317		ret = -ENODATA;318		break;319	}320	return ret;321}322 323static int lm25056_read_word_data(struct i2c_client *client, int page,324				  int phase, int reg)325{326	int ret;327 328	switch (reg) {329	case PMBUS_VIRT_VMON_UV_WARN_LIMIT:330		ret = pmbus_read_word_data(client, 0, 0xff,331					   LM25056_VAUX_UV_WARN_LIMIT);332		if (ret < 0)333			break;334		/* Adjust returned value to match VIN coefficients */335		ret = DIV_ROUND_CLOSEST(ret * 293, 6140);336		break;337	case PMBUS_VIRT_VMON_OV_WARN_LIMIT:338		ret = pmbus_read_word_data(client, 0, 0xff,339					   LM25056_VAUX_OV_WARN_LIMIT);340		if (ret < 0)341			break;342		/* Adjust returned value to match VIN coefficients */343		ret = DIV_ROUND_CLOSEST(ret * 293, 6140);344		break;345	default:346		ret = lm25066_read_word_data(client, page, phase, reg);347		break;348	}349	return ret;350}351 352static int lm25056_read_byte_data(struct i2c_client *client, int page, int reg)353{354	int ret, s;355 356	switch (reg) {357	case PMBUS_VIRT_STATUS_VMON:358		ret = pmbus_read_byte_data(client, 0,359					   PMBUS_STATUS_MFR_SPECIFIC);360		if (ret < 0)361			break;362		s = 0;363		if (ret & LM25056_MFR_STS_VAUX_UV_WARN)364			s |= PB_VOLTAGE_UV_WARNING;365		if (ret & LM25056_MFR_STS_VAUX_OV_WARN)366			s |= PB_VOLTAGE_OV_WARNING;367		ret = s;368		break;369	default:370		ret = -ENODATA;371		break;372	}373	return ret;374}375 376static int lm25066_write_word_data(struct i2c_client *client, int page, int reg,377				   u16 word)378{379	const struct pmbus_driver_info *info = pmbus_get_driver_info(client);380	const struct lm25066_data *data = to_lm25066_data(info);381	int ret;382 383	switch (reg) {384	case PMBUS_POUT_OP_FAULT_LIMIT:385	case PMBUS_POUT_OP_WARN_LIMIT:386	case PMBUS_VOUT_UV_WARN_LIMIT:387	case PMBUS_OT_FAULT_LIMIT:388	case PMBUS_OT_WARN_LIMIT:389	case PMBUS_IIN_OC_FAULT_LIMIT:390	case PMBUS_VIN_UV_WARN_LIMIT:391	case PMBUS_VIN_UV_FAULT_LIMIT:392	case PMBUS_VIN_OV_FAULT_LIMIT:393	case PMBUS_VIN_OV_WARN_LIMIT:394		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);395		ret = pmbus_write_word_data(client, 0, reg, word);396		break;397	case PMBUS_IIN_OC_WARN_LIMIT:398		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);399		ret = pmbus_write_word_data(client, 0,400					    LM25066_MFR_IIN_OC_WARN_LIMIT,401					    word);402		break;403	case PMBUS_PIN_OP_WARN_LIMIT:404		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);405		ret = pmbus_write_word_data(client, 0,406					    LM25066_MFR_PIN_OP_WARN_LIMIT,407					    word);408		break;409	case PMBUS_VIRT_VMON_UV_WARN_LIMIT:410		/* Adjust from VIN coefficients (for LM25056) */411		word = DIV_ROUND_CLOSEST((int)word * 6140, 293);412		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);413		ret = pmbus_write_word_data(client, 0,414					    LM25056_VAUX_UV_WARN_LIMIT, word);415		break;416	case PMBUS_VIRT_VMON_OV_WARN_LIMIT:417		/* Adjust from VIN coefficients (for LM25056) */418		word = DIV_ROUND_CLOSEST((int)word * 6140, 293);419		word = ((s16)word < 0) ? 0 : clamp_val(word, 0, data->rlimit);420		ret = pmbus_write_word_data(client, 0,421					    LM25056_VAUX_OV_WARN_LIMIT, word);422		break;423	case PMBUS_VIRT_RESET_PIN_HISTORY:424		ret = pmbus_write_byte(client, 0, LM25066_CLEAR_PIN_PEAK);425		break;426	case PMBUS_VIRT_SAMPLES:427		word = clamp_val(word, 1, LM25066_SAMPLES_FOR_AVG_MAX);428		ret = pmbus_write_byte_data(client, 0, LM25066_SAMPLES_FOR_AVG,429					    ilog2(word));430		break;431	default:432		ret = -ENODATA;433		break;434	}435	return ret;436}437 438#if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)439static const struct regulator_desc lm25066_reg_desc[] = {440	PMBUS_REGULATOR_ONE("vout"),441};442#endif443 444static const struct i2c_device_id lm25066_id[] = {445	{"lm25056", lm25056},446	{"lm25066", lm25066},447	{"lm5064", lm5064},448	{"lm5066", lm5066},449	{"lm5066i", lm5066i},450	{ }451};452MODULE_DEVICE_TABLE(i2c, lm25066_id);453 454static const struct of_device_id __maybe_unused lm25066_of_match[] = {455	{ .compatible = "ti,lm25056", .data = (void *)lm25056, },456	{ .compatible = "ti,lm25066", .data = (void *)lm25066, },457	{ .compatible = "ti,lm5064",  .data = (void *)lm5064,  },458	{ .compatible = "ti,lm5066",  .data = (void *)lm5066,  },459	{ .compatible = "ti,lm5066i", .data = (void *)lm5066i, },460	{ },461};462MODULE_DEVICE_TABLE(of, lm25066_of_match);463 464static int lm25066_probe(struct i2c_client *client)465{466	int config;467	u32 shunt;468	struct lm25066_data *data;469	struct pmbus_driver_info *info;470	const struct __coeff *coeff;471 472	if (!i2c_check_functionality(client->adapter,473				     I2C_FUNC_SMBUS_READ_BYTE_DATA))474		return -ENODEV;475 476	data = devm_kzalloc(&client->dev, sizeof(struct lm25066_data),477			    GFP_KERNEL);478	if (!data)479		return -ENOMEM;480 481	config = i2c_smbus_read_byte_data(client, LM25066_DEVICE_SETUP);482	if (config < 0)483		return config;484 485	data->id = (enum chips)(unsigned long)i2c_get_match_data(client);486 487	info = &data->info;488 489	info->pages = 1;490	info->format[PSC_VOLTAGE_IN] = direct;491	info->format[PSC_VOLTAGE_OUT] = direct;492	info->format[PSC_CURRENT_IN] = direct;493	info->format[PSC_TEMPERATURE] = direct;494	info->format[PSC_POWER] = direct;495 496	info->func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_VMON497	  | PMBUS_HAVE_PIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT498	  | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP | PMBUS_HAVE_SAMPLES;499 500	if (data->id == lm25056) {501		info->func[0] |= PMBUS_HAVE_STATUS_VMON;502		info->read_word_data = lm25056_read_word_data;503		info->read_byte_data = lm25056_read_byte_data;504		data->rlimit = 0x0fff;505	} else {506		info->func[0] |= PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT;507		info->read_word_data = lm25066_read_word_data;508		data->rlimit = 0x0fff;509	}510	info->write_word_data = lm25066_write_word_data;511 512	coeff = &lm25066_coeff[data->id][0];513	info->m[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].m;514	info->b[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].b;515	info->R[PSC_TEMPERATURE] = coeff[PSC_TEMPERATURE].R;516	info->m[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].m;517	info->b[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].b;518	info->R[PSC_VOLTAGE_IN] = coeff[PSC_VOLTAGE_IN].R;519	info->m[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].m;520	info->b[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].b;521	info->R[PSC_VOLTAGE_OUT] = coeff[PSC_VOLTAGE_OUT].R;522	info->R[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].R;523	info->R[PSC_POWER] = coeff[PSC_POWER].R;524	if (config & LM25066_DEV_SETUP_CL) {525		info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].m;526		info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN_L].b;527		info->m[PSC_POWER] = coeff[PSC_POWER_L].m;528		info->b[PSC_POWER] = coeff[PSC_POWER_L].b;529	} else {530		info->m[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].m;531		info->b[PSC_CURRENT_IN] = coeff[PSC_CURRENT_IN].b;532		info->m[PSC_POWER] = coeff[PSC_POWER].m;533		info->b[PSC_POWER] = coeff[PSC_POWER].b;534	}535 536	/*537	 * Values in the TI datasheets are normalized for a 1mOhm sense538	 * resistor; assume that unless DT specifies a value explicitly.539	 */540	if (of_property_read_u32(client->dev.of_node, "shunt-resistor-micro-ohms", &shunt))541		shunt = 1000;542 543	info->m[PSC_CURRENT_IN] = info->m[PSC_CURRENT_IN] * shunt / 1000;544	info->m[PSC_POWER] = info->m[PSC_POWER] * shunt / 1000;545 546#if IS_ENABLED(CONFIG_SENSORS_LM25066_REGULATOR)547	/* LM25056 doesn't support OPERATION */548	if (data->id != lm25056) {549		info->num_regulators = ARRAY_SIZE(lm25066_reg_desc);550		info->reg_desc = lm25066_reg_desc;551	}552#endif553 554	return pmbus_do_probe(client, info);555}556 557/* This is the driver that will be inserted */558static struct i2c_driver lm25066_driver = {559	.driver = {560		   .name = "lm25066",561		   .of_match_table = of_match_ptr(lm25066_of_match),562	},563	.probe = lm25066_probe,564	.id_table = lm25066_id,565};566 567module_i2c_driver(lm25066_driver);568 569MODULE_AUTHOR("Guenter Roeck");570MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");571MODULE_LICENSE("GPL");572MODULE_IMPORT_NS(PMBUS);573