You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by GitBox <gi...@apache.org> on 2017/11/20 21:03:32 UTC

[GitHub] vrahane closed pull request #663: BMA253 Fixes, adding notification API and interrupt handler API

vrahane closed pull request #663: BMA253 Fixes, adding notification API and interrupt handler API
URL: https://github.com/apache/mynewt-core/pull/663
 
 
   

This is a PR merged from a forked repository.
As GitHub hides the original diff on merge, it is displayed below for
the sake of provenance:

As this is a foreign pull request (from a fork), the diff is supplied
below (as it won't show otherwise due to GitHub magic):

diff --git a/apps/sensors_test/src/main.c b/apps/sensors_test/src/main.c
index 35ebb4c85..423841958 100755
--- a/apps/sensors_test/src/main.c
+++ b/apps/sensors_test/src/main.c
@@ -46,6 +46,9 @@
 #if MYNEWT_VAL(TSL2561_CLI)
 #include <tsl2561/tsl2561.h>
 #endif
+#if MYNEWT_VAL(BMA253_CLI)
+#include <bma253/bma253.h>
+#endif
 #if MYNEWT_VAL(BME280_CLI)
 #include <bme280/bme280.h>
 #endif
@@ -416,6 +419,10 @@ sensors_dev_shell_init(void)
     bno055_shell_init();
 #endif
 
+#if MYNEWT_VAL(BMA253_CLI)
+    bma253_shell_init();
+#endif
+
 #if MYNEWT_VAL(BME280_CLI)
     bme280_shell_init();
 #endif
diff --git a/hw/drivers/sensors/bma253/include/bma253/bma253.h b/hw/drivers/sensors/bma253/include/bma253/bma253.h
index f90e2be81..f3f56e3bf 100644
--- a/hw/drivers/sensors/bma253/include/bma253/bma253.h
+++ b/hw/drivers/sensors/bma253/include/bma253/bma253.h
@@ -24,143 +24,220 @@
 #include "os/os_dev.h"
 #include "sensor/sensor.h"
 #include "sensor/accel.h"
+#include "sensor/temperature.h"
 
-enum bma253_g_range {
-	BMA253_G_RANGE_2  = 0,
-	BMA253_G_RANGE_4  = 1,
-	BMA253_G_RANGE_8  = 2,
-	BMA253_G_RANGE_16 = 3,
-};
+#ifdef __cplusplus
+#extern "C" {
+#endif
 
-enum bma253_filter_bandwidth {
-	BMA253_FILTER_BANDWIDTH_7_81_HZ  = 0,
-	BMA253_FILTER_BANDWIDTH_15_63_HZ = 1,
-	BMA253_FILTER_BANDWIDTH_31_25_HZ = 2,
-	BMA253_FILTER_BANDWIDTH_62_5_HZ  = 3,
-	BMA253_FILTER_BANDWIDTH_125_HZ   = 4,
-	BMA253_FILTER_BANDWIDTH_250_HZ   = 5,
-	BMA253_FILTER_BANDWIDTH_500_HZ   = 6,
-	BMA253_FILTER_BANDWIDTH_1000_HZ  = 7,
-};
+/* XXX use some better defaults. For now it is min */
+#define BMA253_LOW_G_DELAY_MS_DEFAULT       2
+#define BMA253_HIGH_G_DELAY_MS_DEFAULT      2
 
-enum bma253_int_pin_output {
-	BMA253_INT_PIN_OUTPUT_PUSH_PULL  = 0,
-	BMA253_INT_PIN_OUTPUT_OPEN_DRAIN = 1,
+/* Range of acceleration measurements */
+enum bma253_g_range {
+    BMA253_G_RANGE_2  = 0,
+    BMA253_G_RANGE_4  = 1,
+    BMA253_G_RANGE_8  = 2,
+    BMA253_G_RANGE_16 = 3,
 };
 
-enum bma253_int_pin_active {
-	BMA253_INT_PIN_ACTIVE_LOW  = 0,
-	BMA253_INT_PIN_ACTIVE_HIGH = 1,
+/* How often acceleration measurements are taken */
+enum bma253_filter_bandwidth {
+    BMA253_FILTER_BANDWIDTH_7_81_HZ  = 0,
+    BMA253_FILTER_BANDWIDTH_15_63_HZ = 1,
+    BMA253_FILTER_BANDWIDTH_31_25_HZ = 2,
+    BMA253_FILTER_BANDWIDTH_62_5_HZ  = 3,
+    BMA253_FILTER_BANDWIDTH_125_HZ   = 4,
+    BMA253_FILTER_BANDWIDTH_250_HZ   = 5,
+    BMA253_FILTER_BANDWIDTH_500_HZ   = 6,
+    BMA253_FILTER_BANDWIDTH_1000_HZ  = 7,
 };
 
+/* Quiet time after a double/single tap */
 enum bma253_tap_quiet {
-	BMA253_TAP_QUIET_20_MS = 0,
-	BMA253_TAP_QUIET_30_MS = 1,
+    BMA253_TAP_QUIET_20_MS = 0,
+    BMA253_TAP_QUIET_30_MS = 1,
 };
 
+/* Settling time after a double/single tap */
 enum bma253_tap_shock {
-	BMA253_TAP_SHOCK_50_MS = 0,
-	BMA253_TAP_SHOCK_75_MS = 1,
+    BMA253_TAP_SHOCK_50_MS = 0,
+    BMA253_TAP_SHOCK_75_MS = 1,
 };
 
+/* How long to wait for the next tap in a double tap scenario */
 enum bma253_d_tap_window {
-	BMA253_D_TAP_WINDOW_50_MS  = 0,
-	BMA253_D_TAP_WINDOW_100_MS = 1,
-	BMA253_D_TAP_WINDOW_150_MS = 2,
-	BMA253_D_TAP_WINDOW_200_MS = 3,
-	BMA253_D_TAP_WINDOW_250_MS = 4,
-	BMA253_D_TAP_WINDOW_375_MS = 5,
-	BMA253_D_TAP_WINDOW_500_MS = 6,
-	BMA253_D_TAP_WINDOW_700_MS = 7,
+    BMA253_D_TAP_WINDOW_50_MS  = 0,
+    BMA253_D_TAP_WINDOW_100_MS = 1,
+    BMA253_D_TAP_WINDOW_150_MS = 2,
+    BMA253_D_TAP_WINDOW_200_MS = 3,
+    BMA253_D_TAP_WINDOW_250_MS = 4,
+    BMA253_D_TAP_WINDOW_375_MS = 5,
+    BMA253_D_TAP_WINDOW_500_MS = 6,
+    BMA253_D_TAP_WINDOW_700_MS = 7,
 };
 
+/* How many samples to use after a wake up from a low power mode to determine
+ * whether a tap occurred */
 enum bma253_tap_wake_samples {
-	BMA253_TAP_WAKE_SAMPLES_2  = 0,
-	BMA253_TAP_WAKE_SAMPLES_4  = 1,
-	BMA253_TAP_WAKE_SAMPLES_8  = 2,
-	BMA253_TAP_WAKE_SAMPLES_16 = 3,
+    BMA253_TAP_WAKE_SAMPLES_2  = 0,
+    BMA253_TAP_WAKE_SAMPLES_4  = 1,
+    BMA253_TAP_WAKE_SAMPLES_8  = 2,
+    BMA253_TAP_WAKE_SAMPLES_16 = 3,
 };
 
-enum bma253_i2c_watchdog {
-	BMA253_I2C_WATCHDOG_DISABLED = 0,
-	BMA253_I2C_WATCHDOG_1_MS     = 1,
-	BMA253_I2C_WATCHDOG_50_MS    = 2,
+/* Block generation of orientation events based on given criteria */
+enum bma253_orient_blocking {
+    BMA253_ORIENT_BLOCKING_NONE                       = 0,
+    BMA253_ORIENT_BLOCKING_ACCEL_ONLY                 = 1,
+    BMA253_ORIENT_BLOCKING_ACCEL_AND_SLOPE            = 2,
+    BMA253_ORIENT_BLOCKING_ACCEL_AND_SLOPE_AND_STABLE = 3,
 };
 
+/* Orientation mode configuration, used to determine thresholds for
+ * transitions between different orientations */
+enum bma253_orient_mode {
+    BMA253_ORIENT_MODE_SYMMETRICAL       = 0,
+    BMA253_ORIENT_MODE_HIGH_ASYMMETRICAL = 1,
+    BMA253_ORIENT_MODE_LOW_ASYMMETRICAL  = 2,
+};
+
+/* Power mode for the device */
 enum bma253_power_mode {
-	BMA253_POWER_MODE_NORMAL       = 0,
-	BMA253_POWER_MODE_DEEP_SUSPEND = 1,
-	BMA253_POWER_MODE_SUSPEND      = 2,
-	BMA253_POWER_MODE_STANDBY      = 3,
-	BMA253_POWER_MODE_LPM_1        = 4,
-	BMA253_POWER_MODE_LPM_2        = 5,
+    BMA253_POWER_MODE_NORMAL       = 0,
+    BMA253_POWER_MODE_DEEP_SUSPEND = 1,
+    BMA253_POWER_MODE_SUSPEND      = 2,
+    BMA253_POWER_MODE_STANDBY      = 3,
+    BMA253_POWER_MODE_LPM_1        = 4,
+    BMA253_POWER_MODE_LPM_2        = 5,
 };
 
+/* Duration of sleep whenever the device is in a power mode that alternates
+ * between wake and sleep (LPM 1 & 2) */
 enum bma253_sleep_duration {
-	BMA253_SLEEP_DURATION_0_5_MS = 0,
-	BMA253_SLEEP_DURATION_1_MS   = 1,
-	BMA253_SLEEP_DURATION_2_MS   = 2,
-	BMA253_SLEEP_DURATION_4_MS   = 3,
-	BMA253_SLEEP_DURATION_6_MS   = 4,
-	BMA253_SLEEP_DURATION_10_MS  = 5,
-	BMA253_SLEEP_DURATION_25_MS  = 6,
-	BMA253_SLEEP_DURATION_50_MS  = 7,
-	BMA253_SLEEP_DURATION_100_MS = 8,
-	BMA253_SLEEP_DURATION_500_MS = 9,
-	BMA253_SLEEP_DURATION_1_S    = 10,
+    BMA253_SLEEP_DURATION_0_5_MS = 0,
+    BMA253_SLEEP_DURATION_1_MS   = 1,
+    BMA253_SLEEP_DURATION_2_MS   = 2,
+    BMA253_SLEEP_DURATION_4_MS   = 3,
+    BMA253_SLEEP_DURATION_6_MS   = 4,
+    BMA253_SLEEP_DURATION_10_MS  = 5,
+    BMA253_SLEEP_DURATION_25_MS  = 6,
+    BMA253_SLEEP_DURATION_50_MS  = 7,
+    BMA253_SLEEP_DURATION_100_MS = 8,
+    BMA253_SLEEP_DURATION_500_MS = 9,
+    BMA253_SLEEP_DURATION_1_S    = 10,
 };
 
+/* Default configuration values to use with the device */
 struct bma253_cfg {
-	enum bma253_g_range g_range;
-	enum bma253_filter_bandwidth filter_bandwidth;
-	bool use_unfiltered_data;
-	enum bma253_int_pin_output int_pin_output;
-	enum bma253_int_pin_active int_pin_active;
-	enum bma253_tap_quiet tap_quiet;
-	enum bma253_tap_shock tap_shock;
-	enum bma253_d_tap_window d_tap_window;
-	enum bma253_tap_wake_samples tap_wake_samples;
-	float tap_thresh_g;
-	enum bma253_i2c_watchdog i2c_watchdog;
-	float offset_x_g;
-	float offset_y_g;
-	float offset_z_g;
-	enum bma253_power_mode power_mode;
-	enum bma253_sleep_duration sleep_duration;
-	int int_pin1_num;
-	int int_pin2_num;
-	sensor_type_t sensor_mask;
+    /* Accelerometer configuration */
+    enum bma253_g_range g_range;
+    enum bma253_filter_bandwidth filter_bandwidth;
+    /* Whether to use data that has not been filtered at all */
+    bool use_unfiltered_data;
+    /* Low-g event configuration */
+    uint16_t low_g_delay_ms;
+    float low_g_thresh_g;
+    float low_g_hyster_g;
+    /* High-g event configuration */
+    float high_g_hyster_g;
+    uint16_t high_g_delay_ms;
+    float high_g_thresh_g;
+    /* Tap (double & single) event configuration */
+    enum bma253_tap_quiet tap_quiet;
+    enum bma253_tap_shock tap_shock;
+    enum bma253_d_tap_window d_tap_window;
+    enum bma253_tap_wake_samples tap_wake_samples;
+    float tap_thresh_g;
+    /* Orientation event configuration */
+    float orient_hyster_g;
+    enum bma253_orient_blocking orient_blocking;
+    enum bma253_orient_mode orient_mode;
+    bool orient_signal_ud;
+    /* Offsets for acceleration measurements, by axis */
+    float offset_x_g;
+    float offset_y_g;
+    float offset_z_g;
+    /* Power management configuration */
+    enum bma253_power_mode power_mode;
+    enum bma253_sleep_duration sleep_duration;
+    /* Applicable sensor types supported */
+    sensor_type_t sensor_mask;
 };
 
+/* Used to track interrupt state to wake any present waiters */
 struct bma253_int {
-	os_sr_t lock;
-	struct os_sem wait;
-	bool active;
-	bool asleep;
+    /* Synchronize access to this structure */
+    os_sr_t lock;
+    /* Sleep waiting for an interrupt to occur */
+    struct os_sem wait;
+    /* Is the interrupt currently active */
+    bool active;
+    /* Is there a waiter currently sleeping */
+    bool asleep;
+    /* Configured interrupts */
+    struct sensor_int *ints;
 };
 
-enum bma253_int_pin {
-	BMA253_INT_PIN_1   = 0,
-	BMA253_INT_PIN_2   = 1,
-	BMA253_INT_PIN_MAX = 2,
+/* Device private data */
+struct bma253_private_driver_data {
+    struct bma253_int * interrupt;
+    struct sensor_notify_ev_ctx notify_ctx;
+    struct sensor_read_ev_ctx read_ctx;
+    uint8_t registered_mask;
+
+    uint8_t int_num;
+    uint8_t int_route;
+    uint8_t int_ref_cnt;
 };
 
+/* The device itself */
 struct bma253 {
-	struct os_dev dev;
-	struct sensor sensor;
-	struct bma253_cfg cfg;
-	struct bma253_int ints[BMA253_INT_PIN_MAX];
+    /* Underlying OS device */
+    struct os_dev dev;
+    /* The sensor infrastructure */
+    struct sensor sensor;
+    /* Default configuration values */
+    struct bma253_cfg cfg;
+    /* Active interrupt state */
+    struct bma253_int intr;
+    /* Active power mode, could be different from default configured
+     * power mode if a function that requires a higher power mode is
+     * currently running. */
+    enum bma253_power_mode power;
+
+    /* Private driver data */
+    struct bma253_private_driver_data pdd;
 };
 
+/* Offset compensation is performed to target this given value, by axis */
 enum bma253_offset_comp_target {
-	BMA253_OFFSET_COMP_TARGET_0_G     = 0,
-	BMA253_OFFSET_COMP_TARGET_NEG_1_G = 1,
-	BMA253_OFFSET_COMP_TARGET_POS_1_G = 2,
+    BMA253_OFFSET_COMP_TARGET_0_G     = 0,
+    BMA253_OFFSET_COMP_TARGET_NEG_1_G = 1,
+    BMA253_OFFSET_COMP_TARGET_POS_1_G = 2,
+};
+
+/* The device's X/Y orientation, in form of rotation */
+enum bma253_orient_xy {
+    BMA253_ORIENT_XY_PORTRAIT_UPRIGHT     = 0,
+    BMA253_ORIENT_XY_PORTRAIT_UPSIDE_DOWN = 1,
+    BMA253_ORIENT_XY_LANDSCAPE_LEFT       = 2,
+    BMA253_ORIENT_XY_LANDSCAPE_RIGHT      = 3,
+};
+
+/* The device's full orientation */
+struct bma253_orient_xyz {
+    /* The X/Y orientation */
+    enum bma253_orient_xy orient_xy;
+    /* Is device facing upward or downward */
+    bool downward_z;
 };
 
+/* Type of tap event to look for */
 enum bma253_tap_type {
-	BMA253_TAP_TYPE_DOUBLE = 0,
-	BMA253_TAP_TYPE_SINGLE = 1,
+    BMA253_TAP_TYPE_DOUBLE = 0,
+    BMA253_TAP_TYPE_SINGLE = 1,
 };
 
 /**
@@ -173,10 +250,11 @@ enum bma253_tap_type {
  *
  * @return 0 on success, non-zero on failure.
  */
-int bma253_self_test(struct bma253 * bma253,
-		     float delta_high_mult,
-		     float delta_low_mult,
-		     bool * self_test_fail);
+int
+bma253_self_test(struct bma253 * bma253,
+                 float delta_high_mult,
+                 float delta_low_mult,
+                 bool * self_test_fail);
 
 /**
  * Perform an offset compensation and use the resulting offsets.
@@ -188,10 +266,43 @@ int bma253_self_test(struct bma253 * bma253,
  *
  * @return 0 on success, non-zero on failure.
  */
-int bma253_offset_compensation(struct bma253 * bma253,
-			       enum bma253_offset_comp_target target_x,
-			       enum bma253_offset_comp_target target_y,
-			       enum bma253_offset_comp_target target_z);
+int
+bma253_offset_compensation(struct bma253 * bma253,
+                           enum bma253_offset_comp_target target_x,
+                           enum bma253_offset_comp_target target_y,
+                           enum bma253_offset_comp_target target_z);
+
+/**
+ * Return the current compensation offsets in use.
+ *
+ * @param The device object.
+ * @param The offset for the X axis, filled in by this function.
+ * @param The offset for the Y axis, filled in by this function.
+ * @param The offset for the Z axis, filled in by this function.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_query_offsets(struct bma253 * bma253,
+                     float * offset_x_g,
+                     float * offset_y_g,
+                     float * offset_z_g);
+
+/**
+ * Store and use the provided compensation offsets.
+ *
+ * @param The device object.
+ * @param The offset for the X axis.
+ * @param The offset for the Y axis.
+ * @param the offset for the Z axis.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_write_offsets(struct bma253 * bma253,
+                     float offset_x_g,
+                     float offset_y_g,
+                     float offset_z_g);
 
 /**
  * Callback for handling accelerometer sensor data.
@@ -201,8 +312,9 @@ int bma253_offset_compensation(struct bma253 * bma253,
  *
  * @return true to stop streaming data, false to continue.
  */
-typedef bool (*bma253_stream_read_func_t)(void *,
-					  struct sensor_accel_data *);
+typedef bool
+(*bma253_stream_read_func_t)(void *,
+                             struct sensor_accel_data *);
 
 /**
  * Provide a continuous stream of accelerometer readings.
@@ -214,10 +326,67 @@ typedef bool (*bma253_stream_read_func_t)(void *,
  *
  * @return 0 on success, non-zero on failure.
  */
-int bma253_stream_read(struct bma253 * bma253,
-		       bma253_stream_read_func_t read_func,
-		       void * read_arg,
-		       uint32_t time_ms);
+int
+bma253_stream_read(struct bma253 * bma253,
+                   bma253_stream_read_func_t read_func,
+                   void * read_arg,
+                   uint32_t time_ms);
+
+/**
+ * Get the current temperature at the device.
+ *
+ * @param The device object.
+ * @param The current temperature in celsius, filled in by this function.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_current_temp(struct bma253 * bma253,
+                    float * temp_c);
+
+/**
+ * Get the current device orientation.
+ *
+ * @param The device object.
+ * @param The current orientation, filled in by this function.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_current_orient(struct bma253 * bma253,
+                      struct bma253_orient_xyz * orient_xyz);
+
+/**
+ * Block until the device orientation changes.
+ *
+ * @param The device object.
+ * @param The new orientation, filled in by this function.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_wait_for_orient(struct bma253 * bma253,
+                       struct bma253_orient_xyz * orient_xyz);
+
+/**
+ * Block until a high-g event occurs.
+ *
+ * @param The device object.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_wait_for_high_g(struct bma253 * bma253);
+
+/**
+ * Block until a low-g event occurs.
+ *
+ * @param The device object.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_wait_for_low_g(struct bma253 * bma253);
 
 /**
  * Block until a single or double tap event occurs.
@@ -227,8 +396,25 @@ int bma253_stream_read(struct bma253 * bma253,
  *
  * @return 0 on success, non-zero on failure.
  */
-int bma253_wait_for_tap(struct bma253 * bma253,
-			enum bma253_tap_type tap_type);
+int
+bma253_wait_for_tap(struct bma253 * bma253,
+                    enum bma253_tap_type tap_type);
+
+/**
+ * Change the default power settings.
+ *
+ * @param The device object.
+ * @param The new power mode, which the device resides in unless a different
+ *        and more aggressive power mode is required to satisfy a running API
+ *        function.
+ * @param The new sleep duration, used whenever device is in LPM_1/2 mode
+ *        either due to default power mode or due to being in a temporarily
+ *        overridden power mode.
+ */
+int
+bma253_power_settings(struct bma253 * bma253,
+                      enum bma253_power_mode power_mode,
+                      enum bma253_sleep_duration sleep_duration);
 
 /**
  * Configure the sensor.
@@ -238,7 +424,8 @@ int bma253_wait_for_tap(struct bma253 * bma253,
  *
  * @return 0 on success, non-zero on failure.
  */
-int bma253_config(struct bma253 * bma253, struct bma253_cfg * cfg);
+int
+bma253_config(struct bma253 * bma253, struct bma253_cfg * cfg);
 
 /**
  * Expects to be called back through os_dev_create().
@@ -248,6 +435,21 @@ int bma253_config(struct bma253 * bma253, struct bma253_cfg * cfg);
  *
  * @return 0 on success, non-zero on failure.
  */
-int bma253_init(struct os_dev * dev, void * arg);
+int
+bma253_init(struct os_dev * dev, void * arg);
+
+#if MYNEWT_VAL(BMA253_CLI)
+/**
+ * Initialize the BMA253 shell extensions.
+ *
+ * @return 0 on success, non-zero on failure.
+ */
+int
+bma253_shell_init(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif
diff --git a/hw/drivers/sensors/bma253/pkg.yml b/hw/drivers/sensors/bma253/pkg.yml
index 40f9f5cef..d1c7a2a71 100644
--- a/hw/drivers/sensors/bma253/pkg.yml
+++ b/hw/drivers/sensors/bma253/pkg.yml
@@ -27,6 +27,11 @@ pkg.keywords:
 pkg.deps:
     - "@apache-mynewt-core/kernel/os"
     - "@apache-mynewt-core/hw/hal"
+    - "@apache-mynewt-core/hw/sensor"
 
-pkg.deps.BMA253_LOG:
-    - "@apache-mynewt-core/sys/log/full"
+pkg.req_apis:
+    - stats
+    - log
+
+pkg.deps.BMA253_CLI:
+    - "@apache-mynewt-core/util/parse"
diff --git a/hw/drivers/sensors/bma253/src/bma253.c b/hw/drivers/sensors/bma253/src/bma253.c
index 729d7e56f..2d1534617 100644
--- a/hw/drivers/sensors/bma253/src/bma253.c
+++ b/hw/drivers/sensors/bma253/src/bma253.c
@@ -17,11 +17,12 @@
  * under the License.
  */
 
-#include <alloca.h>
 #include <assert.h>
+#include <math.h>
 #include <string.h>
 
 #include "bma253/bma253.h"
+#include "bma253_priv.h"
 #include "defs/error.h"
 #include "hal/hal_gpio.h"
 #include "hal/hal_i2c.h"
@@ -32,3529 +33,4678 @@
 
 #if MYNEWT_VAL(BMA253_LOG)
 static struct log bma253_log;
-#define LOG_MODULE_BMA253	(253)
-#define BMA253_ERROR(...)	LOG_ERROR(&bma253_log, LOG_MODULE_BMA253, __VA_ARGS__)
-#define BMA253_INFO(...)	LOG_INFO(&bma253_log, LOG_MODULE_BMA253, __VA_ARGS__)
+#define LOG_MODULE_BMA253 (253)
+#define BMA253_ERROR(...) LOG_ERROR(&bma253_log, LOG_MODULE_BMA253, __VA_ARGS__)
+#define BMA253_INFO(...)  LOG_INFO(&bma253_log, LOG_MODULE_BMA253, __VA_ARGS__)
 #else
 #define BMA253_ERROR(...)
 #define BMA253_INFO(...)
 #endif
 
-#define REG_ADDR_BGW_CHIPID    0x00    //    r
-// RESERVED                            //
-#define REG_ADDR_ACCD_X_LSB    0x02    //    r
-#define REG_ADDR_ACCD_X_MSB    0x03    //    r
-#define REG_ADDR_ACCD_Y_LSB    0x04    //    r
-#define REG_ADDR_ACCD_Y_MSB    0x05    //    r
-#define REG_ADDR_ACCD_Z_LSB    0x06    //    r
-#define REG_ADDR_ACCD_Z_MSB    0x07    //    r
-#define REG_ADDR_ACCD_TEMP     0x08    //    r
-#define REG_ADDR_INT_STATUS_0  0x09    //    r
-#define REG_ADDR_INT_STATUS_1  0x0A    //    r
-#define REG_ADDR_INT_STATUS_2  0x0B    //    r
-#define REG_ADDR_INT_STATUS_3  0x0C    //    r
-// RESERVED                            //
-#define REG_ADDR_FIFO_STATUS   0x0E    //    r
-#define REG_ADDR_PMU_RANGE     0x0F    //    rw
-#define REG_ADDR_PMU_BW        0x10    //    rw
-#define REG_ADDR_PMU_LPW       0x11    //    rw
-#define REG_ADDR_PMU_LOW_POWER 0x12    //    rw
-#define REG_ADDR_ACCD_HBW      0x13    //    rw
-#define REG_ADDR_BGW_SOFTRESET 0x14    //     w
-// RESERVED                            //
-#define REG_ADDR_INT_EN_0      0x16    //    rw
-#define REG_ADDR_INT_EN_1      0x17    //    rw
-#define REG_ADDR_INT_EN_2      0x18    //    rw
-#define REG_ADDR_INT_MAP_0     0x19    //    rw
-#define REG_ADDR_INT_MAP_1     0x1A    //    rw
-#define REG_ADDR_INT_MAP_2     0x1B    //    rw
-// RESERVED                            //
-// RESERVED                            //
-#define REG_ADDR_INT_SRC       0x1E    //    rw
-// RESERVED                            //
-#define REG_ADDR_INT_OUT_CTRL  0x20    //    rw
-#define REG_ADDR_INT_RST_LATCH 0x21    //    rw
-#define REG_ADDR_INT_0         0x22    //    rw
-#define REG_ADDR_INT_1         0x23    //    rw
-#define REG_ADDR_INT_2         0x24    //    rw
-#define REG_ADDR_INT_3         0x25    //    rw
-#define REG_ADDR_INT_4         0x26    //    rw
-#define REG_ADDR_INT_5         0x27    //    rw
-#define REG_ADDR_INT_6         0x28    //    rw
-#define REG_ADDR_INT_7         0x29    //    rw
-#define REG_ADDR_INT_8         0x2A    //    rw
-#define REG_ADDR_INT_9         0x2B    //    rw
-#define REG_ADDR_INT_A         0x2C    //    rw
-#define REG_ADDR_INT_B         0x2D    //    rw
-#define REG_ADDR_INT_C         0x2E    //    rw
-#define REG_ADDR_INT_D         0x2F    //    rw
-#define REG_ADDR_FIFO_CONFIG_0 0x30    //    rw
-// RESERVED                            //
-#define REG_ADDR_PMU_SELF_TEST 0x32    //    rw
-#define REG_ADDR_TRIM_NVM_CTRL 0x33    //    rw
-#define REG_ADDR_BGW_SPI3_WDT  0x34    //    rw
-// RESERVED                            //
-#define REG_ADDR_OFC_CTRL      0x36    //    rw
-#define REG_ADDR_OFC_SETTING   0x37    //    rw
-#define REG_ADDR_OFC_OFFSET_X  0x38    //    rw    nvm
-#define REG_ADDR_OFC_OFFSET_Y  0x39    //    rw    nvm
-#define REG_ADDR_OFC_OFFSET_Z  0x3A    //    rw    nvm
-#define REG_ADDR_TRIM_GP0      0x3B    //    rw    nvm
-#define REG_ADDR_TRIM_GP1      0x3C    //    rw    nvm
-// RESERVED                            //
-#define REG_ADDR_FIFO_CONFIG_1 0x3E    //    rw
-#define REG_ADDR_FIFO_DATA     0x3F    //    r
-
-#define REG_VALUE_CHIP_ID    0xFA
-#define REG_VALUE_SOFT_RESET 0xB6
-
-static void delay_msec(uint32_t delay)
-{
-	delay = (delay * OS_TICKS_PER_SEC) / 1000 + 1;
-	os_time_delay(delay);
-}
-
-static void interrupt_init(struct bma253_int * interrupt)
-{
-	os_error_t error;
-
-	error = os_sem_init(&interrupt->wait, 0);
-	assert(error == OS_OK);
-
-	interrupt->active = false;
-	interrupt->asleep = false;
-}
-
-static void interrupt_undo(struct bma253_int * interrupt)
-{
-	OS_ENTER_CRITICAL(interrupt->lock);
-	interrupt->active = false;
-	interrupt->asleep = false;
-	OS_EXIT_CRITICAL(interrupt->lock);
-}
-
-static void interrupt_wait(struct bma253_int * interrupt)
-{
-	bool wait;
-
-	OS_ENTER_CRITICAL(interrupt->lock);
-	if (interrupt->active) {
-		interrupt->active = false;
-		wait = false;
-	} else {
-		interrupt->asleep = true;
-		wait = true;
-	}
-	OS_EXIT_CRITICAL(interrupt->lock);
-
-	if (wait) {
-		os_error_t error;
-
-		error = os_sem_pend(&interrupt->wait, -1);
-		assert(error == OS_OK);
-	}
-}
-
-static void interrupt_wake(struct bma253_int * interrupt)
-{
-	bool wake;
-
-	OS_ENTER_CRITICAL(interrupt->lock);
-	if (interrupt->asleep) {
-		interrupt->asleep = false;
-		wake = true;
-	} else {
-		interrupt->active = true;
-		wake = false;
-	}
-	OS_EXIT_CRITICAL(interrupt->lock);
-
-	if (wake) {
-		os_error_t error;
+#define BMA253_NOTIFY_MASK  0x01
+#define BMA253_READ_MASK    0x02
 
-		error = os_sem_release(&interrupt->wait);
-		assert(error == OS_OK);
-	}
+    enum int_route int_route;
+static void
+delay_msec(uint32_t delay)
+{
+    delay = (delay * OS_TICKS_PER_SEC) / 1000 + 1;
+    os_time_delay(delay);
 }
 
-static void interrupt_handler(void * arg)
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+static void
+init_interrupt(struct bma253_int * interrupt, struct sensor_int *ints)
 {
-	struct bma253_int * interrupt;
+    os_error_t error;
 
-	interrupt = (struct bma253_int *)arg;
+    error = os_sem_init(&interrupt->wait, 0);
+    assert(error == OS_OK);
 
-	interrupt_wake(interrupt);
+    interrupt->active = false;
+    interrupt->asleep = false;
+    interrupt->ints = ints;
 }
 
-static int get_register(const struct sensor_itf * itf,
-			uint8_t addr,
-			uint8_t * data)
+static void
+undo_interrupt(struct bma253_int * interrupt)
 {
-	struct hal_i2c_master_data oper;
-	int rc;
+    OS_ENTER_CRITICAL(interrupt->lock);
+    interrupt->active = false;
+    interrupt->asleep = false;
+    OS_EXIT_CRITICAL(interrupt->lock);
+}
+
+static void
+wait_interrupt(struct bma253_int * interrupt, enum bma253_int_num int_num)
+{
+    bool wait;
+
+    OS_ENTER_CRITICAL(interrupt->lock);
+
+    /* Check if we did not missed interrupt */
+    if (hal_gpio_read(interrupt->ints[int_num].host_pin) ==
+                                            interrupt->ints[int_num].active) {
+        OS_EXIT_CRITICAL(interrupt->lock);
+        return;
+    }
+
+    if (interrupt->active) {
+        interrupt->active = false;
+        wait = false;
+    } else {
+        interrupt->asleep = true;
+        wait = true;
+    }
+    OS_EXIT_CRITICAL(interrupt->lock);
+
+    if (wait) {
+        os_error_t error;
+
+        error = os_sem_pend(&interrupt->wait, -1);
+        assert(error == OS_OK);
+    }
+}
 
-	oper.address = itf->si_addr;
-	oper.len     = 1;
-	oper.buffer  = &addr;
+static void
+wake_interrupt(struct bma253_int * interrupt)
+{
+    bool wake;
+
+    OS_ENTER_CRITICAL(interrupt->lock);
+    if (interrupt->asleep) {
+        interrupt->asleep = false;
+        wake = true;
+    } else {
+        interrupt->active = true;
+        wake = false;
+    }
+    OS_EXIT_CRITICAL(interrupt->lock);
+
+    if (wake) {
+        os_error_t error;
+
+        error = os_sem_release(&interrupt->wait);
+        assert(error == OS_OK);
+    }
+}
 
-	rc = hal_i2c_master_write(itf->si_num, &oper,
-				  OS_TICKS_PER_SEC / 10, 1);
-	if (rc != 0) {
-		BMA253_ERROR("I2C access failed at address 0x%02X\n",
-			     addr);
-		return rc;
-	}
+static void
+interrupt_handler(void * arg)
+{
+    struct sensor *sensor = arg;
+    struct bma253 *bma253;
 
-	oper.address = itf->si_addr;
-	oper.len     = 1;
-	oper.buffer  = data;
+    bma253 = (struct bma253 *)SENSOR_GET_DEVICE(sensor);
 
-	rc = hal_i2c_master_read(itf->si_num, &oper,
-				 OS_TICKS_PER_SEC / 10, 1);
-	if (rc != 0) {
-		BMA253_ERROR("I2C read failed at address 0x%02X single byte\n",
-			     addr);
-		return rc;
-	}
+    if (bma253->pdd.interrupt) {
+        wake_interrupt(bma253->pdd.interrupt);
+    }
 
-	return 0;
+    sensor_mgr_put_interrupt_evt(sensor);
 }
+#endif
 
-static int get_registers(const struct sensor_itf * itf,
-			 uint8_t addr,
-			 uint8_t * data,
-			 uint8_t size)
+static int
+get_register(const struct bma253 * bma253,
+             uint8_t addr,
+             uint8_t * data)
 {
-	struct hal_i2c_master_data oper;
-	int rc;
+    const struct sensor_itf * itf;
+    struct hal_i2c_master_data oper;
+    int rc;
+
+    itf = SENSOR_GET_ITF(&bma253->sensor);
+
+    oper.address = itf->si_addr;
+    oper.len     = 1;
+    oper.buffer  = &addr;
+
+    rc = hal_i2c_master_write(itf->si_num, &oper,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc != 0) {
+        BMA253_ERROR("I2C access failed at address 0x%02X\n", addr);
+        return rc;
+    }
+
+    oper.address = itf->si_addr;
+    oper.len     = 1;
+    oper.buffer  = data;
+
+    rc = hal_i2c_master_read(itf->si_num, &oper,
+                             OS_TICKS_PER_SEC / 10, 1);
+    if (rc != 0) {
+        BMA253_ERROR("I2C read failed at address 0x%02X single byte\n",
+                     addr);
+        return rc;
+    }
+
+    return 0;
+}
 
-	oper.address = itf->si_addr;
-	oper.len     = 1;
-	oper.buffer  = &addr;
+static int
+get_registers(const struct bma253 * bma253,
+              uint8_t addr,
+              uint8_t * data,
+              uint8_t size)
+{
+    const struct sensor_itf * itf;
+    struct hal_i2c_master_data oper;
+    int rc;
+
+    itf = SENSOR_GET_ITF(&bma253->sensor);
+
+    oper.address = itf->si_addr;
+    oper.len     = 1;
+    oper.buffer  = &addr;
+
+    rc = hal_i2c_master_write(itf->si_num, &oper,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc != 0) {
+        BMA253_ERROR("I2C access failed at address 0x%02X\n",
+                     addr);
+        return rc;
+    }
+
+    oper.address = itf->si_addr;
+    oper.len     = size;
+    oper.buffer  = data;
+
+    rc = hal_i2c_master_read(itf->si_num, &oper,
+                             OS_TICKS_PER_SEC / 10, 1);
+    if (rc != 0) {
+        BMA253_ERROR("I2C read failed at address 0x%02X length %u\n",
+                     addr, size);
+        return rc;
+    }
+
+    return 0;
+}
 
-	rc = hal_i2c_master_write(itf->si_num, &oper,
-				  OS_TICKS_PER_SEC / 10, 1);
-	if (rc != 0) {
-		BMA253_ERROR("I2C access failed at address 0x%02X\n",
-			     addr);
-		return rc;
-	}
+static int
+set_register(const struct bma253 * bma253,
+             uint8_t addr,
+             uint8_t data)
+{
+    const struct sensor_itf * itf;
+    uint8_t tuple[2];
+    struct hal_i2c_master_data oper;
+    int rc;
+
+    itf = SENSOR_GET_ITF(&bma253->sensor);
+
+    tuple[0] = addr;
+    tuple[1] = data;
+
+    oper.address = itf->si_addr;
+    oper.len     = 2;
+    oper.buffer  = tuple;
+
+    rc = hal_i2c_master_write(itf->si_num, &oper,
+                              OS_TICKS_PER_SEC / 10, 1);
+    if (rc != 0) {
+        BMA253_ERROR("I2C write failed at address 0x%02X single byte\n",
+                     addr);
+        return rc;
+    }
+
+    switch (bma253->power) {
+    case BMA253_POWER_MODE_SUSPEND:
+    case BMA253_POWER_MODE_LPM_1:
+        delay_msec(1);
+        break;
+    default:
+        break;
+    }
+
+    return 0;
+}
 
-	oper.address = itf->si_addr;
-	oper.len     = size;
-	oper.buffer  = data;
+int
+bma253_get_chip_id(const struct bma253 * bma253,
+                   uint8_t * chip_id)
+{
+    return get_register(bma253, REG_ADDR_BGW_CHIPID, chip_id);
+}
+
+static void
+compute_accel_data(struct accel_data * accel_data,
+                   const uint8_t * raw_data,
+                   float accel_scale)
+{
+    int16_t raw_accel;
 
-	rc = hal_i2c_master_read(itf->si_num, &oper,
-				 OS_TICKS_PER_SEC / 10, 1);
-	if (rc != 0) {
-		BMA253_ERROR("I2C read failed at address 0x%02X length %u\n",
-			     addr, size);
-		return rc;
-	}
+    raw_accel = (raw_data[0] >> 4) | (raw_data[1] << 4);
+    raw_accel <<= 4;
+    raw_accel >>= 4;
 
-	return 0;
+    accel_data->accel_g = (float)raw_accel * accel_scale;
+    accel_data->new_data = raw_data[0] & 0x01;
 }
 
-static int set_register(const struct sensor_itf * itf,
-			uint8_t addr,
-			uint8_t data)
+int
+bma253_get_accel(const struct bma253 * bma253,
+                 enum bma253_g_range g_range,
+                 enum axis axis,
+                 struct accel_data * accel_data)
 {
-	uint8_t tuple[2];
-	struct hal_i2c_master_data oper;
-	int rc;
+    float accel_scale;
+    uint8_t base_addr;
+    uint8_t data[2];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        accel_scale = 0.00098;
+        break;
+    case BMA253_G_RANGE_4:
+        accel_scale = 0.00195;
+        break;
+    case BMA253_G_RANGE_8:
+        accel_scale = 0.00391;
+        break;
+    case BMA253_G_RANGE_16:
+        accel_scale = 0.00781;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (axis) {
+    case AXIS_X:
+        base_addr = REG_ADDR_ACCD_X_LSB;
+        break;
+    case AXIS_Y:
+        base_addr = REG_ADDR_ACCD_Y_LSB;
+        break;
+    case AXIS_Z:
+        base_addr = REG_ADDR_ACCD_Z_LSB;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = get_registers(bma253, base_addr,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    compute_accel_data(accel_data, data, accel_scale);
+
+    return 0;
+}
 
-	tuple[0] = addr;
-	tuple[1] = data;
+int
+bma253_get_temp(const struct bma253 * bma253,
+                float * temp_c)
+{
+    uint8_t data;
+    int rc;
 
-	oper.address = itf->si_addr;
-	oper.len     = 2;
-	oper.buffer  = tuple;
+    rc = get_register(bma253, REG_ADDR_ACCD_TEMP, &data);
+    if (rc != 0) {
+        return rc;
+    }
 
-	rc = hal_i2c_master_write(itf->si_num, &oper,
-				  OS_TICKS_PER_SEC / 10, 1);
-	if (rc != 0) {
-		BMA253_ERROR("I2C write failed at address 0x%02X single byte\n",
-			     addr);
-		return rc;
-	}
+    *temp_c = (float)(int8_t)data * 0.5 + 23.0;
 
-	return 0;
+    return 0;
 }
 
-int bma253_get_chip_id(const struct sensor_itf * itf,
-		       uint8_t * chip_id)
+static void
+quad_to_axis_trigger(struct axis_trigger * axis_trigger,
+                     uint8_t quad_bits,
+                     const char * name_bits)
 {
-	return get_register(itf, REG_ADDR_BGW_CHIPID, chip_id);
+    axis_trigger->sign = (quad_bits >> 3) & 0x01;
+    switch (quad_bits & 0x07) {
+    default:
+        BMA253_ERROR("unknown %s quad bits 0x%02X\n",
+                     name_bits, quad_bits);
+    case 0x00:
+        axis_trigger->axis = -1;
+        axis_trigger->axis_known = false;
+        break;
+    case 0x01:
+        axis_trigger->axis = AXIS_X;
+        axis_trigger->axis_known = true;
+        break;
+    case 0x02:
+        axis_trigger->axis = AXIS_Y;
+        axis_trigger->axis_known = true;
+        break;
+    case 0x03:
+        axis_trigger->axis = AXIS_Z;
+        axis_trigger->axis_known = true;
+        break;
+    }
 }
 
-enum axis {
-	AXIS_X   = 0,
-	AXIS_Y   = 1,
-	AXIS_Z   = 2,
-	AXIS_ALL = 3,
-};
+int
+bma253_get_int_status(const struct bma253 * bma253,
+                      struct int_status * int_status)
+{
+    uint8_t data[4];
+    int rc;
+
+    rc = get_registers(bma253, REG_ADDR_INT_STATUS_0,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_status->flat_int_active = data[0] & 0x80;
+    int_status->orient_int_active = data[0] & 0x40;
+    int_status->s_tap_int_active = data[0] & 0x20;
+    int_status->d_tap_int_active = data[0] & 0x10;
+    int_status->slow_no_mot_int_active = data[0] & 0x08;
+    int_status->slope_int_active = data[0] & 0x04;
+    int_status->high_g_int_active = data[0] & 0x02;
+    int_status->low_g_int_active = data[0] & 0x01;
+    int_status->data_int_active = data[1] & 0x80;
+    int_status->fifo_wmark_int_active = data[1] & 0x40;
+    int_status->fifo_full_int_active = data[1] & 0x20;
+    quad_to_axis_trigger(&int_status->tap_trigger,
+                 (data[2] >> 4) & 0x0F, "tap");
+    quad_to_axis_trigger(&int_status->slope_trigger,
+                 (data[2] >> 0) & 0x0F, "slope");
+    int_status->device_is_flat = data[3] & 0x80;
+    int_status->device_is_down = data[3] & 0x40;
+    int_status->device_orientation = (data[3] >> 4) & 0x03;
+    quad_to_axis_trigger(&int_status->high_g_trigger,
+                 (data[3] >> 0) & 0x0F, "high_g");
+
+    return 0;
+}
 
-struct accel_data {
-	float accel_g;
-	bool new_data;
-};
+int
+bma253_get_fifo_status(const struct bma253 * bma253,
+                       bool * overrun,
+                       uint8_t * frame_counter)
+{
+    uint8_t data;
+    int rc;
 
-static void compute_accel_data(struct accel_data * accel_data,
-			       const uint8_t * raw_data,
-			       float accel_scale)
-{
-	int16_t raw_accel;
-
-	raw_accel = (raw_data[0] >> 4) | (raw_data[1] << 4);
-	raw_accel <<= 4;
-	raw_accel >>= 4;
-
-	accel_data->accel_g = (float)raw_accel * accel_scale;
-	accel_data->new_data = raw_data[0] & 0x01;
-}
-
-int bma253_get_accel(const struct sensor_itf * itf,
-		     enum bma253_g_range g_range,
-		     enum axis axis,
-		     struct accel_data * accel_data)
-{
-	float accel_scale;
-	uint8_t base_addr;
-	uint8_t data[2];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		accel_scale = 0.00098;
-		break;
-	case BMA253_G_RANGE_4:
-		accel_scale = 0.00195;
-		break;
-	case BMA253_G_RANGE_8:
-		accel_scale = 0.00391;
-		break;
-	case BMA253_G_RANGE_16:
-		accel_scale = 0.00781;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (axis) {
-	case AXIS_X:
-		base_addr = REG_ADDR_ACCD_X_LSB;
-		break;
-	case AXIS_Y:
-		base_addr = REG_ADDR_ACCD_Y_LSB;
-		break;
-	case AXIS_Z:
-		base_addr = REG_ADDR_ACCD_Z_LSB;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = get_registers(itf, base_addr,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	compute_accel_data(accel_data, data, accel_scale);
-
-	return 0;
-}
-
-int bma253_get_temp(const struct sensor_itf * itf,
-		    float * temp_c)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_ACCD_TEMP, &data);
-	if (rc != 0)
-		return rc;
-
-	*temp_c = (float)(int8_t)data * 0.5 + 23.0;
-
-	return 0;
-}
-
-enum axis_trigger_sign {
-	AXIS_TRIGGER_SIGN_POS = 0,
-	AXIS_TRIGGER_SIGN_NEG = 1,
-};
+    rc = get_register(bma253, REG_ADDR_FIFO_STATUS, &data);
+    if (rc != 0) {
+        return rc;
+    }
 
-struct axis_trigger {
-	enum axis_trigger_sign sign;
-	enum axis axis;
-	bool axis_known;
-};
+    *overrun = data & 0x80;
+    *frame_counter = data & 0x7F;
 
-enum dev_orientation {
-	DEV_ORIENTATION_PORTRAIT_UPRIGHT     = 0,
-	DEV_ORIENTATION_PORTRAIT_UPSIDE_DOWN = 1,
-	DEV_ORIENTATION_LANDSCAPE_LEFT       = 2,
-	DEV_ORIENTATION_LANDSCAPE_RIGHT      = 3,
-};
+    return 0;
+}
 
-struct int_status {
-	bool flat_int_active;
-	bool orient_int_active;
-	bool s_tap_int_active;
-	bool d_tap_int_active;
-	bool slow_no_mot_int_active;
-	bool slope_int_active;
-	bool high_g_int_active;
-	bool low_g_int_active;
-	bool data_int_active;
-	bool fifo_wmark_int_active;
-	bool fifo_full_int_active;
-	struct axis_trigger tap_trigger;
-	struct axis_trigger slope_trigger;
-	bool device_is_flat;
-	bool device_is_up;
-	enum dev_orientation device_orientation;
-	struct axis_trigger high_g_trigger;
-};
+int
+bma253_get_g_range(const struct bma253 * bma253,
+                   enum bma253_g_range * g_range)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_PMU_RANGE, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    switch (data & 0x0F) {
+    default:
+        BMA253_ERROR("unknown PMU_RANGE reg value 0x%02X\n", data);
+        *g_range = BMA253_G_RANGE_16;
+        break;
+    case 0x03:
+        *g_range = BMA253_G_RANGE_2;
+        break;
+    case 0x05:
+        *g_range = BMA253_G_RANGE_4;
+        break;
+    case 0x08:
+        *g_range = BMA253_G_RANGE_8;
+        break;
+    case 0x0C:
+        *g_range = BMA253_G_RANGE_16;
+        break;
+    }
+
+    return 0;
+}
 
-static void quad_to_axis_trigger(struct axis_trigger * axis_trigger,
-				 uint8_t quad_bits,
-				 const char * name_bits)
-{
-	axis_trigger->sign = (quad_bits >> 3) & 0x01;
-	switch (quad_bits & 0x07) {
-	default:
-		BMA253_ERROR("unknown %s quad bits 0x%02X\n",
-			     name_bits, quad_bits);
-	case 0x00:
-		axis_trigger->axis = -1;
-		axis_trigger->axis_known = false;
-		break;
-	case 0x01:
-		axis_trigger->axis = AXIS_X;
-		axis_trigger->axis_known = true;
-		break;
-	case 0x02:
-		axis_trigger->axis = AXIS_Y;
-		axis_trigger->axis_known = true;
-		break;
-	case 0x03:
-		axis_trigger->axis = AXIS_Z;
-		axis_trigger->axis_known = true;
-		break;
-	}
-}
-
-int bma253_get_int_status(const struct sensor_itf * itf,
-			  struct int_status * int_status)
-{
-	uint8_t data[4];
-	int rc;
-
-	rc = get_registers(itf, REG_ADDR_INT_STATUS_0,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	int_status->flat_int_active = data[0] & 0x80;
-	int_status->orient_int_active = data[0] & 0x40;
-	int_status->s_tap_int_active = data[0] & 0x20;
-	int_status->d_tap_int_active = data[0] & 0x10;
-	int_status->slow_no_mot_int_active = data[0] & 0x08;
-	int_status->slope_int_active = data[0] & 0x04;
-	int_status->high_g_int_active = data[0] & 0x02;
-	int_status->low_g_int_active = data[0] & 0x01;
-	int_status->data_int_active = data[1] & 0x80;
-	int_status->fifo_wmark_int_active = data[1] & 0x40;
-	int_status->fifo_full_int_active = data[1] & 0x20;
-	quad_to_axis_trigger(&int_status->tap_trigger,
-			     (data[2] >> 4) & 0x0F, "tap");
-	quad_to_axis_trigger(&int_status->slope_trigger,
-			     (data[2] >> 0) & 0x0F, "slope");
-	int_status->device_is_flat = data[3] & 0x80;
-	int_status->device_is_up = data[3] & 0x40;
-	int_status->device_orientation = (data[3] >> 4) & 0x03;
-	quad_to_axis_trigger(&int_status->high_g_trigger,
-			     (data[3] >> 0) & 0x0F, "high_g");
-
-	return 0;
-}
-
-int bma253_get_fifo_status(const struct sensor_itf * itf,
-			   bool * overrun,
-			   uint8_t * frame_counter)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_FIFO_STATUS, &data);
-	if (rc != 0)
-		return rc;
-
-	*overrun = data & 0x80;
-	*frame_counter = data & 0x7F;
-
-	return 0;
-}
-
-int bma253_get_g_range(const struct sensor_itf * itf,
-		       enum bma253_g_range * g_range)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_PMU_RANGE, &data);
-	if (rc != 0)
-		return rc;
-
-	switch (data & 0x0F) {
-	default:
-		BMA253_ERROR("unknown PMU_RANGE reg value 0x%02X\n", data);
-		*g_range = BMA253_G_RANGE_16;
-		break;
-	case 0x03:
-		*g_range = BMA253_G_RANGE_2;
-		break;
-	case 0x05:
-		*g_range = BMA253_G_RANGE_4;
-		break;
-	case 0x08:
-		*g_range = BMA253_G_RANGE_8;
-		break;
-	case 0x0C:
-		*g_range = BMA253_G_RANGE_16;
-		break;
-	}
-
-	return 0;
-}
-
-int bma253_set_g_range(const struct sensor_itf * itf,
-		       enum bma253_g_range g_range)
-{
-	uint8_t data;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		data = 0x03;
-		break;
-	case BMA253_G_RANGE_4:
-		data = 0x05;
-		break;
-	case BMA253_G_RANGE_8:
-		data = 0x08;
-		break;
-	case BMA253_G_RANGE_16:
-		data = 0x0C;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	return set_register(itf, REG_ADDR_PMU_RANGE, data);
-}
-
-int bma253_get_filter_bandwidth(const struct sensor_itf * itf,
-				enum bma253_filter_bandwidth * filter_bandwidth)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_PMU_BW, &data);
-	if (rc != 0)
-		return rc;
-
-	switch (data & 0x1F) {
-	case 0x00 ... 0x08:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_7_81_HZ;
-		break;
-	case 0x09:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_15_63_HZ;
-		break;
-	case 0x0A:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_31_25_HZ;
-		break;
-	case 0x0B:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_62_5_HZ;
-		break;
-	case 0x0C:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_125_HZ;
-		break;
-	case 0x0D:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_250_HZ;
-		break;
-	case 0x0E:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_500_HZ;
-		break;
-	case 0x0F ... 0x1F:
-		*filter_bandwidth = BMA253_FILTER_BANDWIDTH_1000_HZ;
-		break;
-	}
-
-	return 0;
-}
-
-int bma253_set_filter_bandwidth(const struct sensor_itf * itf,
-				enum bma253_filter_bandwidth filter_bandwidth)
-{
-	uint8_t data;
-
-	switch (filter_bandwidth) {
-	case BMA253_FILTER_BANDWIDTH_7_81_HZ:
-		data = 0x08;
-		break;
-	case BMA253_FILTER_BANDWIDTH_15_63_HZ:
-		data = 0x09;
-		break;
-	case BMA253_FILTER_BANDWIDTH_31_25_HZ:
-		data = 0x0A;
-		break;
-	case BMA253_FILTER_BANDWIDTH_62_5_HZ:
-		data = 0x0B;
-		break;
-	case BMA253_FILTER_BANDWIDTH_125_HZ:
-		data = 0x0C;
-		break;
-	case BMA253_FILTER_BANDWIDTH_250_HZ:
-		data = 0x0D;
-		break;
-	case BMA253_FILTER_BANDWIDTH_500_HZ:
-		data = 0x0E;
-		break;
-	case BMA253_FILTER_BANDWIDTH_1000_HZ:
-		data = 0x0F;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	return set_register(itf, REG_ADDR_PMU_BW, data);
-}
-
-enum sleep_timer {
-	SLEEP_TIMER_EVENT_DRIVEN         = 0,
-	SLEEP_TIMER_EQUIDISTANT_SAMPLING = 1,
-};
+int
+bma253_set_g_range(const struct bma253 * bma253,
+                   enum bma253_g_range g_range)
+{
+    uint8_t data;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        data = 0x03;
+        break;
+    case BMA253_G_RANGE_4:
+        data = 0x05;
+        break;
+    case BMA253_G_RANGE_8:
+        data = 0x08;
+        break;
+    case BMA253_G_RANGE_16:
+        data = 0x0C;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    return set_register(bma253, REG_ADDR_PMU_RANGE, data);
+}
 
-struct power_settings {
-	enum bma253_power_mode power_mode;
-	enum bma253_sleep_duration sleep_duration;
-	enum sleep_timer sleep_timer;
-};
+int
+bma253_get_filter_bandwidth(const struct bma253 * bma253,
+                            enum bma253_filter_bandwidth * filter_bandwidth)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_PMU_BW, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    switch (data & 0x1F) {
+    case 0x00 ... 0x08:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_7_81_HZ;
+        break;
+    case 0x09:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_15_63_HZ;
+        break;
+    case 0x0A:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_31_25_HZ;
+        break;
+    case 0x0B:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_62_5_HZ;
+        break;
+    case 0x0C:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_125_HZ;
+        break;
+    case 0x0D:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_250_HZ;
+        break;
+    case 0x0E:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_500_HZ;
+        break;
+    case 0x0F ... 0x1F:
+        *filter_bandwidth = BMA253_FILTER_BANDWIDTH_1000_HZ;
+        break;
+    }
+
+    return 0;
+}
 
-int bma253_get_power_settings(const struct sensor_itf * itf,
-			      struct power_settings * power_settings)
-{
-	uint8_t data[2];
-	int rc;
-
-	rc = get_registers(itf, REG_ADDR_PMU_LPW,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	switch ((data[0] >> 5) & 0x07) {
-	default:
-		BMA253_ERROR("unknown PMU_LPW reg value 0x%02X\n", data[0]);
-		power_settings->power_mode = BMA253_POWER_MODE_NORMAL;
-		break;
-	case 0x00:
-		power_settings->power_mode = BMA253_POWER_MODE_NORMAL;
-		break;
-	case 0x01:
-		power_settings->power_mode = BMA253_POWER_MODE_DEEP_SUSPEND;
-		break;
-	case 0x02:
-		if ((data[1] & 0x40) == 0)
-			power_settings->power_mode = BMA253_POWER_MODE_LPM_1;
-		else
-			power_settings->power_mode = BMA253_POWER_MODE_LPM_2;
-		break;
-	case 0x04:
-		if ((data[1] & 0x40) == 0)
-			power_settings->power_mode = BMA253_POWER_MODE_SUSPEND;
-		else
-			power_settings->power_mode = BMA253_POWER_MODE_STANDBY;
-		break;
-	}
-
-	switch ((data[0] >> 1) & 0x0F) {
-	case 0x00 ... 0x05:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_0_5_MS;
-		break;
-	case 0x06:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_1_MS;
-		break;
-	case 0x07:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_2_MS;
-		break;
-	case 0x08:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_4_MS;
-		break;
-	case 0x09:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_6_MS;
-		break;
-	case 0x0A:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_10_MS;
-		break;
-	case 0x0B:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_25_MS;
-		break;
-	case 0x0C:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_50_MS;
-		break;
-	case 0x0D:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_100_MS;
-		break;
-	case 0x0E:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_500_MS;
-		break;
-	case 0x0F:
-		power_settings->sleep_duration = BMA253_SLEEP_DURATION_1_S;
-		break;
-	}
-
-	if ((data[1] & 0x20) != 0)
-		power_settings->sleep_timer = SLEEP_TIMER_EQUIDISTANT_SAMPLING;
-	else
-		power_settings->sleep_timer = SLEEP_TIMER_EVENT_DRIVEN;
-
-	return 0;
-}
-
-int bma253_set_power_settings(const struct sensor_itf * itf,
-			      const struct power_settings * power_settings)
-{
-	uint8_t data[2];
-	int rc;
-
-	data[0] = 0;
-	data[1] = 0;
-
-	switch (power_settings->power_mode) {
-	case BMA253_POWER_MODE_NORMAL:
-		data[0] |= 0x00 << 5;
-		break;
-	case BMA253_POWER_MODE_DEEP_SUSPEND:
-		data[0] |= 0x01 << 5;
-		break;
-	case BMA253_POWER_MODE_SUSPEND:
-		data[0] |= 0x04 << 5;
-		data[1] |= 0x00 << 6;
-		break;
-	case BMA253_POWER_MODE_STANDBY:
-		data[0] |= 0x04 << 5;
-		data[1] |= 0x01 << 6;
-		break;
-	case BMA253_POWER_MODE_LPM_1:
-		data[0] |= 0x02 << 5;
-		data[1] |= 0x00 << 6;
-		break;
-	case BMA253_POWER_MODE_LPM_2:
-		data[0] |= 0x02 << 5;
-		data[1] |= 0x01 << 6;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (power_settings->sleep_duration) {
-	case BMA253_SLEEP_DURATION_0_5_MS:
-		data[0] |= 0x05 << 1;
-		break;
-	case BMA253_SLEEP_DURATION_1_MS:
-		data[0] |= 0x06 << 1;
-		break;
-	case BMA253_SLEEP_DURATION_2_MS:
-		data[0] |= 0x07 << 1;
-		break;
-	case BMA253_SLEEP_DURATION_4_MS:
-		data[0] |= 0x08 << 1;
-		break;
-	case BMA253_SLEEP_DURATION_6_MS:
-		data[0] |= 0x09 << 1;
-		break;
-	case BMA253_SLEEP_DURATION_10_MS:
-		data[0] |= 0x0A << 1;
-		break;
-	case BMA253_SLEEP_DURATION_25_MS:
-		data[0] |= 0x0B << 1;
-		break;
-	case BMA253_SLEEP_DURATION_50_MS:
-		data[0] |= 0x0C << 1;
-		break;
-	case BMA253_SLEEP_DURATION_100_MS:
-		data[0] |= 0x0D << 1;
-		break;
-	case BMA253_SLEEP_DURATION_500_MS:
-		data[0] |= 0x0E << 1;
-		break;
-	case BMA253_SLEEP_DURATION_1_S:
-		data[0] |= 0x0F << 1;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (power_settings->sleep_timer) {
-	case SLEEP_TIMER_EVENT_DRIVEN:
-		data[1] |= 0x00 << 5;
-		break;
-	case SLEEP_TIMER_EQUIDISTANT_SAMPLING:
-		data[1] |= 0x01 << 5;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = set_register(itf, REG_ADDR_PMU_LOW_POWER, data[1]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_PMU_LPW, data[0]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-int bma253_get_data_acquisition(const struct sensor_itf * itf,
-				bool * unfiltered_reg_data,
-				bool * disable_reg_shadow)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_ACCD_HBW, &data);
-	if (rc != 0)
-		return rc;
-
-	*unfiltered_reg_data = data & 0x80;
-	*disable_reg_shadow = data & 0x40;
-
-	return 0;
-}
-
-int bma253_set_data_acquisition(const struct sensor_itf * itf,
-				bool unfiltered_reg_data,
-				bool disable_reg_shadow)
-{
-	uint8_t data;
-
-	data = (unfiltered_reg_data << 7) |
-	       (disable_reg_shadow << 6);
-
-	return set_register(itf, REG_ADDR_ACCD_HBW, data);
-}
-
-int bma253_set_softreset(const struct sensor_itf * itf)
-{
-	return set_register(itf, REG_ADDR_BGW_SOFTRESET, REG_VALUE_SOFT_RESET);
-}
-
-struct int_enable {
-	bool flat_int_enable;
-	bool orient_int_enable;
-	bool s_tap_int_enable;
-	bool d_tap_int_enable;
-	bool slope_z_int_enable;
-	bool slope_y_int_enable;
-	bool slope_x_int_enable;
-	bool fifo_wmark_int_enable;
-	bool fifo_full_int_enable;
-	bool data_int_enable;
-	bool low_g_int_enable;
-	bool high_g_z_int_enable;
-	bool high_g_y_int_enable;
-	bool high_g_x_int_enable;
-	bool no_motion_select;
-	bool slow_no_mot_z_int_enable;
-	bool slow_no_mot_y_int_enable;
-	bool slow_no_mot_x_int_enable;
-};
+int
+bma253_set_filter_bandwidth(const struct bma253 * bma253,
+                            enum bma253_filter_bandwidth filter_bandwidth)
+{
+    uint8_t data;
+
+    switch (filter_bandwidth) {
+    case BMA253_FILTER_BANDWIDTH_7_81_HZ:
+        data = 0x08;
+        break;
+    case BMA253_FILTER_BANDWIDTH_15_63_HZ:
+        data = 0x09;
+        break;
+    case BMA253_FILTER_BANDWIDTH_31_25_HZ:
+        data = 0x0A;
+        break;
+    case BMA253_FILTER_BANDWIDTH_62_5_HZ:
+        data = 0x0B;
+        break;
+    case BMA253_FILTER_BANDWIDTH_125_HZ:
+        data = 0x0C;
+        break;
+    case BMA253_FILTER_BANDWIDTH_250_HZ:
+        data = 0x0D;
+        break;
+    case BMA253_FILTER_BANDWIDTH_500_HZ:
+        data = 0x0E;
+        break;
+    case BMA253_FILTER_BANDWIDTH_1000_HZ:
+        data = 0x0F;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    return set_register(bma253, REG_ADDR_PMU_BW, data);
+}
 
-int bma253_get_int_enable(const struct sensor_itf * itf,
-			  struct int_enable * int_enable)
-{
-	uint8_t data[3];
-	int rc;
-
-	rc = get_registers(itf, REG_ADDR_INT_EN_0,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	int_enable->flat_int_enable = data[0] & 0x80;
-	int_enable->orient_int_enable = data[0] & 0x40;
-	int_enable->s_tap_int_enable = data[0] & 0x20;
-	int_enable->d_tap_int_enable = data[0] & 0x10;
-	int_enable->slope_z_int_enable = data[0] & 0x04;
-	int_enable->slope_y_int_enable = data[0] & 0x02;
-	int_enable->slope_x_int_enable = data[0] & 0x01;
-	int_enable->fifo_wmark_int_enable = data[1] & 0x40;
-	int_enable->fifo_full_int_enable = data[1] & 0x20;
-	int_enable->data_int_enable = data[1] & 0x10;
-	int_enable->low_g_int_enable = data[1] & 0x08;
-	int_enable->high_g_z_int_enable = data[1] & 0x04;
-	int_enable->high_g_y_int_enable = data[1] & 0x02;
-	int_enable->high_g_x_int_enable = data[1] & 0x01;
-	int_enable->no_motion_select = data[2] & 0x08;
-	int_enable->slow_no_mot_z_int_enable = data[2] & 0x04;
-	int_enable->slow_no_mot_y_int_enable = data[2] & 0x02;
-	int_enable->slow_no_mot_x_int_enable = data[2] & 0x01;
-
-	return 0;
-}
-
-int bma253_set_int_enable(const struct sensor_itf * itf,
-			  const struct int_enable * int_enable)
-{
-	uint8_t data[3];
-	int rc;
-
-	data[0] = (int_enable->flat_int_enable << 7) |
-		  (int_enable->orient_int_enable << 6) |
-		  (int_enable->s_tap_int_enable << 5) |
-		  (int_enable->d_tap_int_enable << 4) |
-		  (int_enable->slope_z_int_enable << 2) |
-		  (int_enable->slope_y_int_enable << 1) |
-		  (int_enable->slope_x_int_enable << 0);
-
-	data[1] = (int_enable->fifo_wmark_int_enable << 6) |
-		  (int_enable->fifo_full_int_enable << 5) |
-		  (int_enable->data_int_enable << 4) |
-		  (int_enable->low_g_int_enable << 3) |
-		  (int_enable->high_g_z_int_enable << 2) |
-		  (int_enable->high_g_y_int_enable << 1) |
-		  (int_enable->high_g_x_int_enable << 0);
-
-	data[2] = (int_enable->no_motion_select << 3) |
-		  (int_enable->slow_no_mot_z_int_enable << 2) |
-		  (int_enable->slow_no_mot_y_int_enable << 1) |
-		  (int_enable->slow_no_mot_x_int_enable << 0);
-
-	rc = set_register(itf, REG_ADDR_INT_EN_0, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_EN_1, data[1]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_EN_2, data[2]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-enum int_route {
-	INT_ROUTE_NONE  = 0,
-	INT_ROUTE_PIN_1 = 1,
-	INT_ROUTE_PIN_2 = 2,
-	INT_ROUTE_BOTH  = 3,
-};
+int
+bma253_get_power_settings(const struct bma253 * bma253,
+                          struct power_settings * power_settings)
+{
+    uint8_t data[2];
+    int rc;
+
+    rc = get_registers(bma253, REG_ADDR_PMU_LPW,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    switch ((data[0] >> 5) & 0x07) {
+    default:
+        BMA253_ERROR("unknown PMU_LPW reg value 0x%02X\n", data[0]);
+        power_settings->power_mode = BMA253_POWER_MODE_NORMAL;
+        break;
+    case 0x00:
+        power_settings->power_mode = BMA253_POWER_MODE_NORMAL;
+        break;
+    case 0x01:
+        power_settings->power_mode = BMA253_POWER_MODE_DEEP_SUSPEND;
+        break;
+    case 0x02:
+        if ((data[1] & 0x40) == 0) {
+            power_settings->power_mode = BMA253_POWER_MODE_LPM_1;
+        } else {
+            power_settings->power_mode = BMA253_POWER_MODE_LPM_2;
+        }
+        break;
+    case 0x04:
+        if ((data[1] & 0x40) == 0) {
+            power_settings->power_mode = BMA253_POWER_MODE_SUSPEND;
+        } else {
+            power_settings->power_mode = BMA253_POWER_MODE_STANDBY;
+        }
+        break;
+    }
+
+    switch ((data[0] >> 1) & 0x0F) {
+    case 0x00 ... 0x05:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_0_5_MS;
+        break;
+    case 0x06:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_1_MS;
+        break;
+    case 0x07:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_2_MS;
+        break;
+    case 0x08:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_4_MS;
+        break;
+    case 0x09:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_6_MS;
+        break;
+    case 0x0A:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_10_MS;
+        break;
+    case 0x0B:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_25_MS;
+        break;
+    case 0x0C:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_50_MS;
+        break;
+    case 0x0D:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_100_MS;
+        break;
+    case 0x0E:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_500_MS;
+        break;
+    case 0x0F:
+        power_settings->sleep_duration = BMA253_SLEEP_DURATION_1_S;
+        break;
+    }
+
+    if ((data[1] & 0x20) != 0) {
+        power_settings->sleep_timer = SLEEP_TIMER_EQUIDISTANT_SAMPLING;
+    } else {
+        power_settings->sleep_timer = SLEEP_TIMER_EVENT_DRIVEN;
+    }
+
+    return 0;
+}
 
-struct int_routes {
-	enum int_route flat_int_route;
-	enum int_route orient_int_route;
-	enum int_route s_tap_int_route;
-	enum int_route d_tap_int_route;
-	enum int_route slow_no_mot_int_route;
-	enum int_route slope_int_route;
-	enum int_route high_g_int_route;
-	enum int_route low_g_int_route;
-	enum int_route fifo_wmark_int_route;
-	enum int_route fifo_full_int_route;
-	enum int_route data_int_route;
-};
+int
+bma253_set_power_settings(const struct bma253 * bma253,
+                          const struct power_settings * power_settings)
+{
+    uint8_t data[2];
+    int rc;
+
+    data[0] = 0;
+    data[1] = 0;
+
+    switch (power_settings->power_mode) {
+    case BMA253_POWER_MODE_NORMAL:
+        data[0] |= 0x00 << 5;
+        break;
+    case BMA253_POWER_MODE_DEEP_SUSPEND:
+        data[0] |= 0x01 << 5;
+        break;
+    case BMA253_POWER_MODE_SUSPEND:
+        data[0] |= 0x04 << 5;
+        data[1] |= 0x00 << 6;
+        break;
+    case BMA253_POWER_MODE_STANDBY:
+        data[0] |= 0x04 << 5;
+        data[1] |= 0x01 << 6;
+        break;
+    case BMA253_POWER_MODE_LPM_1:
+        data[0] |= 0x02 << 5;
+        data[1] |= 0x00 << 6;
+        break;
+    case BMA253_POWER_MODE_LPM_2:
+        data[0] |= 0x02 << 5;
+        data[1] |= 0x01 << 6;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (power_settings->sleep_duration) {
+    case BMA253_SLEEP_DURATION_0_5_MS:
+        data[0] |= 0x05 << 1;
+        break;
+    case BMA253_SLEEP_DURATION_1_MS:
+        data[0] |= 0x06 << 1;
+        break;
+    case BMA253_SLEEP_DURATION_2_MS:
+        data[0] |= 0x07 << 1;
+        break;
+    case BMA253_SLEEP_DURATION_4_MS:
+        data[0] |= 0x08 << 1;
+        break;
+    case BMA253_SLEEP_DURATION_6_MS:
+        data[0] |= 0x09 << 1;
+        break;
+    case BMA253_SLEEP_DURATION_10_MS:
+        data[0] |= 0x0A << 1;
+        break;
+    case BMA253_SLEEP_DURATION_25_MS:
+        data[0] |= 0x0B << 1;
+        break;
+    case BMA253_SLEEP_DURATION_50_MS:
+        data[0] |= 0x0C << 1;
+        break;
+    case BMA253_SLEEP_DURATION_100_MS:
+        data[0] |= 0x0D << 1;
+        break;
+    case BMA253_SLEEP_DURATION_500_MS:
+        data[0] |= 0x0E << 1;
+        break;
+    case BMA253_SLEEP_DURATION_1_S:
+        data[0] |= 0x0F << 1;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (power_settings->sleep_timer) {
+    case SLEEP_TIMER_EVENT_DRIVEN:
+        data[1] |= 0x00 << 5;
+        break;
+    case SLEEP_TIMER_EQUIDISTANT_SAMPLING:
+        data[1] |= 0x01 << 5;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = set_register(bma253, REG_ADDR_PMU_LOW_POWER, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_PMU_LPW, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-int bma253_get_int_routes(const struct sensor_itf * itf,
-			  struct int_routes * int_routes)
-{
-	uint8_t data[3];
-	int rc;
-
-	rc = get_registers(itf, REG_ADDR_INT_MAP_0,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	int_routes->flat_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x80) != 0)
-		int_routes->flat_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x80) != 0)
-		int_routes->flat_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->orient_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x40) != 0)
-		int_routes->orient_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x40) != 0)
-		int_routes->orient_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->s_tap_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x20) != 0)
-		int_routes->s_tap_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x20) != 0)
-		int_routes->s_tap_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->d_tap_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x10) != 0)
-		int_routes->d_tap_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x10) != 0)
-		int_routes->d_tap_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->slow_no_mot_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x08) != 0)
-		int_routes->slow_no_mot_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x08) != 0)
-		int_routes->slow_no_mot_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->slope_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x04) != 0)
-		int_routes->slope_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x04) != 0)
-		int_routes->slope_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->high_g_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x02) != 0)
-		int_routes->high_g_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x02) != 0)
-		int_routes->high_g_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->low_g_int_route = INT_ROUTE_NONE;
-	if ((data[0] & 0x01) != 0)
-		int_routes->low_g_int_route |= INT_ROUTE_PIN_1;
-	if ((data[2] & 0x01) != 0)
-		int_routes->low_g_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->fifo_wmark_int_route = INT_ROUTE_NONE;
-	if ((data[1] & 0x02) != 0)
-		int_routes->fifo_wmark_int_route |= INT_ROUTE_PIN_1;
-	if ((data[1] & 0x40) != 0)
-		int_routes->fifo_wmark_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->fifo_full_int_route = INT_ROUTE_NONE;
-	if ((data[1] & 0x04) != 0)
-		int_routes->fifo_full_int_route |= INT_ROUTE_PIN_1;
-	if ((data[1] & 0x20) != 0)
-		int_routes->fifo_full_int_route |= INT_ROUTE_PIN_2;
-
-	int_routes->data_int_route = INT_ROUTE_NONE;
-	if ((data[1] & 0x01) != 0)
-		int_routes->data_int_route |= INT_ROUTE_PIN_1;
-	if ((data[1] & 0x80) != 0)
-		int_routes->data_int_route |= INT_ROUTE_PIN_2;
-
-	return 0;
-}
-
-int bma253_set_int_routes(const struct sensor_itf * itf,
-			  const struct int_routes * int_routes)
-{
-	uint8_t data[3];
-	int rc;
-
-	data[0] = (((int_routes->flat_int_route & INT_ROUTE_PIN_1) != 0) << 7) |
-		  (((int_routes->orient_int_route & INT_ROUTE_PIN_1) != 0) << 6) |
-		  (((int_routes->s_tap_int_route & INT_ROUTE_PIN_1) != 0) << 5) |
-		  (((int_routes->d_tap_int_route & INT_ROUTE_PIN_1) != 0) << 4) |
-		  (((int_routes->slow_no_mot_int_route & INT_ROUTE_PIN_1) != 0) << 3) |
-		  (((int_routes->slope_int_route & INT_ROUTE_PIN_1) != 0) << 2) |
-		  (((int_routes->high_g_int_route & INT_ROUTE_PIN_1) != 0) << 1) |
-		  (((int_routes->low_g_int_route & INT_ROUTE_PIN_1) != 0) << 0);
-
-	data[1] = (((int_routes->data_int_route & INT_ROUTE_PIN_2) != 0) << 7) |
-		  (((int_routes->fifo_wmark_int_route & INT_ROUTE_PIN_2) != 0) << 6) |
-		  (((int_routes->fifo_full_int_route & INT_ROUTE_PIN_2) != 0) << 5) |
-		  (((int_routes->fifo_full_int_route & INT_ROUTE_PIN_1) != 0) << 2) |
-		  (((int_routes->fifo_wmark_int_route & INT_ROUTE_PIN_1) != 0) << 1) |
-		  (((int_routes->data_int_route & INT_ROUTE_PIN_1) != 0) << 0);
-
-	data[2] = (((int_routes->flat_int_route & INT_ROUTE_PIN_2) != 0) << 7) |
-		  (((int_routes->orient_int_route & INT_ROUTE_PIN_2) != 0) << 6) |
-		  (((int_routes->s_tap_int_route & INT_ROUTE_PIN_2) != 0) << 5) |
-		  (((int_routes->d_tap_int_route & INT_ROUTE_PIN_2) != 0) << 4) |
-		  (((int_routes->slow_no_mot_int_route & INT_ROUTE_PIN_2) != 0) << 3) |
-		  (((int_routes->slope_int_route & INT_ROUTE_PIN_2) != 0) << 2) |
-		  (((int_routes->high_g_int_route & INT_ROUTE_PIN_2) != 0) << 1) |
-		  (((int_routes->low_g_int_route & INT_ROUTE_PIN_2) != 0) << 0);
-
-	rc = set_register(itf, REG_ADDR_INT_MAP_0, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_MAP_1, data[1]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_MAP_2, data[2]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-struct int_filters {
-	bool unfiltered_data_int;
-	bool unfiltered_tap_int;
-	bool unfiltered_slow_no_mot_int;
-	bool unfiltered_slope_int;
-	bool unfiltered_high_g_int;
-	bool unfiltered_low_g_int;
-};
+int
+bma253_get_data_acquisition(const struct bma253 * bma253,
+                            bool * unfiltered_reg_data,
+                            bool * disable_reg_shadow)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_ACCD_HBW, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    *unfiltered_reg_data = data & 0x80;
+    *disable_reg_shadow = data & 0x40;
+
+    return 0;
+}
+
+int
+bma253_set_data_acquisition(const struct bma253 * bma253,
+                            bool unfiltered_reg_data,
+                            bool disable_reg_shadow)
+{
+    uint8_t data;
 
-int bma253_get_int_filters(const struct sensor_itf * itf,
-			   struct int_filters * int_filters)
+    data = (unfiltered_reg_data << 7) |
+           (disable_reg_shadow << 6);
+
+    return set_register(bma253, REG_ADDR_ACCD_HBW, data);
+}
+
+int
+bma253_set_softreset(const struct bma253 * bma253)
 {
-	uint8_t data;
-	int rc;
+    int rc;
 
-	rc = get_register(itf, REG_ADDR_INT_SRC, &data);
-	if (rc != 0)
-		return rc;
+    rc = set_register(bma253, REG_ADDR_BGW_SOFTRESET, REG_VALUE_SOFT_RESET);
+    if (rc != 0) {
+        return rc;
+    }
 
-	int_filters->unfiltered_data_int = data & 0x20;
-	int_filters->unfiltered_tap_int = data & 0x10;
-	int_filters->unfiltered_slow_no_mot_int = data & 0x08;
-	int_filters->unfiltered_slope_int = data & 0x04;
-	int_filters->unfiltered_high_g_int = data & 0x02;
-	int_filters->unfiltered_low_g_int = data & 0x01;
+    delay_msec(2);
 
-	return 0;
+    return 0;
 }
 
-int bma253_set_int_filters(const struct sensor_itf * itf,
-			   const struct int_filters * int_filters)
+int
+bma253_get_int_enable(const struct bma253 * bma253,
+                      struct int_enable * int_enable)
 {
-	uint8_t data;
+    uint8_t data[3];
+    int rc;
+
+    rc = get_registers(bma253, REG_ADDR_INT_EN_0,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_enable->flat_int_enable = data[0] & 0x80;
+    int_enable->orient_int_enable = data[0] & 0x40;
+    int_enable->s_tap_int_enable = data[0] & 0x20;
+    int_enable->d_tap_int_enable = data[0] & 0x10;
+    int_enable->slope_z_int_enable = data[0] & 0x04;
+    int_enable->slope_y_int_enable = data[0] & 0x02;
+    int_enable->slope_x_int_enable = data[0] & 0x01;
+    int_enable->fifo_wmark_int_enable = data[1] & 0x40;
+    int_enable->fifo_full_int_enable = data[1] & 0x20;
+    int_enable->data_int_enable = data[1] & 0x10;
+    int_enable->low_g_int_enable = data[1] & 0x08;
+    int_enable->high_g_z_int_enable = data[1] & 0x04;
+    int_enable->high_g_y_int_enable = data[1] & 0x02;
+    int_enable->high_g_x_int_enable = data[1] & 0x01;
+    int_enable->no_motion_select = data[2] & 0x08;
+    int_enable->slow_no_mot_z_int_enable = data[2] & 0x04;
+    int_enable->slow_no_mot_y_int_enable = data[2] & 0x02;
+    int_enable->slow_no_mot_x_int_enable = data[2] & 0x01;
+
+    return 0;
+}
 
-	data = (int_filters->unfiltered_data_int << 5) |
-	       (int_filters->unfiltered_tap_int << 4) |
-	       (int_filters->unfiltered_slow_no_mot_int << 3) |
-	       (int_filters->unfiltered_slope_int << 2) |
-	       (int_filters->unfiltered_high_g_int << 1) |
-	       (int_filters->unfiltered_low_g_int << 0);
+int
+bma253_set_int_enable(const struct bma253 * bma253,
+                      const struct int_enable * int_enable)
+{
+    uint8_t data[3];
+    int rc;
+
+    data[0] = (int_enable->flat_int_enable << 7) |
+              (int_enable->orient_int_enable << 6) |
+              (int_enable->s_tap_int_enable << 5) |
+              (int_enable->d_tap_int_enable << 4) |
+              (int_enable->slope_z_int_enable << 2) |
+              (int_enable->slope_y_int_enable << 1) |
+              (int_enable->slope_x_int_enable << 0);
+
+    data[1] = (int_enable->fifo_wmark_int_enable << 6) |
+              (int_enable->fifo_full_int_enable << 5) |
+              (int_enable->data_int_enable << 4) |
+              (int_enable->low_g_int_enable << 3) |
+              (int_enable->high_g_z_int_enable << 2) |
+              (int_enable->high_g_y_int_enable << 1) |
+              (int_enable->high_g_x_int_enable << 0);
+
+    data[2] = (int_enable->no_motion_select << 3) |
+              (int_enable->slow_no_mot_z_int_enable << 2) |
+              (int_enable->slow_no_mot_y_int_enable << 1) |
+              (int_enable->slow_no_mot_x_int_enable << 0);
+
+    rc = set_register(bma253, REG_ADDR_INT_EN_0, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_EN_1, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_EN_2, data[2]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-	return set_register(itf, REG_ADDR_INT_SRC, data);
+int
+bma253_get_int_routes(const struct bma253 * bma253,
+                      struct int_routes * int_routes)
+{
+    uint8_t data[3];
+    int rc;
+
+    rc = get_registers(bma253, REG_ADDR_INT_MAP_0,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_routes->flat_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x80) != 0) {
+        int_routes->flat_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x80) != 0) {
+        int_routes->flat_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->orient_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x40) != 0) {
+        int_routes->orient_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x40) != 0) {
+        int_routes->orient_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->s_tap_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x20) != 0) {
+        int_routes->s_tap_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x20) != 0) {
+        int_routes->s_tap_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->d_tap_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x10) != 0) {
+        int_routes->d_tap_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x10) != 0) {
+        int_routes->d_tap_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->slow_no_mot_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x08) != 0) {
+        int_routes->slow_no_mot_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x08) != 0) {
+        int_routes->slow_no_mot_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->slope_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x04) != 0) {
+        int_routes->slope_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x04) != 0) {
+        int_routes->slope_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->high_g_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x02) != 0) {
+        int_routes->high_g_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x02) != 0) {
+        int_routes->high_g_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->low_g_int_route = INT_ROUTE_NONE;
+    if ((data[0] & 0x01) != 0) {
+        int_routes->low_g_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[2] & 0x01) != 0) {
+        int_routes->low_g_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->fifo_wmark_int_route = INT_ROUTE_NONE;
+    if ((data[1] & 0x02) != 0) {
+        int_routes->fifo_wmark_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[1] & 0x40) != 0) {
+        int_routes->fifo_wmark_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->fifo_full_int_route = INT_ROUTE_NONE;
+    if ((data[1] & 0x04) != 0) {
+        int_routes->fifo_full_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[1] & 0x20) != 0) {
+        int_routes->fifo_full_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    int_routes->data_int_route = INT_ROUTE_NONE;
+    if ((data[1] & 0x01) != 0) {
+        int_routes->data_int_route |= INT_ROUTE_PIN_1;
+    }
+    if ((data[1] & 0x80) != 0) {
+        int_routes->data_int_route |= INT_ROUTE_PIN_2;
+    }
+
+    return 0;
 }
 
-struct int_pin_electrical {
-	enum bma253_int_pin_output pin1_output;
-	enum bma253_int_pin_active pin1_active;
-	enum bma253_int_pin_output pin2_output;
-	enum bma253_int_pin_active pin2_active;
-};
+int
+bma253_set_int_routes(const struct bma253 * bma253,
+                      const struct int_routes * int_routes)
+{
+    uint8_t data[3];
+    int rc;
+
+    data[0] = (((int_routes->flat_int_route & INT_ROUTE_PIN_1) != 0) << 7) |
+              (((int_routes->orient_int_route & INT_ROUTE_PIN_1) != 0) << 6) |
+              (((int_routes->s_tap_int_route & INT_ROUTE_PIN_1) != 0) << 5) |
+              (((int_routes->d_tap_int_route & INT_ROUTE_PIN_1) != 0) << 4) |
+              (((int_routes->slow_no_mot_int_route & INT_ROUTE_PIN_1) != 0) << 3) |
+              (((int_routes->slope_int_route & INT_ROUTE_PIN_1) != 0) << 2) |
+              (((int_routes->high_g_int_route & INT_ROUTE_PIN_1) != 0) << 1) |
+              (((int_routes->low_g_int_route & INT_ROUTE_PIN_1) != 0) << 0);
+
+    data[1] = (((int_routes->data_int_route & INT_ROUTE_PIN_2) != 0) << 7) |
+              (((int_routes->fifo_wmark_int_route & INT_ROUTE_PIN_2) != 0) << 6) |
+              (((int_routes->fifo_full_int_route & INT_ROUTE_PIN_2) != 0) << 5) |
+              (((int_routes->fifo_full_int_route & INT_ROUTE_PIN_1) != 0) << 2) |
+              (((int_routes->fifo_wmark_int_route & INT_ROUTE_PIN_1) != 0) << 1) |
+              (((int_routes->data_int_route & INT_ROUTE_PIN_1) != 0) << 0);
+
+    data[2] = (((int_routes->flat_int_route & INT_ROUTE_PIN_2) != 0) << 7) |
+              (((int_routes->orient_int_route & INT_ROUTE_PIN_2) != 0) << 6) |
+              (((int_routes->s_tap_int_route & INT_ROUTE_PIN_2) != 0) << 5) |
+              (((int_routes->d_tap_int_route & INT_ROUTE_PIN_2) != 0) << 4) |
+              (((int_routes->slow_no_mot_int_route & INT_ROUTE_PIN_2) != 0) << 3) |
+              (((int_routes->slope_int_route & INT_ROUTE_PIN_2) != 0) << 2) |
+              (((int_routes->high_g_int_route & INT_ROUTE_PIN_2) != 0) << 1) |
+              (((int_routes->low_g_int_route & INT_ROUTE_PIN_2) != 0) << 0);
+
+    rc = set_register(bma253, REG_ADDR_INT_MAP_0, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_MAP_1, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_MAP_2, data[2]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-int bma253_get_int_pin_electrical(const struct sensor_itf * itf,
-				  struct int_pin_electrical * electrical)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_INT_OUT_CTRL, &data);
-	if (rc != 0)
-		return rc;
-
-	if ((data & 0x02) != 0)
-		electrical->pin1_output = BMA253_INT_PIN_OUTPUT_OPEN_DRAIN;
-	else
-		electrical->pin1_output = BMA253_INT_PIN_OUTPUT_PUSH_PULL;
-	if ((data & 0x01) != 0)
-		electrical->pin1_active = BMA253_INT_PIN_ACTIVE_HIGH;
-	else
-		electrical->pin1_active = BMA253_INT_PIN_ACTIVE_LOW;
-	if ((data & 0x08) != 0)
-		electrical->pin2_output = BMA253_INT_PIN_OUTPUT_OPEN_DRAIN;
-	else
-		electrical->pin2_output = BMA253_INT_PIN_OUTPUT_PUSH_PULL;
-	if ((data & 0x04) != 0)
-		electrical->pin2_active = BMA253_INT_PIN_ACTIVE_HIGH;
-	else
-		electrical->pin2_active = BMA253_INT_PIN_ACTIVE_LOW;
-
-	return 0;
-}
-
-int bma253_set_int_pin_electrical(const struct sensor_itf * itf,
-				  const struct int_pin_electrical * electrical)
-{
-	uint8_t data;
-
-	data = 0;
-
-	switch (electrical->pin1_output) {
-	case BMA253_INT_PIN_OUTPUT_OPEN_DRAIN:
-		data |= 0x02;
-		break;
-	case BMA253_INT_PIN_OUTPUT_PUSH_PULL:
-		data |= 0x00;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (electrical->pin1_active) {
-	case BMA253_INT_PIN_ACTIVE_HIGH:
-		data |= 0x01;
-		break;
-	case BMA253_INT_PIN_ACTIVE_LOW:
-		data |= 0x00;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (electrical->pin2_output) {
-	case BMA253_INT_PIN_OUTPUT_OPEN_DRAIN:
-		data |= 0x08;
-		break;
-	case BMA253_INT_PIN_OUTPUT_PUSH_PULL:
-		data |= 0x00;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (electrical->pin2_active) {
-	case BMA253_INT_PIN_ACTIVE_HIGH:
-		data |= 0x04;
-		break;
-	case BMA253_INT_PIN_ACTIVE_LOW:
-		data |= 0x00;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	return set_register(itf, REG_ADDR_INT_OUT_CTRL, data);
-}
-
-enum int_latch {
-	INT_LATCH_NON_LATCHED       = 0,
-	INT_LATCH_LATCHED           = 1,
-	INT_LATCH_TEMPORARY_250_US  = 2,
-	INT_LATCH_TEMPORARY_500_US  = 3,
-	INT_LATCH_TEMPORARY_1_MS    = 4,
-	INT_LATCH_TEMPORARY_12_5_MS = 5,
-	INT_LATCH_TEMPORARY_25_MS   = 6,
-	INT_LATCH_TEMPORARY_50_MS   = 7,
-	INT_LATCH_TEMPORARY_250_MS  = 8,
-	INT_LATCH_TEMPORARY_500_MS  = 9,
-	INT_LATCH_TEMPORARY_1_S     = 10,
-	INT_LATCH_TEMPORARY_2_S     = 11,
-	INT_LATCH_TEMPORARY_4_S     = 12,
-	INT_LATCH_TEMPORARY_8_S     = 13,
-};
+int
+bma253_get_int_filters(const struct bma253 * bma253,
+                       struct int_filters * int_filters)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_INT_SRC, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_filters->unfiltered_data_int = data & 0x20;
+    int_filters->unfiltered_tap_int = data & 0x10;
+    int_filters->unfiltered_slow_no_mot_int = data & 0x08;
+    int_filters->unfiltered_slope_int = data & 0x04;
+    int_filters->unfiltered_high_g_int = data & 0x02;
+    int_filters->unfiltered_low_g_int = data & 0x01;
+
+    return 0;
+}
 
-int bma253_get_int_latch(const struct sensor_itf * itf,
-			 enum int_latch * int_latch)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_INT_RST_LATCH, &data);
-	if (rc != 0)
-		return rc;
-
-	switch (data & 0x0F) {
-	case 0x00:
-		*int_latch = INT_LATCH_NON_LATCHED;
-		break;
-	case 0x01:
-		*int_latch = INT_LATCH_TEMPORARY_250_MS;
-		break;
-	case 0x02:
-		*int_latch = INT_LATCH_TEMPORARY_500_MS;
-		break;
-	case 0x03:
-		*int_latch = INT_LATCH_TEMPORARY_1_S;
-		break;
-	case 0x04:
-		*int_latch = INT_LATCH_TEMPORARY_2_S;
-		break;
-	case 0x05:
-		*int_latch = INT_LATCH_TEMPORARY_4_S;
-		break;
-	case 0x06:
-		*int_latch = INT_LATCH_TEMPORARY_8_S;
-		break;
-	case 0x07:
-		*int_latch = INT_LATCH_LATCHED;
-		break;
-	case 0x08:
-		*int_latch = INT_LATCH_NON_LATCHED;
-		break;
-	case 0x09:
-		*int_latch = INT_LATCH_TEMPORARY_250_US;
-		break;
-	case 0x0A:
-		*int_latch = INT_LATCH_TEMPORARY_500_US;
-		break;
-	case 0x0B:
-		*int_latch = INT_LATCH_TEMPORARY_1_MS;
-		break;
-	case 0x0C:
-		*int_latch = INT_LATCH_TEMPORARY_12_5_MS;
-		break;
-	case 0x0D:
-		*int_latch = INT_LATCH_TEMPORARY_25_MS;
-		break;
-	case 0x0E:
-		*int_latch = INT_LATCH_TEMPORARY_50_MS;
-		break;
-	case 0x0F:
-		*int_latch = INT_LATCH_LATCHED;
-		break;
-	}
-
-	return 0;
-}
-
-int bma253_set_int_latch(const struct sensor_itf * itf,
-			 bool reset_ints,
-			 enum int_latch int_latch)
-{
-	uint8_t data;
-
-	data = 0;
-	data |= reset_ints << 7;
-
-	switch (int_latch) {
-	case INT_LATCH_NON_LATCHED:
-		data |= 0x00;
-		break;
-	case INT_LATCH_LATCHED:
-		data |= 0x0F;
-		break;
-	case INT_LATCH_TEMPORARY_250_US:
-		data |= 0x09;
-		break;
-	case INT_LATCH_TEMPORARY_500_US:
-		data |= 0x0A;
-		break;
-	case INT_LATCH_TEMPORARY_1_MS:
-		data |= 0x0B;
-		break;
-	case INT_LATCH_TEMPORARY_12_5_MS:
-		data |= 0x0C;
-		break;
-	case INT_LATCH_TEMPORARY_25_MS:
-		data |= 0x0D;
-		break;
-	case INT_LATCH_TEMPORARY_50_MS:
-		data |= 0x0E;
-		break;
-	case INT_LATCH_TEMPORARY_250_MS:
-		data |= 0x01;
-		break;
-	case INT_LATCH_TEMPORARY_500_MS:
-		data |= 0x02;
-		break;
-	case INT_LATCH_TEMPORARY_1_S:
-		data |= 0x03;
-		break;
-	case INT_LATCH_TEMPORARY_2_S:
-		data |= 0x04;
-		break;
-	case INT_LATCH_TEMPORARY_4_S:
-		data |= 0x05;
-		break;
-	case INT_LATCH_TEMPORARY_8_S:
-		data |= 0x06;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	return set_register(itf, REG_ADDR_INT_RST_LATCH, data);
-}
-
-struct low_g_int_cfg {
-	uint16_t delay_ms;
-	float thresh_g;
-	float hyster_g;
-	bool axis_summing;
-};
+int
+bma253_set_int_filters(const struct bma253 * bma253,
+                       const struct int_filters * int_filters)
+{
+    uint8_t data;
+
+    data = (int_filters->unfiltered_data_int << 5) |
+           (int_filters->unfiltered_tap_int << 4) |
+           (int_filters->unfiltered_slow_no_mot_int << 3) |
+           (int_filters->unfiltered_slope_int << 2) |
+           (int_filters->unfiltered_high_g_int << 1) |
+           (int_filters->unfiltered_low_g_int << 0);
+
+    return set_register(bma253, REG_ADDR_INT_SRC, data);
+}
 
-int bma253_get_low_g_int_cfg(const struct sensor_itf * itf,
-			     struct low_g_int_cfg * low_g_int_cfg)
+int
+bma253_get_int_pin_electrical(const struct bma253 * bma253,
+                              struct int_pin_electrical * electrical)
 {
-	uint8_t data[3];
-	int rc;
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_INT_OUT_CTRL, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if ((data & 0x02) != 0) {
+        electrical->pin1_output = INT_PIN_OUTPUT_OPEN_DRAIN;
+    } else {
+        electrical->pin1_output = INT_PIN_OUTPUT_PUSH_PULL;
+    }
+    if ((data & 0x01) != 0) {
+        electrical->pin1_active = INT_PIN_ACTIVE_HIGH;
+    } else {
+        electrical->pin1_active = INT_PIN_ACTIVE_LOW;
+    }
+    if ((data & 0x08) != 0) {
+        electrical->pin2_output = INT_PIN_OUTPUT_OPEN_DRAIN;
+    } else {
+        electrical->pin2_output = INT_PIN_OUTPUT_PUSH_PULL;
+    }
+    if ((data & 0x04) != 0) {
+        electrical->pin2_active = INT_PIN_ACTIVE_HIGH;
+    } else {
+        electrical->pin2_active = INT_PIN_ACTIVE_LOW;
+    }
+
+    return 0;
+}
 
-	rc = get_registers(itf, REG_ADDR_INT_0,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
+int
+bma253_set_int_pin_electrical(const struct bma253 * bma253,
+                              const struct int_pin_electrical * electrical)
+{
+    uint8_t data;
+
+    data = 0;
+
+    switch (electrical->pin1_output) {
+    case INT_PIN_OUTPUT_OPEN_DRAIN:
+        data |= 0x02;
+        break;
+    case INT_PIN_OUTPUT_PUSH_PULL:
+        data |= 0x00;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (electrical->pin1_active) {
+    case INT_PIN_ACTIVE_HIGH:
+        data |= 0x01;
+        break;
+    case INT_PIN_ACTIVE_LOW:
+        data |= 0x00;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (electrical->pin2_output) {
+    case INT_PIN_OUTPUT_OPEN_DRAIN:
+        data |= 0x08;
+        break;
+    case INT_PIN_OUTPUT_PUSH_PULL:
+        data |= 0x00;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (electrical->pin2_active) {
+    case INT_PIN_ACTIVE_HIGH:
+        data |= 0x04;
+        break;
+    case INT_PIN_ACTIVE_LOW:
+        data |= 0x00;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    return set_register(bma253, REG_ADDR_INT_OUT_CTRL, data);
+}
 
-	low_g_int_cfg->delay_ms = (data[0] + 1) << 1;
-	low_g_int_cfg->thresh_g = (float)data[1] * 0.00781;
-	low_g_int_cfg->hyster_g = (float)(data[2] & 0x03) * 0.125;
-	low_g_int_cfg->axis_summing = data[2] & 0x04;
+int
+bma253_get_int_latch(const struct bma253 * bma253,
+                     enum int_latch * int_latch)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_INT_RST_LATCH, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    switch (data & 0x0F) {
+    case 0x00:
+        *int_latch = INT_LATCH_NON_LATCHED;
+        break;
+    case 0x01:
+        *int_latch = INT_LATCH_TEMPORARY_250_MS;
+        break;
+    case 0x02:
+        *int_latch = INT_LATCH_TEMPORARY_500_MS;
+        break;
+    case 0x03:
+        *int_latch = INT_LATCH_TEMPORARY_1_S;
+        break;
+    case 0x04:
+        *int_latch = INT_LATCH_TEMPORARY_2_S;
+        break;
+    case 0x05:
+        *int_latch = INT_LATCH_TEMPORARY_4_S;
+        break;
+    case 0x06:
+        *int_latch = INT_LATCH_TEMPORARY_8_S;
+        break;
+    case 0x07:
+        *int_latch = INT_LATCH_LATCHED;
+        break;
+    case 0x08:
+        *int_latch = INT_LATCH_NON_LATCHED;
+        break;
+    case 0x09:
+        *int_latch = INT_LATCH_TEMPORARY_250_US;
+        break;
+    case 0x0A:
+        *int_latch = INT_LATCH_TEMPORARY_500_US;
+        break;
+    case 0x0B:
+        *int_latch = INT_LATCH_TEMPORARY_1_MS;
+        break;
+    case 0x0C:
+        *int_latch = INT_LATCH_TEMPORARY_12_5_MS;
+        break;
+    case 0x0D:
+        *int_latch = INT_LATCH_TEMPORARY_25_MS;
+        break;
+    case 0x0E:
+        *int_latch = INT_LATCH_TEMPORARY_50_MS;
+        break;
+    case 0x0F:
+        *int_latch = INT_LATCH_LATCHED;
+        break;
+    }
+
+    return 0;
+}
 
-	return 0;
+int
+bma253_set_int_latch(const struct bma253 * bma253,
+                     bool reset_ints,
+                     enum int_latch int_latch)
+{
+    uint8_t data;
+
+    data = 0;
+    data |= reset_ints << 7;
+
+    switch (int_latch) {
+    case INT_LATCH_NON_LATCHED:
+        data |= 0x00;
+        break;
+    case INT_LATCH_LATCHED:
+        data |= 0x0F;
+        break;
+    case INT_LATCH_TEMPORARY_250_US:
+        data |= 0x09;
+        break;
+    case INT_LATCH_TEMPORARY_500_US:
+        data |= 0x0A;
+        break;
+    case INT_LATCH_TEMPORARY_1_MS:
+        data |= 0x0B;
+        break;
+    case INT_LATCH_TEMPORARY_12_5_MS:
+        data |= 0x0C;
+        break;
+    case INT_LATCH_TEMPORARY_25_MS:
+        data |= 0x0D;
+        break;
+    case INT_LATCH_TEMPORARY_50_MS:
+        data |= 0x0E;
+        break;
+    case INT_LATCH_TEMPORARY_250_MS:
+        data |= 0x01;
+        break;
+    case INT_LATCH_TEMPORARY_500_MS:
+        data |= 0x02;
+        break;
+    case INT_LATCH_TEMPORARY_1_S:
+        data |= 0x03;
+        break;
+    case INT_LATCH_TEMPORARY_2_S:
+        data |= 0x04;
+        break;
+    case INT_LATCH_TEMPORARY_4_S:
+        data |= 0x05;
+        break;
+    case INT_LATCH_TEMPORARY_8_S:
+        data |= 0x06;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    return set_register(bma253, REG_ADDR_INT_RST_LATCH, data);
 }
 
-int bma253_set_low_g_int_cfg(const struct sensor_itf * itf,
-			     const struct low_g_int_cfg * low_g_int_cfg)
+int
+bma253_get_low_g_int_cfg(const struct bma253 * bma253,
+                         struct low_g_int_cfg * low_g_int_cfg)
 {
-	uint8_t data[3];
-	int rc;
+    uint8_t data[3];
+    int rc;
 
-	if (low_g_int_cfg->delay_ms < 2 ||
-	    low_g_int_cfg->delay_ms > 512)
-		return SYS_EINVAL;
-	if (low_g_int_cfg->thresh_g < 0.0 ||
-	    low_g_int_cfg->thresh_g > 1.992)
-		return SYS_EINVAL;
-	if (low_g_int_cfg->hyster_g < 0.0 ||
-	    low_g_int_cfg->hyster_g > 0.375)
-		return SYS_EINVAL;
+    rc = get_registers(bma253, REG_ADDR_INT_0,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
 
-	data[0] = (low_g_int_cfg->delay_ms >> 1) - 1;
-	data[1] = low_g_int_cfg->thresh_g / 0.00781;
-	data[2] = (low_g_int_cfg->axis_summing << 2) |
-		  (((uint8_t)(low_g_int_cfg->hyster_g / 0.125) & 0x03) << 0);
+    low_g_int_cfg->delay_ms = (data[0] + 1) << 1;
+    low_g_int_cfg->thresh_g = (float)data[1] * 0.00781;
+    low_g_int_cfg->hyster_g = (float)(data[2] & 0x03) * 0.125;
+    low_g_int_cfg->axis_summing = data[2] & 0x04;
 
-	rc = set_register(itf, REG_ADDR_INT_0, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_1, data[1]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_2, data[2]);
-	if (rc != 0)
-		return rc;
+    return 0;
+}
 
-	return 0;
+int
+bma253_set_low_g_int_cfg(const struct bma253 * bma253,
+                         const struct low_g_int_cfg * low_g_int_cfg)
+{
+    uint8_t data[3];
+    int rc;
+
+    if (low_g_int_cfg->delay_ms < 2 ||
+        low_g_int_cfg->delay_ms > 512) {
+        return SYS_EINVAL;
+    }
+    if (low_g_int_cfg->thresh_g < 0.0 ||
+        low_g_int_cfg->thresh_g > 1.992) {
+        return SYS_EINVAL;
+    }
+    if (low_g_int_cfg->hyster_g < 0.0 ||
+        low_g_int_cfg->hyster_g > 0.375) {
+        return SYS_EINVAL;
+    }
+
+    data[0] = (low_g_int_cfg->delay_ms >> 1) - 1;
+    data[1] = low_g_int_cfg->thresh_g / 0.00781;
+    data[2] = (low_g_int_cfg->axis_summing << 2) |
+              (((uint8_t)(low_g_int_cfg->hyster_g / 0.125) & 0x03) << 0);
+
+    rc = set_register(bma253, REG_ADDR_INT_0, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_1, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_2, data[2]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
 }
 
-struct high_g_int_cfg {
-	float hyster_g;
-	uint16_t delay_ms;
-	float thresh_g;
-};
+int
+bma253_get_high_g_int_cfg(const struct bma253 * bma253,
+                          enum bma253_g_range g_range,
+                          struct high_g_int_cfg * high_g_int_cfg)
+{
+    float hyster_scale;
+    float thresh_scale;
+    uint8_t data[3];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        hyster_scale = 0.125;
+        thresh_scale = 0.00781;
+        break;
+    case BMA253_G_RANGE_4:
+        hyster_scale = 0.25;
+        thresh_scale = 0.01563;
+        break;
+    case BMA253_G_RANGE_8:
+        hyster_scale = 0.5;
+        thresh_scale = 0.03125;
+        break;
+    case BMA253_G_RANGE_16:
+        hyster_scale = 1.0;
+        thresh_scale = 0.0625;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = get_registers(bma253, REG_ADDR_INT_2,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    high_g_int_cfg->hyster_g = (float)((data[0] >> 6) & 0x03) * hyster_scale;
+    high_g_int_cfg->delay_ms = (data[1] + 1) << 1;
+    high_g_int_cfg->thresh_g = (float)data[2] * thresh_scale;
+
+    return 0;
+}
 
-int bma253_get_high_g_int_cfg(const struct sensor_itf * itf,
-			      enum bma253_g_range g_range,
-			      struct high_g_int_cfg * high_g_int_cfg)
-{
-	float hyster_scale;
-	float thresh_scale;
-	uint8_t data[3];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		hyster_scale = 0.125;
-		thresh_scale = 0.00781;
-		break;
-	case BMA253_G_RANGE_4:
-		hyster_scale = 0.25;
-		thresh_scale = 0.01563;
-		break;
-	case BMA253_G_RANGE_8:
-		hyster_scale = 0.5;
-		thresh_scale = 0.03125;
-		break;
-	case BMA253_G_RANGE_16:
-		hyster_scale = 1.0;
-		thresh_scale = 0.0625;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = get_registers(itf, REG_ADDR_INT_2,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	high_g_int_cfg->hyster_g = (float)((data[0] >> 6) & 0x03) * hyster_scale;
-	high_g_int_cfg->delay_ms = (data[1] + 1) << 1;
-	high_g_int_cfg->thresh_g = (float)data[2] * thresh_scale;
-
-	return 0;
-}
-
-int bma253_set_high_g_int_cfg(const struct sensor_itf * itf,
-			      enum bma253_g_range g_range,
-			      const struct high_g_int_cfg * high_g_int_cfg)
-{
-	float hyster_scale;
-	float thresh_scale;
-	uint8_t data[3];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		hyster_scale = 0.125;
-		thresh_scale = 0.00781;
-		break;
-	case BMA253_G_RANGE_4:
-		hyster_scale = 0.25;
-		thresh_scale = 0.01563;
-		break;
-	case BMA253_G_RANGE_8:
-		hyster_scale = 0.5;
-		thresh_scale = 0.03125;
-		break;
-	case BMA253_G_RANGE_16:
-		hyster_scale = 1.0;
-		thresh_scale = 0.0625;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	if (high_g_int_cfg->hyster_g < 0.0 ||
-	    high_g_int_cfg->hyster_g > hyster_scale * 3.0)
-		return SYS_EINVAL;
-	if (high_g_int_cfg->delay_ms < 2 ||
-	    high_g_int_cfg->delay_ms > 512)
-		return SYS_EINVAL;
-	if (high_g_int_cfg->thresh_g < 0.0 ||
-	    high_g_int_cfg->thresh_g > thresh_scale * 255.0)
-		return SYS_EINVAL;
-
-	data[0] = ((uint8_t)(high_g_int_cfg->hyster_g / hyster_scale) & 0x03) << 6;
-	data[1] = (high_g_int_cfg->delay_ms >> 1) - 1;
-	data[2] = high_g_int_cfg->thresh_g / thresh_scale;
-
-	rc = set_register(itf, REG_ADDR_INT_2, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_3, data[1]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_4, data[2]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-struct slow_no_mot_int_cfg {
-	uint16_t duration_p_or_s;
-	float thresh_g;
-};
+int
+bma253_set_high_g_int_cfg(const struct bma253 * bma253,
+                          enum bma253_g_range g_range,
+                          const struct high_g_int_cfg * high_g_int_cfg)
+{
+    float hyster_scale;
+    float thresh_scale;
+    uint8_t data[3];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        hyster_scale = 0.125;
+        thresh_scale = 0.00781;
+        break;
+    case BMA253_G_RANGE_4:
+        hyster_scale = 0.25;
+        thresh_scale = 0.01563;
+        break;
+    case BMA253_G_RANGE_8:
+        hyster_scale = 0.5;
+        thresh_scale = 0.03125;
+        break;
+    case BMA253_G_RANGE_16:
+        hyster_scale = 1.0;
+        thresh_scale = 0.0625;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    if (high_g_int_cfg->hyster_g < 0.0 ||
+        high_g_int_cfg->hyster_g > hyster_scale * 3.0) {
+        return SYS_EINVAL;
+    }
+    if (high_g_int_cfg->delay_ms < 2 ||
+        high_g_int_cfg->delay_ms > 512) {
+        return SYS_EINVAL;
+    }
+    if (high_g_int_cfg->thresh_g < 0.0 ||
+        high_g_int_cfg->thresh_g > thresh_scale * 255.0) {
+        return SYS_EINVAL;
+    }
+
+    data[0] = ((uint8_t)(high_g_int_cfg->hyster_g / hyster_scale) & 0x03) << 6;
+    data[1] = (high_g_int_cfg->delay_ms >> 1) - 1;
+    data[2] = high_g_int_cfg->thresh_g / thresh_scale;
+
+    rc = set_register(bma253, REG_ADDR_INT_2, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_3, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_4, data[2]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-int bma253_get_slow_no_mot_int_cfg(const struct sensor_itf * itf,
-				   bool no_motion_select,
-				   enum bma253_g_range g_range,
-				   struct slow_no_mot_int_cfg * slow_no_mot_int_cfg)
-{
-	float thresh_scale;
-	uint8_t data[2];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		thresh_scale = 0.00391;
-		break;
-	case BMA253_G_RANGE_4:
-		thresh_scale = 0.00781;
-		break;
-	case BMA253_G_RANGE_8:
-		thresh_scale = 0.01563;
-		break;
-	case BMA253_G_RANGE_16:
-		thresh_scale = 0.03125;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = get_register(itf, REG_ADDR_INT_5, data + 0);
-	if (rc != 0)
-		return rc;
-	rc = get_register(itf, REG_ADDR_INT_7, data + 1);
-	if (rc != 0)
-		return rc;
-
-	if (no_motion_select)
-		if ((data[0] & 0x80) == 0)
-			if ((data[0] & 0x40) == 0)
-				slow_no_mot_int_cfg->duration_p_or_s =
-					((data[0] >> 2) & 0x0F) + 1;
-			else
-				slow_no_mot_int_cfg->duration_p_or_s =
-					(((data[0] >> 2) & 0x0F) << 2) + 20;
-		else
-			slow_no_mot_int_cfg->duration_p_or_s =
-				(((data[0] >> 2) & 0x1F) << 3) + 88;
-	else
-		slow_no_mot_int_cfg->duration_p_or_s =
-			((data[0] >> 2) & 0x03) + 1;
-	slow_no_mot_int_cfg->thresh_g = (float)data[1] * thresh_scale;
-
-	return 0;
-}
-
-int bma253_set_slow_no_mot_int_cfg(const struct sensor_itf * itf,
-				   bool no_motion_select,
-				   enum bma253_g_range g_range,
-				   const struct slow_no_mot_int_cfg * slow_no_mot_int_cfg)
-{
-	float thresh_scale;
-	uint8_t data[2];
-	uint16_t duration;
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		thresh_scale = 0.00391;
-		break;
-	case BMA253_G_RANGE_4:
-		thresh_scale = 0.00781;
-		break;
-	case BMA253_G_RANGE_8:
-		thresh_scale = 0.01563;
-		break;
-	case BMA253_G_RANGE_16:
-		thresh_scale = 0.03125;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	if (no_motion_select) {
-		if (slow_no_mot_int_cfg->duration_p_or_s < 1 ||
-		    slow_no_mot_int_cfg->duration_p_or_s > 336)
-			return SYS_EINVAL;
-	} else {
-		if (slow_no_mot_int_cfg->duration_p_or_s < 1 ||
-		    slow_no_mot_int_cfg->duration_p_or_s > 4)
-			return SYS_EINVAL;
-	}
-	if (slow_no_mot_int_cfg->thresh_g < 0.0 ||
-	    slow_no_mot_int_cfg->thresh_g > thresh_scale * 255.0)
-		return SYS_EINVAL;
-
-	duration = slow_no_mot_int_cfg->duration_p_or_s;
-	if (no_motion_select) {
-		if (duration > 80) {
-			if (duration < 88)
-				duration = 88;
-			data[0] = (((duration - 88) >> 3) << 2) | 0x80;
-		} else if (duration > 16) {
-			if (duration < 20)
-				duration = 20;
-			data[0] = (((duration - 20) >> 2) << 2) | 0x40;
-		} else {
-			data[0] = (duration - 1) << 2;
-		}
-	} else {
-		data[0] = (duration - 1) << 2;
-	}
-	data[1] = slow_no_mot_int_cfg->thresh_g / thresh_scale;
-
-	rc = set_register(itf, REG_ADDR_INT_5, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_7, data[1]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-struct slope_int_cfg {
-	uint8_t duration_p;
-	float thresh_g;
-};
+int
+bma253_get_slow_no_mot_int_cfg(const struct bma253 * bma253,
+                               bool no_motion_select,
+                               enum bma253_g_range g_range,
+                               struct slow_no_mot_int_cfg * slow_no_mot_int_cfg)
+{
+    float thresh_scale;
+    uint8_t data[2];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        thresh_scale = 0.00391;
+        break;
+    case BMA253_G_RANGE_4:
+        thresh_scale = 0.00781;
+        break;
+    case BMA253_G_RANGE_8:
+        thresh_scale = 0.01563;
+        break;
+    case BMA253_G_RANGE_16:
+        thresh_scale = 0.03125;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = get_register(bma253, REG_ADDR_INT_5, data + 0);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = get_register(bma253, REG_ADDR_INT_7, data + 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (no_motion_select) {
+        if ((data[0] & 0x80) == 0) {
+            if ((data[0] & 0x40) == 0) {
+                slow_no_mot_int_cfg->duration_p_or_s =
+                    ((data[0] >> 2) & 0x0F) + 1;
+            } else {
+                slow_no_mot_int_cfg->duration_p_or_s =
+                    (((data[0] >> 2) & 0x0F) << 2) + 20;
+            }
+        } else {
+            slow_no_mot_int_cfg->duration_p_or_s =
+                (((data[0] >> 2) & 0x1F) << 3) + 88;
+        }
+    } else {
+        slow_no_mot_int_cfg->duration_p_or_s =
+            ((data[0] >> 2) & 0x03) + 1;
+    }
+    slow_no_mot_int_cfg->thresh_g = (float)data[1] * thresh_scale;
+
+    return 0;
+}
 
-int bma253_get_slope_int_cfg(const struct sensor_itf * itf,
-			     enum bma253_g_range g_range,
-			     struct slope_int_cfg * slope_int_cfg)
-{
-	float thresh_scale;
-	uint8_t data[2];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		thresh_scale = 0.00391;
-		break;
-	case BMA253_G_RANGE_4:
-		thresh_scale = 0.00781;
-		break;
-	case BMA253_G_RANGE_8:
-		thresh_scale = 0.01563;
-		break;
-	case BMA253_G_RANGE_16:
-		thresh_scale = 0.03125;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = get_registers(itf, REG_ADDR_INT_5,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	slope_int_cfg->duration_p = (data[0] & 0x03) + 1;
-	slope_int_cfg->thresh_g = (float)data[1] * thresh_scale;
-
-	return 0;
-}
-
-int bma253_set_slope_int_cfg(const struct sensor_itf * itf,
-			     enum bma253_g_range g_range,
-			     const struct slope_int_cfg * slope_int_cfg)
-{
-	float thresh_scale;
-	uint8_t data[2];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		thresh_scale = 0.00391;
-		break;
-	case BMA253_G_RANGE_4:
-		thresh_scale = 0.00781;
-		break;
-	case BMA253_G_RANGE_8:
-		thresh_scale = 0.01563;
-		break;
-	case BMA253_G_RANGE_16:
-		thresh_scale = 0.03125;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	if (slope_int_cfg->duration_p < 1 ||
-	    slope_int_cfg->duration_p > 4)
-		return SYS_EINVAL;
-	if (slope_int_cfg->thresh_g < 0.0 ||
-	    slope_int_cfg->thresh_g > thresh_scale * 255.0)
-		return SYS_EINVAL;
-
-	data[0] = (slope_int_cfg->duration_p - 1) & 0x03;
-	data[1] = slope_int_cfg->thresh_g / thresh_scale;
-
-	rc = set_register(itf, REG_ADDR_INT_5, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_6, data[1]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-struct tap_int_cfg {
-	enum bma253_tap_quiet tap_quiet;
-	enum bma253_tap_shock tap_shock;
-	enum bma253_d_tap_window d_tap_window;
-	enum bma253_tap_wake_samples tap_wake_samples;
-	float thresh_g;
-};
+int
+bma253_set_slow_no_mot_int_cfg(const struct bma253 * bma253,
+                               bool no_motion_select,
+                               enum bma253_g_range g_range,
+                               const struct slow_no_mot_int_cfg * slow_no_mot_int_cfg)
+{
+    float thresh_scale;
+    uint8_t data[2];
+    uint16_t duration;
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        thresh_scale = 0.00391;
+        break;
+    case BMA253_G_RANGE_4:
+        thresh_scale = 0.00781;
+        break;
+    case BMA253_G_RANGE_8:
+        thresh_scale = 0.01563;
+        break;
+    case BMA253_G_RANGE_16:
+        thresh_scale = 0.03125;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    if (no_motion_select) {
+        if (slow_no_mot_int_cfg->duration_p_or_s < 1 ||
+            slow_no_mot_int_cfg->duration_p_or_s > 336) {
+            return SYS_EINVAL;
+        }
+    } else {
+        if (slow_no_mot_int_cfg->duration_p_or_s < 1 ||
+            slow_no_mot_int_cfg->duration_p_or_s > 4) {
+            return SYS_EINVAL;
+        }
+    }
+    if (slow_no_mot_int_cfg->thresh_g < 0.0 ||
+        slow_no_mot_int_cfg->thresh_g > thresh_scale * 255.0) {
+        return SYS_EINVAL;
+    }
+
+    duration = slow_no_mot_int_cfg->duration_p_or_s;
+    if (no_motion_select) {
+        if (duration > 80) {
+            if (duration < 88) {
+                duration = 88;
+            }
+            data[0] = (((duration - 88) >> 3) << 2) | 0x80;
+        } else if (duration > 16) {
+            if (duration < 20) {
+                duration = 20;
+            }
+            data[0] = (((duration - 20) >> 2) << 2) | 0x40;
+        } else {
+            data[0] = (duration - 1) << 2;
+        }
+    } else {
+        data[0] = (duration - 1) << 2;
+    }
+    data[1] = slow_no_mot_int_cfg->thresh_g / thresh_scale;
+
+    rc = set_register(bma253, REG_ADDR_INT_5, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_7, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-int bma253_get_tap_int_cfg(const struct sensor_itf * itf,
-			   enum bma253_g_range g_range,
-			   struct tap_int_cfg * tap_int_cfg)
-{
-	float thresh_scale;
-	uint8_t data[2];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		thresh_scale = 0.0625;
-		break;
-	case BMA253_G_RANGE_4:
-		thresh_scale = 0.125;
-		break;
-	case BMA253_G_RANGE_8:
-		thresh_scale = 0.25;
-		break;
-	case BMA253_G_RANGE_16:
-		thresh_scale = 0.5;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = get_registers(itf, REG_ADDR_INT_8,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	if ((data[0] & 0x80) == 0)
-		tap_int_cfg->tap_quiet = BMA253_TAP_QUIET_30_MS;
-	else
-		tap_int_cfg->tap_quiet = BMA253_TAP_QUIET_20_MS;
-	if ((data[0] & 0x40) == 0)
-		tap_int_cfg->tap_shock = BMA253_TAP_SHOCK_50_MS;
-	else
-		tap_int_cfg->tap_shock = BMA253_TAP_SHOCK_75_MS;
-
-	switch (data[0] & 0x07) {
-	case 0x00:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_50_MS;
-		break;
-	case 0x01:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_100_MS;
-		break;
-	case 0x02:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_150_MS;
-		break;
-	case 0x03:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_200_MS;
-		break;
-	case 0x04:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_250_MS;
-		break;
-	case 0x05:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_375_MS;
-		break;
-	case 0x06:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_500_MS;
-		break;
-	case 0x07:
-		tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_700_MS;
-		break;
-	}
-
-	switch ((data[1] >> 6) & 0x03) {
-	case 0x00:
-		tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_2;
-		break;
-	case 0x01:
-		tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_4;
-		break;
-	case 0x02:
-		tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_8;
-		break;
-	case 0x03:
-		tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_16;
-		break;
-	}
-
-	tap_int_cfg->thresh_g = (float)(data[1] & 0x1F) * thresh_scale;
-
-	return 0;
-}
-
-int bma253_set_tap_int_cfg(const struct sensor_itf * itf,
-			   enum bma253_g_range g_range,
-			   const struct tap_int_cfg * tap_int_cfg)
-{
-	float thresh_scale;
-	uint8_t data[2];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		thresh_scale = 0.0625;
-		break;
-	case BMA253_G_RANGE_4:
-		thresh_scale = 0.125;
-		break;
-	case BMA253_G_RANGE_8:
-		thresh_scale = 0.25;
-		break;
-	case BMA253_G_RANGE_16:
-		thresh_scale = 0.5;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	if (tap_int_cfg->thresh_g < 0.0 ||
-	    tap_int_cfg->thresh_g > thresh_scale * 31.0)
-		return SYS_EINVAL;
-
-	data[0] = 0;
-	data[1] = 0;
-
-	switch (tap_int_cfg->tap_quiet) {
-	case BMA253_TAP_QUIET_20_MS:
-		data[0] |= 0x80;
-		break;
-	case BMA253_TAP_QUIET_30_MS:
-		data[0] |= 0x00;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (tap_int_cfg->tap_shock) {
-	case BMA253_TAP_SHOCK_50_MS:
-		data[0] |= 0x00;
-		break;
-	case BMA253_TAP_SHOCK_75_MS:
-		data[0] |= 0x40;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (tap_int_cfg->d_tap_window) {
-	case BMA253_D_TAP_WINDOW_50_MS:
-		data[0] |= 0x00;
-		break;
-	case BMA253_D_TAP_WINDOW_100_MS:
-		data[0] |= 0x01;
-		break;
-	case BMA253_D_TAP_WINDOW_150_MS:
-		data[0] |= 0x02;
-		break;
-	case BMA253_D_TAP_WINDOW_200_MS:
-		data[0] |= 0x03;
-		break;
-	case BMA253_D_TAP_WINDOW_250_MS:
-		data[0] |= 0x04;
-		break;
-	case BMA253_D_TAP_WINDOW_375_MS:
-		data[0] |= 0x05;
-		break;
-	case BMA253_D_TAP_WINDOW_500_MS:
-		data[0] |= 0x06;
-		break;
-	case BMA253_D_TAP_WINDOW_700_MS:
-		data[0] |= 0x07;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (tap_int_cfg->tap_wake_samples) {
-	case BMA253_TAP_WAKE_SAMPLES_2:
-		data[1] |= 0x00 << 6;
-		break;
-	case BMA253_TAP_WAKE_SAMPLES_4:
-		data[1] |= 0x01 << 6;
-		break;
-	case BMA253_TAP_WAKE_SAMPLES_8:
-		data[1] |= 0x02 << 6;
-		break;
-	case BMA253_TAP_WAKE_SAMPLES_16:
-		data[1] |= 0x03 << 6;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	data[1] |= (uint8_t)(tap_int_cfg->thresh_g / thresh_scale) & 0x1F;
-
-	rc = set_register(itf, REG_ADDR_INT_8, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_9, data[1]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-enum orient_blocking {
-	ORIENT_BLOCKING_NONE                       = 0,
-	ORIENT_BLOCKING_ACCEL_ONLY                 = 1,
-	ORIENT_BLOCKING_ACCEL_AND_SLOPE            = 2,
-	ORIENT_BLOCKING_ACCEL_AND_SLOPE_AND_STABLE = 3,
-};
+int
+bma253_get_slope_int_cfg(const struct bma253 * bma253,
+                         enum bma253_g_range g_range,
+                         struct slope_int_cfg * slope_int_cfg)
+{
+    float thresh_scale;
+    uint8_t data[2];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        thresh_scale = 0.00391;
+        break;
+    case BMA253_G_RANGE_4:
+        thresh_scale = 0.00781;
+        break;
+    case BMA253_G_RANGE_8:
+        thresh_scale = 0.01563;
+        break;
+    case BMA253_G_RANGE_16:
+        thresh_scale = 0.03125;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = get_registers(bma253, REG_ADDR_INT_5,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    slope_int_cfg->duration_p = (data[0] & 0x03) + 1;
+    slope_int_cfg->thresh_g = (float)data[1] * thresh_scale;
+
+    return 0;
+}
 
-enum orient_mode {
-	ORIENT_MODE_SYMMETRICAL       = 0,
-	ORIENT_MODE_HIGH_ASYMMETRICAL = 1,
-	ORIENT_MODE_LOW_ASYMMETRICAL  = 2,
-};
+int
+bma253_set_slope_int_cfg(const struct bma253 * bma253,
+                         enum bma253_g_range g_range,
+                         const struct slope_int_cfg * slope_int_cfg)
+{
+    float thresh_scale;
+    uint8_t data[2];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        thresh_scale = 0.00391;
+        break;
+    case BMA253_G_RANGE_4:
+        thresh_scale = 0.00781;
+        break;
+    case BMA253_G_RANGE_8:
+        thresh_scale = 0.01563;
+        break;
+    case BMA253_G_RANGE_16:
+        thresh_scale = 0.03125;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    if (slope_int_cfg->duration_p < 1 ||
+        slope_int_cfg->duration_p > 4) {
+        return SYS_EINVAL;
+    }
+    if (slope_int_cfg->thresh_g < 0.0 ||
+        slope_int_cfg->thresh_g > thresh_scale * 255.0) {
+        return SYS_EINVAL;
+    }
+
+    data[0] = (slope_int_cfg->duration_p - 1) & 0x03;
+    data[1] = slope_int_cfg->thresh_g / thresh_scale;
+
+    rc = set_register(bma253, REG_ADDR_INT_5, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_6, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-struct orient_int_cfg {
-	float hyster_g;
-	enum orient_blocking orient_blocking;
-	enum orient_mode orient_mode;
-	bool signal_up_down;
-	uint8_t blocking_angle;
-};
+int
+bma253_get_tap_int_cfg(const struct bma253 * bma253,
+                       enum bma253_g_range g_range,
+                       struct tap_int_cfg * tap_int_cfg)
+{
+    float thresh_scale;
+    uint8_t data[2];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        thresh_scale = 0.0625;
+        break;
+    case BMA253_G_RANGE_4:
+        thresh_scale = 0.125;
+        break;
+    case BMA253_G_RANGE_8:
+        thresh_scale = 0.25;
+        break;
+    case BMA253_G_RANGE_16:
+        thresh_scale = 0.5;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = get_registers(bma253, REG_ADDR_INT_8,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    if ((data[0] & 0x80) == 0) {
+        tap_int_cfg->tap_quiet = BMA253_TAP_QUIET_30_MS;
+    } else {
+        tap_int_cfg->tap_quiet = BMA253_TAP_QUIET_20_MS;
+    }
+    if ((data[0] & 0x40) == 0) {
+        tap_int_cfg->tap_shock = BMA253_TAP_SHOCK_50_MS;
+    } else {
+        tap_int_cfg->tap_shock = BMA253_TAP_SHOCK_75_MS;
+    }
+
+    switch (data[0] & 0x07) {
+    case 0x00:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_50_MS;
+        break;
+    case 0x01:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_100_MS;
+        break;
+    case 0x02:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_150_MS;
+        break;
+    case 0x03:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_200_MS;
+        break;
+    case 0x04:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_250_MS;
+        break;
+    case 0x05:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_375_MS;
+        break;
+    case 0x06:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_500_MS;
+        break;
+    case 0x07:
+        tap_int_cfg->d_tap_window = BMA253_D_TAP_WINDOW_700_MS;
+        break;
+    }
+
+    switch ((data[1] >> 6) & 0x03) {
+    case 0x00:
+        tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_2;
+        break;
+    case 0x01:
+        tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_4;
+        break;
+    case 0x02:
+        tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_8;
+        break;
+    case 0x03:
+        tap_int_cfg->tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_16;
+        break;
+    }
+
+    tap_int_cfg->thresh_g = (float)(data[1] & 0x1F) * thresh_scale;
+
+    return 0;
+}
 
-int bma253_get_orient_int_cfg(const struct sensor_itf * itf,
-			      struct orient_int_cfg * orient_int_cfg)
-{
-	uint8_t data[2];
-	int rc;
-
-	rc = get_registers(itf, REG_ADDR_INT_A,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	orient_int_cfg->hyster_g = (float)((data[0] >> 4) & 0x07) * 0.0625;
-
-	switch ((data[0] >> 2) & 0x03) {
-	case 0x00:
-		orient_int_cfg->orient_blocking =
-			ORIENT_BLOCKING_NONE;
-		break;
-	case 0x01:
-		orient_int_cfg->orient_blocking =
-			ORIENT_BLOCKING_ACCEL_ONLY;
-		break;
-	case 0x02:
-		orient_int_cfg->orient_blocking =
-			ORIENT_BLOCKING_ACCEL_AND_SLOPE;
-		break;
-	case 0x03:
-		orient_int_cfg->orient_blocking =
-			ORIENT_BLOCKING_ACCEL_AND_SLOPE_AND_STABLE;
-		break;
-	}
-
-	switch (data[0] & 0x03) {
-	case 0x00:
-		orient_int_cfg->orient_mode = ORIENT_MODE_SYMMETRICAL;
-		break;
-	case 0x01:
-		orient_int_cfg->orient_mode = ORIENT_MODE_HIGH_ASYMMETRICAL;
-		break;
-	case 0x02:
-		orient_int_cfg->orient_mode = ORIENT_MODE_LOW_ASYMMETRICAL;
-		break;
-	case 0x03:
-		orient_int_cfg->orient_mode = ORIENT_MODE_SYMMETRICAL;
-		break;
-	}
-
-	orient_int_cfg->signal_up_down = data[1] & 0x40;
-	orient_int_cfg->blocking_angle = data[1] & 0x3F;
-
-	return 0;
-}
-
-int bma253_set_orient_int_cfg(const struct sensor_itf * itf,
-			      const struct orient_int_cfg * orient_int_cfg)
-{
-	uint8_t data[2];
-	int rc;
-
-	if (orient_int_cfg->hyster_g < 0.0 ||
-	    orient_int_cfg->hyster_g > (0.0625 * 7.0))
-		return SYS_EINVAL;
-	if (orient_int_cfg->blocking_angle > 0x3F)
-		return SYS_EINVAL;
-
-	data[0] = (uint8_t)(orient_int_cfg->hyster_g / 0.0625) << 4;
-
-	switch (orient_int_cfg->orient_blocking) {
-	case ORIENT_BLOCKING_NONE:
-		data[0] |= 0x00 << 2;
-		break;
-	case ORIENT_BLOCKING_ACCEL_ONLY:
-		data[0] |= 0x01 << 2;
-		break;
-	case ORIENT_BLOCKING_ACCEL_AND_SLOPE:
-		data[0] |= 0x02 << 2;
-		break;
-	case ORIENT_BLOCKING_ACCEL_AND_SLOPE_AND_STABLE:
-		data[0] |= 0x03 << 2;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (orient_int_cfg->orient_mode) {
-	case ORIENT_MODE_SYMMETRICAL:
-		data[0] |= 0x00;
-		break;
-	case ORIENT_MODE_HIGH_ASYMMETRICAL:
-		data[0] |= 0x01;
-		break;
-	case ORIENT_MODE_LOW_ASYMMETRICAL:
-		data[0] |= 0x02;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	data[1] = (orient_int_cfg->signal_up_down << 6) |
-		  ((orient_int_cfg->blocking_angle & 0x3F) << 0);
-
-	rc = set_register(itf, REG_ADDR_INT_A, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_B, data[1]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-enum flat_hold {
-	FLAT_HOLD_0_MS    = 0,
-	FLAT_HOLD_512_MS  = 1,
-	FLAT_HOLD_1024_MS = 2,
-	FLAT_HOLD_2048_MS = 3,
-};
+int
+bma253_set_tap_int_cfg(const struct bma253 * bma253,
+                       enum bma253_g_range g_range,
+                       const struct tap_int_cfg * tap_int_cfg)
+{
+    float thresh_scale;
+    uint8_t data[2];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        thresh_scale = 0.0625;
+        break;
+    case BMA253_G_RANGE_4:
+        thresh_scale = 0.125;
+        break;
+    case BMA253_G_RANGE_8:
+        thresh_scale = 0.25;
+        break;
+    case BMA253_G_RANGE_16:
+        thresh_scale = 0.5;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    if (tap_int_cfg->thresh_g < 0.0 ||
+        tap_int_cfg->thresh_g > thresh_scale * 31.0) {
+        return SYS_EINVAL;
+    }
+
+    data[0] = 0;
+    data[1] = 0;
+
+    switch (tap_int_cfg->tap_quiet) {
+    case BMA253_TAP_QUIET_20_MS:
+        data[0] |= 0x80;
+        break;
+    case BMA253_TAP_QUIET_30_MS:
+        data[0] |= 0x00;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (tap_int_cfg->tap_shock) {
+    case BMA253_TAP_SHOCK_50_MS:
+        data[0] |= 0x00;
+        break;
+    case BMA253_TAP_SHOCK_75_MS:
+        data[0] |= 0x40;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (tap_int_cfg->d_tap_window) {
+    case BMA253_D_TAP_WINDOW_50_MS:
+        data[0] |= 0x00;
+        break;
+    case BMA253_D_TAP_WINDOW_100_MS:
+        data[0] |= 0x01;
+        break;
+    case BMA253_D_TAP_WINDOW_150_MS:
+        data[0] |= 0x02;
+        break;
+    case BMA253_D_TAP_WINDOW_200_MS:
+        data[0] |= 0x03;
+        break;
+    case BMA253_D_TAP_WINDOW_250_MS:
+        data[0] |= 0x04;
+        break;
+    case BMA253_D_TAP_WINDOW_375_MS:
+        data[0] |= 0x05;
+        break;
+    case BMA253_D_TAP_WINDOW_500_MS:
+        data[0] |= 0x06;
+        break;
+    case BMA253_D_TAP_WINDOW_700_MS:
+        data[0] |= 0x07;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (tap_int_cfg->tap_wake_samples) {
+    case BMA253_TAP_WAKE_SAMPLES_2:
+        data[1] |= 0x00 << 6;
+        break;
+    case BMA253_TAP_WAKE_SAMPLES_4:
+        data[1] |= 0x01 << 6;
+        break;
+    case BMA253_TAP_WAKE_SAMPLES_8:
+        data[1] |= 0x02 << 6;
+        break;
+    case BMA253_TAP_WAKE_SAMPLES_16:
+        data[1] |= 0x03 << 6;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    data[1] |= (uint8_t)(tap_int_cfg->thresh_g / thresh_scale) & 0x1F;
+
+    rc = set_register(bma253, REG_ADDR_INT_8, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_9, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-struct flat_int_cfg {
-	uint8_t flat_angle;
-	enum flat_hold flat_hold;
-	uint8_t flat_hyster;
-	bool hyster_enable;
-};
+int
+bma253_get_orient_int_cfg(const struct bma253 * bma253,
+                          struct orient_int_cfg * orient_int_cfg)
+{
+    uint8_t data[2];
+    int rc;
+
+    rc = get_registers(bma253, REG_ADDR_INT_A,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    orient_int_cfg->hyster_g = (float)((data[0] >> 4) & 0x07) * 0.0625;
+
+    switch ((data[0] >> 2) & 0x03) {
+    case 0x00:
+        orient_int_cfg->orient_blocking =
+            BMA253_ORIENT_BLOCKING_NONE;
+        break;
+    case 0x01:
+        orient_int_cfg->orient_blocking =
+            BMA253_ORIENT_BLOCKING_ACCEL_ONLY;
+        break;
+    case 0x02:
+        orient_int_cfg->orient_blocking =
+            BMA253_ORIENT_BLOCKING_ACCEL_AND_SLOPE;
+        break;
+    case 0x03:
+        orient_int_cfg->orient_blocking =
+            BMA253_ORIENT_BLOCKING_ACCEL_AND_SLOPE_AND_STABLE;
+        break;
+    }
+
+    switch (data[0] & 0x03) {
+    case 0x00:
+        orient_int_cfg->orient_mode =
+            BMA253_ORIENT_MODE_SYMMETRICAL;
+        break;
+    case 0x01:
+        orient_int_cfg->orient_mode =
+            BMA253_ORIENT_MODE_HIGH_ASYMMETRICAL;
+        break;
+    case 0x02:
+        orient_int_cfg->orient_mode =
+            BMA253_ORIENT_MODE_LOW_ASYMMETRICAL;
+        break;
+    case 0x03:
+        orient_int_cfg->orient_mode =
+            BMA253_ORIENT_MODE_SYMMETRICAL;
+        break;
+    }
+
+    orient_int_cfg->signal_up_dn = data[1] & 0x40;
+    orient_int_cfg->blocking_angle = data[1] & 0x3F;
+
+    return 0;
+}
+
+int
+bma253_set_orient_int_cfg(const struct bma253 * bma253,
+                          const struct orient_int_cfg * orient_int_cfg)
+{
+    uint8_t data[2];
+    int rc;
+
+    if (orient_int_cfg->hyster_g < 0.0 ||
+        orient_int_cfg->hyster_g > (0.0625 * 7.0)) {
+        return SYS_EINVAL;
+    }
+    if (orient_int_cfg->blocking_angle > 0x3F) {
+        return SYS_EINVAL;
+    }
+
+    data[0] = (uint8_t)(orient_int_cfg->hyster_g / 0.0625) << 4;
+
+    switch (orient_int_cfg->orient_blocking) {
+    case BMA253_ORIENT_BLOCKING_NONE:
+        data[0] |= 0x00 << 2;
+        break;
+    case BMA253_ORIENT_BLOCKING_ACCEL_ONLY:
+        data[0] |= 0x01 << 2;
+        break;
+    case BMA253_ORIENT_BLOCKING_ACCEL_AND_SLOPE:
+        data[0] |= 0x02 << 2;
+        break;
+    case BMA253_ORIENT_BLOCKING_ACCEL_AND_SLOPE_AND_STABLE:
+        data[0] |= 0x03 << 2;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (orient_int_cfg->orient_mode) {
+    case BMA253_ORIENT_MODE_SYMMETRICAL:
+        data[0] |= 0x00;
+        break;
+    case BMA253_ORIENT_MODE_HIGH_ASYMMETRICAL:
+        data[0] |= 0x01;
+        break;
+    case BMA253_ORIENT_MODE_LOW_ASYMMETRICAL:
+        data[0] |= 0x02;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    data[1] = (orient_int_cfg->signal_up_dn << 6) |
+              ((orient_int_cfg->blocking_angle & 0x3F) << 0);
+
+    rc = set_register(bma253, REG_ADDR_INT_A, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_B, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+int
+bma253_get_flat_int_cfg(const struct bma253 * bma253,
+                        struct flat_int_cfg * flat_int_cfg)
+{
+    uint8_t data[2];
+    int rc;
+
+    rc = get_registers(bma253, REG_ADDR_INT_C,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    flat_int_cfg->flat_angle = data[0] & 0x3F;
+
+    switch ((data[1] >> 4) & 0x03) {
+    case 0x00:
+        flat_int_cfg->flat_hold = FLAT_HOLD_0_MS;
+        break;
+    case 0x01:
+        flat_int_cfg->flat_hold = FLAT_HOLD_512_MS;
+        break;
+    case 0x02:
+        flat_int_cfg->flat_hold = FLAT_HOLD_1024_MS;
+        break;
+    case 0x03:
+        flat_int_cfg->flat_hold = FLAT_HOLD_2048_MS;
+        break;
+    }
+
+    flat_int_cfg->flat_hyster = data[1] & 0x07;
+    flat_int_cfg->hyster_enable = (data[1] & 0x07) != 0x00;
+
+    return 0;
+}
+
+int
+bma253_set_flat_int_cfg(const struct bma253 * bma253,
+                        const struct flat_int_cfg * flat_int_cfg)
+{
+    uint8_t data[2];
+    int rc;
+
+    if (flat_int_cfg->flat_angle > 0x3F) {
+        return SYS_EINVAL;
+    }
+    if (flat_int_cfg->flat_hyster == 0x00 &&
+        flat_int_cfg->hyster_enable) {
+        return SYS_EINVAL;
+    }
+
+    data[0] = flat_int_cfg->flat_angle & 0x3F;
+    data[1] = 0;
+
+    switch (flat_int_cfg->flat_hold) {
+    case FLAT_HOLD_0_MS:
+        data[1] |= 0x00 << 4;
+        break;
+    case FLAT_HOLD_512_MS:
+        data[1] |= 0x01 << 4;
+        break;
+    case FLAT_HOLD_1024_MS:
+        data[1] |= 0x02 << 4;
+        break;
+    case FLAT_HOLD_2048_MS:
+        data[1] |= 0x03 << 4;
+        break;
+    }
+
+    if (flat_int_cfg->hyster_enable) {
+        data[1] |= flat_int_cfg->flat_hyster & 0x07;
+    }
+
+    rc = set_register(bma253, REG_ADDR_INT_C, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_INT_D, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+int
+bma253_get_fifo_wmark_level(const struct bma253 * bma253,
+                            uint8_t * wmark_level)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_FIFO_CONFIG_0, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    *wmark_level = data & 0x3F;
+
+    return 0;
+}
 
-int bma253_get_flat_int_cfg(const struct sensor_itf * itf,
-			    struct flat_int_cfg * flat_int_cfg)
+int
+bma253_set_fifo_wmark_level(const struct bma253 * bma253,
+                            uint8_t wmark_level)
 {
-	uint8_t data[2];
-	int rc;
+    uint8_t data;
 
-	rc = get_registers(itf, REG_ADDR_INT_C,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
+    if (wmark_level > 32) {
+        return SYS_EINVAL;
+    }
 
-	flat_int_cfg->flat_angle = data[0] & 0x3F;
+    data = wmark_level & 0x3F;
 
-	switch ((data[1] >> 4) & 0x03) {
-	case 0x00:
-		flat_int_cfg->flat_hold = FLAT_HOLD_0_MS;
-		break;
-	case 0x01:
-		flat_int_cfg->flat_hold = FLAT_HOLD_512_MS;
-		break;
-	case 0x02:
-		flat_int_cfg->flat_hold = FLAT_HOLD_1024_MS;
-		break;
-	case 0x03:
-		flat_int_cfg->flat_hold = FLAT_HOLD_2048_MS;
-		break;
-	}
+    return set_register(bma253, REG_ADDR_FIFO_CONFIG_0, data);
+}
 
-	flat_int_cfg->flat_hyster = data[1] & 0x07;
-	flat_int_cfg->hyster_enable = (data[1] & 0x07) != 0x00;
+int
+bma253_get_self_test_cfg(const struct bma253 * bma253,
+                         struct self_test_cfg * self_test_cfg)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_PMU_SELF_TEST, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if ((data & 0x10) == 0) {
+        self_test_cfg->self_test_ampl = SELF_TEST_AMPL_LOW;
+    } else {
+        self_test_cfg->self_test_ampl = SELF_TEST_AMPL_HIGH;
+    }
+    if ((data & 0x04) == 0) {
+        self_test_cfg->self_test_sign = SELF_TEST_SIGN_NEGATIVE;
+    } else {
+        self_test_cfg->self_test_sign = SELF_TEST_SIGN_POSITIVE;
+    }
+
+    switch (data & 0x03) {
+    case 0x00:
+        self_test_cfg->self_test_axis = -1;
+        self_test_cfg->self_test_enabled = false;
+        break;
+    case 0x01:
+        self_test_cfg->self_test_axis = AXIS_X;
+        self_test_cfg->self_test_enabled = true;
+        break;
+    case 0x02:
+        self_test_cfg->self_test_axis = AXIS_Y;
+        self_test_cfg->self_test_enabled = true;
+        break;
+    case 0x03:
+        self_test_cfg->self_test_axis = AXIS_Z;
+        self_test_cfg->self_test_enabled = true;
+        break;
+    }
+
+    return 0;
+}
 
-	return 0;
+int
+bma253_set_self_test_cfg(const struct bma253 * bma253,
+                         const struct self_test_cfg * self_test_cfg)
+{
+    uint8_t data;
+
+    data = 0;
+
+    switch (self_test_cfg->self_test_ampl) {
+    case SELF_TEST_AMPL_HIGH:
+        data |= 0x10;
+        break;
+    case SELF_TEST_AMPL_LOW:
+        data |= 0x00;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (self_test_cfg->self_test_sign) {
+    case SELF_TEST_SIGN_NEGATIVE:
+        data |= 0x00;
+        break;
+    case SELF_TEST_SIGN_POSITIVE:
+        data |= 0x04;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    if (self_test_cfg->self_test_enabled) {
+        switch (self_test_cfg->self_test_axis) {
+        case AXIS_X:
+            data |= 0x01;
+            break;
+        case AXIS_Y:
+            data |= 0x02;
+            break;
+        case AXIS_Z:
+            data |= 0x03;
+            break;
+        default:
+            return SYS_EINVAL;
+        }
+    }
+
+    return set_register(bma253, REG_ADDR_PMU_SELF_TEST, data);
 }
 
-int bma253_set_flat_int_cfg(const struct sensor_itf * itf,
-			    const struct flat_int_cfg * flat_int_cfg)
+int
+bma253_get_nvm_control(const struct bma253 * bma253,
+                       uint8_t * remaining_cycles,
+                       bool * load_from_nvm,
+                       bool * nvm_is_ready,
+                       bool * nvm_unlocked)
 {
-	uint8_t data[2];
-	int rc;
+    uint8_t data;
+    int rc;
 
-	if (flat_int_cfg->flat_angle > 0x3F)
-		return SYS_EINVAL;
-	if (flat_int_cfg->flat_hyster == 0x00 &&
-	    flat_int_cfg->hyster_enable)
-		return SYS_EINVAL;
+    rc = get_register(bma253, REG_ADDR_TRIM_NVM_CTRL, &data);
+    if (rc != 0) {
+        return rc;
+    }
 
-	data[0] = flat_int_cfg->flat_angle & 0x3F;
-	data[1] = 0;
+    *remaining_cycles = (data >> 4) & 0x0F;
+    *load_from_nvm = data & 0x08;
+    *nvm_is_ready = data & 0x04;
+    *nvm_unlocked = data & 0x01;
 
-	switch (flat_int_cfg->flat_hold) {
-	case FLAT_HOLD_0_MS:
-		data[1] |= 0x00 << 4;
-		break;
-	case FLAT_HOLD_512_MS:
-		data[1] |= 0x01 << 4;
-		break;
-	case FLAT_HOLD_1024_MS:
-		data[1] |= 0x02 << 4;
-		break;
-	case FLAT_HOLD_2048_MS:
-		data[1] |= 0x03 << 4;
-		break;
-	}
+    return 0;
+}
 
-	if (flat_int_cfg->hyster_enable)
-		data[1] |= flat_int_cfg->flat_hyster & 0x07;
+int
+bma253_set_nvm_control(const struct bma253 * bma253,
+                       bool load_from_nvm,
+                       bool store_into_nvm,
+                       bool nvm_unlocked)
+{
+    uint8_t data;
 
-	rc = set_register(itf, REG_ADDR_INT_C, data[0]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_INT_D, data[1]);
-	if (rc != 0)
-		return rc;
+    data = (load_from_nvm << 3) |
+           (store_into_nvm << 1) |
+           (nvm_unlocked << 0);
 
-	return 0;
+    return set_register(bma253, REG_ADDR_TRIM_NVM_CTRL, data);
 }
 
-int bma253_get_fifo_wmark_level(const struct sensor_itf * itf,
-				uint8_t * wmark_level)
+int
+bma253_get_i2c_watchdog(const struct bma253 * bma253,
+                        enum i2c_watchdog * i2c_watchdog)
 {
-	uint8_t data;
-	int rc;
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_BGW_SPI3_WDT, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if ((data & 0x04) != 0) {
+        if ((data & 0x02) != 0) {
+            *i2c_watchdog = I2C_WATCHDOG_50_MS;
+        } else {
+            *i2c_watchdog = I2C_WATCHDOG_1_MS;
+        }
+    } else {
+        *i2c_watchdog = I2C_WATCHDOG_DISABLED;
+    }
+
+    return 0;
+}
 
-	rc = get_register(itf, REG_ADDR_FIFO_CONFIG_0, &data);
-	if (rc != 0)
-		return rc;
+int
+bma253_set_i2c_watchdog(const struct bma253 * bma253,
+                        enum i2c_watchdog i2c_watchdog)
+{
+    uint8_t data;
+
+    switch (i2c_watchdog) {
+    case I2C_WATCHDOG_DISABLED:
+        data = 0x00;
+        break;
+    case I2C_WATCHDOG_1_MS:
+        data = 0x04;
+        break;
+    case I2C_WATCHDOG_50_MS:
+        data = 0x06;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    return set_register(bma253, REG_ADDR_BGW_SPI3_WDT, data);
+}
 
-	*wmark_level = data & 0x3F;
+int
+bma253_get_fast_ofc_cfg(const struct bma253 * bma253,
+                        bool * fast_ofc_ready,
+                        enum bma253_offset_comp_target * ofc_target_z,
+                        enum bma253_offset_comp_target * ofc_target_y,
+                        enum bma253_offset_comp_target * ofc_target_x)
+{
+    uint8_t data[2];
+    int rc;
+
+    rc = get_registers(bma253, REG_ADDR_OFC_CTRL,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
+
+    *fast_ofc_ready = data[0] & 0x10;
+
+    switch ((data[1] >> 5) & 0x03) {
+    case 0x00:
+        *ofc_target_z = BMA253_OFFSET_COMP_TARGET_0_G;
+        break;
+    case 0x01:
+        *ofc_target_z = BMA253_OFFSET_COMP_TARGET_POS_1_G;
+        break;
+    case 0x02:
+        *ofc_target_z = BMA253_OFFSET_COMP_TARGET_NEG_1_G;
+        break;
+    case 0x03:
+        *ofc_target_z = BMA253_OFFSET_COMP_TARGET_0_G;
+        break;
+    }
+
+    switch ((data[1] >> 3) & 0x03) {
+    case 0x00:
+        *ofc_target_y = BMA253_OFFSET_COMP_TARGET_0_G;
+        break;
+    case 0x01:
+        *ofc_target_y = BMA253_OFFSET_COMP_TARGET_POS_1_G;
+        break;
+    case 0x02:
+        *ofc_target_y = BMA253_OFFSET_COMP_TARGET_NEG_1_G;
+        break;
+    case 0x03:
+        *ofc_target_y = BMA253_OFFSET_COMP_TARGET_0_G;
+        break;
+    }
+
+    switch ((data[1] >> 1) & 0x03) {
+    case 0x00:
+        *ofc_target_x = BMA253_OFFSET_COMP_TARGET_0_G;
+        break;
+    case 0x01:
+        *ofc_target_x = BMA253_OFFSET_COMP_TARGET_POS_1_G;
+        break;
+    case 0x02:
+        *ofc_target_x = BMA253_OFFSET_COMP_TARGET_NEG_1_G;
+        break;
+    case 0x03:
+        *ofc_target_x = BMA253_OFFSET_COMP_TARGET_0_G;
+        break;
+    }
+
+    return 0;
+}
 
-	return 0;
+int
+bma253_set_fast_ofc_cfg(const struct bma253 * bma253,
+                        enum axis fast_ofc_axis,
+                        enum bma253_offset_comp_target fast_ofc_target,
+                        bool trigger_fast_ofc)
+{
+    uint8_t data[2];
+    uint8_t axis_value;
+    uint8_t axis_shift;
+    int rc;
+
+    data[0] = 0;
+    data[1] = 0;
+
+    switch (fast_ofc_axis) {
+    case AXIS_X:
+        axis_value = 0x01;
+        axis_shift = 1;
+        break;
+    case AXIS_Y:
+        axis_value = 0x02;
+        axis_shift = 3;
+        break;
+    case AXIS_Z:
+        axis_value = 0x03;
+        axis_shift = 5;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (fast_ofc_target) {
+    case BMA253_OFFSET_COMP_TARGET_0_G:
+        data[1] |= 0x00 << axis_shift;
+        break;
+    case BMA253_OFFSET_COMP_TARGET_NEG_1_G:
+        data[1] |= 0x02 << axis_shift;
+        break;
+    case BMA253_OFFSET_COMP_TARGET_POS_1_G:
+        data[1] |= 0x01 << axis_shift;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    if (trigger_fast_ofc) {
+        data[0] |= axis_value << 5;
+    }
+
+    rc = set_register(bma253, REG_ADDR_OFC_SETTING, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_OFC_CTRL, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
 }
 
-int bma253_set_fifo_wmark_level(const struct sensor_itf * itf,
-				uint8_t wmark_level)
+int
+bma253_get_slow_ofc_cfg(const struct bma253 * bma253,
+                        struct slow_ofc_cfg * slow_ofc_cfg)
 {
-	uint8_t data;
+    uint8_t data[2];
+    int rc;
 
-	if (wmark_level > 32)
-		return SYS_EINVAL;
+    rc = get_registers(bma253, REG_ADDR_OFC_CTRL,
+                       data, sizeof(data) / sizeof(*data));
+    if (rc != 0) {
+        return rc;
+    }
 
-	data = wmark_level & 0x3F;
+    slow_ofc_cfg->ofc_z_enabled = data[0] & 0x04;
+    slow_ofc_cfg->ofc_y_enabled = data[0] & 0x02;
+    slow_ofc_cfg->ofc_x_enabled = data[0] & 0x01;
+    slow_ofc_cfg->high_bw_cut_off = data[1] & 0x01;
 
-	return set_register(itf, REG_ADDR_FIFO_CONFIG_0, data);
+    return 0;
 }
 
-enum self_test_ampl {
-	SELF_TEST_AMPL_HIGH = 0,
-	SELF_TEST_AMPL_LOW  = 1,
-};
+int
+bma253_set_slow_ofc_cfg(const struct bma253 * bma253,
+                        const struct slow_ofc_cfg * slow_ofc_cfg)
+{
+    uint8_t data[2];
+    int rc;
+
+    data[0] = (slow_ofc_cfg->ofc_z_enabled << 2) |
+              (slow_ofc_cfg->ofc_y_enabled << 1) |
+              (slow_ofc_cfg->ofc_x_enabled << 0);
+    data[1] = slow_ofc_cfg->high_bw_cut_off << 0;
+
+    rc = set_register(bma253, REG_ADDR_OFC_SETTING, data[1]);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = set_register(bma253, REG_ADDR_OFC_CTRL, data[0]);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-enum self_test_sign {
-	SELF_TEST_SIGN_NEGATIVE = 0,
-	SELF_TEST_SIGN_POSITIVE = 1,
-};
+int
+bma253_set_ofc_reset(const struct bma253 * bma253)
+{
+    return set_register(bma253, REG_ADDR_OFC_CTRL, 0x80);
+}
 
-struct self_test_cfg {
-	enum self_test_ampl self_test_ampl;
-	enum self_test_sign self_test_sign;
-	enum axis self_test_axis;
-	bool self_test_enabled;
-};
+int
+bma253_get_ofc_offset(const struct bma253 * bma253,
+                      enum axis axis,
+                      float * offset_g)
+{
+    uint8_t reg_addr;
+    uint8_t data;
+    int rc;
+
+    switch (axis) {
+    case AXIS_X:
+        reg_addr = REG_ADDR_OFC_OFFSET_X;
+        break;
+    case AXIS_Y:
+        reg_addr = REG_ADDR_OFC_OFFSET_Y;
+        break;
+    case AXIS_Z:
+        reg_addr = REG_ADDR_OFC_OFFSET_Z;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = get_register(bma253, reg_addr, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    *offset_g = (float)(int8_t)data * 0.00781;
+
+    return 0;
+}
 
-int bma253_get_self_test_cfg(const struct sensor_itf * itf,
-			     struct self_test_cfg * self_test_cfg)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_PMU_SELF_TEST, &data);
-	if (rc != 0)
-		return rc;
-
-	if ((data & 0x10) == 0)
-		self_test_cfg->self_test_ampl = SELF_TEST_AMPL_LOW;
-	else
-		self_test_cfg->self_test_ampl = SELF_TEST_AMPL_HIGH;
-	if ((data & 0x04) == 0)
-		self_test_cfg->self_test_sign = SELF_TEST_SIGN_NEGATIVE;
-	else
-		self_test_cfg->self_test_sign = SELF_TEST_SIGN_POSITIVE;
-
-	switch (data & 0x03) {
-	case 0x00:
-		self_test_cfg->self_test_axis = -1;
-		self_test_cfg->self_test_enabled = false;
-		break;
-	case 0x01:
-		self_test_cfg->self_test_axis = AXIS_X;
-		self_test_cfg->self_test_enabled = true;
-		break;
-	case 0x02:
-		self_test_cfg->self_test_axis = AXIS_Y;
-		self_test_cfg->self_test_enabled = true;
-		break;
-	case 0x03:
-		self_test_cfg->self_test_axis = AXIS_Z;
-		self_test_cfg->self_test_enabled = true;
-		break;
-	}
-
-	return 0;
-}
-
-int bma253_set_self_test_cfg(const struct sensor_itf * itf,
-			     const struct self_test_cfg * self_test_cfg)
-{
-	uint8_t data;
-
-	data = 0;
-
-	switch (self_test_cfg->self_test_ampl) {
-	case SELF_TEST_AMPL_HIGH:
-		data |= 0x10;
-		break;
-	case SELF_TEST_AMPL_LOW:
-		data |= 0x00;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (self_test_cfg->self_test_sign) {
-	case SELF_TEST_SIGN_NEGATIVE:
-		data |= 0x00;
-		break;
-	case SELF_TEST_SIGN_POSITIVE:
-		data |= 0x04;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	if (self_test_cfg->self_test_enabled) {
-		switch (self_test_cfg->self_test_axis) {
-		case AXIS_X:
-			data |= 0x01;
-			break;
-		case AXIS_Y:
-			data |= 0x02;
-			break;
-		case AXIS_Z:
-			data |= 0x03;
-			break;
-		default:
-			return SYS_EINVAL;
-		}
-	}
-
-	return set_register(itf, REG_ADDR_PMU_SELF_TEST, data);
-}
-
-int bma253_get_nvm_control(const struct sensor_itf * itf,
-			   uint8_t * remaining_cycles,
-			   bool * load_from_nvm,
-			   bool * nvm_is_ready,
-			   bool * nvm_unlocked)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_TRIM_NVM_CTRL, &data);
-	if (rc != 0)
-		return rc;
-
-	*remaining_cycles = (data >> 4) & 0x0F;
-	*load_from_nvm = data & 0x08;
-	*nvm_is_ready = data & 0x04;
-	*nvm_unlocked = data & 0x01;
-
-	return 0;
-}
-
-int bma253_set_nvm_control(const struct sensor_itf * itf,
-			   bool load_from_nvm,
-			   bool store_into_nvm,
-			   bool nvm_unlocked)
-{
-	uint8_t data;
-
-	data = (load_from_nvm << 3) |
-	       (store_into_nvm << 1) |
-	       (nvm_unlocked << 0);
-
-	return set_register(itf, REG_ADDR_TRIM_NVM_CTRL, data);
-}
-
-int bma253_get_i2c_watchdog(const struct sensor_itf * itf,
-			    enum bma253_i2c_watchdog * i2c_watchdog)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_BGW_SPI3_WDT, &data);
-	if (rc != 0)
-		return rc;
-
-	if ((data & 0x04) != 0) {
-		if ((data & 0x02) != 0)
-			*i2c_watchdog = BMA253_I2C_WATCHDOG_50_MS;
-		else
-			*i2c_watchdog = BMA253_I2C_WATCHDOG_1_MS;
-	} else {
-		*i2c_watchdog = BMA253_I2C_WATCHDOG_DISABLED;
-	}
-
-	return 0;
-}
-
-int bma253_set_i2c_watchdog(const struct sensor_itf * itf,
-			    enum bma253_i2c_watchdog i2c_watchdog)
-{
-	uint8_t data;
-
-	switch (i2c_watchdog) {
-	case BMA253_I2C_WATCHDOG_DISABLED:
-		data = 0x00;
-		break;
-	case BMA253_I2C_WATCHDOG_1_MS:
-		data = 0x04;
-		break;
-	case BMA253_I2C_WATCHDOG_50_MS:
-		data = 0x06;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	return set_register(itf, REG_ADDR_BGW_SPI3_WDT, data);
+int
+bma253_set_ofc_offset(const struct bma253 * bma253,
+                      enum axis axis,
+                      float offset_g)
+{
+    uint8_t reg_addr;
+    uint8_t data;
+
+    switch (axis) {
+    case AXIS_X:
+        reg_addr = REG_ADDR_OFC_OFFSET_X;
+        break;
+    case AXIS_Y:
+        reg_addr = REG_ADDR_OFC_OFFSET_Y;
+        break;
+    case AXIS_Z:
+        reg_addr = REG_ADDR_OFC_OFFSET_Z;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    data = (int8_t)(offset_g / 0.00781);
+
+    return set_register(bma253, reg_addr, data);
 }
 
-struct slow_ofc_cfg {
-	bool ofc_z_enabled;
-	bool ofc_y_enabled;
-	bool ofc_x_enabled;
-	bool high_bw_cut_off;
-};
+int
+bma253_get_saved_data(const struct bma253 * bma253,
+                      enum saved_data_addr saved_data_addr,
+                      uint8_t * saved_data_val)
+{
+    uint8_t reg_addr;
+
+    switch (saved_data_addr) {
+    case SAVED_DATA_ADDR_0:
+        reg_addr = REG_ADDR_TRIM_GP0;
+        break;
+    case SAVED_DATA_ADDR_1:
+        reg_addr = REG_ADDR_TRIM_GP1;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    return get_register(bma253, reg_addr, saved_data_val);
+}
 
-int bma253_get_fast_ofc_cfg(const struct sensor_itf * itf,
-			    bool * fast_ofc_ready,
-			    enum bma253_offset_comp_target * ofc_target_z,
-			    enum bma253_offset_comp_target * ofc_target_y,
-			    enum bma253_offset_comp_target * ofc_target_x)
-{
-	uint8_t data[2];
-	int rc;
-
-	rc = get_registers(itf, REG_ADDR_OFC_CTRL,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	*fast_ofc_ready = data[0] & 0x10;
-
-	switch ((data[1] >> 5) & 0x03) {
-	case 0x00:
-		*ofc_target_z = BMA253_OFFSET_COMP_TARGET_0_G;
-		break;
-	case 0x01:
-		*ofc_target_z = BMA253_OFFSET_COMP_TARGET_POS_1_G;
-		break;
-	case 0x02:
-		*ofc_target_z = BMA253_OFFSET_COMP_TARGET_NEG_1_G;
-		break;
-	case 0x03:
-		*ofc_target_z = BMA253_OFFSET_COMP_TARGET_0_G;
-		break;
-	}
-
-	switch ((data[1] >> 3) & 0x03) {
-	case 0x00:
-		*ofc_target_y = BMA253_OFFSET_COMP_TARGET_0_G;
-		break;
-	case 0x01:
-		*ofc_target_y = BMA253_OFFSET_COMP_TARGET_POS_1_G;
-		break;
-	case 0x02:
-		*ofc_target_y = BMA253_OFFSET_COMP_TARGET_NEG_1_G;
-		break;
-	case 0x03:
-		*ofc_target_y = BMA253_OFFSET_COMP_TARGET_0_G;
-		break;
-	}
-
-	switch ((data[1] >> 1) & 0x03) {
-	case 0x00:
-		*ofc_target_x = BMA253_OFFSET_COMP_TARGET_0_G;
-		break;
-	case 0x01:
-		*ofc_target_x = BMA253_OFFSET_COMP_TARGET_POS_1_G;
-		break;
-	case 0x02:
-		*ofc_target_x = BMA253_OFFSET_COMP_TARGET_NEG_1_G;
-		break;
-	case 0x03:
-		*ofc_target_x = BMA253_OFFSET_COMP_TARGET_0_G;
-		break;
-	}
-
-	return 0;
-}
-
-int bma253_set_fast_ofc_cfg(const struct sensor_itf * itf,
-			    enum axis fast_ofc_axis,
-			    enum bma253_offset_comp_target fast_ofc_target,
-			    bool trigger_fast_ofc)
-{
-	uint8_t data[2];
-	uint8_t axis_value;
-	uint8_t axis_shift;
-	int rc;
-
-	data[0] = 0;
-	data[1] = 0;
-
-	switch (fast_ofc_axis) {
-	case AXIS_X:
-		axis_value = 0x01;
-		axis_shift = 1;
-		break;
-	case AXIS_Y:
-		axis_value = 0x02;
-		axis_shift = 3;
-		break;
-	case AXIS_Z:
-		axis_value = 0x03;
-		axis_shift = 5;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (fast_ofc_target) {
-	case BMA253_OFFSET_COMP_TARGET_0_G:
-		data[1] |= 0x00 << axis_shift;
-		break;
-	case BMA253_OFFSET_COMP_TARGET_NEG_1_G:
-		data[1] |= 0x02 << axis_shift;
-		break;
-	case BMA253_OFFSET_COMP_TARGET_POS_1_G:
-		data[1] |= 0x01 << axis_shift;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	if (trigger_fast_ofc)
-		data[0] |= axis_value << 5;
-
-	rc = set_register(itf, REG_ADDR_OFC_SETTING, data[1]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_OFC_CTRL, data[0]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-int bma253_get_slow_ofc_cfg(const struct sensor_itf * itf,
-			    struct slow_ofc_cfg * slow_ofc_cfg)
-{
-	uint8_t data[2];
-	int rc;
-
-	rc = get_registers(itf, REG_ADDR_OFC_CTRL,
-			   data, sizeof(data) / sizeof(*data));
-	if (rc != 0)
-		return rc;
-
-	slow_ofc_cfg->ofc_z_enabled = data[0] & 0x04;
-	slow_ofc_cfg->ofc_y_enabled = data[0] & 0x02;
-	slow_ofc_cfg->ofc_x_enabled = data[0] & 0x01;
-	slow_ofc_cfg->high_bw_cut_off = data[1] & 0x01;
-
-	return 0;
-}
-
-int bma253_set_slow_ofc_cfg(const struct sensor_itf * itf,
-			    const struct slow_ofc_cfg * slow_ofc_cfg)
-{
-	uint8_t data[2];
-	int rc;
-
-	data[0] = (slow_ofc_cfg->ofc_z_enabled << 2) |
-		  (slow_ofc_cfg->ofc_y_enabled << 1) |
-		  (slow_ofc_cfg->ofc_x_enabled << 0);
-	data[1] = slow_ofc_cfg->high_bw_cut_off << 0;
-
-	rc = set_register(itf, REG_ADDR_OFC_SETTING, data[1]);
-	if (rc != 0)
-		return rc;
-	rc = set_register(itf, REG_ADDR_OFC_CTRL, data[0]);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-int bma253_set_ofc_reset(const struct sensor_itf * itf)
-{
-	return set_register(itf, REG_ADDR_OFC_CTRL, 0x80);
-}
-
-int bma253_get_ofc_offset(const struct sensor_itf * itf,
-			  enum axis axis,
-			  float * offset_g)
-{
-	uint8_t reg_addr;
-	uint8_t data;
-	int rc;
-
-	switch (axis) {
-	case AXIS_X:
-		reg_addr = REG_ADDR_OFC_OFFSET_X;
-		break;
-	case AXIS_Y:
-		reg_addr = REG_ADDR_OFC_OFFSET_Y;
-		break;
-	case AXIS_Z:
-		reg_addr = REG_ADDR_OFC_OFFSET_Z;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
+int
+bma253_set_saved_data(const struct bma253 * bma253,
+                      enum saved_data_addr saved_data_addr,
+                      uint8_t saved_data_val)
+{
+    uint8_t reg_addr;
+
+    switch (saved_data_addr) {
+    case SAVED_DATA_ADDR_0:
+        reg_addr = REG_ADDR_TRIM_GP0;
+        break;
+    case SAVED_DATA_ADDR_1:
+        reg_addr = REG_ADDR_TRIM_GP1;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    return set_register(bma253, reg_addr, saved_data_val);
+}
 
-	rc = get_register(itf, reg_addr, &data);
-	if (rc != 0)
-		return rc;
+int
+bma253_get_fifo_cfg(const struct bma253 * bma253,
+                    struct fifo_cfg * fifo_cfg)
+{
+    uint8_t data;
+    int rc;
+
+    rc = get_register(bma253, REG_ADDR_FIFO_CONFIG_1, &data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    switch ((data >> 6) & 0x03) {
+    case 0x03:
+        BMA253_ERROR("unknown FIFO_CONFIG_1 reg value 0x%02X\n", data);
+    case 0x00:
+        fifo_cfg->fifo_mode = FIFO_MODE_BYPASS;
+        break;
+    case 0x01:
+        fifo_cfg->fifo_mode = FIFO_MODE_FIFO;
+        break;
+    case 0x02:
+        fifo_cfg->fifo_mode = FIFO_MODE_STREAM;
+        break;
+    }
+
+    switch ((data >> 0) & 0x03) {
+    case 0x00:
+        fifo_cfg->fifo_data = FIFO_DATA_X_AND_Y_AND_Z;
+        break;
+    case 0x01:
+        fifo_cfg->fifo_data = FIFO_DATA_X_ONLY;
+        break;
+    case 0x02:
+        fifo_cfg->fifo_data = FIFO_DATA_Y_ONLY;
+        break;
+    case 0x03:
+        fifo_cfg->fifo_data = FIFO_DATA_Z_ONLY;
+        break;
+    }
+
+    return 0;
+}
 
-	*offset_g = (float)(int8_t)data * 0.00781;
+int
+bma253_set_fifo_cfg(const struct bma253 * bma253,
+                    const struct fifo_cfg * fifo_cfg)
+{
+    uint8_t data;
+
+    data = 0;
+
+    switch (fifo_cfg->fifo_mode) {
+    case FIFO_MODE_BYPASS:
+        data |= 0x00 << 6;
+        break;
+    case FIFO_MODE_FIFO:
+        data |= 0x01 << 6;
+        break;
+    case FIFO_MODE_STREAM:
+        data |= 0x02 << 6;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (fifo_cfg->fifo_data) {
+    case FIFO_DATA_X_AND_Y_AND_Z:
+        data |= 0x00 << 0;
+        break;
+    case FIFO_DATA_X_ONLY:
+        data |= 0x01 << 0;
+        break;
+    case FIFO_DATA_Y_ONLY:
+        data |= 0x02 << 0;
+        break;
+    case FIFO_DATA_Z_ONLY:
+        data |= 0x03 << 0;
+        break;
+    }
+
+    return set_register(bma253, REG_ADDR_FIFO_CONFIG_1, data);
+}
 
-	return 0;
+int
+bma253_get_fifo(const struct bma253 * bma253,
+                enum bma253_g_range g_range,
+                enum fifo_data fifo_data,
+                struct accel_data * accel_data)
+{
+    float accel_scale;
+    uint8_t size, iter;
+    uint8_t data[AXIS_ALL << 1];
+    int rc;
+
+    switch (g_range) {
+    case BMA253_G_RANGE_2:
+        accel_scale = 0.00098;
+        break;
+    case BMA253_G_RANGE_4:
+        accel_scale = 0.00195;
+        break;
+    case BMA253_G_RANGE_8:
+        accel_scale = 0.00391;
+        break;
+    case BMA253_G_RANGE_16:
+        accel_scale = 0.00781;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    switch (fifo_data) {
+    case FIFO_DATA_X_AND_Y_AND_Z:
+        size = AXIS_ALL << 1;
+        break;
+    case FIFO_DATA_X_ONLY:
+    case FIFO_DATA_Y_ONLY:
+    case FIFO_DATA_Z_ONLY:
+        size = 1 << 1;
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = get_registers(bma253, REG_ADDR_FIFO_DATA, data, size);
+    if (rc != 0) {
+        return rc;
+    }
+
+    for (iter = 0; iter < size; iter += 2) {
+        compute_accel_data(accel_data + (iter >> 1),
+                           data + iter,
+                           accel_scale);
+    }
+
+    return 0;
 }
 
-int bma253_set_ofc_offset(const struct sensor_itf * itf,
-			  enum axis axis,
-			  float offset_g)
+static int
+reset_and_recfg(struct bma253 * bma253)
 {
-	uint8_t reg_addr;
-	uint8_t data;
+    const struct bma253_cfg * cfg;
+    int rc;
+    enum int_route int_route;
+    struct int_routes int_routes;
+    struct int_filters int_filters;
+    struct int_pin_electrical int_pin_electrical;
+    struct low_g_int_cfg low_g_int_cfg;
+    struct high_g_int_cfg high_g_int_cfg;
+    struct tap_int_cfg tap_int_cfg;
+    struct orient_int_cfg orient_int_cfg;
+    enum i2c_watchdog i2c_watchdog;
+    struct fifo_cfg fifo_cfg;
+    struct bma253_private_driver_data *pdd;
+
+    cfg = &bma253->cfg;
+    pdd = &bma253->pdd;
+
+    bma253->power = BMA253_POWER_MODE_NORMAL;
+
+    rc = bma253_set_softreset(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_g_range(bma253, cfg->g_range);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_filter_bandwidth(bma253, cfg->filter_bandwidth);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_data_acquisition(bma253,
+                     cfg->use_unfiltered_data,
+                     false);
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_route = INT_ROUTE_NONE;
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    int_route = pdd->int_route;
+#endif
+
+    int_routes.flat_int_route        = INT_ROUTE_NONE;
+    int_routes.orient_int_route      = int_route;
+    int_routes.s_tap_int_route       = INT_ROUTE_NONE;
+    int_routes.d_tap_int_route       = INT_ROUTE_NONE;
+    int_routes.slow_no_mot_int_route = INT_ROUTE_NONE;
+    int_routes.slope_int_route       = INT_ROUTE_NONE;
+    int_routes.high_g_int_route      = int_route;
+    int_routes.low_g_int_route       = int_route;
+    int_routes.fifo_wmark_int_route  = INT_ROUTE_NONE;
+    int_routes.fifo_full_int_route   = INT_ROUTE_NONE;
+    int_routes.data_int_route        = int_route;
+
+    rc = bma253_set_int_routes(bma253, &int_routes);
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_filters.unfiltered_data_int        = cfg->use_unfiltered_data;
+    int_filters.unfiltered_tap_int         = cfg->use_unfiltered_data;
+    int_filters.unfiltered_slow_no_mot_int = cfg->use_unfiltered_data;
+    int_filters.unfiltered_slope_int       = cfg->use_unfiltered_data;
+    int_filters.unfiltered_high_g_int      = cfg->use_unfiltered_data;
+    int_filters.unfiltered_low_g_int       = cfg->use_unfiltered_data;
+
+    rc = bma253_set_int_filters(bma253, &int_filters);
+    if (rc != 0) {
+        return rc;
+    }
+
+#if MYNEWT_VAL(BMA253_INT_CFG_OUTPUT)
+    int_pin_electrical.pin1_output = INT_PIN_OUTPUT_OPEN_DRAIN;
+    int_pin_electrical.pin2_output = INT_PIN_OUTPUT_OPEN_DRAIN;
+#else
+    int_pin_electrical.pin1_output = INT_PIN_OUTPUT_PUSH_PULL;
+    int_pin_electrical.pin2_output = INT_PIN_OUTPUT_PUSH_PULL;
+#endif
+#if MYNEWT_VAL(BMA253_INT_CFG_ACTIVE)
+    int_pin_electrical.pin1_active = INT_PIN_ACTIVE_HIGH;
+    int_pin_electrical.pin2_active = INT_PIN_ACTIVE_HIGH;
+#else
+    int_pin_electrical.pin1_active = INT_PIN_ACTIVE_LOW;
+    int_pin_electrical.pin2_active = INT_PIN_ACTIVE_LOW;
+#endif
+
+    rc = bma253_set_int_pin_electrical(bma253, &int_pin_electrical);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_int_latch(bma253, false, INT_LATCH_NON_LATCHED);
+    if (rc != 0) {
+        return rc;
+    }
+
+    low_g_int_cfg.delay_ms     = cfg->low_g_delay_ms;
+    low_g_int_cfg.thresh_g     = cfg->low_g_thresh_g;
+    low_g_int_cfg.hyster_g     = cfg->low_g_hyster_g;
+    low_g_int_cfg.axis_summing = false;
+
+    rc = bma253_set_low_g_int_cfg(bma253, &low_g_int_cfg);
+    if (rc != 0) {
+        return rc;
+    }
+
+    high_g_int_cfg.hyster_g = cfg->high_g_hyster_g;
+    high_g_int_cfg.delay_ms = cfg->high_g_delay_ms;
+    high_g_int_cfg.thresh_g = cfg->high_g_thresh_g;
+
+    rc = bma253_set_high_g_int_cfg(bma253, cfg->g_range, &high_g_int_cfg);
+    if (rc != 0) {
+        return rc;
+    }
+
+    tap_int_cfg.tap_quiet        = cfg->tap_quiet;
+    tap_int_cfg.tap_shock        = cfg->tap_shock;
+    tap_int_cfg.d_tap_window     = cfg->d_tap_window;
+    tap_int_cfg.tap_wake_samples = cfg->tap_wake_samples;
+    tap_int_cfg.thresh_g         = cfg->tap_thresh_g;
+
+    rc = bma253_set_tap_int_cfg(bma253, cfg->g_range, &tap_int_cfg);
+    if (rc != 0) {
+        return rc;
+    }
+
+    orient_int_cfg.hyster_g        = cfg->orient_hyster_g;
+    orient_int_cfg.orient_blocking = cfg->orient_blocking;
+    orient_int_cfg.orient_mode     = cfg->orient_mode;
+    orient_int_cfg.signal_up_dn    = cfg->orient_signal_ud;
+    orient_int_cfg.blocking_angle  = 0x08;
+
+    rc = bma253_set_orient_int_cfg(bma253, &orient_int_cfg);
+    if (rc != 0) {
+        return rc;
+    }
+
+#if MYNEWT_VAL(BMA253_I2C_WDT)
+    i2c_watchdog = I2C_WATCHDOG_50_MS;
+#else
+    i2c_watchdog = I2C_WATCHDOG_DISABLED;
+#endif
+
+    rc = bma253_set_i2c_watchdog(bma253, i2c_watchdog);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_ofc_offset(bma253, AXIS_X, cfg->offset_x_g);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_ofc_offset(bma253, AXIS_Y, cfg->offset_y_g);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_ofc_offset(bma253, AXIS_Z, cfg->offset_z_g);
+    if (rc != 0) {
+        return rc;
+    }
 
-	switch (axis) {
-	case AXIS_X:
-		reg_addr = REG_ADDR_OFC_OFFSET_X;
-		break;
-	case AXIS_Y:
-		reg_addr = REG_ADDR_OFC_OFFSET_Y;
-		break;
-	case AXIS_Z:
-		reg_addr = REG_ADDR_OFC_OFFSET_Z;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
+    fifo_cfg.fifo_mode = FIFO_MODE_BYPASS;
+    fifo_cfg.fifo_data = FIFO_DATA_X_AND_Y_AND_Z;
 
-	data = (int8_t)(offset_g / 0.00781);
+    rc = bma253_set_fifo_cfg(bma253, &fifo_cfg);
+    if (rc != 0) {
+        return rc;
+    }
 
-	return set_register(itf, reg_addr, data);
+    return 0;
 }
 
-enum saved_data_addr {
-	SAVED_DATA_ADDR_0 = 0,
-	SAVED_DATA_ADDR_1 = 1,
-};
+static int
+change_power(struct bma253 * bma253,
+             enum bma253_power_mode target)
+{
+    const struct bma253_cfg * cfg;
+    int rc;
+    bool step1_move;
+    bool step2_move;
+    enum bma253_power_mode step1_mode;
+    enum bma253_power_mode step2_mode;
+    struct power_settings power_settings;
+
+    cfg = &bma253->cfg;
+
+    if (bma253->power == BMA253_POWER_MODE_DEEP_SUSPEND) {
+        rc = reset_and_recfg(bma253);
+        if (rc != 0) {
+            return rc;
+        }
+    }
+
+    step1_move = false;
+    switch (bma253->power) {
+    case BMA253_POWER_MODE_SUSPEND:
+    case BMA253_POWER_MODE_LPM_1:
+        switch (target) {
+        case BMA253_POWER_MODE_STANDBY:
+        case BMA253_POWER_MODE_LPM_2:
+            step1_mode = BMA253_POWER_MODE_NORMAL;
+            step1_move = true;
+            break;
+        default:
+            break;
+        }
+        break;
+    case BMA253_POWER_MODE_STANDBY:
+    case BMA253_POWER_MODE_LPM_2:
+        switch (target) {
+        case BMA253_POWER_MODE_SUSPEND:
+        case BMA253_POWER_MODE_LPM_1:
+            step1_mode = BMA253_POWER_MODE_NORMAL;
+            step1_move = true;
+            break;
+        default:
+            break;
+        }
+        break;
+    default:
+        break;
+    }
+
+    if (bma253->power != target) {
+        step2_mode = target;
+        step2_move = true;
+    } else {
+        step2_move = false;
+    }
+
+    if (step1_move) {
+        power_settings.power_mode     = step1_mode;
+        power_settings.sleep_duration = cfg->sleep_duration;
+        power_settings.sleep_timer    = SLEEP_TIMER_EVENT_DRIVEN;
+
+        rc = bma253_set_power_settings(bma253, &power_settings);
+        if (rc != 0) {
+            return rc;
+        }
+
+        bma253->power = step1_mode;
+    }
+
+    if (step2_move) {
+        power_settings.power_mode     = step2_mode;
+        power_settings.sleep_duration = cfg->sleep_duration;
+        power_settings.sleep_timer    = SLEEP_TIMER_EVENT_DRIVEN;
+
+        rc = bma253_set_power_settings(bma253, &power_settings);
+        if (rc != 0) {
+            return rc;
+        }
+
+        bma253->power = step2_mode;
+    }
+
+    return 0;
+}
 
-int bma253_get_saved_data(const struct sensor_itf * itf,
-			  enum saved_data_addr saved_data_addr,
-			  uint8_t * saved_data_val)
+static int
+interim_power(struct bma253 * bma253,
+              const enum bma253_power_mode * reqs,
+              uint8_t size)
 {
-	uint8_t reg_addr;
+    uint8_t i;
+
+    if (size == 0) {
+        return SYS_EINVAL;
+    }
 
-	switch (saved_data_addr) {
-	case SAVED_DATA_ADDR_0:
-		reg_addr = REG_ADDR_TRIM_GP0;
-		break;
-	case SAVED_DATA_ADDR_1:
-		reg_addr = REG_ADDR_TRIM_GP1;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
+    for (i = 0; i < size; i++) {
+        if (reqs[i] == bma253->power) {
+            return 0;
+        }
+    }
 
-	return get_register(itf, reg_addr, saved_data_val);
+    return change_power(bma253, reqs[0]);
 }
 
-int bma253_set_saved_data(const struct sensor_itf * itf,
-			  enum saved_data_addr saved_data_addr,
-			  uint8_t saved_data_val)
+static int
+default_power(struct bma253 * bma253)
 {
-	uint8_t reg_addr;
+    const struct bma253_cfg * cfg;
 
-	switch (saved_data_addr) {
-	case SAVED_DATA_ADDR_0:
-		reg_addr = REG_ADDR_TRIM_GP0;
-		break;
-	case SAVED_DATA_ADDR_1:
-		reg_addr = REG_ADDR_TRIM_GP1;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
+    cfg = &bma253->cfg;
 
-	return set_register(itf, reg_addr, saved_data_val);
+    if (cfg->power_mode == bma253->power) {
+        return 0;
+    }
+
+    return change_power(bma253, cfg->power_mode);
 }
 
-enum fifo_mode {
-	FIFO_MODE_BYPASS = 0,
-	FIFO_MODE_FIFO   = 1,
-	FIFO_MODE_STREAM = 2,
-};
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+static int
+init_intpin(struct bma253 * bma253,
+              hal_gpio_irq_handler_t handler,
+              void * arg)
+{
+    struct bma253_private_driver_data *pdd = &bma253->pdd;
+    hal_gpio_irq_trig_t trig;
+    int pin = -1;
+    int rc;
+    int i;
+
+    for (i = 0; i < MYNEWT_VAL(SENSOR_MAX_INTERRUPTS_PINS); i++){
+        pin = bma253->sensor.s_itf.si_ints[i].host_pin;
+        if (pin > 0) {
+            break;
+        }
+    }
+
+    if (pin < 0) {
+        BMA253_ERROR("Interrupt pin not configured\n");
+        return SYS_EINVAL;
+    }
+
+    pdd->int_num = i;
+    if (bma253->sensor.s_itf.si_ints[pdd->int_num].active) {
+        trig = HAL_GPIO_TRIG_RISING;
+    } else {
+        trig = HAL_GPIO_TRIG_FALLING;
+    }
+
+    if (bma253->sensor.s_itf.si_ints[pdd->int_num].device_pin == 1) {
+        pdd->int_route = INT_ROUTE_PIN_1;
+    } else if (bma253->sensor.s_itf.si_ints[pdd->int_num].device_pin == 2) {
+        pdd->int_route = INT_ROUTE_PIN_2;
+    } else {
+        BMA253_ERROR("Route not configured\n");
+        return SYS_EINVAL;
+    }
+
+    rc = hal_gpio_irq_init(pin,
+                           handler,
+                           arg,
+                           trig,
+                           HAL_GPIO_PULL_NONE);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-enum fifo_data {
-	FIFO_DATA_X_AND_Y_AND_Z = 0,
-	FIFO_DATA_X_ONLY        = 1,
-	FIFO_DATA_Y_ONLY        = 2,
-	FIFO_DATA_Z_ONLY        = 3,
-};
+static void
+enable_intpin(struct bma253 * bma253)
+{
+    struct bma253_private_driver_data *pdd = &bma253->pdd;
+    enum bma253_int_num int_num = pdd->int_num;
 
-struct fifo_cfg {
-	enum fifo_mode fifo_mode;
-	enum fifo_data fifo_data;
-};
+    pdd->int_ref_cnt++;
+
+    if (pdd->int_ref_cnt == 1) {
+        hal_gpio_irq_enable(bma253->sensor.s_itf.si_ints[int_num].host_pin);
+    }
+}
+
+static void
+disable_intpin(struct bma253 * bma253)
+{
+    struct bma253_private_driver_data *pdd = &bma253->pdd;
+    enum bma253_int_num int_num = pdd->int_num;
+
+    if (pdd->int_ref_cnt == 0) {
+        return;
+    }
+
+    pdd->int_ref_cnt--;
+
+    if (pdd->int_ref_cnt == 0) {
+        hal_gpio_irq_disable(bma253->sensor.s_itf.si_ints[int_num].host_pin);
+    }
+}
+#endif
+
+static int
+self_test_enable(const struct bma253 * bma253,
+                 enum self_test_ampl ampl,
+                 enum self_test_sign sign,
+                 enum axis axis)
+{
+    struct self_test_cfg self_test_cfg;
+
+    self_test_cfg.self_test_ampl    = ampl;
+    self_test_cfg.self_test_sign    = sign;
+    self_test_cfg.self_test_axis    = axis;
+    self_test_cfg.self_test_enabled = true;
+
+    return bma253_set_self_test_cfg(bma253, &self_test_cfg);
+}
+
+static int
+self_test_disable(const struct bma253 * bma253)
+{
+    struct self_test_cfg self_test_cfg;
+
+    self_test_cfg.self_test_ampl    = SELF_TEST_AMPL_LOW;
+    self_test_cfg.self_test_sign    = SELF_TEST_SIGN_NEGATIVE;
+    self_test_cfg.self_test_axis    = -1;
+    self_test_cfg.self_test_enabled = false;
+
+    return bma253_set_self_test_cfg(bma253, &self_test_cfg);
+}
+
+static int
+self_test_nudge(const struct bma253 * bma253,
+                enum self_test_ampl ampl,
+                enum self_test_sign sign,
+                enum axis axis,
+                enum bma253_g_range g_range,
+                struct accel_data * accel_data)
+{
+    int rc;
+
+    rc = self_test_enable(bma253, ampl, sign, axis);
+    if (rc != 0) {
+        return rc;
+    }
+
+    delay_msec(50);
+
+    rc = bma253_get_accel(bma253, g_range, axis, accel_data);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = self_test_disable(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    delay_msec(50);
+
+    return 0;
+}
+
+static int
+self_test_axis(const struct bma253 * bma253,
+               enum axis axis,
+               enum bma253_g_range g_range,
+               float * delta_hi_g,
+               float * delta_lo_g)
+{
+    struct accel_data accel_neg_hi;
+    struct accel_data accel_neg_lo;
+    struct accel_data accel_pos_hi;
+    struct accel_data accel_pos_lo;
+    int rc;
+
+    rc = self_test_nudge(bma253,
+                         SELF_TEST_AMPL_HIGH,
+                         SELF_TEST_SIGN_NEGATIVE,
+                         axis,
+                         g_range,
+                         &accel_neg_hi);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = self_test_nudge(bma253,
+                         SELF_TEST_AMPL_LOW,
+                         SELF_TEST_SIGN_NEGATIVE,
+                         axis,
+                         g_range,
+                         &accel_neg_lo);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = self_test_nudge(bma253,
+                         SELF_TEST_AMPL_HIGH,
+                         SELF_TEST_SIGN_POSITIVE,
+                         axis,
+                         g_range,
+                         &accel_pos_hi);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = self_test_nudge(bma253,
+                         SELF_TEST_AMPL_LOW,
+                         SELF_TEST_SIGN_POSITIVE,
+                         axis,
+                         g_range,
+                         &accel_pos_lo);
+    if (rc != 0) {
+        return rc;
+    }
+
+    *delta_hi_g = accel_pos_hi.accel_g - accel_neg_hi.accel_g;
+    *delta_lo_g = accel_pos_lo.accel_g - accel_neg_lo.accel_g;
+
+    return 0;
+}
+
+int
+bma253_self_test(struct bma253 * bma253,
+                 float delta_high_mult,
+                 float delta_low_mult,
+                 bool * self_test_fail)
+{
+    const struct bma253_cfg * cfg;
+    enum bma253_power_mode request_power;
+    int rc;
+    float delta_hi_x_g;
+    float delta_lo_x_g;
+    float delta_hi_y_g;
+    float delta_lo_y_g;
+    float delta_hi_z_g;
+    float delta_lo_z_g;
+    bool fail;
+
+    cfg = &bma253->cfg;
+
+    request_power = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253, &request_power, 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_g_range(bma253, BMA253_G_RANGE_8);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = self_test_axis(bma253,
+                        AXIS_X,
+                        BMA253_G_RANGE_8,
+                        &delta_hi_x_g,
+                        &delta_lo_x_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = self_test_axis(bma253,
+                        AXIS_Y,
+                        BMA253_G_RANGE_8,
+                        &delta_hi_y_g,
+                        &delta_lo_y_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = self_test_axis(bma253,
+                        AXIS_Z,
+                        BMA253_G_RANGE_8,
+                        &delta_hi_z_g,
+                        &delta_lo_z_g);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = self_test_disable(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_g_range(bma253, cfg->g_range);
+    if (rc != 0) {
+        return rc;
+    }
+
+    delay_msec(50);
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    fail = false;
+    if (delta_hi_x_g < delta_high_mult * 0.8) {
+        fail = true;
+    }
+    if (delta_lo_x_g < delta_low_mult * 0.8) {
+        fail = true;
+    }
+    if (delta_hi_y_g < delta_high_mult * 0.8) {
+        fail = true;
+    }
+    if (delta_lo_y_g < delta_low_mult * 0.8) {
+        fail = true;
+    }
+    if (delta_hi_z_g < delta_high_mult * 0.4) {
+        fail = true;
+    }
+    if (delta_lo_z_g < delta_low_mult * 0.4) {
+        fail = true;
+    }
+
+    *self_test_fail = fail;
+
+    return 0;
+}
+
+static int
+axis_offset_compensation(const struct bma253 * bma253,
+                         enum axis axis,
+                         enum bma253_offset_comp_target target)
+{
+    int rc;
+    bool ready;
+    enum bma253_offset_comp_target target_z;
+    enum bma253_offset_comp_target target_y;
+    enum bma253_offset_comp_target target_x;
+    uint32_t count;
+
+    rc = bma253_get_fast_ofc_cfg(bma253,
+                                 &ready,
+                                 &target_z,
+                                 &target_y,
+                                 &target_x);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (!ready) {
+        BMA253_ERROR("offset compensation already in progress\n");
+        return SYS_ETIMEOUT;
+    }
+
+    rc = bma253_set_fast_ofc_cfg(bma253, axis, target, true);
+    if (rc != 0) {
+        return rc;
+    }
+
+    for (count = 1000; count != 0; count--) {
+        rc = bma253_get_fast_ofc_cfg(bma253,
+                                     &ready,
+                                     &target_z,
+                                     &target_y,
+                                     &target_x);
+        if (rc != 0) {
+            return rc;
+        }
+
+        if (ready) {
+            break;
+        }
+    }
+
+    if (count == 0) {
+        BMA253_ERROR("offset compensation did not complete\n");
+        return SYS_ETIMEOUT;
+    }
+
+    return 0;
+}
+
+int
+bma253_offset_compensation(struct bma253 * bma253,
+                           enum bma253_offset_comp_target target_x,
+                           enum bma253_offset_comp_target target_y,
+                           enum bma253_offset_comp_target target_z)
+{
+    const struct bma253_cfg * cfg;
+    enum bma253_power_mode request_power;
+    int rc;
+
+    cfg = &bma253->cfg;
+
+    request_power = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253, &request_power, 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_g_range(bma253, BMA253_G_RANGE_2);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = axis_offset_compensation(bma253, AXIS_X, target_x);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = axis_offset_compensation(bma253, AXIS_Y, target_y);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = axis_offset_compensation(bma253, AXIS_Z, target_z);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_get_ofc_offset(bma253, AXIS_X, &bma253->cfg.offset_x_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = bma253_get_ofc_offset(bma253, AXIS_Y, &bma253->cfg.offset_y_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = bma253_get_ofc_offset(bma253, AXIS_Z, &bma253->cfg.offset_z_g);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_g_range(bma253, cfg->g_range);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+int
+bma253_query_offsets(struct bma253 * bma253,
+                     float * offset_x_g,
+                     float * offset_y_g,
+                     float * offset_z_g)
+{
+    const struct bma253_cfg * cfg;
+    enum bma253_power_mode request_power[5];
+    int rc;
+    float val_offset_x_g;
+    float val_offset_y_g;
+    float val_offset_z_g;
+    bool mismatch;
+
+    cfg = &bma253->cfg;
+
+    request_power[0] = BMA253_POWER_MODE_SUSPEND;
+    request_power[1] = BMA253_POWER_MODE_STANDBY;
+    request_power[2] = BMA253_POWER_MODE_LPM_1;
+    request_power[3] = BMA253_POWER_MODE_LPM_2;
+    request_power[4] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_get_ofc_offset(bma253, AXIS_X, &val_offset_x_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = bma253_get_ofc_offset(bma253, AXIS_Y, &val_offset_y_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = bma253_get_ofc_offset(bma253, AXIS_Z, &val_offset_z_g);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    mismatch = false;
+    if (cfg->offset_x_g != val_offset_x_g) {
+        BMA253_ERROR("X compensation offset value mismatch\n");
+        mismatch = true;
+    }
+    if (cfg->offset_y_g != val_offset_y_g) {
+        BMA253_ERROR("Y compensation offset value mismatch\n");
+        mismatch = true;
+    }
+    if (cfg->offset_z_g != val_offset_z_g) {
+        BMA253_ERROR("Z compensation offset value mismatch\n");
+        mismatch = true;
+    }
+
+    if (mismatch) {
+        return SYS_EINVAL;
+    }
+
+    *offset_x_g = val_offset_x_g;
+    *offset_y_g = val_offset_y_g;
+    *offset_z_g = val_offset_z_g;
+
+    return 0;
+}
 
-int bma253_get_fifo_cfg(const struct sensor_itf * itf,
-			struct fifo_cfg * fifo_cfg)
-{
-	uint8_t data;
-	int rc;
-
-	rc = get_register(itf, REG_ADDR_FIFO_CONFIG_1, &data);
-	if (rc != 0)
-		return rc;
-
-	switch ((data >> 6) & 0x03) {
-	case 0x03:
-		BMA253_ERROR("unknown FIFO_CONFIG_1 reg value 0x%02X\n", data);
-	case 0x00:
-		fifo_cfg->fifo_mode = FIFO_MODE_BYPASS;
-		break;
-	case 0x01:
-		fifo_cfg->fifo_mode = FIFO_MODE_FIFO;
-		break;
-	case 0x02:
-		fifo_cfg->fifo_mode = FIFO_MODE_STREAM;
-		break;
-	}
-
-	switch ((data >> 0) & 0x03) {
-	case 0x00:
-		fifo_cfg->fifo_data = FIFO_DATA_X_AND_Y_AND_Z;
-		break;
-	case 0x01:
-		fifo_cfg->fifo_data = FIFO_DATA_X_ONLY;
-		break;
-	case 0x02:
-		fifo_cfg->fifo_data = FIFO_DATA_Y_ONLY;
-		break;
-	case 0x03:
-		fifo_cfg->fifo_data = FIFO_DATA_Z_ONLY;
-		break;
-	}
-
-	return 0;
-}
-
-int bma253_set_fifo_cfg(const struct sensor_itf * itf,
-			const struct fifo_cfg * fifo_cfg)
-{
-	uint8_t data;
-
-	data = 0;
-
-	switch (fifo_cfg->fifo_mode) {
-	case FIFO_MODE_BYPASS:
-		data |= 0x00 << 6;
-		break;
-	case FIFO_MODE_FIFO:
-		data |= 0x01 << 6;
-		break;
-	case FIFO_MODE_STREAM:
-		data |= 0x02 << 6;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (fifo_cfg->fifo_data) {
-	case FIFO_DATA_X_AND_Y_AND_Z:
-		data |= 0x00 << 0;
-		break;
-	case FIFO_DATA_X_ONLY:
-		data |= 0x01 << 0;
-		break;
-	case FIFO_DATA_Y_ONLY:
-		data |= 0x02 << 0;
-		break;
-	case FIFO_DATA_Z_ONLY:
-		data |= 0x03 << 0;
-		break;
-	}
-
-	return set_register(itf, REG_ADDR_FIFO_CONFIG_1, data);
-}
-
-int bma253_get_fifo(const struct sensor_itf * itf,
-		    enum bma253_g_range g_range,
-		    enum fifo_data fifo_data,
-		    struct accel_data * accel_data)
-{
-	float accel_scale;
-	uint8_t size, iter;
-	uint8_t data[AXIS_ALL << 1];
-	int rc;
-
-	switch (g_range) {
-	case BMA253_G_RANGE_2:
-		accel_scale = 0.00098;
-		break;
-	case BMA253_G_RANGE_4:
-		accel_scale = 0.00195;
-		break;
-	case BMA253_G_RANGE_8:
-		accel_scale = 0.00391;
-		break;
-	case BMA253_G_RANGE_16:
-		accel_scale = 0.00781;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	switch (fifo_data) {
-	case FIFO_DATA_X_AND_Y_AND_Z:
-		size = AXIS_ALL << 1;
-		break;
-	case FIFO_DATA_X_ONLY:
-	case FIFO_DATA_Y_ONLY:
-	case FIFO_DATA_Z_ONLY:
-		size = 1 << 1;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = get_registers(itf, REG_ADDR_FIFO_DATA, data, size);
-	if (rc != 0)
-		return rc;
-
-	for (iter = 0; iter < size; iter += 2)
-		compute_accel_data(accel_data + (iter >> 1),
-				   data + iter,
-				   accel_scale);
-
-	return 0;
-}
-
-static int self_test_enable(const struct sensor_itf * itf,
-			    enum self_test_ampl ampl,
-			    enum self_test_sign sign,
-			    enum axis axis)
-{
-	struct self_test_cfg self_test_cfg;
-
-	self_test_cfg.self_test_ampl    = ampl;
-	self_test_cfg.self_test_sign    = sign;
-	self_test_cfg.self_test_axis    = axis;
-	self_test_cfg.self_test_enabled = true;
-
-	return bma253_set_self_test_cfg(itf, &self_test_cfg);
-}
-
-static int self_test_disable(const struct sensor_itf * itf)
-{
-	struct self_test_cfg self_test_cfg;
-
-	self_test_cfg.self_test_ampl    = SELF_TEST_AMPL_LOW;
-	self_test_cfg.self_test_sign    = SELF_TEST_SIGN_NEGATIVE;
-	self_test_cfg.self_test_axis    = -1;
-	self_test_cfg.self_test_enabled = false;
-
-	return bma253_set_self_test_cfg(itf, &self_test_cfg);
-}
-
-static int self_test_nudge(const struct sensor_itf * itf,
-			   enum self_test_ampl ampl,
-			   enum self_test_sign sign,
-			   enum axis axis,
-			   enum bma253_g_range g_range,
-			   struct accel_data * accel_data)
-{
-	int rc;
-
-	rc = self_test_enable(itf,
-			      ampl,
-			      sign,
-			      axis);
-	if (rc != 0)
-		return rc;
-
-	delay_msec(50);
-
-	rc = bma253_get_accel(itf,
-			      g_range,
-			      axis,
-			      accel_data);
-	if (rc != 0)
-		return rc;
-
-	rc = self_test_disable(itf);
-	if (rc != 0)
-		return rc;
-
-	delay_msec(50);
-
-	return 0;
-}
-
-static int self_test_axis(const struct sensor_itf * itf,
-			  enum axis axis,
-			  enum bma253_g_range g_range,
-			  float * delta_hi_g,
-			  float * delta_lo_g)
-{
-	struct accel_data accel_neg_hi;
-	struct accel_data accel_neg_lo;
-	struct accel_data accel_pos_hi;
-	struct accel_data accel_pos_lo;
-	int rc;
-
-	rc = self_test_nudge(itf,
-			     SELF_TEST_AMPL_HIGH,
-			     SELF_TEST_SIGN_NEGATIVE,
-			     axis,
-			     g_range,
-			     &accel_neg_hi);
-	if (rc != 0)
-		return rc;
-	rc = self_test_nudge(itf,
-			     SELF_TEST_AMPL_LOW,
-			     SELF_TEST_SIGN_NEGATIVE,
-			     axis,
-			     g_range,
-			     &accel_neg_lo);
-	if (rc != 0)
-		return rc;
-	rc = self_test_nudge(itf,
-			     SELF_TEST_AMPL_HIGH,
-			     SELF_TEST_SIGN_POSITIVE,
-			     axis,
-			     g_range,
-			     &accel_pos_hi);
-	if (rc != 0)
-		return rc;
-	rc = self_test_nudge(itf,
-			     SELF_TEST_AMPL_LOW,
-			     SELF_TEST_SIGN_POSITIVE,
-			     axis,
-			     g_range,
-			     &accel_pos_lo);
-	if (rc != 0)
-		return rc;
-
-	*delta_hi_g = accel_pos_hi.accel_g - accel_neg_hi.accel_g;
-	*delta_lo_g = accel_pos_lo.accel_g - accel_neg_lo.accel_g;
-
-	return 0;
-}
-
-int bma253_self_test(struct bma253 * bma253,
-		     float delta_high_mult,
-		     float delta_low_mult,
-		     bool * self_test_fail)
-{
-	const struct sensor_itf * itf;
-	enum bma253_g_range g_range;
-	int rc;
-	float delta_hi_x_g;
-	float delta_lo_x_g;
-	float delta_hi_y_g;
-	float delta_lo_y_g;
-	float delta_hi_z_g;
-	float delta_lo_z_g;
-	bool fail;
-
-	itf = SENSOR_GET_ITF(&bma253->sensor);
-	g_range = bma253->cfg.g_range;
-
-	rc = bma253_set_g_range(itf, BMA253_G_RANGE_8);
-	if (rc != 0)
-		return rc;
-
-	rc = self_test_axis(itf,
-			    AXIS_X,
-			    BMA253_G_RANGE_8,
-			    &delta_hi_x_g,
-			    &delta_lo_x_g);
-	if (rc != 0)
-		return rc;
-	rc = self_test_axis(itf,
-			    AXIS_Y,
-			    BMA253_G_RANGE_8,
-			    &delta_hi_y_g,
-			    &delta_lo_y_g);
-	if (rc != 0)
-		return rc;
-	rc = self_test_axis(itf,
-			    AXIS_Z,
-			    BMA253_G_RANGE_8,
-			    &delta_hi_z_g,
-			    &delta_lo_z_g);
-	if (rc != 0)
-		return rc;
-
-	rc = self_test_disable(itf);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_g_range(itf, g_range);
-	if (rc != 0)
-		return rc;
-
-	delay_msec(50);
-
-	fail = false;
-	if (delta_hi_x_g < delta_high_mult * 0.8)
-		fail = true;
-	if (delta_lo_x_g < delta_low_mult * 0.8)
-		fail = true;
-	if (delta_hi_y_g < delta_high_mult * 0.8)
-		fail = true;
-	if (delta_lo_y_g < delta_low_mult * 0.8)
-		fail = true;
-	if (delta_hi_z_g < delta_high_mult * 0.4)
-		fail = true;
-	if (delta_lo_z_g < delta_low_mult * 0.4)
-		fail = true;
-
-	*self_test_fail = fail;
-
-	return 0;
-}
-
-static int axis_offset_compensation(const struct sensor_itf * itf,
-				    enum axis axis,
-				    enum bma253_offset_comp_target target)
-{
-	int rc;
-	bool ready;
-	enum bma253_offset_comp_target target_z;
-	enum bma253_offset_comp_target target_y;
-	enum bma253_offset_comp_target target_x;
-	uint32_t count;
-
-	rc = bma253_get_fast_ofc_cfg(itf,
-				     &ready,
-				     &target_z,
-				     &target_y,
-				     &target_x);
-	if (rc != 0)
-		return rc;
-
-	if (!ready) {
-		BMA253_ERROR("offset compensation already in progress\n");
-		return SYS_ETIMEOUT;
-	}
-
-	rc = bma253_set_fast_ofc_cfg(itf,
-				     axis,
-				     target,
-				     true);
-	if (rc != 0)
-		return rc;
-
-	for (count = 1000; count != 0; count--) {
-		rc = bma253_get_fast_ofc_cfg(itf,
-					     &ready,
-					     &target_z,
-					     &target_y,
-					     &target_x);
-		if (rc != 0)
-			return rc;
-
-		if (ready)
-			break;
-	}
-
-	if (count == 0) {
-		BMA253_ERROR("offset compensation did not complete\n");
-		return SYS_ETIMEOUT;
-	}
-
-	return 0;
-}
-
-int bma253_offset_compensation(struct bma253 * bma253,
-			       enum bma253_offset_comp_target target_x,
-			       enum bma253_offset_comp_target target_y,
-			       enum bma253_offset_comp_target target_z)
-{
-	const struct sensor_itf * itf;
-	enum bma253_g_range g_range;
-	int rc;
-
-	itf = SENSOR_GET_ITF(&bma253->sensor);
-	g_range = bma253->cfg.g_range;
-
-	rc = bma253_set_g_range(itf, BMA253_G_RANGE_2);
-	if (rc != 0)
-		return rc;
-
-	rc = axis_offset_compensation(itf,
-				      AXIS_X,
-				      target_x);
-	if (rc != 0)
-		return rc;
-	rc = axis_offset_compensation(itf,
-				      AXIS_Y,
-				      target_y);
-	if (rc != 0)
-		return rc;
-	rc = axis_offset_compensation(itf,
-				      AXIS_Z,
-				      target_z);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_get_ofc_offset(itf,
-				   AXIS_X,
-				   &bma253->cfg.offset_x_g);
-	if (rc != 0)
-		return rc;
-	rc = bma253_get_ofc_offset(itf,
-				   AXIS_Y,
-				   &bma253->cfg.offset_y_g);
-	if (rc != 0)
-		return rc;
-	rc = bma253_get_ofc_offset(itf,
-				   AXIS_Z,
-				   &bma253->cfg.offset_z_g);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_g_range(itf, g_range);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-int bma253_stream_read(struct bma253 * bma253,
-		       bma253_stream_read_func_t read_func,
-		       void * read_arg,
-		       uint32_t time_ms)
-{
-	const struct sensor_itf * itf;
-	enum bma253_g_range g_range;
-	int rc;
-	os_time_t stop_ticks;
-	struct int_enable int_enable;
-
-	itf = SENSOR_GET_ITF(&bma253->sensor);
-	g_range = bma253->cfg.g_range;
+int
+bma253_write_offsets(struct bma253 * bma253,
+                     float offset_x_g,
+                     float offset_y_g,
+                     float offset_z_g)
+{
+    struct bma253_cfg * cfg;
+    enum bma253_power_mode request_power[5];
+    int rc;
+
+    cfg = &bma253->cfg;
+
+    request_power[0] = BMA253_POWER_MODE_SUSPEND;
+    request_power[1] = BMA253_POWER_MODE_STANDBY;
+    request_power[2] = BMA253_POWER_MODE_LPM_1;
+    request_power[3] = BMA253_POWER_MODE_LPM_2;
+    request_power[4] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_set_ofc_offset(bma253, AXIS_X, offset_x_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = bma253_set_ofc_offset(bma253, AXIS_Y, offset_y_g);
+    if (rc != 0) {
+        return rc;
+    }
+    rc = bma253_set_ofc_offset(bma253, AXIS_Z, offset_z_g);
+    if (rc != 0) {
+        return rc;
+    }
+
+    cfg->offset_x_g = offset_x_g;
+    cfg->offset_y_g = offset_y_g;
+    cfg->offset_z_g = offset_z_g;
+
+    return 0;
+}
+
+int
+bma253_stream_read(struct bma253 * bma253,
+                   bma253_stream_read_func_t read_func,
+                   void * read_arg,
+                   uint32_t time_ms)
+{
+    const struct bma253_cfg * cfg;
+    int rc;
+    enum bma253_power_mode request_power;
+    struct int_enable int_enable_org;
+    struct int_enable int_enable = { 0 };
+    os_time_t time_ticks;
+    os_time_t stop_ticks;
+    struct accel_data accel_data[AXIS_ALL];
+    struct sensor_accel_data sad;
+    struct bma253_private_driver_data *pdd;
+
+    cfg = &bma253->cfg;
+    pdd = &bma253->pdd;
 
     stop_ticks = 0;
-	if (time_ms != 0) {
-		uint32_t time_ticks;
-
-		rc = os_time_ms_to_ticks(time_ms, &time_ticks);
-		if (rc != 0)
-			return rc;
-
-		stop_ticks = os_time_get() + time_ticks;
-	}
-
-	interrupt_undo(bma253->ints + BMA253_INT_PIN_1);
-
-	int_enable.flat_int_enable          = false;
-	int_enable.orient_int_enable        = false;
-	int_enable.s_tap_int_enable         = false;
-	int_enable.d_tap_int_enable         = false;
-	int_enable.slope_z_int_enable       = false;
-	int_enable.slope_y_int_enable       = false;
-	int_enable.slope_x_int_enable       = false;
-	int_enable.fifo_wmark_int_enable    = true;
-	int_enable.fifo_full_int_enable     = false;
-	int_enable.data_int_enable          = false;
-	int_enable.low_g_int_enable         = false;
-	int_enable.high_g_z_int_enable      = false;
-	int_enable.high_g_y_int_enable      = false;
-	int_enable.high_g_x_int_enable      = false;
-	int_enable.no_motion_select         = false;
-	int_enable.slow_no_mot_z_int_enable = false;
-	int_enable.slow_no_mot_y_int_enable = false;
-	int_enable.slow_no_mot_x_int_enable = false;
-
-	rc = bma253_set_int_enable(itf, &int_enable);
-	if (rc != 0)
-		return rc;
-
-	for (;;) {
-		struct accel_data accel_data[AXIS_ALL];
-		struct sensor_accel_data sad;
-
-		interrupt_wait(bma253->ints + BMA253_INT_PIN_1);
-
-		rc = bma253_get_fifo(itf,
-				     g_range,
-				     FIFO_DATA_X_AND_Y_AND_Z,
-				     accel_data);
-		if (rc != 0)
-			return rc;
-
-		sad.sad_x = accel_data[AXIS_X].accel_g;
-		sad.sad_y = accel_data[AXIS_Y].accel_g;
-		sad.sad_z = accel_data[AXIS_Z].accel_g;
-		sad.sad_x_is_valid = 1;
-		sad.sad_y_is_valid = 1;
-		sad.sad_z_is_valid = 1;
-
-		if (read_func(read_arg, &sad))
-			break;
-
-		if (time_ms != 0 &&
-		    OS_TIME_TICK_GT(os_time_get(), stop_ticks))
-			break;
-	}
-
-	int_enable.flat_int_enable          = false;
-	int_enable.orient_int_enable        = false;
-	int_enable.s_tap_int_enable         = false;
-	int_enable.d_tap_int_enable         = false;
-	int_enable.slope_z_int_enable       = false;
-	int_enable.slope_y_int_enable       = false;
-	int_enable.slope_x_int_enable       = false;
-	int_enable.fifo_wmark_int_enable    = false;
-	int_enable.fifo_full_int_enable     = false;
-	int_enable.data_int_enable          = false;
-	int_enable.low_g_int_enable         = false;
-	int_enable.high_g_z_int_enable      = false;
-	int_enable.high_g_y_int_enable      = false;
-	int_enable.high_g_x_int_enable      = false;
-	int_enable.no_motion_select         = false;
-	int_enable.slow_no_mot_z_int_enable = false;
-	int_enable.slow_no_mot_y_int_enable = false;
-	int_enable.slow_no_mot_x_int_enable = false;
-
-	rc = bma253_set_int_enable(itf, &int_enable);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-int bma253_wait_for_tap(struct bma253 * bma253,
-			enum bma253_tap_type tap_type)
-{
-	const struct sensor_itf * itf;
-	struct int_enable int_enable;
-	int rc;
-
-	itf = SENSOR_GET_ITF(&bma253->sensor);
-
-	switch (tap_type) {
-	case BMA253_TAP_TYPE_DOUBLE:
-	case BMA253_TAP_TYPE_SINGLE:
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	interrupt_undo(bma253->ints + BMA253_INT_PIN_2);
-
-	int_enable.flat_int_enable          = false;
-	int_enable.orient_int_enable        = false;
-	int_enable.s_tap_int_enable         = tap_type == BMA253_TAP_TYPE_SINGLE;
-	int_enable.d_tap_int_enable         = tap_type == BMA253_TAP_TYPE_DOUBLE;
-	int_enable.slope_z_int_enable       = false;
-	int_enable.slope_y_int_enable       = false;
-	int_enable.slope_x_int_enable       = false;
-	int_enable.fifo_wmark_int_enable    = false;
-	int_enable.fifo_full_int_enable     = false;
-	int_enable.data_int_enable          = false;
-	int_enable.low_g_int_enable         = false;
-	int_enable.high_g_z_int_enable      = false;
-	int_enable.high_g_y_int_enable      = false;
-	int_enable.high_g_x_int_enable      = false;
-	int_enable.no_motion_select         = false;
-	int_enable.slow_no_mot_z_int_enable = false;
-	int_enable.slow_no_mot_y_int_enable = false;
-	int_enable.slow_no_mot_x_int_enable = false;
-
-	rc = bma253_set_int_enable(itf, &int_enable);
-	if (rc != 0)
-		return rc;
-
-	interrupt_wait(bma253->ints + BMA253_INT_PIN_2);
-
-	int_enable.flat_int_enable          = false;
-	int_enable.orient_int_enable        = false;
-	int_enable.s_tap_int_enable         = false;
-	int_enable.d_tap_int_enable         = false;
-	int_enable.slope_z_int_enable       = false;
-	int_enable.slope_y_int_enable       = false;
-	int_enable.slope_x_int_enable       = false;
-	int_enable.fifo_wmark_int_enable    = false;
-	int_enable.fifo_full_int_enable     = false;
-	int_enable.data_int_enable          = false;
-	int_enable.low_g_int_enable         = false;
-	int_enable.high_g_z_int_enable      = false;
-	int_enable.high_g_y_int_enable      = false;
-	int_enable.high_g_x_int_enable      = false;
-	int_enable.no_motion_select         = false;
-	int_enable.slow_no_mot_z_int_enable = false;
-	int_enable.slow_no_mot_y_int_enable = false;
-	int_enable.slow_no_mot_x_int_enable = false;
-
-	rc = bma253_set_int_enable(itf, &int_enable);
-	if (rc != 0)
-		return rc;
-
-	return 0;
-}
-
-// TODO In suspend mode (or low-power mode 1) an interface idle time of at least 450 us is required
-//      after a write.
-// TODO enter/exit power modes dynamically - will likely need to pull reset out
-// TODO public API setter for power mode
-
-struct sensor_driver_read_context {
-	int result_code;
-	sensor_data_func_t data_func;
-	void * data_arg;
-	struct sensor * sensor;
-};
 
-static bool sensor_driver_read_func(void * arg,
-				    struct sensor_accel_data * sad)
+    request_power = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253, &request_power, 1);
+    if (rc != 0) {
+        return rc;
+    }
+
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    undo_interrupt(&bma253->intr);
+
+    if (pdd->interrupt) {
+        return SYS_EBUSY;
+    }
+    pdd->interrupt = &bma253->intr;
+    enable_intpin(bma253);
+#endif
+
+    rc = bma253_get_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        goto done;
+    }
+
+    /* Leave tap configured as it is since it is on int2*/
+    int_enable.s_tap_int_enable = int_enable_org.s_tap_int_enable;
+    int_enable.d_tap_int_enable = int_enable_org.d_tap_int_enable;
+    int_enable.data_int_enable = true;
+
+    rc = bma253_set_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        goto done;
+    }
+
+    if (time_ms != 0) {
+        rc = os_time_ms_to_ticks(time_ms, &time_ticks);
+        if (rc != 0) {
+            goto done;
+        }
+        stop_ticks = os_time_get() + time_ticks;
+    }
+
+    for (;;) {
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+        wait_interrupt(&bma253->intr, pdd->int_num);
+#else
+        switch (cfg->filter_bandwidth) {
+        case BMA253_FILTER_BANDWIDTH_7_81_HZ:
+            delay_msec(128);
+            break;
+        case BMA253_FILTER_BANDWIDTH_15_63_HZ:
+            delay_msec(64);
+            break;
+        case BMA253_FILTER_BANDWIDTH_31_25_HZ:
+            delay_msec(32);
+            break;
+        case BMA253_FILTER_BANDWIDTH_62_5_HZ:
+            delay_msec(16);
+            break;
+        case BMA253_FILTER_BANDWIDTH_125_HZ:
+            delay_msec(8);
+            break;
+        case BMA253_FILTER_BANDWIDTH_250_HZ:
+            delay_msec(4);
+            break;
+        case BMA253_FILTER_BANDWIDTH_500_HZ:
+            delay_msec(2);
+            break;
+        case BMA253_FILTER_BANDWIDTH_1000_HZ:
+            delay_msec(1);
+            break;
+        default:
+            delay_msec(1000);
+            break;
+        }
+#endif
+
+        rc = bma253_get_fifo(bma253,
+                             cfg->g_range,
+                             FIFO_DATA_X_AND_Y_AND_Z,
+                             accel_data);
+        if (rc != 0) {
+            goto done;
+        }
+
+        sad.sad_x = accel_data[AXIS_X].accel_g;
+        sad.sad_y = accel_data[AXIS_Y].accel_g;
+        sad.sad_z = accel_data[AXIS_Z].accel_g;
+        sad.sad_x_is_valid = 1;
+        sad.sad_y_is_valid = 1;
+        sad.sad_z_is_valid = 1;
+
+        if (read_func(read_arg, &sad)) {
+            break;
+        }
+
+        if (time_ms != 0 && OS_TIME_TICK_GT(os_time_get(), stop_ticks)) {
+                break;
+        }
+    }
+
+    rc = bma253_set_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        goto done;
+    }
+
+done:
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    pdd->interrupt = NULL;
+    disable_intpin(bma253);
+#endif
+
+    return rc;
+}
+
+int
+bma253_current_temp(struct bma253 * bma253,
+                    float * temp_c)
+{
+    enum bma253_power_mode request_power[3];
+    int rc;
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_get_temp(bma253, temp_c);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+int
+bma253_current_orient(struct bma253 * bma253,
+                      struct bma253_orient_xyz * orient_xyz)
+{
+    enum bma253_power_mode request_power[3];
+    int rc;
+    struct int_enable int_enable_org;
+    struct int_enable int_enable = { 0 };
+    struct int_status int_status;
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_get_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        return rc;
+    }
+
+   /* Leave tap configured as it is since it is on int2*/
+    int_enable.s_tap_int_enable = int_enable_org.s_tap_int_enable;
+    int_enable.d_tap_int_enable = int_enable_org.d_tap_int_enable;
+
+    int_enable.orient_int_enable = true;
+
+    rc = bma253_set_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_get_int_status(bma253, &int_status);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* Back to original interrupts */
+    rc = bma253_set_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    orient_xyz->orient_xy  = int_status.device_orientation;
+    orient_xyz->downward_z = int_status.device_is_down;
+
+    return 0;
+}
+
+int
+bma253_wait_for_orient(struct bma253 * bma253,
+                       struct bma253_orient_xyz * orient_xyz)
 {
-	struct sensor_driver_read_context * context;
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    int rc;
+    enum bma253_power_mode request_power[3];
+    struct int_enable int_enable_org;
+    struct int_enable int_enable = {0};
+    struct int_status int_status;
+    struct bma253_private_driver_data *pdd;
+
+    pdd = &bma253->pdd;
+
+    if (pdd->interrupt) {
+        BMA253_ERROR("Interrupt used\n");
+        return SYS_EINVAL;
+    }
+
+    pdd->interrupt = &bma253->intr;
+    enable_intpin(bma253);
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        goto done;
+    }
+
+    undo_interrupt(&bma253->intr);
+
+    rc = bma253_get_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        return rc;
+    }
+
+   /* Leave tap configured as it is since it is on int2*/
+    int_enable.s_tap_int_enable = int_enable_org.s_tap_int_enable;
+    int_enable.d_tap_int_enable = int_enable_org.d_tap_int_enable;
+    int_enable.orient_int_enable = true;
+    rc = bma253_set_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        goto done;
+    }
+
+    wait_interrupt(&bma253->intr, pdd->int_num);
+
+    rc = bma253_get_int_status(bma253, &int_status);
+    if (rc != 0) {
+        goto done;
+    }
+
+    /* Back to original interrupts */
+    rc = bma253_set_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        goto done;
+    }
+
+    orient_xyz->orient_xy  = int_status.device_orientation;
+    orient_xyz->downward_z = int_status.device_is_down;
+
+done:
+    pdd->interrupt = NULL;
+    disable_intpin(bma253);
+    return rc;
+#else
+    return SYS_ENODEV;
+#endif
+}
 
-	context = (struct sensor_driver_read_context *)arg;
+int
+bma253_wait_for_high_g(struct bma253 * bma253)
+{
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    int rc;
+    enum bma253_power_mode request_power[3];
+    struct int_enable int_enable_org;
+    struct int_enable int_enable = { 0 };
+    struct bma253_private_driver_data *pdd;
+
+    pdd = &bma253->pdd;
+
+    if (pdd->interrupt) {
+        BMA253_ERROR("Interrupt used\n");
+        return SYS_EINVAL;
+    }
+
+    pdd->interrupt = &bma253->intr;
+    enable_intpin(bma253);
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        goto done;
+    }
+
+    undo_interrupt(&bma253->intr);
+
+    rc = bma253_get_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        return rc;
+    }
+
+   /* Leave tap configured as it is since it is on int2*/
+    int_enable.s_tap_int_enable = int_enable_org.s_tap_int_enable;
+    int_enable.d_tap_int_enable = int_enable_org.d_tap_int_enable;
+
+    int_enable.high_g_z_int_enable = true;
+    int_enable.high_g_y_int_enable = true;
+    int_enable.high_g_x_int_enable = true;
+
+    rc = bma253_set_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        goto done;
+    }
+
+    wait_interrupt(&bma253->intr, pdd->int_num);
+
+    rc = bma253_set_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        goto done;
+    }
+
+done:
+    pdd->interrupt = NULL;
+    disable_intpin(bma253);
+    return rc;
+#else
+    return SYS_ENODEV;
+#endif
+}
 
-	context->result_code = context->data_func(context->sensor,
-						  context->data_arg,
-						  sad,
-						  SENSOR_TYPE_ACCELEROMETER);
+int
+bma253_wait_for_low_g(struct bma253 * bma253)
+{
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    int rc;
+    enum bma253_power_mode request_power[3];
+    struct int_enable int_enable_org;
+    struct int_enable int_enable = { 0 };
+    struct bma253_private_driver_data *pdd;
+
+    pdd = &bma253->pdd;
+
+    if (pdd->interrupt) {
+        BMA253_ERROR("Interrupt used\n");
+        return SYS_EINVAL;
+    }
+
+    pdd->interrupt = &bma253->intr;
+    enable_intpin(bma253);
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        goto done;
+    }
+
+    undo_interrupt(&bma253->intr);
+
+    rc = bma253_get_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        return rc;
+    }
+
+   /* Leave tap configured as it is since it is on int2 */
+    int_enable.s_tap_int_enable = int_enable_org.s_tap_int_enable;
+    int_enable.d_tap_int_enable = int_enable_org.d_tap_int_enable;
+
+    int_enable.low_g_int_enable         = true;
+
+    rc = bma253_set_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        goto done;
+    }
+
+    wait_interrupt(&bma253->intr, pdd->int_num);
+
+    rc = bma253_set_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        goto done;
+    }
+
+done:
+    pdd->interrupt = NULL;
+    disable_intpin(bma253);
+    return 0;
+#else
+    return SYS_ENODEV;
+#endif
+}
 
-	return true;
+int
+bma253_wait_for_tap(struct bma253 * bma253,
+                    enum bma253_tap_type tap_type)
+{
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    int rc = 0;
+    enum bma253_power_mode request_power[3];
+    struct int_enable int_enable_org;
+    struct int_enable int_enable = { 0 };
+    struct int_routes int_routes;
+    struct int_routes int_routes_org;
+    struct bma253_private_driver_data *pdd;
+
+    pdd = &bma253->pdd;
+
+    switch (tap_type) {
+    case BMA253_TAP_TYPE_DOUBLE:
+    case BMA253_TAP_TYPE_SINGLE:
+        break;
+    default:
+        return SYS_EINVAL;
+    }
+
+    rc = bma253_get_int_routes(bma253, &int_routes_org);
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_routes = int_routes_org;
+    if (tap_type == BMA253_TAP_TYPE_DOUBLE) {
+        /* According to BMA253 when single tap shall not be used we should not
+         * route it to any INTX
+         */
+        int_routes.d_tap_int_route = pdd->int_route;
+        int_routes.s_tap_int_route = INT_ROUTE_NONE;
+    } else {
+        int_routes.d_tap_int_route = INT_ROUTE_NONE;
+        int_routes.s_tap_int_route = pdd->int_route;
+    }
+
+    rc = bma253_set_int_routes(bma253, &int_routes);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (pdd->interrupt) {
+        BMA253_ERROR("Interrupt used\n");
+        return SYS_EINVAL;
+    }
+
+    pdd->interrupt = &bma253->intr;
+    enable_intpin(bma253);
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        goto done;
+    }
+
+    undo_interrupt(&bma253->intr);
+
+    rc = bma253_get_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_enable.s_tap_int_enable         = tap_type == BMA253_TAP_TYPE_SINGLE;
+    int_enable.d_tap_int_enable         = tap_type == BMA253_TAP_TYPE_DOUBLE;
+
+    rc = bma253_set_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        goto done;
+    }
+
+    wait_interrupt(&bma253->intr, pdd->int_num);
+
+    rc = bma253_set_int_enable(bma253, &int_enable_org);
+    if (rc != 0) {
+        goto done;
+    }
+
+    rc = default_power(bma253);
+
+done:
+    pdd->interrupt = NULL;
+    disable_intpin(bma253);
+    /* Restore previous routing */
+    rc = bma253_set_int_routes(bma253, &int_routes_org);
+
+    return rc;
+#else
+    return SYS_ENODEV;
+#endif
 }
 
-static int sensor_driver_read(struct sensor * sensor,
-			      sensor_type_t sensor_type,
-			      sensor_data_func_t data_func,
-			      void * data_arg,
-			      uint32_t timeout)
+int
+bma253_power_settings(struct bma253 * bma253,
+                      enum bma253_power_mode power_mode,
+                      enum bma253_sleep_duration sleep_duration)
 {
-	struct bma253 * bma253;
-	struct sensor_driver_read_context context;
-	int rc;
+    struct bma253_cfg * cfg;
+
+    cfg = &bma253->cfg;
 
-	if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER))
-		return SYS_EINVAL;
+    cfg->power_mode     = power_mode;
+    cfg->sleep_duration = sleep_duration;
 
-	bma253 = (struct bma253 *)SENSOR_GET_DEVICE(sensor);
+    return default_power(bma253);
+}
 
-	context.data_func = data_func;
-	context.data_arg  = data_arg;
-	context.sensor    = sensor;
+static int
+sensor_driver_read(struct sensor * sensor,
+                   sensor_type_t sensor_type,
+                   sensor_data_func_t data_func,
+                   void * data_arg,
+                   uint32_t timeout)
+{
+    struct bma253 * bma253;
+    const struct bma253_cfg * cfg;
+    enum bma253_power_mode request_power[3];
+    int rc;
+    struct accel_data accel_data[AXIS_ALL];
+    struct sensor_accel_data sad;
+    float temp_c;
+    struct sensor_temp_data std;
+
+    if ((sensor_type & ~(SENSOR_TYPE_ACCELEROMETER |
+                         SENSOR_TYPE_AMBIENT_TEMPERATURE)) != 0) {
+        return SYS_EINVAL;
+    }
+
+    bma253 = (struct bma253 *)SENSOR_GET_DEVICE(sensor);
+    cfg = &bma253->cfg;
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        return rc;
+    }
+
+    if ((sensor_type & SENSOR_TYPE_ACCELEROMETER) != 0) {
+        rc = bma253_get_accel(bma253,
+                              cfg->g_range,
+                              AXIS_X,
+                              accel_data + AXIS_X);
+        if (rc != 0) {
+            return rc;
+        }
+        rc = bma253_get_accel(bma253,
+                              cfg->g_range,
+                              AXIS_Y,
+                              accel_data + AXIS_Y);
+        if (rc != 0) {
+            return rc;
+        }
+        rc = bma253_get_accel(bma253,
+                              cfg->g_range,
+                              AXIS_Z,
+                              accel_data + AXIS_Z);
+        if (rc != 0) {
+            return rc;
+        }
+
+        sad.sad_x = accel_data[AXIS_X].accel_g;
+        sad.sad_y = accel_data[AXIS_Y].accel_g;
+        sad.sad_z = accel_data[AXIS_Z].accel_g;
+        sad.sad_x_is_valid = 1;
+        sad.sad_y_is_valid = 1;
+        sad.sad_z_is_valid = 1;
+
+        rc = data_func(sensor,
+                       data_arg,
+                       &sad,
+                       SENSOR_TYPE_ACCELEROMETER);
+        if (rc != 0) {
+            return rc;
+        }
+    }
+
+    if ((sensor_type & SENSOR_TYPE_AMBIENT_TEMPERATURE) != 0) {
+        rc = bma253_get_temp(bma253, &temp_c);
+        if (rc != 0) {
+            return rc;
+        }
+
+        std.std_temp = temp_c;
+        std.std_temp_is_valid = 1;
+
+        rc = data_func(sensor,
+                       data_arg,
+                       &std,
+                       SENSOR_TYPE_AMBIENT_TEMPERATURE);
+        if (rc != 0) {
+            return rc;
+        }
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
 
-	rc = bma253_stream_read(bma253,
-				sensor_driver_read_func,
-				&context,
-				0);
-	if (rc != 0)
-		return rc;
+static int
+sensor_driver_get_config(struct sensor * sensor,
+                         sensor_type_t sensor_type,
+                         struct sensor_cfg * cfg)
+{
+    if ((sensor_type & ~(SENSOR_TYPE_ACCELEROMETER |
+                         SENSOR_TYPE_AMBIENT_TEMPERATURE)) != 0) {
+        return SYS_EINVAL;
+    }
+    if ((sensor_type & (sensor_type - 1)) != 0) {
+        return SYS_EINVAL;
+    }
+
+    if ((sensor_type & SENSOR_TYPE_ACCELEROMETER) != 0) {
+        cfg->sc_valtype = SENSOR_VALUE_TYPE_FLOAT_TRIPLET;
+    }
+    if ((sensor_type & SENSOR_TYPE_AMBIENT_TEMPERATURE) != 0) {
+        cfg->sc_valtype = SENSOR_VALUE_TYPE_FLOAT;
+    }
+
+    return 0;
+}
 
-	return context.result_code;
+static int
+sensor_driver_set_trigger_thresh(struct sensor * sensor,
+                                 sensor_type_t sensor_type,
+                                 struct sensor_type_traits * stt)
+{
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    struct bma253 * bma253;
+    const struct bma253_cfg * cfg;
+    int rc;
+    enum bma253_power_mode request_power[3];
+    const struct sensor_accel_data * low_thresh;
+    const struct sensor_accel_data * high_thresh;
+    struct int_enable int_enable;
+    float thresh;
+    struct low_g_int_cfg low_g_int_cfg;
+    struct high_g_int_cfg high_g_int_cfg;
+    struct bma253_private_driver_data *pdd;
+
+    if (sensor_type != SENSOR_TYPE_ACCELEROMETER) {
+        return SYS_EINVAL;
+    }
+
+    bma253 = (struct bma253 *)SENSOR_GET_DEVICE(sensor);
+    cfg = &bma253->cfg;
+    pdd = &bma253->pdd;
+
+    pdd->read_ctx.srec_type |= sensor_type;
+    pdd->registered_mask |= BMA253_READ_MASK;
+    enable_intpin(bma253);
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        goto done;
+    }
+
+    low_thresh  = stt->stt_low_thresh.sad;
+    high_thresh = stt->stt_high_thresh.sad;
+
+    rc = bma253_get_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        goto done;
+    }
+
+    if (low_thresh->sad_x_is_valid |
+        low_thresh->sad_y_is_valid |
+        low_thresh->sad_z_is_valid) {
+        thresh = INFINITY;
+
+        if (low_thresh->sad_x_is_valid) {
+            if (thresh > low_thresh->sad_x) {
+                thresh = low_thresh->sad_x;
+            }
+        }
+        if (low_thresh->sad_y_is_valid) {
+            if (thresh > low_thresh->sad_y) {
+                thresh = low_thresh->sad_y;
+            }
+        }
+        if (low_thresh->sad_z_is_valid) {
+            if (thresh > low_thresh->sad_z) {
+                thresh = low_thresh->sad_z;
+            }
+        }
+
+        low_g_int_cfg.delay_ms     = 20;
+        low_g_int_cfg.thresh_g     = thresh;
+        low_g_int_cfg.hyster_g     = 0.125;
+        low_g_int_cfg.axis_summing = false;
+
+        rc = bma253_set_low_g_int_cfg(bma253,
+                                      &low_g_int_cfg);
+        if (rc != 0) {
+            goto done;
+        }
+
+        int_enable.low_g_int_enable = true;
+    }
+
+    if (high_thresh->sad_x_is_valid |
+        high_thresh->sad_y_is_valid |
+        high_thresh->sad_z_is_valid) {
+        thresh = 0.0;
+
+        if (high_thresh->sad_x_is_valid) {
+            if (thresh < high_thresh->sad_x) {
+                thresh = high_thresh->sad_x;
+            }
+        }
+        if (high_thresh->sad_y_is_valid) {
+            if (thresh < high_thresh->sad_y) {
+                thresh = high_thresh->sad_y;
+            }
+        }
+        if (high_thresh->sad_z_is_valid) {
+            if (thresh < high_thresh->sad_z) {
+                thresh = high_thresh->sad_z;
+            }
+        }
+
+        high_g_int_cfg.hyster_g = 0.25;
+        high_g_int_cfg.delay_ms = 32;
+        high_g_int_cfg.thresh_g = thresh;
+
+        rc = bma253_set_high_g_int_cfg(bma253,
+                                       cfg->g_range,
+                                       &high_g_int_cfg);
+        if (rc != 0) {
+            goto done;
+        }
+
+        int_enable.high_g_z_int_enable = high_thresh->sad_z_is_valid;
+        int_enable.high_g_y_int_enable = high_thresh->sad_y_is_valid;
+        int_enable.high_g_x_int_enable = high_thresh->sad_x_is_valid;
+    }
+
+    rc = bma253_set_int_enable(bma253, &int_enable);
+
+done:
+    if (rc != 0) {
+        /* Something went wrong, unregister from interrupt */
+        pdd->read_ctx.srec_type &= ~sensor_type;
+        pdd->registered_mask &= ~BMA253_READ_MASK;
+        disable_intpin(bma253);
+    }
+
+    return rc;
+#else
+    return SYS_ENODEV;
+#endif
 }
 
-static int sensor_driver_get_config(struct sensor * sensor,
-				    sensor_type_t sensor_type,
-				    struct sensor_cfg * cfg)
+static int
+sensor_driver_unset_notification(struct sensor * sensor,
+                               sensor_event_type_t sensor_event_type)
 {
-	if (!(sensor_type & SENSOR_TYPE_ACCELEROMETER))
-		return SYS_EINVAL;
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    struct bma253 * bma253;
+    enum bma253_power_mode request_power[3];
+    struct int_enable int_enable;
+    struct int_routes int_routes;
+    struct bma253_private_driver_data *pdd;
+    int rc;
+
+    if ((sensor_event_type & ~(SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                               SENSOR_EVENT_TYPE_SINGLE_TAP)) != 0) {
+        return SYS_EINVAL;
+    }
+
+    /*XXX for now we do not support registering for both events */
+    if (sensor_event_type == (SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                                        SENSOR_EVENT_TYPE_SINGLE_TAP)) {
+        return SYS_EINVAL;
+    }
+
+    bma253 = (struct bma253 *)SENSOR_GET_DEVICE(sensor);
+    pdd = &bma253->pdd;
+
+    pdd->notify_ctx.snec_evtype &= ~sensor_event_type;
+    pdd->registered_mask &= ~BMA253_NOTIFY_MASK;
+    disable_intpin(bma253);
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* Clear route and interrupts. We can do it for single and double as driver
+     * supports notification only for one of them at the time
+     */
+    rc = bma253_get_int_routes(bma253, &int_routes);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (sensor_event_type & SENSOR_EVENT_TYPE_SINGLE_TAP) {
+        int_routes.s_tap_int_route = INT_ROUTE_NONE;
+    }
+
+    if (sensor_event_type & SENSOR_EVENT_TYPE_DOUBLE_TAP) {
+        int_routes.d_tap_int_route = INT_ROUTE_NONE;
+    }
+
+    rc = bma253_set_int_routes(bma253, &int_routes);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = bma253_get_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        return rc;
+    }
+
+    int_enable.d_tap_int_enable = false;
+    int_enable.s_tap_int_enable = false;
+
+    rc = bma253_set_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+#else
+    return SYS_ENODEV;
+#endif
+}
 
-	cfg->sc_valtype = SENSOR_VALUE_TYPE_FLOAT_TRIPLET;
+static int
+sensor_driver_set_notification(struct sensor * sensor,
+                               sensor_event_type_t sensor_event_type)
+{
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    struct bma253 * bma253;
+    int rc;
+    enum bma253_power_mode request_power[3];
+    struct int_enable int_enable;
+    struct int_routes int_routes;
+    struct bma253_private_driver_data *pdd;
+
+    if ((sensor_event_type & ~(SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                               SENSOR_EVENT_TYPE_SINGLE_TAP)) != 0) {
+        return SYS_EINVAL;
+    }
+
+    /*XXX for now we do not support registering for both events */
+    if (sensor_event_type == (SENSOR_EVENT_TYPE_DOUBLE_TAP |
+                                        SENSOR_EVENT_TYPE_SINGLE_TAP)) {
+        return SYS_EINVAL;
+    }
+
+    bma253 = (struct bma253 *)SENSOR_GET_DEVICE(sensor);
+    pdd = &bma253->pdd;
+
+    if (pdd->registered_mask & BMA253_NOTIFY_MASK) {
+        return SYS_EBUSY;
+    }
+
+    pdd->notify_ctx.snec_evtype |= sensor_event_type;
+    pdd->registered_mask |= BMA253_NOTIFY_MASK;
+    enable_intpin(bma253);
+
+    request_power[0] = BMA253_POWER_MODE_LPM_1;
+    request_power[1] = BMA253_POWER_MODE_LPM_2;
+    request_power[2] = BMA253_POWER_MODE_NORMAL;
+
+    rc = interim_power(bma253,
+                       request_power,
+                       sizeof(request_power) / sizeof(*request_power));
+    if (rc != 0) {
+        goto done;
+    }
+
+    /* Configure route */
+    rc = bma253_get_int_routes(bma253, &int_routes);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (sensor_event_type & SENSOR_EVENT_TYPE_DOUBLE_TAP) {
+        int_routes.d_tap_int_route = pdd->int_route;
+    }
+
+    if (sensor_event_type & SENSOR_EVENT_TYPE_SINGLE_TAP) {
+        int_routes.s_tap_int_route = pdd->int_route;
+    }
+
+    rc = bma253_set_int_routes(bma253, &int_routes);
+    if (rc != 0) {
+        return rc;
+    }
+
+    /* Configure enable event*/
+    rc = bma253_get_int_enable(bma253, &int_enable);
+    if (rc != 0) {
+        goto done;
+    }
+
+    /* Enable tap event*/
+    int_enable.s_tap_int_enable         = sensor_event_type &
+                                          SENSOR_EVENT_TYPE_SINGLE_TAP;
+    int_enable.d_tap_int_enable         = sensor_event_type &
+                                          SENSOR_EVENT_TYPE_DOUBLE_TAP;
+    rc = bma253_set_int_enable(bma253, &int_enable);
+
+done:
+    if (rc != 0) {
+        pdd->notify_ctx.snec_evtype &= ~sensor_event_type;
+        pdd->registered_mask &= ~BMA253_NOTIFY_MASK;
+        disable_intpin(bma253);
+    }
+
+    return rc;
+#else
+    return SYS_ENODEV;
+#endif
+}
 
-	return 0;
+static int
+sensor_driver_handle_interrupt(struct sensor * sensor)
+{
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    struct bma253 * bma253;
+    struct bma253_private_driver_data *pdd;
+    struct int_status int_status;
+    int rc;
+
+    bma253 = (struct bma253 *)SENSOR_GET_DEVICE(sensor);
+    pdd = &bma253->pdd;
+
+    rc = bma253_get_int_status(bma253, &int_status);
+    if (rc != 0) {
+        BMA253_ERROR("Cound not read int status err=0x%02x\n", rc);
+        return rc;
+    }
+
+    if ((pdd->registered_mask & BMA253_NOTIFY_MASK) &&
+            (int_status.s_tap_int_active || int_status.d_tap_int_active)) {
+        sensor_mgr_put_notify_evt(&pdd->notify_ctx);
+    }
+
+    if ((pdd->registered_mask & BMA253_READ_MASK) &&
+            (int_status.high_g_int_active || int_status.low_g_int_active)) {
+        sensor_mgr_put_read_evt(&pdd->read_ctx);
+    }
+
+    return 0;
+#else
+    return SYS_ENODEV;
+#endif
 }
 
 static struct sensor_driver bma253_sensor_driver = {
-	.sd_read       = sensor_driver_read,
-	.sd_get_config = sensor_driver_get_config,
+    .sd_read               = sensor_driver_read,
+    .sd_get_config         = sensor_driver_get_config,
+    .sd_set_trigger_thresh = sensor_driver_set_trigger_thresh,
+    .sd_set_notification   = sensor_driver_set_notification,
+    .sd_unset_notification = sensor_driver_unset_notification,
+    .sd_handle_interrupt   = sensor_driver_handle_interrupt,
 };
 
-int bma253_config(struct bma253 * bma253, struct bma253_cfg * cfg)
-{
-	struct sensor * sensor;
-	const struct sensor_itf * itf;
-	int rc;
-	uint8_t chip_id;
-	struct int_routes int_routes;
-	struct int_filters int_filters;
-	struct int_pin_electrical int_pin_electrical;
-	struct tap_int_cfg tap_int_cfg;
-	struct fifo_cfg fifo_cfg;
-	hal_gpio_irq_trig_t gpio_trig;
-
-	sensor = &bma253->sensor;
-	itf = SENSOR_GET_ITF(sensor);
-
-	rc = bma253_get_chip_id(itf, &chip_id);
-	if (rc != 0)
-		return rc;
-	if (chip_id != REG_VALUE_CHIP_ID) {
-		BMA253_ERROR("received incorrect chip ID 0x%02X\n", chip_id);
-		return SYS_EINVAL;
-	}
-
-	rc = bma253_set_softreset(itf);
-	if (rc != 0)
-		return rc;
-
-	delay_msec(2);
-
-	rc = bma253_set_g_range(itf, cfg->g_range);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_filter_bandwidth(itf, cfg->filter_bandwidth);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_data_acquisition(itf, cfg->use_unfiltered_data, false);
-	if (rc != 0)
-		return rc;
-
-	int_routes.flat_int_route        = INT_ROUTE_NONE;
-	int_routes.orient_int_route      = INT_ROUTE_NONE;
-	int_routes.s_tap_int_route       = INT_ROUTE_PIN_2;
-	int_routes.d_tap_int_route       = INT_ROUTE_PIN_2;
-	int_routes.slow_no_mot_int_route = INT_ROUTE_NONE;
-	int_routes.slope_int_route       = INT_ROUTE_NONE;
-	int_routes.high_g_int_route      = INT_ROUTE_NONE;
-	int_routes.low_g_int_route       = INT_ROUTE_NONE;
-	int_routes.fifo_wmark_int_route  = INT_ROUTE_PIN_1;
-	int_routes.fifo_full_int_route   = INT_ROUTE_NONE;
-	int_routes.data_int_route        = INT_ROUTE_NONE;
-
-	rc = bma253_set_int_routes(itf, &int_routes);
-	if (rc != 0)
-		return rc;
-
-	int_filters.unfiltered_data_int        = cfg->use_unfiltered_data;
-	int_filters.unfiltered_tap_int         = cfg->use_unfiltered_data;
-	int_filters.unfiltered_slow_no_mot_int = cfg->use_unfiltered_data;
-	int_filters.unfiltered_slope_int       = cfg->use_unfiltered_data;
-	int_filters.unfiltered_high_g_int      = cfg->use_unfiltered_data;
-	int_filters.unfiltered_low_g_int       = cfg->use_unfiltered_data;
-
-	rc = bma253_set_int_filters(itf, &int_filters);
-	if (rc != 0)
-		return rc;
-
-	int_pin_electrical.pin1_output = cfg->int_pin_output;
-	int_pin_electrical.pin1_active = cfg->int_pin_active;
-	int_pin_electrical.pin2_output = cfg->int_pin_output;
-	int_pin_electrical.pin2_active = cfg->int_pin_active;
-
-	rc = bma253_set_int_pin_electrical(itf, &int_pin_electrical);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_int_latch(itf, false, INT_LATCH_NON_LATCHED);
-	if (rc != 0)
-		return rc;
-
-	tap_int_cfg.tap_quiet        = cfg->tap_quiet;
-	tap_int_cfg.tap_shock        = cfg->tap_shock;
-	tap_int_cfg.d_tap_window     = cfg->d_tap_window;
-	tap_int_cfg.tap_wake_samples = cfg->tap_wake_samples;
-	tap_int_cfg.thresh_g         = cfg->tap_thresh_g;
-
-	rc = bma253_set_tap_int_cfg(itf, cfg->g_range, &tap_int_cfg);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_fifo_wmark_level(itf, 1);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_i2c_watchdog(itf, cfg->i2c_watchdog);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_ofc_offset(itf,
-				   AXIS_X,
-				   cfg->offset_x_g);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_ofc_offset(itf,
-				   AXIS_Y,
-				   cfg->offset_y_g);
-	if (rc != 0)
-		return rc;
-
-	rc = bma253_set_ofc_offset(itf,
-				   AXIS_Z,
-				   cfg->offset_z_g);
-	if (rc != 0)
-		return rc;
-
-	fifo_cfg.fifo_mode = FIFO_MODE_BYPASS;
-	fifo_cfg.fifo_data = FIFO_DATA_X_AND_Y_AND_Z;
-
-	rc = bma253_set_fifo_cfg(itf, &fifo_cfg);
-	if (rc != 0)
-		return rc;
-
-	switch (cfg->int_pin_active) {
-	case BMA253_INT_PIN_ACTIVE_LOW:
-		gpio_trig = HAL_GPIO_TRIG_FALLING;
-		break;
-	case BMA253_INT_PIN_ACTIVE_HIGH:
-		gpio_trig = HAL_GPIO_TRIG_RISING;
-		break;
-	default:
-		return SYS_EINVAL;
-	}
-
-	rc = hal_gpio_irq_init(cfg->int_pin1_num,
-			       interrupt_handler,
-			       bma253->ints + BMA253_INT_PIN_1,
-			       gpio_trig,
-			       HAL_GPIO_PULL_NONE);
-	if (rc != 0)
-		return rc;
-
-  if (cfg->int_pin2_num) {
-	    rc = hal_gpio_irq_init(cfg->int_pin2_num,
-			           interrupt_handler,
-			           bma253->ints + BMA253_INT_PIN_2,
-	    		       gpio_trig,
-    			       HAL_GPIO_PULL_NONE);
-    	if (rc != 0)
-	        return rc;
-	    hal_gpio_irq_enable(cfg->int_pin2_num);
-  }
-
-	hal_gpio_irq_enable(cfg->int_pin1_num);
-
-	rc = sensor_set_type_mask(sensor, cfg->sensor_mask);
-	if (rc != 0)
-		return rc;
-
-	bma253->cfg = *cfg;
-
-	return 0;
-}
-
-int bma253_init(struct os_dev * dev, void * arg)
-{
-	struct bma253 * bma253;
-	struct sensor * sensor;
-	int rc;
-
-	if (!dev || !arg)
-		return SYS_ENODEV;
+int
+bma253_config(struct bma253 * bma253, struct bma253_cfg * cfg)
+{
+    struct sensor * sensor;
+    int rc;
+    uint8_t chip_id;
+
+    bma253->cfg = *cfg;
+
+    sensor = &bma253->sensor;
+
+    rc = bma253_get_chip_id(bma253, &chip_id);
+    if (rc != 0) {
+        return rc;
+    }
+    if (chip_id != REG_VALUE_CHIP_ID) {
+        BMA253_ERROR("received incorrect chip ID 0x%02X\n", chip_id);
+        return SYS_EINVAL;
+    }
+
+    rc = reset_and_recfg(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = default_power(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    rc = sensor_set_type_mask(sensor, cfg->sensor_mask);
+    if (rc != 0) {
+        return rc;
+    }
+
+    return 0;
+}
+
+int
+bma253_init(struct os_dev * dev, void * arg)
+{
+    struct bma253 * bma253;
+    struct sensor * sensor;
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    struct bma253_private_driver_data *pdd;
+#endif
+    int rc;
+
+    if (!dev || !arg) {
+        return SYS_ENODEV;
+    }
 
 #if MYNEWT_VAL(BMA253_LOG)
-	rc = log_register(dev->od_name, &bma253_log, &log_console_handler,
-			  NULL, LOG_SYSLEVEL);
-	if (rc != 0)
-		return rc;
+    rc = log_register(dev->od_name,
+                      &bma253_log,
+                      &log_console_handler,
+                      NULL,
+                      LOG_SYSLEVEL);
+    if (rc != 0) {
+        return rc;
+    }
 #endif
 
-	bma253 = (struct bma253 *)dev;
-	sensor = &bma253->sensor;
+    bma253 = (struct bma253 *)dev;
+    sensor = &bma253->sensor;
+
+    rc = sensor_init(sensor, dev);
+    if (rc != 0) {
+        return rc;
+    }
 
-	rc = sensor_init(sensor, dev);
-	if (rc != 0)
-		return rc;
+    rc = sensor_set_driver(sensor,
+                           SENSOR_TYPE_ACCELEROMETER |
+                           SENSOR_TYPE_AMBIENT_TEMPERATURE,
+                           &bma253_sensor_driver);
+    if (rc != 0) {
+        return rc;
+    }
 
-	rc = sensor_set_driver(sensor, SENSOR_TYPE_ACCELEROMETER,
-			       &bma253_sensor_driver);
-	if (rc != 0)
-		return rc;
+    rc = sensor_set_interface(sensor, arg);
+    if (rc != 0) {
+        return rc;
+    }
 
-	rc = sensor_set_interface(sensor, arg);
-	if (rc != 0)
-		return rc;
+    sensor->s_next_run = OS_TIMEOUT_NEVER;
 
-	sensor->s_next_run = OS_TIMEOUT_NEVER;
+    rc = sensor_mgr_register(sensor);
+    if (rc != 0) {
+        return rc;
+    }
 
-	rc = sensor_mgr_register(sensor);
-	if (rc != 0)
-		return rc;
+#if MYNEWT_VAL(BMA253_INT_ENABLE)
+    init_interrupt(&bma253->intr, bma253->sensor.s_itf.si_ints);
+
+    pdd = &bma253->pdd;
+
+    pdd->read_ctx.srec_sensor = sensor;
+    pdd->notify_ctx.snec_sensor = sensor;
+
+    rc = init_intpin(bma253, interrupt_handler, sensor);
+    if (rc != 0) {
+        return rc;
+    }
+#endif
 
-	interrupt_init(bma253->ints + BMA253_INT_PIN_1);
-	interrupt_init(bma253->ints + BMA253_INT_PIN_2);
+    bma253->power = BMA253_POWER_MODE_NORMAL;
 
-	return 0;
+    return 0;
 }
diff --git a/hw/drivers/sensors/bma253/src/bma253_priv.h b/hw/drivers/sensors/bma253/src/bma253_priv.h
new file mode 100644
index 000000000..eac21c240
--- /dev/null
+++ b/hw/drivers/sensors/bma253/src/bma253_priv.h
@@ -0,0 +1,656 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 __BMA253_PRIV_H__
+#define __BMA253_PRIV_H__
+
+#include "bma253/bma253.h"
+
+#ifdef __cplusplus
+#extern "C" {
+#endif
+
+/*
+ * Full register map:
+ */
+
+#define REG_ADDR_BGW_CHIPID    0x00    /*    r            */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_ACCD_X_LSB    0x02    /*    r            */
+#define REG_ADDR_ACCD_X_MSB    0x03    /*    r            */
+#define REG_ADDR_ACCD_Y_LSB    0x04    /*    r            */
+#define REG_ADDR_ACCD_Y_MSB    0x05    /*    r            */
+#define REG_ADDR_ACCD_Z_LSB    0x06    /*    r            */
+#define REG_ADDR_ACCD_Z_MSB    0x07    /*    r            */
+#define REG_ADDR_ACCD_TEMP     0x08    /*    r            */
+#define REG_ADDR_INT_STATUS_0  0x09    /*    r            */
+#define REG_ADDR_INT_STATUS_1  0x0A    /*    r            */
+#define REG_ADDR_INT_STATUS_2  0x0B    /*    r            */
+#define REG_ADDR_INT_STATUS_3  0x0C    /*    r            */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_FIFO_STATUS   0x0E    /*    r            */
+#define REG_ADDR_PMU_RANGE     0x0F    /*    rw           */
+#define REG_ADDR_PMU_BW        0x10    /*    rw           */
+#define REG_ADDR_PMU_LPW       0x11    /*    rw           */
+#define REG_ADDR_PMU_LOW_POWER 0x12    /*    rw           */
+#define REG_ADDR_ACCD_HBW      0x13    /*    rw           */
+#define REG_ADDR_BGW_SOFTRESET 0x14    /*     w           */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_INT_EN_0      0x16    /*    rw           */
+#define REG_ADDR_INT_EN_1      0x17    /*    rw           */
+#define REG_ADDR_INT_EN_2      0x18    /*    rw           */
+#define REG_ADDR_INT_MAP_0     0x19    /*    rw           */
+#define REG_ADDR_INT_MAP_1     0x1A    /*    rw           */
+#define REG_ADDR_INT_MAP_2     0x1B    /*    rw           */
+/* RESERVED */                         /*                 */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_INT_SRC       0x1E    /*    rw           */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_INT_OUT_CTRL  0x20    /*    rw           */
+#define REG_ADDR_INT_RST_LATCH 0x21    /*    rw           */
+#define REG_ADDR_INT_0         0x22    /*    rw           */
+#define REG_ADDR_INT_1         0x23    /*    rw           */
+#define REG_ADDR_INT_2         0x24    /*    rw           */
+#define REG_ADDR_INT_3         0x25    /*    rw           */
+#define REG_ADDR_INT_4         0x26    /*    rw           */
+#define REG_ADDR_INT_5         0x27    /*    rw           */
+#define REG_ADDR_INT_6         0x28    /*    rw           */
+#define REG_ADDR_INT_7         0x29    /*    rw           */
+#define REG_ADDR_INT_8         0x2A    /*    rw           */
+#define REG_ADDR_INT_9         0x2B    /*    rw           */
+#define REG_ADDR_INT_A         0x2C    /*    rw           */
+#define REG_ADDR_INT_B         0x2D    /*    rw           */
+#define REG_ADDR_INT_C         0x2E    /*    rw           */
+#define REG_ADDR_INT_D         0x2F    /*    rw           */
+#define REG_ADDR_FIFO_CONFIG_0 0x30    /*    rw           */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_PMU_SELF_TEST 0x32    /*    rw           */
+#define REG_ADDR_TRIM_NVM_CTRL 0x33    /*    rw           */
+#define REG_ADDR_BGW_SPI3_WDT  0x34    /*    rw           */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_OFC_CTRL      0x36    /*    rw           */
+#define REG_ADDR_OFC_SETTING   0x37    /*    rw           */
+#define REG_ADDR_OFC_OFFSET_X  0x38    /*    rw    nvm    */
+#define REG_ADDR_OFC_OFFSET_Y  0x39    /*    rw    nvm    */
+#define REG_ADDR_OFC_OFFSET_Z  0x3A    /*    rw    nvm    */
+#define REG_ADDR_TRIM_GP0      0x3B    /*    rw    nvm    */
+#define REG_ADDR_TRIM_GP1      0x3C    /*    rw    nvm    */
+/* RESERVED */                         /*                 */
+#define REG_ADDR_FIFO_CONFIG_1 0x3E    /*    rw           */
+#define REG_ADDR_FIFO_DATA     0x3F    /*    r            */
+
+/* Magical value that the chip always reports as its ID */
+#define REG_VALUE_CHIP_ID    0xFA
+/* Magical value that is used to initiate a full reset */
+#define REG_VALUE_SOFT_RESET 0xB6
+
+/* Get the chip ID */
+int
+bma253_get_chip_id(const struct bma253 * bma253,
+                   uint8_t * chip_id);
+
+/* All three axis types */
+enum axis {
+    AXIS_X   = 0,
+    AXIS_Y   = 1,
+    AXIS_Z   = 2,
+    AXIS_ALL = 3,
+};
+
+/* A single accelerometer measurement for one axis */
+struct accel_data {
+    float accel_g;
+    bool new_data;
+};
+
+/* Get an accelerometer measurement for a single axis */
+int
+bma253_get_accel(const struct bma253 * bma253,
+                 enum bma253_g_range g_range,
+                 enum axis axis,
+                 struct accel_data * accel_data);
+
+/* Get a temperature measurement */
+int
+bma253_get_temp(const struct bma253 * bma253,
+                float * temp_c);
+
+/* Which direction in an axis was this interrupt triggered on */
+enum axis_trigger_sign {
+    AXIS_TRIGGER_SIGN_POS = 0,
+    AXIS_TRIGGER_SIGN_NEG = 1,
+};
+
+/* Which axis was this interrupt triggered on */
+struct axis_trigger {
+    enum axis_trigger_sign sign;
+    enum axis axis;
+    bool axis_known;
+};
+
+/* Active status of all interrupts */
+struct int_status {
+    bool flat_int_active;
+    bool orient_int_active;
+    bool s_tap_int_active;
+    bool d_tap_int_active;
+    bool slow_no_mot_int_active;
+    bool slope_int_active;
+    bool high_g_int_active;
+    bool low_g_int_active;
+    bool data_int_active;
+    bool fifo_wmark_int_active;
+    bool fifo_full_int_active;
+    struct axis_trigger tap_trigger;
+    struct axis_trigger slope_trigger;
+    bool device_is_flat;
+    bool device_is_down;
+    enum bma253_orient_xy device_orientation;
+    struct axis_trigger high_g_trigger;
+};
+
+/* Get the active status of all interrupts */
+int
+bma253_get_int_status(const struct bma253 * bma253,
+                      struct int_status * int_status);
+
+/* Get the status and size of the FIFO */
+int
+bma253_get_fifo_status(const struct bma253 * bma253,
+                       bool * overrun,
+                       uint8_t * frame_counter);
+
+/* Get/Set the accelerometer range */
+int
+bma253_get_g_range(const struct bma253 * bma253,
+                   enum bma253_g_range * g_range);
+int
+bma253_set_g_range(const struct bma253 * bma253,
+                   enum bma253_g_range g_range);
+
+/* Get/Set the filter output bandwidth */
+int
+bma253_get_filter_bandwidth(const struct bma253 * bma253,
+                            enum bma253_filter_bandwidth * filter_bandwidth);
+int
+bma253_set_filter_bandwidth(const struct bma253 * bma253,
+                            enum bma253_filter_bandwidth filter_bandwidth);
+
+/* Whether the sleep timer is locked to events or to time */
+enum sleep_timer {
+    SLEEP_TIMER_EVENT_DRIVEN         = 0,
+    SLEEP_TIMER_EQUIDISTANT_SAMPLING = 1,
+};
+
+/* Power settings of the device */
+struct power_settings {
+    enum bma253_power_mode power_mode;
+    enum bma253_sleep_duration sleep_duration;
+    enum sleep_timer sleep_timer;
+};
+
+/* Get/Set the power settings of the device */
+int
+bma253_get_power_settings(const struct bma253 * bma253,
+                          struct power_settings * power_settings);
+int
+bma253_set_power_settings(const struct bma253 * bma253,
+                          const struct power_settings * power_settings);
+
+/* Get/Set the data register settings */
+int
+bma253_get_data_acquisition(const struct bma253 * bma253,
+                            bool * unfiltered_reg_data,
+                            bool * disable_reg_shadow);
+int
+bma253_set_data_acquisition(const struct bma253 * bma253,
+                            bool unfiltered_reg_data,
+                            bool disable_reg_shadow);
+
+/* Kick off a full soft reset of the device */
+int
+bma253_set_softreset(const struct bma253 * bma253);
+
+/* Enable settings of all interupts */
+struct int_enable {
+    bool flat_int_enable;
+    bool orient_int_enable;
+    bool s_tap_int_enable;
+    bool d_tap_int_enable;
+    bool slope_z_int_enable;
+    bool slope_y_int_enable;
+    bool slope_x_int_enable;
+    bool fifo_wmark_int_enable;
+    bool fifo_full_int_enable;
+    bool data_int_enable;
+    bool low_g_int_enable;
+    bool high_g_z_int_enable;
+    bool high_g_y_int_enable;
+    bool high_g_x_int_enable;
+    bool no_motion_select;
+    bool slow_no_mot_z_int_enable;
+    bool slow_no_mot_y_int_enable;
+    bool slow_no_mot_x_int_enable;
+};
+
+/* Get/Set the enable settings of all interrupts */
+int
+bma253_get_int_enable(const struct bma253 * bma253,
+                      struct int_enable * int_enable);
+int
+bma253_set_int_enable(const struct bma253 * bma253,
+                      const struct int_enable * int_enable);
+
+/* Which physical device pin is a given interrupt routed to */
+enum int_route {
+    INT_ROUTE_NONE  = 0,
+    INT_ROUTE_PIN_1 = 1,
+    INT_ROUTE_PIN_2 = 2,
+    INT_ROUTE_BOTH  = 3,
+};
+
+enum bma253_int_num {
+    INT1_PIN,
+    INT2_PIN
+};
+
+/* Pin routing settings of all interrupts */
+struct int_routes {
+    enum int_route flat_int_route;
+    enum int_route orient_int_route;
+    enum int_route s_tap_int_route;
+    enum int_route d_tap_int_route;
+    enum int_route slow_no_mot_int_route;
+    enum int_route slope_int_route;
+    enum int_route high_g_int_route;
+    enum int_route low_g_int_route;
+    enum int_route fifo_wmark_int_route;
+    enum int_route fifo_full_int_route;
+    enum int_route data_int_route;
+};
+
+/* Get/Set the pin routing settings of all interrupts */
+int
+bma253_get_int_routes(const struct bma253 * bma253,
+                      struct int_routes * int_routes);
+int
+bma253_set_int_routes(const struct bma253 * bma253,
+                      const struct int_routes * int_routes);
+
+/* Whether each interrupt uses filtered or unfiltered data */
+struct int_filters {
+    bool unfiltered_data_int;
+    bool unfiltered_tap_int;
+    bool unfiltered_slow_no_mot_int;
+    bool unfiltered_slope_int;
+    bool unfiltered_high_g_int;
+    bool unfiltered_low_g_int;
+};
+
+/* Get/Set the filtered data settings of all interrupts */
+int
+bma253_get_int_filters(const struct bma253 * bma253,
+                       struct int_filters * int_filters);
+int
+bma253_set_int_filters(const struct bma253 * bma253,
+                       const struct int_filters * int_filters);
+
+/* Drive mode of the interrupt pins */
+enum int_pin_output {
+    INT_PIN_OUTPUT_PUSH_PULL  = 0,
+    INT_PIN_OUTPUT_OPEN_DRAIN = 1,
+};
+
+/* Active mode of the interrupt pins */
+enum int_pin_active {
+    INT_PIN_ACTIVE_LOW  = 0,
+    INT_PIN_ACTIVE_HIGH = 1,
+};
+
+/* Electrical settings of both interrupt pins */
+struct int_pin_electrical {
+    enum int_pin_output pin1_output;
+    enum int_pin_active pin1_active;
+    enum int_pin_output pin2_output;
+    enum int_pin_active pin2_active;
+};
+
+/* Get/Set the electrical settings of both interrupt pins */
+int
+bma253_get_int_pin_electrical(const struct bma253 * bma253,
+                              struct int_pin_electrical * electrical);
+int
+bma253_set_int_pin_electrical(const struct bma253 * bma253,
+                              const struct int_pin_electrical * electrical);
+
+/* Length of time that an interrupt condition should be latched active */
+enum int_latch {
+    INT_LATCH_NON_LATCHED       = 0,
+    INT_LATCH_LATCHED           = 1,
+    INT_LATCH_TEMPORARY_250_US  = 2,
+    INT_LATCH_TEMPORARY_500_US  = 3,
+    INT_LATCH_TEMPORARY_1_MS    = 4,
+    INT_LATCH_TEMPORARY_12_5_MS = 5,
+    INT_LATCH_TEMPORARY_25_MS   = 6,
+    INT_LATCH_TEMPORARY_50_MS   = 7,
+    INT_LATCH_TEMPORARY_250_MS  = 8,
+    INT_LATCH_TEMPORARY_500_MS  = 9,
+    INT_LATCH_TEMPORARY_1_S     = 10,
+    INT_LATCH_TEMPORARY_2_S     = 11,
+    INT_LATCH_TEMPORARY_4_S     = 12,
+    INT_LATCH_TEMPORARY_8_S     = 13,
+};
+
+/* Get/Set the interrupt condition latch time */
+int
+bma253_get_int_latch(const struct bma253 * bma253,
+                     enum int_latch * int_latch);
+int
+bma253_set_int_latch(const struct bma253 * bma253,
+                     bool reset_ints,
+                     enum int_latch int_latch);
+
+/* Settings for the low-g interrupt */
+struct low_g_int_cfg {
+    uint16_t delay_ms;
+    float thresh_g;
+    float hyster_g;
+    bool axis_summing;
+};
+
+/* Get/Set the low-g interrupt settings */
+int
+bma253_get_low_g_int_cfg(const struct bma253 * bma253,
+                         struct low_g_int_cfg * low_g_int_cfg);
+int
+bma253_set_low_g_int_cfg(const struct bma253 * bma253,
+                         const struct low_g_int_cfg * low_g_int_cfg);
+
+/* Settings for the high-g interrupt */
+struct high_g_int_cfg {
+    float hyster_g;
+    uint16_t delay_ms;
+    float thresh_g;
+};
+
+/* Get/Set the high-g interrupt settings */
+int
+bma253_get_high_g_int_cfg(const struct bma253 * bma253,
+                          enum bma253_g_range g_range,
+                          struct high_g_int_cfg * high_g_int_cfg);
+int
+bma253_set_high_g_int_cfg(const struct bma253 * bma253,
+                          enum bma253_g_range g_range,
+                          const struct high_g_int_cfg * high_g_int_cfg);
+
+/* Settings for the slow/no-motion interrupt */
+struct slow_no_mot_int_cfg {
+    uint16_t duration_p_or_s;
+    float thresh_g;
+};
+
+/* Get/Set the slow/no-motion interrupt settings */
+int
+bma253_get_slow_no_mot_int_cfg(const struct bma253 * bma253,
+                               bool no_motion_select,
+                               enum bma253_g_range g_range,
+                               struct slow_no_mot_int_cfg * slow_no_mot_int_cfg);
+int
+bma253_set_slow_no_mot_int_cfg(const struct bma253 * bma253,
+                               bool no_motion_select,
+                               enum bma253_g_range g_range,
+                               const struct slow_no_mot_int_cfg * slow_no_mot_int_cfg);
+
+/* Settings for the slope interrupt */
+struct slope_int_cfg {
+    uint8_t duration_p;
+    float thresh_g;
+};
+
+/* Get/Set the slope interrupt settings */
+int
+bma253_get_slope_int_cfg(const struct bma253 * bma253,
+                         enum bma253_g_range g_range,
+                         struct slope_int_cfg * slope_int_cfg);
+int
+bma253_set_slope_int_cfg(const struct bma253 * bma253,
+                         enum bma253_g_range g_range,
+                         const struct slope_int_cfg * slope_int_cfg);
+
+/* Settings for the double/single tap interrupt */
+struct tap_int_cfg {
+    enum bma253_tap_quiet tap_quiet;
+    enum bma253_tap_shock tap_shock;
+    enum bma253_d_tap_window d_tap_window;
+    enum bma253_tap_wake_samples tap_wake_samples;
+    float thresh_g;
+};
+
+/* Get/Set the double/single tap interrupt settings */
+int
+bma253_get_tap_int_cfg(const struct bma253 * bma253,
+                       enum bma253_g_range g_range,
+                       struct tap_int_cfg * tap_int_cfg);
+int
+bma253_set_tap_int_cfg(const struct bma253 * bma253,
+                       enum bma253_g_range g_range,
+                       const struct tap_int_cfg * tap_int_cfg);
+
+/* Settings for the orientation interrupt */
+struct orient_int_cfg {
+    float hyster_g;
+    enum bma253_orient_blocking orient_blocking;
+    enum bma253_orient_mode orient_mode;
+    bool signal_up_dn;
+    uint8_t blocking_angle;
+};
+
+/* Get/Set the orientation interrupt settings */
+int
+bma253_get_orient_int_cfg(const struct bma253 * bma253,
+                          struct orient_int_cfg * orient_int_cfg);
+int
+bma253_set_orient_int_cfg(const struct bma253 * bma253,
+                          const struct orient_int_cfg * orient_int_cfg);
+
+/* Hold time for flat condition */
+enum flat_hold {
+    FLAT_HOLD_0_MS    = 0,
+    FLAT_HOLD_512_MS  = 1,
+    FLAT_HOLD_1024_MS = 2,
+    FLAT_HOLD_2048_MS = 3,
+};
+
+/* Settings for the flat interrupt */
+struct flat_int_cfg {
+    uint8_t flat_angle;
+    enum flat_hold flat_hold;
+    uint8_t flat_hyster;
+    bool hyster_enable;
+};
+
+/* Get/Set the flat interrupt settings */
+int
+bma253_get_flat_int_cfg(const struct bma253 * bma253,
+                        struct flat_int_cfg * flat_int_cfg);
+int
+bma253_set_flat_int_cfg(const struct bma253 * bma253,
+                        const struct flat_int_cfg * flat_int_cfg);
+
+/* Get/Set the FIFO watermark level */
+int
+bma253_get_fifo_wmark_level(const struct bma253 * bma253,
+                            uint8_t * wmark_level);
+int
+bma253_set_fifo_wmark_level(const struct bma253 * bma253,
+                            uint8_t wmark_level);
+
+/* Amplitude of a self-test induced acceleration */
+enum self_test_ampl {
+    SELF_TEST_AMPL_HIGH = 0,
+    SELF_TEST_AMPL_LOW  = 1,
+};
+
+/* Direction of a self-test induced acceleration */
+enum self_test_sign {
+    SELF_TEST_SIGN_NEGATIVE = 0,
+    SELF_TEST_SIGN_POSITIVE = 1,
+};
+
+/* Settings for the self-test functionality */
+struct self_test_cfg {
+    enum self_test_ampl self_test_ampl;
+    enum self_test_sign self_test_sign;
+    enum axis self_test_axis;
+    bool self_test_enabled;
+};
+
+/* Get/Set the self-test settings */
+int
+bma253_get_self_test_cfg(const struct bma253 * bma253,
+                         struct self_test_cfg * self_test_cfg);
+int
+bma253_set_self_test_cfg(const struct bma253 * bma253,
+                         const struct self_test_cfg * self_test_cfg);
+
+/* Get/Set the NVM reset/write control values */
+int
+bma253_get_nvm_control(const struct bma253 * bma253,
+                       uint8_t * remaining_cycles,
+                       bool * load_from_nvm,
+                       bool * nvm_is_ready,
+                       bool * nvm_unlocked);
+int
+bma253_set_nvm_control(const struct bma253 * bma253,
+                       bool load_from_nvm,
+                       bool store_into_nvm,
+                       bool nvm_unlocked);
+
+/* Length of time before the I2C watchdog fires */
+enum i2c_watchdog {
+    I2C_WATCHDOG_DISABLED = 0,
+    I2C_WATCHDOG_1_MS     = 1,
+    I2C_WATCHDOG_50_MS    = 2,
+};
+
+/* Get/Set the I2C watchdog settings */
+int
+bma253_get_i2c_watchdog(const struct bma253 * bma253,
+                        enum i2c_watchdog * i2c_watchdog);
+int
+bma253_set_i2c_watchdog(const struct bma253 * bma253,
+                        enum i2c_watchdog i2c_watchdog);
+
+/* Offset compensation settings used in slow compensation mode */
+struct slow_ofc_cfg {
+    bool ofc_z_enabled;
+    bool ofc_y_enabled;
+    bool ofc_x_enabled;
+    bool high_bw_cut_off;
+};
+
+/* Get/Set the fast & slow offset compensation mode settings, and reset all
+ * offset compensation values back to NVM defaults */
+int
+bma253_get_fast_ofc_cfg(const struct bma253 * bma253,
+                        bool * fast_ofc_ready,
+                        enum bma253_offset_comp_target * ofc_target_z,
+                        enum bma253_offset_comp_target * ofc_target_y,
+                        enum bma253_offset_comp_target * ofc_target_x);
+int
+bma253_set_fast_ofc_cfg(const struct bma253 * bma253,
+                        enum axis fast_ofc_axis,
+                        enum bma253_offset_comp_target fast_ofc_target,
+                        bool trigger_fast_ofc);
+int
+bma253_get_slow_ofc_cfg(const struct bma253 * bma253,
+                        struct slow_ofc_cfg * slow_ofc_cfg);
+int
+bma253_set_slow_ofc_cfg(const struct bma253 * bma253,
+                        const struct slow_ofc_cfg * slow_ofc_cfg);
+int
+bma253_set_ofc_reset(const struct bma253 * bma253);
+
+/* Get/Set the offset compensation value for a specific axis */
+int
+bma253_get_ofc_offset(const struct bma253 * bma253,
+                      enum axis axis,
+                      float * offset_g);
+int
+bma253_set_ofc_offset(const struct bma253 * bma253,
+                      enum axis axis,
+                      float offset_g);
+
+/* General purpose non-volatile data registers */
+enum saved_data_addr {
+    SAVED_DATA_ADDR_0 = 0,
+    SAVED_DATA_ADDR_1 = 1,
+};
+
+/* Get/Set the data stored in general purpose non-volatile registers */
+int
+bma253_get_saved_data(const struct bma253 * bma253,
+                      enum saved_data_addr saved_data_addr,
+                      uint8_t * saved_data_val);
+int
+bma253_set_saved_data(const struct bma253 * bma253,
+                      enum saved_data_addr saved_data_addr,
+                      uint8_t saved_data_val);
+
+/* Mode that the FIFO is running in */
+enum fifo_mode {
+    FIFO_MODE_BYPASS = 0,
+    FIFO_MODE_FIFO   = 1,
+    FIFO_MODE_STREAM = 2,
+};
+
+/* Measurements for which axis to capture into the FIFO */
+enum fifo_data {
+    FIFO_DATA_X_AND_Y_AND_Z = 0,
+    FIFO_DATA_X_ONLY        = 1,
+    FIFO_DATA_Y_ONLY        = 2,
+    FIFO_DATA_Z_ONLY        = 3,
+};
+
+/* FIFO capture and behavior settings */
+struct fifo_cfg {
+    enum fifo_mode fifo_mode;
+    enum fifo_data fifo_data;
+};
+
+/* Get/Set the FIFO capture and behavior settings */
+int
+bma253_get_fifo_cfg(const struct bma253 * bma253,
+                    struct fifo_cfg * fifo_cfg);
+int
+bma253_set_fifo_cfg(const struct bma253 * bma253,
+                    const struct fifo_cfg * fifo_cfg);
+
+/* Read a single multi-axis data frame from the FIFO */
+int
+bma253_get_fifo(const struct bma253 * bma253,
+                enum bma253_g_range g_range,
+                enum fifo_data fifo_data,
+                struct accel_data * accel_data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/hw/drivers/sensors/bma253/src/bma253_shell.c b/hw/drivers/sensors/bma253/src/bma253_shell.c
new file mode 100644
index 000000000..6a5ae9c4f
--- /dev/null
+++ b/hw/drivers/sensors/bma253/src/bma253_shell.c
@@ -0,0 +1,717 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 <errno.h>
+
+#include "syscfg/syscfg.h"
+#include "bma253/bma253.h"
+#include "bma253_priv.h"
+#include "console/console.h"
+#include "shell/shell.h"
+
+#if MYNEWT_VAL(BMA253_CLI)
+
+struct self_test_mode {
+    const char * name;
+    float hmult;
+    float lmult;
+};
+
+static const struct self_test_mode self_test_modes[] = {
+    {
+        .name  = "default",
+        .hmult = 1.0,
+        .lmult = 0.0,
+    },
+    {
+        .name  = "strict",
+        .hmult = 2.0,
+        .lmult = 0.5,
+    },
+};
+
+static int
+bma253_self_test_cmd(struct bma253 * bma253,
+                     int argc,
+                     char * argv[])
+{
+    const struct self_test_mode * self_test_mode;
+    uint8_t i;
+    bool self_test_fail;
+    int rc;
+
+    if (argc != 1) {
+        return EINVAL;
+    }
+
+    self_test_mode = NULL;
+    for (i = 0; i < sizeof(self_test_modes) /
+                    sizeof(*self_test_modes); i++) {
+        if (strcmp(self_test_modes[i].name, argv[0]) == 0) {
+            self_test_mode = self_test_modes + i;
+        }
+    }
+
+    if (self_test_mode == NULL) {
+        return EINVAL;
+    }
+
+    rc = bma253_self_test(bma253,
+                          self_test_mode->hmult,
+                          self_test_mode->lmult,
+                          &self_test_fail);
+    if (rc != 0) {
+        return rc;
+    }
+
+    if (self_test_fail) {
+        console_printf("self test failed\n");
+    } else {
+        console_printf("self test passed\n");
+    }
+
+    return 0;
+}
+
+struct offset_comp_target {
+    const char * name;
+    enum bma253_offset_comp_target target;
+};
+
+static const struct offset_comp_target offset_comp_targets[] = {
+    {
+        .name   = "0g",
+        .target = BMA253_OFFSET_COMP_TARGET_0_G,
+    },
+    {
+        .name   = "-1g",
+        .target = BMA253_OFFSET_COMP_TARGET_NEG_1_G,
+    },
+    {
+        .name   = "+1g",
+        .target = BMA253_OFFSET_COMP_TARGET_POS_1_G,
+    },
+};
+
+static int
+bma253_offset_compensation_cmd(struct bma253 * bma253,
+                               int argc,
+                               char * argv[])
+{
+    const struct offset_comp_target * target_x;
+    const struct offset_comp_target * target_y;
+    const struct offset_comp_target * target_z;
+    uint8_t i;
+
+    if (argc != 3) {
+        return EINVAL;
+    }
+
+    target_x = NULL;
+    for (i = 0; i < sizeof(offset_comp_targets) /
+                    sizeof(*offset_comp_targets); i++) {
+        if (strcmp(offset_comp_targets[i].name, argv[0]) == 0) {
+            target_x = offset_comp_targets + i;
+        }
+    }
+    target_y = NULL;
+    for (i = 0; i < sizeof(offset_comp_targets) /
+                    sizeof(*offset_comp_targets); i++) {
+        if (strcmp(offset_comp_targets[i].name, argv[1]) == 0) {
+            target_y = offset_comp_targets + i;
+        }
+    }
+    target_z = NULL;
+    for (i = 0; i < sizeof(offset_comp_targets) /
+                    sizeof(*offset_comp_targets); i++) {
+        if (strcmp(offset_comp_targets[i].name, argv[2]) == 0) {
+            target_z = offset_comp_targets + i;
+        }
+    }
+
+    if (target_x == NULL) {
+        return EINVAL;
+    }
+    if (target_y == NULL) {
+        return EINVAL;
+    }
+    if (target_z == NULL) {
+        return EINVAL;
+    }
+
+    return bma253_offset_compensation(bma253,
+                                      target_x->target,
+                                      target_y->target,
+                                      target_z->target);
+}
+
+static int
+bma253_query_offsets_cmd(struct bma253 * bma253,
+                         int argc,
+                         char * argv[])
+{
+    int rc;
+    float offset_x_g;
+    float offset_y_g;
+    float offset_z_g;
+    char buffer_x[20];
+    char buffer_y[20];
+    char buffer_z[20];
+
+    if (argc != 0) {
+        return EINVAL;
+    }
+
+    rc = bma253_query_offsets(bma253,
+                              &offset_x_g,
+                              &offset_y_g,
+                              &offset_z_g);
+    if (rc != 0) {
+        return rc;
+    }
+
+    sensor_ftostr(offset_x_g, buffer_x, sizeof(buffer_x));
+    sensor_ftostr(offset_y_g, buffer_y, sizeof(buffer_y));
+    sensor_ftostr(offset_z_g, buffer_z, sizeof(buffer_z));
+
+    console_printf("offset x = %s offset y = %s offset z = %s\n",
+                   buffer_x,
+                   buffer_y,
+                   buffer_z);
+
+    return 0;
+}
+
+static int
+bma253_write_offsets_cmd(struct bma253 * bma253,
+                         int argc,
+                         char * argv[])
+{
+    if (argc != 0) {
+        return EINVAL;
+    }
+
+    return bma253_write_offsets(bma253, 0.0, 0.0, 0.0);
+}
+
+struct stream_read_context {
+    uint32_t count;
+};
+
+static bool
+bma253_stream_read_cb(void * arg,
+                      struct sensor_accel_data * sad)
+{
+    char buffer_x[20];
+    char buffer_y[20];
+    char buffer_z[20];
+    struct stream_read_context * ctx;
+
+    sensor_ftostr(sad->sad_x, buffer_x, sizeof(buffer_x));
+    sensor_ftostr(sad->sad_y, buffer_y, sizeof(buffer_y));
+    sensor_ftostr(sad->sad_z, buffer_z, sizeof(buffer_z));
+
+    console_printf("x = %s y = %s z = %s\n",
+                   buffer_x,
+                   buffer_y,
+                   buffer_z);
+
+    ctx = (struct stream_read_context *)arg;
+    ctx->count--;
+
+    return ctx->count == 0;
+}
+
+static int
+bma253_stream_read_cmd(struct bma253 * bma253,
+                       int argc,
+                       char * argv[])
+{
+    char * end;
+    struct stream_read_context ctx;
+
+    if (argc != 1) {
+        return EINVAL;
+    }
+
+    ctx.count = strtoul(argv[0], &end, 10);
+    if (*end != '\0') {
+        return EINVAL;
+    }
+
+    return bma253_stream_read(bma253,
+                              bma253_stream_read_cb,
+                              &ctx,
+                              0);
+}
+
+static int
+bma253_current_temp_cmd(struct bma253 * bma253,
+                        int argc,
+                        char * argv[])
+{
+    float temp_c;
+    int rc;
+    char buffer[20];
+
+    if (argc != 0) {
+        return EINVAL;
+    }
+
+    rc = bma253_current_temp(bma253, &temp_c);
+    if (rc != 0) {
+        return rc;
+    }
+
+    sensor_ftostr(temp_c, buffer, sizeof(buffer));
+
+    console_printf("temp = %s C\n", buffer);
+
+    return 0;
+}
+
+static void
+console_print_orient(const struct bma253_orient_xyz * orient_xyz)
+{
+    const char * xy_desc;
+    const char * z_desc;
+
+    switch (orient_xyz->orient_xy) {
+    case BMA253_ORIENT_XY_PORTRAIT_UPRIGHT:
+        xy_desc = "portrait-upright";
+        break;
+    case BMA253_ORIENT_XY_PORTRAIT_UPSIDE_DOWN:
+        xy_desc = "portrait-upside-down";
+        break;
+    case BMA253_ORIENT_XY_LANDSCAPE_LEFT:
+        xy_desc = "landscape-left";
+        break;
+    case BMA253_ORIENT_XY_LANDSCAPE_RIGHT:
+        xy_desc = "landscape-right";
+        break;
+    default:
+        xy_desc = "unknown-enum";
+        break;
+    }
+
+    if (orient_xyz->downward_z) {
+        z_desc = "facing-downward";
+    } else {
+        z_desc = "facing-upward";
+    }
+
+    console_printf("xy = %s z = %s\n", xy_desc, z_desc);
+}
+
+static int
+bma253_current_orient_cmd(struct bma253 * bma253,
+                          int argc,
+                          char * argv[])
+{
+    struct bma253_orient_xyz orient_xyz;
+    int rc;
+
+    if (argc != 0) {
+        return EINVAL;
+    }
+
+    rc = bma253_current_orient(bma253, &orient_xyz);
+    if (rc != 0) {
+        return rc;
+    }
+
+    console_print_orient(&orient_xyz);
+
+    return 0;
+}
+
+static int
+bma253_wait_for_orient_cmd(struct bma253 * bma253,
+                           int argc,
+                           char * argv[])
+{
+    struct bma253_orient_xyz orient_xyz;
+    int rc;
+
+    if (argc != 0) {
+        return EINVAL;
+    }
+
+    rc = bma253_wait_for_orient(bma253, &orient_xyz);
+    if (rc != 0) {
+        return rc;
+    }
+
+    console_print_orient(&orient_xyz);
+    console_printf("done!\n");
+
+    return 0;
+}
+
+static int
+bma253_wait_for_high_g_cmd(struct bma253 * bma253,
+                           int argc,
+                           char * argv[])
+{
+    int rc;
+
+    if (argc != 0) {
+        return EINVAL;
+    }
+
+    rc = bma253_wait_for_high_g(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    console_printf("done!\n");
+
+    return 0;
+}
+
+static int
+bma253_wait_for_low_g_cmd(struct bma253 * bma253,
+                          int argc,
+                          char * argv[])
+{
+    int rc;
+
+    if (argc != 0) {
+        return EINVAL;
+    }
+
+    rc = bma253_wait_for_low_g(bma253);
+    if (rc != 0) {
+        return rc;
+    }
+
+    console_printf("done!\n");
+
+    return 0;
+}
+
+struct tap_type {
+    const char * name;
+    enum bma253_tap_type type;
+};
+
+static const struct tap_type tap_types[] = {
+    {
+        .name = "double",
+        .type = BMA253_TAP_TYPE_DOUBLE,
+    },
+    {
+        .name = "single",
+        .type = BMA253_TAP_TYPE_SINGLE,
+    },
+};
+
+static int
+bma253_wait_for_tap_cmd(struct bma253 * bma253,
+                        int argc,
+                        char * argv[])
+{
+    const struct tap_type * tap_type;
+    uint8_t i;
+    int rc;
+
+    if (argc != 1) {
+        return EINVAL;
+    }
+
+    tap_type = NULL;
+    for (i = 0; i < sizeof(tap_types) /
+                    sizeof(*tap_types); i++) {
+        if (strcmp(tap_types[i].name, argv[0]) == 0) {
+            tap_type = tap_types + i;
+        }
+    }
+
+    if (tap_type == NULL) {
+        return EINVAL;
+    }
+
+    rc = bma253_wait_for_tap(bma253, tap_type->type);
+    if (rc != 0) {
+        return rc;
+    }
+
+    console_printf("done!\n");
+
+    return 0;
+}
+
+struct power_mode {
+    const char * name;
+    enum bma253_power_mode power;
+};
+
+static const struct power_mode power_modes[] = {
+    {
+        .name  = "normal",
+        .power = BMA253_POWER_MODE_NORMAL,
+    },
+    {
+        .name  = "deep-suspend",
+        .power = BMA253_POWER_MODE_DEEP_SUSPEND,
+    },
+    {
+        .name  = "suspend",
+        .power = BMA253_POWER_MODE_SUSPEND,
+    },
+    {
+        .name  = "standby",
+        .power = BMA253_POWER_MODE_STANDBY,
+    },
+    {
+        .name  = "lpm1",
+        .power = BMA253_POWER_MODE_LPM_1,
+    },
+    {
+        .name  = "lpm2",
+        .power = BMA253_POWER_MODE_LPM_2,
+    },
+};
+
+struct sleep_duration {
+    const char * name;
+    enum bma253_sleep_duration sleep;
+};
+
+static const struct sleep_duration sleep_durations[] = {
+    {
+        .name  = "0.5ms",
+        .sleep = BMA253_SLEEP_DURATION_0_5_MS,
+    },
+    {
+        .name  = "1ms",
+        .sleep = BMA253_SLEEP_DURATION_1_MS,
+    },
+    {
+        .name  = "2ms",
+        .sleep = BMA253_SLEEP_DURATION_2_MS,
+    },
+    {
+        .name  = "4ms",
+        .sleep = BMA253_SLEEP_DURATION_4_MS,
+    },
+    {
+        .name  = "6ms",
+        .sleep = BMA253_SLEEP_DURATION_6_MS,
+    },
+    {
+        .name  = "10ms",
+        .sleep = BMA253_SLEEP_DURATION_10_MS,
+    },
+    {
+        .name  = "25ms",
+        .sleep = BMA253_SLEEP_DURATION_25_MS,
+    },
+    {
+        .name  = "50ms",
+        .sleep = BMA253_SLEEP_DURATION_50_MS,
+    },
+    {
+        .name  = "100ms",
+        .sleep = BMA253_SLEEP_DURATION_100_MS,
+    },
+    {
+        .name  = "500ms",
+        .sleep = BMA253_SLEEP_DURATION_500_MS,
+    },
+    {
+        .name  = "1s",
+        .sleep = BMA253_SLEEP_DURATION_1_S,
+    },
+};
+
+static int
+bma253_power_settings_cmd(struct bma253 * bma253,
+                          int argc,
+                          char * argv[])
+{
+    const struct power_mode * power_mode;
+    const struct sleep_duration * sleep_duration;
+    uint8_t i;
+
+    if (argc != 2) {
+        return EINVAL;
+    }
+
+    power_mode = NULL;
+    for (i = 0; i < sizeof(power_modes) /
+                    sizeof(*power_modes); i++) {
+        if (strcmp(power_modes[i].name, argv[0]) == 0) {
+            power_mode = power_modes + i;
+        }
+    }
+
+    sleep_duration = NULL;
+    for (i = 0; i < sizeof(sleep_durations) /
+                    sizeof(*sleep_durations); i++) {
+        if (strcmp(sleep_durations[i].name, argv[1]) == 0) {
+            sleep_duration = sleep_durations + i;
+        }
+    }
+
+    if (power_mode == NULL) {
+        return EINVAL;
+    }
+    if (sleep_duration == NULL) {
+        return EINVAL;
+    }
+
+    return bma253_power_settings(bma253,
+                                 power_mode->power,
+                                 sleep_duration->sleep);
+}
+
+struct subcmd {
+    const char * name;
+    const char * help;
+    int (*func)(struct bma253 * bma253,
+                int argc,
+                char * argv[]);
+};
+
+static const struct subcmd supported_subcmds[] = {
+    {
+        .name = "self-test",
+        .help = "<default|strict>",
+        .func = bma253_self_test_cmd,
+    },
+    {
+        .name = "offset-compensation",
+        .help = "<x={0g|-1g|+1g}> <y={0g|-1g|+1g}> <z={0g|-1g|+1g}>",
+        .func = bma253_offset_compensation_cmd,
+    },
+    {
+        .name = "query-offsets",
+        .help = "",
+        .func = bma253_query_offsets_cmd,
+    },
+    {
+        .name = "write-offsets",
+        .help = "",
+        .func = bma253_write_offsets_cmd,
+    },
+    {
+        .name = "stream-read",
+        .help = "<num-reads>",
+        .func = bma253_stream_read_cmd,
+    },
+    {
+        .name = "current-temp",
+        .help = "",
+        .func = bma253_current_temp_cmd,
+    },
+    {
+        .name = "current-orient",
+        .help = "",
+        .func = bma253_current_orient_cmd,
+    },
+    {
+        .name = "wait-for-orient",
+        .help = "",
+        .func = bma253_wait_for_orient_cmd,
+    },
+    {
+        .name = "wait-for-high-g",
+        .help = "",
+        .func = bma253_wait_for_high_g_cmd,
+    },
+    {
+        .name = "wait-for-low-g",
+        .help = "",
+        .func = bma253_wait_for_low_g_cmd,
+    },
+    {
+        .name = "wait-for-tap",
+        .help = "<double|single>",
+        .func = bma253_wait_for_tap_cmd,
+    },
+    {
+        .name = "power-settings",
+        .help = "<normal|deep-suspend|suspend|standby|lpm1|lpm2>" \
+                "\n                      "                        \
+                "<0.5ms|1ms|2ms|4ms|6ms|10ms|25ms|50ms|100ms|500ms|1s>",
+        .func = bma253_power_settings_cmd,
+    },
+};
+
+static int
+bma253_shell_cmd(int argc, char * argv[])
+{
+    struct os_dev * dev;
+    struct bma253 * bma253;
+    const struct subcmd * subcmd;
+    uint8_t i;
+
+    dev = os_dev_open(MYNEWT_VAL(BMA253_SHELL_DEV_NAME), OS_TIMEOUT_NEVER, NULL);
+    if (dev == NULL) {
+        console_printf("failed to open bma253_0 device\n");
+        return ENODEV;
+    }
+
+    bma253 = (struct bma253 *)dev;
+
+    subcmd = NULL;
+    if (argc > 1) {
+        for (i = 0; i < sizeof(supported_subcmds) /
+                        sizeof(*supported_subcmds); i++) {
+            if (strcmp(supported_subcmds[i].name, argv[1]) == 0) {
+                subcmd = supported_subcmds + i;
+            }
+        }
+
+        if (subcmd == NULL) {
+            console_printf("unknown %s subcommand\n", argv[1]);
+        }
+    }
+
+    if (subcmd != NULL) {
+        if (subcmd->func(bma253, argc - 2, argv + 2) != 0) {
+            console_printf("could not run %s subcommand\n", argv[1]);
+            console_printf("%s %s\n", subcmd->name, subcmd->help);
+        }
+    } else {
+        for (i = 0; i < sizeof(supported_subcmds) /
+                        sizeof(*supported_subcmds); i++) {
+            subcmd = supported_subcmds + i;
+            console_printf("%s %s\n", subcmd->name, subcmd->help);
+        }
+    }
+
+    os_dev_close(dev);
+
+    return 0;
+}
+
+static const struct shell_cmd bma253_shell_cmd_desc = {
+    .sc_cmd      = "bma253",
+    .sc_cmd_func = bma253_shell_cmd,
+};
+
+int
+bma253_shell_init(void)
+{
+    return shell_cmd_register(&bma253_shell_cmd_desc);
+}
+
+#endif
diff --git a/hw/drivers/sensors/bma253/syscfg.yml b/hw/drivers/sensors/bma253/syscfg.yml
index b48d8ed55..ee8f720cf 100644
--- a/hw/drivers/sensors/bma253/syscfg.yml
+++ b/hw/drivers/sensors/bma253/syscfg.yml
@@ -18,6 +18,36 @@
 #
 
 syscfg.defs:
+    BMA253_CLI:
+        description: 'Enable shell support for BMA253'
+        value: 0
+    BMA253_I2C_WDT:
+        description: 'Enable I2C watchdog functionality'
+        value: 1
+    BMA253_INT_ENABLE:
+        description: 'Enable interrupt support, necessary for events'
+        value: 1
+    BMA253_INT_CFG_ACTIVE:
+        description: 'Set 0 for active-low, 1 for active-high'
+        value: 1
+    BMA253_INT_CFG_OUTPUT:
+        description: 'Set 0 for push-pull, 1 for open-drain'
+        value: 1
+    BMA253_INT_PIN_DEVICE:
+        description: 'Interrupt pin number 1 or 2 on accelerometer device'
+        value: 1
+    BMA253_INT2_PIN_DEVICE:
+        description: 'Interrupt pin number 1 or 2 on accelerometer device'
+        value: 2
+    BMA253_INT_PIN_HOST:
+        description: 'Interrupt pin number on host device connected to INT1 on device'
+        value: 20
+    BMA253_INT2_PIN_HOST:
+        description: 'Interrupt pin number on host device connected to INT2 on device'
+        value: -1
     BMA253_LOG:
         description: 'Enable BMA253 logging'
-        value: 1
+        value: 0
+    BMA253_SHELL_DEV_NAME:
+        description: 'BMA253 Shell device name'
+        value: "\"bma253_0\""
diff --git a/hw/sensor/creator/src/sensor_creator.c b/hw/sensor/creator/src/sensor_creator.c
index cb19e66c3..aa21deede 100644
--- a/hw/sensor/creator/src/sensor_creator.c
+++ b/hw/sensor/creator/src/sensor_creator.c
@@ -17,6 +17,7 @@
  * under the License.
  */
 
+#include <syscfg/syscfg.h>
 #include <os/os_dev.h>
 #include <assert.h>
 #include <defs/error.h>
@@ -182,6 +183,12 @@ static struct sensor_itf i2c_0_itf_lis = {
     .si_type = SENSOR_ITF_I2C,
     .si_num  = 0,
     .si_addr = 0x18,
+    .si_ints = {
+       { MYNEWT_VAL(BMA253_INT_PIN_HOST), MYNEWT_VAL(BMA253_INT_PIN_DEVICE),
+                                         MYNEWT_VAL(BMA253_INT_CFG_ACTIVE)},
+       { MYNEWT_VAL(BMA253_INT2_PIN_HOST), MYNEWT_VAL(BMA253_INT2_PIN_DEVICE),
+                                       MYNEWT_VAL(BMA253_INT_CFG_ACTIVE)}
+    },
 };
 #endif
 
@@ -469,30 +476,27 @@ int
 config_bma253_sensor(void)
 {
     struct os_dev * dev;
-    struct bma253_cfg cfg;
+    struct bma253_cfg cfg = {0};
     int rc;
 
     dev = os_dev_open("bma253_0", OS_TIMEOUT_NEVER, NULL);
     assert(dev != NULL);
 
+    cfg.low_g_delay_ms = BMA253_LOW_G_DELAY_MS_DEFAULT;
+    cfg.high_g_delay_ms = BMA253_HIGH_G_DELAY_MS_DEFAULT;
     cfg.g_range = BMA253_G_RANGE_2;
     cfg.filter_bandwidth = BMA253_FILTER_BANDWIDTH_1000_HZ;
     cfg.use_unfiltered_data = false;
-    cfg.int_pin_output = BMA253_INT_PIN_OUTPUT_PUSH_PULL;
-    cfg.int_pin_active = BMA253_INT_PIN_ACTIVE_HIGH;
     cfg.tap_quiet = BMA253_TAP_QUIET_30_MS;
     cfg.tap_shock = BMA253_TAP_SHOCK_50_MS;
     cfg.d_tap_window = BMA253_D_TAP_WINDOW_250_MS;
     cfg.tap_wake_samples = BMA253_TAP_WAKE_SAMPLES_2;
     cfg.tap_thresh_g = 1.0;
-    cfg.i2c_watchdog = BMA253_I2C_WATCHDOG_DISABLED;
     cfg.offset_x_g = 0.0;
     cfg.offset_y_g = 0.0;
     cfg.offset_z_g = 0.0;
     cfg.power_mode = BMA253_POWER_MODE_NORMAL;
     cfg.sleep_duration = BMA253_SLEEP_DURATION_0_5_MS;
-    cfg.int_pin1_num = 20;
-    cfg.int_pin2_num = 19;
     cfg.sensor_mask = SENSOR_TYPE_ACCELEROMETER;
 
     rc = bma253_config((struct bma253 *)dev, &cfg);
diff --git a/hw/sensor/include/sensor/sensor.h b/hw/sensor/include/sensor/sensor.h
index 4ff4da207..40a37b61e 100644
--- a/hw/sensor/include/sensor/sensor.h
+++ b/hw/sensor/include/sensor/sensor.h
@@ -98,6 +98,13 @@ typedef enum {
     SENSOR_TYPE_ALL                  = 0xFFFFFFFF
 } sensor_type_t;
 
+typedef enum {
+    /* Accelerometer double tap event */
+    SENSOR_EVENT_TYPE_DOUBLE_TAP     = (1 << 0),
+    /* Accelerometer single tap event */
+    SENSOR_EVENT_TYPE_SINGLE_TAP     = (1 << 1),
+} sensor_event_type_t;
+
 
 /**
  * Opaque 32-bit value, must understand underlying sensor type
@@ -211,6 +218,16 @@ typedef int
 (*sensor_trigger_cmp_func_t)(sensor_type_t, sensor_data_t *,
                              sensor_data_t *, void *);
 
+/**
+ * Callback for event notifications.
+ *
+ * @param The sensor that observed the event
+ * @param The opaque argument provided during registration
+ * @param The sensor event type that was observed
+ */
+typedef int
+(*sensor_notifier_func_t)(struct sensor *, void *, sensor_event_type_t);
+
 /**
  *
  */
@@ -233,6 +250,30 @@ struct sensor_listener {
     SLIST_ENTRY(sensor_listener) sl_next;
 };
 
+/**
+ * Registration for sensor event notifications
+ */
+struct sensor_notifier {
+    /* The type of sensor event to be notified on, this is interpreted as a
+     * mask, and this notifier is called for all event types on this
+     * sensor that match the mask.
+     */
+    sensor_event_type_t sn_sensor_event_type;
+
+    /* Sensor event notification handler function, called when a matching
+     * event occurred.
+     */
+    sensor_notifier_func_t sn_func;
+
+    /* Opaque argument for the sensor event notification handler function. */
+    void *sn_arg;
+
+    /* Next item in the sensor notifier list. The head of this list is
+     * contained within the sensor object.
+     */
+    SLIST_ENTRY(sensor_notifier) sn_next;
+};
+
 /**
  * Sensor type traits list
  */
@@ -272,6 +313,13 @@ struct sensor_type_traits {
     SLIST_ENTRY(sensor_type_traits) stt_next;
 };
 
+struct sensor_notify_ev_ctx {
+    /* The sensor for which the ev cb should be called */
+    struct sensor * snec_sensor;
+    /* The event type */
+    sensor_event_type_t snec_evtype;
+};
+
 struct sensor_read_ev_ctx {
     /* The sensor for which the ev cb should be called */
     struct sensor *srec_sensor;
@@ -323,10 +371,48 @@ typedef int (*sensor_get_config_func_t)(struct sensor *, sensor_type_t,
 typedef int (*sensor_set_trigger_thresh_t)(struct sensor *, sensor_type_t,
                                            struct sensor_type_traits *stt);
 
+/**
+ * Set the notification expectation for a targeted set of events for the
+ * specific sensor. After this function returns successfully, the implementer
+ * shall post corresponding event notifications to the sensor manager.
+ *
+ * @param The sensor to expect notifications from.
+ * @param The mask of event types to expect notifications from.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*sensor_set_notification_t)(struct sensor *,
+                                         sensor_event_type_t);
+
+/**
+ * Unset the notification expectation for a targeted set of events for the
+ * specific sensor.
+ *
+ * @param The sensor.
+ * @param The mask of event types.
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*sensor_unset_notification_t)(struct sensor *,
+                                           sensor_event_type_t);
+
+/**
+ * Let driver handle interrupt in the sensor context
+ *
+ * @param The sensor.
+ * @param Interrupt argument
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+typedef int (*sensor_handle_interrupt_t)(struct sensor *);
+
 struct sensor_driver {
     sensor_read_func_t sd_read;
     sensor_get_config_func_t sd_get_config;
     sensor_set_trigger_thresh_t sd_set_trigger_thresh;
+    sensor_set_notification_t sd_set_notification;
+    sensor_unset_notification_t sd_unset_notification;
+    sensor_handle_interrupt_t sd_handle_interrupt;
 };
 
 struct sensor_timestamp {
@@ -335,6 +421,12 @@ struct sensor_timestamp {
     uint32_t st_cputime;
 };
 
+struct sensor_int {
+    uint8_t host_pin;
+    uint8_t device_pin;
+    uint8_t active;
+};
+
 struct sensor_itf {
 
     /* Sensor interface type */
@@ -354,6 +446,11 @@ struct sensor_itf {
 
     /* Sensor interface high int pin */
     uint8_t si_high_pin;
+
+    /* Sensor interface interrupts pins */
+    /* XXX We should probably remove low/high pins and replace it with those
+     */
+    struct sensor_int si_ints[MYNEWT_VAL(SENSOR_MAX_INTERRUPTS_PINS)];
 };
 
 /*
@@ -414,6 +511,11 @@ struct sensor {
      */
     SLIST_HEAD(, sensor_listener) s_listener_list;
 
+    /* A list of notifiers that are registered to receive events from this
+     * sensor
+     */
+    SLIST_HEAD(, sensor_notifier) s_notifier_list;
+
     /* A list of sensor thresholds that are registered */
     SLIST_HEAD(, sensor_type_traits) s_type_traits_list;
 
@@ -451,6 +553,28 @@ int sensor_register_listener(struct sensor *, struct sensor_listener *);
 
 int sensor_unregister_listener(struct sensor *, struct sensor_listener *);
 
+/**
+ * Register a sensor notifier. This allows a calling application to receive
+ * callbacks any time a requested event is observed.
+ *
+ * @param The sensor to register the notifier on
+ * @param The notifier to register
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int sensor_register_notifier(struct sensor *, struct sensor_notifier *);
+
+/**
+ * Un-register a sensor notifier. This allows a calling application to stop
+ * receiving callbacks for events on the sensor object.
+ *
+ * @param The sensor object to un-register the notifier on
+ * @param The notifier to remove from the notification list
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int sensor_unregister_notifier(struct sensor *, struct sensor_notifier *);
+
 int sensor_read(struct sensor *, sensor_type_t, sensor_data_func_t, void *,
         uint32_t);
 
@@ -513,13 +637,7 @@ sensor_check_type(struct sensor *sensor, sensor_type_t type)
 static inline int
 sensor_set_interface(struct sensor *sensor, struct sensor_itf *s_itf)
 {
-    sensor->s_itf.si_type = s_itf->si_type;
-    sensor->s_itf.si_num = s_itf->si_num;
-    sensor->s_itf.si_cs_pin = s_itf->si_cs_pin;
-    sensor->s_itf.si_addr = s_itf->si_addr;
-    sensor->s_itf.si_low_pin = s_itf->si_low_pin;
-    sensor->s_itf.si_high_pin = s_itf->si_high_pin;
-
+    memcpy(&sensor->s_itf, s_itf, sizeof(*s_itf));
     return (0);
 }
 
@@ -705,6 +823,22 @@ sensor_set_thresh(char *, struct sensor_type_traits *);
 int
 sensor_set_watermark_thresh(char *, struct sensor_type_traits *);
 
+/**
+ * Puts a notification event on the sensor manager evq
+ *
+ * @param notification event context
+ */
+void
+sensor_mgr_put_notify_evt(struct sensor_notify_ev_ctx *);
+
+/**
+ * Puts a interrupt event on the sensor manager evq
+ *
+ * @param interrupt event context
+ */
+void
+sensor_mgr_put_interrupt_evt(struct sensor *);
+
 /**
  * Puts read event on the sensor manager evq
  *
diff --git a/hw/sensor/src/sensor.c b/hw/sensor/src/sensor.c
index a34fd6858..79384d06d 100644
--- a/hw/sensor/src/sensor.c
+++ b/hw/sensor/src/sensor.c
@@ -76,7 +76,17 @@ struct sensor_read_ctx {
 struct sensor_timestamp sensor_base_ts;
 struct os_callout st_up_osco;
 
+static void sensor_notify_ev_cb(struct os_event * ev);
 static void sensor_read_ev_cb(struct os_event *ev);
+static void sensor_interrupt_ev_cb(struct os_event *ev);
+
+static struct os_event sensor_interrupt_event = {
+    .ev_cb = sensor_interrupt_ev_cb,
+};
+
+static struct os_event sensor_notify_event = {
+    .ev_cb = sensor_notify_ev_cb,
+};
 
   /** OS event - for doing a sensor read */
 static struct os_event sensor_read_event = {
@@ -949,15 +959,21 @@ sensor_unregister_listener(struct sensor *sensor,
         struct sensor_listener *listener)
 {
     int rc;
+    struct sensor_listener *tmp;
 
     rc = sensor_lock(sensor);
     if (rc != 0) {
         goto err;
     }
 
-    /* Remove this entry from the list */
-    SLIST_REMOVE(&sensor->s_listener_list, listener, sensor_listener,
-            sl_next);
+    SLIST_FOREACH(tmp, &sensor->s_listener_list, sl_next) {
+        if (listener == tmp) {
+        /* Remove this entry from the list */
+            SLIST_REMOVE(&sensor->s_listener_list, listener, sensor_listener,
+                    sl_next);
+            break;
+        }
+    }
 
     sensor_unlock(sensor);
 
@@ -966,6 +982,116 @@ sensor_unregister_listener(struct sensor *sensor,
     return (rc);
 }
 
+static int
+sensor_set_notification(struct sensor *sensor)
+{
+    sensor_event_type_t event_type;
+    const struct sensor_notifier *notifier;
+    int rc;
+
+    event_type = 0;
+    SLIST_FOREACH(notifier, &sensor->s_notifier_list, sn_next) {
+        event_type |= notifier->sn_sensor_event_type;
+    }
+
+    if (sensor->s_funcs->sd_set_notification) {
+        rc = sensor->s_funcs->sd_set_notification(sensor, event_type);
+    } else {
+        rc = SYS_ENODEV;
+    }
+
+    return rc;
+}
+
+/**
+ * Register a sensor notifier. This allows a calling application to receive
+ * callbacks any time a requested event is observed.
+ *
+ * @param The sensor to register the notifier on
+ * @param The notifier to register
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int
+sensor_register_notifier(struct sensor *sensor,
+                         struct sensor_notifier *notifier)
+{
+    int rc;
+    struct sensor_notifier *tmp;
+
+    rc = sensor_lock(sensor);
+    if (rc != 0) {
+        goto err;
+    }
+
+    /* Check if notifier is not already on the list */
+    SLIST_FOREACH(tmp, &sensor->s_notifier_list, sn_next) {
+        if (notifier == tmp) {
+            rc = SYS_EINVAL;
+            goto err;
+        }
+    }
+
+    SLIST_INSERT_HEAD(&sensor->s_notifier_list, notifier, sn_next);
+
+    rc = sensor_set_notification(sensor);
+    if (rc != 0) {
+        goto remove;
+    }
+
+    sensor_unlock(sensor);
+
+    return (0);
+
+remove:
+    SLIST_REMOVE(&sensor->s_notifier_list, notifier, sensor_notifier,
+            sn_next);
+
+err:
+    sensor_unlock(sensor);
+    return (rc);
+}
+
+/**
+ * Un-register a sensor notifier. This allows a calling application to stop
+ * receiving callbacks for events on the sensor object.
+ *
+ * @param The sensor object to un-register the notifier on
+ * @param The notifier to remove from the notification list
+ *
+ * @return 0 on success, non-zero error code on failure.
+ */
+int
+sensor_unregister_notifier(struct sensor *sensor,
+                           struct sensor_notifier *notifier)
+{
+    int rc = 0;
+    struct sensor_notifier *tmp;
+
+    rc = sensor_lock(sensor);
+    if (rc != 0) {
+        goto done;
+    }
+
+    SLIST_FOREACH(tmp, &sensor->s_notifier_list, sn_next) {
+        if (notifier == tmp) {
+            SLIST_REMOVE(&sensor->s_notifier_list, notifier, sensor_notifier,
+                         sn_next);
+            break;
+        }
+    }
+
+    sensor_unlock(sensor);
+
+    if (sensor->s_funcs->sd_unset_notification) {
+        rc = sensor->s_funcs->sd_unset_notification(sensor,
+                                                notifier->sn_sensor_event_type);
+    }
+
+done:
+    return (rc);
+}
+
 static int
 sensor_read_data_func(struct sensor *sensor, void *arg, void *data,
                       sensor_type_t type)
@@ -987,9 +1113,33 @@ sensor_read_data_func(struct sensor *sensor, void *arg, void *data,
     /* Call data function */
     if (ctx->user_func != NULL) {
         return (ctx->user_func(sensor, ctx->user_arg, data, type));
-    } else {
-        return (0);
     }
+
+    return (0);
+}
+
+/**
+ * Puts a interrupt event on the sensor manager evq
+ *
+ * @param interrupt event context
+ */
+void
+sensor_mgr_put_interrupt_evt(struct sensor *sensor)
+{
+    sensor_interrupt_event.ev_arg = sensor;
+    os_eventq_put(sensor_mgr_evq_get(), &sensor_interrupt_event);
+}
+
+/**
+ * Puts a notification event on the sensor manager evq
+ *
+ * @param notification event context
+ */
+void
+sensor_mgr_put_notify_evt(struct sensor_notify_ev_ctx *ctx)
+{
+    sensor_notify_event.ev_arg = ctx;
+    os_eventq_put(sensor_mgr_evq_get(), &sensor_notify_event);
 }
 
 /**
@@ -1004,6 +1154,35 @@ sensor_mgr_put_read_evt(void *arg)
     os_eventq_put(sensor_mgr_evq_get(), &sensor_read_event);
 }
 
+static void
+sensor_interrupt_ev_cb(struct os_event *ev)
+{
+    struct sensor *sensor;
+
+    sensor = ev->ev_arg;
+
+    if (sensor && sensor->s_funcs->sd_handle_interrupt) {
+        sensor->s_funcs->sd_handle_interrupt(sensor);
+    }
+}
+
+static void
+sensor_notify_ev_cb(struct os_event * ev)
+{
+    const struct sensor_notify_ev_ctx *ctx;
+    const struct sensor_notifier *notifier;
+
+    ctx = ev->ev_arg;
+
+    SLIST_FOREACH(notifier, &ctx->snec_sensor->s_notifier_list, sn_next) {
+        if (notifier->sn_sensor_event_type & ctx->snec_evtype) {
+            notifier->sn_func(ctx->snec_sensor,
+                              notifier->sn_arg,
+                              ctx->snec_evtype);
+        }
+    }
+}
+
 static void
 sensor_read_ev_cb(struct os_event *ev)
 {
diff --git a/hw/sensor/src/sensor_shell.c b/hw/sensor/src/sensor_shell.c
index 85a8bf206..18fbdca0d 100644
--- a/hw/sensor/src/sensor_shell.c
+++ b/hw/sensor/src/sensor_shell.c
@@ -79,6 +79,7 @@ sensor_display_help(void)
     console_printf("      at <poll_interval> rate for <poll_duration>\n");
     console_printf("  type <sensor_name>\n");
     console_printf("      types supported by registered sensor\n");
+    console_printf("  notify <sensor_name> [on/off] <type>\n");
 }
 
 static void
@@ -596,17 +597,106 @@ sensor_cmd_read(char *name, sensor_type_t type, struct sensor_poll_data *spd)
     return rc;
 }
 
+int
+sensor_one_tap_notif(struct sensor *sensor, void *data,
+                     sensor_event_type_t type)
+{
+
+    console_printf("Single tap happend\n");
+
+    return 0;
+};
+
+static struct sensor_notifier one_tap = {
+    .sn_sensor_event_type = SENSOR_EVENT_TYPE_SINGLE_TAP,
+    .sn_func = sensor_one_tap_notif,
+    .sn_arg = NULL,
+};
+
+int
+sensor_double_tap_notif(struct sensor *sensor, void *data,
+                        sensor_event_type_t type)
+{
+    console_printf("Double tap happend\n");
+
+    return 0;
+};
+
+static struct sensor_notifier double_tap = {
+    .sn_sensor_event_type = SENSOR_EVENT_TYPE_DOUBLE_TAP,
+    .sn_func = sensor_double_tap_notif,
+    .sn_arg = NULL,
+};
+
+static int
+sensor_cmd_notify(char *name, bool on, char *type_string)
+{
+    struct sensor *sensor;
+    int type = 0;
+    int rc = 0;
+
+    /* Look up sensor by name */
+    sensor = sensor_mgr_find_next_bydevname(name, NULL);
+    if (!sensor) {
+        console_printf("Sensor %s not found!\n", name);
+    }
+
+    if (!strcmp(type_string, "single")) {
+        type = SENSOR_EVENT_TYPE_SINGLE_TAP;
+    } else if (!strcmp(type_string, "double")) {
+        type = SENSOR_EVENT_TYPE_DOUBLE_TAP;
+    } else {
+        return 1;
+    }
+
+    if (!on) {
+        if (type == SENSOR_EVENT_TYPE_SINGLE_TAP) {
+            rc = sensor_unregister_notifier(sensor, &one_tap);
+            if (rc) {
+                console_printf("Could not unregister single tap\n");
+                goto done;
+            }
+        }
+        if (type == SENSOR_EVENT_TYPE_DOUBLE_TAP) {
+            rc = sensor_unregister_notifier(sensor, &double_tap);
+            if (rc) {
+                 console_printf("Could not unregister double tap\n");
+                 goto done;
+            }
+        }
+        goto done;
+    }
+
+    if (type == SENSOR_EVENT_TYPE_SINGLE_TAP) {
+        rc = sensor_register_notifier(sensor, &one_tap);
+        if (rc) {
+            console_printf("Could not register single tap\n");
+            goto done;
+        }
+    }
+
+    if (type == SENSOR_EVENT_TYPE_DOUBLE_TAP) {
+        rc = sensor_register_notifier(sensor, &double_tap);
+        if (rc) {
+             console_printf("Could not register double tap\n");
+             goto done;
+        }
+    }
+
+done:
+    return rc;
+}
+
 static int
 sensor_cmd_exec(int argc, char **argv)
 {
     struct sensor_poll_data spd;
     char *subcmd;
-    int rc;
+    int rc = 0;
     int i;
 
     if (argc <= 1) {
         sensor_display_help();
-        rc = 0;
         goto done;
     }
 
@@ -620,7 +710,7 @@ sensor_cmd_exec(int argc, char **argv)
                            "[-n nsamples] [-i poll_itvl(ms)] [-d poll_duration(ms)]\n",
                            argc - 2);
             rc = SYS_EINVAL;
-            goto err;
+            goto done;
         }
 
         i = 4;
@@ -640,22 +730,37 @@ sensor_cmd_exec(int argc, char **argv)
 
         rc = sensor_cmd_read(argv[2], (sensor_type_t) strtol(argv[3], NULL, 0), &spd);
         if (rc) {
-            goto err;
+            goto done;
         }
     } else if (!strcmp(argv[1], "type")) {
         rc = sensor_cmd_display_type(argv);
         if (rc) {
-            goto err;
+            goto done;
+        }
+    } else if (!strcmp(argv[1], "notify")) {
+        if (argc < 3) {
+            console_printf("Too few arguments: %d\n"
+                           "Usage: sensor notify <sensor_name> <on/off> <single/double>",
+                           argc - 2);
+            rc = SYS_EINVAL;
+            goto done;
+        }
+
+        rc = sensor_cmd_notify(argv[2], !strcmp(argv[3], "on"), argv[4]);
+        if (rc) {
+            console_printf("Too few arguments: %d\n"
+                           "Usage: sensor notify <sensor_name> <on/off> <single/double>",
+                           argc - 2);
+           goto done;
         }
+
     } else {
         console_printf("Unknown sensor command %s\n", subcmd);
         rc = SYS_EINVAL;
-        goto err;
+        goto done;
     }
 
 done:
-    return (0);
-err:
     return (rc);
 }
 
diff --git a/hw/sensor/syscfg.yml b/hw/sensor/syscfg.yml
index fbff785bf..53d548169 100644
--- a/hw/sensor/syscfg.yml
+++ b/hw/sensor/syscfg.yml
@@ -48,3 +48,8 @@ syscfg.defs:
     SENSOR_POLL_TEST_LOG:
         description: 'Sensor poller log'
         value: '0'
+
+    SENSOR_MAX_INTERRUPTS_PINS:
+         desecrition: 'Max number of interupts configuration for the sensor.
+                This should be max from all the sensors attached to the system'
+         value: 2


 

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
users@infra.apache.org


With regards,
Apache Git Services