brintos

brintos / linux-shallow public Read only

0
0
Text · 12.4 KiB · 66b54c0 Raw
475 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * IIO driver for Texas Instruments ADS7924 ADC, 12-bit, 4-Channels, I2C4 *5 * Author: Hugo Villeneuve <hvilleneuve@dimonoff.com>6 * Copyright 2022 DimOnOff7 *8 * based on iio/adc/ti-ads1015.c9 * Copyright (c) 2016, Intel Corporation.10 *11 * Datasheet: https://www.ti.com/lit/gpn/ads792412 */13 14#include <linux/bitfield.h>15#include <linux/delay.h>16#include <linux/gpio/consumer.h>17#include <linux/init.h>18#include <linux/irq.h>19#include <linux/i2c.h>20#include <linux/module.h>21#include <linux/mutex.h>22#include <linux/regmap.h>23#include <linux/regulator/consumer.h>24 25#include <linux/iio/iio.h>26#include <linux/iio/types.h>27 28#define ADS7924_CHANNELS	 429#define ADS7924_BITS		1230#define ADS7924_DATA_SHIFT	 431 32/* Registers. */33#define ADS7924_MODECNTRL_REG	0x0034#define ADS7924_INTCNTRL_REG	0x0135#define ADS7924_DATA0_U_REG	0x0236#define ADS7924_DATA0_L_REG	0x0337#define ADS7924_DATA1_U_REG	0x0438#define ADS7924_DATA1_L_REG	0x0539#define ADS7924_DATA2_U_REG	0x0640#define ADS7924_DATA2_L_REG	0x0741#define ADS7924_DATA3_U_REG	0x0842#define ADS7924_DATA3_L_REG	0x0943#define ADS7924_ULR0_REG	0x0A44#define ADS7924_LLR0_REG	0x0B45#define ADS7924_ULR1_REG	0x0C46#define ADS7924_LLR1_REG	0x0D47#define ADS7924_ULR2_REG	0x0E48#define ADS7924_LLR2_REG	0x0F49#define ADS7924_ULR3_REG	0x1050#define ADS7924_LLR3_REG	0x1151#define ADS7924_INTCONFIG_REG	0x1252#define ADS7924_SLPCONFIG_REG	0x1353#define ADS7924_ACQCONFIG_REG	0x1454#define ADS7924_PWRCONFIG_REG	0x1555#define ADS7924_RESET_REG	0x1656 57/*58 * Register address INC bit: when set to '1', the register address is59 * automatically incremented after every register read which allows convenient60 * reading of multiple registers. Set INC to '0' when reading a single register.61 */62#define ADS7924_AUTO_INCREMENT_BIT	BIT(7)63 64#define ADS7924_MODECNTRL_MODE_MASK	GENMASK(7, 2)65 66#define ADS7924_MODECNTRL_SEL_MASK	GENMASK(1, 0)67 68#define ADS7924_CFG_INTPOL_BIT		169#define ADS7924_CFG_INTTRIG_BIT		070 71#define ADS7924_CFG_INTPOL_MASK		BIT(ADS7924_CFG_INTPOL_BIT)72#define ADS7924_CFG_INTTRIG_MASK	BIT(ADS7924_CFG_INTTRIG_BIT)73 74/* Interrupt pin polarity */75#define ADS7924_CFG_INTPOL_LOW		076#define ADS7924_CFG_INTPOL_HIGH		177 78/* Interrupt pin signaling */79#define ADS7924_CFG_INTTRIG_LEVEL	080#define ADS7924_CFG_INTTRIG_EDGE	181 82/* Mode control values */83#define ADS7924_MODECNTRL_IDLE			0x0084#define ADS7924_MODECNTRL_AWAKE			0x2085#define ADS7924_MODECNTRL_MANUAL_SINGLE		0x3086#define ADS7924_MODECNTRL_MANUAL_SCAN		0x3287#define ADS7924_MODECNTRL_AUTO_SINGLE		0x3188#define ADS7924_MODECNTRL_AUTO_SCAN		0x3389#define ADS7924_MODECNTRL_AUTO_SINGLE_SLEEP	0x3990#define ADS7924_MODECNTRL_AUTO_SCAN_SLEEP	0x3B91#define ADS7924_MODECNTRL_AUTO_BURST_SLEEP	0x3F92 93#define ADS7924_ACQTIME_MASK	GENMASK(4, 0)94 95#define ADS7924_PWRUPTIME_MASK	GENMASK(4, 0)96 97/*98 * The power-up time is allowed to elapse whenever the device has been shutdown99 * in idle mode. Power-up time can allow external circuits, such as an100 * operational amplifier, between the MUXOUT and ADCIN pins to turn on.101 * The nominal time programmed by the PUTIME[4:0] register bits is given by:102 *     t PU = PWRUPTIME[4:0] × 2 μs103 * If a power-up time is not required, set the bits to '0' to effectively bypass.104 */105#define ADS7924_PWRUPTIME_US 0 /* Bypass (0us). */106 107/*108 * Acquisition Time according to ACQTIME[4:0] register bits.109 * The Acquisition Time is given by:110 *     t ACQ = (ACQTIME[4:0] × 2 μs) + 6 μs111 * Using default value of 0 for ACQTIME[4:0] results in a minimum acquisition112 * time of 6us.113 */114#define ADS7924_ACQTIME_US 6115 116/* The conversion time is always 4μs and cannot be programmed by the user. */117#define ADS7924_CONVTIME_US 4118 119#define ADS7924_TOTAL_CONVTIME_US (ADS7924_PWRUPTIME_US + ADS7924_ACQTIME_US + \120				   ADS7924_CONVTIME_US)121 122#define ADS7924_V_CHAN(_chan, _addr) {				\123	.type = IIO_VOLTAGE,					\124	.indexed = 1,						\125	.channel = _chan,					\126	.address = _addr,					\127	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), 		\128	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\129	.datasheet_name = "AIN"#_chan,				\130}131 132struct ads7924_data {133	struct device *dev;134	struct regmap *regmap;135	struct regulator *vref_reg;136 137	/* GPIO descriptor for device hard-reset pin. */138	struct gpio_desc *reset_gpio;139 140	/*141	 * Protects ADC ops, e.g: concurrent sysfs/buffered142	 * data reads, configuration updates143	 */144	struct mutex lock;145 146	/*147	 * Set to true when the ADC is switched to the continuous-conversion148	 * mode and exits from a power-down state. This flag is used to avoid149	 * getting the stale result from the conversion register.150	 */151	bool conv_invalid;152};153 154static bool ads7924_is_writeable_reg(struct device *dev, unsigned int reg)155{156	switch (reg) {157	case ADS7924_MODECNTRL_REG:158	case ADS7924_INTCNTRL_REG:159	case ADS7924_ULR0_REG:160	case ADS7924_LLR0_REG:161	case ADS7924_ULR1_REG:162	case ADS7924_LLR1_REG:163	case ADS7924_ULR2_REG:164	case ADS7924_LLR2_REG:165	case ADS7924_ULR3_REG:166	case ADS7924_LLR3_REG:167	case ADS7924_INTCONFIG_REG:168	case ADS7924_SLPCONFIG_REG:169	case ADS7924_ACQCONFIG_REG:170	case ADS7924_PWRCONFIG_REG:171	case ADS7924_RESET_REG:172		return true;173	default:174		return false;175	}176}177 178static const struct regmap_config ads7924_regmap_config = {179	.reg_bits = 8,180	.val_bits = 8,181	.max_register = ADS7924_RESET_REG,182	.writeable_reg = ads7924_is_writeable_reg,183};184 185static const struct iio_chan_spec ads7924_channels[] = {186	ADS7924_V_CHAN(0, ADS7924_DATA0_U_REG),187	ADS7924_V_CHAN(1, ADS7924_DATA1_U_REG),188	ADS7924_V_CHAN(2, ADS7924_DATA2_U_REG),189	ADS7924_V_CHAN(3, ADS7924_DATA3_U_REG),190};191 192static int ads7924_get_adc_result(struct ads7924_data *data,193				  struct iio_chan_spec const *chan, int *val)194{195	int ret;196	__be16 be_val;197 198	if (chan->channel < 0 || chan->channel >= ADS7924_CHANNELS)199		return -EINVAL;200 201	if (data->conv_invalid) {202		int conv_time;203 204		conv_time = ADS7924_TOTAL_CONVTIME_US;205		/* Allow 10% for internal clock inaccuracy. */206		conv_time += conv_time / 10;207		usleep_range(conv_time, conv_time + 1);208		data->conv_invalid = false;209	}210 211	ret = regmap_raw_read(data->regmap, ADS7924_AUTO_INCREMENT_BIT |212			      chan->address, &be_val, sizeof(be_val));213	if (ret)214		return ret;215 216	*val = be16_to_cpu(be_val) >> ADS7924_DATA_SHIFT;217 218	return 0;219}220 221static int ads7924_read_raw(struct iio_dev *indio_dev,222			    struct iio_chan_spec const *chan, int *val,223			    int *val2, long mask)224{225	int ret, vref_uv;226	struct ads7924_data *data = iio_priv(indio_dev);227 228	switch (mask) {229	case IIO_CHAN_INFO_RAW:230		mutex_lock(&data->lock);231		ret = ads7924_get_adc_result(data, chan, val);232		mutex_unlock(&data->lock);233		if (ret < 0)234			return ret;235 236		return IIO_VAL_INT;237	case IIO_CHAN_INFO_SCALE:238		vref_uv = regulator_get_voltage(data->vref_reg);239		if (vref_uv < 0)240			return vref_uv;241 242		*val =  vref_uv / 1000; /* Convert reg voltage to mV */243		*val2 = ADS7924_BITS;244		return IIO_VAL_FRACTIONAL_LOG2;245	default:246		return -EINVAL;247	}248}249 250static const struct iio_info ads7924_info = {251	.read_raw = ads7924_read_raw,252};253 254static int ads7924_get_channels_config(struct i2c_client *client,255				       struct iio_dev *indio_dev)256{257	struct ads7924_data *priv = iio_priv(indio_dev);258	struct device *dev = priv->dev;259	struct fwnode_handle *node;260	int num_channels = 0;261 262	device_for_each_child_node(dev, node) {263		u32 pval;264		unsigned int channel;265 266		if (fwnode_property_read_u32(node, "reg", &pval)) {267			dev_err(dev, "invalid reg on %pfw\n", node);268			continue;269		}270 271		channel = pval;272		if (channel >= ADS7924_CHANNELS) {273			dev_err(dev, "invalid channel index %d on %pfw\n",274				channel, node);275			continue;276		}277 278		num_channels++;279	}280 281	if (!num_channels)282		return -EINVAL;283 284	return 0;285}286 287static int ads7924_set_conv_mode(struct ads7924_data *data, int mode)288{289	int ret;290	unsigned int mode_field;291	struct device *dev = data->dev;292 293	/*294	 * When switching between modes, be sure to first select the Awake mode295	 * and then switch to the desired mode. This procedure ensures the296	 * internal control logic is properly synchronized.297	 */298	if (mode != ADS7924_MODECNTRL_IDLE) {299		mode_field = FIELD_PREP(ADS7924_MODECNTRL_MODE_MASK,300					ADS7924_MODECNTRL_AWAKE);301 302		ret = regmap_update_bits(data->regmap, ADS7924_MODECNTRL_REG,303					 ADS7924_MODECNTRL_MODE_MASK,304					 mode_field);305		if (ret) {306			dev_err(dev, "failed to set awake mode (%pe)\n",307				ERR_PTR(ret));308			return ret;309		}310	}311 312	mode_field = FIELD_PREP(ADS7924_MODECNTRL_MODE_MASK, mode);313 314	ret = regmap_update_bits(data->regmap, ADS7924_MODECNTRL_REG,315				 ADS7924_MODECNTRL_MODE_MASK, mode_field);316	if (ret)317		dev_err(dev, "failed to set mode %d (%pe)\n", mode,318			ERR_PTR(ret));319 320	return ret;321}322 323static int ads7924_reset(struct iio_dev *indio_dev)324{325	struct ads7924_data *data = iio_priv(indio_dev);326 327	if (data->reset_gpio) {328		gpiod_set_value(data->reset_gpio, 1); /* Assert. */329		/* Educated guess: assert time not specified in datasheet... */330		mdelay(100);331		gpiod_set_value(data->reset_gpio, 0); /* Deassert. */332		return 0;333	}334 335	/*336	 * A write of 10101010 to this register will generate a337	 * software reset of the ADS7924.338	 */339	return regmap_write(data->regmap, ADS7924_RESET_REG, 0b10101010);340};341 342static void ads7924_reg_disable(void *data)343{344	regulator_disable(data);345}346 347static void ads7924_set_idle_mode(void *data)348{349	ads7924_set_conv_mode(data, ADS7924_MODECNTRL_IDLE);350}351 352static int ads7924_probe(struct i2c_client *client)353{354	struct iio_dev *indio_dev;355	struct ads7924_data *data;356	struct device *dev = &client->dev;357	int ret;358 359	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));360	if (!indio_dev)361		return dev_err_probe(dev, -ENOMEM,362				     "failed to allocate iio device\n");363 364	data = iio_priv(indio_dev);365 366	data->dev = dev;367 368	/* Initialize the reset GPIO as output with an initial value of 0. */369	data->reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);370	if (IS_ERR(data->reset_gpio))371		return dev_err_probe(dev, PTR_ERR(data->reset_gpio),372				     "failed to get request reset GPIO\n");373 374	mutex_init(&data->lock);375 376	indio_dev->name = "ads7924";377	indio_dev->modes = INDIO_DIRECT_MODE;378 379	indio_dev->channels = ads7924_channels;380	indio_dev->num_channels = ARRAY_SIZE(ads7924_channels);381	indio_dev->info = &ads7924_info;382 383	ret = ads7924_get_channels_config(client, indio_dev);384	if (ret < 0)385		return dev_err_probe(dev, ret,386				     "failed to get channels configuration\n");387 388	data->regmap = devm_regmap_init_i2c(client, &ads7924_regmap_config);389	if (IS_ERR(data->regmap))390		return dev_err_probe(dev, PTR_ERR(data->regmap),391				     "failed to init regmap\n");392 393	data->vref_reg = devm_regulator_get(dev, "vref");394	if (IS_ERR(data->vref_reg))395		return dev_err_probe(dev, PTR_ERR(data->vref_reg),396				     "failed to get vref regulator\n");397 398	ret = regulator_enable(data->vref_reg);399	if (ret)400		return dev_err_probe(dev, ret,401				     "failed to enable regulator\n");402 403	ret = devm_add_action_or_reset(dev, ads7924_reg_disable, data->vref_reg);404	if (ret)405		return dev_err_probe(dev, ret,406				     "failed to add regulator disable action\n");407 408	ret = ads7924_reset(indio_dev);409	if (ret < 0)410		return dev_err_probe(dev, ret,411				     "failed to reset device\n");412 413	ret = ads7924_set_conv_mode(data, ADS7924_MODECNTRL_AUTO_SCAN);414	if (ret)415		return dev_err_probe(dev, ret,416				     "failed to set conversion mode\n");417 418	ret = devm_add_action_or_reset(dev, ads7924_set_idle_mode, data);419	if (ret)420		return dev_err_probe(dev, ret,421				     "failed to add idle mode action\n");422 423	/* Use minimum signal acquire time. */424	ret = regmap_update_bits(data->regmap, ADS7924_ACQCONFIG_REG,425				 ADS7924_ACQTIME_MASK,426				 FIELD_PREP(ADS7924_ACQTIME_MASK, 0));427	if (ret < 0)428		return dev_err_probe(dev, ret,429				     "failed to configure signal acquire time\n");430 431	/* Disable power-up time. */432	ret = regmap_update_bits(data->regmap, ADS7924_PWRCONFIG_REG,433				 ADS7924_PWRUPTIME_MASK,434				 FIELD_PREP(ADS7924_PWRUPTIME_MASK, 0));435	if (ret < 0)436		return dev_err_probe(dev, ret,437				     "failed to configure power-up time\n");438 439	data->conv_invalid = true;440 441	ret = devm_iio_device_register(dev, indio_dev);442	if (ret < 0)443		return dev_err_probe(dev, ret,444				     "failed to register IIO device\n");445 446	return 0;447}448 449static const struct i2c_device_id ads7924_id[] = {450	{ "ads7924" },451	{ }452};453MODULE_DEVICE_TABLE(i2c, ads7924_id);454 455static const struct of_device_id ads7924_of_match[] = {456	{ .compatible = "ti,ads7924", },457	{ }458};459MODULE_DEVICE_TABLE(of, ads7924_of_match);460 461static struct i2c_driver ads7924_driver = {462	.driver = {463		.name = "ads7924",464		.of_match_table = ads7924_of_match,465	},466	.probe		= ads7924_probe,467	.id_table	= ads7924_id,468};469 470module_i2c_driver(ads7924_driver);471 472MODULE_AUTHOR("Hugo Villeneuve <hvilleneuve@dimonoff.com>");473MODULE_DESCRIPTION("Texas Instruments ADS7924 ADC I2C driver");474MODULE_LICENSE("GPL");475