brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · 5a6fbe3 Raw
352 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2 3/*4 * Copyright (c) Linumiz 20215 *6 * max31865.c - Maxim MAX31865 RTD-to-Digital Converter sensor driver7 *8 * Author: Navin Sankar Velliangiri <navin@linumiz.com>9 */10 11#include <linux/ctype.h>12#include <linux/delay.h>13#include <linux/err.h>14#include <linux/init.h>15#include <linux/mod_devicetable.h>16#include <linux/module.h>17#include <linux/iio/iio.h>18#include <linux/iio/sysfs.h>19#include <linux/property.h>20#include <linux/spi/spi.h>21#include <linux/unaligned.h>22 23/*24 * The MSB of the register value determines whether the following byte will25 * be written or read. If it is 0, read will follow and if it is 1, write26 * will follow.27 */28#define MAX31865_RD_WR_BIT			BIT(7)29 30#define MAX31865_CFG_VBIAS			BIT(7)31#define MAX31865_CFG_1SHOT			BIT(5)32#define MAX31865_3WIRE_RTD			BIT(4)33#define MAX31865_FAULT_STATUS_CLEAR		BIT(1)34#define MAX31865_FILTER_50HZ			BIT(0)35 36/* The MAX31865 registers */37#define MAX31865_CFG_REG			0x0038#define MAX31865_RTD_MSB			0x0139#define MAX31865_FAULT_STATUS			0x0740 41#define MAX31865_FAULT_OVUV			BIT(2)42 43static const char max31865_show_samp_freq[] = "50 60";44 45static const struct iio_chan_spec max31865_channels[] = {46	{	/* RTD Temperature */47		.type = IIO_TEMP,48		.info_mask_separate =49			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE)50	},51};52 53struct max31865_data {54	struct spi_device *spi;55	struct mutex lock;56	bool filter_50hz;57	bool three_wire;58	u8 buf[2] __aligned(IIO_DMA_MINALIGN);59};60 61static int max31865_read(struct max31865_data *data, u8 reg,62			 unsigned int read_size)63{64	return spi_write_then_read(data->spi, &reg, 1, data->buf, read_size);65}66 67static int max31865_write(struct max31865_data *data, size_t len)68{69	return spi_write(data->spi, data->buf, len);70}71 72static int enable_bias(struct max31865_data *data)73{74	u8 cfg;75	int ret;76 77	ret = max31865_read(data, MAX31865_CFG_REG, 1);78	if (ret)79		return ret;80 81	cfg = data->buf[0];82 83	data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;84	data->buf[1] = cfg | MAX31865_CFG_VBIAS;85 86	return max31865_write(data, 2);87}88 89static int disable_bias(struct max31865_data *data)90{91	u8 cfg;92	int ret;93 94	ret = max31865_read(data, MAX31865_CFG_REG, 1);95	if (ret)96		return ret;97 98	cfg = data->buf[0];99	cfg &= ~MAX31865_CFG_VBIAS;100 101	data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;102	data->buf[1] = cfg;103 104	return max31865_write(data, 2);105}106 107static int max31865_rtd_read(struct max31865_data *data, int *val)108{109	u8 reg;110	int ret;111 112	/* Enable BIAS to start the conversion */113	ret = enable_bias(data);114	if (ret)115		return ret;116 117	/* wait 10.5ms before initiating the conversion */118	msleep(11);119 120	ret = max31865_read(data, MAX31865_CFG_REG, 1);121	if (ret)122		return ret;123 124	reg = data->buf[0];125	reg |= MAX31865_CFG_1SHOT | MAX31865_FAULT_STATUS_CLEAR;126	data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;127	data->buf[1] = reg;128 129	ret = max31865_write(data, 2);130	if (ret)131		return ret;132 133	if (data->filter_50hz) {134		/* 50Hz filter mode requires 62.5ms to complete */135		msleep(63);136	} else {137		/* 60Hz filter mode requires 52ms to complete */138		msleep(52);139	}140 141	ret = max31865_read(data, MAX31865_RTD_MSB, 2);142	if (ret)143		return ret;144 145	*val = get_unaligned_be16(&data->buf) >> 1;146 147	return disable_bias(data);148}149 150static int max31865_read_raw(struct iio_dev *indio_dev,151			     struct iio_chan_spec const *chan,152			     int *val, int *val2, long mask)153{154	struct max31865_data *data = iio_priv(indio_dev);155	int ret;156 157	switch (mask) {158	case IIO_CHAN_INFO_RAW:159		mutex_lock(&data->lock);160		ret = max31865_rtd_read(data, val);161		mutex_unlock(&data->lock);162		if (ret)163			return ret;164		return IIO_VAL_INT;165	case IIO_CHAN_INFO_SCALE:166		/* Temp. Data resolution is 0.03125 degree centigrade */167		*val = 31;168		*val2 = 250000; /* 1000 * 0.03125 */169		return IIO_VAL_INT_PLUS_MICRO;170	default:171		return -EINVAL;172	}173}174 175static int max31865_init(struct max31865_data *data)176{177	u8 cfg;178	int ret;179 180	ret = max31865_read(data, MAX31865_CFG_REG, 1);181	if (ret)182		return ret;183 184	cfg = data->buf[0];185 186	if (data->three_wire)187		/* 3-wire RTD connection */188		cfg |= MAX31865_3WIRE_RTD;189 190	if (data->filter_50hz)191		/* 50Hz noise rejection filter */192		cfg |= MAX31865_FILTER_50HZ;193 194	data->buf[0] = MAX31865_CFG_REG | MAX31865_RD_WR_BIT;195	data->buf[1] = cfg;196 197	return max31865_write(data, 2);198}199 200static ssize_t show_fault(struct device *dev, u8 faultbit, char *buf)201{202	int ret;203	bool fault;204	struct iio_dev *indio_dev = dev_to_iio_dev(dev);205	struct max31865_data *data = iio_priv(indio_dev);206 207	ret = max31865_read(data, MAX31865_FAULT_STATUS, 1);208	if (ret)209		return ret;210 211	fault = data->buf[0] & faultbit;212 213	return sysfs_emit(buf, "%d\n", fault);214}215 216static ssize_t show_fault_ovuv(struct device *dev,217			      struct device_attribute *attr,218			      char *buf)219{220	return show_fault(dev, MAX31865_FAULT_OVUV, buf);221}222 223static ssize_t show_filter(struct device *dev,224			   struct device_attribute *attr,225			   char *buf)226{227	struct iio_dev *indio_dev = dev_to_iio_dev(dev);228	struct max31865_data *data = iio_priv(indio_dev);229 230	return sysfs_emit(buf, "%d\n", data->filter_50hz ? 50 : 60);231}232 233static ssize_t set_filter(struct device *dev,234			  struct device_attribute *attr,235			  const char *buf,236			  size_t len)237{238	struct iio_dev *indio_dev = dev_to_iio_dev(dev);239	struct max31865_data *data = iio_priv(indio_dev);240	unsigned int freq;241	int ret;242 243	ret = kstrtouint(buf, 10, &freq);244	if (ret)245		return ret;246 247	switch (freq) {248	case 50:249		data->filter_50hz = true;250		break;251	case 60:252		data->filter_50hz = false;253		break;254	default:255		return -EINVAL;256	}257 258	mutex_lock(&data->lock);259	ret = max31865_init(data);260	mutex_unlock(&data->lock);261	if (ret)262		return ret;263 264	return len;265}266 267static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(max31865_show_samp_freq);268static IIO_DEVICE_ATTR(fault_ovuv, 0444, show_fault_ovuv, NULL, 0);269static IIO_DEVICE_ATTR(in_filter_notch_center_frequency, 0644,270		    show_filter, set_filter, 0);271 272static struct attribute *max31865_attributes[] = {273	&iio_dev_attr_fault_ovuv.dev_attr.attr,274	&iio_const_attr_sampling_frequency_available.dev_attr.attr,275	&iio_dev_attr_in_filter_notch_center_frequency.dev_attr.attr,276	NULL,277};278 279static const struct attribute_group max31865_group = {280	.attrs = max31865_attributes,281};282 283static const struct iio_info max31865_info = {284	.read_raw = max31865_read_raw,285	.attrs = &max31865_group,286};287 288static int max31865_probe(struct spi_device *spi)289{290	const struct spi_device_id *id = spi_get_device_id(spi);291	struct iio_dev *indio_dev;292	struct max31865_data *data;293	int ret;294 295	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*data));296	if (!indio_dev)297		return -ENOMEM;298 299	data = iio_priv(indio_dev);300	data->spi = spi;301	data->filter_50hz = false;302	mutex_init(&data->lock);303 304	indio_dev->info = &max31865_info;305	indio_dev->name = id->name;306	indio_dev->modes = INDIO_DIRECT_MODE;307	indio_dev->channels = max31865_channels;308	indio_dev->num_channels = ARRAY_SIZE(max31865_channels);309 310	if (device_property_read_bool(&spi->dev, "maxim,3-wire")) {311		/* select 3 wire */312		data->three_wire = 1;313	} else {314		/* select 2 or 4 wire */315		data->three_wire = 0;316	}317 318	ret = max31865_init(data);319	if (ret) {320		dev_err(&spi->dev, "error: Failed to configure max31865\n");321		return ret;322	}323 324	return devm_iio_device_register(&spi->dev, indio_dev);325}326 327static const struct spi_device_id max31865_id[] = {328	{ "max31865", 0 },329	{ }330};331MODULE_DEVICE_TABLE(spi, max31865_id);332 333static const struct of_device_id max31865_of_match[] = {334	{ .compatible = "maxim,max31865" },335	{ }336};337MODULE_DEVICE_TABLE(of, max31865_of_match);338 339static struct spi_driver max31865_driver = {340	.driver = {341		.name	= "max31865",342		.of_match_table = max31865_of_match,343	},344	.probe = max31865_probe,345	.id_table = max31865_id,346};347module_spi_driver(max31865_driver);348 349MODULE_AUTHOR("Navin Sankar Velliangiri <navin@linumiz.com>");350MODULE_DESCRIPTION("Maxim MAX31865 RTD-to-Digital Converter sensor driver");351MODULE_LICENSE("GPL v2");352