sensor: add driver for BMA280 accelerometer

Add device driver for the BMA280 I2C-based triaxial accelerometer
sensor, which supports reading data from the accel-x, accel-y, accel-z
and temperature channels. The driver also has support for data-ready
and any-motion triggers.

Datasheet:
	http://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BMA280-DS000-11_published.pdf

Origin: Original
Change-Id: Iff7246d7dd4a9358ec7a71e8ffbcfcccd49e393c
Signed-off-by: Bogdan Davidoaia <bogdan.m.davidoaia@intel.com>
Signed-off-by: Teodora Baluta <teodora.baluta@intel.com>
This commit is contained in:
Bogdan Davidoaia 2016-02-18 17:40:55 +02:00 committed by Gerrit Code Review
parent ace49af6b0
commit fe9c947fee
6 changed files with 854 additions and 0 deletions

View file

@ -44,6 +44,8 @@ config SENSOR_DEBUG
help
This option enables debug output for sensor drivers.
source "drivers/sensor/Kconfig.bma280"
source "drivers/sensor/Kconfig.mcp9808"
source "drivers/sensor/Kconfig.sx9500"

View file

@ -0,0 +1,201 @@
# Kconfig.bma280 - BMA280 Three Axis Accelerometer configuration options
#
# 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.
#
menuconfig BMA280
bool
prompt "BMA280 Three Axis Accelerometer"
depends on SENSOR && I2C
default n
help
Enable driver for BMA280 I2C-based triaxial accelerometer sensor.
config BMA280_NAME
string
prompt "Driver name"
default "BMA280"
depends on BMA280
help
Device name with which the BMA280 sensor is identified.
config BMA280_INIT_PRIORITY
int
prompt "Init priority"
depends on BMA280
default 70
help
Device driver initialization priority.
choice
prompt "I2C address"
depends on BMA280
default BMA280_I2C_ADDR_0x18
help
I2C address of the BMA280 sensor.
config BMA280_I2C_ADDR_0x18
bool
prompt "0x18"
help
Choose this option if the SDO pin is pulled to GND.
config BMA280_I2C_ADDR_0x19
bool
prompt "0x19"
help
Choose this option if the SDO pin is pulled to VDDIO.
endchoice
config BMA280_I2C_MASTER_DEV_NAME
string
prompt "I2C master where BMA280 is connected"
depends on BMA280
default "I2C0"
help
Specify the device name of the I2C master device to which BMA280 is
connected.
choice
prompt "Trigger mode"
depends on BMA280
default BMA280_TRIGGER_GLOBAL_FIBER
help
Specify the type of triggering to be used by the driver.
config BMA280_TRIGGER_NONE
bool
prompt "No trigger"
config BMA280_TRIGGER_GLOBAL_FIBER
bool
prompt "Use global fiber"
depends on GPIO
select BMA280_TRIGGER
select SENSOR_DELAYED_WORK
config BMA280_TRIGGER_OWN_FIBER
bool
prompt "Use own fiber"
depends on GPIO
select BMA280_TRIGGER
endchoice
config BMA280_TRIGGER
bool
depends on BMA280
config BMA280_GPIO_DEV_NAME
string
prompt "GPIO device"
default "GPIO_0"
depends on BMA280 && BMA280_TRIGGER
help
The device name of the GPIO device to which the BMA280 interrupt pins
are connected.
config BMA280_GPIO_PIN_NUM
int
prompt "Interrupt GPIO pin number"
default 0
depends on BMA280 && BMA280_TRIGGER
help
The number of the GPIO on which the interrupt signal from the BMA280
chip will be received.
config BMA280_FIBER_PRIORITY
int
prompt "Fiber priority"
depends on BMA280 && BMA280_TRIGGER_OWN_FIBER
default 10
help
Priority of fiber used by the driver to handle interrupts.
config BMA280_FIBER_STACK_SIZE
int
prompt "Fiber stack size"
depends on BMA280 && BMA280_TRIGGER_OWN_FIBER
default 1024
help
Stack size of fiber used by the driver to handle interrupts.
choice
prompt "Acceleration measurement range"
depends on BMA280
default BMA280_PMU_RANGE_2G
help
Measurement range for acceleration values.
config BMA280_PMU_RANGE_2G
bool
prompt "+/-2g"
config BMA280_PMU_RANGE_4G
bool
prompt "+/-4g"
config BMA280_PMU_RANGE_8G
bool
prompt "+/-8g"
config BMA280_PMU_RANGE_16G
bool
prompt "+/-16g"
endchoice
choice
prompt "Acceleration data filter bandwidth"
depends on BMA280
default BMA280_PMU_BW_7
help
Bandwidth of filtered acceleration data.
config BMA280_PMU_BW_1
bool
prompt "7.81Hz"
config BMA280_PMU_BW_2
bool
prompt "15.63HZ"
config BMA280_PMU_BW_3
bool
prompt "31.25Hz"
config BMA280_PMU_BW_4
bool
prompt "62.5Hz"
config BMA280_PMU_BW_5
bool
prompt "125Hz"
config BMA280_PMU_BW_6
bool
prompt "250HZ"
config BMA280_PMU_BW_7
bool
prompt "500Hz"
config BMA280_PMU_BW_8
bool
prompt "unfiltered"
endchoice

