Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.15.
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2023 Analog Devices, Inc.
  4 * Author: Antoniu Miclaus <antoniu.miclaus@analog.com>
  5 */
  6
  7#include <linux/bitops.h>
  8#include <linux/err.h>
  9#include <linux/hwmon.h>
 10#include <linux/i2c.h>
 11#include <linux/kernel.h>
 12#include <linux/module.h>
 13#include <linux/property.h>
 14#include <linux/regmap.h>
 15#include <linux/regulator/consumer.h>
 16
 17#define LTC2991_STATUS_LOW		0x00
 18#define LTC2991_CH_EN_TRIGGER		0x01
 19#define LTC2991_V1_V4_CTRL		0x06
 20#define LTC2991_V5_V8_CTRL		0x07
 21#define LTC2991_PWM_TH_LSB_T_INT	0x08
 22#define LTC2991_PWM_TH_MSB		0x09
 23#define LTC2991_CHANNEL_V_MSB(x)	(0x0A + ((x) * 2))
 24#define LTC2991_CHANNEL_T_MSB(x)	(0x0A + ((x) * 4))
 25#define LTC2991_CHANNEL_C_MSB(x)	(0x0C + ((x) * 4))
 26#define LTC2991_T_INT_MSB		0x1A
 27#define LTC2991_VCC_MSB			0x1C
 28
 29#define LTC2991_V7_V8_EN		BIT(7)
 30#define LTC2991_V5_V6_EN		BIT(6)
 31#define LTC2991_V3_V4_EN		BIT(5)
 32#define LTC2991_V1_V2_EN		BIT(4)
 33#define LTC2991_T_INT_VCC_EN		BIT(3)
 34
 35#define LTC2991_V3_V4_FILT_EN		BIT(7)
 36#define LTC2991_V3_V4_TEMP_EN		BIT(5)
 37#define LTC2991_V3_V4_DIFF_EN		BIT(4)
 38#define LTC2991_V1_V2_FILT_EN		BIT(3)
 39#define LTC2991_V1_V2_TEMP_EN		BIT(1)
 40#define LTC2991_V1_V2_DIFF_EN		BIT(0)
 41
 42#define LTC2991_V7_V8_FILT_EN		BIT(7)
 43#define LTC2991_V7_V8_TEMP_EN		BIT(5)
 44#define LTC2991_V7_V8_DIFF_EN		BIT(4)
 45#define LTC2991_V5_V6_FILT_EN		BIT(7)
 46#define LTC2991_V5_V6_TEMP_EN		BIT(5)
 47#define LTC2991_V5_V6_DIFF_EN		BIT(4)
 48
 49#define LTC2991_REPEAT_ACQ_EN		BIT(4)
 50#define LTC2991_T_INT_FILT_EN		BIT(3)
 51
 52#define LTC2991_MAX_CHANNEL		4
 53#define LTC2991_T_INT_CH_NR		4
 54#define LTC2991_VCC_CH_NR		0
 55
 56struct ltc2991_state {
 57	struct regmap		*regmap;
 58	u32			r_sense_uohm[LTC2991_MAX_CHANNEL];
 59	bool			temp_en[LTC2991_MAX_CHANNEL];
 60};
 61
 62static int ltc2991_read_reg(struct ltc2991_state *st, u8 addr, u8 reg_len,
 63			    int *val)
 64{
 65	__be16 regvals;
 66	int ret;
 67
 68	if (reg_len < 2)
 69		return regmap_read(st->regmap, addr, val);
 70
 71	ret = regmap_bulk_read(st->regmap, addr, &regvals, reg_len);
 72	if (ret)
 73		return ret;
 74
 75	*val = be16_to_cpu(regvals);
 76
 77	return 0;
 78}
 79
 80static int ltc2991_get_voltage(struct ltc2991_state *st, u32 reg, long *val)
 81{
 82	int reg_val, ret, offset = 0;
 83
 84	ret = ltc2991_read_reg(st, reg, 2, &reg_val);
 85	if (ret)
 86		return ret;
 87
 88	if (reg == LTC2991_VCC_MSB)
 89		/* Vcc 2.5V offset */
 90		offset = 2500;
 91
 92	/* Vx, 305.18uV/LSB */
 93	*val = DIV_ROUND_CLOSEST(sign_extend32(reg_val, 14) * 30518,
 94				 1000 * 100) + offset;
 95
 96	return 0;
 97}
 98
 99static int ltc2991_read_in(struct device *dev, u32 attr, int channel, long *val)
