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