View file

@ -2,6 +2,8 @@ ccflags-y +=-I$(srctree)/drivers
obj-$(CONFIG_SENSOR_DELAYED_WORK) += sensor.o
obj-$(CONFIG_BMA280) += sensor_bma280.o
obj-$(CONFIG_BMA280_TRIGGER) += sensor_bma280_trigger.o
obj-$(CONFIG_MCP9808) += sensor_mcp9808.o
obj-$(CONFIG_MCP9808_TRIGGER) += sensor_mcp9808_trigger.o
obj-$(CONFIG_SX9500) += sensor_sx9500.o

View file

@ -0,0 +1,217 @@
/*
* 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.
*/
#include <i2c.h>
#include <init.h>
#include <sensor.h>
#include "sensor_bma280.h"
static int bma280_reg_burst_read(struct bma280_data *drv_data,
uint8_t reg, uint8_t *buff,
int buff_len)
{
struct i2c_msg msgs[2] = {
{
.buf = &reg,
.len = 1,
.flags = I2C_MSG_WRITE | I2C_MSG_RESTART,
},
{
.buf = buff,
.len = buff_len,
.flags = I2C_MSG_READ | I2C_MSG_STOP,
},
};
return i2c_transfer(drv_data->i2c, msgs, 2, BMA280_I2C_ADDRESS);
}
int bma280_reg_read(struct bma280_data *drv_data,
uint8_t reg, uint8_t *val)
{
return bma280_reg_burst_read(drv_data, reg, val, 1);
}
int bma280_reg_write(struct bma280_data *drv_data,
uint8_t reg, uint8_t val)
{
uint8_t tx_buf[2] = {reg, val};
return i2c_write(drv_data->i2c, tx_buf, sizeof(tx_buf),
BMA280_I2C_ADDRESS);
}
int bma280_reg_update(struct bma280_data *drv_data,
uint8_t reg, uint8_t mask, uint8_t val)
{
uint8_t old_val = 0;
uint8_t new_val;
if (bma280_reg_read(drv_data, reg, &old_val) != DEV_OK) {
return DEV_FAIL;
}
new_val = old_val & ~mask;
new_val |= val & mask;
return bma280_reg_write(drv_data, reg, new_val);
}
static int bma280_sample_fetch(struct device *dev)
{
struct bma280_data *drv_data = dev->driver_data;
uint8_t buf[6];
uint8_t lsb;
int rc;
/*
* since all accel data register addresses are consecutive,
* a burst read can be used to read all the samples
*/
rc = bma280_reg_burst_read(drv_data, BMA280_REG_ACCEL_X_LSB, buf, 6);
if (rc != DEV_OK) {
DBG("Could not read accel axis data\n");
return DEV_FAIL;
}
lsb = (buf[0] & BMA280_ACCEL_LSB_MASK) >> BMA280_ACCEL_LSB_SHIFT;
drv_data->x_sample = (((int8_t)buf[1]) << BMA280_ACCEL_LSB_BITS) + lsb;
lsb = (buf[2] & BMA280_ACCEL_LSB_MASK) >> BMA280_ACCEL_LSB_SHIFT;
drv_data->y_sample = (((int8_t)buf[3]) << BMA280_ACCEL_LSB_BITS) + lsb;
lsb = (buf[4] & BMA280_ACCEL_LSB_MASK) >> BMA280_ACCEL_LSB_SHIFT;
drv_data->z_sample = (((int8_t)buf[5]) << BMA280_ACCEL_LSB_BITS) + lsb;
rc = bma280_reg_read(drv_data, BMA280_REG_TEMP, (uint8_t *)&drv_data->temp_sample);
if (rc != DEV_OK) {
DBG("Could not read temperature data\n");
return DEV_FAIL;
}
return DEV_OK;
}
static int bma280_channel_get(struct device *dev,
enum sensor_channel chan,
struct sensor_value *val)
{
struct bma280_data *drv_data = dev->driver_data;
int64_t raw_val;
/*
* See datasheet "Sensor data" section for
* more details on processing sample data.
*/
if (chan == SENSOR_CHAN_ACCEL_X) {
raw_val = drv_data->x_sample;
} else if (chan == SENSOR_CHAN_ACCEL_Y) {
raw_val = drv_data->y_sample;
} else if (chan == SENSOR_CHAN_ACCEL_Z) {
raw_val = drv_data->z_sample;
} else if (chan == SENSOR_CHAN_TEMP) {
/* temperature_val = 23 + sample / 2 */
val->type = SENSOR_TYPE_INT_PLUS_MICRO;
val->val1 = (drv_data->temp_sample >> 1) + 23;
val->val2 = 500000 * (drv_data->temp_sample & 1);
return DEV_OK;
} else {
return DEV_INVALID_OP;
}
/* accel_val = sample * BMA280_ACCEL_SCALE / 1000 */
val->type = SENSOR_TYPE_INT_PLUS_MICRO;
raw_val = raw_val * BMA280_ACCEL_SCALE;
val->val1 = raw_val / 1000000000L;
val->val2 = (raw_val % 1000000000L) / 1000;
/* normalize val to make sure val->val2 is positive */
if (val->val2 < 0) {
val->val1 -= 1;
val->val2 += 1000000;
}
return DEV_OK;
}
static struct sensor_driver_api bma280_driver_api = {
#if CONFIG_BMA280_TRIGGER
.attr_set = bma280_attr_set,
.trigger_set = bma280_trigger_set,
#endif
.sample_fetch = bma280_sample_fetch,
.channel_get = bma280_channel_get,
};
int bma280_init(struct device *dev)
{
struct bma280_data *drv_data = dev->driver_data;
uint8_t id = 0;
int rc;
dev->driver_api = &bma280_driver_api;
drv_data->i2c = device_get_binding(CONFIG_BMA280_I2C_MASTER_DEV_NAME);
if (drv_data->i2c == NULL) {
DBG("Could not get pointer to %s device\n",
CONFIG_BMA280_I2C_MASTER_DEV_NAME);
return DEV_INVALID_CONF;
}
/* read device ID */
rc = bma280_reg_read(drv_data, BMA280_REG_CHIP_ID, &id);
if (rc != DEV_OK) {
DBG("Could not read chip id\n");
return DEV_FAIL;
}
if (id != BMA280_CHIP_ID) {
DBG("Unexpected chip id (%x)\n", id);
return DEV_FAIL;
}
/* set the data filter bandwidth */
rc = bma280_reg_write(drv_data, BMA280_REG_PMU_BW,
BMA280_PMU_BW);
if (rc != DEV_OK) {
DBG("Could not set data filter bandwidth\n");
return DEV_FAIL;
}
/* set g-range */
rc = bma280_reg_write(drv_data, BMA280_REG_PMU_RANGE,
BMA280_PMU_RANGE);
if (rc != DEV_OK) {
DBG("Could not set data g-range\n");
return DEV_FAIL;
}
#ifdef CONFIG_BMA280_TRIGGER
rc = bma280_init_interrupt(dev);
if (rc != DEV_OK) {
DBG("Could not initialize interrupts\n");
return DEV_FAIL;
}
#endif
return DEV_OK;
}
struct bma280_data bma280_driver;
DEVICE_INIT(bma280, CONFIG_BMA280_NAME, bma280_init, &bma280_driver,
NULL, SECONDARY, CONFIG_BMA280_INIT_PRIORITY);

