File Index
Files and directories
Sign in
FILE

tps23861.c

File preview with syntax highlighting.

linux-6.19.14/drivers/hwmon/tps23861.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/*
  3 * Copyright (c) 2020 Sartura Ltd.
  4 *
  5 * Driver for the TI TPS23861 PoE PSE.
  6 *
  7 * Author: Robert Marko <robert.marko@sartura.hr>
  8 */
  9
 10#include <linux/bitfield.h>
 11#include <linux/debugfs.h>
 12#include <linux/delay.h>
 13#include <linux/hwmon-sysfs.h>
 14#include <linux/hwmon.h>
 15#include <linux/i2c.h>
 16#include <linux/module.h>
 17#include <linux/of.h>
 18#include <linux/regmap.h>
 19
 20#define TEMPERATURE			0x2c
 21#define INPUT_VOLTAGE_LSB		0x2e
 22#define INPUT_VOLTAGE_MSB		0x2f
 23#define PORT_1_CURRENT_LSB		0x30
 24#define PORT_1_CURRENT_MSB		0x31
 25#define PORT_1_VOLTAGE_LSB		0x32
 26#define PORT_1_VOLTAGE_MSB		0x33
 27#define PORT_2_CURRENT_LSB		0x34
 28#define PORT_2_CURRENT_MSB		0x35
 29#define PORT_2_VOLTAGE_LSB		0x36
 30#define PORT_2_VOLTAGE_MSB		0x37
 31#define PORT_3_CURRENT_LSB		0x38
 32#define PORT_3_CURRENT_MSB		0x39
 33#define PORT_3_VOLTAGE_LSB		0x3a
 34#define PORT_3_VOLTAGE_MSB		0x3b
 35#define PORT_4_CURRENT_LSB		0x3c
 36#define PORT_4_CURRENT_MSB		0x3d
 37#define PORT_4_VOLTAGE_LSB		0x3e
 38#define PORT_4_VOLTAGE_MSB		0x3f
 39#define PORT_N_CURRENT_LSB_OFFSET	0x04
 40#define PORT_N_VOLTAGE_LSB_OFFSET	0x04
 41#define VOLTAGE_CURRENT_MASK		GENMASK(13, 0)
 42#define PORT_1_RESISTANCE_LSB		0x60
 43#define PORT_1_RESISTANCE_MSB		0x61
 44#define PORT_2_RESISTANCE_LSB		0x62
 45#define PORT_2_RESISTANCE_MSB		0x63
 46#define PORT_3_RESISTANCE_LSB		0x64
 47#define PORT_3_RESISTANCE_MSB		0x65
 48#define PORT_4_RESISTANCE_LSB		0x66
 49#define PORT_4_RESISTANCE_MSB		0x67
 50#define PORT_N_RESISTANCE_LSB_OFFSET	0x02
 51#define PORT_RESISTANCE_MASK		GENMASK(13, 0)
 52#define PORT_RESISTANCE_RSN_MASK	GENMASK(15, 14)
 53#define PORT_RESISTANCE_RSN_OTHER	0
 54#define PORT_RESISTANCE_RSN_LOW		1
 55#define PORT_RESISTANCE_RSN_OPEN	2
 56#define PORT_RESISTANCE_RSN_SHORT	3
 57#define PORT_1_STATUS			0x0c
 58#define PORT_2_STATUS			0x0d
 59#define PORT_3_STATUS			0x0e
 60#define PORT_4_STATUS			0x0f
 61#define PORT_STATUS_CLASS_MASK		GENMASK(7, 4)
 62#define PORT_STATUS_DETECT_MASK		GENMASK(3, 0)
 63#define PORT_CLASS_UNKNOWN		0
 64#define PORT_CLASS_1			1
 65#define PORT_CLASS_2			2
 66#define PORT_CLASS_3			3
 67#define PORT_CLASS_4			4
 68#define PORT_CLASS_RESERVED		5
 69#define PORT_CLASS_0			6
 70#define PORT_CLASS_OVERCURRENT		7
 71#define PORT_CLASS_MISMATCH		8
 72#define PORT_DETECT_UNKNOWN		0
 73#define PORT_DETECT_SHORT		1
 74#define PORT_DETECT_RESERVED		2
 75#define PORT_DETECT_RESISTANCE_LOW	3
 76#define PORT_DETECT_RESISTANCE_OK	4
 77#define PORT_DETECT_RESISTANCE_HIGH	5
 78#define PORT_DETECT_OPEN_CIRCUIT	6
 79#define PORT_DETECT_RESERVED_2		7
 80#define PORT_DETECT_MOSFET_FAULT	8
 81#define PORT_DETECT_LEGACY		9
 82/* Measurment beyond clamp voltage */
 83#define PORT_DETECT_CAPACITANCE_INVALID_BEYOND	10
 84/* Insufficient voltage delta */
 85#define PORT_DETECT_CAPACITANCE_INVALID_DELTA	11
 86#define PORT_DETECT_CAPACITANCE_OUT_OF_RANGE	12
 87#define POE_PLUS			0x40
 88#define OPERATING_MODE			0x12
 89#define OPERATING_MODE_OFF		0
 90#define OPERATING_MODE_MANUAL		1
 91#define OPERATING_MODE_SEMI		2
 92#define OPERATING_MODE_AUTO		3
 93#define OPERATING_MODE_PORT_1_MASK	GENMASK(1, 0)
 94#define OPERATING_MODE_PORT_2_MASK	GENMASK(3, 2)
 95#define OPERATING_MODE_PORT_3_MASK	GENMASK(5, 4)
 96#define OPERATING_MODE_PORT_4_MASK	GENMASK(7, 6)
 97
 98#define DETECT_CLASS_RESTART		0x18
 99#define POWER_ENABLE			0x19
