* initialize. No device identification and connect testing is done for
* specific configurations.
*/
-/* A defined interrupt can be used as a SW flag to configure the device if
- * behind the MPU. When an interrupt is defined in struct i2c_client.irq,
- * the driver is configured to only use the device's continuous mode if the
- * device supports it. The interrupt itself is never touched so any value can
- * be used. This frees the MPU auxiliary port used for writes. This
- * configuration would be used if another MPU auxiliary port was needed for
- * another device connected to the MPU. The delay timing used in continuous
- * mode is equal to or the next fastest supported speed.
- */
/* The NVS = NVidia Sensor framework */
/* NVI = NVidia/Invensense */
/* See Nvs.cpp in the HAL for the NVS implementation of batch/flush. */
#include <linux/mpu_iio.h>
#endif /* BMP_NVI_MPU_SUPPORT */
-#define BMP_DRIVER_VERSION (325)
+#define BMP_DRIVER_VERSION (336)
#define BMP_VENDOR "Bosch"
#define BMP_NAME "bmpX80"
#define BMP180_NAME "bmp180"
#define BMP_PRES_MAX_RANGE_MICRO (0)
#define BMP_TEMP_MAX_RANGE_IVAL (125)
#define BMP_TEMP_MAX_RANGE_MICRO (0)
-#define BMP180_RANGE_DFLT (0)
-/* until BMP280 OSS pressure calculation is supported, this defaults to 5 */
-#define BMP280_RANGE_DFLT (5)
#define BMP_HW_DELAY_POR_MS (10)
#define BMP_POLL_DELAY_MS_DFLT (200)
#define BMP_MPU_RETRY_COUNT (50)
#define BMP280_REG_CTRL_MODE_FORCED2 (2)
#define BMP280_REG_CTRL_MODE_NORMAL (3)
#define BMP280_REG_CTRL_OSRS_P (2)
-#define BMP280_REG_CTRL_OSRS_P_MASK (0x1C)
#define BMP280_REG_CTRL_OSRS_T (5)
-#define BMP280_REG_CTRL_OSRS_T_MASK (0xE0)
#define BMP180_REG_OUT_MSB (0xF6)
#define BMP180_REG_OUT_LSB (0xF7)
#define BMP180_REG_OUT_XLSB (0xF8)
#define RD (1)
#define PORT_N (2)
/* _buf_push expects this scan order */
-#define BMP_DEV_PRES (0)
-#define BMP_DEV_TEMP (1)
+#define BMP_DEV_PRS (0)
+#define BMP_DEV_TMP (1)
#define BMP_DEV_N (2)
/* regulator names in order of powering on */
};
struct bmp_scale {
- unsigned long delay_ms;
+ unsigned int delay_ms;
+ u8 os; /* oversampling */
struct nvs_float resolution;
struct nvs_float milliamp;
};
struct bmp_hal_dev {
int version;
- unsigned int scale_i_max;
- unsigned int scale_dflt;
+ unsigned int scale_n;
struct bmp_scale *scale;
struct nvs_float scale_float;
};
unsigned int sts; /* status flags */
unsigned int errs; /* error count */
unsigned int enabled; /* enable status */
+ unsigned int period_us_min; /* minimum period from MPU */
unsigned int poll_delay_us; /* global sampling delay */
unsigned int delay_us[BMP_DEV_N]; /* sampling delay */
unsigned int timeout_us[BMP_DEV_N]; /* batch timeout */
unsigned int scale_i; /* oversampling index */
unsigned int scale_user; /* user oversampling index */
+ unsigned int mpu_bypass_n; /* allow single bypass call */
+ unsigned int dmp_rd_len_sts; /* status length from DMP */
+ unsigned int dmp_rd_len_data; /* data length from DMP */
u16 i2c_addr; /* I2C address */
u8 dev_id; /* device ID */
bool initd; /* set if initialized */
+ bool cmode; /* mode normal (continuous) */
bool mpu_en; /* if device behind MPU */
bool port_en[PORT_N]; /* enable status of MPU write port */
int port_id[PORT_N]; /* MPU port ID */
s32 ut; /* uncompensated temperature */
s32 up; /* uncompensated pressure */
s32 t_fine; /* temperature used in pressure calc */
- s32 temp; /* true temperature */
- int pressure; /* true pressure hPa/100 Pa/1 mBar */
- s64 ts; /* sample data timestamp */
+ s32 tmp; /* true temperature */
+ u32 prs; /* true pressure hPa/100 Pa/1 mBar */
u8 nvi_config; /* NVI configuration */
};
struct bmp_hal {
- struct bmp_hal_dev *p;
- struct bmp_hal_dev *t;
+ struct bmp_hal_dev *dev;
const char *part;
u8 rom_addr_start;
u8 rom_size;
u8 mode_mask;
struct bmp_cmode *cmode_tbl;
int (*bmp_read)(struct bmp_state *st);
+#if BMP_NVI_MPU_SUPPORT
unsigned int mpu_id;
+ u8 port_rd_reg;
+ u8 port_rd_ctrl;
+ void (*port_rd_handler)(u8 *data, unsigned int len,
+ long long timestamp, void *ext_driver);
+#endif /* BMP_NVI_MPU_SUPPORT */
};
int i;
if (st->mpu_en) {
- for (i = 0; i < BMP_MPU_RETRY_COUNT; i++) {
- ret = nvi_mpu_bypass_request(true);
- if ((!ret) || (ret == -EPERM))
- break;
+ if (!st->mpu_bypass_n) {
+ for (i = 0; i < BMP_MPU_RETRY_COUNT; i++) {
+ ret = nvi_mpu_bypass_request(true);
+ if ((!ret) || (ret == -EPERM))
+ break;
- msleep(BMP_MPU_RETRY_DELAY_MS);
+ msleep(BMP_MPU_RETRY_DELAY_MS);
+ }
+
+ if (ret) {
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_err(&st->i2c->dev, "%s err=%d\n",
+ __func__, ret);
+ if (ret == -EPERM)
+ ret = 0;
+ } else {
+ st->mpu_bypass_n++;
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_info(&st->i2c->dev, "%s\n",
+ __func__);
+ }
+ } else {
+ st->mpu_bypass_n++;
}
- if (ret == -EPERM)
- ret = 0;
}
#endif /* BMP_NVI_MPU_SUPPORT */
return ret;
int ret = 0;
#if BMP_NVI_MPU_SUPPORT
- if (st->mpu_en)
- ret = nvi_mpu_bypass_release();
+ if (st->mpu_en) {
+ if (st->mpu_bypass_n == 1) {
+ ret = nvi_mpu_bypass_release();
+ if (ret) {
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_err(&st->i2c->dev, "%s err=%d\n",
+ __func__, ret);
+ } else {
+ st->mpu_bypass_n--;
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_info(&st->i2c->dev, "%s\n",
+ __func__);
+ }
+ } else {
+ st->mpu_bypass_n--;
+ }
+ }
#endif /* BMP_NVI_MPU_SUPPORT */
return ret;
}
int ret;
#if BMP_NVI_MPU_SUPPORT
- if (st->mpu_en && !st->i2c->irq) {
+ if (st->mpu_en && !st->cmode) {
ret = nvi_mpu_data_out(st->port_id[WR], mode);
} else {
ret = bmp_nvi_mpu_bypass_request(st);
if (!ret) {
- if (st->i2c->irq) {
+ if (st->cmode) {
ret = bmp_i2c_wr(st, BMP_REG_CTRL,
BMP_REG_CTRL_MODE_SLEEP);
if (mode & st->hal->mode_mask) {
} else {
ret = bmp_i2c_wr(st, BMP_REG_CTRL, mode);
}
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_info(&st->i2c->dev, "%s mode=%x err=%d\n",
+ __func__, mode, ret);
bmp_nvi_mpu_bypass_release(st);
}
}
#else /* BMP_NVI_MPU_SUPPORT */
ret = bmp_i2c_wr(st, BMP_REG_CTRL, mode);
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_info(&st->i2c->dev, "%s mode=%x err=%d\n",
+ __func__, mode, ret);
#endif /* BMP_NVI_MPU_SUPPORT */
if (!ret)
st->data_out = mode;
if (ret)
mdelay(BMP_HW_DELAY_POR_MS);
} else {
- if (st->i2c->irq) {
+ if (st->cmode) {
ret = nvs_vregs_sts(st->vreg, ARRAY_SIZE(bmp_vregs));
if ((ret < 0) || (ret == ARRAY_SIZE(bmp_vregs))) {
ret = bmp_mode_wr(st, BMP_REG_CTRL_MODE_SLEEP);
return ret;
}
+#if BMP_NVI_MPU_SUPPORT
static int bmp_port_free(struct bmp_state *st, int port)
{
int ret = 0;
-#if BMP_NVI_MPU_SUPPORT
if (st->port_id[port] >= 0) {
ret = nvi_mpu_port_free(st->port_id[port]);
if (!ret)
st->port_id[port] = -1;
}
-#endif /* BMP_NVI_MPU_SUPPORT */
return ret;
}
ret |= bmp_port_free(st, RD);
return ret;
}
+#endif /* BMP_NVI_MPU_SUPPORT */
static void bmp_pm_exit(struct bmp_state *st)
{
+#if BMP_NVI_MPU_SUPPORT
bmp_ports_free(st);
+#endif /* BMP_NVI_MPU_SUPPORT */
bmp_pm(st, false);
nvs_vregs_exit(&st->i2c->dev, st->vreg, ARRAY_SIZE(bmp_vregs));
}
{
int ret;
- st->enabled = 0;
- st->delay_us[BMP_DEV_PRES] = (BMP_POLL_DELAY_MS_DFLT * 1000);
- st->delay_us[BMP_DEV_TEMP] = (BMP_POLL_DELAY_MS_DFLT * 1000);
+ st->delay_us[BMP_DEV_PRS] = (BMP_POLL_DELAY_MS_DFLT * 1000);
+ st->delay_us[BMP_DEV_TMP] = (BMP_POLL_DELAY_MS_DFLT * 1000);
st->poll_delay_us = (BMP_POLL_DELAY_MS_DFLT * 1000);
- st->initd = false;
- st->mpu_en = false;
- st->port_en[WR] = false;
- st->port_en[RD] = false;
st->port_id[WR] = -1;
st->port_id[RD] = -1;
nvs_vregs_init(&st->i2c->dev,
return ret;
}
+#if BMP_NVI_MPU_SUPPORT
static int bmp_ports_enable(struct bmp_state *st, bool enable)
{
int ret = 0;
-#if BMP_NVI_MPU_SUPPORT
unsigned int port_mask = 0;
unsigned int i;
}
}
}
-#endif /* BMP_NVI_MPU_SUPPORT */
-
return ret;
}
+#endif /* BMP_NVI_MPU_SUPPORT */
static int bmp_wr(struct bmp_state *st, u8 reg, u8 val)
{
return ret;
}
-static int bmp_mode(struct bmp_state *st)
+static unsigned int bmp_cmode_t(struct bmp_state *st, u8 *t_sb,
+ unsigned int period_us, unsigned int scale_i)
+{
+ unsigned int us = 0;
+ unsigned int i = 0;
+
+
+ while (st->hal->cmode_tbl[i].t_us) {
+ *t_sb = st->hal->cmode_tbl[i].t_sb;
+ us = st->hal->cmode_tbl[i].t_us;
+ us += st->hal->dev[BMP_DEV_PRS].scale[scale_i].delay_ms * 1000;
+ if (period_us >= us)
+ return us;
+
+ i++;
+ if ((!st->mpu_en) && st->hal->cmode_tbl[i].t_us) {
+ us -= st->hal->cmode_tbl[i].t_us;
+ us >>= 1;
+ us += st->hal->cmode_tbl[i].t_us;
+ us += st->hal->dev[BMP_DEV_PRS].scale[scale_i].
+ delay_ms * 1000;
+ if (period_us > us)
+ return us;
+ }
+ }
+
+ return us;
+}
+
+static int bmp_mode(struct bmp_state *st, unsigned int period_us,
+ unsigned int scale_user, unsigned int enable)
{
u8 mode;
u8 t_sb;
- unsigned int t_us;
unsigned int i;
- int ret;
-
- if (st->dev_id == BMP_REG_ID_BMP180) {
- mode = st->scale_i << BMP180_REG_CTRL_OSS;
- mode |= BMP180_REG_CTRL_MODE_TEMP;
- } else {
- mode = st->scale_i + 1;
- mode = ((mode << BMP280_REG_CTRL_OSRS_T) |
- (mode << BMP280_REG_CTRL_OSRS_P));
- mode |= BMP280_REG_CTRL_MODE_FORCED1;
- }
- if (st->i2c->irq) {
- i = 0;
- t_sb = 0;
- while (st->hal->cmode_tbl[i].t_us) {
- t_sb = st->hal->cmode_tbl[i].t_sb;
- t_us = st->hal->cmode_tbl[i].t_us;
- if (st->poll_delay_us >=
- st->hal->cmode_tbl[i].t_us)
- break;
+ unsigned int scale_i;
+ unsigned int us = 0;
+ int ret = 0;
- i++;
- if (!st->mpu_en) {
- t_us -= st->hal->cmode_tbl[i].t_us;
- t_us >>= 1;
- t_us += st->hal->cmode_tbl[i].t_us;
- if (st->poll_delay_us > t_us)
+ i = BMP_DEV_PRS;
+ if (st->cmode) {
+ if (scale_user) {
+ /* static scale mode */
+ scale_i = scale_user - 1;
+ us = bmp_cmode_t(st, &t_sb, period_us, scale_i);
+ } else {
+ /* auto scale mode - matching scale to the period */
+ scale_i = 0;
+ for (; scale_i < st->hal->dev[i].scale_n; scale_i++) {
+ us = bmp_cmode_t(st, &t_sb,
+ period_us, scale_i);
+ if (period_us >= us)
+ /* HW (us) is fast enough */
break;
}
+
+ if (scale_i >= st->hal->dev[i].scale_n)
+ scale_i = st->hal->dev[i].scale_n - 1;
}
+
+ if (period_us < us)
+ period_us = us;
+ mode = BMP280_REG_CTRL_MODE_NORMAL;
+ mode |= st->hal->dev[BMP_DEV_TMP].scale[scale_i].os <<
+ BMP280_REG_CTRL_OSRS_T;
+ if (enable & (1 << BMP_DEV_PRS))
+ mode |= st->hal->dev[BMP_DEV_PRS].scale[scale_i].os <<
+ BMP280_REG_CTRL_OSRS_P;
+ /* else presure will be disabled */
t_sb <<= BMP280_REG_CONFIG_T_SB;
- bmp_wr(st, BMP280_REG_CONFIG, t_sb);
- mode |= BMP280_REG_CTRL_MODE_NORMAL;
+ ret = bmp_nvi_mpu_bypass_request(st);
+ if (!ret) {
+ ret = bmp_wr(st, BMP280_REG_CONFIG, t_sb);
+ if (ret)
+ mode = BMP_REG_CTRL_MODE_SLEEP;
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_info(&st->i2c->dev, "%s cfg=%x err=%d\n",
+ __func__, t_sb, ret);
+ ret |= bmp_mode_wr(st, mode);
+ bmp_nvi_mpu_bypass_release(st);
+ }
+ } else {
+ if (scale_user) {
+ scale_i = scale_user - 1;
+ us = st->hal->dev[i].scale[scale_i].delay_ms * 1000;
+ } else {
+ /* scale is automatic based on period */
+ scale_i = 0;
+ for (; scale_i < st->hal->dev[i].scale_n; scale_i++) {
+ us = st->hal->dev[i].scale[scale_i].delay_ms;
+ us *= 1000;
+ if (period_us >= us)
+ /* HW (us) is fast enough */
+ break;
+ }
+
+ if (scale_i >= st->hal->dev[i].scale_n)
+ scale_i = st->hal->dev[i].scale_n - 1;
+ }
+
+ if (period_us < us)
+ period_us = us;
+#if BMP_NVI_MPU_SUPPORT
+ if (scale_i != st->scale_i && st->mpu_en &&
+ st->port_id[WR] >= 0)
+ ret = nvi_mpu_delay_ms(st->port_id[WR],
+ st->hal->dev[i].scale[scale_i].delay_ms);
+#endif /* BMP_NVI_MPU_SUPPORT */
+ if (st->dev_id == BMP_REG_ID_BMP180) {
+ mode = st->hal->dev[i].scale[scale_i].os <<
+ BMP180_REG_CTRL_OSS;
+ mode |= BMP180_REG_CTRL_MODE_TEMP;
+ } else {
+ mode = BMP280_REG_CTRL_MODE_FORCED1;
+ mode |= st->hal->dev[BMP_DEV_TMP].scale[scale_i].os <<
+ BMP280_REG_CTRL_OSRS_T;
+ if (enable & (1 << BMP_DEV_PRS))
+ mode |= st->hal->dev[i].scale[scale_i].os <<
+ BMP280_REG_CTRL_OSRS_P;
+ }
+ ret |= bmp_mode_wr(st, mode);
+ }
+ if (!ret) {
+ if (period_us != st->poll_delay_us) {
+ if (st->sts & NVS_STS_SPEW_MSG)
+ dev_info(&st->i2c->dev, "%s: period_us=%u\n",
+ __func__, period_us);
+#if BMP_NVI_MPU_SUPPORT
+ if (st->mpu_en) {
+ us = -1;
+ for (i = 0; i < BMP_DEV_N; i++) {
+ if ((enable & (1 << i)) &&
+ st->timeout_us[i] < us)
+ us = st->timeout_us[i];
+ }
+ ret = nvi_mpu_batch(st->port_id[RD],
+ period_us, us);
+ }
+ if (!ret)
+#endif /* BMP_NVI_MPU_SUPPORT */
+ st->poll_delay_us = period_us;
+ }
+ if (!ret)
+ st->scale_i = scale_i;
}
- ret = bmp_mode_wr(st, mode);
return ret;
}
long X1, X2, X3, B3, B5, B6, p;
unsigned long B4, B7;
long pressure;
+ u8 oss = st->hal->dev[BMP_DEV_PRS].scale[st->scale_i].os;
X1 = ((st->ut - st->rom.bmp180.ac6) * st->rom.bmp180.ac5) >> 15;
X2 = st->rom.bmp180.mc * (1 << 11) / (X1 + st->rom.bmp180.md);
B5 = X1 + X2;
- st->temp = (B5 + 8) >> 4;
+ st->tmp = (B5 + 8) >> 4;
B6 = B5 - 4000;
X1 = (st->rom.bmp180.b2 * ((B6 * B6) >> 12)) >> 11;
X2 = (st->rom.bmp180.ac2 * B6) >> 11;
X3 = X1 + X2;
- B3 = ((((st->rom.bmp180.ac1 << 2) + X3) << st->scale_i) + 2) >> 2;
+ B3 = ((((st->rom.bmp180.ac1 << 2) + X3) << oss) + 2) >> 2;
X1 = (st->rom.bmp180.ac3 * B6) >> 13;
X2 = (st->rom.bmp180.b1 * ((B6 * B6) >> 12)) >> 16;
X3 = ((X1 + X2) + 2) >> 2;
B4 = (st->rom.bmp180.ac4 * (unsigned long)(X3 + 32768)) >> 15;
- B7 = ((unsigned long)st->up - B3) * (50000 >> st->scale_i);
+ B7 = ((unsigned long)st->up - B3) * (50000 >> oss);
if (B7 < 0x80000000)
p = (B7 << 1) / B4;
else
X1 = (X1 * 3038) >> 16;
X2 = (-7357 * p) >> 16;
pressure = p + ((X1 + X2 + 3791) >> 4);
- st->pressure = (int)pressure;
+ st->prs = (int)pressure;
}
static int bmp_read_sts_180(struct bmp_state *st, u8 *data, s64 ts)
{
+ u8 oss;
s32 val;
int ret = 0;
/* BMP180_REG_CTRL_SCO is 0 when data is ready */
if (!(data[0] & (1 << BMP180_REG_CTRL_SCO))) {
+ oss = st->hal->dev[BMP_DEV_PRS].scale[st->scale_i].os;
ret = -1;
if (data[0] == 0x0A) { /* temperature */
st->ut = ((data[2] << 8) + data[3]);
st->data_out = BMP180_REG_CTRL_MODE_PRES |
- (st->scale_i << BMP180_REG_CTRL_OSS);
+ (oss << BMP180_REG_CTRL_OSS);
} else { /* pressure */
- val = ((data[2] << 16) + (data[3] << 8) +
- data[4]) >> (8 - st->scale_i);
+ val = ((data[2] << 16) + (data[3] << 8) + data[4]);
+ val >>= (8 - oss);
st->data_out = BMP180_REG_CTRL_MODE_TEMP;
st->up = val;
bmp_calc_180(st);
- st->ts = ts;
ret = 1;
}
}
ts = nvs_timestamp();
ret = bmp_read_sts_180(st, data, ts);
if (ret > 0) {
- if (st->nvs_st[BMP_DEV_PRES])
- st->nvs->handler(st->nvs_st[BMP_DEV_PRES],
- &st->pressure, ts);
- if (st->nvs_st[BMP_DEV_TEMP])
- st->nvs->handler(st->nvs_st[BMP_DEV_TEMP],
- &st->temp, ts);
+ if (st->enabled & (1 << BMP_DEV_PRS))
+ st->nvs->handler(st->nvs_st[BMP_DEV_PRS],
+ &st->prs, ts);
+ if (st->enabled & (1 << BMP_DEV_TMP))
+ /* nvs handles on-change sensor timing & same values */
+ st->nvs->handler(st->nvs_st[BMP_DEV_TMP],
+ &st->tmp, ts);
bmp_i2c_wr(st, BMP_REG_CTRL, st->data_out);
} else if (ret < 0) {
bmp_i2c_wr(st, BMP_REG_CTRL, st->data_out);
static void bmp_calc_temp_280(struct bmp_state *st)
{
- s32 adc_t;
s32 var1;
s32 var2;
- adc_t = st->ut;
- adc_t >>= (4 - st->scale_i);
- var1 = adc_t >> 3;
- var1 -= ((s32)st->rom.bmp280.dig_T1 << 1);
- var1 *= (s32)st->rom.bmp280.dig_T2;
+ var1 = st->ut;
+ var1 >>= 3;
+ var2 = st->rom.bmp280.dig_T1;
+ var2 <<= 1;
+ var1 -= var2;
+ var1 *= st->rom.bmp280.dig_T2;
var1 >>= 11;
- var2 = adc_t >> 4;
+ var2 = st->ut;
+ var2 >>= 4;
var2 -= (s32)st->rom.bmp280.dig_T1;
var2 *= var2;
var2 >>= 12;
- var2 *= (s32)st->rom.bmp280.dig_T3;
+ var2 *= st->rom.bmp280.dig_T3;
var2 >>= 14;
st->t_fine = var1 + var2;
- st->temp = (st->t_fine * 5 + 128) >> 8;
+ st->tmp = (st->t_fine * 5 + 128) >> 8;
}
static int bmp_calc_pres_280(struct bmp_state *st)
{
- s32 adc_p;
- s32 var1;
- s32 var2;
- s32 var3;
- u32 p;
-
- adc_p = st->up;
- var1 = st->t_fine >> 1;
- var1 -= 64000;
- var2 = var1 >> 2;
- var2 *= var2;
- var3 = var2;
- var2 >>= 11;
+ s64 var1;
+ s64 var2;
+ s64 var3;
+ s64 p;
+
+ var1 = st->t_fine;
+ var1 -= 128000;
+ var2 = var1 * var1;
var2 *= st->rom.bmp280.dig_P6;
- var2 += ((var1 * st->rom.bmp280.dig_P5) << 1);
- var2 >>= 2;
- var2 += (st->rom.bmp280.dig_P4 << 16);
- var3 >>= 13;
- var3 *= st->rom.bmp280.dig_P3;
- var3 >>= 3;
- var1 *= st->rom.bmp280.dig_P2;
- var1 >>= 1;
+ var3 = st->rom.bmp280.dig_P5;
+ var3 *= var1;
+ var3 <<= 17;
+ var2 += var3;
+ var3 = st->rom.bmp280.dig_P4;
+ var3 <<= 35;
+ var2 += var3;
+ var3 = var1;
+ var3 *= st->rom.bmp280.dig_P2;
+ var3 <<= 12;
+ var1 *= var1;
+ var1 *= st->rom.bmp280.dig_P3;
+ var1 >>= 8;
+ var1 += var3;
+ var3 = 1;
+ var3 <<= 47;
var1 += var3;
- var1 >>= 18;
- var1 += 32768;
var1 *= st->rom.bmp280.dig_P1;
- var1 >>= 15;
+ var1 >>= 33;
if (!var1)
return -1;
- p = ((u32)(((s32)1048576) - adc_p) - (var2 >> 12)) * 3125;
- if (p < 0x80000000)
- p = (p << 1) / ((u32)var1);
- else
- p = (p / (u32)var1) << 1;
- var3 = p >> 3;
- var3 *= var3;
- var3 >>= 13;
- var1 = (s32)st->rom.bmp280.dig_P9 * var3;
- var1 >>= 12;
- var2 = (s32)(p >> 2);
- var2 *= (s32)st->rom.bmp280.dig_P8;
- var2 >>= 13;
- var3 = var1 + var2 + st->rom.bmp280.dig_P7;
- var3 >>= 4;
- p = (u32)((s32)p + var3);
- st->pressure = (int)p;
+ p = 1048576 - st->up;
+ p <<= 31;
+ p -= var2;
+ p *= 3125;
+ p = div64_s64(p, var1);
+ var1 = p;
+ var1 >>= 13;
+ var1 *= var1;
+ var1 *= st->rom.bmp280.dig_P9;
+ var1 >>= 25;
+ var2 = st->rom.bmp280.dig_P8;
+ var2 *= p;
+ var2 >>= 19;
+ var3 = st->rom.bmp280.dig_P7;
+ var3 <<= 4;
+ p += var1;
+ p += var2;
+ p >>= 8;
+ p += var3;
+ p >>= 8;
+ st->prs = (u32)p;
return 1;
}
val >>= 4;
st->ut = val;
bmp_calc_temp_280(st);
- ret = bmp_calc_pres_280(st);
- if (ret > 0) {
- st->ts = ts;
- if (st->nvs_st[BMP_DEV_PRES])
- st->nvs->handler(st->nvs_st[BMP_DEV_PRES],
- &st->pressure, ts);
- if (st->nvs_st[BMP_DEV_TEMP])
- st->nvs->handler(st->nvs_st[BMP_DEV_TEMP],
- &st->temp, ts);
+ if (st->enabled & (1 << BMP_DEV_PRS)) {
+ ret = bmp_calc_pres_280(st);
+ if (ret > 0)
+ st->nvs->handler(st->nvs_st[BMP_DEV_PRS],
+ &st->prs, ts);
+ } else {
+ ret = 1;
}
+ if (st->enabled & (1 << BMP_DEV_TMP))
+ /* nvs handles on-change sensor timing & same values */
+ st->nvs->handler(st->nvs_st[BMP_DEV_TMP], &st->tmp, ts);
return ret;
}
}
if (st->enabled) {
- if (len == 6) {
+ if (len == st->dmp_rd_len_sts)
+ /* status data from the DMP not supported */
+ return;
+
+ if (len == st->dmp_rd_len_data) {
/* this data is from the DMP */
i = 0;
ret = 1;
return;
}
- if (st->enabled) {
- ret = bmp_read_sts_180(st, data, ts);
- if (ret > 0) {
- if (st->nvs_st[BMP_DEV_PRES])
- st->nvs->handler(st->nvs_st[BMP_DEV_PRES],
- &st->pressure, ts);
- if (st->nvs_st[BMP_DEV_TEMP])
- st->nvs->handler(st->nvs_st[BMP_DEV_TEMP],
- &st->temp, ts);
- nvi_mpu_data_out(st->port_id[WR], st->data_out);
- } else if (ret < 0) {
- nvi_mpu_data_out(st->port_id[WR], st->data_out);
- }
+ ret = bmp_read_sts_180(st, data, ts);
+ if (ret > 0) {
+ if (st->enabled & (1 << BMP_DEV_PRS))
+ st->nvs->handler(st->nvs_st[BMP_DEV_PRS],
+ &st->prs, ts);
+ if (st->enabled & (1 << BMP_DEV_TMP))
+ /* nvs handles on-change sensor timing & same values */
+ st->nvs->handler(st->nvs_st[BMP_DEV_TMP],
+ &st->tmp, ts);
+ nvi_mpu_data_out(st->port_id[WR], st->data_out);
+ } else if (ret < 0) {
+ nvi_mpu_data_out(st->port_id[WR], st->data_out);
}
}
#endif /* BMP_NVI_MPU_SUPPORT */
st->nvs->nvs_mutex_unlock(st->nvs_st[i]);
}
-static unsigned int bmp_poll_delay(struct bmp_state *st)
+static unsigned int bmp_poll_delay(struct bmp_state *st, unsigned int en_msk)
{
unsigned int i;
unsigned int delay_us = -1;
+ bool valid = false;
for (i = 0; i < BMP_DEV_N; i++) {
- if (st->enabled & (1 << i)) {
- if (st->delay_us[i] < delay_us)
+ if (en_msk & (1 << i)) {
+ if (st->delay_us[i] && st->delay_us[i] < delay_us) {
delay_us = st->delay_us[i];
+ valid = true;
+ }
}
}
- if (delay_us == -1)
+ if (!valid)
delay_us = (BMP_POLL_DELAY_MS_DFLT * 1000);
return delay_us;
}
-static int bmp_delay(struct bmp_state *st,
- unsigned int delay_us, int scale_user)
-{
- unsigned int timeout;
- unsigned int i;
- int ret;
- int ret_t = 0;
-
- if (scale_user) {
- i = scale_user - 1;
- } else {
- for (i = (st->hal->p->scale_i_max - 1); i > 0; i--) {
- if (delay_us >= (st->hal->p->scale[i].delay_ms * 1000))
- break;
- }
- }
- if (i != st->scale_i) {
- ret = 0;
-#if BMP_NVI_MPU_SUPPORT
- if (st->mpu_en)
- ret = nvi_mpu_delay_ms(st->port_id[WR],
- st->hal->p->scale[i].delay_ms);
-#endif /* BMP_NVI_MPU_SUPPORT */
- if (ret < 0)
- ret_t |= ret;
- else
- st->scale_i = i;
- }
- if (delay_us < (st->hal->p->scale[st->scale_i].delay_ms * 1000))
- delay_us = (st->hal->p->scale[st->scale_i].delay_ms * 1000);
- if (delay_us != st->poll_delay_us) {
- if (st->sts & NVS_STS_SPEW_MSG)
- dev_info(&st->i2c->dev, "%s: %u\n",
- __func__, delay_us);
-#if BMP_NVI_MPU_SUPPORT
- ret = 0;
- if (st->mpu_en) {
- timeout = -1;
- for (i = 0; i < BMP_DEV_N; i++) {
- if (st->enabled & (1 << i)) {
- if (st->timeout_us[i] < timeout)
- timeout = st->timeout_us[i];
- }
- }
- ret = nvi_mpu_batch(st->port_id[RD],
- delay_us, timeout);
- }
- if (ret)
- ret_t |= ret;
- else
-#endif /* BMP_NVI_MPU_SUPPORT */
- st->poll_delay_us = delay_us;
- }
- return ret_t;
-}
-
static int bmp_init_hw(struct bmp_state *st)
{
u8 *p_rom8;
st->ut = 0;
st->up = 0;
- st->temp = 0;
- st->pressure = 0;
+ st->tmp = 0;
+ st->prs = 0;
p_rom8 = (u8 *)&st->rom;
ret = bmp_nvi_mpu_bypass_request(st);
if (!ret) {
static int bmp_dis(struct bmp_state *st)
{
+#if BMP_NVI_MPU_SUPPORT
int ret = 0;
if (st->mpu_en)
if (!ret)
st->enabled = 0;
return ret;
+#else /* BMP_NVI_MPU_SUPPORT */
+ cancel_delayed_work(&st->dw);
+ st->enabled = 0;
+ return 0;
+#endif /* BMP_NVI_MPU_SUPPORT */
}
static int bmp_disable(struct bmp_state *st, int snsr_id)
enable = st->enabled | (1 << snsr_id);
ret = bmp_en(st);
if (!ret) {
- ret |= bmp_delay(st, bmp_poll_delay(st),
- st->scale_user);
- ret |= bmp_mode(st);
+ ret = bmp_mode(st, bmp_poll_delay(st, enable),
+ st->scale_user, enable);
+#if BMP_NVI_MPU_SUPPORT
if (st->mpu_en)
ret |= bmp_ports_enable(st, true);
+#endif /* BMP_NVI_MPU_SUPPORT */
if (ret) {
bmp_disable(st, snsr_id);
} else {
unsigned int period, unsigned int timeout)
{
struct bmp_state *st = (struct bmp_state *)client;
+ int ret = 0;
unsigned int old_period;
unsigned int old_timeout;
- int ret;
if (timeout && !st->mpu_en)
/* timeout not supported (no HW FIFO) */
old_timeout = st->timeout_us[snsr_id];
st->delay_us[snsr_id] = period;
st->timeout_us[snsr_id] = timeout;
- ret = bmp_delay(st, bmp_poll_delay(st), st->scale_user);
- if (st->enabled && st->i2c->irq && !ret)
- ret = bmp_mode(st);
- if (ret) {
- st->delay_us[snsr_id] = old_period;
- st->timeout_us[snsr_id] = old_timeout;
+ if (st->enabled) {
+ ret = bmp_mode(st, bmp_poll_delay(st, st->enabled),
+ st->scale_user, st->enabled);
+ if (ret) {
+ st->delay_us[snsr_id] = old_period;
+ st->timeout_us[snsr_id] = old_timeout;
+ }
}
- return 0;
+ return ret;
}
static int bmp_flush(void *client, int snsr_id)
if (st->mpu_en)
ret = nvi_mpu_flush(st->port_id[RD]);
#endif /* BMP_NVI_MPU_SUPPORT */
+
return ret;
}
static int bmp_resolution(void *client, int snsr_id, int resolution)
{
struct bmp_state *st = (struct bmp_state *)client;
+ unsigned int us;
+ unsigned int i;
int ret;
- if (snsr_id != BMP_DEV_PRES)
+ if (snsr_id != BMP_DEV_PRS)
return -EINVAL;
- if (resolution < 0 || resolution > st->hal->p->scale_i_max)
- return -EINVAL;
+ if (resolution < 0)
+ resolution = 0;
+ if (resolution > st->hal->dev[BMP_DEV_PRS].scale_n)
+ resolution = st->hal->dev[BMP_DEV_PRS].scale_n;
+ if (st->enabled) {
+ ret = bmp_mode(st, st->poll_delay_us, resolution, st->enabled);
+ if (ret)
+ return ret;
+ } else {
+ if (resolution)
+ st->scale_i = resolution - 1;
+ else
+ st->scale_i = 0;
+ }
- ret = bmp_delay(st, st->poll_delay_us, resolution);
- if (!ret) {
- st->scale_user = resolution;
- if (st->enabled && st->i2c->irq)
- ret = bmp_mode(st);
+ st->scale_user = resolution;
+ for (i = 0; i < BMP_DEV_N; i++) {
+ st->cfg[i].resolution.ival =
+ st->hal->dev[i].scale[st->scale_i].resolution.ival;
+ st->cfg[i].resolution.fval =
+ st->hal->dev[i].scale[st->scale_i].resolution.fval;
+ st->cfg[i].milliamp.ival =
+ st->hal->dev[i].scale[st->scale_i].milliamp.ival;
+ st->cfg[i].milliamp.fval =
+ st->hal->dev[i].scale[st->scale_i].milliamp.fval;
+ us = st->hal->dev[i].scale[st->scale_i].delay_ms * 1000;
+ if (us < st->period_us_min)
+ us = st->period_us_min;
+ st->cfg[i].delay_us_min = us;
}
- if (ret)
- return ret;
- st->cfg[BMP_DEV_PRES].resolution.ival =
- st->hal->p->scale[st->scale_i].resolution.ival;
- st->cfg[BMP_DEV_PRES].resolution.fval =
- st->hal->p->scale[st->scale_i].resolution.fval;
- st->cfg[BMP_DEV_PRES].milliamp.ival =
- st->hal->p->scale[st->scale_i].milliamp.ival;
- st->cfg[BMP_DEV_PRES].milliamp.fval =
- st->hal->p->scale[st->scale_i].milliamp.fval;
- st->cfg[BMP_DEV_PRES].delay_us_min =
- st->hal->p->scale[st->scale_i].delay_ms * 1000;
- st->cfg[BMP_DEV_TEMP].resolution.ival =
- st->hal->t->scale[st->scale_i].resolution.ival;
- st->cfg[BMP_DEV_TEMP].resolution.fval =
- st->hal->t->scale[st->scale_i].resolution.fval;
- st->cfg[BMP_DEV_TEMP].milliamp.ival =
- st->hal->t->scale[st->scale_i].milliamp.ival;
- st->cfg[BMP_DEV_TEMP].milliamp.fval =
- st->hal->t->scale[st->scale_i].milliamp.fval;
- st->cfg[BMP_DEV_TEMP].delay_us_min =
- st->hal->t->scale[st->scale_i].delay_ms * 1000;
return 0;
}
int ret;
if (!st->initd) {
- t = sprintf(buf, "calibration: NEED ENABLE\n");
+ t = snprintf(buf, PAGE_SIZE, "calibration: NEED ENABLE\n");
} else {
- t = sprintf(buf, "calibration:\n");
+ t = snprintf(buf, PAGE_SIZE, "calibration:\n");
cal = &st->rom.bmp280.dig_T1;
for (i = 0; i < st->hal->rom_size; i = i + 2)
- t += sprintf(buf + t, "%#2x=%#2x\n",
- st->hal->rom_addr_start + i,
- *cal++);
+ t += snprintf(buf + t, PAGE_SIZE - t, "%#2x=%#2x\n",
+ st->hal->rom_addr_start + i, *cal++);
}
ret = bmp_nvi_mpu_bypass_request(st);
if (!ret) {
bmp_nvi_mpu_bypass_release(st);
}
if (ret) {
- t += sprintf(buf + t, "registers: ERR %d\n", ret);
+ t += snprintf(buf + t, PAGE_SIZE - t,
+ "registers: ERR %d\n", ret);
} else {
- t += sprintf(buf + t, "registers:\n");
- t += sprintf(buf + t, "%#2x=%#2x\n",
- BMP_REG_ID, data[0]);
+ t += snprintf(buf + t, PAGE_SIZE - t, "registers:\n");
+ t += snprintf(buf + t, PAGE_SIZE - t, "%#2x=%#2x\n",
+ BMP_REG_ID, data[0]);
for (i = 0; i < 10; i++)
- t += sprintf(buf + t, "%#2x=%#2x\n",
- BMP280_REG_STATUS + i,
- data[i + 1]);
+ t += snprintf(buf + t, PAGE_SIZE - t, "%#2x=%#2x\n",
+ BMP280_REG_STATUS + i, data[i + 1]);
}
return t;
}
struct bmp_state *st = (struct bmp_state *)client;
ssize_t t;
- t = sprintf(buf, "driver v.%u\n", BMP_DRIVER_VERSION);
- t += sprintf(buf + t, "mpu_en=%x\n", st->mpu_en);
- t += sprintf(buf + t, "nvi_config=%hhu\n", st->nvi_config);
+ t = snprintf(buf, PAGE_SIZE, "driver v.%u\n", BMP_DRIVER_VERSION);
+ t += snprintf(buf + t, PAGE_SIZE - t, "mpu_en=%x\n", st->mpu_en);
+ t += snprintf(buf + t, PAGE_SIZE - t, "nvi_config=%hhu\n",
+ st->nvi_config);
+ t += snprintf(buf + t, PAGE_SIZE - t, "cmode_enable=%x\n", st->cmode);
+ if (!st->scale_user)
+ t += snprintf(buf + t, PAGE_SIZE - t, "scale_user=auto\n");
+ t += snprintf(buf + t, PAGE_SIZE - t, "scale_i=%x\n", st->scale_i);
return t;
}
struct sensor_cfg bmp_cfg_dflt[] = {
{
.name = "pressure",
- .snsr_id = BMP_DEV_PRES,
+ .snsr_id = BMP_DEV_PRS,
.kbuf_sz = BMP_KBUF_SIZE,
.ch_n = 1,
.ch_sz = -4,
.ival = BMP_PRES_MAX_RANGE_IVAL,
.fval = BMP_PRES_MAX_RANGE_MICRO,
},
- .delay_us_min = 10000,
- .delay_us_max = 255000,
},
{
.name = "ambient_temperature",
- .snsr_id = BMP_DEV_TEMP,
+ .snsr_id = BMP_DEV_TMP,
.ch_n = 1,
.ch_sz = -4,
.part = BMP_NAME,
.ival = BMP_TEMP_MAX_RANGE_IVAL,
.fval = BMP_TEMP_MAX_RANGE_MICRO,
},
- .delay_us_min = 10000,
- .delay_us_max = 255000,
.flags = SENSOR_FLAG_ON_CHANGE_MODE,
},
};
-static struct bmp_scale bmp_scale_pres_180[] = {
+static struct bmp_scale bmp_scale_prs_180[] = {
{
- .delay_ms = 5,
+ .delay_ms = 26,
+ .os = 0x03,
.resolution = {
.ival = 0,
.fval = 10000,
},
.milliamp = {
.ival = 0,
- .fval = 3000,
+ .fval = 12000,
},
},
{
- .delay_ms = 8,
+ .delay_ms = 14,
+ .os = 0x02,
.resolution = {
.ival = 0,
.fval = 10000,
},
.milliamp = {
.ival = 0,
- .fval = 5000,
+ .fval = 7000,
},
},
{
- .delay_ms = 14,
+ .delay_ms = 8,
+ .os = 0x01,
.resolution = {
.ival = 0,
.fval = 10000,
},
.milliamp = {
.ival = 0,
- .fval = 7000,
+ .fval = 5000,
},
},
{
- .delay_ms = 26,
+ .delay_ms = 5,
+ .os = 0x00,
.resolution = {
.ival = 0,
.fval = 10000,
},
.milliamp = {
.ival = 0,
- .fval = 12000,
+ .fval = 3000,
},
},
};
-static struct bmp_scale bmp_scale_temp_180[] = {
+static struct bmp_scale bmp_scale_tmp_180[] = {
{
- .delay_ms = 5,
+ .delay_ms = 26,
.resolution = {
.ival = 0,
.fval = 100000,
},
.milliamp = {
.ival = 0,
- .fval = 3000,
+ .fval = 12000,
},
},
{
- .delay_ms = 8,
+ .delay_ms = 14,
.resolution = {
.ival = 0,
.fval = 100000,
},
.milliamp = {
.ival = 0,
- .fval = 5000,
+ .fval = 7000,
},
},
{
- .delay_ms = 14,
+ .delay_ms = 8,
.resolution = {
.ival = 0,
.fval = 100000,
},
.milliamp = {
.ival = 0,
- .fval = 7000,
+ .fval = 5000,
},
},
{
- .delay_ms = 26,
+ .delay_ms = 5,
.resolution = {
.ival = 0,
.fval = 100000,
},
.milliamp = {
.ival = 0,
- .fval = 12000,
+ .fval = 3000,
},
},
};
-static struct bmp_hal_dev bmp_hal_dev_pres_180 = {
- .version = 1,
- .scale_i_max = ARRAY_SIZE(bmp_scale_pres_180),
- .scale_dflt = BMP180_RANGE_DFLT,
- .scale = bmp_scale_pres_180,
- .scale_float = {
- .ival = 0,
- .fval = 10000,
- }
-};
-
-static struct bmp_hal_dev bmp_hal_dev_temp_180 = {
- .version = 1,
- .scale_i_max = ARRAY_SIZE(bmp_scale_temp_180),
- .scale_dflt = BMP180_RANGE_DFLT,
- .scale = bmp_scale_temp_180,
- .scale_float = {
- .ival = 0,
- .fval = 100000,
- }
+static struct bmp_hal_dev bmp_hal_dev_180[] = {
+ {
+ .version = 1,
+ .scale_n = ARRAY_SIZE(bmp_scale_prs_180),
+ .scale = bmp_scale_prs_180,
+ .scale_float = {
+ .ival = 0,
+ .fval = 10000,
+ },
+ },
+ {
+ .version = 1,
+ .scale_n = ARRAY_SIZE(bmp_scale_tmp_180),
+ .scale = bmp_scale_tmp_180,
+ .scale_float = {
+ .ival = 0,
+ .fval = 100000,
+ }
+ },
};
static struct bmp_hal bmp_hal_180 = {
- .p = &bmp_hal_dev_pres_180,
- .t = &bmp_hal_dev_temp_180,
+ .dev = bmp_hal_dev_180,
.part = BMP180_NAME,
.rom_addr_start = BMP180_REG_AC1,
.rom_size = 22,
.mode_mask = BMP180_REG_CTRL_MODE_MASK,
.cmode_tbl = NULL,
.bmp_read = &bmp_read_180,
+#if BMP_NVI_MPU_SUPPORT
+ .mpu_id = 0,
+ .port_rd_reg = BMP_REG_CTRL,
+ .port_rd_ctrl = 6,
+ .port_rd_handler = &bmp_mpu_handler_180,
+#endif /* BMP_NVI_MPU_SUPPORT */
};
-static struct bmp_scale bmp_scale_pres_280[] = {
+static struct bmp_scale bmp_scale_prs_280[] = {
{
- .delay_ms = 9,
+ .delay_ms = 44,
+ .os = 0x05,
.resolution = {
.ival = 0,
- .fval = 28700,
+ .fval = 1800,
},
.milliamp = {
.ival = 0,
- .fval = 2740,
+ .fval = 24800,
},
},
{
- .delay_ms = 12,
+ .delay_ms = 23,
+ .os = 0x04,
.resolution = {
.ival = 0,
- .fval = 14300,
+ .fval = 3600,
},
.milliamp = {
.ival = 0,
- .fval = 4170,
+ .fval = 12700,
},
},
{
- .delay_ms = 18,
+ .delay_ms = 14,
+ .os = 0x03,
.resolution = {
.ival = 0,
.fval = 7200,
},
},
{
- .delay_ms = 30,
+ .delay_ms = 9,
+ .os = 0x02,
.resolution = {
.ival = 0,
- .fval = 3600,
+ .fval = 14300,
},
.milliamp = {
.ival = 0,
- .fval = 12700,
+ .fval = 4170,
},
},
{
- .delay_ms = 57,
+ .delay_ms = 7,
+ .os = 0x01,
.resolution = {
.ival = 0,
- .fval = 1800,
+ .fval = 28700,
},
.milliamp = {
.ival = 0,
- .fval = 24800,
+ .fval = 2740,
},
},
};
-static struct bmp_scale bmp_scale_temp_280[] = {
+static struct bmp_scale bmp_scale_tmp_280[] = {
+ /* os oversampling is useless > 2x and only used for pressure @ 16x */
{
- .delay_ms = 9,
+ .delay_ms = 44,
+ .os = 0x02,
.resolution = {
.ival = 0,
- .fval = 5000,
+ .fval = 300,
},
.milliamp = {
.ival = 0,
- .fval = 2740,
+ .fval = 24800,
},
},
{
- .delay_ms = 12,
+ .delay_ms = 23,
+ .os = 0x01,
.resolution = {
.ival = 0,
- .fval = 2500,
+ .fval = 600,
},
.milliamp = {
.ival = 0,
- .fval = 4170,
+ .fval = 12700,
},
},
{
- .delay_ms = 18,
+ .delay_ms = 14,
+ .os = 0x01,
.resolution = {
.ival = 0,
.fval = 1200,
},
},
{
- .delay_ms = 30,
+ .delay_ms = 9,
+ .os = 0x01,
.resolution = {
.ival = 0,
- .fval = 600,
+ .fval = 2500,
},
.milliamp = {
.ival = 0,
- .fval = 12700,
+ .fval = 4170,
},
},
{
- .delay_ms = 57,
+ .delay_ms = 7,
+ .os = 0x01,
.resolution = {
.ival = 0,
- .fval = 300,
+ .fval = 5000,
},
.milliamp = {
.ival = 0,
- .fval = 24800,
+ .fval = 2740,
},
},
};
-static struct bmp_hal_dev bmp_hal_dev_pres_280 = {
- .version = 1,
- .scale_i_max = ARRAY_SIZE(bmp_scale_pres_280),
- .scale_dflt = BMP280_RANGE_DFLT,
- .scale = bmp_scale_pres_280,
- .scale_float = {
- .ival = 0,
- .fval = 10000,
- }
-};
-
-static struct bmp_hal_dev bmp_hal_dev_temp_280 = {
- .version = 1,
- .scale_i_max = ARRAY_SIZE(bmp_scale_temp_280),
- .scale_dflt = BMP280_RANGE_DFLT,
- .scale = bmp_scale_temp_280,
- .scale_float = {
- .ival = 0,
- .fval = 10000,
- }
+static struct bmp_hal_dev bmp_hal_dev_280[] = {
+ {
+ .version = 1,
+ .scale_n = ARRAY_SIZE(bmp_scale_prs_280),
+ .scale = bmp_scale_prs_280,
+ .scale_float = {
+ .ival = 0,
+ .fval = 10000,
+ }
+ },
+ {
+ .version = 1,
+ .scale_n = ARRAY_SIZE(bmp_scale_tmp_280),
+ .scale = bmp_scale_tmp_280,
+ .scale_float = {
+ .ival = 0,
+ .fval = 10000,
+ },
+ },
};
static struct bmp_cmode bmp_cmode_280[] = {
};
static struct bmp_hal bmp_hal_280 = {
- .p = &bmp_hal_dev_pres_280,
- .t = &bmp_hal_dev_temp_280,
+ .dev = bmp_hal_dev_280,
.part = BMP280_NAME,
.rom_addr_start = BMP280_REG_CWORD00,
.rom_size = 26,
.bmp_read = &bmp_read_280,
#if BMP_NVI_MPU_SUPPORT
.mpu_id = PRESSURE_ID_BMP280,
+ .port_rd_reg = BMP280_REG_STATUS,
+ .port_rd_ctrl = 10,
+ .port_rd_handler = &bmp_mpu_handler_280,
#endif /* BMP_NVI_MPU_SUPPORT */
};
break;
}
- st->scale_user = st->hal->p->scale_dflt;
+ /* default scale to fastest and least power usage */
+ st->scale_user = st->hal->dev[BMP_DEV_PRS].scale_n;
+ st->scale_i = st->scale_user - 1;
+ if (st->hal->cmode_tbl == NULL)
+ st->cmode = false;
for (i = 0; i < BMP_DEV_N; i++)
memcpy(&st->cfg[i], &bmp_cfg_dflt[i],
sizeof(struct sensor_cfg));
- st->cfg[BMP_DEV_PRES].part = st->hal->part;
- st->cfg[BMP_DEV_PRES].version = st->hal->p->version;
- st->cfg[BMP_DEV_PRES].resolution.ival =
- st->hal->p->scale[st->scale_i].resolution.ival;
- st->cfg[BMP_DEV_PRES].resolution.fval =
- st->hal->p->scale[st->scale_i].resolution.fval;
- st->cfg[BMP_DEV_PRES].milliamp.ival =
- st->hal->p->scale[st->scale_i].milliamp.ival;
- st->cfg[BMP_DEV_PRES].milliamp.fval =
- st->hal->p->scale[st->scale_i].milliamp.fval;
- st->cfg[BMP_DEV_PRES].delay_us_min =
- st->hal->p->scale[st->scale_i].delay_ms * 1000;
- st->cfg[BMP_DEV_PRES].scale.ival = st->hal->p->scale_float.ival;
- st->cfg[BMP_DEV_PRES].scale.fval = st->hal->p->scale_float.fval;
- st->cfg[BMP_DEV_TEMP].part = st->hal->part;
- st->cfg[BMP_DEV_TEMP].version = st->hal->t->version;
- st->cfg[BMP_DEV_TEMP].resolution.ival =
- st->hal->t->scale[st->scale_i].resolution.ival;
- st->cfg[BMP_DEV_TEMP].resolution.fval =
- st->hal->t->scale[st->scale_i].resolution.fval;
- st->cfg[BMP_DEV_TEMP].milliamp.ival =
- st->hal->t->scale[st->scale_i].milliamp.ival;
- st->cfg[BMP_DEV_TEMP].milliamp.fval =
- st->hal->t->scale[st->scale_i].milliamp.fval;
- st->cfg[BMP_DEV_TEMP].delay_us_min =
- st->hal->t->scale[st->scale_i].delay_ms * 1000;
- st->cfg[BMP_DEV_TEMP].scale.ival = st->hal->t->scale_float.ival;
- st->cfg[BMP_DEV_TEMP].scale.fval = st->hal->t->scale_float.fval;
+ for (i = 0; i < BMP_DEV_N; i++) {
+ st->cfg[i].part = st->hal->part;
+ st->cfg[i].version = st->hal->dev[i].version;
+ st->cfg[i].scale.ival = st->hal->dev[i].scale_float.ival;
+ st->cfg[i].scale.fval = st->hal->dev[i].scale_float.fval;
+ }
return ret;
}
{
#if BMP_NVI_MPU_SUPPORT
struct nvi_mpu_port nmp;
+ struct nvi_mpu_inf inf;
+ unsigned int i;
u8 config_boot;
#endif /* BMP_NVI_MPU_SUPPORT */
u8 val = 0;
if (config_boot == NVI_CONFIG_BOOT_MPU) {
st->mpu_en = true;
bmp_id_hal(st);
- if (st->hal->cmode_tbl == NULL || !st->i2c->irq) {
- nmp.addr = st->i2c_addr;
- nmp.reg = BMP_REG_CTRL;
- nmp.ctrl = 1;
- nmp.data_out = st->data_out;
- nmp.delay_ms = st->hal->p->scale[st->scale_i].delay_ms;
- nmp.delay_us = 0;
- nmp.shutdown_bypass = false;
- nmp.handler = NULL;
- nmp.ext_driver = NULL;
- ret = nvi_mpu_port_alloc(&nmp, 2);
- dev_dbg(&st->i2c->dev, "%s MPU port/ret=%d\n",
- __func__, ret);
- if (ret < 0)
+ nmp.type = SECONDARY_SLAVE_TYPE_PRESSURE;
+ nmp.id = st->hal->mpu_id;
+ nmp.addr = st->i2c_addr; /* write port */
+ nmp.reg = BMP_REG_CTRL;
+ nmp.ctrl = 1;
+ nmp.data_out = st->data_out;
+ nmp.delay_ms = st->hal->dev[BMP_DEV_PRS].
+ scale[st->scale_i].delay_ms;
+ nmp.period_us = 0;
+ nmp.shutdown_bypass = false;
+ nmp.handler = NULL;
+ nmp.ext_driver = NULL;
+ ret = nvi_mpu_port_alloc(&nmp);
+ dev_dbg(&st->i2c->dev, "%s MPU port/ret=%d\n",
+ __func__, ret);
+ /* By requesting the write port first it allows us to
+ * automatically determine if the DMP requires a single
+ * port, in which case this port request will fail.
+ * If this part does not support continuous mode
+ * required for single port operation, then this device
+ * population fails.
+ */
+ if (ret < 0) {
+ if (st->hal->cmode_tbl)
+ st->cmode = true;
+ else
return ret;
-
+ } else {
+ st->cmode = false;
st->port_id[WR] = ret;
}
- nmp.addr = st->i2c_addr | 0x80;
+
+ nmp.addr = st->i2c_addr | 0x80; /* read port */
nmp.data_out = 0;
nmp.delay_ms = 0;
- nmp.delay_us = st->poll_delay_us;
- if ((st->hal->cmode_tbl != NULL) && st->i2c->irq)
+ nmp.period_us = st->poll_delay_us;
+ if (st->cmode)
nmp.shutdown_bypass = true;
- else
- nmp.shutdown_bypass = false;
nmp.ext_driver = (void *)st;
- if (st->dev_id == BMP_REG_ID_BMP180) {
- nmp.reg = BMP_REG_CTRL;
- nmp.ctrl = 6; /* MPU FIFO can't handle odd size */
- nmp.handler = &bmp_mpu_handler_180;
- } else {
- nmp.reg = BMP280_REG_STATUS;
- nmp.ctrl = 10; /* MPU FIFO can't handle odd size */
- nmp.handler = &bmp_mpu_handler_280;
- }
- nmp.type = SECONDARY_SLAVE_TYPE_PRESSURE;
- nmp.id = st->hal->mpu_id;
- ret = nvi_mpu_port_alloc(&nmp, 3);
+ nmp.reg = st->hal->port_rd_reg;
+ nmp.ctrl = st->hal->port_rd_ctrl;
+ nmp.handler = st->hal->port_rd_handler;
+ ret = nvi_mpu_port_alloc(&nmp);
dev_dbg(&st->i2c->dev, "%s MPU port/ret=%d\n",
__func__, ret);
if (ret < 0) {
}
st->port_id[RD] = ret;
- nvi_mpu_fifo(st->port_id[RD],
- &st->cfg[BMP_DEV_PRES].fifo_rsrv_evnt_cnt,
- &st->cfg[BMP_DEV_PRES].fifo_max_evnt_cnt);
- st->cfg[BMP_DEV_TEMP].fifo_rsrv_evnt_cnt =
- st->cfg[BMP_DEV_PRES].fifo_rsrv_evnt_cnt;
- st->cfg[BMP_DEV_TEMP].fifo_max_evnt_cnt =
- st->cfg[BMP_DEV_PRES].fifo_max_evnt_cnt;
+ ret = nvi_mpu_info(st->port_id[RD], &inf);
+ if (ret)
+ return ret;
+
+ st->period_us_min = inf.period_us_min;
+ for (i = 0; i < BMP_DEV_N; i++) {
+ st->cfg[i].fifo_rsrv_evnt_cnt = inf.fifo_reserve;
+ st->cfg[i].fifo_max_evnt_cnt = inf.fifo_max;
+ st->cfg[i].delay_us_max = inf.period_us_max;
+ }
+ st->dmp_rd_len_sts = inf.dmp_rd_len_sts;
+ st->dmp_rd_len_data = inf.dmp_rd_len_data;
return 0;
}
#endif /* BMP_NVI_MPU_SUPPORT */
return -ENODEV;
/* this device supports these programmable parameters */
- if (!(of_property_read_string(dn, "nvi_config", &pchar))) {
+ if (!of_property_read_string(dn, "nvi_config", &pchar)) {
for (cfg = 0; cfg < ARRAY_SIZE(bmp_configs); cfg++) {
if (!strcasecmp(pchar, bmp_configs[cfg])) {
st->nvi_config = cfg;
}
}
}
- }
+ if (!of_property_read_u8(dn, "cmode_enable", &cfg)) {
+ if (cfg)
+ st->cmode = true;
+ else
+ st->cmode = false;
+ }
+ }
return 0;
}
{
struct bmp_state *st;
unsigned int i;
+ unsigned int n;
int ret;
dev_info(&client->dev, "%s %s\n", id->name, __func__);
bmp_pm_init(st);
ret = bmp_id_i2c(st, id);
if (ret == -EAGAIN)
- goto bmp_probe_again;
+ goto bmp_probe_exit;
else if (ret)
goto bmp_probe_err;
goto bmp_probe_err;
}
+ st->cfg[BMP_DEV_PRS].resolution.ival = st->scale_user;
+ nvs_of_dt(client->dev.of_node, &st->cfg[BMP_DEV_PRS], NULL);
+ bmp_resolution(st, BMP_DEV_PRS, st->cfg[BMP_DEV_PRS].resolution.ival);
+ nvs_of_dt(client->dev.of_node, &st->cfg[BMP_DEV_TMP], NULL);
+ if (st->cfg[BMP_DEV_PRS].snsr_id < 0)
+ /* pressure disabled so use temperature settings */
+ bmp_resolution(st, BMP_DEV_PRS,
+ st->cfg[BMP_DEV_TMP].resolution.ival);
+ n = 0;
for (i = 0; i < BMP_DEV_N; i++) {
- nvs_of_dt(client->dev.of_node, &st->cfg[i], NULL);
- ret |= st->nvs->probe(&st->nvs_st[i], st, &client->dev,
- &bmp_fn_dev, &st->cfg[i]);
+ ret = st->nvs->probe(&st->nvs_st[i], st, &client->dev,
+ &bmp_fn_dev, &st->cfg[i]);
+ if (!ret)
+ n++;
}
- if (ret) {
- dev_err(&client->dev, "%s nvs_probe ERR\n", __func__);
+ if (!n) {
ret = -ENODEV;
- goto bmp_probe_err;
+ goto bmp_probe_exit;
}
if (!st->mpu_en)
INIT_DELAYED_WORK(&st->dw, bmp_work);
-
dev_info(&client->dev, "%s done\n", __func__);
return 0;
bmp_probe_err:
dev_err(&client->dev, "%s ERR %d\n", __func__, ret);
-bmp_probe_again:
+bmp_probe_exit:
bmp_remove(client);
return ret;
}