1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * hp206c.c - HOPERF HP206C precision barometer and altimeter sensor 4 * 5 * Copyright (c) 2016, Intel Corporation. 6 * 7 * (7-bit I2C slave address 0x76) 8 * 9 * Datasheet: 10 * http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf 11 */ 12 13 #include <linux/module.h> 14 #include <linux/i2c.h> 15 #include <linux/iio/iio.h> 16 #include <linux/iio/sysfs.h> 17 #include <linux/delay.h> 18 #include <linux/util_macros.h> 19 #include <linux/acpi.h> 20 21 /* I2C commands: */ 22 #define HP206C_CMD_SOFT_RST 0x06 23 24 #define HP206C_CMD_ADC_CVT 0x40 25 26 #define HP206C_CMD_ADC_CVT_OSR_4096 0x00 27 #define HP206C_CMD_ADC_CVT_OSR_2048 0x04 28 #define HP206C_CMD_ADC_CVT_OSR_1024 0x08 29 #define HP206C_CMD_ADC_CVT_OSR_512 0x0c 30 #define HP206C_CMD_ADC_CVT_OSR_256 0x10 31 #define HP206C_CMD_ADC_CVT_OSR_128 0x14 32 33 #define HP206C_CMD_ADC_CVT_CHNL_PT 0x00 34 #define HP206C_CMD_ADC_CVT_CHNL_T 0x02 35 36 #define HP206C_CMD_READ_P 0x30 37 #define HP206C_CMD_READ_T 0x32 38 39 #define HP206C_CMD_READ_REG 0x80 40 #define HP206C_CMD_WRITE_REG 0xc0 41 42 #define HP206C_REG_INT_EN 0x0b 43 #define HP206C_REG_INT_CFG 0x0c 44 45 #define HP206C_REG_INT_SRC 0x0d 46 #define HP206C_FLAG_DEV_RDY 0x40 47 48 #define HP206C_REG_PARA 0x0f 49 #define HP206C_FLAG_CMPS_EN 0x80 50 51 /* Maximum spin for DEV_RDY */ 52 #define HP206C_MAX_DEV_RDY_WAIT_COUNT 20 53 #define HP206C_DEV_RDY_WAIT_US 20000 54 55 struct hp206c_data { 56 struct mutex mutex; 57 struct i2c_client *client; 58 int temp_osr_index; 59 int pres_osr_index; 60 }; 61 62 struct hp206c_osr_setting { 63 u8 osr_mask; 64 unsigned int temp_conv_time_us; 65 unsigned int pres_conv_time_us; 66 }; 67 68 /* Data from Table 5 in datasheet. */ 69 static const struct hp206c_osr_setting hp206c_osr_settings[] = { 70 { HP206C_CMD_ADC_CVT_OSR_4096, 65600, 131100 }, 71 { HP206C_CMD_ADC_CVT_OSR_2048, 32800, 65600 }, 72 { HP206C_CMD_ADC_CVT_OSR_1024, 16400, 32800 }, 73 { HP206C_CMD_ADC_CVT_OSR_512, 8200, 16400 }, 74 { HP206C_CMD_ADC_CVT_OSR_256, 4100, 8200 }, 75 { HP206C_CMD_ADC_CVT_OSR_128, 2100, 4100 }, 76 }; 77 static const int hp206c_osr_rates[] = { 4096, 2048, 1024, 512, 256, 128 }; 78 static const char hp206c_osr_rates_str[] = "4096 2048 1024 512 256 128"; 79 80 static inline int hp206c_read_reg(struct i2c_client *client, u8 reg) 81 { 82 return i2c_smbus_read_byte_data(client, HP206C_CMD_READ_REG | reg); 83 } 84 85 static inline int hp206c_write_reg(struct i2c_client *client, u8 reg, u8 val) 86 { 87 return i2c_smbus_write_byte_data(client, 88 HP206C_CMD_WRITE_REG | reg, val); 89 } 90 91 static int hp206c_read_20bit(struct i2c_client *client, u8 cmd) 92 { 93 int ret; 94 u8 values[3]; 95 96 ret = i2c_smbus_read_i2c_block_data(client, cmd, 3, values); 97 if (ret < 0) 98 return ret; 99 if (ret != 3) 100 return -EIO; 101 return ((values[0] & 0xF) << 16) | (values[1] << 8) | (values[2]); 102 } 103 104 /* Spin for max 160ms until DEV_RDY is 1, or return error. */ 105 static int hp206c_wait_dev_rdy(struct iio_dev *indio_dev) 106 { 107 int ret; 108 int count = 0; 109 struct hp206c_data *data = iio_priv(indio_dev); 110 struct i2c_client *client = data->client; 111 112 while (++count <= HP206C_MAX_DEV_RDY_WAIT_COUNT) { 113 ret = hp206c_read_reg(client, HP206C_REG_INT_SRC); 114 if (ret < 0) { 115 dev_err(&indio_dev->dev, "Failed READ_REG INT_SRC: %d\n", ret); 116 return ret; 117 } 118 if (ret & HP206C_FLAG_DEV_RDY) 119 return 0; 120 usleep_range(HP206C_DEV_RDY_WAIT_US, HP206C_DEV_RDY_WAIT_US * 3 / 2); 121 } 122 return -ETIMEDOUT; 123 } 124 125 static int hp206c_set_compensation(struct i2c_client *client, bool enabled) 126 { 127 int val; 128 129 val = hp206c_read_reg(client, HP206C_REG_PARA); 130 if (val < 0) 131 return val; 132 if (enabled) 133 val |= HP206C_FLAG_CMPS_EN; 134 else 135 val &= ~HP206C_FLAG_CMPS_EN; 136 137 return hp206c_write_reg(client, HP206C_REG_PARA, val); 138 } 139 140 /* Do a soft reset */ 141 static int hp206c_soft_reset(struct iio_dev *indio_dev) 142 { 143 int ret; 144 struct hp206c_data *data = iio_priv(indio_dev); 145 struct i2c_client *client = data->client; 146 147 ret = i2c_smbus_write_byte(client, HP206C_CMD_SOFT_RST); 148 if (ret) { 149 dev_err(&client->dev, "Failed to reset device: %d\n", ret); 150 return ret; 151 } 152 153 usleep_range(400, 600); 154 155 ret = hp206c_wait_dev_rdy(indio_dev); 156 if (ret) { 157 dev_err(&client->dev, "Device not ready after soft reset: %d\n", ret); 158 return ret; 159 } 160 161 ret = hp206c_set_compensation(client, true); 162 if (ret) 163 dev_err(&client->dev, "Failed to enable compensation: %d\n", ret); 164 return ret; 165 } 166 167 static int hp206c_conv_and_read(struct iio_dev *indio_dev, 168 u8 conv_cmd, u8 read_cmd, 169 unsigned int sleep_us) 170 { 171 int ret; 172 struct hp206c_data *data = iio_priv(indio_dev); 173 struct i2c_client *client = data->client; 174 175 ret = hp206c_wait_dev_rdy(indio_dev); 176 if (ret < 0) { 177 dev_err(&indio_dev->dev, "Device not ready: %d\n", ret); 178 return ret; 179 } 180 181 ret = i2c_smbus_write_byte(client, conv_cmd); 182 if (ret < 0) { 183 dev_err(&indio_dev->dev, "Failed convert: %d\n", ret); 184 return ret; 185 } 186 187 usleep_range(sleep_us, sleep_us * 3 / 2); 188 189 ret = hp206c_wait_dev_rdy(indio_dev); 190 if (ret < 0) { 191 dev_err(&indio_dev->dev, "Device not ready: %d\n", ret); 192 return ret; 193 } 194 195 ret = hp206c_read_20bit(client, read_cmd); 196 if (ret < 0) 197 dev_err(&indio_dev->dev, "Failed read: %d\n", ret); 198 199 return ret; 200 } 201 202 static int hp206c_read_raw(struct iio_dev *indio_dev, 203 struct iio_chan_spec const *chan, int *val, 204 int *val2, long mask) 205 { 206 int ret; 207 struct hp206c_data *data = iio_priv(indio_dev); 208 const struct hp206c_osr_setting *osr_setting; 209 u8 conv_cmd; 210 211 mutex_lock(&data->mutex); 212 213 switch (mask) { 214 case IIO_CHAN_INFO_OVERSAMPLING_RATIO: 215 switch (chan->type) { 216 case IIO_TEMP: 217 *val = hp206c_osr_rates[data->temp_osr_index]; 218 ret = IIO_VAL_INT; 219 break; 220 221 case IIO_PRESSURE: 222 *val = hp206c_osr_rates[data->pres_osr_index]; 223 ret = IIO_VAL_INT; 224 break; 225 default: 226 ret = -EINVAL; 227 } 228 break; 229 230 case IIO_CHAN_INFO_RAW: 231 switch (chan->type) { 232 case IIO_TEMP: 233 osr_setting = &hp206c_osr_settings[data->temp_osr_index]; 234 conv_cmd = HP206C_CMD_ADC_CVT | 235 osr_setting->osr_mask | 236 HP206C_CMD_ADC_CVT_CHNL_T; 237 ret = hp206c_conv_and_read(indio_dev, 238 conv_cmd, 239 HP206C_CMD_READ_T, 240 osr_setting->temp_conv_time_us); 241 if (ret >= 0) { 242 /* 20 significant bits are provided. 243 * Extend sign over the rest. 244 */ 245 *val = sign_extend32(ret, 19); 246 ret = IIO_VAL_INT; 247 } 248 break; 249 250 case IIO_PRESSURE: 251 osr_setting = &hp206c_osr_settings[data->pres_osr_index]; 252 conv_cmd = HP206C_CMD_ADC_CVT | 253 osr_setting->osr_mask | 254 HP206C_CMD_ADC_CVT_CHNL_PT; 255 ret = hp206c_conv_and_read(indio_dev, 256 conv_cmd, 257 HP206C_CMD_READ_P, 258 osr_setting->pres_conv_time_us); 259 if (ret >= 0) { 260 *val = ret; 261 ret = IIO_VAL_INT; 262 } 263 break; 264 default: 265 ret = -EINVAL; 266 } 267 break; 268 269 case IIO_CHAN_INFO_SCALE: 270 switch (chan->type) { 271 case IIO_TEMP: 272 *val = 0; 273 *val2 = 10000; 274 ret = IIO_VAL_INT_PLUS_MICRO; 275 break; 276 277 case IIO_PRESSURE: 278 *val = 0; 279 *val2 = 1000; 280 ret = IIO_VAL_INT_PLUS_MICRO; 281 break; 282 default: 283 ret = -EINVAL; 284 } 285 break; 286 287 default: 288 ret = -EINVAL; 289 } 290 291 mutex_unlock(&data->mutex); 292 return ret; 293 } 294 295 static int hp206c_write_raw(struct iio_dev *indio_dev, 296 struct iio_chan_spec const *chan, 297 int val, int val2, long mask) 298 { 299 int ret = 0; 300 struct hp206c_data *data = iio_priv(indio_dev); 301 302 if (mask != IIO_CHAN_INFO_OVERSAMPLING_RATIO) 303 return -EINVAL; 304 mutex_lock(&data->mutex); 305 switch (chan->type) { 306 case IIO_TEMP: 307 data->temp_osr_index = find_closest_descending(val, 308 hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates)); 309 break; 310 case IIO_PRESSURE: 311 data->pres_osr_index = find_closest_descending(val, 312 hp206c_osr_rates, ARRAY_SIZE(hp206c_osr_rates)); 313 break; 314 default: 315 ret = -EINVAL; 316 } 317 mutex_unlock(&data->mutex); 318 return ret; 319 } 320 321 static const struct iio_chan_spec hp206c_channels[] = { 322 { 323 .type = IIO_TEMP, 324 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 325 BIT(IIO_CHAN_INFO_SCALE) | 326 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 327 }, 328 { 329 .type = IIO_PRESSURE, 330 .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | 331 BIT(IIO_CHAN_INFO_SCALE) | 332 BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 333 } 334 }; 335 336 static IIO_CONST_ATTR_SAMP_FREQ_AVAIL(hp206c_osr_rates_str); 337 338 static struct attribute *hp206c_attributes[] = { 339 &iio_const_attr_sampling_frequency_available.dev_attr.attr, 340 NULL, 341 }; 342 343 static const struct attribute_group hp206c_attribute_group = { 344 .attrs = hp206c_attributes, 345 }; 346 347 static const struct iio_info hp206c_info = { 348 .attrs = &hp206c_attribute_group, 349 .read_raw = hp206c_read_raw, 350 .write_raw = hp206c_write_raw, 351 }; 352 353 static int hp206c_probe(struct i2c_client *client, 354 const struct i2c_device_id *id) 355 { 356 struct iio_dev *indio_dev; 357 struct hp206c_data *data; 358 int ret; 359 360 if (!i2c_check_functionality(client->adapter, 361 I2C_FUNC_SMBUS_BYTE | 362 I2C_FUNC_SMBUS_BYTE_DATA | 363 I2C_FUNC_SMBUS_READ_I2C_BLOCK)) { 364 dev_err(&client->dev, "Adapter does not support " 365 "all required i2c functionality\n"); 366 return -ENODEV; 367 } 368 369 indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); 370 if (!indio_dev) 371 return -ENOMEM; 372 373 data = iio_priv(indio_dev); 374 data->client = client; 375 mutex_init(&data->mutex); 376 377 indio_dev->info = &hp206c_info; 378 indio_dev->name = id->name; 379 indio_dev->dev.parent = &client->dev; 380 indio_dev->modes = INDIO_DIRECT_MODE; 381 indio_dev->channels = hp206c_channels; 382 indio_dev->num_channels = ARRAY_SIZE(hp206c_channels); 383 384 i2c_set_clientdata(client, indio_dev); 385 386 /* Do a soft reset on probe */ 387 ret = hp206c_soft_reset(indio_dev); 388 if (ret) { 389 dev_err(&client->dev, "Failed to reset on startup: %d\n", ret); 390 return -ENODEV; 391 } 392 393 return devm_iio_device_register(&client->dev, indio_dev); 394 } 395 396 static const struct i2c_device_id hp206c_id[] = { 397 {"hp206c"}, 398 {} 399 }; 400 MODULE_DEVICE_TABLE(i2c, hp206c_id); 401 402 #ifdef CONFIG_ACPI 403 static const struct acpi_device_id hp206c_acpi_match[] = { 404 {"HOP206C", 0}, 405 { }, 406 }; 407 MODULE_DEVICE_TABLE(acpi, hp206c_acpi_match); 408 #endif 409 410 static struct i2c_driver hp206c_driver = { 411 .probe = hp206c_probe, 412 .id_table = hp206c_id, 413 .driver = { 414 .name = "hp206c", 415 .acpi_match_table = ACPI_PTR(hp206c_acpi_match), 416 }, 417 }; 418 419 module_i2c_driver(hp206c_driver); 420 421 MODULE_DESCRIPTION("HOPERF HP206C precision barometer and altimeter sensor"); 422 MODULE_AUTHOR("Leonard Crestez <leonard.crestez@intel.com>"); 423 MODULE_LICENSE("GPL v2"); 424