brintos

brintos / linux-shallow public Read only

0
0
Text · 4.6 KiB · 21d024b Raw
195 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Copyright (c) 2022 Analog Devices, Inc.4 * ADI MAX77541 ADC Driver with IIO interface5 */6 7#include <linux/bitfield.h>8#include <linux/iio/iio.h>9#include <linux/mod_devicetable.h>10#include <linux/platform_device.h>11#include <linux/regmap.h>12#include <linux/units.h>13 14#include <linux/mfd/max77541.h>15 16enum max77541_adc_range {17	LOW_RANGE,18	MID_RANGE,19	HIGH_RANGE,20};21 22enum max77541_adc_channel {23	MAX77541_ADC_VSYS_V,24	MAX77541_ADC_VOUT1_V,25	MAX77541_ADC_VOUT2_V,26	MAX77541_ADC_TEMP,27};28 29static int max77541_adc_offset(struct iio_dev *indio_dev,30			       struct iio_chan_spec const *chan,31			       int *val, int *val2)32{33	switch (chan->channel) {34	case MAX77541_ADC_TEMP:35		*val = DIV_ROUND_CLOSEST(ABSOLUTE_ZERO_MILLICELSIUS, 1725);36		return IIO_VAL_INT;37	default:38		return -EINVAL;39	}40}41 42static int max77541_adc_scale(struct iio_dev *indio_dev,43			      struct iio_chan_spec const *chan,44			      int *val, int *val2)45{46	struct regmap **regmap = iio_priv(indio_dev);47	unsigned int reg_val;48	int ret;49 50	switch (chan->channel) {51	case MAX77541_ADC_VSYS_V:52		*val = 25;53		return IIO_VAL_INT;54	case MAX77541_ADC_VOUT1_V:55	case MAX77541_ADC_VOUT2_V:56		ret = regmap_read(*regmap, MAX77541_REG_M2_CFG1, &reg_val);57		if (ret)58			return ret;59 60		reg_val = FIELD_GET(MAX77541_BITS_MX_CFG1_RNG, reg_val);61		switch (reg_val) {62		case LOW_RANGE:63			*val = 6;64			*val2 = 250000;65			break;66		case MID_RANGE:67			*val = 12;68			*val2 = 500000;69			break;70		case HIGH_RANGE:71			*val = 25;72			return IIO_VAL_INT;73		default:74			return -EINVAL;75		}76 77		return IIO_VAL_INT_PLUS_MICRO;78	case MAX77541_ADC_TEMP:79		*val = 1725;80		return IIO_VAL_INT;81	default:82		return -EINVAL;83	}84}85 86static int max77541_adc_raw(struct iio_dev *indio_dev,87			    struct iio_chan_spec const *chan,88			    int *val)89{90	struct regmap **regmap = iio_priv(indio_dev);91	int ret;92 93	ret = regmap_read(*regmap, chan->address, val);94	if (ret)95		return ret;96 97	return IIO_VAL_INT;98}99 100#define MAX77541_ADC_CHANNEL_V(_channel, _name, _type, _reg) \101	{							\102		.type = _type,					\103		.indexed = 1,					\104		.channel = _channel,				\105		.address = _reg,				\106		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\107				      BIT(IIO_CHAN_INFO_SCALE), \108		.datasheet_name = _name,			\109	}110 111#define MAX77541_ADC_CHANNEL_TEMP(_channel, _name, _type, _reg) \112	{							\113		.type = _type,					\114		.indexed = 1,					\115		.channel = _channel,				\116		.address = _reg,				\117		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |	\118				      BIT(IIO_CHAN_INFO_SCALE) |\119				      BIT(IIO_CHAN_INFO_OFFSET),\120		.datasheet_name = _name,			\121	}122 123static const struct iio_chan_spec max77541_adc_channels[] = {124	MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VSYS_V, "vsys_v", IIO_VOLTAGE,125			       MAX77541_REG_ADC_DATA_CH1),126	MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT1_V, "vout1_v", IIO_VOLTAGE,127			       MAX77541_REG_ADC_DATA_CH2),128	MAX77541_ADC_CHANNEL_V(MAX77541_ADC_VOUT2_V, "vout2_v", IIO_VOLTAGE,129			       MAX77541_REG_ADC_DATA_CH3),130	MAX77541_ADC_CHANNEL_TEMP(MAX77541_ADC_TEMP, "temp", IIO_TEMP,131				  MAX77541_REG_ADC_DATA_CH6),132};133 134static int max77541_adc_read_raw(struct iio_dev *indio_dev,135				 struct iio_chan_spec const *chan,136				 int *val, int *val2, long mask)137{138	switch (mask) {139	case IIO_CHAN_INFO_OFFSET:140		return max77541_adc_offset(indio_dev, chan, val, val2);141	case IIO_CHAN_INFO_SCALE:142		return max77541_adc_scale(indio_dev, chan, val, val2);143	case IIO_CHAN_INFO_RAW:144		return max77541_adc_raw(indio_dev, chan, val);145	default:146		return -EINVAL;147	}148}149 150static const struct iio_info max77541_adc_info = {151	.read_raw = max77541_adc_read_raw,152};153 154static int max77541_adc_probe(struct platform_device *pdev)155{156	struct device *dev = &pdev->dev;157	struct iio_dev *indio_dev;158	struct regmap **regmap;159 160	indio_dev = devm_iio_device_alloc(dev, sizeof(*regmap));161	if (!indio_dev)162		return -ENOMEM;163 164	regmap = iio_priv(indio_dev);165 166	*regmap = dev_get_regmap(dev->parent, NULL);167	indio_dev->modes = INDIO_DIRECT_MODE;168 169	indio_dev->name = "max77541";170	indio_dev->info = &max77541_adc_info;171	indio_dev->channels = max77541_adc_channels;172	indio_dev->num_channels = ARRAY_SIZE(max77541_adc_channels);173 174	return devm_iio_device_register(dev, indio_dev);175}176 177static const struct platform_device_id max77541_adc_platform_id[] = {178	{ "max77541-adc" },179	{ /* sentinel */ }180};181MODULE_DEVICE_TABLE(platform, max77541_adc_platform_id);182 183static struct platform_driver max77541_adc_driver = {184	.driver = {185		.name = "max77541-adc",186	},187	.probe = max77541_adc_probe,188	.id_table = max77541_adc_platform_id,189};190module_platform_driver(max77541_adc_driver);191 192MODULE_AUTHOR("Okan Sahin <Okan.Sahin@analog.com>");193MODULE_DESCRIPTION("MAX77541 ADC driver");194MODULE_LICENSE("GPL");195