File Index
Files and directories
Sign in
FILE

nct7201.c

File preview with syntax highlighting.

linux-6.19.14/drivers/iio/adc/nct7201.c C
  1// SPDX-License-Identifier: GPL-2.0+
  2/*
  3 * Driver for Nuvoton nct7201 and nct7202 power monitor chips.
  4 *
  5 * Copyright (c) 2024-2025 Nuvoton Technology corporation.
  6 */
  7
  8#include <linux/array_size.h>
  9#include <linux/bitfield.h>
 10#include <linux/bits.h>
 11#include <linux/delay.h>
 12#include <linux/dev_printk.h>
 13#include <linux/err.h>
 14#include <linux/i2c.h>
 15#include <linux/mod_devicetable.h>
 16#include <linux/module.h>
 17#include <linux/regmap.h>
 18#include <linux/time.h>
 19#include <linux/types.h>
 20#include <linux/unaligned.h>
 21
 22#include <linux/iio/events.h>
 23#include <linux/iio/iio.h>
 24
 25#define NCT7201_REG_INTERRUPT_STATUS			0x0C
 26#define NCT7201_REG_VOLT_LOW_BYTE			0x0F
 27#define NCT7201_REG_CONFIGURATION			0x10
 28#define  NCT7201_BIT_CONFIGURATION_START		BIT(0)
 29#define  NCT7201_BIT_CONFIGURATION_ALERT_MSK		BIT(1)
 30#define  NCT7201_BIT_CONFIGURATION_CONV_RATE		BIT(2)
 31#define  NCT7201_BIT_CONFIGURATION_RESET		BIT(7)
 32
 33#define NCT7201_REG_ADVANCED_CONFIGURATION		0x11
 34#define  NCT7201_BIT_ADVANCED_CONF_MOD_ALERT		BIT(0)
 35#define  NCT7201_BIT_ADVANCED_CONF_MOD_STS		BIT(1)
 36#define  NCT7201_BIT_ADVANCED_CONF_FAULT_QUEUE		BIT(2)
 37#define  NCT7201_BIT_ADVANCED_CONF_EN_DEEP_SHUTDOWN	BIT(4)
 38#define  NCT7201_BIT_ADVANCED_CONF_EN_SMB_TIMEOUT	BIT(5)
 39#define  NCT7201_BIT_ADVANCED_CONF_MOD_RSTIN		BIT(7)
 40
 41#define NCT7201_REG_CHANNEL_INPUT_MODE			0x12
 42#define NCT7201_REG_CHANNEL_ENABLE			0x13
 43#define NCT7201_REG_INTERRUPT_MASK_1			0x15
 44#define NCT7201_REG_INTERRUPT_MASK_2			0x16
 45#define NCT7201_REG_BUSY_STATUS			0x1E
 46#define  NCT7201_BIT_BUSY				BIT(0)
 47#define  NCT7201_BIT_PWR_UP				BIT(1)
 48#define NCT7201_REG_ONE_SHOT				0x1F
 49#define NCT7201_REG_SMUS_ADDRESS			0xFC
 50#define NCT7201_REG_VIN_MASK				GENMASK(15, 3)
 51
 52#define NCT7201_REG_VIN(i)				(0x00 + i)
 53#define NCT7201_REG_VIN_HIGH_LIMIT(i)			(0x20 + (i) * 2)
 54#define NCT7201_REG_VIN_LOW_LIMIT(i)			(0x21 + (i) * 2)
 55#define NCT7201_MAX_CHANNEL				12
 56
 57static const struct regmap_range nct7201_read_reg_range[] = {
 58	regmap_reg_range(NCT7201_REG_INTERRUPT_STATUS, NCT7201_REG_BUSY_STATUS),
 59	regmap_reg_range(NCT7201_REG_SMUS_ADDRESS, NCT7201_REG_SMUS_ADDRESS),
 60};
 61
 62static const struct regmap_access_table nct7201_readable_regs_tbl = {
 63	.yes_ranges = nct7201_read_reg_range,
 64	.n_yes_ranges = ARRAY_SIZE(nct7201_read_reg_range),
 65};
 66
 67static const struct regmap_range nct7201_write_reg_range[] = {
 68	regmap_reg_range(NCT7201_REG_CONFIGURATION, NCT7201_REG_INTERRUPT_MASK_2),
 69	regmap_reg_range(NCT7201_REG_ONE_SHOT, NCT7201_REG_ONE_SHOT),
 70};
 71
 72static const struct regmap_access_table nct7201_writeable_regs_tbl = {
 73	.yes_ranges = nct7201_write_reg_range,
 74	.n_yes_ranges = ARRAY_SIZE(nct7201_write_reg_range),
 75};
 76
 77static const struct regmap_range nct7201_read_vin_reg_range[] = {
 78	regmap_reg_range(NCT7201_REG_VIN(0), NCT7201_REG_VIN(NCT7201_MAX_CHANNEL - 1)),
 79	regmap_reg_range(NCT7201_REG_VIN_HIGH_LIMIT(0),
 80			 NCT7201_REG_VIN_LOW_LIMIT(NCT7201_MAX_CHANNEL - 1)),
 81};
 82
 83static const struct regmap_access_table nct7201_readable_vin_regs_tbl = {
 84	.yes_ranges = nct7201_read_vin_reg_range,
 85	.n_yes_ranges = ARRAY_SIZE(nct7201_read_vin_reg_range),
 86};
 87
 88static const struct regmap_range nct7201_write_vin_reg_range[] = {
 89	regmap_reg_range(NCT7201_REG_VIN_HIGH_LIMIT(0),
 90			 NCT7201_REG_VIN_LOW_LIMIT(NCT7201_MAX_CHANNEL - 1)),
 91};
 92
 93static const struct regmap_access_table nct7201_writeable_vin_regs_tbl = {
 94	.yes_ranges = nct7201_write_vin_reg_range,
 95	.n_yes_ranges = ARRAY_SIZE(nct7201_write_vin_reg_range),
 96};
 97
 98static const struct regmap_config nct7201_regmap8_config = {
 99	.name = "vin-data-read-byte",
100	.reg_bits = 8,
101	.val_bits = 8,
102	.use_single_read = true,
103	.use_single_write = true,
104	.max_register = 0xff,
105	.rd_table = &nct7201_readable_regs_tbl,
106	.wr_table = &nct7201_writeable_regs_tbl,
107};
108
109static const struct regmap_config nct7201_regmap16_config = {
110	.name = "vin-data-read-word",
111	.reg_bits = 8,
112	.val_bits = 16,
113	.max_register = 0xff,
114	.rd_table = &nct7201_readable_vin_regs_tbl,
115	.wr_table = &nct7201_writeable_vin_regs_tbl,
116};
117
118struct nct7201_chip_info {
119	struct regmap *regmap;
120	struct regmap *regmap16;
121	int num_vin_channels;
122	__le16 vin_mask;
123};
124
125struct nct7201_adc_model_data {
126	const char *model_name;
127	const struct iio_chan_spec *channels;
128	unsigned int num_channels;
129	int num_vin_channels;
130};
131
132static const struct iio_event_spec nct7201_events[] = {
133	{
134		.type = IIO_EV_TYPE_THRESH,
135		.dir = IIO_EV_DIR_RISING,
136		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
137				 BIT(IIO_EV_INFO_ENABLE),
138	}, {
139		.type = IIO_EV_TYPE_THRESH,
140		.dir = IIO_EV_DIR_FALLING,
141		.mask_separate = BIT(IIO_EV_INFO_VALUE) |
142				 BIT(IIO_EV_INFO_ENABLE),
143	},
144};
145
146#define NCT7201_VOLTAGE_CHANNEL(num)					\
147	{								\
148		.type = IIO_VOLTAGE,					\
149		.indexed = 1,						\
150		.channel = num + 1,					\
151		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
152		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
153		.address = num,						\
154		.event_spec = nct7201_events,				\
155		.num_event_specs = ARRAY_SIZE(nct7201_events),		\
156	}
157
158static const struct iio_chan_spec nct7201_channels[] = {
159	NCT7201_VOLTAGE_CHANNEL(0),
160	NCT7201_VOLTAGE_CHANNEL(1),
161	NCT7201_VOLTAGE_CHANNEL(2),
162	NCT7201_VOLTAGE_CHANNEL(3),
163	NCT7201_VOLTAGE_CHANNEL(4),
164	NCT7201_VOLTAGE_CHANNEL(5),
165	NCT7201_VOLTAGE_CHANNEL(6),
166	NCT7201_VOLTAGE_CHANNEL(7),
167};
168
169static const struct iio_chan_spec nct7202_channels[] = {
170	NCT7201_VOLTAGE_CHANNEL(0),
171	NCT7201_VOLTAGE_CHANNEL(1),
172	NCT7201_VOLTAGE_CHANNEL(2),
173	NCT7201_VOLTAGE_CHANNEL(3),
174	NCT7201_VOLTAGE_CHANNEL(4),
175	NCT7201_VOLTAGE_CHANNEL(5),
176	NCT7201_VOLTAGE_CHANNEL(6),
177	NCT7201_VOLTAGE_CHANNEL(7),
178	NCT7201_VOLTAGE_CHANNEL(8),
179	NCT7201_VOLTAGE_CHANNEL(9),
180	NCT7201_VOLTAGE_CHANNEL(10),
181	NCT7201_VOLTAGE_CHANNEL(11),
182};
183
184static int nct7201_read_raw(struct iio_dev *indio_dev,
185			    struct iio_chan_spec const *chan,
186			    int *val, int *val2, long mask)
187{
188	struct nct7201_chip_info *chip = iio_priv(indio_dev);
189	unsigned int value;
190	int err;
191
192	if (chan->type != IIO_VOLTAGE)
193		return -EOPNOTSUPP;
194
195	switch (mask) {
196	case IIO_CHAN_INFO_RAW:
197		err = regmap_read(chip->regmap16, NCT7201_REG_VIN(chan->address), &value);
198		if (err)
199			return err;
200		*val = FIELD_GET(NCT7201_REG_VIN_MASK, value);
201		return IIO_VAL_INT;
202	case IIO_CHAN_INFO_SCALE:
203		/* From the datasheet, we have to multiply by 0.0004995 */
204		*val = 0;
205		*val2 = 499500;
206		return IIO_VAL_INT_PLUS_NANO;
207	default:
208		return -EINVAL;
209	}
210}
211
212static int nct7201_read_event_value(struct iio_dev *indio_dev,
213				    const struct iio_chan_spec *chan,
214				    enum iio_event_type type,
215				    enum iio_event_direction dir,
216				    enum iio_event_info info,
217				    int *val, int *val2)
218{
219	struct nct7201_chip_info *chip = iio_priv(indio_dev);
220	unsigned int value;
221	int err;
222
223	if (chan->type != IIO_VOLTAGE)
224		return -EOPNOTSUPP;
225
226	if (info != IIO_EV_INFO_VALUE)
227		return -EINVAL;
228
229	if (dir == IIO_EV_DIR_FALLING)
230		err = regmap_read(chip->regmap16, NCT7201_REG_VIN_LOW_LIMIT(chan->address),
231				  &value);
232	else
233		err = regmap_read(chip->regmap16, NCT7201_REG_VIN_HIGH_LIMIT(chan->address),
234				  &value);
235	if (err)
236		return err;
237
238	*val = FIELD_GET(NCT7201_REG_VIN_MASK, value);
239
240	return IIO_VAL_INT;
241}
242
243static int nct7201_write_event_value(struct iio_dev *indio_dev,
244				     const struct iio_chan_spec *chan,
245				     enum iio_event_type type,
246				     enum iio_event_direction dir,
247				     enum iio_event_info info,
248				     int val, int val2)
249{
250	struct nct7201_chip_info *chip = iio_priv(indio_dev);
251	int err;
252
253	if (chan->type != IIO_VOLTAGE)
254		return -EOPNOTSUPP;
255
256	if (info != IIO_EV_INFO_VALUE)
257		return -EOPNOTSUPP;
258
259	if (dir == IIO_EV_DIR_FALLING)
260		err = regmap_write(chip->regmap16, NCT7201_REG_VIN_LOW_LIMIT(chan->address),
261				   FIELD_PREP(NCT7201_REG_VIN_MASK, val));
262	else
263		err = regmap_write(chip->regmap16, NCT7201_REG_VIN_HIGH_LIMIT(chan->address),
264				   FIELD_PREP(NCT7201_REG_VIN_MASK, val));
265
266	return err;
267}
268
269static int nct7201_read_event_config(struct iio_dev *indio_dev,
270				     const struct iio_chan_spec *chan,
271				     enum iio_event_type type,
272				     enum iio_event_direction dir)
273{
274	struct nct7201_chip_info *chip = iio_priv(indio_dev);
275
276	if (chan->type != IIO_VOLTAGE)
277		return -EOPNOTSUPP;
278
279	return !!(le16_to_cpu(chip->vin_mask) & BIT(chan->address));
280}
281
282static int nct7201_write_event_config(struct iio_dev *indio_dev,
283				      const struct iio_chan_spec *chan,
284				      enum iio_event_type type,
285				      enum iio_event_direction dir,
286				      bool state)
287{
288	struct nct7201_chip_info *chip = iio_priv(indio_dev);
289	__le16 mask = cpu_to_le16(BIT(chan->address));
290	int err;
291
292	if (chan->type != IIO_VOLTAGE)
293		return -EOPNOTSUPP;
294
295	if (state)
296		chip->vin_mask |= mask;
297	else
298		chip->vin_mask &= ~mask;
299
300	if (chip->num_vin_channels <= 8)
301		err = regmap_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE,
302				   le16_to_cpu(chip->vin_mask));
303	else
304		err = regmap_bulk_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE,
305					&chip->vin_mask, sizeof(chip->vin_mask));
306
307	return err;
308}
309
310static const struct iio_info nct7201_info = {
311	.read_raw = nct7201_read_raw,
312	.read_event_config = nct7201_read_event_config,
313	.write_event_config = nct7201_write_event_config,
314	.read_event_value = nct7201_read_event_value,
315	.write_event_value = nct7201_write_event_value,
316};
317
318static const struct iio_info nct7201_info_no_irq = {
319	.read_raw = nct7201_read_raw,
320};
321
322static const struct nct7201_adc_model_data nct7201_model_data = {
323	.model_name = "nct7201",
324	.channels = nct7201_channels,
325	.num_channels = ARRAY_SIZE(nct7201_channels),
326	.num_vin_channels = 8,
327};
328
329static const struct nct7201_adc_model_data nct7202_model_data = {
330	.model_name = "nct7202",
331	.channels = nct7202_channels,
332	.num_channels = ARRAY_SIZE(nct7202_channels),
333	.num_vin_channels = 12,
334};
335
336static int nct7201_init_chip(struct nct7201_chip_info *chip)
337{
338	struct device *dev = regmap_get_device(chip->regmap);
339	__le16 data = cpu_to_le16(GENMASK(chip->num_vin_channels - 1, 0));
340	unsigned int value;
341	int err;
342
343	err = regmap_write(chip->regmap, NCT7201_REG_CONFIGURATION,
344			   NCT7201_BIT_CONFIGURATION_RESET);
345	if (err)
346		return dev_err_probe(dev, err, "Failed to reset chip\n");
347
348	/*
349	 * After about 25 msecs, the device should be ready and then the power-up
350	 * bit will be set to 1.
351	 */
352	fsleep(25 * USEC_PER_MSEC);
353
354	err = regmap_read(chip->regmap, NCT7201_REG_BUSY_STATUS, &value);
355	if (err)
356		return dev_err_probe(dev, err, "Failed to read busy status\n");
357	if (!(value & NCT7201_BIT_PWR_UP))
358		return dev_err_probe(dev, -EIO, "Failed to power up after reset\n");
359
360	/* Enable Channels */
361	if (chip->num_vin_channels <= 8)
362		err = regmap_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE,
363				   le16_to_cpu(data));
364	else
365		err = regmap_bulk_write(chip->regmap, NCT7201_REG_CHANNEL_ENABLE,
366					&data, sizeof(data));
367	if (err)
368		return dev_err_probe(dev, err, "Failed to enable channels\n");
369
370	err = regmap_bulk_read(chip->regmap, NCT7201_REG_CHANNEL_ENABLE,
371			       &chip->vin_mask, sizeof(chip->vin_mask));
372	if (err)
373		return dev_err_probe(dev, err,
374				     "Failed to read channel enable register\n");
375
376	/* Start monitoring if needed */
377	err = regmap_set_bits(chip->regmap, NCT7201_REG_CONFIGURATION,
378			      NCT7201_BIT_CONFIGURATION_START);
379	if (err)
380		return dev_err_probe(dev, err, "Failed to start monitoring\n");
381
382	return 0;
383}
384
385static irqreturn_t nct7201_irq_handler(int irq, void *private)
386{
387	struct iio_dev *indio_dev = private;
388	struct nct7201_chip_info *chip = iio_priv(indio_dev);
389	__le16 data;
390	int err;
391
392	err = regmap_bulk_read(chip->regmap, NCT7201_REG_INTERRUPT_STATUS,
393			       &data, sizeof(data));
394	if (err)
395		return IRQ_NONE;
396
397	if (data)
398		iio_push_event(indio_dev,
399			       IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE,
400						    0,
401						    IIO_EV_TYPE_THRESH,
402						    IIO_EV_DIR_EITHER),
403			       iio_get_time_ns(indio_dev));
404
405	return IRQ_HANDLED;
406}
407
408static int nct7201_probe(struct i2c_client *client)
409{
410	const struct nct7201_adc_model_data *model_data;
411	struct device *dev = &client->dev;
412	struct nct7201_chip_info *chip;
413	struct iio_dev *indio_dev;
414	int ret;
415
416	model_data = i2c_get_match_data(client);
417	if (!model_data)
418		return -ENODEV;
419
420	indio_dev = devm_iio_device_alloc(dev, sizeof(*chip));
421	if (!indio_dev)
422		return -ENOMEM;
423	chip = iio_priv(indio_dev);
424
425	chip->regmap = devm_regmap_init_i2c(client, &nct7201_regmap8_config);
426	if (IS_ERR(chip->regmap))
427		return dev_err_probe(dev, PTR_ERR(chip->regmap),
428				     "Failed to init regmap\n");
429
430	chip->regmap16 = devm_regmap_init_i2c(client, &nct7201_regmap16_config);
431	if (IS_ERR(chip->regmap16))
432		return dev_err_probe(dev, PTR_ERR(chip->regmap16),
433				     "Failed to init regmap16\n");
434
435	chip->num_vin_channels = model_data->num_vin_channels;
436
437	ret = nct7201_init_chip(chip);
438	if (ret)
439		return ret;
440
441	indio_dev->name = model_data->model_name;
442	indio_dev->channels = model_data->channels;
443	indio_dev->num_channels = model_data->num_channels;
444	if (client->irq) {
445		/* Enable alert function */
446		ret = regmap_clear_bits(chip->regmap, NCT7201_REG_CONFIGURATION,
447				      NCT7201_BIT_CONFIGURATION_ALERT_MSK);
448		if (ret)
449			return dev_err_probe(dev, ret,
450					     "Failed to enable alert function\n");
451
452		ret = devm_request_threaded_irq(dev, client->irq,
453						NULL, nct7201_irq_handler,
454						IRQF_TRIGGER_LOW | IRQF_ONESHOT,
455						client->name, indio_dev);
456		if (ret)
457			return dev_err_probe(dev, ret,
458					     "Failed to assign interrupt.\n");
459
460		indio_dev->info = &nct7201_info;
461	} else {
462		indio_dev->info = &nct7201_info_no_irq;
463	}
464	indio_dev->modes = INDIO_DIRECT_MODE;
465
466	return devm_iio_device_register(dev, indio_dev);
467}
468
469static const struct i2c_device_id nct7201_id[] = {
470	{ .name = "nct7201", .driver_data = (kernel_ulong_t)&nct7201_model_data },
471	{ .name = "nct7202", .driver_data = (kernel_ulong_t)&nct7202_model_data },
472	{ }
473};
474MODULE_DEVICE_TABLE(i2c, nct7201_id);
475
476static const struct of_device_id nct7201_of_match[] = {
477	{
478		.compatible = "nuvoton,nct7201",
479		.data = &nct7201_model_data,
480	},
481	{
482		.compatible = "nuvoton,nct7202",
483		.data = &nct7202_model_data,
484	},
485	{ }
486};
487MODULE_DEVICE_TABLE(of, nct7201_of_match);
488
489static struct i2c_driver nct7201_driver = {
490	.driver = {
491		.name	= "nct7201",
492		.of_match_table = nct7201_of_match,
493	},
494	.probe = nct7201_probe,
495	.id_table = nct7201_id,
496};
497module_i2c_driver(nct7201_driver);
498
499MODULE_AUTHOR("Eason Yang <j2anfernee@gmail.com>");
500MODULE_DESCRIPTION("Nuvoton NCT7201 voltage monitor driver");
501MODULE_LICENSE("GPL");
~/ Read-only file preview.