brintos

brintos / linux-shallow public Read only

0
0
Text · 10.2 KiB · 169e359 Raw
386 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Texas Instruments LMP92064 SPI ADC driver4 *5 * Copyright (c) 2022 Leonard Göhrs <kernel@pengutronix.de>, Pengutronix6 *7 * Based on linux/drivers/iio/adc/ti-tsc2046.c8 * Copyright (c) 2021 Oleksij Rempel <kernel@pengutronix.de>, Pengutronix9 */10 11#include <linux/delay.h>12#include <linux/gpio/consumer.h>13#include <linux/module.h>14#include <linux/regmap.h>15#include <linux/regulator/consumer.h>16#include <linux/spi/spi.h>17 18#include <linux/iio/iio.h>19#include <linux/iio/buffer.h>20#include <linux/iio/driver.h>21#include <linux/iio/triggered_buffer.h>22#include <linux/iio/trigger_consumer.h>23 24#define TI_LMP92064_REG_CONFIG_A 0x000025#define TI_LMP92064_REG_CONFIG_B 0x000126#define TI_LMP92064_REG_CHIP_REV 0x000627 28#define TI_LMP92064_REG_MFR_ID1 0x000C29#define TI_LMP92064_REG_MFR_ID2 0x000D30 31#define TI_LMP92064_REG_REG_UPDATE 0x000F32#define TI_LMP92064_REG_CONFIG_REG 0x010033#define TI_LMP92064_REG_STATUS 0x010334 35#define TI_LMP92064_REG_DATA_VOUT_LSB 0x020036#define TI_LMP92064_REG_DATA_VOUT_MSB 0x020137#define TI_LMP92064_REG_DATA_COUT_LSB 0x020238#define TI_LMP92064_REG_DATA_COUT_MSB 0x020339 40#define TI_LMP92064_VAL_CONFIG_A 0x9941#define TI_LMP92064_VAL_CONFIG_B 0x0042#define TI_LMP92064_VAL_STATUS_OK 0x0143 44/*45 * Channel number definitions for the two channels of the device46 * - IN Current (INC)47 * - IN Voltage (INV)48 */49#define TI_LMP92064_CHAN_INC 050#define TI_LMP92064_CHAN_INV 151 52static const struct regmap_range lmp92064_readable_reg_ranges[] = {53	regmap_reg_range(TI_LMP92064_REG_CONFIG_A, TI_LMP92064_REG_CHIP_REV),54	regmap_reg_range(TI_LMP92064_REG_MFR_ID1, TI_LMP92064_REG_MFR_ID2),55	regmap_reg_range(TI_LMP92064_REG_REG_UPDATE, TI_LMP92064_REG_REG_UPDATE),56	regmap_reg_range(TI_LMP92064_REG_CONFIG_REG, TI_LMP92064_REG_CONFIG_REG),57	regmap_reg_range(TI_LMP92064_REG_STATUS, TI_LMP92064_REG_STATUS),58	regmap_reg_range(TI_LMP92064_REG_DATA_VOUT_LSB, TI_LMP92064_REG_DATA_COUT_MSB),59};60 61static const struct regmap_access_table lmp92064_readable_regs = {62	.yes_ranges = lmp92064_readable_reg_ranges,63	.n_yes_ranges = ARRAY_SIZE(lmp92064_readable_reg_ranges),64};65 66static const struct regmap_range lmp92064_writable_reg_ranges[] = {67	regmap_reg_range(TI_LMP92064_REG_CONFIG_A, TI_LMP92064_REG_CONFIG_B),68	regmap_reg_range(TI_LMP92064_REG_REG_UPDATE, TI_LMP92064_REG_REG_UPDATE),69	regmap_reg_range(TI_LMP92064_REG_CONFIG_REG, TI_LMP92064_REG_CONFIG_REG),70};71 72static const struct regmap_access_table lmp92064_writable_regs = {73	.yes_ranges = lmp92064_writable_reg_ranges,74	.n_yes_ranges = ARRAY_SIZE(lmp92064_writable_reg_ranges),75};76 77static const struct regmap_config lmp92064_spi_regmap_config = {78	.reg_bits = 16,79	.val_bits = 8,80	.max_register = TI_LMP92064_REG_DATA_COUT_MSB,81	.rd_table = &lmp92064_readable_regs,82	.wr_table = &lmp92064_writable_regs,83};84 85struct lmp92064_adc_priv {86	int shunt_resistor_uohm;87	struct spi_device *spi;88	struct regmap *regmap;89};90 91static const struct iio_chan_spec lmp92064_adc_channels[] = {92	{93		.type = IIO_CURRENT,94		.address = TI_LMP92064_CHAN_INC,95		.info_mask_separate =96			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),97		.scan_index = TI_LMP92064_CHAN_INC,98		.scan_type = {99			.sign = 'u',100			.realbits = 12,101			.storagebits = 16,102		},103		.datasheet_name = "INC",104	},105	{106		.type = IIO_VOLTAGE,107		.address = TI_LMP92064_CHAN_INV,108		.info_mask_separate =109			BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),110		.scan_index = TI_LMP92064_CHAN_INV,111		.scan_type = {112			.sign = 'u',113			.realbits = 12,114			.storagebits = 16,115		},116		.datasheet_name = "INV",117	},118	IIO_CHAN_SOFT_TIMESTAMP(2),119};120 121static const unsigned long lmp92064_scan_masks[] = {122	BIT(TI_LMP92064_CHAN_INC) | BIT(TI_LMP92064_CHAN_INV),123	0124};125 126static int lmp92064_read_meas(struct lmp92064_adc_priv *priv, u16 *res)127{128	__be16 raw[2];129	int ret;130 131	/*132	 * The ADC only latches in new samples if all DATA registers are read133	 * in descending sequential order.134	 * The ADC auto-decrements the register index with each clocked byte.135	 * Read both channels in single SPI transfer by selecting the highest136	 * register using the command below and clocking out all four data137	 * bytes.138	 */139 140	ret = regmap_bulk_read(priv->regmap, TI_LMP92064_REG_DATA_COUT_MSB,141			 &raw, sizeof(raw));142 143	if (ret) {144		dev_err(&priv->spi->dev, "regmap_bulk_read failed: %pe\n",145			ERR_PTR(ret));146		return ret;147	}148 149	res[0] = be16_to_cpu(raw[0]);150	res[1] = be16_to_cpu(raw[1]);151 152	return 0;153}154 155static int lmp92064_read_raw(struct iio_dev *indio_dev,156			     struct iio_chan_spec const *chan, int *val,157			     int *val2, long mask)158{159	struct lmp92064_adc_priv *priv = iio_priv(indio_dev);160	u16 raw[2];161	int ret;162 163	switch (mask) {164	case IIO_CHAN_INFO_RAW:165		ret = lmp92064_read_meas(priv, raw);166		if (ret < 0)167			return ret;168 169		*val = (chan->address == TI_LMP92064_CHAN_INC) ? raw[0] : raw[1];170 171		return IIO_VAL_INT;172	case IIO_CHAN_INFO_SCALE:173		if (chan->address == TI_LMP92064_CHAN_INC) {174			/*175			 * processed (mA) = raw * current_lsb (mA)176			 * current_lsb (mA) = shunt_voltage_lsb (nV) / shunt_resistor (uOhm)177			 * shunt_voltage_lsb (nV) = 81920000 / 4096 = 20000178			 */179			*val = 20000;180			*val2 = priv->shunt_resistor_uohm;181		} else {182			/*183			 * processed (mV) = raw * voltage_lsb (mV)184			 * voltage_lsb (mV) = 2048 / 4096185			 */186			*val = 2048;187			*val2 = 4096;188		}189		return IIO_VAL_FRACTIONAL;190	default:191		return -EINVAL;192	}193}194 195static irqreturn_t lmp92064_trigger_handler(int irq, void *p)196{197	struct iio_poll_func *pf = p;198	struct iio_dev *indio_dev = pf->indio_dev;199	struct lmp92064_adc_priv *priv = iio_priv(indio_dev);200	struct {201		u16 values[2];202		int64_t timestamp __aligned(8);203	} data;204	int ret;205 206	memset(&data, 0, sizeof(data));207 208	ret = lmp92064_read_meas(priv, data.values);209	if (ret)210		goto err;211 212	iio_push_to_buffers_with_timestamp(indio_dev, &data,213					   iio_get_time_ns(indio_dev));214 215err:216	iio_trigger_notify_done(indio_dev->trig);217 218	return IRQ_HANDLED;219}220 221static int lmp92064_reset(struct lmp92064_adc_priv *priv,222			  struct gpio_desc *gpio_reset)223{224	unsigned int status;225	int ret, i;226 227	if (gpio_reset) {228		/*229		 * Perform a hard reset if gpio_reset is available.230		 * The datasheet specifies a very low 3.5ns reset pulse duration and does not231		 * specify how long to wait after a reset to access the device.232		 * Use more conservative pulse lengths to allow analog RC filtering of the233		 * reset line at the board level (as recommended in the datasheet).234		 */235		gpiod_set_value_cansleep(gpio_reset, 1);236		usleep_range(1, 10);237		gpiod_set_value_cansleep(gpio_reset, 0);238		usleep_range(500, 750);239	} else {240		/*241		 * Perform a soft-reset if not.242		 * Also write default values to the config registers that are not243		 * affected by soft reset.244		 */245		ret = regmap_write(priv->regmap, TI_LMP92064_REG_CONFIG_A,246				   TI_LMP92064_VAL_CONFIG_A);247		if (ret < 0)248			return ret;249 250		ret = regmap_write(priv->regmap, TI_LMP92064_REG_CONFIG_B,251				   TI_LMP92064_VAL_CONFIG_B);252		if (ret < 0)253			return ret;254	}255 256	/*257	 * Wait for the device to signal readiness to prevent reading bogus data258	 * and make sure device is actually connected.259	 * The datasheet does not specify how long this takes but usually it is260	 * not more than 3-4 iterations of this loop.261	 */262	for (i = 0; i < 10; i++) {263		ret = regmap_read(priv->regmap, TI_LMP92064_REG_STATUS, &status);264		if (ret < 0)265			return ret;266 267		if (status == TI_LMP92064_VAL_STATUS_OK)268			return 0;269 270		usleep_range(1000, 2000);271	}272 273	/*274	 * No (correct) response received.275	 * Device is mostly likely not connected to the bus.276	 */277	return -ENXIO;278}279 280static const struct iio_info lmp92064_adc_info = {281	.read_raw = lmp92064_read_raw,282};283 284static int lmp92064_adc_probe(struct spi_device *spi)285{286	struct device *dev = &spi->dev;287	struct lmp92064_adc_priv *priv;288	struct gpio_desc *gpio_reset;289	struct iio_dev *indio_dev;290	u32 shunt_resistor_uohm;291	struct regmap *regmap;292	int ret;293 294	ret = spi_setup(spi);295	if (ret < 0)296		return dev_err_probe(dev, ret, "Error in SPI setup\n");297 298	regmap = devm_regmap_init_spi(spi, &lmp92064_spi_regmap_config);299	if (IS_ERR(regmap))300		return dev_err_probe(dev, PTR_ERR(regmap),301				     "Failed to set up SPI regmap\n");302 303	indio_dev = devm_iio_device_alloc(dev, sizeof(*priv));304	if (!indio_dev)305		return -ENOMEM;306 307	priv = iio_priv(indio_dev);308 309	priv->spi = spi;310	priv->regmap = regmap;311 312	ret = device_property_read_u32(dev, "shunt-resistor-micro-ohms",313				       &shunt_resistor_uohm);314	if (ret < 0)315		return dev_err_probe(dev, ret,316				     "Failed to get shunt-resistor value\n");317 318	/*319	 * The shunt resistance is passed to userspace as the denominator of an iio320	 * fraction. Make sure it is in range for that.321	 */322	if (shunt_resistor_uohm == 0 || shunt_resistor_uohm > INT_MAX) {323		dev_err(dev, "Shunt resistance is out of range\n");324		return -EINVAL;325	}326 327	priv->shunt_resistor_uohm = shunt_resistor_uohm;328 329	ret = devm_regulator_get_enable(dev, "vdd");330	if (ret)331		return ret;332 333	ret = devm_regulator_get_enable(dev, "vdig");334	if (ret)335		return ret;336 337	gpio_reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_HIGH);338	if (IS_ERR(gpio_reset))339		return dev_err_probe(dev, PTR_ERR(gpio_reset),340				     "Failed to get GPIO reset pin\n");341 342	ret = lmp92064_reset(priv, gpio_reset);343	if (ret < 0)344		return dev_err_probe(dev, ret, "Failed to reset device\n");345 346	indio_dev->name = "lmp92064";347	indio_dev->modes = INDIO_DIRECT_MODE;348	indio_dev->channels = lmp92064_adc_channels;349	indio_dev->num_channels = ARRAY_SIZE(lmp92064_adc_channels);350	indio_dev->info = &lmp92064_adc_info;351	indio_dev->available_scan_masks = lmp92064_scan_masks;352 353	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,354					      lmp92064_trigger_handler, NULL);355	if (ret)356		return dev_err_probe(dev, ret, "Failed to setup buffered read\n");357 358	return devm_iio_device_register(dev, indio_dev);359}360 361static const struct spi_device_id lmp92064_id_table[] = {362	{ "lmp92064" },363	{ }364};365MODULE_DEVICE_TABLE(spi, lmp92064_id_table);366 367static const struct of_device_id lmp92064_of_table[] = {368	{ .compatible = "ti,lmp92064" },369	{}370};371MODULE_DEVICE_TABLE(of, lmp92064_of_table);372 373static struct spi_driver lmp92064_adc_driver = {374	.driver = {375		.name = "lmp92064",376		.of_match_table = lmp92064_of_table,377	},378	.probe = lmp92064_adc_probe,379	.id_table = lmp92064_id_table,380};381module_spi_driver(lmp92064_adc_driver);382 383MODULE_AUTHOR("Leonard Göhrs <kernel@pengutronix.de>");384MODULE_DESCRIPTION("TI LMP92064 ADC");385MODULE_LICENSE("GPL");386