100{
101	struct ltc2991_state *st = dev_get_drvdata(dev);
102	u32 reg;
103
104	switch (attr) {
105	case hwmon_in_input:
106		if (channel == LTC2991_VCC_CH_NR)
107			reg = LTC2991_VCC_MSB;
108		else
109			reg = LTC2991_CHANNEL_V_MSB(channel - 1);
110
111		return ltc2991_get_voltage(st, reg, val);
112	default:
113		return -EOPNOTSUPP;
114	}
115}
116
117static int ltc2991_get_curr(struct ltc2991_state *st, u32 reg, int channel,
118			    long *val)
119{
120	int reg_val, ret;
121
122	ret = ltc2991_read_reg(st, reg, 2, &reg_val);
123	if (ret)
124		return ret;
125
126	/* Vx-Vy, 19.075uV/LSB */
127	*val = DIV_ROUND_CLOSEST(sign_extend32(reg_val, 14) * 19075,
128				 st->r_sense_uohm[channel]);
129
130	return 0;
131}
132
133static int ltc2991_read_curr(struct device *dev, u32 attr, int channel,
134			     long *val)
135{
136	struct ltc2991_state *st = dev_get_drvdata(dev);
137	u32 reg;
138
139	switch (attr) {
140	case hwmon_curr_input:
141		reg = LTC2991_CHANNEL_C_MSB(channel);
142		return ltc2991_get_curr(st, reg, channel, val);
143	default:
144		return -EOPNOTSUPP;
145	}
146}
147
148static int ltc2991_get_temp(struct ltc2991_state *st, u32 reg, int channel,
149			    long *val)
150{
151	int reg_val, ret;
152
153	ret = ltc2991_read_reg(st, reg, 2, &reg_val);
154	if (ret)
155		return ret;
156
157	/* Temp LSB = 0.0625 Degrees */
158	*val = DIV_ROUND_CLOSEST(sign_extend32(reg_val, 12) * 1000, 16);
159
160	return 0;
161}
162
163static int ltc2991_read_temp(struct device *dev, u32 attr, int channel,
164			     long *val)
165{
166	struct ltc2991_state *st = dev_get_drvdata(dev);
167	u32 reg;
168
169	switch (attr) {
170	case hwmon_temp_input:
171		if (channel == LTC2991_T_INT_CH_NR)
172			reg = LTC2991_T_INT_MSB;
173		else
174			reg = LTC2991_CHANNEL_T_MSB(channel);
175
176		return ltc2991_get_temp(st, reg, channel, val);
177	default:
178		return -EOPNOTSUPP;
179	}
180}
181
182static int ltc2991_read(struct device *dev, enum hwmon_sensor_types type,
183			u32 attr, int channel, long *val)
184{
185	switch (type) {
186	case hwmon_in:
187		return ltc2991_read_in(dev, attr, channel, val);
188	case hwmon_curr:
189		return ltc2991_read_curr(dev, attr, channel, val);
190	case hwmon_temp:
191		return ltc2991_read_temp(dev, attr, channel, val);
192	default:
193		return -EOPNOTSUPP;
194	}
195}
196
197static umode_t ltc2991_is_visible(const void *data,
198				  enum hwmon_sensor_types type, u32 attr,
199				  int channel)
200{
201	const struct ltc2991_state *st = data;
202
203	switch (type) {
204	case hwmon_in:
205		switch (attr) {
206		case hwmon_in_input:
207			if (channel == LTC2991_VCC_CH_NR)
208				return 0444;
209			if (st->temp_en[(channel - 1) / 2])
210				break;
211			if (channel % 2)
212				return 0444;
213			if (!st->r_sense_uohm[(channel - 1) / 2])
214				return 0444;
215		}
216		break;
217	case hwmon_curr:
218		switch (attr) {
219		case hwmon_curr_input:
220			if (st->r_sense_uohm[channel])
221				return 0444;
222			break;
223		}
224		break;
225	case hwmon_temp:
226		switch (attr) {
227		case hwmon_temp_input:
228			if (st->temp_en[channel] ||
229			    channel == LTC2991_T_INT_CH_NR)
230				return 0444;
231			break;
232		}
233		break;
234	default:
235		break;
236	}
237
238	return 0;
239}
240
241static const struct hwmon_ops ltc2991_hwmon_ops = {
242	.is_visible = ltc2991_is_visible,
243	.read = ltc2991_read,
244};
245
246static const struct hwmon_channel_info *ltc2991_info[] = {
247	HWMON_CHANNEL_INFO(temp,
248			   HWMON_T_INPUT,
249			   HWMON_T_INPUT,
250			   HWMON_T_INPUT,
251			   HWMON_T_INPUT,
252			   HWMON_T_INPUT
253			   ),
254	HWMON_CHANNEL_INFO(curr,
255			   HWMON_C_INPUT,
256			   HWMON_C_INPUT,
257			   HWMON_C_INPUT,
258			   HWMON_C_INPUT
259			   ),
260	HWMON_CHANNEL_INFO(in,
261			   HWMON_I_INPUT,
262			   HWMON_I_INPUT,
263			   HWMON_I_INPUT,
264			   HWMON_I_INPUT,
265			   HWMON_I_INPUT,
266			   HWMON_I_INPUT,
267			   HWMON_I_INPUT,
268			   HWMON_I_INPUT,
269			   HWMON_I_INPUT
270			   ),
271	NULL
272};
273
274static const struct hwmon_chip_info ltc2991_chip_info = {
275	.ops = &ltc2991_hwmon_ops,
276	.info = ltc2991_info,
277};
278
279static const struct regmap_config ltc2991_regmap_config = {
280	.reg_bits = 8,
281	.val_bits = 8,
282	.max_register = 0x1D,
283};
284
285static int ltc2991_init(struct ltc2991_state *st, struct device *dev)
286{
287	struct fwnode_handle *child;
288	int ret;
289	u32 val, addr;
290	u8 v5_v8_reg_data = 0, v1_v4_reg_data = 0;
291
292	ret = devm_regulator_get_enable(dev, "vcc");
293	if (ret)
294		return dev_err_probe(dev, ret,
295				     "failed to enable regulator\n");
296
297	device_for_each_child_node(dev, child) {
298		ret = fwnode_property_read_u32(child, "reg", &addr);
299		if (ret < 0) {
300			fwnode_handle_put(child);
301			return ret;
302		}
303
304		if (addr > 3) {
305			fwnode_handle_put(child);
306			return -EINVAL;
307		}
308
309		ret = fwnode_property_read_u32(child,
310					       "shunt-resistor-micro-ohms",
311					       &val);
312		if (!ret) {
313			if (!val)
314				return dev_err_probe(dev, -EINVAL,
315						     "shunt resistor value cannot be zero\n");
316
317			st->r_sense_uohm[addr] = val;
318
319			switch (addr) {
320			case 0:
321				v1_v4_reg_data |= LTC2991_V1_V2_DIFF_EN;
322				break;
323			case 1:
324				v1_v4_reg_data |= LTC2991_V3_V4_DIFF_EN;
325				break;
326			case 2:
327				v5_v8_reg_data |= LTC2991_V5_V6_DIFF_EN;
328				break;
329			case 3:
330				v5_v8_reg_data |= LTC2991_V7_V8_DIFF_EN;
331				break;
332			default:
333				break;
334			}
335		}
336
337		ret = fwnode_property_read_bool(child,
338						"adi,temperature-enable");
339		if (ret) {
340			st->temp_en[addr] = ret;
341
342			switch (addr) {
343			case 0:
344				v1_v4_reg_data |= LTC2991_V1_V2_TEMP_EN;
345				break;
346			case 1:
347				v1_v4_reg_data |= LTC2991_V3_V4_TEMP_EN;
348				break;
349			case 2:
350				v5_v8_reg_data |= LTC2991_V5_V6_TEMP_EN;
351				break;
352			case 3:
353				v5_v8_reg_data |= LTC2991_V7_V8_TEMP_EN;
354				break;
355			default:
356				break;
357			}
358		}
359	}
360
361	ret = regmap_write(st->regmap, LTC2991_V5_V8_CTRL, v5_v8_reg_data);
362	if (ret)
363		return dev_err_probe(dev, ret,
364				     "Error: Failed to set V5-V8 CTRL reg.\n");
365
366	ret = regmap_write(st->regmap, LTC2991_V1_V4_CTRL, v1_v4_reg_data);
367	if (ret)
368		return dev_err_probe(dev, ret,
369				     "Error: Failed to set V1-V4 CTRL reg.\n");
370
371	ret = regmap_write(st->regmap, LTC2991_PWM_TH_LSB_T_INT,
372			   LTC2991_REPEAT_ACQ_EN);
373	if (ret)
374		return dev_err_probe(dev, ret,
375				     "Error: Failed to set continuous mode.\n");
376
377	/* Enable all channels and trigger conversions */
378	return regmap_write(st->regmap, LTC2991_CH_EN_TRIGGER,
379			    LTC2991_V7_V8_EN | LTC2991_V5_V6_EN |
380			    LTC2991_V3_V4_EN | LTC2991_V1_V2_EN |
381			    LTC2991_T_INT_VCC_EN);
382}
383
384static int ltc2991_i2c_probe(struct i2c_client *client)
385{
386	int ret;
387	struct device *hwmon_dev;
388	struct ltc2991_state *st;
389
390	st = devm_kzalloc(&client->dev, sizeof(*st), GFP_KERNEL);
391	if (!st)
392		return -ENOMEM;
393
394	st->regmap = devm_regmap_init_i2c(client, &ltc2991_regmap_config);
395	if (IS_ERR(st->regmap))
396		return PTR_ERR(st->regmap);
397
398	ret = ltc2991_init(st, &client->dev);
399	if (ret)
400		return ret;
401
402	hwmon_dev = devm_hwmon_device_register_with_info(&client->dev,
403							 client->name, st,
404							 &ltc2991_chip_info,
405							 NULL);
406
407	return PTR_ERR_OR_ZERO(hwmon_dev);
408}
409
410static const struct of_device_id ltc2991_of_match[] = {
411	{ .compatible = "adi,ltc2991" },
412	{ }
413};
414MODULE_DEVICE_TABLE(of, ltc2991_of_match);
415
416static const struct i2c_device_id ltc2991_i2c_id[] = {
417	{ "ltc2991", 0 },
418	{}
419};
420MODULE_DEVICE_TABLE(i2c, ltc2991_i2c_id);
421
422static struct i2c_driver ltc2991_i2c_driver = {
423	.driver = {
424		.name = "ltc2991",
425		.of_match_table = ltc2991_of_match,
426	},
427	.probe = ltc2991_i2c_probe,
428	.id_table = ltc2991_i2c_id,
429};
430
431module_i2c_driver(ltc2991_i2c_driver);
432
433MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
434MODULE_DESCRIPTION("Analog Devices LTC2991 HWMON Driver");
435MODULE_LICENSE("GPL");