View file

@ -0,0 +1,177 @@
/*
* 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.
*/
#ifndef __SENSOR_BMA280_H__
#define __SENSOR_BMA280_H__
#include <device.h>
#include <misc/util.h>
#include <stdint.h>
#ifndef CONFIG_SENSOR_DEBUG
#define DBG(...) { ; }
#else
#include <misc/printk.h>
#define DBG printk
#endif /* CONFIG_SENSOR_DEBUG */
#if CONFIG_BMA280_I2C_ADDR_0x18
#define BMA280_I2C_ADDRESS 0x18
#elif CONFIG_BMA280_I2C_ADDR_0x19
#define BMA280_I2C_ADDRESS 0x19
#endif
#define BMA280_REG_CHIP_ID 0x00
#define BMA280_CHIP_ID 0xFB
#define BMA280_REG_PMU_BW 0x10
#if CONFIG_BMA280_PMU_BW_1
#define BMA280_PMU_BW 0x08
#elif CONFIG_BMA280_PMU_BW_2
#define BMA280_PMU_BW 0x09
#elif CONFIG_BMA280_PMU_BW_3
#define BMA280_PMU_BW 0x0A
#elif CONFIG_BMA280_PMU_BW_4
#define BMA280_PMU_BW 0x0B
#elif CONFIG_BMA280_PMU_BW_5
#define BMA280_PMU_BW 0x0C
#elif CONFIG_BMA280_PMU_BW_6
#define BMA280_PMU_BW 0x0D
#elif CONFIG_BMA280_PMU_BW_7
#define BMA280_PMU_BW 0x0E
#elif CONFIG_BMA280_PMU_BW_8
#define BMA280_PMU_BW 0x0F
#endif
/*
* accel and slope scale measured in nano-m/s^2 instead
* of m/s^2 to avoid using struct sensor_value for it
*/
#define GRAVITY_CONST 9807
#define BMA280_REG_PMU_RANGE 0x0F
#if CONFIG_BMA280_PMU_RANGE_2G
#define BMA280_PMU_RANGE 0x03
#define BMA280_ACCEL_SCALE (244 * GRAVITY_CONST)
#define BMA280_SLOPE_TH_SCALE 3910
#elif CONFIG_BMA280_PMU_RANGE_4G
#define BMA280_PMU_RANGE 0x05
#define BMA280_ACCEL_SCALE (488 * GRAVITY_CONST)
#define BMA280_SLOPE_TH_SCALE 7810
#elif CONFIG_BMA280_PMU_RANGE_8G
#define BMA280_PMU_RANGE 0x08
#define BMA280_ACCEL_SCALE (977 * GRAVITY_CONST)
#define BMA280_SLOPE_TH_SCALE 15630
#elif CONFIG_BMA280_PMU_RANGE_16G
#define BMA280_PMU_RANGE 0x0C
#define BMA280_ACCEL_SCALE (1953 * GRAVITY_CONST)
#define BMA280_SLOPE_TH_SCALE 31250
#endif
#define BMA280_REG_TEMP 0x08
#define BMA280_REG_INT_STATUS_0 0x09
#define BMA280_BIT_SLOPE_INT_STATUS BIT(2)
#define BMA280_REG_INT_STATUS_1 0x0A
#define BMA280_BIT_DATA_INT_STATUS BIT(7)
#define BMA280_REG_INT_EN_0 0x16
#define BMA280_BIT_SLOPE_EN_X BIT(0)
#define BMA280_BIT_SLOPE_EN_Y BIT(1)
#define BMA280_BIT_SLOPE_EN_Z BIT(2)
#define BMA280_SLOPE_EN_XYZ (BMA280_BIT_SLOPE_EN_X | \
BMA280_BIT_SLOPE_EN_Y | BMA280_BIT_SLOPE_EN_X)
#define BMA280_REG_INT_EN_1 0x17
#define BMA280_BIT_DATA_EN BIT(4)
#define BMA280_REG_INT_MAP_0 0x19
#define BMA280_INT_MAP_0_BIT_SLOPE BIT(2)
#define BMA280_REG_INT_MAP_1 0x1A
#define BMA280_INT_MAP_1_BIT_DATA BIT(0)
#define BMA280_REG_INT_RST_LATCH 0x21
#define BMA280_INT_MODE_LATCH 0x0F
#define BMA280_BIT_INT_LATCH_RESET BIT(7)
#define BMA280_REG_INT_5 0x27
#define BMA280_SLOPE_DUR_SHIFT 0
#define BMA280_SLOPE_DUR_MASK (3 << BMA280_SLOPE_DUR_SHIFT)
#define BMA280_REG_SLOPE_TH 0x28
#define BMA280_REG_ACCEL_X_LSB 0x2
#define BMA280_REG_ACCEL_Y_LSB 0x4
#define BMA280_REG_ACCEL_Z_LSB 0x6
#define BMA280_ACCEL_LSB_BITS 6
#define BMA280_ACCEL_LSB_SHIFT 2
#define BMA280_ACCEL_LSB_MASK (0x3F << BMA280_ACCEL_LSB_SHIFT)
#define BMA280_REG_ACCEL_X_MSB 0x3
#define BMA280_REG_ACCEL_Y_MSB 0x5
#define BMA280_REG_ACCEL_Z_MSB 0x7
#define BMA280_FIBER_PRIORITY 10
#define BMA280_FIBER_STACKSIZE_UNIT 1024
struct bma280_data {
struct device *i2c;
int16_t x_sample;
int16_t y_sample;
int16_t z_sample;
int8_t temp_sample;
#ifdef CONFIG_BMA280_TRIGGER
struct device *gpio;
struct sensor_trigger data_ready_trigger;
sensor_trigger_handler_t data_ready_handler;
struct sensor_trigger any_motion_trigger;
sensor_trigger_handler_t any_motion_handler;
#if defined(CONFIG_BMA280_TRIGGER_OWN_FIBER)
char __stack fiber_stack[CONFIG_BMA280_FIBER_STACK_SIZE];
struct nano_sem gpio_sem;
#elif defined(CONFIG_BMA280_TRIGGER_GLOBAL_FIBER)
struct sensor_work work;
#endif
#endif /* CONFIG_BMA280_TRIGGER */
};
#ifdef CONFIG_BMA280_TRIGGER
int bma280_reg_write(struct bma280_data *drv_data,
uint8_t reg, uint8_t val);
int bma280_reg_read(struct bma280_data *drv_data,
uint8_t reg, uint8_t *val);
int bma280_reg_update(struct bma280_data *drv_data,
uint8_t reg, uint8_t mask, uint8_t val);
int bma280_trigger_set(struct device *dev,
const struct sensor_trigger *trig,
sensor_trigger_handler_t handler);
int bma280_attr_set(struct device *dev,
enum sensor_channel chan,
enum sensor_attribute attr,
const struct sensor_value *val);
int bma280_init_interrupt(struct device *dev);
#endif
#endif /* __SENSOR_BMA280_H__ */

