<commit_before>/* HopeRF Electronic HP206C precision barometer and altimeter driver
 *
 * Copyright (c) 2016 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Datasheet:
 *   http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
 */

#include <init.h>
#include <sensor.h>
#include <i2c.h>
#include <misc/byteorder.h>
#include <kernel.h>
#include <gpio.h>

#include "hp206c.h"

static inline int hp206c_bus_config(struct device *dev)
{
	struct hp206c_device_data *hp206c = dev->driver_data;
	union dev_config i2c_cfg;

	i2c_cfg.raw = 0;
	i2c_cfg.bits.is_master_device = 1;
	i2c_cfg.bits.speed = I2C_SPEED_STANDARD;

	return i2c_configure(hp206c->i2c, i2c_cfg.raw);
}

static int hp206c_read(struct device *dev, uint8_t cmd, uint8_t *data,
		       uint8_t len)
{
	struct hp206c_device_data *hp206c = dev->driver_data;

	hp206c_bus_config(dev);

	if (i2c_burst_read(hp206c->i2c, HP206C_I2C_ADDRESS,
			   cmd, data, len) < 0) {
		return -EIO;
	}

	return 0;
}

static int hp206c_read_reg(struct device *dev, uint8_t reg_addr,
			   uint8_t *reg_val)
{
	uint8_t cmd = HP206C_CMD_READ_REG | (reg_addr & HP206C_REG_ADDR_MASK);

	return hp206c_read(dev, cmd, reg_val, 1);
}

static int hp206c_write(struct device *dev, uint8_t cmd, uint8_t *data,
			uint8_t len)
{
	struct hp206c_device_data *hp206c = dev->driver_data;

	hp206c_bus_config(dev);

	if (i2c_burst_write(hp206c->i2c, HP206C_I2C_ADDRESS,
			    cmd, data, len) < 0) {
		return -EIO;
	}

	return 0;
}

static int hp206c_write_reg(struct device *dev, uint8_t reg_addr,
			    uint8_t reg_val)
{
	uint8_t cmd = HP206C_CMD_WRITE_REG | (reg_addr & HP206C_REG_ADDR_MASK);

	return hp206c_write(dev, cmd, &reg_val, 1);
}

static int hp206c_cmd_send(struct device *dev, uint8_t cmd)
{
	struct hp206c_device_data *hp206c = dev->driver_data;

	hp206c_bus_config(dev);

	return i2c_write(hp206c->i2c, &cmd, 1, HP206C_I2C_ADDRESS);
}

/*
 * The conversion times in this map were rounded up. The reason for doing that
 * is merely to spare 24 bytes that, otherwise, would've been taken by having
 * the times converted to microseconds. The trade-off is 900us added to the
 * conversion wait time which looks like a good compromise provided the highest
 * precision computation takes 131.1ms.
 */
static uint8_t hp206c_adc_time_ms[] = {
/*	conversion time(ms),   OSR  */
	132,		    /* 4096 */
	66,		    /* 2048 */
	34,		    /* 1024 */
	17,		    /* 512  */
	9,		    /* 256  */
	5,		    /* 128  */
};

static int hp206c_osr_set(struct device *dev, uint16_t osr)
{
	struct hp206c_device_data *hp206c = dev->driver_data;
	uint8_t i;

	/* the following code translates OSR values to an index */
	for (i = 0; i < 6 && BIT(12 - i) != osr; i++) {
		;
	}

	if (i == 6) {
		return -ENOTSUP;
	}

	hp206c->osr = i;

	return 0;
}

static int hp206c_altitude_offs_set(struct device *dev, int16_t offs)
{
	uint8_t reg_val;

	reg_val = offs & 0xff;

	if (hp206c_write_reg(dev, HP206C_REG_ALT_OFF_LSB, reg_val) < 0) {
		return -EIO;
	}

	reg_val = (offs & 0xff00) >> 8;

	if (hp206c_write_reg(dev, HP206C_REG_ALT_OFF_MSB, reg_val) < 0) {
		return -EIO;
	}

	return hp206c_write_reg(dev, HP206C_REG_PARA, HP206C_COMPENSATION_EN);
}

static int hp206c_attr_set(struct device *dev, enum sensor_channel chan,
			   enum sensor_attribute attr,
			   const struct sensor_value *val)
{
	if (val->type != SENSOR_VALUE_TYPE_INT_PLUS_MICRO) {
		return -EINVAL;
	}

#ifdef CONFIG_HP206C_OSR_RUNTIME
	if (attr == SENSOR_ATTR_OVERSAMPLING) {
		return hp206c_osr_set(dev, val->val1);
	}
#endif
#ifdef CONFIG_HP206C_ALT_OFFSET_RUNTIME
	if (attr == SENSOR_ATTR_OFFSET) {
		if (chan != SENSOR_CHAN_ALTITUDE) {
			return -ENOTSUP;
		}

		return hp206c_altitude_offs_set(dev, val->val1);
	}
#endif

	return -ENOTSUP;
}