100#define TPS23861_NUM_PORTS		4
101
102#define TPS23861_GENERAL_MASK_1		0x17
103#define TPS23861_CURRENT_SHUNT_MASK	BIT(0)
104
105#define TEMPERATURE_LSB			652 /* 0.652 degrees Celsius */
106#define VOLTAGE_LSB			3662 /* 3.662 mV */
107#define SHUNT_RESISTOR_DEFAULT		255000 /* 255 mOhm */
108#define CURRENT_LSB_250			62260 /* 62.260 uA */
109#define CURRENT_LSB_255			61039 /* 61.039 uA */
110#define RESISTANCE_LSB			110966 /* 11.0966 Ohm*/
111#define RESISTANCE_LSB_LOW		157216 /* 15.7216 Ohm*/
112
113struct tps23861_data {
114	struct regmap *regmap;
115	u32 shunt_resistor;
116	struct i2c_client *client;
117};
118
119static const struct regmap_config tps23861_regmap_config = {
120	.reg_bits = 8,
121	.val_bits = 8,
122	.max_register = 0x6f,
123};
124
125static int tps23861_read_temp(struct tps23861_data *data, long *val)
126{
127	unsigned int regval;
128	int err;
129
130	err = regmap_read(data->regmap, TEMPERATURE, &regval);
131	if (err < 0)
132		return err;
133
134	*val = ((long)regval * TEMPERATURE_LSB) - 20000;
135
136	return 0;
137}
138
139static int tps23861_read_voltage(struct tps23861_data *data, int channel,
140				 long *val)
141{
142	__le16 regval;
143	long raw_val;
144	int err;
145
146	if (channel < TPS23861_NUM_PORTS) {
147		err = regmap_bulk_read(data->regmap,
148				       PORT_1_VOLTAGE_LSB + channel * PORT_N_VOLTAGE_LSB_OFFSET,
149				       &regval, 2);
150	} else {
151		err = regmap_bulk_read(data->regmap,
152				       INPUT_VOLTAGE_LSB,
153				       &regval, 2);
154	}
155	if (err < 0)
156		return err;
157
158	raw_val = le16_to_cpu(regval);
159	*val = (FIELD_GET(VOLTAGE_CURRENT_MASK, raw_val) * VOLTAGE_LSB) / 1000;
160
161	return 0;
162}
163
164static int tps23861_read_current(struct tps23861_data *data, int channel,
165				 long *val)
166{
167	long raw_val, current_lsb;
168	__le16 regval;
169
170	int err;
171
172	if (data->shunt_resistor == SHUNT_RESISTOR_DEFAULT)
173		current_lsb = CURRENT_LSB_255;
174	else
175		current_lsb = CURRENT_LSB_250;
176
177	err = regmap_bulk_read(data->regmap,
178			       PORT_1_CURRENT_LSB + channel * PORT_N_CURRENT_LSB_OFFSET,
179			       &regval, 2);
180	if (err < 0)
181		return err;
182
183	raw_val = le16_to_cpu(regval);
184	*val = (FIELD_GET(VOLTAGE_CURRENT_MASK, raw_val) * current_lsb) / 1000000;
185
186	return 0;
187}
188
189static int tps23861_port_disable(struct tps23861_data *data, int channel)
190{
191	unsigned int regval = 0;
192	int err;
193
194	regval |= BIT(channel + 4);
195	err = regmap_write(data->regmap, POWER_ENABLE, regval);
196
197	return err;
198}
199
200static int tps23861_port_enable(struct tps23861_data *data, int channel)
201{
202	unsigned int regval = 0;
203	int err;
204
205	regval |= BIT(channel);
206	regval |= BIT(channel + 4);
207	err = regmap_write(data->regmap, DETECT_CLASS_RESTART, regval);
208
209	return err;
210}
211
212static umode_t tps23861_is_visible(const void *data, enum hwmon_sensor_types type,
213				   u32 attr, int channel)
214{
215	switch (type) {
216	case hwmon_temp:
217		switch (attr) {
218		case hwmon_temp_input:
219		case hwmon_temp_label:
220			return 0444;
221		default:
222			return 0;
223		}
224	case hwmon_in:
225		switch (attr) {
226		case hwmon_in_input:
227		case hwmon_in_label:
228			return 0444;
229		case hwmon_in_enable:
230			return 0200;
231		default:
232			return 0;
233		}
234	case hwmon_curr:
235		switch (attr) {
236		case hwmon_curr_input:
237		case hwmon_curr_label:
238			return 0444;
239		default:
240			return 0;
241		}
242	default:
243		return 0;
244	}
245}
246
247static int tps23861_write(struct device *dev, enum hwmon_sensor_types type,
248			  u32 attr, int channel, long val)
249{
250	struct tps23861_data *data = dev_get_drvdata(dev);
251	int err;
252
253	switch (type) {
254	case hwmon_in:
255		switch (attr) {
256		case hwmon_in_enable:
257			if (val == 0)
258				err = tps23861_port_disable(data, channel);
259			else if (val == 1)
260				err = tps23861_port_enable(data, channel);
261			else
262				err = -EINVAL;
263			break;
264		default:
265			return -EOPNOTSUPP;
266		}
267		break;
268	default:
269		return -EOPNOTSUPP;
270	}
271
272	return err;
273}
274
275static int tps23861_read(struct device *dev, enum hwmon_sensor_types type,
276			 u32 attr, int channel, long *val)
277{
278	struct tps23861_data *data = dev_get_drvdata(dev);
279	int err;
280
281	switch (type) {
282	case hwmon_temp:
283		switch (attr) {
284		case hwmon_temp_input:
285			err = tps23861_read_temp(data, val);
286			break;
287		default:
288			return -EOPNOTSUPP;
289		}
290		break;
291	case hwmon_in:
292		switch (attr) {
293		case hwmon_in_input:
294			err = tps23861_read_voltage(data, channel, val);
295			break;
296		default:
297			return -EOPNOTSUPP;
298		}
299		break;
300	case hwmon_curr:
301		switch (attr) {
302		case hwmon_curr_input:
303			err = tps23861_read_current(data, channel, val);
304			break;
305		default:
306			return -EOPNOTSUPP;
307		}
308		break;
309	default:
310		return -EOPNOTSUPP;
311	}
312
313	return err;
314}
315
316static const char * const tps23861_port_label[] = {
317	"Port1",
318	"Port2",
319	"Port3",
320	"Port4",
321	"Input",
322};
323
324static int tps23861_read_string(struct device *dev,
325				enum hwmon_sensor_types type,
326				u32 attr, int channel, const char **str)
327{
328	switch (type) {
329	case hwmon_in:
330	case hwmon_curr:
331		*str = tps23861_port_label[channel];
332		break;
333	case hwmon_temp:
334		*str = "Die";
335		break;
336	default:
337		return -EOPNOTSUPP;
338	}
339
340	return 0;
341}
342
343static const struct hwmon_channel_info * const tps23861_info[] = {
344	HWMON_CHANNEL_INFO(chip,
345			   HWMON_C_REGISTER_TZ),
346	HWMON_CHANNEL_INFO(temp,
347			   HWMON_T_INPUT | HWMON_T_LABEL),
348	HWMON_CHANNEL_INFO(in,
349			   HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
350			   HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
351			   HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
352			   HWMON_I_INPUT | HWMON_I_ENABLE | HWMON_I_LABEL,
353			   HWMON_I_INPUT | HWMON_I_LABEL),
354	HWMON_CHANNEL_INFO(curr,
355			   HWMON_C_INPUT | HWMON_C_LABEL,
356			   HWMON_C_INPUT | HWMON_C_LABEL,
357			   HWMON_C_INPUT | HWMON_C_LABEL,
358			   HWMON_C_INPUT | HWMON_C_LABEL),
359	NULL
360};
361
362static const struct hwmon_ops tps23861_hwmon_ops = {
363	.is_visible = tps23861_is_visible,
364	.write = tps23861_write,
365	.read = tps23861_read,
366	.read_string = tps23861_read_string,
367};
368
369static const struct hwmon_chip_info tps23861_chip_info = {
370	.ops = &tps23861_hwmon_ops,
371	.info = tps23861_info,
372};
373
374static char *port_operating_mode_string(uint8_t mode_reg, unsigned int port)
375{
376	unsigned int mode = ~0;
377
378	if (port < TPS23861_NUM_PORTS)
379		mode = (mode_reg >> (2 * port)) & OPERATING_MODE_PORT_1_MASK;
380
381	switch (mode) {
382	case OPERATING_MODE_OFF:
383		return "Off";
384	case OPERATING_MODE_MANUAL:
385		return "Manual";
386	case OPERATING_MODE_SEMI:
387		return "Semi-Auto";
388	case OPERATING_MODE_AUTO:
389		return "Auto";
390	default:
391		return "Invalid";
392	}
393}
394
395static char *port_detect_status_string(uint8_t status_reg)
396{
397	switch (FIELD_GET(PORT_STATUS_DETECT_MASK, status_reg)) {
398	case PORT_DETECT_UNKNOWN:
399		return "Unknown device";
400	case PORT_DETECT_SHORT:
401		return "Short circuit";
402	case PORT_DETECT_RESISTANCE_LOW:
403		return "Too low resistance";
404	case PORT_DETECT_RESISTANCE_OK:
405		return "Valid resistance";
406	case PORT_DETECT_RESISTANCE_HIGH:
407		return "Too high resistance";
408	case PORT_DETECT_OPEN_CIRCUIT:
409		return "Open circuit";
410	case PORT_DETECT_MOSFET_FAULT:
411		return "MOSFET fault";
412	case PORT_DETECT_LEGACY:
413		return "Legacy device";
414	case PORT_DETECT_CAPACITANCE_INVALID_BEYOND:
415		return "Invalid capacitance, beyond clamp voltage";
416	case PORT_DETECT_CAPACITANCE_INVALID_DELTA:
417		return "Invalid capacitance, insufficient voltage delta";
418	case PORT_DETECT_CAPACITANCE_OUT_OF_RANGE:
419		return "Valid capacitance, outside of legacy range";
420	case PORT_DETECT_RESERVED:
421	case PORT_DETECT_RESERVED_2:
422	default:
423		return "Invalid";
424	}
425}
426
427static char *port_class_status_string(uint8_t status_reg)
428{
429	switch (FIELD_GET(PORT_STATUS_CLASS_MASK, status_reg)) {
430	case PORT_CLASS_UNKNOWN:
431		return "Unknown";
432	case PORT_CLASS_RESERVED:
433	case PORT_CLASS_0:
434		return "0";
435	case PORT_CLASS_1:
436		return "1";
437	case PORT_CLASS_2:
438		return "2";
439	case PORT_CLASS_3:
440		return "3";
441	case PORT_CLASS_4:
442		return "4";
443	case PORT_CLASS_OVERCURRENT:
444		return "Overcurrent";
445	case PORT_CLASS_MISMATCH:
446		return "Mismatch";
447	default:
448		return "Invalid";
449	}
450}
451
452static char *port_poe_plus_status_string(uint8_t poe_plus, unsigned int port)
453{
454	return (BIT(port + 4) & poe_plus) ? "Yes" : "No";
455}
456
457static int tps23861_port_resistance(struct tps23861_data *data, int port)
458{
459	unsigned int raw_val;
460	__le16 regval;
461
462	regmap_bulk_read(data->regmap,
463			 PORT_1_RESISTANCE_LSB + PORT_N_RESISTANCE_LSB_OFFSET * port,
464			 &regval,
465			 2);
466
467	raw_val = le16_to_cpu(regval);
468	switch (FIELD_GET(PORT_RESISTANCE_RSN_MASK, raw_val)) {
469	case PORT_RESISTANCE_RSN_OTHER:
470		return (FIELD_GET(PORT_RESISTANCE_MASK, raw_val) * RESISTANCE_LSB) / 10000;
471	case PORT_RESISTANCE_RSN_LOW:
472		return (FIELD_GET(PORT_RESISTANCE_MASK, raw_val) * RESISTANCE_LSB_LOW) / 10000;
473	case PORT_RESISTANCE_RSN_SHORT:
474	case PORT_RESISTANCE_RSN_OPEN:
475	default:
476		return 0;
477	}
478}
479
480static int tps23861_port_status_show(struct seq_file *s, void *data)
481{
482	struct tps23861_data *priv = s->private;
483	unsigned int i, mode, poe_plus, status;
484
485	regmap_read(priv->regmap, OPERATING_MODE, &mode);
486	regmap_read(priv->regmap, POE_PLUS, &poe_plus);
487
488	for (i = 0; i < TPS23861_NUM_PORTS; i++) {
489		regmap_read(priv->regmap, PORT_1_STATUS + i, &status);
490
491		seq_printf(s, "Port: \t\t%d\n", i + 1);
492		seq_printf(s, "Operating mode: %s\n", port_operating_mode_string(mode, i));
493		seq_printf(s, "Detected: \t%s\n", port_detect_status_string(status));
494		seq_printf(s, "Class: \t\t%s\n", port_class_status_string(status));
495		seq_printf(s, "PoE Plus: \t%s\n", port_poe_plus_status_string(poe_plus, i));
496		seq_printf(s, "Resistance: \t%d\n", tps23861_port_resistance(priv, i));
497		seq_putc(s, '\n');
498	}
499
500	return 0;
501}
502
503DEFINE_SHOW_ATTRIBUTE(tps23861_port_status);
504
505static int tps23861_probe(struct i2c_client *client)
506{
507	struct device *dev = &client->dev;
508	struct tps23861_data *data;
509	struct device *hwmon_dev;
510	u32 shunt_resistor;
511
512	data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
513	if (!data)
514		return -ENOMEM;
515
516	data->client = client;
517	i2c_set_clientdata(client, data);
518
519	data->regmap = devm_regmap_init_i2c(client, &tps23861_regmap_config);
520	if (IS_ERR(data->regmap)) {
521		dev_err(dev, "failed to allocate register map\n");
522		return PTR_ERR(data->regmap);
523	}
524
525	if (!of_property_read_u32(dev->of_node, "shunt-resistor-micro-ohms", &shunt_resistor))
526		data->shunt_resistor = shunt_resistor;
527	else
528		data->shunt_resistor = SHUNT_RESISTOR_DEFAULT;
529
530	if (data->shunt_resistor == SHUNT_RESISTOR_DEFAULT)
531		regmap_clear_bits(data->regmap,
532				  TPS23861_GENERAL_MASK_1,
533				  TPS23861_CURRENT_SHUNT_MASK);
534	else
535		regmap_set_bits(data->regmap,
536				TPS23861_GENERAL_MASK_1,
537				TPS23861_CURRENT_SHUNT_MASK);
538
539	hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
540							 data, &tps23861_chip_info,
541							 NULL);
542	if (IS_ERR(hwmon_dev))
543		return PTR_ERR(hwmon_dev);
544
545	debugfs_create_file("port_status", 0400, client->debugfs, data,
546			    &tps23861_port_status_fops);
547
548	return 0;
549}
550
551static const struct of_device_id __maybe_unused tps23861_of_match[] = {
552	{ .compatible = "ti,tps23861", },
553	{ },
554};
555MODULE_DEVICE_TABLE(of, tps23861_of_match);
556
557static struct i2c_driver tps23861_driver = {
558	.probe			= tps23861_probe,
559	.driver = {
560		.name		= "tps23861",
561		.of_match_table	= of_match_ptr(tps23861_of_match),
562	},
563};
564module_i2c_driver(tps23861_driver);
565
566MODULE_LICENSE("GPL");
567MODULE_AUTHOR("Robert Marko <robert.marko@sartura.hr>");
568MODULE_DESCRIPTION("TI TPS23861 PoE PSE");
~/ Read-only file preview.