View file

@ -0,0 +1,255 @@
/*
* 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.
*/
#include <device.h>
#include <gpio.h>
#include <misc/util.h>
#include <nanokernel.h>
#include <sensor.h>
#include "sensor_bma280.h"
extern struct bma280_data bma280_driver;
int bma280_attr_set(struct device *dev,
enum sensor_channel chan,
enum sensor_attribute attr,
const struct sensor_value *val)
{
struct bma280_data *drv_data = dev->driver_data;
uint64_t slope_th;
int rc;
if (chan != SENSOR_CHAN_ACCEL_ANY) {
return DEV_INVALID_OP;
}
if (attr == SENSOR_ATTR_SLOPE_TH) {
slope_th = (uint64_t)val->val1 * 1000 / BMA280_SLOPE_TH_SCALE;
rc = bma280_reg_write(drv_data, BMA280_REG_SLOPE_TH,
(uint8_t)slope_th);
if (rc != DEV_OK) {
DBG("Could not set slope threshold\n");
return DEV_FAIL;
}
} else if (attr == SENSOR_ATTR_SLOPE_DUR) {
rc = bma280_reg_update(drv_data, BMA280_REG_INT_5,
BMA280_SLOPE_DUR_MASK,
val->val1 << BMA280_SLOPE_DUR_SHIFT);
if (rc != DEV_OK) {
DBG("Could not set slope duration\n");
return DEV_FAIL;
}
} else {
return DEV_INVALID_OP;
}
return DEV_OK;
}
static void bma280_gpio_callback(struct device *dev, uint32_t pin)
{
gpio_pin_disable_callback(dev, pin);
#if defined(CONFIG_BMA280_TRIGGER_OWN_FIBER)
nano_sem_give(&bma280_driver.gpio_sem);
#elif defined(CONFIG_BMA280_TRIGGER_GLOBAL_FIBER)
nano_isr_fifo_put(sensor_get_work_fifo(), &bma280_driver.work);
#endif
}
static void bma280_fiber_cb(void *arg)
{
struct device *dev = arg;
struct bma280_data *drv_data = dev->driver_data;
uint8_t status = 0;
/* check for data ready */
bma280_reg_read(drv_data, BMA280_REG_INT_STATUS_1, &status);
if (status & BMA280_BIT_DATA_INT_STATUS &&
drv_data->data_ready_handler != NULL) {
drv_data->data_ready_handler(dev, &drv_data->data_ready_trigger);
}
/* check for any motion */
bma280_reg_read(drv_data, BMA280_REG_INT_STATUS_0, &status);
if (status & BMA280_BIT_SLOPE_INT_STATUS &&
drv_data->any_motion_handler != NULL) {
drv_data->any_motion_handler(dev, &drv_data->data_ready_trigger);
/* clear latched interrupt */
bma280_reg_update(drv_data, BMA280_REG_INT_RST_LATCH,
BMA280_BIT_INT_LATCH_RESET,
BMA280_BIT_INT_LATCH_RESET);
}
gpio_pin_enable_callback(drv_data->gpio, CONFIG_BMA280_GPIO_PIN_NUM);
}
#ifdef CONFIG_BMA280_TRIGGER_OWN_FIBER
static void bma280_fiber(int dev_ptr, int unused)
{
struct device *dev = INT_TO_POINTER(dev_ptr);
struct bma280_data *drv_data = dev->driver_data;
ARG_UNUSED(unused);
while (1) {
nano_fiber_sem_take(&drv_data->gpio_sem, TICKS_UNLIMITED);
bma280_fiber_cb(dev);
}
}
#endif
int bma280_trigger_set(struct device *dev,
const struct sensor_trigger *trig,
sensor_trigger_handler_t handler)
{
struct bma280_data *drv_data = dev->driver_data;
int rc;
if (trig->type == SENSOR_TRIG_DATA_READY) {
/* disable data ready interrupt while changing trigger params */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_EN_1,
BMA280_BIT_DATA_EN, 0);
if (rc != DEV_OK) {
DBG("Could not disable data ready interrupt\n");
return DEV_FAIL;
}
drv_data->data_ready_handler = handler;
if (handler == NULL) {
return DEV_OK;
}
drv_data->data_ready_trigger = *trig;
/* enable data ready interrupt */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_EN_1,
BMA280_BIT_DATA_EN, BMA280_BIT_DATA_EN);
if (rc != DEV_OK) {
DBG("Could not enable data ready interrupt\n");
return DEV_FAIL;
}
} else if (trig->type == SENSOR_TRIG_DELTA) {
/* disable any-motion interrupt while changing trigger params */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_EN_0,
BMA280_SLOPE_EN_XYZ, 0);
if (rc != DEV_OK) {
DBG("Could not disable data ready interrupt\n");
return DEV_FAIL;
}
drv_data->any_motion_handler = handler;
if (handler == NULL) {
return DEV_OK;
}
drv_data->any_motion_trigger = *trig;
/* enable any-motion interrupt */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_EN_0,
BMA280_SLOPE_EN_XYZ, BMA280_SLOPE_EN_XYZ);
if (rc != DEV_OK) {
DBG("Could not enable data ready interrupt\n");
return DEV_FAIL;
}
} else {
return DEV_INVALID_OP;
}
return DEV_OK;
}
int bma280_init_interrupt(struct device *dev)
{
struct bma280_data *drv_data = dev->driver_data;
int rc;
/* set latched interrupts */
rc = bma280_reg_write(drv_data, BMA280_REG_INT_RST_LATCH,
BMA280_BIT_INT_LATCH_RESET |
BMA280_INT_MODE_LATCH);
if (rc != 0) {
DBG("Could not set latched interrupts\n");
return DEV_FAIL;
}
/* setup data ready gpio interrupt */
drv_data->gpio = device_get_binding(CONFIG_BMA280_GPIO_DEV_NAME);
if (drv_data->gpio == NULL) {
DBG("Cannot get pointer to %s device\n",
CONFIG_BMA280_GPIO_DEV_NAME);
return DEV_INVALID_CONF;
}
gpio_pin_configure(drv_data->gpio, CONFIG_BMA280_GPIO_PIN_NUM,
GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL |
GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE);
rc = gpio_set_callback(drv_data->gpio, bma280_gpio_callback);
if (rc != DEV_OK) {
DBG("Could not set gpio callback\n");
return DEV_FAIL;
}
/* map data ready interrupt to INT1 */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_MAP_1,
BMA280_INT_MAP_1_BIT_DATA,
BMA280_INT_MAP_1_BIT_DATA);
if (rc != DEV_OK) {
DBG("Could not map data ready interrupt pin\n");
return DEV_FAIL;
}
/* map any-motion interrupt to INT1 */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_MAP_0,
BMA280_INT_MAP_0_BIT_SLOPE,
BMA280_INT_MAP_0_BIT_SLOPE);
if (rc != DEV_OK) {
DBG("Could not map any-motion interrupt pin\n");
return DEV_FAIL;
}
/* disable data ready interrupt */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_EN_1,
BMA280_BIT_DATA_EN, 0);
if (rc != DEV_OK) {
DBG("Could not disable data ready interrupt\n");
return DEV_FAIL;
}
/* disable any-motion interrupt */
rc = bma280_reg_update(drv_data, BMA280_REG_INT_EN_0,
BMA280_SLOPE_EN_XYZ, 0);
if (rc != DEV_OK) {
DBG("Could not disable data ready interrupt\n");
return DEV_FAIL;
}
#if defined(CONFIG_BMA280_TRIGGER_OWN_FIBER)
nano_sem_init(&drv_data->gpio_sem);
fiber_start(drv_data->fiber_stack, CONFIG_BMA280_FIBER_STACK_SIZE,
(nano_fiber_entry_t)bma280_fiber, POINTER_TO_INT(dev),
0, CONFIG_BMA280_FIBER_PRIORITY, 0);
#elif defined(CONFIG_BMA280_TRIGGER_GLOBAL_FIBER)
drv_data->work.handler = bma280_fiber_cb;
drv_data->work.arg = dev;
#endif
gpio_pin_enable_callback(drv_data->gpio, CONFIG_BMA280_GPIO_PIN_NUM);
return DEV_OK;
}