blob: e7fb1f128039f7343f04c21dc655ac650c9a33e8 [file] [log] [blame]
/* sensor_bmc150_magn.c - Driver for Bosch BMC150 magnetometer sensor */
/*
* Copyright (c) 2016 Intel Corporation
*
* This code is based on bmm050.c from https://github.com/BoschSensortec/BMM050_driver
*
* 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.
*/
#include <sensor.h>
#include <nanokernel.h>
#include <device.h>
#include <init.h>
#include <i2c.h>
#include <misc/byteorder.h>
#include <gpio.h>
#include "sensor_bmc150_magn.h"
static struct bmc150_magn_data bmc150_magn_data;
#ifdef CONFIG_SENSOR_DEBUG
#include <misc/printk.h>
#define sensor_dbg(fmt, ...) printk("bmc150_magn: " fmt, ##__VA_ARGS__)
#else
#define sensor_dbg(fmt, ...) do { } while (0)
#endif /* CONFIG_SENSOR_DEBUG */
static const struct {
int freq;
uint8_t reg_val;
} bmc150_magn_samp_freq_table[] = { {2, 0x01},
{6, 0x02},
{8, 0x03},
{10, 0x00},
{15, 0x04},
{20, 0x05},
{25, 0x06},
{30, 0x07} };
static const struct bmc150_magn_preset {
uint8_t rep_xy;
uint8_t rep_z;
uint8_t odr;
} bmc150_magn_presets_table[] = {
[LOW_POWER_PRESET] = {3, 3, 10},
[REGULAR_PRESET] = {9, 15, 10},
[ENHANCED_REGULAR_PRESET] = {15, 27, 10},
[HIGH_ACCURACY_PRESET] = {47, 83, 20}
};
static int bmc150_magn_reg_read(struct device *dev, uint8_t reg, uint8_t *val)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
struct bmc150_magn_config *config =
(struct bmc150_magn_config *) dev->config->config_info;
struct i2c_msg msgs[2] = {
{
.buf = &reg,
.len = 1,
.flags = I2C_MSG_WRITE | I2C_MSG_RESTART,
},
{
.buf = val,
.len = 1,
.flags = I2C_MSG_READ | I2C_MSG_STOP,
},
};
return i2c_transfer(data->i2c_master, msgs, 2, config->i2c_slave_addr);
}
static int bmc150_magn_reg_bulk_read(struct device *dev, uint8_t reg,
uint8_t *buf, uint32_t len)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
struct bmc150_magn_config *config =
(struct bmc150_magn_config *) dev->config->config_info;
struct i2c_msg msgs[2] = {
{
.buf = &reg,
.len = 1,
.flags = I2C_MSG_WRITE | I2C_MSG_RESTART,
},
{
.buf = buf,
.len = len,
.flags = I2C_MSG_READ | I2C_MSG_STOP,
},
};
return i2c_transfer(data->i2c_master, msgs, 2, config->i2c_slave_addr);
}
static int bmc150_magn_reg_write(struct device *dev, uint8_t reg, uint8_t val)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
struct bmc150_magn_config *config =
(struct bmc150_magn_config *) dev->config->config_info;
uint8_t buf[2] = {reg, val};
return i2c_write(data->i2c_master, buf, 2, config->i2c_slave_addr);
}
static int bmc150_magn_update_bits(struct device *dev, uint8_t reg,
uint8_t mask, uint8_t val)
{
uint8_t old_val, new_val;
if (bmc150_magn_reg_read(dev, reg, &old_val) != 0) {
return -EIO;
}
new_val = (old_val & ~mask) | (val & mask);
if (new_val == old_val) {
return 0;
}
return bmc150_magn_reg_write(dev, reg, new_val);
}
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
static int bmc150_magn_set_drdy_polarity(struct device *dev, int state)
{
if (state) {
state = 1;
}
return bmc150_magn_update_bits(dev, BMC150_MAGN_REG_INT_DRDY,
BMC150_MAGN_MASK_DRDY_DR_POLARITY,
state << BMC150_MAGN_SHIFT_DRDY_DR_POLARITY);
}
#endif
static int bmc150_magn_set_power_mode(struct device *dev,
enum bmc150_magn_power_modes mode,
int state)
{
switch (mode) {
case BMC150_MAGN_POWER_MODE_SUSPEND:
if (bmc150_magn_update_bits(dev, BMC150_MAGN_REG_POWER,
BMC150_MAGN_MASK_POWER_CTL, !state)
!= 0) {
return -EIO;
}
sys_thread_busy_wait(5 * USEC_PER_MSEC);
return 0;
case BMC150_MAGN_POWER_MODE_SLEEP:
return bmc150_magn_update_bits(dev,
BMC150_MAGN_REG_OPMODE_ODR,
BMC150_MAGN_MASK_OPMODE,
BMC150_MAGN_MODE_SLEEP <<
BMC150_MAGN_SHIFT_OPMODE);
break;
case BMC150_MAGN_POWER_MODE_NORMAL:
return bmc150_magn_update_bits(dev,
BMC150_MAGN_REG_OPMODE_ODR,
BMC150_MAGN_MASK_OPMODE,
BMC150_MAGN_MODE_NORMAL <<
BMC150_MAGN_SHIFT_OPMODE);
break;
}
return -ENOTSUP;
}
static int bmc150_magn_set_odr(struct device *dev, uint8_t val)
{
uint8_t i;
for (i = 0; i < ARRAY_SIZE(bmc150_magn_samp_freq_table); ++i) {
if (bmc150_magn_samp_freq_table[i].freq == val) {
return bmc150_magn_update_bits(dev,
BMC150_MAGN_REG_OPMODE_ODR,
BMC150_MAGN_MASK_ODR,
bmc150_magn_samp_freq_table[i].
reg_val <<
BMC150_MAGN_SHIFT_ODR);
}
}
return -ENOTSUP;
}
#if defined(BMC150_MAGN_SET_ATTR)
static int bmc150_magn_read_rep_xy(struct device *dev)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
uint8_t reg_val;
if (bmc150_magn_reg_read(dev, BMC150_MAGN_REG_REP_XY, &reg_val) != 0) {
return -EIO;
}
data->rep_xy = BMC150_MAGN_REGVAL_TO_REPXY((int)(reg_val));
return 0;
}
static int bmc150_magn_read_rep_z(struct device *dev)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
uint8_t reg_val;
if (bmc150_magn_reg_read(dev, BMC150_MAGN_REG_REP_Z, &reg_val) != 0) {
return -EIO;
}
data->rep_z = BMC150_MAGN_REGVAL_TO_REPZ((int)(reg_val));
return 0;
}
static int bmc150_magn_compute_max_odr(struct device *dev, int rep_xy, int rep_z, int *max_odr)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
if (rep_xy == 0) {
if (data->rep_xy <= 0) {
if (bmc150_magn_read_rep_xy(dev) != 0) {
return -EIO;
}
}
rep_xy = data->rep_xy;
}
if (rep_z == 0) {
if (data->rep_z <= 0) {
if (bmc150_magn_read_rep_z(dev) != 0) {
return -EIO;
}
}
rep_z = data->rep_z;
}
*max_odr = 1000000 / (145 * rep_xy + 500 * rep_z + 980);
return 0;
}
#endif
#if defined(BMC150_MAGN_SET_ATTR_REP)
static int bmc150_magn_read_odr(struct device *dev)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
uint8_t i, odr_val, reg_val;
if (bmc150_magn_reg_read(dev, BMC150_MAGN_REG_OPMODE_ODR, &reg_val) != 0) {
return -EIO;
}
odr_val = (reg_val & BMC150_MAGN_MASK_ODR) >> BMC150_MAGN_SHIFT_ODR;
for (i = 0; i < ARRAY_SIZE(bmc150_magn_samp_freq_table); ++i) {
if (bmc150_magn_samp_freq_table[i].reg_val == odr_val) {
data->odr = bmc150_magn_samp_freq_table[i].freq;
return 0;
}
}
return -ENOTSUP;
}
#endif
#if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_XY)
static int bmc150_magn_write_rep_xy(struct device *dev, int val)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
if (bmc150_magn_update_bits(dev,
BMC150_MAGN_REG_REP_XY,
BMC150_MAGN_REG_REP_DATAMASK,
BMC150_MAGN_REPXY_TO_REGVAL(val)) != 0) {
return -EIO;
}
data->rep_xy = val;
return 0;
}
#endif
#if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_Z)
static int bmc150_magn_write_rep_z(struct device *dev, int val)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
if (bmc150_magn_update_bits(dev,
BMC150_MAGN_REG_REP_Z,
BMC150_MAGN_REG_REP_DATAMASK,
BMC150_MAGN_REPZ_TO_REGVAL(val)) != 0) {
return -EIO;
}
data->rep_z = val;
return 0;
}
#endif
/*
* Datasheet part 4.3.4, provided by Bosch here:
* https://github.com/BoschSensortec/BMM050_driver
*/
static int32_t bmc150_magn_compensate_xy(struct bmc150_magn_trim_regs *tregs, int16_t xy,
uint16_t rhall, bool is_x)
{
int8_t txy1, txy2;
int16_t val;
if (xy == BMC150_MAGN_XY_OVERFLOW_VAL) {
return INT32_MIN;
}
if (!rhall) {
rhall = tregs->xyz1;
}
if (is_x) {
txy1 = tregs->x1;
txy2 = tregs->x2;
} else {
txy1 = tregs->y1;
txy2 = tregs->y2;
}
val = ((int16_t)(((uint16_t)((((int32_t)tregs->xyz1) << 14) / rhall)) -
((uint16_t)0x4000)));
val = ((int16_t)((((int32_t)xy) * ((((((((int32_t)tregs->xy2) * ((((int32_t)val) *
((int32_t)val)) >> 7)) + (((int32_t)val) *
((int32_t)(((int16_t)tregs->xy1) << 7)))) >> 9) + ((int32_t)0x100000)) *
((int32_t)(((int16_t)txy2) + ((int16_t)0xA0)))) >> 12)) >> 13)) +
(((int16_t)txy1) << 3);
return (int32_t)val;
}
static int32_t bmc150_magn_compensate_z(struct bmc150_magn_trim_regs *tregs, int16_t z,
uint16_t rhall)
{
int32_t val;
if (z == BMC150_MAGN_Z_OVERFLOW_VAL) {
return INT32_MIN;
}
val = (((((int32_t)(z - tregs->z4)) << 15) - ((((int32_t)tregs->z3) *
((int32_t)(((int16_t)rhall) - ((int16_t)tregs->xyz1)))) >> 2)) /
(tregs->z2 + ((int16_t)(((((int32_t)tregs->z1) *
((((int16_t)rhall) << 1))) + (1 << 15)) >> 16))));
return val;
}
static int bmc150_magn_sample_fetch(struct device *dev)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
uint16_t values[BMC150_MAGN_AXIS_XYZR_MAX];
int16_t raw_x, raw_y, raw_z;
uint16_t rhall;
if (bmc150_magn_reg_bulk_read(dev, BMC150_MAGN_REG_X_L,
(uint8_t *)values, sizeof(values)) != 0) {
sensor_dbg("failed to read sample\n");
return -EIO;
}
raw_x = (int16_t)sys_le16_to_cpu(values[BMC150_MAGN_AXIS_X]) >> BMC150_MAGN_SHIFT_XY_L;
raw_y = (int16_t)sys_le16_to_cpu(values[BMC150_MAGN_AXIS_Y]) >> BMC150_MAGN_SHIFT_XY_L;
raw_z = (int16_t)sys_le16_to_cpu(values[BMC150_MAGN_AXIS_Z]) >> BMC150_MAGN_SHIFT_Z_L;
rhall = sys_le16_to_cpu(values[BMC150_MAGN_RHALL]) >> BMC150_MAGN_SHIFT_RHALL_L;
data->sample_x = bmc150_magn_compensate_xy(&data->tregs, raw_x, rhall, true);
data->sample_y = bmc150_magn_compensate_xy(&data->tregs, raw_y, rhall, false);
data->sample_z = bmc150_magn_compensate_z(&data->tregs, raw_z, rhall);
return 0;
}
static int bmc150_magn_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
val->type = SENSOR_TYPE_DOUBLE;
switch (chan) {
case SENSOR_CHAN_MAGN_X:
val->dval = (double)(data->sample_x) * (1.0/1600.0);
break;
case SENSOR_CHAN_MAGN_Y:
val->dval = (double)(data->sample_y) * (1.0/1600.0);
break;
case SENSOR_CHAN_MAGN_Z:
val->dval = (double)(data->sample_z) * (1.0/1600.0);
break;
default:
return -EINVAL;
}
return 0;
}
#if defined(BMC150_MAGN_SET_ATTR_REP)
static inline int bmc150_magn_attr_set_oversampling(struct device *dev,
enum sensor_channel chan,
const struct sensor_value *val)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
int max_odr;
switch (chan) {
#if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_XY)
case SENSOR_CHAN_MAGN_X:
case SENSOR_CHAN_MAGN_Y:
if (val->val1 < 1 || val->val1 > 511) {
return -EINVAL;
}
if (bmc150_magn_compute_max_odr(dev, val->val1, 0, &max_odr) != 0) {
return -EIO;
}
if (data->odr <= 0) {
if (bmc150_magn_read_odr(dev) != 0) {
return -EIO;
}
}
if (data->odr > max_odr) {
return -EINVAL;
}
if (bmc150_magn_write_rep_xy(dev, val->val1) != 0) {
return -EIO;
}
break;
#endif
#if defined(CONFIG_BMC150_MAGN_SAMPLING_REP_Z)
case SENSOR_CHAN_MAGN_Z:
if (val->val1 < 1 || val->val1 > 256) {
return -EINVAL;
}
if (bmc150_magn_compute_max_odr(dev, 0, val->val1, &max_odr) != 0) {
return -EIO;
}
if (data->odr <= 0) {
if (bmc150_magn_read_odr(dev) != 0) {
return -EIO;
}
}
if (data->odr > max_odr) {
return -EINVAL;
}
if (bmc150_magn_write_rep_z(dev, val->val1) != 0) {
return -EIO;
}
break;
#endif
default:
return -EINVAL;
}
}
#endif
#if defined(BMC150_MAGN_SET_ATTR)
static int bmc150_magn_attr_set(struct device *dev,
enum sensor_channel chan,
enum sensor_attribute attr,
const struct sensor_value *val)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
switch (attr) {
#if defined(CONFIG_BMC150_MAGN_SAMPLING_RATE_RUNTIME)
case SENSOR_ATTR_SAMPLING_FREQUENCY:
if (val->type != SENSOR_TYPE_INT) {
sensor_dbg("invalid parameter type for SENSOR_ATTR_SAMPLING_FREQUENCY\n");
return -ENOTSUP;
}
if (data->max_odr <= 0) {
if (bmc150_magn_compute_max_odr(dev, 0, 0, &data->max_odr) != 0) {
return -EIO;
}
}
if (data->max_odr < val->val1) {
sensor_dbg("sampling rate not supported with current oversampling factor\n");
return -ENOTSUP;
}
if (bmc150_magn_set_odr(dev, (uint8_t)(val->val1)) != 0) {
return -EIO;
}
break;
#endif
#if defined(BMC150_MAGN_SET_ATTR_REP)
case SENSOR_ATTR_OVERSAMPLING:
if (val->type != SENSOR_TYPE_INT) {
sensor_dbg("invalid parameter type for SENSOR_ATTR_OVERSAMPLING\n");
return -ENOTSUP;
}
bmc150_magn_attr_set_oversampling(dev, chan, val);
break;
#endif
default:
return -EINVAL;
}
return 0;
}
#endif
#if defined(CONFIG_BMC150_MAGN_TRIGGERS)
static int bmc150_magn_trigger_set(struct device *dev,
const struct sensor_trigger *trig,
sensor_trigger_handler_t handler)
{
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
struct bmc150_magn_data *data = (struct bmc150_magn_data *)dev->driver_data;
const struct bmc150_magn_config * const config = dev->config->config_info;
uint8_t state;
#endif
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
if (trig->type == SENSOR_TRIG_DATA_READY) {
gpio_pin_disable_callback(data->gpio_drdy, config->gpio_drdy_int_pin);
state = 0;
if (handler) {
state = 1;
}
data->handler_drdy = handler;
data->trigger_drdy = *trig;
if (!bmc150_magn_update_bits(dev, BMC150_MAGN_REG_INT_DRDY,
BMC150_MAGN_MASK_DRDY_EN,
state << BMC150_MAGN_SHIFT_DRDY_EN)
!= 0) {
sensor_dbg("failed to set DRDY interrupt\n");
return -EIO;
}
gpio_pin_enable_callback(data->gpio_drdy, config->gpio_drdy_int_pin);
}
#endif
return 0;
}
#endif
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
static void bmc150_magn_gpio_drdy_callback(struct device *dev, uint32_t pin)
{
gpio_pin_disable_callback(dev, pin);
nano_isr_sem_give(&bmc150_magn_data.sem);
}
static void bmc150_magn_fiber_main(int arg1, int gpio_pin)
{
struct device *dev = (struct device *) arg1;
struct bmc150_magn_data *data = (struct bmc150_magn_data *)dev->driver_data;
uint8_t reg_val;
while (1) {
nano_fiber_sem_take(&data->sem, TICKS_UNLIMITED);
while (bmc150_magn_reg_read(dev, BMC150_MAGN_REG_INT_STATUS, &reg_val) != 0) {
sensor_dbg("failed to clear data ready interrupt\n");
}
if (data->handler_drdy) {
data->handler_drdy(dev, &data->trigger_drdy);
}
gpio_pin_enable_callback(data->gpio_drdy, gpio_pin);
}
}
#endif
static struct sensor_driver_api bmc150_magn_api_funcs = {
#if defined(BMC150_MAGN_SET_ATTR)
.attr_set = bmc150_magn_attr_set,
#endif
.sample_fetch = bmc150_magn_sample_fetch,
.channel_get = bmc150_magn_channel_get,
#if defined(CONFIG_BMC150_MAGN_TRIGGERS)
.trigger_set = bmc150_magn_trigger_set,
#endif
};
static int bmc150_magn_init_chip(struct device *dev)
{
struct bmc150_magn_data *data = (struct bmc150_magn_data *) dev->driver_data;
uint8_t chip_id;
struct bmc150_magn_preset preset;
bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_NORMAL, 0);
bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_SUSPEND, 1);
if (bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_SUSPEND, 0) != 0) {
sensor_dbg("failed to bring up device from suspend mode\n");
return -EIO;
}
if (bmc150_magn_reg_read(dev, BMC150_MAGN_REG_CHIP_ID, &chip_id) != 0) {
sensor_dbg("failed reading chip id\n");
goto err_poweroff;
}
if (chip_id != BMC150_MAGN_CHIP_ID_VAL) {
sensor_dbg("invalid chip id 0x%x\n", chip_id);
goto err_poweroff;
}
sensor_dbg("chip id 0x%x\n", chip_id);
preset = bmc150_magn_presets_table[BMC150_MAGN_DEFAULT_PRESET];
if (bmc150_magn_set_odr(dev, preset.odr) != 0) {
sensor_dbg("failed to set ODR to %d\n",
preset.odr);
goto err_poweroff;
}
if (bmc150_magn_reg_write(dev, BMC150_MAGN_REG_REP_XY,
BMC150_MAGN_REPXY_TO_REGVAL(preset.rep_xy)) != 0) {
sensor_dbg("failed to set REP XY to %d\n",
preset.rep_xy);
goto err_poweroff;
}
if (bmc150_magn_reg_write(dev, BMC150_MAGN_REG_REP_Z,
BMC150_MAGN_REPZ_TO_REGVAL(preset.rep_z)) != 0) {
sensor_dbg("failed to set REP Z to %d\n",
preset.rep_z);
goto err_poweroff;
}
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
if (bmc150_magn_set_drdy_polarity(dev, 0) != 0) {
sensor_dbg("failed to set DR polarity\n");
goto err_poweroff;
}
if (bmc150_magn_update_bits(dev, BMC150_MAGN_REG_INT_DRDY,
BMC150_MAGN_MASK_DRDY_EN,
0 << BMC150_MAGN_SHIFT_DRDY_EN) != 0) {
sensor_dbg("failed to update data ready interrupt enabled bit\n");
goto err_poweroff;
}
#endif
if (bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_NORMAL, 1) != 0) {
sensor_dbg("failed to power on device\n");
goto err_poweroff;
}
if (bmc150_magn_reg_bulk_read(dev, BMC150_MAGN_REG_TRIM_START,
(uint8_t *)&data->tregs, sizeof(data->tregs))
!= 0) {
sensor_dbg("failed to read trim regs\n");
goto err_poweroff;
}
data->rep_xy = 0;
data->rep_z = 0;
data->odr = 0;
data->max_odr = 0;
data->sample_x = 0;
data->sample_y = 0;
data->sample_z = 0;
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
data->handler_drdy = NULL;
#endif
data->tregs.xyz1 = sys_le16_to_cpu(data->tregs.xyz1);
data->tregs.z1 = sys_le16_to_cpu(data->tregs.z1);
data->tregs.z2 = sys_le16_to_cpu(data->tregs.z2);
data->tregs.z3 = sys_le16_to_cpu(data->tregs.z3);
data->tregs.z4 = sys_le16_to_cpu(data->tregs.z4);
return 0;
err_poweroff:
bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_NORMAL, 0);
bmc150_magn_set_power_mode(dev, BMC150_MAGN_POWER_MODE_SUSPEND, 1);
return -EIO;
}
int bmc150_magn_init(struct device *dev)
{
const struct bmc150_magn_config * const config = dev->config->config_info;
struct bmc150_magn_data *data = dev->driver_data;
dev->driver_api = &bmc150_magn_api_funcs;
data->i2c_master = device_get_binding((char *)config->i2c_master_dev_name);
if (!data->i2c_master) {
sensor_dbg("i2c master not found: %s\n",
config->i2c_master_dev_name);
return -EINVAL;
}
if (bmc150_magn_init_chip(dev) != 0) {
sensor_dbg("failed to initialize chip\n");
return -EIO;
}
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
nano_sem_init(&data->sem);
task_fiber_start(data->bmc150_magn_fiber_stack, CONFIG_BMC150_MAGN_TRIGGER_FIBER_STACK,
bmc150_magn_fiber_main, (int) dev, config->gpio_drdy_int_pin, 10, 0);
data->gpio_drdy = device_get_binding(config->gpio_drdy_dev_name);
if (!data->gpio_drdy) {
sensor_dbg("gpio controller %s not found\n",
config->gpio_drdy_dev_name);
return -EINVAL;
}
gpio_pin_configure(data->gpio_drdy, config->gpio_drdy_int_pin,
GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE |
GPIO_INT_ACTIVE_LOW | GPIO_INT_DEBOUNCE);
if (gpio_set_callback(data->gpio_drdy, bmc150_magn_gpio_drdy_callback) != 0) {
sensor_dbg("failed to set gpio callback\n");
return -EIO;
}
#endif
return 0;
}
static struct bmc150_magn_config bmc150_magn_config = {
.i2c_master_dev_name = CONFIG_BMC150_MAGN_I2C_MASTER_DEV_NAME,
.i2c_slave_addr = BMC150_MAGN_I2C_ADDR,
#if defined(CONFIG_BMC150_MAGN_TRIGGER_DRDY)
.gpio_drdy_dev_name = CONFIG_BMC150_MAGN_GPIO_DRDY_DEV_NAME,
.gpio_drdy_int_pin = CONFIG_BMC150_MAGN_GPIO_DRDY_INT_PIN,
#endif
};
DEVICE_INIT(bmc150_magn, CONFIG_BMC150_MAGN_DEV_NAME, bmc150_magn_init, &bmc150_magn_data,
&bmc150_magn_config, NANOKERNEL, CONFIG_BMC150_MAGN_INIT_PRIORITY);