static int hp206c_wait_dev_ready(struct device *dev, uint32_t timeout_ms)
{
	struct hp206c_device_data *hp206c = dev->driver_data;
	uint8_t int_src;

#ifdef CONFIG_NANO_TIMERS
	k_timer_start(&hp206c->tmr, MSEC(timeout_ms), 0);
	k_timer_status_sync(&hp206c->tmr);
#else
	k_busy_wait(timeout_ms * 1000);
#endif<commit_msg>drivers: fix timeout in hp206<commit_after>/* HopeRF Electronic HP206C precision barometer and altimeter driver
 *
 * Copyright (c) 2016 Intel Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * Datasheet:
 *   http://www.hoperf.com/upload/sensor/HP206C_DataSheet_EN_V2.0.pdf
 */

#include <init.h>
#include <sensor.h>
#include <i2c.h>
#include <misc/byteorder.h>
#include <kernel.h>
#include <gpio.h>

#include "hp206c.h"

static inline int hp206c_bus_config(struct device *dev)
{
	struct hp206c_device_data *hp206c = dev->driver_data;
	union dev_config i2c_cfg;

	i2c_cfg.raw = 0;
	i2c_cfg.bits.is_master_device = 1;
	i2c_cfg.bits.speed = I2C_SPEED_STANDARD;

	return i2c_configure(hp206c->i2c, i2c_cfg.raw);
}

static int hp206c_read(struct device *dev, uint8_t cmd, uint8_t *data,
		       uint8_t len)
{
	struct hp206c_device_data *hp206c = dev->driver_data;

	hp206c_bus_config(dev);

	if (i2c_burst_read(hp206c->i2c, HP206C_I2C_ADDRESS,
			   cmd, data, len) < 0) {
		return -EIO;
	}

	return 0;
}

static int hp206c_read_reg(struct device *dev, uint8_t reg_addr,
			   uint8_t *reg_val)
{
	uint8_t cmd = HP206C_CMD_READ_REG | (reg_addr & HP206C_REG_ADDR_MASK);

	return hp206c_read(dev, cmd, reg_val, 1);
}

static int hp206c_write(struct device *dev, uint8_t cmd, uint8_t *data,
			uint8_t len)
{
	struct hp206c_device_data *hp206c = dev->driver_data;

	hp206c_bus_config(dev);

	if (i2c_burst_write(hp206c->i2c, HP206C_I2C_ADDRESS,
			    cmd, data, len) < 0) {
		return -EIO;
	}

	return 0;
}

static int hp206c_write_reg(struct device *dev, uint8_t reg_addr,
			    uint8_t reg_val)
{
	uint8_t cmd = HP206C_CMD_WRITE_REG | (reg_addr & HP206C_REG_ADDR_MASK);

	return hp206c_write(dev, cmd, &reg_val, 1);
}

static int hp206c_cmd_send(struct device *dev, uint8_t cmd)
{
	struct hp206c_device_data *hp206c = dev->driver_data;

	hp206c_bus_config(dev);

	return i2c_write(hp206c->i2c, &cmd, 1, HP206C_I2C_ADDRESS);
}

/*
 * The conversion times in this map were rounded up. The reason for doing that
 * is merely to spare 24 bytes that, otherwise, would've been taken by having
 * the times converted to microseconds. The trade-off is 900us added to the
 * conversion wait time which looks like a good compromise provided the highest
 * precision computation takes 131.1ms.
 */
static uint8_t hp206c_adc_time_ms[] = {
/*	conversion time(ms),   OSR  */
	132,		    /* 4096 */
	66,		    /* 2048 */
	34,		    /* 1024 */
	17,		    /* 512  */
	9,		    /* 256  */
	5,		    /* 128  */
};

static int hp206c_osr_set(struct device *dev, uint16_t osr)
{
	struct hp206c_device_data *hp206c = dev->driver_data;
	uint8_t i;

	/* the following code translates OSR values to an index */
	for (i = 0; i < 6 && BIT(12 - i) != osr; i++) {
		;
	}

	if (i == 6) {
		return -ENOTSUP;
	}

	hp206c->osr = i;

	return 0;
}

static int hp206c_altitude_offs_set(struct device *dev, int16_t offs)
{
	uint8_t reg_val;

	reg_val = offs & 0xff;

	if (hp206c_write_reg(dev, HP206C_REG_ALT_OFF_LSB, reg_val) < 0) {
		return -EIO;
	}

	reg_val = (offs & 0xff00) >> 8;

	if (hp206c_write_reg(dev, HP206C_REG_ALT_OFF_MSB, reg_val) < 0) {
		return -EIO;
	}

	return hp206c_write_reg(dev, HP206C_REG_PARA, HP206C_COMPENSATION_EN);
}

static int hp206c_attr_set(struct device *dev, enum sensor_channel chan,
			   enum sensor_attribute attr,
			   const struct sensor_value *val)
{
	if (val->type != SENSOR_VALUE_TYPE_INT_PLUS_MICRO) {
		return -EINVAL;
	}

#ifdef CONFIG_HP206C_OSR_RUNTIME
	if (attr == SENSOR_ATTR_OVERSAMPLING) {
		return hp206c_osr_set(dev, val->val1);
	}
#endif
#ifdef CONFIG_HP206C_ALT_OFFSET_RUNTIME
	if (attr == SENSOR_ATTR_OFFSET) {
		if (chan != SENSOR_CHAN_ALTITUDE) {
			return -ENOTSUP;
		}

		return hp206c_altitude_offs_set(dev, val->val1);
	}
#endif

	return -ENOTSUP;
}

static int hp206c_wait_dev_ready(struct device *dev, uint32_t timeout_ms)
{
	struct hp206c_device_data *hp206c = dev->driver_data;
	uint8_t int_src;

#ifdef CONFIG_NANO_TIMERS
	k_timer_start(&hp206c->tmr, timeout_ms, 0);
	k_timer_status_sync(&hp206c->tmr);
#else
	k_busy_wait(timeout_ms * 1000);
#endif
{'fraction_non_alphanumeric': 0.10652883569096844, 'fraction_numerical': 0.0632208922742111, 'mean_word_length': 4.12033426183844, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 51, 'https://': 0, 'lorem ipsum': 0, 'www.': 4, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1981916', 'n_tokens_mistral': 4185, 'n_tokens_neox': 3677, 'n_words': 911}