18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * hp206c.c - HOPERF HP206C precision barometer and altimeter sensor
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 2016, Intel Corporation.
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * (7-bit I2C slave address 0x76)
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Datasheet:
108c2ecf20Sopenharmony_ci *  http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
118c2ecf20Sopenharmony_ci */
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#include <linux/module.h>
148c2ecf20Sopenharmony_ci#include <linux/i2c.h>
158c2ecf20Sopenharmony_ci#include <linux/iio/iio.h>
168c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h>
178c2ecf20Sopenharmony_ci#include <linux/delay.h>
188c2ecf20Sopenharmony_ci#include <linux/util_macros.h>
198c2ecf20Sopenharmony_ci#include <linux/acpi.h>
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci/* I2C commands: */
248c2ecf20Sopenharmony_ci#define HP206C_CMD_SOFT_RST	0x06
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT	0x40
278c2ecf20Sopenharmony_ci
288c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_OSR_4096	0x00
298c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_OSR_2048	0x04
308c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_OSR_1024	0x08
318c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_OSR_512	0x0c
328c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_OSR_256	0x10
338c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_OSR_128	0x14
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_CHNL_PT	0x00
368c2ecf20Sopenharmony_ci#define HP206C_CMD_ADC_CVT_CHNL_T	0x02
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ci#define HP206C_CMD_READ_P	0x30
398c2ecf20Sopenharmony_ci#define HP206C_CMD_READ_T	0x32
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_ci#define HP206C_CMD_READ_REG	0x80
428c2ecf20Sopenharmony_ci#define HP206C_CMD_WRITE_REG	0xc0
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define HP206C_REG_INT_EN	0x0b
458c2ecf20Sopenharmony_ci#define HP206C_REG_INT_CFG	0x0c
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define HP206C_REG_INT_SRC	0x0d
488c2ecf20Sopenharmony_ci#define HP206C_FLAG_DEV_RDY	0x40
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define HP206C_REG_PARA		0x0f
518c2ecf20Sopenharmony_ci#define HP206C_FLAG_CMPS_EN	0x80
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci/* Maximum spin for DEV_RDY */
548c2ecf20Sopenharmony_ci#define HP206C_MAX_DEV_RDY_WAIT_COUNT 20
558c2ecf20Sopenharmony_ci#define HP206C_DEV_RDY_WAIT_US    20000
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_cistruct hp206c_data {
588c2ecf20Sopenharmony_ci	struct mutex mutex;
598c2ecf20Sopenharmony_ci	struct i2c_client *client;
608c2ecf20Sopenharmony_ci	int temp_osr_index;
618c2ecf20Sopenharmony_ci	int pres_osr_index;
628c2ecf20Sopenharmony_ci};
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_cistruct hp206c_osr_setting {
658c2ecf20Sopenharmony_ci	u8 osr_mask;
668c2ecf20Sopenharmony_ci	unsigned int temp_conv_time_us;
678c2ecf20Sopenharmony_ci	unsigned int pres_conv_time_us;
688c2ecf20Sopenharmony_ci};
698c2ecf20Sopenharmony_ci
708c2ecf20Sopenharmony_ci/* Data from Table 5 in datasheet. */
718c2ecf20Sopenharmony_cistatic const struct hp206c_osr_setting hp206c_osr_settings[] = {
728c2ecf20Sopenharmony_ci	{ HP206C_CMD_ADC_CVT_OSR_4096,	65600,	131100	},
738c2ecf20Sopenharmony_ci	{ HP206C_CMD_ADC_CVT_OSR_2048,	32800,	65600	},
748c2ecf20Sopenharmony_ci	{ HP206C_CMD_ADC_CVT_OSR_1024,	16400,	32800	},
758c2ecf20Sopenharmony_ci	{ HP206C_CMD_ADC_CVT_OSR_512,	8200,	16400	},
768c2ecf20Sopenharmony_ci	{ HP206C_CMD_ADC_CVT_OSR_256,	4100,	8200	},
778c2ecf20Sopenharmony_ci	{ HP206C_CMD_ADC_CVT_OSR_128,	2100,	4100	},
788c2ecf20Sopenharmony_ci};
798c2ecf20Sopenharmony_cistatic const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 };
808c2ecf20Sopenharmony_cistatic const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128";
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_cistatic inline int hp206c_read_reg(struct i2c_client *client, u8 reg)
838c2ecf20Sopenharmony_ci{
848c2ecf20Sopenharmony_ci	return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg);
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val)
888c2ecf20Sopenharmony_ci{
898c2ecf20Sopenharmony_ci	return i2c_smbus_write_byte_data(client,
908c2ecf20Sopenharmony_ci			HP206C_CMD_WRITE_REG | reg, val);
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic int hp206c_read_20bit(struct i2c_client *client, u8 cmd)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	int ret;
968c2ecf20Sopenharmony_ci	u8 values[3];
978c2ecf20Sopenharmony_ci
988c2ecf20Sopenharmony_ci	ret = i2c_smbus_read_i2c_block_data(client, cmd, sizeof(values), values);
998c2ecf20Sopenharmony_ci	if (ret < 0)
1008c2ecf20Sopenharmony_ci		return ret;
1018c2ecf20Sopenharmony_ci	if (ret != sizeof(values))
1028c2ecf20Sopenharmony_ci		return -EIO;
1038c2ecf20Sopenharmony_ci	return get_unaligned_be24(&values[0]) & GENMASK(19, 0);
1048c2ecf20Sopenharmony_ci}
1058c2ecf20Sopenharmony_ci
1068c2ecf20Sopenharmony_ci/* Spin for max 160ms until DEV_RDY is 1, or return error. */
1078c2ecf20Sopenharmony_cistatic int hp206c_wait_dev_rdy(struct iio_dev *indio_dev)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	int ret;
1108c2ecf20Sopenharmony_ci	int count = 0;
1118c2ecf20Sopenharmony_ci	struct hp206c_data *data = iio_priv(indio_dev);
1128c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) {
1158c2ecf20Sopenharmony_ci		ret = hp206c_read_reg(client, HP206C_REG_INT_SRC);
1168c2ecf20Sopenharmony_ci		if (ret < 0) {
1178c2ecf20Sopenharmony_ci			dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret);
1188c2ecf20Sopenharmony_ci			return ret;
1198c2ecf20Sopenharmony_ci		}
1208c2ecf20Sopenharmony_ci		if (ret & HP206C_FLAG_DEV_RDY)
1218c2ecf20Sopenharmony_ci			return 0;
1228c2ecf20Sopenharmony_ci		usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2);
1238c2ecf20Sopenharmony_ci	}
1248c2ecf20Sopenharmony_ci	return -ETIMEDOUT;
1258c2ecf20Sopenharmony_ci}
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cistatic int hp206c_set_compensation(struct i2c_client *client, bool enabled)
1288c2ecf20Sopenharmony_ci{
1298c2ecf20Sopenharmony_ci	int val;
1308c2ecf20Sopenharmony_ci
1318c2ecf20Sopenharmony_ci	val = hp206c_read_reg(client, HP206C_REG_PARA);
1328c2ecf20Sopenharmony_ci	if (val < 0)
1338c2ecf20Sopenharmony_ci		return val;
1348c2ecf20Sopenharmony_ci	if (enabled)
1358c2ecf20Sopenharmony_ci		val |= HP206C_FLAG_CMPS_EN;
1368c2ecf20Sopenharmony_ci	else
1378c2ecf20Sopenharmony_ci		val &= ~HP206C_FLAG_CMPS_EN;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	return hp206c_write_reg(client, HP206C_REG_PARA, val);
1408c2ecf20Sopenharmony_ci}
1418c2ecf20Sopenharmony_ci
1428c2ecf20Sopenharmony_ci/* Do a soft reset */
1438c2ecf20Sopenharmony_cistatic int hp206c_soft_reset(struct iio_dev *indio_dev)
1448c2ecf20Sopenharmony_ci{
1458c2ecf20Sopenharmony_ci	int ret;
1468c2ecf20Sopenharmony_ci	struct hp206c_data *data = iio_priv(indio_dev);
1478c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
1488c2ecf20Sopenharmony_ci
1498c2ecf20Sopenharmony_ci	ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST);
1508c2ecf20Sopenharmony_ci	if (ret) {
1518c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Failed to reset device: %d\n", ret);
1528c2ecf20Sopenharmony_ci		return ret;
1538c2ecf20Sopenharmony_ci	}
1548c2ecf20Sopenharmony_ci
1558c2ecf20Sopenharmony_ci	usleep_range(400, 600);
1568c2ecf20Sopenharmony_ci
1578c2ecf20Sopenharmony_ci	ret = hp206c_wait_dev_rdy(indio_dev);
1588c2ecf20Sopenharmony_ci	if (ret) {
1598c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret);
1608c2ecf20Sopenharmony_ci		return ret;
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_ci	ret = hp206c_set_compensation(client, true);
1648c2ecf20Sopenharmony_ci	if (ret)
1658c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Failed to enable compensation: %d\n", ret);
1668c2ecf20Sopenharmony_ci	return ret;
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cistatic int hp206c_conv_and_read(struct iio_dev *indio_dev,
1708c2ecf20Sopenharmony_ci				u8 conv_cmd, u8 read_cmd,
1718c2ecf20Sopenharmony_ci				unsigned int sleep_us)
1728c2ecf20Sopenharmony_ci{
1738c2ecf20Sopenharmony_ci	int ret;
1748c2ecf20Sopenharmony_ci	struct hp206c_data *data = iio_priv(indio_dev);
1758c2ecf20Sopenharmony_ci	struct i2c_client *client = data->client;
1768c2ecf20Sopenharmony_ci
1778c2ecf20Sopenharmony_ci	ret = hp206c_wait_dev_rdy(indio_dev);
1788c2ecf20Sopenharmony_ci	if (ret < 0) {
1798c2ecf20Sopenharmony_ci		dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
1808c2ecf20Sopenharmony_ci		return ret;
1818c2ecf20Sopenharmony_ci	}
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	ret = i2c_smbus_write_byte(client, conv_cmd);
1848c2ecf20Sopenharmony_ci	if (ret < 0) {
1858c2ecf20Sopenharmony_ci		dev_err(&indio_dev->dev, "Failed convert: %d\n", ret);
1868c2ecf20Sopenharmony_ci		return ret;
1878c2ecf20Sopenharmony_ci	}
1888c2ecf20Sopenharmony_ci
1898c2ecf20Sopenharmony_ci	usleep_range(sleep_us, sleep_us * 3 / 2);
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	ret = hp206c_wait_dev_rdy(indio_dev);
1928c2ecf20Sopenharmony_ci	if (ret < 0) {
1938c2ecf20Sopenharmony_ci		dev_err(&indio_dev->dev, "Device not ready: %d\n", ret);
1948c2ecf20Sopenharmony_ci		return ret;
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	ret = hp206c_read_20bit(client, read_cmd);
1988c2ecf20Sopenharmony_ci	if (ret < 0)
1998c2ecf20Sopenharmony_ci		dev_err(&indio_dev->dev, "Failed read: %d\n", ret);
2008c2ecf20Sopenharmony_ci
2018c2ecf20Sopenharmony_ci	return ret;
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic int hp206c_read_raw(struct iio_dev *indio_dev,
2058c2ecf20Sopenharmony_ci			   struct iio_chan_spec const *chan, int *val,
2068c2ecf20Sopenharmony_ci			   int *val2, long mask)
2078c2ecf20Sopenharmony_ci{
2088c2ecf20Sopenharmony_ci	int ret;
2098c2ecf20Sopenharmony_ci	struct hp206c_data *data = iio_priv(indio_dev);
2108c2ecf20Sopenharmony_ci	const struct hp206c_osr_setting *osr_setting;
2118c2ecf20Sopenharmony_ci	u8 conv_cmd;
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	mutex_lock(&data->mutex);
2148c2ecf20Sopenharmony_ci
2158c2ecf20Sopenharmony_ci	switch (mask) {
2168c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
2178c2ecf20Sopenharmony_ci		switch (chan->type) {
2188c2ecf20Sopenharmony_ci		case IIO_TEMP:
2198c2ecf20Sopenharmony_ci			*val = hp206c_osr_rates[data->temp_osr_index];
2208c2ecf20Sopenharmony_ci			ret = IIO_VAL_INT;
2218c2ecf20Sopenharmony_ci			break;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci		case IIO_PRESSURE:
2248c2ecf20Sopenharmony_ci			*val = hp206c_osr_rates[data->pres_osr_index];
2258c2ecf20Sopenharmony_ci			ret = IIO_VAL_INT;
2268c2ecf20Sopenharmony_ci			break;
2278c2ecf20Sopenharmony_ci		default:
2288c2ecf20Sopenharmony_ci			ret = -EINVAL;
2298c2ecf20Sopenharmony_ci		}
2308c2ecf20Sopenharmony_ci		break;
2318c2ecf20Sopenharmony_ci
2328c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
2338c2ecf20Sopenharmony_ci		switch (chan->type) {
2348c2ecf20Sopenharmony_ci		case IIO_TEMP:
2358c2ecf20Sopenharmony_ci			osr_setting = &hp206c_osr_settings[data->temp_osr_index];
2368c2ecf20Sopenharmony_ci			conv_cmd = HP206C_CMD_ADC_CVT |
2378c2ecf20Sopenharmony_ci					osr_setting->osr_mask |
2388c2ecf20Sopenharmony_ci					HP206C_CMD_ADC_CVT_CHNL_T;
2398c2ecf20Sopenharmony_ci			ret = hp206c_conv_and_read(indio_dev,
2408c2ecf20Sopenharmony_ci					conv_cmd,
2418c2ecf20Sopenharmony_ci					HP206C_CMD_READ_T,
2428c2ecf20Sopenharmony_ci					osr_setting->temp_conv_time_us);
2438c2ecf20Sopenharmony_ci			if (ret >= 0) {
2448c2ecf20Sopenharmony_ci				/* 20 significant bits are provided.
2458c2ecf20Sopenharmony_ci				 * Extend sign over the rest.
2468c2ecf20Sopenharmony_ci				 */
2478c2ecf20Sopenharmony_ci				*val = sign_extend32(ret, 19);
2488c2ecf20Sopenharmony_ci				ret = IIO_VAL_INT;
2498c2ecf20Sopenharmony_ci			}
2508c2ecf20Sopenharmony_ci			break;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci		case IIO_PRESSURE:
2538c2ecf20Sopenharmony_ci			osr_setting = &hp206c_osr_settings[data->pres_osr_index];
2548c2ecf20Sopenharmony_ci			conv_cmd = HP206C_CMD_ADC_CVT |
2558c2ecf20Sopenharmony_ci					osr_setting->osr_mask |
2568c2ecf20Sopenharmony_ci					HP206C_CMD_ADC_CVT_CHNL_PT;
2578c2ecf20Sopenharmony_ci			ret = hp206c_conv_and_read(indio_dev,
2588c2ecf20Sopenharmony_ci					conv_cmd,
2598c2ecf20Sopenharmony_ci					HP206C_CMD_READ_P,
2608c2ecf20Sopenharmony_ci					osr_setting->pres_conv_time_us);
2618c2ecf20Sopenharmony_ci			if (ret >= 0) {
2628c2ecf20Sopenharmony_ci				*val = ret;
2638c2ecf20Sopenharmony_ci				ret = IIO_VAL_INT;
2648c2ecf20Sopenharmony_ci			}
2658c2ecf20Sopenharmony_ci			break;
2668c2ecf20Sopenharmony_ci		default:
2678c2ecf20Sopenharmony_ci			ret = -EINVAL;
2688c2ecf20Sopenharmony_ci		}
2698c2ecf20Sopenharmony_ci		break;
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
2728c2ecf20Sopenharmony_ci		switch (chan->type) {
2738c2ecf20Sopenharmony_ci		case IIO_TEMP:
2748c2ecf20Sopenharmony_ci			*val = 0;
2758c2ecf20Sopenharmony_ci			*val2 = 10000;
2768c2ecf20Sopenharmony_ci			ret = IIO_VAL_INT_PLUS_MICRO;
2778c2ecf20Sopenharmony_ci			break;
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci		case IIO_PRESSURE:
2808c2ecf20Sopenharmony_ci			*val = 0;
2818c2ecf20Sopenharmony_ci			*val2 = 1000;
2828c2ecf20Sopenharmony_ci			ret = IIO_VAL_INT_PLUS_MICRO;
2838c2ecf20Sopenharmony_ci			break;
2848c2ecf20Sopenharmony_ci		default:
2858c2ecf20Sopenharmony_ci			ret = -EINVAL;
2868c2ecf20Sopenharmony_ci		}
2878c2ecf20Sopenharmony_ci		break;
2888c2ecf20Sopenharmony_ci
2898c2ecf20Sopenharmony_ci	default:
2908c2ecf20Sopenharmony_ci		ret = -EINVAL;
2918c2ecf20Sopenharmony_ci	}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	mutex_unlock(&data->mutex);
2948c2ecf20Sopenharmony_ci	return ret;
2958c2ecf20Sopenharmony_ci}
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_cistatic int hp206c_write_raw(struct iio_dev *indio_dev,
2988c2ecf20Sopenharmony_ci			    struct iio_chan_spec const *chan,
2998c2ecf20Sopenharmony_ci			    int val, int val2, long mask)
3008c2ecf20Sopenharmony_ci{
3018c2ecf20Sopenharmony_ci	int ret = 0;
3028c2ecf20Sopenharmony_ci	struct hp206c_data *data = iio_priv(indio_dev);
3038c2ecf20Sopenharmony_ci
3048c2ecf20Sopenharmony_ci	if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO)
3058c2ecf20Sopenharmony_ci		return -EINVAL;
3068c2ecf20Sopenharmony_ci	mutex_lock(&data->mutex);
3078c2ecf20Sopenharmony_ci	switch (chan->type) {
3088c2ecf20Sopenharmony_ci	case IIO_TEMP:
3098c2ecf20Sopenharmony_ci		data->temp_osr_index = find_closest_descending(val,
3108c2ecf20Sopenharmony_ci			hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
3118c2ecf20Sopenharmony_ci		break;
3128c2ecf20Sopenharmony_ci	case IIO_PRESSURE:
3138c2ecf20Sopenharmony_ci		data->pres_osr_index = find_closest_descending(val,
3148c2ecf20Sopenharmony_ci			hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates));
3158c2ecf20Sopenharmony_ci		break;
3168c2ecf20Sopenharmony_ci	default:
3178c2ecf20Sopenharmony_ci		ret = -EINVAL;
3188c2ecf20Sopenharmony_ci	}
3198c2ecf20Sopenharmony_ci	mutex_unlock(&data->mutex);
3208c2ecf20Sopenharmony_ci	return ret;
3218c2ecf20Sopenharmony_ci}
3228c2ecf20Sopenharmony_ci
3238c2ecf20Sopenharmony_cistatic const struct iio_chan_spec hp206c_channels[] = {
3248c2ecf20Sopenharmony_ci	{
3258c2ecf20Sopenharmony_ci		.type = IIO_TEMP,
3268c2ecf20Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
3278c2ecf20Sopenharmony_ci				      BIT(IIO_CHAN_INFO_SCALE) |
3288c2ecf20Sopenharmony_ci				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
3298c2ecf20Sopenharmony_ci	},
3308c2ecf20Sopenharmony_ci	{
3318c2ecf20Sopenharmony_ci		.type = IIO_PRESSURE,
3328c2ecf20Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
3338c2ecf20Sopenharmony_ci				      BIT(IIO_CHAN_INFO_SCALE) |
3348c2ecf20Sopenharmony_ci				      BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
3358c2ecf20Sopenharmony_ci	}
3368c2ecf20Sopenharmony_ci};
3378c2ecf20Sopenharmony_ci
3388c2ecf20Sopenharmony_cistatic IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_cistatic struct attribute *hp206c_attributes[] = {
3418c2ecf20Sopenharmony_ci	&iio_const_attr_sampling_frequency_available.dev_attr.attr,
3428c2ecf20Sopenharmony_ci	NULL,
3438c2ecf20Sopenharmony_ci};
3448c2ecf20Sopenharmony_ci
3458c2ecf20Sopenharmony_cistatic const struct attribute_group hp206c_attribute_group = {
3468c2ecf20Sopenharmony_ci	.attrs = hp206c_attributes,
3478c2ecf20Sopenharmony_ci};
3488c2ecf20Sopenharmony_ci
3498c2ecf20Sopenharmony_cistatic const struct iio_info hp206c_info = {
3508c2ecf20Sopenharmony_ci	.attrs = &hp206c_attribute_group,
3518c2ecf20Sopenharmony_ci	.read_raw = hp206c_read_raw,
3528c2ecf20Sopenharmony_ci	.write_raw = hp206c_write_raw,
3538c2ecf20Sopenharmony_ci};
3548c2ecf20Sopenharmony_ci
3558c2ecf20Sopenharmony_cistatic int hp206c_probe(struct i2c_client *client,
3568c2ecf20Sopenharmony_ci			const struct i2c_device_id *id)
3578c2ecf20Sopenharmony_ci{
3588c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev;
3598c2ecf20Sopenharmony_ci	struct hp206c_data *data;
3608c2ecf20Sopenharmony_ci	int ret;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	if (!i2c_check_functionality(client->adapter,
3638c2ecf20Sopenharmony_ci				     I2C_FUNC_SMBUS_BYTE |
3648c2ecf20Sopenharmony_ci				     I2C_FUNC_SMBUS_BYTE_DATA |
3658c2ecf20Sopenharmony_ci				     I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
3668c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Adapter does not support "
3678c2ecf20Sopenharmony_ci				"all required i2c functionality\n");
3688c2ecf20Sopenharmony_ci		return -ENODEV;
3698c2ecf20Sopenharmony_ci	}
3708c2ecf20Sopenharmony_ci
3718c2ecf20Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
3728c2ecf20Sopenharmony_ci	if (!indio_dev)
3738c2ecf20Sopenharmony_ci		return -ENOMEM;
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	data = iio_priv(indio_dev);
3768c2ecf20Sopenharmony_ci	data->client = client;
3778c2ecf20Sopenharmony_ci	mutex_init(&data->mutex);
3788c2ecf20Sopenharmony_ci
3798c2ecf20Sopenharmony_ci	indio_dev->info = &hp206c_info;
3808c2ecf20Sopenharmony_ci	indio_dev->name = id->name;
3818c2ecf20Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
3828c2ecf20Sopenharmony_ci	indio_dev->channels = hp206c_channels;
3838c2ecf20Sopenharmony_ci	indio_dev->num_channels = ARRAY_SIZE(hp206c_channels);
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	i2c_set_clientdata(client, indio_dev);
3868c2ecf20Sopenharmony_ci
3878c2ecf20Sopenharmony_ci	/* Do a soft reset on probe */
3888c2ecf20Sopenharmony_ci	ret = hp206c_soft_reset(indio_dev);
3898c2ecf20Sopenharmony_ci	if (ret) {
3908c2ecf20Sopenharmony_ci		dev_err(&client->dev, "Failed to reset on startup: %d\n", ret);
3918c2ecf20Sopenharmony_ci		return -ENODEV;
3928c2ecf20Sopenharmony_ci	}
3938c2ecf20Sopenharmony_ci
3948c2ecf20Sopenharmony_ci	return devm_iio_device_register(&client->dev, indio_dev);
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic const struct i2c_device_id hp206c_id[] = {
3988c2ecf20Sopenharmony_ci	{"hp206c"},
3998c2ecf20Sopenharmony_ci	{}
4008c2ecf20Sopenharmony_ci};
4018c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, hp206c_id);
4028c2ecf20Sopenharmony_ci
4038c2ecf20Sopenharmony_ci#ifdef CONFIG_ACPI
4048c2ecf20Sopenharmony_cistatic const struct acpi_device_id hp206c_acpi_match[] = {
4058c2ecf20Sopenharmony_ci	{"HOP206C", 0},
4068c2ecf20Sopenharmony_ci	{ },
4078c2ecf20Sopenharmony_ci};
4088c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, hp206c_acpi_match);
4098c2ecf20Sopenharmony_ci#endif
4108c2ecf20Sopenharmony_ci
4118c2ecf20Sopenharmony_cistatic struct i2c_driver hp206c_driver = {
4128c2ecf20Sopenharmony_ci	.probe = hp206c_probe,
4138c2ecf20Sopenharmony_ci	.id_table = hp206c_id,
4148c2ecf20Sopenharmony_ci	.driver = {
4158c2ecf20Sopenharmony_ci		.name = "hp206c",
4168c2ecf20Sopenharmony_ci		.acpi_match_table = ACPI_PTR(hp206c_acpi_match),
4178c2ecf20Sopenharmony_ci	},
4188c2ecf20Sopenharmony_ci};
4198c2ecf20Sopenharmony_ci
4208c2ecf20Sopenharmony_cimodule_i2c_driver(hp206c_driver);
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor");
4238c2ecf20Sopenharmony_ciMODULE_AUTHOR("Leonard Crestez <leonard.crestez@intel.com>");
4248c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
425