File Index
Files and directories
Sign in
FILE

tps25990.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hwmon/pmbus/tps25990.c C
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// Copyright (c) 2024 BayLibre, SAS.
  4// Author: Jerome Brunet <jbrunet@baylibre.com>
  5
  6#include <linux/bitfield.h>
  7#include <linux/debugfs.h>
  8#include <linux/err.h>
  9#include <linux/hwmon-sysfs.h>
 10#include <linux/i2c.h>
 11#include <linux/init.h>
 12#include <linux/kernel.h>
 13#include <linux/module.h>
 14
 15#include "pmbus.h"
 16
 17#define TPS25990_READ_VAUX		0xd0
 18#define TPS25990_READ_VIN_MIN		0xd1
 19#define TPS25990_READ_VIN_PEAK		0xd2
 20#define TPS25990_READ_IIN_PEAK		0xd4
 21#define TPS25990_READ_PIN_PEAK		0xd5
 22#define TPS25990_READ_TEMP_AVG		0xd6
 23#define TPS25990_READ_TEMP_PEAK		0xd7
 24#define TPS25990_READ_VOUT_MIN		0xda
 25#define TPS25990_READ_VIN_AVG		0xdc
 26#define TPS25990_READ_VOUT_AVG		0xdd
 27#define TPS25990_READ_IIN_AVG		0xde
 28#define TPS25990_READ_PIN_AVG		0xdf
 29#define TPS25990_VIREF			0xe0
 30#define TPS25990_PK_MIN_AVG		0xea
 31#define  PK_MIN_AVG_RST_PEAK		BIT(7)
 32#define  PK_MIN_AVG_RST_AVG		BIT(6)
 33#define  PK_MIN_AVG_RST_MIN		BIT(5)
 34#define  PK_MIN_AVG_AVG_CNT		GENMASK(2, 0)
 35#define TPS25990_MFR_WRITE_PROTECT	0xf8
 36#define  TPS25990_UNLOCKED		BIT(7)
 37
 38#define TPS25990_8B_SHIFT		2
 39#define TPS25990_VIN_OVF_NUM		525100
 40#define TPS25990_VIN_OVF_DIV		10163
 41#define TPS25990_VIN_OVF_OFF		155
 42#define TPS25990_IIN_OCF_NUM		953800
 43#define TPS25990_IIN_OCF_DIV		129278
 44#define TPS25990_IIN_OCF_OFF		157
 45
 46#define PK_MIN_AVG_RST_MASK		(PK_MIN_AVG_RST_PEAK | \
 47					 PK_MIN_AVG_RST_AVG  | \
 48					 PK_MIN_AVG_RST_MIN)
 49
 50/*
 51 * Arbitrary default Rimon value: 1kOhm
 52 * This correspond to an overcurrent limit of 55A, close to the specified limit
 53 * of un-stacked TPS25990 and makes further calculation easier to setup in
 54 * sensor.conf, if necessary
 55 */
 56#define TPS25990_DEFAULT_RIMON		1000000000
 57
 58static void tps25990_set_m(int *m, u32 rimon)
 59{
 60	u64 val = ((u64)*m) * rimon;
 61
 62	/* Make sure m fits the s32 type */
 63	*m = DIV_ROUND_CLOSEST_ULL(val, 1000000);
 64}
 65
 66static int tps25990_mfr_write_protect_set(struct i2c_client *client,
 67					  u8 protect)
 68{
 69	u8 val;
 70
 71	switch (protect) {
 72	case 0:
 73		val = 0xa2;
 74		break;
 75	case PB_WP_ALL:
 76		val = 0x0;
 77		break;
 78	default:
 79		return -EINVAL;
 80	}
 81
 82	return pmbus_write_byte_data(client, -1, TPS25990_MFR_WRITE_PROTECT,
 83				     val);
 84}
 85
 86static int tps25990_mfr_write_protect_get(struct i2c_client *client)
 87{
 88	int ret = pmbus_read_byte_data(client, -1, TPS25990_MFR_WRITE_PROTECT);
 89
 90	if (ret < 0)
 91		return ret;
 92
 93	return (ret & TPS25990_UNLOCKED) ? 0 : PB_WP_ALL;
 94}
 95
 96static int tps25990_read_word_data(struct i2c_client *client,
 97				   int page, int phase, int reg)
 98{
 99	int ret;
100
101	switch (reg) {
102	case PMBUS_VIRT_READ_VIN_MAX:
103		ret = pmbus_read_word_data(client, page, phase,
104					   TPS25990_READ_VIN_PEAK);
105		break;
106
107	case PMBUS_VIRT_READ_VIN_MIN:
108		ret = pmbus_read_word_data(client, page, phase,
109					   TPS25990_READ_VIN_MIN);
110		break;
111
112	case PMBUS_VIRT_READ_VIN_AVG:
113		ret = pmbus_read_word_data(client, page, phase,
114					   TPS25990_READ_VIN_AVG);
115		break;
116
117	case PMBUS_VIRT_READ_VOUT_MIN:
118		ret = pmbus_read_word_data(client, page, phase,
119					   TPS25990_READ_VOUT_MIN);
120		break;
121
122	case PMBUS_VIRT_READ_VOUT_AVG:
123		ret = pmbus_read_word_data(client, page, phase,
124					   TPS25990_READ_VOUT_AVG);
125		break;
126
127	case PMBUS_VIRT_READ_IIN_AVG:
128		ret = pmbus_read_word_data(client, page, phase,
129					   TPS25990_READ_IIN_AVG);
130		break;
131
132	case PMBUS_VIRT_READ_IIN_MAX:
133		ret = pmbus_read_word_data(client, page, phase,
134					   TPS25990_READ_IIN_PEAK);
135		break;
136
137	case PMBUS_VIRT_READ_TEMP_AVG:
138		ret = pmbus_read_word_data(client, page, phase,
139					   TPS25990_READ_TEMP_AVG);
140		break;
141
142	case PMBUS_VIRT_READ_TEMP_MAX:
143		ret = pmbus_read_word_data(client, page, phase,
144					   TPS25990_READ_TEMP_PEAK);
145		break;
146
147	case PMBUS_VIRT_READ_PIN_AVG:
148		ret = pmbus_read_word_data(client, page, phase,
149					   TPS25990_READ_PIN_AVG);
150		break;
151
152	case PMBUS_VIRT_READ_PIN_MAX:
153		ret = pmbus_read_word_data(client, page, phase,
154					   TPS25990_READ_PIN_PEAK);
155		break;
156
157	case PMBUS_VIRT_READ_VMON:
158		ret = pmbus_read_word_data(client, page, phase,
159					   TPS25990_READ_VAUX);
160		break;
161
162	case PMBUS_VIN_UV_WARN_LIMIT:
163	case PMBUS_VIN_UV_FAULT_LIMIT:
164	case PMBUS_VIN_OV_WARN_LIMIT:
165	case PMBUS_VOUT_UV_WARN_LIMIT:
166	case PMBUS_IIN_OC_WARN_LIMIT:
167	case PMBUS_OT_WARN_LIMIT:
168	case PMBUS_OT_FAULT_LIMIT:
169	case PMBUS_PIN_OP_WARN_LIMIT:
170		/*
171		 * These registers provide an 8 bits value instead of a
172		 * 10bits one. Just shifting twice the register value is
173		 * enough to make the sensor type conversion work, even
174		 * if the datasheet provides different m, b and R for
175		 * those.
176		 */
177		ret = pmbus_read_word_data(client, page, phase, reg);
178		if (ret < 0)
179			break;
180		ret <<= TPS25990_8B_SHIFT;
181		break;
182
183	case PMBUS_VIN_OV_FAULT_LIMIT:
184		ret = pmbus_read_word_data(client, page, phase, reg);
185		if (ret < 0)
186			break;
187		ret = DIV_ROUND_CLOSEST(ret * TPS25990_VIN_OVF_NUM,
188					TPS25990_VIN_OVF_DIV);
189		ret += TPS25990_VIN_OVF_OFF;
190		break;
191
192	case PMBUS_IIN_OC_FAULT_LIMIT:
193		/*
194		 * VIREF directly sets the over-current limit at which the eFuse
195		 * will turn the FET off and trigger a fault. Expose it through
196		 * this generic property instead of a manufacturer specific one.
197		 */
198		ret = pmbus_read_byte_data(client, page, TPS25990_VIREF);
199		if (ret < 0)
200			break;
201		ret = DIV_ROUND_CLOSEST(ret * TPS25990_IIN_OCF_NUM,
202					TPS25990_IIN_OCF_DIV);
203		ret += TPS25990_IIN_OCF_OFF;
204		break;
205
206	case PMBUS_VIRT_SAMPLES:
207		ret = pmbus_read_byte_data(client, page, TPS25990_PK_MIN_AVG);
208		if (ret < 0)
209			break;
210		ret = 1 << FIELD_GET(PK_MIN_AVG_AVG_CNT, ret);
211		break;
212
213	case PMBUS_VIRT_RESET_TEMP_HISTORY:
214	case PMBUS_VIRT_RESET_VIN_HISTORY:
215	case PMBUS_VIRT_RESET_IIN_HISTORY:
216	case PMBUS_VIRT_RESET_PIN_HISTORY:
217	case PMBUS_VIRT_RESET_VOUT_HISTORY:
218		ret = 0;
219		break;
220
221	default:
222		ret = -ENODATA;
223		break;
224	}
225
226	return ret;
227}
228
229static int tps25990_write_word_data(struct i2c_client *client,
230				    int page, int reg, u16 value)
231{
232	int ret;
233
234	switch (reg) {
235	case PMBUS_VIN_UV_WARN_LIMIT:
236	case PMBUS_VIN_UV_FAULT_LIMIT:
237	case PMBUS_VIN_OV_WARN_LIMIT:
238	case PMBUS_VOUT_UV_WARN_LIMIT:
239	case PMBUS_IIN_OC_WARN_LIMIT:
240	case PMBUS_OT_WARN_LIMIT:
241	case PMBUS_OT_FAULT_LIMIT:
242	case PMBUS_PIN_OP_WARN_LIMIT:
243		value >>= TPS25990_8B_SHIFT;
244		value = clamp_val(value, 0, 0xff);
245		ret = pmbus_write_word_data(client, page, reg, value);
246		break;
247
248	case PMBUS_VIN_OV_FAULT_LIMIT:
249		value -= TPS25990_VIN_OVF_OFF;
250		value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_VIN_OVF_DIV,
251					  TPS25990_VIN_OVF_NUM);
252		value = clamp_val(value, 0, 0xf);
253		ret = pmbus_write_word_data(client, page, reg, value);
254		break;
255
256	case PMBUS_IIN_OC_FAULT_LIMIT:
257		value -= TPS25990_IIN_OCF_OFF;
258		value = DIV_ROUND_CLOSEST(((unsigned int)value) * TPS25990_IIN_OCF_DIV,
259					  TPS25990_IIN_OCF_NUM);
260		value = clamp_val(value, 0, 0x3f);
261		ret = pmbus_write_byte_data(client, page, TPS25990_VIREF, value);
262		break;
263
264	case PMBUS_VIRT_SAMPLES:
265		value = clamp_val(value, 1, 1 << PK_MIN_AVG_AVG_CNT);
266		value = ilog2(value);
267		ret = pmbus_update_byte_data(client, page, TPS25990_PK_MIN_AVG,
268					     PK_MIN_AVG_AVG_CNT,
269					     FIELD_PREP(PK_MIN_AVG_AVG_CNT, value));
270		break;
271
272	case PMBUS_VIRT_RESET_TEMP_HISTORY:
273	case PMBUS_VIRT_RESET_VIN_HISTORY:
274	case PMBUS_VIRT_RESET_IIN_HISTORY:
275	case PMBUS_VIRT_RESET_PIN_HISTORY:
276	case PMBUS_VIRT_RESET_VOUT_HISTORY:
277		/*
278		 * TPS25990 has history resets based on MIN/AVG/PEAK instead of per
279		 * sensor type. Exposing this quirk in hwmon is not desirable so
280		 * reset MIN, AVG and PEAK together. Even is there effectively only
281		 * one reset, which resets everything, expose the 5 entries so
282		 * userspace is not required map a sensor type to another to trigger
283		 * a reset
284		 */
285		ret = pmbus_update_byte_data(client, 0, TPS25990_PK_MIN_AVG,
286					     PK_MIN_AVG_RST_MASK,
287					     PK_MIN_AVG_RST_MASK);
288		break;
289
290	default:
291		ret = -ENODATA;
292		break;
293	}
294
295	return ret;
296}
297
298static int tps25990_read_byte_data(struct i2c_client *client,
299				   int page, int reg)
300{
301	int ret;
302
303	switch (reg) {
304	case PMBUS_WRITE_PROTECT:
305		ret = tps25990_mfr_write_protect_get(client);
306		break;
307
308	default:
309		ret = -ENODATA;
310		break;
311	}
312
313	return ret;
314}
315
316static int tps25990_write_byte_data(struct i2c_client *client,
317				    int page, int reg, u8 byte)
318{
319	int ret;
320
321	switch (reg) {
322	case PMBUS_WRITE_PROTECT:
323		ret = tps25990_mfr_write_protect_set(client, byte);
324		break;
325
326	default:
327		ret = -ENODATA;
328		break;
329	}
330
331	return ret;
332}
333
334#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR)
335static const struct regulator_desc tps25990_reg_desc[] = {
336	PMBUS_REGULATOR_ONE_NODE("vout"),
337};
338#endif
339
340static const struct pmbus_driver_info tps25990_base_info = {
341	.pages = 1,
342	.format[PSC_VOLTAGE_IN] = direct,
343	.m[PSC_VOLTAGE_IN] = 5251,
344	.b[PSC_VOLTAGE_IN] = 0,
345	.R[PSC_VOLTAGE_IN] = -2,
346	.format[PSC_VOLTAGE_OUT] = direct,
347	.m[PSC_VOLTAGE_OUT] = 5251,
348	.b[PSC_VOLTAGE_OUT] = 0,
349	.R[PSC_VOLTAGE_OUT] = -2,
350	.format[PSC_TEMPERATURE] = direct,
351	.m[PSC_TEMPERATURE] = 140,
352	.b[PSC_TEMPERATURE] = 32100,
353	.R[PSC_TEMPERATURE] = -2,
354	/*
355	 * Current and Power measurement depends on the ohm value
356	 * of Rimon. m is multiplied by 1000 below to have an integer
357	 * and -3 is added to R to compensate.
358	 */
359	.format[PSC_CURRENT_IN] = direct,
360	.m[PSC_CURRENT_IN] = 9538,
361	.b[PSC_CURRENT_IN] = 0,
362	.R[PSC_CURRENT_IN] = -6,
363	.format[PSC_POWER] = direct,
364	.m[PSC_POWER] = 4901,
365	.b[PSC_POWER] = 0,
366	.R[PSC_POWER] = -7,
367	.func[0] = (PMBUS_HAVE_VIN |
368		    PMBUS_HAVE_VOUT |
369		    PMBUS_HAVE_VMON |
370		    PMBUS_HAVE_IIN |
371		    PMBUS_HAVE_PIN |
372		    PMBUS_HAVE_TEMP |
373		    PMBUS_HAVE_STATUS_VOUT |
374		    PMBUS_HAVE_STATUS_IOUT |
375		    PMBUS_HAVE_STATUS_INPUT |
376		    PMBUS_HAVE_STATUS_TEMP |
377		    PMBUS_HAVE_SAMPLES),
378	.read_word_data = tps25990_read_word_data,
379	.write_word_data = tps25990_write_word_data,
380	.read_byte_data = tps25990_read_byte_data,
381	.write_byte_data = tps25990_write_byte_data,
382
383#if IS_ENABLED(CONFIG_SENSORS_TPS25990_REGULATOR)
384	.reg_desc = tps25990_reg_desc,
385	.num_regulators = ARRAY_SIZE(tps25990_reg_desc),
386#endif
387};
388
389static const struct i2c_device_id tps25990_i2c_id[] = {
390	{ "tps25990" },
391	{}
392};
393MODULE_DEVICE_TABLE(i2c, tps25990_i2c_id);
394
395static const struct of_device_id tps25990_of_match[] = {
396	{ .compatible = "ti,tps25990" },
397	{}
398};
399MODULE_DEVICE_TABLE(of, tps25990_of_match);
400
401static int tps25990_probe(struct i2c_client *client)
402{
403	struct device *dev = &client->dev;
404	struct pmbus_driver_info *info;
405	u32 rimon = TPS25990_DEFAULT_RIMON;
406	int ret;
407
408	ret = device_property_read_u32(dev, "ti,rimon-micro-ohms", &rimon);
409	if (ret < 0 && ret != -EINVAL)
410		return dev_err_probe(dev, ret, "failed to get rimon\n");
411
412	info = devm_kmemdup(dev, &tps25990_base_info, sizeof(*info), GFP_KERNEL);
413	if (!info)
414		return -ENOMEM;
415
416	/* Adapt the current and power scale for each instance */
417	tps25990_set_m(&info->m[PSC_CURRENT_IN], rimon);
418	tps25990_set_m(&info->m[PSC_POWER], rimon);
419
420	return pmbus_do_probe(client, info);
421}
422
423static struct i2c_driver tps25990_driver = {
424	.driver = {
425		.name = "tps25990",
426		.of_match_table = tps25990_of_match,
427	},
428	.probe = tps25990_probe,
429	.id_table = tps25990_i2c_id,
430};
431module_i2c_driver(tps25990_driver);
432
433MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
434MODULE_DESCRIPTION("PMBUS driver for TPS25990 eFuse");
435MODULE_LICENSE("GPL");
436MODULE_IMPORT_NS("PMBUS");
~/ Read-only file preview.