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 2018/11/23 16:16:29 UTC

[GitHub] andrzej-kaczmarek closed pull request #1507: Add generic serial bus driver

andrzej-kaczmarek closed pull request #1507: Add generic serial bus driver
URL: https://github.com/apache/mynewt-core/pull/1507
 
 
   

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/bus_test/lis2dh_node/include/lis2dh_node/lis2dh_node.h b/apps/bus_test/lis2dh_node/include/lis2dh_node/lis2dh_node.h
new file mode 100644
index 0000000000..f97a66c253
--- /dev/null
+++ b/apps/bus_test/lis2dh_node/include/lis2dh_node/lis2dh_node.h
@@ -0,0 +1,46 @@
+/*
+ * 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 LIS2DH_NODE_H_
+#define LIS2DH_NODE_H_
+
+#include <stdint.h>
+#include "os/os_dev.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct lis2dh_node_pos {
+    uint16_t x;
+    uint16_t y;
+    uint16_t z;
+};
+
+int
+lis2dh_node_read(struct os_dev *dev, struct lis2dh_node_pos *pos);
+
+int
+lis2dh_node_i2c_create(const char *name, const struct bus_i2c_node_cfg *cfg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIS2DH_NODE_H_ */
diff --git a/apps/bus_test/lis2dh_node/pkg.yml b/apps/bus_test/lis2dh_node/pkg.yml
new file mode 100644
index 0000000000..08f3b72d5c
--- /dev/null
+++ b/apps/bus_test/lis2dh_node/pkg.yml
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+pkg.name: apps/bus_test/lis2dh_node
+pkg.description:
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/bus/i2c"
diff --git a/apps/bus_test/lis2dh_node/src/lis2dh_node.c b/apps/bus_test/lis2dh_node/src/lis2dh_node.c
new file mode 100644
index 0000000000..47e14ae798
--- /dev/null
+++ b/apps/bus_test/lis2dh_node/src/lis2dh_node.c
@@ -0,0 +1,94 @@
+/*
+ * 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 "os/mynewt.h"
+#include "console/console.h"
+#include "bus/bus.h"
+#include "bus/i2c.h"
+#include "lis2dh_node/lis2dh_node.h"
+
+static struct bus_i2c_node g_lis2dh_node;
+
+struct reg_val {
+    uint8_t addr;
+    uint8_t val[32];
+};
+
+static void
+open_node_cb(struct bus_node *node)
+{
+    struct os_dev *odev = (struct os_dev *)node;
+    struct reg_val reg;
+    int rc;
+
+    console_printf("%s: node %p\n", __func__, node);
+
+    reg.addr = 0x0f; /* WHO_AM_I */
+    rc = bus_node_simple_write_read_transact(odev, &reg.addr, 1, reg.val, 1);
+    assert(rc == 0);
+    assert(reg.val[0] == 0x33);
+
+    reg.addr = 0x20; /* CTRL_REG1 */
+    reg.val[0] = 0x37;
+    rc = bus_node_simple_write(odev, &reg.addr, 2);
+    assert(rc == 0);
+}
+
+static void
+close_node_cb(struct bus_node *node)
+{
+    console_printf("%s: node %p\n", __func__, node);
+}
+
+int
+lis2dh_node_read(struct os_dev *node, struct lis2dh_node_pos *pos)
+{
+    struct reg_val reg;
+    int rc;
+
+    assert(pos);
+
+    reg.addr = 0x80 | 0x28; /* OUT_X_L */
+    rc = bus_node_simple_write_read_transact(node, &reg.addr, 1, reg.val, 6);
+    assert(rc == 0);
+
+    pos->x = get_le16(&reg.val[0]);
+    pos->y = get_le16(&reg.val[2]);
+    pos->z = get_le16(&reg.val[4]);
+
+    return 0;
+}
+
+int
+lis2dh_node_i2c_create(const char *name, const struct bus_i2c_node_cfg *cfg)
+{
+    struct bus_node_callbacks cbs = {
+        .init = NULL,
+        .open = open_node_cb,
+        .close = close_node_cb,
+    };
+    int rc;
+
+    bus_node_set_callbacks((struct os_dev *)&g_lis2dh_node, &cbs);
+
+    rc = bus_i2c_node_create(name, &g_lis2dh_node,
+                             (struct bus_i2c_node_cfg *)cfg);
+
+    return rc;
+}
diff --git a/apps/bus_test/pkg.yml b/apps/bus_test/pkg.yml
new file mode 100644
index 0000000000..e0a43fedb5
--- /dev/null
+++ b/apps/bus_test/pkg.yml
@@ -0,0 +1,37 @@
+#
+# 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.
+#
+
+pkg.name: apps/bus_test
+pkg.type: app
+pkg.description:
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+
+pkg.deps:
+    - "@apache-mynewt-core/kernel/os"
+    - "@apache-mynewt-core/sys/console/full"
+    - "@apache-mynewt-core/sys/log/full"
+    - "@apache-mynewt-core/sys/stats/stub"
+
+pkg.deps.APP_USE_LIS2DH_NODE:
+    - "@apache-mynewt-core/apps/bus_test/lis2dh_node"
+pkg.deps.APP_USE_BME280_SENSOR:
+    - "@apache-mynewt-core/hw/drivers/sensors/bme280"
+    - "@apache-mynewt-core/hw/sensor"
diff --git a/apps/bus_test/src/main.c b/apps/bus_test/src/main.c
new file mode 100644
index 0000000000..de118a648a
--- /dev/null
+++ b/apps/bus_test/src/main.c
@@ -0,0 +1,212 @@
+/*
+ * 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 "os/mynewt.h"
+#include "bus/bus.h"
+#include "bus/i2c.h"
+#include "bus/spi.h"
+#include "console/console.h"
+#include "hal/hal_gpio.h"
+#include "sensor/sensor.h"
+#include "sensor/temperature.h"
+
+#if MYNEWT_VAL(APP_USE_LIS2DH_NODE)
+#include "lis2dh_node/lis2dh_node.h"
+#endif
+#if MYNEWT_VAL(APP_USE_BME280_SENSOR)
+#include "bme280/bme280.h"
+#endif
+
+#if MYNEWT_VAL(APP_USE_BME280_SENSOR)
+static struct sensor_itf g_bme280_sensor_itf;
+
+#if MYNEWT_VAL(BME280_NODE_BUS_TYPE) == 0
+static const struct bus_i2c_node_cfg g_bme280_i2c_node_cfg = {
+    .node_cfg = {
+        .bus_name = MYNEWT_VAL(BME280_NODE_BUS_NAME),
+    },
+    .addr = MYNEWT_VAL(BME280_NODE_I2C_ADDRESS),
+    .freq = MYNEWT_VAL(BME280_NODE_I2C_FREQUENCY),
+};
+#elif MYNEWT_VAL(BME280_NODE_BUS_TYPE) == 1
+static const struct bus_spi_node_cfg g_bme280_spi_node_cfg = {
+    .node_cfg = {
+        .bus_name = MYNEWT_VAL(BME280_NODE_BUS_NAME),
+    },
+    .pin_cs = MYNEWT_VAL(BME280_NODE_SPI_CS_PIN),
+    .mode = BUS_SPI_MODE_0,
+    .data_order = BUS_SPI_DATA_ORDER_MSB,
+    .freq = MYNEWT_VAL(BME280_NODE_SPI_FREQUENCY),
+#endif
+};
+
+static struct os_dev *g_bme280_node;
+#endif
+
+#if MYNEWT_VAL(APP_USE_LIS2DH_NODE)
+static const struct bus_i2c_node_cfg g_lis2dh_node_i2c_cfg = {
+    .node_cfg = {
+        .bus_name = MYNEWT_VAL(LIS2DH_NODE_BUS_NAME),
+    },
+    .addr = MYNEWT_VAL(LIS2DH_NODE_I2C_ADDRESS),
+    .freq = MYNEWT_VAL(LIS2DH_NODE_I2C_FREQUENCY),
+};
+
+static struct os_dev *g_lis2dh_node;
+#endif
+
+#if MYNEWT_VAL(APP_USE_BME280_SENSOR)
+static struct bme280 bme280;
+static struct sensor *bme280_sensor;
+struct sensor_listener bme280_listener;
+
+#endif
+
+static struct os_callout co_read;
+
+static void
+co_read_cb(struct os_event *ev)
+{
+#if MYNEWT_VAL(APP_USE_LIS2DH_NODE)
+    struct lis2dh_node_pos pos;
+#endif
+    int rc;
+
+#if MYNEWT_VAL(APP_USE_LIS2DH_NODE)
+    rc = lis2dh_node_read(g_lis2dh_node, &pos);
+    assert(rc == 0);
+    console_printf("X=%04x Y=%04x Z=%04x\n", pos.x, pos.y, pos.z);
+#endif
+
+    rc = os_callout_reset(&co_read, os_time_ms_to_ticks32(1000));
+    assert(rc == 0);
+}
+
+#if MYNEWT_VAL(APP_USE_BME280_SENSOR)
+static int
+bme280_sensor_listener_cb(struct sensor *sensor, void *arg,
+                          void *data, sensor_type_t type)
+{
+    struct sensor_temp_data *std;
+
+    std = data;
+
+    console_printf("T=%f (valid %d)\n", std->std_temp, std->std_temp_is_valid);
+
+    return 0;
+}
+
+
+static void
+bme280_sensor_configure(void)
+{
+    struct os_dev *dev;
+    struct bme280_cfg cfg;
+    int rc;
+
+    dev = os_dev_open("bme280", OS_TIMEOUT_NEVER, NULL);
+    assert(dev != NULL);
+
+    memset(&cfg, 0, sizeof(cfg));
+
+    cfg.bc_mode = BME280_MODE_FORCED;
+    cfg.bc_iir = BME280_FILTER_OFF;
+    cfg.bc_sby_dur = BME280_STANDBY_MS_0_5;
+    cfg.bc_boc[0].boc_type = SENSOR_TYPE_RELATIVE_HUMIDITY;
+    cfg.bc_boc[1].boc_type = SENSOR_TYPE_PRESSURE;
+    cfg.bc_boc[2].boc_type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
+    cfg.bc_boc[0].boc_oversample = BME280_SAMPLING_X1;
+    cfg.bc_boc[1].boc_oversample = BME280_SAMPLING_X1;
+    cfg.bc_boc[2].boc_oversample = BME280_SAMPLING_X1;
+    cfg.bc_s_mask = SENSOR_TYPE_AMBIENT_TEMPERATURE|
+                       SENSOR_TYPE_PRESSURE|
+                       SENSOR_TYPE_RELATIVE_HUMIDITY;
+
+    rc = bme280_config((struct bme280 *)dev, &cfg);
+    assert(rc == 0);
+
+    os_dev_close(dev);
+}
+#endif
+
+int
+main(int argc, char **argv)
+{
+    int rc;
+
+    sysinit();
+
+#if MYNEWT_VAL(APP_USE_LIS2DH_NODE)
+    rc = lis2dh_node_i2c_create("lis2dh", &g_lis2dh_node_i2c_cfg);
+    assert(rc == 0);
+
+    g_lis2dh_node = os_dev_open("lis2dh", 0, NULL);
+    assert(g_lis2dh_node);
+#endif
+
+#if MYNEWT_VAL(APP_USE_BME280_SENSOR)
+#if MYNEWT_VAL(BME280_NODE_BUS_TYPE) == 0
+    /* For I2C SDO pin is address select pin */
+    hal_gpio_init_out(MYNEWT_VAL(SPI_1_MASTER_PIN_MISO), 0);
+    /* Make sure CSB is not set to low state as it will switch BME280 to SPI */
+    hal_gpio_init_out(MYNEWT_VAL(BME280_NODE_SPI_CS_PIN), 1);
+
+    rc = bme280_create_i2c_sensor_dev(&bme280.i2c_node, "bme280",
+                                      &g_bme280_i2c_node_cfg,
+                                      &g_bme280_sensor_itf);
+    assert(rc == 0);
+#elif MYNEWT_VAL(BME280_NODE_BUS_TYPE) == 1
+    rc = bme280_create_spi_sensor_dev(&bme280.spi_node, "bme280",
+                                      &g_bme280_spi_node_cfg,
+                                      &g_bme280_sensor_itf);
+    assert(rc == 0);
+#endif
+
+    g_bme280_node = os_dev_open("bme280", 0, NULL);
+    assert(g_bme280_node);
+
+    bme280_sensor_configure();
+
+    bme280_sensor = sensor_mgr_find_next_bydevname("bme280", NULL);
+    assert(bme280_sensor);
+
+    bme280_listener.sl_sensor_type = SENSOR_TYPE_AMBIENT_TEMPERATURE;
+    bme280_listener.sl_func = bme280_sensor_listener_cb;
+    bme280_listener.sl_arg = NULL;
+
+    rc = sensor_register_listener(bme280_sensor, &bme280_listener);
+    assert(rc == 0);
+
+    rc = sensor_set_poll_rate_ms("bme280", 500);
+    assert(rc == 0);
+#endif
+
+    os_callout_init(&co_read, os_eventq_dflt_get(), co_read_cb, NULL);
+
+#if MYNEWT_VAL(APP_USE_LIS2DH_NODE)
+    rc = os_callout_reset(&co_read, os_time_ms_to_ticks32(1000));
+    assert(rc == 0);
+#endif
+
+    while (1) {
+        os_eventq_run(os_eventq_dflt_get());
+    }
+
+    return (0);
+}
diff --git a/apps/bus_test/syscfg.yml b/apps/bus_test/syscfg.yml
new file mode 100644
index 0000000000..885a57f297
--- /dev/null
+++ b/apps/bus_test/syscfg.yml
@@ -0,0 +1,67 @@
+# 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.
+#
+
+syscfg.defs:
+    APP_USE_BME280_NODE:
+        value: 1
+    APP_USE_LIS2DH_NODE:
+        value: 1
+    APP_USE_BME280_SENSOR:
+        value: 0
+
+    BME280_NODE_BUS_TYPE:
+        description: >
+            Type of bus device where BME280 is attached. Set:
+            0 for I2C
+            1 for SPI
+        value: 0
+    BME280_NODE_BUS_NAME:
+        description: Name of bus device where BME280 is attached
+        value: '"i2c0"'
+    BME280_NODE_I2C_ADDRESS:
+        description: I2C address of BME280 device
+        value: 0x76
+    BME280_NODE_I2C_FREQUENCY:
+        description: I2C frequency [kHz] to use for BME280
+        value: 100
+    BME280_NODE_SPI_FREQUENCY:
+        description: SPI frequency [kHz] to use for BME280
+        value: 4000
+    BME280_NODE_SPI_CS_PIN:
+        description: Chip select pin for BME280
+        value: 35
+
+    LIS2DH_NODE_BUS_NAME:
+        description: Name of bus device where LIS2DH is attached
+        value: '"i2c0"'
+    LIS2DH_NODE_I2C_ADDRESS:
+        description: I2C address of LIS2DH device
+        value: 0x18
+    LIS2DH_NODE_I2C_FREQUENCY:
+        description: I2C frequency [kHz] to use for LIS2DH
+        value: 400
+
+
+syscfg.vals:
+    BUS_DEBUG_OS_DEV: 1
+    FLOAT_USER: 1
+    SENSOR_CLI: 1
+    SHELL_TASK: 1
+
+syscfg.restrictions:
+    - 'BME280_NODE_BUS_TYPE == 0 || BME280_NODE_BUS_TYPE == 1'
diff --git a/hw/bus/i2c/include/bus/i2c.h b/hw/bus/i2c/include/bus/i2c.h
new file mode 100644
index 0000000000..3053da5123
--- /dev/null
+++ b/hw/bus/i2c/include/bus/i2c.h
@@ -0,0 +1,165 @@
+/*
+ * 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 HW_BUS_I2C_H_
+#define HW_BUS_I2C_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include "bus/bus.h"
+#include "bus/bus_driver.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define BUS_I2C_QUIRK_NEED_RESET_ON_TMO     0x0001
+
+/**
+ * Bus I2C device configuration
+ */
+struct bus_i2c_dev_cfg {
+    /** I2C interface number */
+    int i2c_num;
+    /** GPIO number of SDA line */
+    int pin_sda;
+    /** GPIO number of SCL line */
+    int pin_scl;
+};
+
+/**
+ * Bus I2C node configuration
+ */
+struct bus_i2c_node_cfg {
+    /** General node configuration */
+    struct bus_node_cfg node_cfg;
+    /** I2C address of node */
+    uint8_t addr;
+    /** I2C frequency to be used for node */
+    uint16_t freq;
+    /** Quirks to be applied for device */
+    uint16_t quirks;
+};
+
+/**
+ * Bus I2C device object state
+ *
+ * Contents of these objects are managed internally by bus driver and shall not
+ * be accessed directly.
+ */
+struct bus_i2c_dev {
+    struct bus_dev bdev;
+    struct bus_i2c_dev_cfg cfg;
+
+#if MYNEWT_VAL(BUS_DEBUG_OS_DEV)
+    uint32_t devmagic;
+#endif
+};
+
+/**
+ * Bus I2C node object state
+ *
+ * Contents of these objects are managed internally by bus driver and shall not
+ * be accessed directly.
+ */
+struct bus_i2c_node {
+    struct bus_node bnode;
+    uint16_t freq;
+    uint16_t quirks;
+    uint8_t addr;
+
+#if MYNEWT_VAL(BUS_DEBUG_OS_DEV)
+    uint32_t nodemagic;
+#endif
+};
+
+/**
+ * Initialize os_dev as bus I2C device
+ *
+ * This can be passed as a parameter to os_dev_create() when creating os_dev
+ * object for I2C device, however it's recommended to create devices using helper
+ * like bus_i2c_dev_create().
+ *
+ * @param node  Node device object
+ * @param arg   Node configuration struct (struct bus_node_cfg)
+ */
+int
+bus_i2c_dev_init_func(struct os_dev *odev, void *arg);
+
+/**
+ * Create bus I2C device
+ *
+ * This is a convenient helper and recommended way to create os_dev for bus I2C
+ * device instead of calling os_dev_create() directly.
+ *
+ * @param name  Name of device
+ * @param dev   Device state object
+ * @param cfg   Configuration
+ */
+static inline int
+bus_i2c_dev_create(const char *name, struct bus_i2c_dev *dev,
+                   struct bus_i2c_dev_cfg *cfg)
+{
+    struct os_dev *odev = (struct os_dev *)dev;
+
+    return os_dev_create(odev, name, OS_DEV_INIT_PRIMARY, 0,
+                         bus_i2c_dev_init_func, cfg);
+}
+
+/**
+ * Initialize os_dev as bus I2C node
+ *
+ * This can be passed as a parameter to os_dev_create() when creating os_dev
+ * object for I2C node, however it's recommended to create devices using helper
+ * like bus_i2c_node_create().
+ *
+ * @param node  Node device object
+ * @param arg   Node configuration struct (struct bus_node_cfg)
+ */
+int
+bus_i2c_node_init_func(struct os_dev *odev, void *arg);
+
+/**
+ * Create bus I2C node
+ *
+ * This is a convenient helper and recommended way to create os_dev for bus I2C
+ * node instead of calling os_dev_create() directly.
+ *
+ * @param name  Name of device
+ * @param node  Node state object
+ * @param cfg   Configuration
+ */
+static inline int
+bus_i2c_node_create(const char *name, struct bus_i2c_node *node,
+                    const struct bus_i2c_node_cfg *cfg, void *arg)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+    struct os_dev *odev = (struct os_dev *)node;
+
+    bnode->init_arg = arg;
+
+    return os_dev_create(odev, name, OS_DEV_INIT_PRIMARY, 1,
+                         bus_i2c_node_init_func, (void *)cfg);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HW_BUS_I2C_H_ */
diff --git a/hw/bus/i2c/pkg.yml b/hw/bus/i2c/pkg.yml
new file mode 100644
index 0000000000..2e2e0ac560
--- /dev/null
+++ b/hw/bus/i2c/pkg.yml
@@ -0,0 +1,25 @@
+#
+# 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.
+#
+
+pkg.name: hw/bus/i2c
+pkg.description: I2C bus implementation
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.deps:
diff --git a/hw/bus/i2c/src/i2c.c b/hw/bus/i2c/src/i2c.c
new file mode 100644
index 0000000000..d9170b7442
--- /dev/null
+++ b/hw/bus/i2c/src/i2c.c
@@ -0,0 +1,202 @@
+/*
+ * 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 <assert.h>
+#include "defs/error.h"
+#include "hal/hal_i2c.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/i2c.h"
+
+static int
+bus_i2c_enable(struct bus_dev *bdev)
+{
+    struct bus_i2c_dev *dev = (struct bus_i2c_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+
+    rc = hal_i2c_enable(dev->cfg.i2c_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_i2c_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_i2c_dev *dev = (struct bus_i2c_dev *)bdev;
+    struct bus_i2c_node *node = (struct bus_i2c_node *)bnode;
+    struct bus_i2c_node *current_node = (struct bus_i2c_node *)bdev->configured_for;
+    struct hal_i2c_settings i2c_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    if (current_node && (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_i2c_disable(dev->cfg.i2c_num);
+    if (rc) {
+        goto done;
+    }
+
+    i2c_cfg.frequency = node->freq;
+
+    rc = hal_i2c_config(dev->cfg.i2c_num, &i2c_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_i2c_enable(dev->cfg.i2c_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_i2c_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_i2c_dev *dev = (struct bus_i2c_dev *)bdev;
+    struct bus_i2c_node *node = (struct bus_i2c_node *)bnode;
+    struct hal_i2c_master_data i2c_data;
+    uint8_t last_op;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    i2c_data.address = node->addr;
+    i2c_data.buffer = buf;
+    i2c_data.len = length;
+
+    last_op = !(flags & BUS_F_NOSTOP);
+
+    rc = hal_i2c_master_read(dev->cfg.i2c_num, &i2c_data,
+                             os_time_ticks_to_ms32(timeout), last_op);
+
+    return rc;
+}
+
+static int
+bus_i2c_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_i2c_dev *dev = (struct bus_i2c_dev *)bdev;
+    struct bus_i2c_node *node = (struct bus_i2c_node *)bnode;
+    struct hal_i2c_master_data i2c_data;
+    uint8_t last_op;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    i2c_data.address = node->addr;
+    i2c_data.buffer = (uint8_t *)buf;
+    i2c_data.len = length;
+
+    last_op = !(flags & BUS_F_NOSTOP);
+
+    rc = hal_i2c_master_write(dev->cfg.i2c_num, &i2c_data,
+                              os_time_ticks_to_ms32(timeout), last_op);
+
+    return rc;
+}
+
+static int bus_i2c_disable(struct bus_dev *bdev)
+{
+    struct bus_i2c_dev *dev = (struct bus_i2c_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+
+    rc = hal_i2c_disable(dev->cfg.i2c_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static const struct bus_dev_ops bus_i2c_ops = {
+    .enable = bus_i2c_enable,
+    .configure = bus_i2c_configure,
+    .read = bus_i2c_read,
+    .write = bus_i2c_write,
+    .disable = bus_i2c_disable,
+};
+
+int
+bus_i2c_dev_init_func(struct os_dev *odev, void *arg)
+{
+    struct bus_i2c_dev *dev = (struct bus_i2c_dev *)odev;
+    struct bus_i2c_dev_cfg *cfg = arg;
+    struct hal_i2c_hw_settings hal_cfg;
+    int rc;
+
+    hal_cfg.pin_scl = cfg->pin_scl;
+    hal_cfg.pin_sda = cfg->pin_sda;
+    rc = hal_i2c_init_hw(cfg->i2c_num, &hal_cfg);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    BUS_DEBUG_POISON_DEV(dev);
+
+    rc = bus_dev_init_func(odev, (void*)&bus_i2c_ops);
+    assert(rc == 0);
+
+    dev->cfg = *cfg;
+
+    rc = hal_i2c_enable(dev->cfg.i2c_num);
+    assert(rc == 0);
+
+    return 0;
+}
+
+int
+bus_i2c_node_init_func(struct os_dev *odev, void *arg)
+{
+    struct bus_i2c_node *node = (struct bus_i2c_node *)odev;
+    struct bus_i2c_node_cfg *cfg = arg;
+    struct bus_node_cfg *node_cfg = &cfg->node_cfg;
+    int rc;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    rc = bus_node_init_func(odev, node_cfg);
+    if (rc) {
+        return rc;
+    }
+
+    node->freq = cfg->freq;
+    node->addr = cfg->addr;
+    node->quirks = cfg->quirks;
+
+    return 0;
+}
diff --git a/hw/bus/include/bus/bus.h b/hw/bus/include/bus/bus.h
new file mode 100644
index 0000000000..11a8d074a0
--- /dev/null
+++ b/hw/bus/include/bus/bus.h
@@ -0,0 +1,217 @@
+/*
+ * 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 HW_BUS_H_
+#define HW_BUS_H_
+
+#include <stdint.h>
+#include "os/os_dev.h"
+#include "os/os_mutex.h"
+#include "os/os_time.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Flags used for bus operations
+ */
+#define BUS_F_NONE          0
+#define BUS_F_NOSTOP        0x0001
+
+/**
+ * Read data from node
+ *
+ * Reads data from node. Bus is locked automatically for the duration of
+ * operation.
+ *
+ * The timeout parameter applies to complete transaction time, including
+ * locking the bus.
+ *
+ * @param node     Node device object
+ * @param buf      Buffer to read data into
+ * @param length   Length of data to be read
+ * @param timeout  Operation timeout
+ * @param flags    Flags
+ *
+ * @return 0 on success, SYS_xxx on error
+ */
+int
+bus_node_read(struct os_dev *node, void *buf, uint16_t length,
+              os_time_t timeout, uint16_t flags);
+
+/**
+ * Write data to node
+ *
+ * Writes data to node. Bus is locked automatically for the duration of
+ * operation.
+ *
+ * The timeout parameter applies to complete transaction time, including
+ * locking the bus.
+ *
+ * @param node     Node device object
+ * @param buf      Buffer with data to be written
+ * @param length   Length of data to be written
+ * @param timeout  Operation timeout
+ * @param flags    Flags
+ *
+ * @return 0 on success, SYS_xxx on error
+ */
+int
+bus_node_write(struct os_dev *node, const void *buf, uint16_t length,
+               os_time_t timeout, uint16_t flags);
+
+/**
+ * Perform write and read transaction on node
+ *
+ * Writes data to node and automatically reads response afterwards. This is a
+ * convenient shortcut for a generic write-then-read operation used to read data
+ * from devices which is executed atomically (i.e. with bus lock held during
+ * entire transaction).
+ *
+ * The timeout parameter applies to complete transaction time.
+ *
+ * @param node     Node device object
+ * @param wbuf     Buffer with data to be written
+ * @param wlength  Length of data to be written
+ * @param rbuf     Buffer to read data into
+ * @param rlength  Length of data to be read
+ * @param timeout  Operation timeout
+ * @param flags    Flags
+ *
+ * @return 0 on success, SYS_xxx on error
+ */
+int
+bus_node_write_read_transact(struct os_dev *node, const void  *wbuf,
+                             uint16_t wlength, void *rbuf, uint16_t rlength,
+                             os_time_t timeout, uint16_t flags);
+
+/**
+ * Read data from node
+ *
+ * This is simple version of bus_node_read() with default timeout and no flags.
+ *
+ * @param node     Node device object
+ * @param buf      Buffer to read data into
+ * @param length   Length of data to be read
+ *
+ * @return 0 on success, SYS_xxx on error
+ */
+static inline int
+bus_node_simple_read(struct os_dev *node, void *buf, uint16_t length)
+{
+    return bus_node_read(node, buf, length, OS_TIMEOUT_NEVER, BUS_F_NONE);
+}
+
+/**
+ * Write data to node
+ *
+ * This is simple version of bus_node_write() with default timeout and no flags.
+ *
+ * @param node     Node device object
+ * @param buf      Buffer with data to be written
+ * @param length   Length of data to be written
+ *
+ * @return 0 on success, SYS_xxx on error
+ */
+static inline int
+bus_node_simple_write(struct os_dev *node, const void *buf, uint16_t length)
+{
+    return bus_node_write(node, buf, length, OS_TIMEOUT_NEVER, BUS_F_NONE);
+}
+
+/**
+ * Perform write and read transaction on node
+ *
+ * This is simple version of bus_node_write_read_transact() with default timeout
+ * and no flags.
+ *
+ * @param node     Node device object
+ * @param wbuf     Buffer with data to be written
+ * @param wlength  Length of data to be written
+ * @param rbuf     Buffer to read data into
+ * @param rlength  Length of data to be read
+ *
+ * @return 0 on success, SYS_xxx on error
+ */
+static inline int
+bus_node_simple_write_read_transact(struct os_dev *node, const void *wbuf,
+                                    uint16_t wlength, void *rbuf,
+                                    uint16_t rlength)
+{
+    return bus_node_write_read_transact(node, wbuf, wlength, rbuf, rlength,
+                                        OS_TIMEOUT_NEVER, BUS_F_NONE);
+}
+
+/**
+ * Get lock object for bus
+ *
+ * \deprecated
+ * This API is only provided for compatibility with legacy drivers where locking
+ * is provided by Sensors interface. To lock bus for compound transactions use
+ * bus_dev_lock() and bus_dev_unlock() instead.
+ *
+ * @param bus    Bus device object
+ * @param mutex  Mutex used for bus lock
+ *
+ * return 0 on success, SYS_xxx on error
+ */
+int
+bus_dev_get_lock(struct os_dev *bus, struct os_mutex **mutex);
+
+/**
+ * Lock bus for exclusive access
+ *
+ * Locks bus for exclusive access. The parent bus of given node (i.e. bus where
+ * this node is attached) will be locked. This should be only used for compound
+ * transactions where bus shall be locked for the duration of entire transaction.
+ * Simple operations like read, write or write-read (i.e. those with dedicated
+ * APIs) lock bus automatically.
+ *
+ * After successful locking, bus is configured to be used with given node.
+ *
+ * @param node     Node to lock its parent bus
+ * @param timeout  Timeout on locking attempt
+ *
+ * return 0 on success
+ *        SYS_ETIMEOUT on lock timeout
+ */
+int
+bus_node_lock(struct os_dev *node, os_time_t timeout);
+
+/**
+ * Unlock bus node
+ *
+ * Unlocks exclusive bus access. This shall be only used when bus was previously
+ * locked with bus_node_lock(). API operations which lock bus will also unlock
+ * bus automatically.
+ *
+ * @param node  Node to unlock its parent bus
+ *
+ * return 0 on success
+ *        SYS_EACCESS when bus was not locked by current task
+ */
+int
+bus_node_unlock(struct os_dev *node);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HW_BUS_H_ */
diff --git a/hw/bus/include/bus/bus_debug.h b/hw/bus/include/bus/bus_debug.h
new file mode 100644
index 0000000000..1ab9899e54
--- /dev/null
+++ b/hw/bus/include/bus/bus_debug.h
@@ -0,0 +1,47 @@
+/*
+ * 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 HW_BUS_DEBUG_H_
+#define HW_BUS_DEBUG_H_
+
+#include "syscfg/syscfg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if MYNEWT_VAL(BUS_DEBUG_OS_DEV)
+#define BUS_DEBUG_MAGIC_DEV             0xABADBABE
+#define BUS_DEBUG_MAGIC_NODE            0xABADCAFE
+#define BUS_DEBUG_POISON_DEV(_dev)      do { (_dev)->devmagic = (BUS_DEBUG_MAGIC_DEV); } while (0)
+#define BUS_DEBUG_POISON_NODE(_node)    do { (_node)->nodemagic = (BUS_DEBUG_MAGIC_NODE); } while (0)
+#define BUS_DEBUG_VERIFY_DEV(_dev)      assert((_dev)->devmagic == (BUS_DEBUG_MAGIC_DEV))
+#define BUS_DEBUG_VERIFY_NODE(_node)    assert((_node)->nodemagic == (BUS_DEBUG_MAGIC_NODE))
+#else
+#define BUS_DEBUG_POISON_DEV(_dev)      (void)(_dev)
+#define BUS_DEBUG_POISON_NODE(_node)    (void)(_node)
+#define BUS_DEBUG_VERIFY_DEV(_dev)      (void)(_dev)
+#define BUS_DEBUG_VERIFY_NODE(_node)    (void)(_node)
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HW_BUS_DEBUG_H_ */
diff --git a/hw/bus/include/bus/bus_driver.h b/hw/bus/include/bus/bus_driver.h
new file mode 100644
index 0000000000..04306e5e38
--- /dev/null
+++ b/hw/bus/include/bus/bus_driver.h
@@ -0,0 +1,164 @@
+/*
+ * 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 HW_BUS_DRIVER_H_
+#define HW_BUS_DRIVER_H_
+
+#include <stdint.h>
+#include "os/mynewt.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bus_dev;
+struct bus_node;
+
+/**
+ * Bus device operations
+ *
+ * These operations shall be defined by bus driver
+ */
+struct bus_dev_ops {
+    /* Enable bus device */
+    int (* enable)(struct bus_dev *bus);
+    /* Configure bus for node */
+    int (* configure)(struct bus_dev *bus, struct bus_node *node);
+    /* Read data from node */
+    int (* read)(struct bus_dev *dev, struct bus_node *node, uint8_t *buf,
+                 uint16_t length, os_time_t timeout, uint16_t flags);
+    /* Write data to node */
+    int (* write)(struct bus_dev *dev, struct bus_node *node, const uint8_t *buf,
+                  uint16_t length, os_time_t timeout,  uint16_t flags);
+    /* Disable bus device */
+    int (* disable)(struct bus_dev *bus);
+};
+
+/**
+ * Bus node callbacks
+ *
+ * Node can use these callbacks to receive notifications from bus driver.
+ * All callbacks are optional.
+ */
+struct bus_node_callbacks {
+    /* Called when os_dev is initialized */
+    void (* init)(struct bus_node *node, void *arg);
+    /* Called when first reference to node object is opened */
+    void (* open)(struct bus_node *node);
+    /* Called when last reference to node object is closed */
+    void (* close)(struct bus_node *node);
+};
+
+/**
+ * Bus node configuration
+ *
+ * This can be wrapped in configuration structure defined by bus driver.
+ */
+struct bus_node_cfg {
+    /** Bus device name where node is attached */
+    const char *bus_name;
+};
+
+/**
+ * Bus device object state
+ *
+ * Contents of these objects are managed internally by bus driver and shall not
+ * be accessed directly.
+ */
+struct bus_dev {
+    struct os_dev odev;
+    const struct bus_dev_ops *dops;
+
+    struct os_mutex lock;
+    struct bus_node *configured_for;
+
+#if MYNEWT_VAL(BUS_DEBUG_OS_DEV)
+    uint32_t devmagic;
+#endif
+};
+
+/**
+ * Bus node object state
+ *
+ * Contents of these objects are managed internally by bus driver and shall not
+ * be accessed directly.
+ */
+struct bus_node {
+    struct os_dev odev;
+    struct bus_node_callbacks callbacks;
+
+    /*
+     * init_arg is valid until os_dev is initialized (bus_node_init_func called)
+     * parent_bus is valid afterwards
+     */
+    union {
+        struct bus_dev *parent_bus;
+        void *init_arg;
+    };
+
+#if MYNEWT_VAL(BUS_DEBUG_OS_DEV)
+    uint32_t nodemagic;
+#endif
+};
+
+/**
+ * Initialize os_dev as bus device
+ *
+ * This can be passed as a parameter to os_dev_create() when creating os_dev
+ * object for bus, however it's recommended to create devices using specialized
+ * APIs provided by bus drivers.
+ *
+ * @param bus  Bus device object
+ * @param arg  Bus device operations struct (struct bus_dev_ops)
+ */
+int
+bus_dev_init_func(struct os_dev *bus, void *arg);
+
+/**
+ * Initialize os_dev as bus node
+ *
+ * This can be passed as a parameter to os_dev_create() when creating os_dev
+ * object for node, however it's recommended to create devices using specialized
+ * APIs provided by bus drivers.
+ *
+ * @param node  Node device object
+ * @param arg   Node configuration struct (struct bus_node_cfg)
+ */
+int
+bus_node_init_func(struct os_dev *node, void *arg);
+
+/**
+ * Set driver callbacks for node
+ *
+ * This should be used before node device is initialized to set callbacks for
+ * receiving notifications from bus driver. It shall be called no more than once
+ * on any bus_node object.
+ *
+ * @param node  Node device object;
+ * @param cbs   Callbacks
+ *
+ */
+void
+bus_node_set_callbacks(struct os_dev *node, struct bus_node_callbacks *cbs);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HW_BUS_DRIVER_H_ */
diff --git a/hw/bus/pkg.yml b/hw/bus/pkg.yml
new file mode 100644
index 0000000000..7828e46962
--- /dev/null
+++ b/hw/bus/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+pkg.name: hw/bus
+pkg.description: Serial bus access layer
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.deps:
+
+pkg.init:
+    bus_pkg_init: 100
diff --git a/hw/bus/spi/include/bus/spi.h b/hw/bus/spi/include/bus/spi.h
new file mode 100644
index 0000000000..c2ea0425fd
--- /dev/null
+++ b/hw/bus/spi/include/bus/spi.h
@@ -0,0 +1,119 @@
+/*
+ * 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 HW_BUS_SPI_H_
+#define HW_BUS_SPI_H_
+
+#include <stddef.h>
+#include <stdint.h>
+#include "bus/bus.h"
+#include "bus/bus_driver.h"
+#include "bus/bus_debug.h"
+#include "hal/hal_spi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bus_spi_dev_cfg {
+    int spi_num;
+    int pin_sck;
+    int pin_mosi;
+    int pin_miso;
+};
+
+struct bus_spi_dev {
+    struct bus_dev bdev;
+    struct bus_spi_dev_cfg cfg;
+
+#if MYNEWT_VAL(BUS_DEBUG_OS_DEV)
+    uint32_t devmagic;
+#endif
+};
+
+#define BUS_SPI_MODE_0              (HAL_SPI_MODE0)
+#define BUS_SPI_MODE_1              (HAL_SPI_MODE1)
+#define BUS_SPI_MODE_2              (HAL_SPI_MODE2)
+#define BUS_SPI_MODE_3              (HAL_SPI_MODE3)
+
+#define BUS_SPI_DATA_ORDER_LSB      (HAL_SPI_LSB_FIRST)
+#define BUS_SPI_DATA_ORDER_MSB      (HAL_SPI_MSB_FIRST)
+
+struct bus_spi_node_cfg {
+    /** General node configuration */
+    struct bus_node_cfg node_cfg;
+    /** */
+    int pin_cs;
+    /** Data mode */
+    int mode;
+    /** Data order */
+    int data_order;
+    /** SCK frequency to be used for node */
+    uint16_t freq;
+    /** Quirks to be applied for device */
+    uint16_t quirks;
+};
+
+struct bus_spi_node {
+    struct bus_node bnode;
+    int pin_cs;
+    uint8_t mode;
+    uint8_t data_order;
+    uint16_t freq;
+    uint16_t quirks;
+
+#if MYNEWT_VAL(BUS_DEBUG_OS_DEV)
+    uint32_t nodemagic;
+#endif
+};
+
+int
+bus_spi_dev_init_func(struct os_dev *odev, void *arg);
+
+static inline int
+bus_spi_dev_create(const char *name, struct bus_spi_dev *dev,
+                   struct bus_spi_dev_cfg *cfg)
+{
+    struct os_dev *odev = (struct os_dev *)dev;
+
+    return os_dev_create(odev, name, OS_DEV_INIT_PRIMARY, 0,
+                         bus_spi_dev_init_func, cfg);
+}
+
+int
+bus_spi_node_init_func(struct os_dev *odev, void *arg);
+
+static inline int
+bus_spi_node_create(const char *name, struct bus_spi_node *node,
+                    const struct bus_spi_node_cfg *cfg, void *arg)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+    struct os_dev *odev = (struct os_dev *)node;
+
+    bnode->init_arg = arg;
+
+    return os_dev_create(odev, name, OS_DEV_INIT_PRIMARY, 1,
+                         bus_spi_node_init_func, (void *)cfg);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HW_BUS_SPI_H_ */
diff --git a/hw/bus/spi/pkg.yml b/hw/bus/spi/pkg.yml
new file mode 100644
index 0000000000..9c824323bf
--- /dev/null
+++ b/hw/bus/spi/pkg.yml
@@ -0,0 +1,28 @@
+#
+# 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.
+#
+
+pkg.name: hw/bus/spi
+pkg.description: SPI bus implementation
+pkg.author: "Apache Mynewt <de...@mynewt.apache.org>"
+pkg.homepage: "http://mynewt.apache.org/"
+pkg.keywords:
+pkg.deps:
+
+pkg.deps:
+    - "@apache-mynewt-core/hw/bus"
diff --git a/hw/bus/spi/src/spi.c b/hw/bus/spi/src/spi.c
new file mode 100644
index 0000000000..dec2926dd1
--- /dev/null
+++ b/hw/bus/spi/src/spi.c
@@ -0,0 +1,225 @@
+/*
+ * 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 <assert.h>
+#include "defs/error.h"
+#include "hal/hal_gpio.h"
+#include "hal/hal_spi.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/spi.h"
+
+static int
+bus_spi_enable(struct bus_dev *bdev)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+
+    rc = hal_spi_enable(dev->cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static int
+bus_spi_configure(struct bus_dev *bdev, struct bus_node *bnode)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    struct bus_spi_node *current_node = (struct bus_spi_node *)bdev->configured_for;
+    struct hal_spi_settings spi_cfg;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    /* No need to reconfigure if already configured with the same settings */
+    if (current_node && (current_node->mode == node->mode) &&
+                        (current_node->data_order == node->data_order) &&
+                        (current_node->freq == node->freq)) {
+        return 0;
+    }
+
+    rc = hal_spi_disable(dev->cfg.spi_num);
+    if (rc) {
+        goto done;
+    }
+
+    spi_cfg.data_mode = node->mode;
+    spi_cfg.data_order = node->data_order;
+    spi_cfg.baudrate = node->freq;
+    /* XXX add support for other word sizes */
+    spi_cfg.word_size = HAL_SPI_WORD_SIZE_8BIT;
+
+    rc = hal_spi_config(dev->cfg.spi_num, &spi_cfg);
+    if (rc) {
+        goto done;
+    }
+
+    rc = hal_spi_enable(dev->cfg.spi_num);
+
+done:
+    if (rc) {
+        rc = SYS_EIO;
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_read(struct bus_dev *bdev, struct bus_node *bnode, uint8_t *buf,
+             uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    uint8_t val;
+    int i;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    rc = 0;
+
+    hal_gpio_write(node->pin_cs, 0);
+
+    for (i = 0; i < length; i++) {
+        val = hal_spi_tx_val(dev->cfg.spi_num, 0xAA);
+        if (val == 0xFFFF) {
+            rc = SYS_EINVAL;
+            break;
+        }
+
+        buf[i] = val;
+    }
+
+    if (rc || !(flags & BUS_F_NOSTOP)) {
+        hal_gpio_write(node->pin_cs, 1);
+    }
+
+    return rc;
+}
+
+static int
+bus_spi_write(struct bus_dev *bdev, struct bus_node *bnode, const uint8_t *buf,
+              uint16_t length, os_time_t timeout, uint16_t flags)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+    struct bus_spi_node *node = (struct bus_spi_node *)bnode;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+    BUS_DEBUG_VERIFY_NODE(node);
+
+    hal_gpio_write(node->pin_cs, 0);
+
+    /* XXX update HAL to accept const instead */
+    rc = hal_spi_txrx(dev->cfg.spi_num, (uint8_t *)buf, NULL, length);
+
+    if (!(flags & BUS_F_NOSTOP)) {
+        hal_gpio_write(node->pin_cs, 1);
+    }
+
+    return rc;
+}
+
+static int bus_spi_disable(struct bus_dev *bdev)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)bdev;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(dev);
+
+    rc = hal_spi_disable(dev->cfg.spi_num);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    return 0;
+}
+
+static const struct bus_dev_ops bus_spi_ops = {
+    .enable = bus_spi_enable,
+    .configure = bus_spi_configure,
+    .read = bus_spi_read,
+    .write = bus_spi_write,
+    .disable = bus_spi_disable,
+};
+
+int
+bus_spi_dev_init_func(struct os_dev *odev, void *arg)
+{
+    struct bus_spi_dev *dev = (struct bus_spi_dev *)odev;
+    struct bus_spi_dev_cfg *cfg = arg;
+    struct hal_spi_hw_settings hal_cfg;
+    int rc;
+
+    hal_cfg.pin_sck = cfg->pin_sck;
+    hal_cfg.pin_mosi = cfg->pin_mosi;
+    hal_cfg.pin_miso = cfg->pin_miso;
+    hal_cfg.pin_ss = 0;
+
+    /* XXX we support master only! */
+    rc = hal_spi_init_hw(cfg->spi_num, HAL_SPI_TYPE_MASTER, &hal_cfg);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    BUS_DEBUG_POISON_DEV(dev);
+
+    rc = bus_dev_init_func(odev, (void*)&bus_spi_ops);
+    assert(rc == 0);
+
+    dev->cfg = *cfg;
+
+    rc = hal_spi_enable(dev->cfg.spi_num);
+    assert(rc == 0);
+
+    return 0;
+}
+
+int
+bus_spi_node_init_func(struct os_dev *odev, void *arg)
+{
+    struct bus_spi_node *node = (struct bus_spi_node *)odev;
+    struct bus_spi_node_cfg *cfg = arg;
+    struct bus_node_cfg *node_cfg = &cfg->node_cfg;
+    int rc;
+
+    BUS_DEBUG_POISON_NODE(node);
+
+    rc = bus_node_init_func(odev, node_cfg);
+    if (rc) {
+        return rc;
+    }
+
+    node->pin_cs = cfg->pin_cs;
+    node->mode = cfg->mode;
+    node->data_order = cfg->data_order;
+    node->freq = cfg->freq;
+    node->quirks = cfg->quirks;
+
+    hal_gpio_init_out(node->pin_cs, 1);
+
+    return 0;
+}
diff --git a/hw/bus/src/bus.c b/hw/bus/src/bus.c
new file mode 100644
index 0000000000..4635969be5
--- /dev/null
+++ b/hw/bus/src/bus.c
@@ -0,0 +1,292 @@
+/*
+ * 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 <assert.h>
+#include <string.h>
+#include "defs/error.h"
+#include "bus/bus.h"
+#include "bus/bus_debug.h"
+#include "bus/bus_driver.h"
+
+static int
+bus_node_open_func(struct os_dev *odev, uint32_t wait, void *arg)
+{
+    struct bus_node *bnode = (struct bus_node *)odev;
+
+    BUS_DEBUG_VERIFY_NODE(bnode);
+
+    if (!bnode->callbacks.open) {
+        return 0;
+    }
+
+    /*
+     * XXX current os_dev implementation is prone to races since reference
+     * counting is done without any locking, we'll need to fix it there
+     */
+
+    /* Call open callback if opening first ref */
+    if (odev->od_open_ref == 0) {
+        bnode->callbacks.open(bnode);
+    }
+
+    return 0;
+}
+
+static int
+bus_node_close_func(struct os_dev *odev)
+{
+    struct bus_node *bnode = (struct bus_node *)odev;
+
+    BUS_DEBUG_VERIFY_NODE(bnode);
+
+    if (!bnode->callbacks.close) {
+        return 0;
+    }
+
+    /*
+     * XXX current os_dev implementation is prone to races since reference
+     * counting is done without any locking, we'll need to fix it there
+     */
+
+    /* Call close callback if closing last ref */
+    if (odev->od_open_ref == 1) {
+        bnode->callbacks.close(bnode);
+    }
+
+    return 0;
+}
+
+void
+bus_node_set_callbacks(struct os_dev *node, struct bus_node_callbacks *cbs)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+
+    /* This should be done only once so all callbacks should be NULL here */
+    assert(bnode->callbacks.init == NULL);
+    assert(bnode->callbacks.open == NULL);
+    assert(bnode->callbacks.close == NULL);
+
+    bnode->callbacks = *cbs;
+}
+
+int
+bus_dev_init_func(struct os_dev *odev, void *arg)
+{
+    struct bus_dev *bdev = (struct bus_dev *)odev;
+    struct bus_dev_ops *ops = arg;
+
+    BUS_DEBUG_POISON_DEV(bdev);
+
+    bdev->dops = ops;
+    bdev->configured_for = NULL;
+
+    os_mutex_init(&bdev->lock);
+
+    return 0;
+}
+
+int
+bus_node_init_func(struct os_dev *odev, void *arg)
+{
+    struct bus_node *bnode = (struct bus_node *)odev;
+    struct bus_node_cfg *node_cfg = arg;
+    struct os_dev *parent_odev;
+    void *init_arg;
+
+    parent_odev = os_dev_lookup(node_cfg->bus_name);
+    if (!parent_odev) {
+        return OS_EINVAL;
+    }
+
+    BUS_DEBUG_POISON_NODE(bnode);
+
+    /* We need to save init_arg here since it will be overwritten by parent_bus */
+    init_arg = bnode->init_arg;
+    bnode->parent_bus = (struct bus_dev *)parent_odev;
+
+    odev->od_handlers.od_open = bus_node_open_func;
+    odev->od_handlers.od_close = bus_node_close_func;
+
+    if (bnode->callbacks.init) {
+        bnode->callbacks.init(bnode, init_arg);
+    }
+
+    return 0;
+}
+
+int
+bus_node_read(struct os_dev *node, void *buf, uint16_t length,
+              os_time_t timeout, uint16_t flags)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+    struct bus_dev *bdev = bnode->parent_bus;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(bdev);
+    BUS_DEBUG_VERIFY_NODE(bnode);
+
+    if (!bdev->dops->read) {
+        return SYS_ENOTSUP;
+    }
+
+    rc = bus_node_lock(node, timeout);
+    if (rc) {
+        return rc;
+    }
+
+    rc = bdev->dops->read(bdev, bnode, buf, length, timeout, flags);
+
+    (void)bus_node_unlock(node);
+
+    return rc;
+}
+
+int
+bus_node_write(struct os_dev *node, const void *buf, uint16_t length,
+               os_time_t timeout, uint16_t flags)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+    struct bus_dev *bdev = bnode->parent_bus;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(bdev);
+    BUS_DEBUG_VERIFY_NODE(bnode);
+
+    if (!bdev->dops->write) {
+        return SYS_ENOTSUP;
+    }
+
+    rc = bus_node_lock(node, timeout);
+    if (rc) {
+        return rc;
+    }
+
+    rc = bdev->dops->write(bdev, bnode, buf, length, timeout, flags);
+
+    (void)bus_node_unlock(node);
+
+    return rc;
+}
+
+int
+bus_node_write_read_transact(struct os_dev *node, const void *wbuf,
+                             uint16_t wlength, void *rbuf, uint16_t rlength,
+                             os_time_t timeout, uint16_t flags)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+    struct bus_dev *bdev = bnode->parent_bus;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(bdev);
+    BUS_DEBUG_VERIFY_NODE(bnode);
+
+    if (!bdev->dops->write || !bdev->dops->read) {
+        return SYS_ENOTSUP;
+    }
+
+    rc = bus_node_lock(node, timeout);
+    if (rc) {
+        return rc;
+    }
+
+    /*
+     * XXX we probably should pass flags here but with some of them stripped,
+     * e.g. BUS_F_NOSTOP should not be present here, but since we do not have
+     * too many flags now (like we literally have only one flag) let's just pass
+     * no flags for now
+     */
+    rc = bdev->dops->write(bdev, bnode, wbuf, wlength, timeout, BUS_F_NOSTOP);
+    if (rc) {
+        goto done;
+    }
+
+    rc = bdev->dops->read(bdev, bnode, rbuf, rlength, timeout, flags);
+    if (rc) {
+        goto done;
+    }
+
+done:
+    (void)bus_node_unlock(node);
+
+    return rc;
+}
+
+
+int
+bus_node_lock(struct os_dev *node, os_time_t timeout)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+    struct bus_dev *bdev = bnode->parent_bus;
+    os_error_t err;
+    int rc;
+
+    BUS_DEBUG_VERIFY_DEV(bdev);
+    BUS_DEBUG_VERIFY_NODE(bnode);
+
+    err = os_mutex_pend(&bdev->lock, timeout);
+    if (err == OS_TIMEOUT) {
+        return SYS_ETIMEOUT;
+    }
+
+    assert(err == OS_OK || err == OS_NOT_STARTED);
+
+    /* No need to configure if already configured for the same node */
+    if (bdev->configured_for == bnode) {
+        return 0;
+    }
+
+    rc = bdev->dops->configure(bdev, bnode);
+    if (rc) {
+        bdev->configured_for = NULL;
+    } else {
+        bdev->configured_for = bnode;
+    }
+
+    return rc;
+}
+
+int
+bus_node_unlock(struct os_dev *node)
+{
+    struct bus_node *bnode = (struct bus_node *)node;
+    struct bus_dev *bdev = bnode->parent_bus;
+    os_error_t err;
+
+    BUS_DEBUG_VERIFY_DEV(bdev);
+    BUS_DEBUG_VERIFY_NODE(bnode);
+
+    err = os_mutex_release(&bdev->lock);
+
+    /*
+     * Probably no one cares about return value from unlock, so for debugging
+     * purposes let's assert on anything that is not a success. This includes
+     * OS_INVALID_PARM (we basically can't pass invalid mutex here unless our
+     * structs are broken) and OS_BAD_MUTEX (unlock shall be only done by the
+     * same task which locked it).
+     */
+    assert(err == OS_OK || err == OS_NOT_STARTED);
+
+    return 0;
+}
+
+void
+bus_pkg_init(void)
+{
+
+}
diff --git a/hw/bus/syscfg.yml b/hw/bus/syscfg.yml
new file mode 100644
index 0000000000..62653bcdb9
--- /dev/null
+++ b/hw/bus/syscfg.yml
@@ -0,0 +1,32 @@
+# 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.
+#
+
+syscfg.defs:
+    BUS_DRIVER_PRESENT:
+        description: >
+            This indicated that hw/bus package is present in build.
+            Do not override this settings.
+        value: 1
+
+    BUS_DEBUG_OS_DEV:
+        description: >
+            Enable additional debugging for os_dev objects.
+            Each os_dev object created by bus driver will be poisoned with
+            magic value which is then checked on each operation to ensure
+            proper objects are passed to APIs.
+        value: 0
diff --git a/hw/drivers/sensors/bme280/include/bme280/bme280.h b/hw/drivers/sensors/bme280/include/bme280/bme280.h
index 55c78896cc..1411fa7b28 100644
--- a/hw/drivers/sensors/bme280/include/bme280/bme280.h
+++ b/hw/drivers/sensors/bme280/include/bme280/bme280.h
@@ -22,6 +22,11 @@
 #define __BME280_H__
 
 #include "os/mynewt.h"
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+#include "bus/bus_driver.h"
+#include "bus/i2c.h"
+#include "bus/spi.h"
+#endif
 #include "sensor/sensor.h"
 
 #define BME280_SPI_READ_CMD_BIT 0x80
@@ -102,7 +107,14 @@ struct bme280_pdd {
 };
 
 struct bme280 {
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    union {
+        struct bus_i2c_node i2c_node;
+        struct bus_spi_node spi_node;
+    };
+#else
     struct os_dev dev;
+#endif
     struct sensor sensor;
     struct bme280_cfg cfg;
     struct bme280_pdd pdd;
@@ -272,6 +284,38 @@ bme280_forced_mode_measurement(struct sensor_itf *itf);
 int bme280_shell_init(void);
 #endif
 
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+/**
+ * Create I2C bus node for BME280 sensor
+ *
+ * @param node        Bus node
+ * @param name        Device name
+ * @param i2c_cfg     I2C node configuration
+ * @param sensor_itf  Sensors interface
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+bme280_create_i2c_sensor_dev(struct bus_i2c_node *node, const char *name,
+                             const struct bus_i2c_node_cfg *i2c_cfg,
+                             struct sensor_itf *sensor_itf);
+
+/**
+ * Create SPI bus node for BME280 sensor
+ *
+ * @param node        Bus node
+ * @param name        Device name
+ * @param spi_cfg     SPI node configuration
+ * @param sensor_itf  Sensors interface
+ *
+ * @return 0 on success, non-zero on failure
+ */
+int
+bme280_create_spi_sensor_dev(struct bus_spi_node *node, const char *name,
+                             const struct bus_spi_node_cfg *spi_cfg,
+                             struct sensor_itf *sensor_itf);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/hw/drivers/sensors/bme280/pkg.yml b/hw/drivers/sensors/bme280/pkg.yml
index 22a0a6b710..2e7ed1aea2 100644
--- a/hw/drivers/sensors/bme280/pkg.yml
+++ b/hw/drivers/sensors/bme280/pkg.yml
@@ -38,3 +38,7 @@ pkg.req_apis:
 
 pkg.deps.BME280_CLI:
     - "@apache-mynewt-core/util/parse"
+
+pkg.deps.BUS_DRIVER_PRESENT:
+    - "@apache-mynewt-core/hw/bus/i2c"
+    - "@apache-mynewt-core/hw/bus/spi"
diff --git a/hw/drivers/sensors/bme280/src/bme280.c b/hw/drivers/sensors/bme280/src/bme280.c
index 67a0adee0a..1226e909b8 100644
--- a/hw/drivers/sensors/bme280/src/bme280.c
+++ b/hw/drivers/sensors/bme280/src/bme280.c
@@ -38,12 +38,14 @@
 static double NAN = 0.0/0.0;
 #endif
 
+#if !MYNEWT_VAL(BUS_DRIVER_PRESENT)
 static struct hal_spi_settings spi_bme280_settings = {
     .data_order = HAL_SPI_MSB_FIRST,
     .data_mode  = HAL_SPI_MODE0,
     .baudrate   = 4000,
     .word_size  = HAL_SPI_WORD_SIZE_8BIT,
 };
+#endif
 
 /* Define the stats section and records */
 STATS_SECT_START(bme280_stat_section)
@@ -157,6 +159,7 @@ bme280_init(struct os_dev *dev, void *arg)
         goto err;
     }
 
+#if !MYNEWT_VAL(BUS_DRIVER_PRESENT)
     rc = hal_spi_config(sensor->s_itf.si_num, &spi_bme280_settings);
     if (rc == EINVAL) {
         /* If spi is already enabled, for nrf52, it returns -1, We should not
@@ -174,6 +177,7 @@ bme280_init(struct os_dev *dev, void *arg)
     if (rc) {
         goto err;
     }
+#endif
 
     return (0);
 err:
@@ -826,9 +830,21 @@ int
 bme280_readlen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload,
                uint8_t len)
 {
+    int rc;
+
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    struct os_dev *dev = SENSOR_ITF_GET_DEVICE(itf);
+
+    /* XXX this is only required for SPI, but apparently device has no problem
+     * with this being set also for I2C so let's leave it for now since there's
+     * no API now to figure out bus type for node
+     */
+    addr |= BME280_SPI_READ_CMD_BIT;
+
+    rc = bus_node_simple_write_read_transact(dev, &addr, 1, payload, len);
+#else
     int i;
     uint16_t retval;
-    int rc;
 
     rc = 0;
 
@@ -863,6 +879,7 @@ bme280_readlen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload,
 err:
     /* De-select the device */
     hal_gpio_write(itf->si_cs_pin, 1);
+#endif
 
     return rc;
 }
@@ -880,9 +897,30 @@ int
 bme280_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload,
                 uint8_t len)
 {
-    int i;
     int rc;
 
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    struct os_dev *dev = SENSOR_ITF_GET_DEVICE(itf);
+
+    rc = bus_node_lock(dev, OS_TIMEOUT_NEVER);
+    if (rc) {
+        return SYS_EINVAL;
+    }
+
+    addr &= ~BME280_SPI_READ_CMD_BIT;
+
+    rc = bus_node_write(dev, &addr, 1, OS_TIMEOUT_NEVER, BUS_F_NOSTOP);
+    if (rc) {
+        goto done;
+    }
+
+    rc = bus_node_simple_write(dev, payload, len);
+
+done:
+    (void)bus_node_unlock(dev);
+#else
+    int i;
+
     /* Select the device */
     hal_gpio_write(itf->si_cs_pin, 0);
 
@@ -914,7 +952,7 @@ bme280_writelen(struct sensor_itf *itf, uint8_t addr, uint8_t *payload,
 err:
     /* De-select the device */
     hal_gpio_write(itf->si_cs_pin, 1);
-
+#endif
     os_time_delay((OS_TICKS_PER_SEC * 30)/1000 + 1);
 
     return rc;
@@ -1348,3 +1386,47 @@ bme280_forced_mode_measurement(struct sensor_itf *itf)
 err:
     return rc;
 }
+
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static void
+init_node_cb(struct bus_node *bnode, void *arg)
+{
+    struct sensor_itf *itf = arg;
+
+    bme280_init((struct os_dev *)bnode, itf);
+}
+
+int
+bme280_create_i2c_sensor_dev(struct bus_i2c_node *node, const char *name,
+                             const struct bus_i2c_node_cfg *i2c_cfg,
+                             struct sensor_itf *sensor_itf)
+{
+    struct bus_node_callbacks cbs = {
+        .init = init_node_cb,
+    };
+    int rc;
+
+    bus_node_set_callbacks((struct os_dev *)node, &cbs);
+
+    rc = bus_i2c_node_create(name, node, i2c_cfg, sensor_itf);
+
+    return rc;
+}
+
+int
+bme280_create_spi_sensor_dev(struct bus_spi_node *node, const char *name,
+                             const struct bus_spi_node_cfg *spi_cfg,
+                             struct sensor_itf *sensor_itf)
+{
+    struct bus_node_callbacks cbs = {
+        .init = init_node_cb,
+    };
+    int rc;
+
+    bus_node_set_callbacks((struct os_dev *)node, &cbs);
+
+    rc = bus_spi_node_create(name, node, spi_cfg, sensor_itf);
+
+    return rc;
+}
+#endif
diff --git a/hw/hal/include/hal/hal_i2c.h b/hw/hal/include/hal/hal_i2c.h
index be080ca0cd..647e7c93a1 100644
--- a/hw/hal/include/hal/hal_i2c.h
+++ b/hw/hal/include/hal/hal_i2c.h
@@ -79,6 +79,18 @@ extern "C" {
 /** Slave responded to data byte with NACK. */
 #define HAL_I2C_ERR_DATA_NACK           5
 
+/** I2C controller hardware settings */
+struct hal_i2c_hw_settings {
+    int pin_scl;
+    int pin_sda;
+};
+
+/** I2C configuration */
+struct hal_i2c_settings {
+    /** Frequency in kHz */
+    uint32_t frequency;
+};
+
 /**
  * When sending a packet, use this structure to pass the arguments.
  */
@@ -112,6 +124,52 @@ struct hal_i2c_master_data {
  */
 int hal_i2c_init(uint8_t i2c_num, void *cfg);
 
+/**
+ * Initialize I2C controller
+ *
+ * This initializes I2C controller hardware before 1st use. Shall be called
+ * only once.
+ *
+ * @param i2c_num  Number of I2C controller
+ * @param cfg      Configuration
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+int hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg);
+
+/**
+ * Enable I2C controller
+ *
+ * This enables I2C controller before usage.
+ *
+ * @param i2c_num  Number of I2C controller
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+int hal_i2c_enable(uint8_t i2c_num);
+
+/**
+ * Disable I2C controller
+ *
+ * This disabled I2C controller if no longer needed. Hardware configuration
+ * be preserved after controller is disabled.
+ *
+ * @param i2c_num  Number of I2C controller
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+int hal_i2c_disable(uint8_t i2c_num);
+
+/**
+ * Configure I2C controller
+ *
+ * This configures I2C controller for operation. Can be called multiple times.
+ *
+ * @param i2c_num  Number of I2C controller
+ * @param cfg      Configuration
+ */
+int hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg);
+
 /**
  * Sends a start condition and writes <len> bytes of data on the i2c bus.
  * This API does NOT issue a stop condition unless `last_op` is set to `1`.
diff --git a/hw/hal/include/hal/hal_spi.h b/hw/hal/include/hal/hal_spi.h
index 092cbf7065..7f26448ba6 100644
--- a/hw/hal/include/hal/hal_spi.h
+++ b/hw/hal/include/hal/hal_spi.h
@@ -60,6 +60,14 @@ extern "C" {
 /* Prototype for tx/rx callback */
 typedef void (*hal_spi_txrx_cb)(void *arg, int len);
 
+/** SPI controller hardware settings */
+struct hal_spi_hw_settings {
+    int pin_sck;
+    int pin_mosi;
+    int pin_miso;
+    int pin_ss;
+};
+
 /**
  * since one spi device can control multiple devices, some configuration
  * can be changed on the fly from the hal
@@ -88,6 +96,20 @@ struct hal_spi_settings {
  */
 int hal_spi_init(int spi_num, void *cfg, uint8_t spi_type);
 
+/**
+ * Initialize SPI controller
+ *
+ * This initializes SPI controller hardware before 1st use. Shall be called
+ * only once.
+ *
+ * @param spi_num  Number of SPI controller
+ * @param cfg      Configuration
+ *
+ * @return 0 on success, non-zero error code on failure
+ */
+int hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                    const struct hal_spi_hw_settings *cfg);
+
 /**
  * Configure the spi. Must be called after the spi is initialized (after
  * hal_spi_init is called) and when the spi is disabled (user must call
diff --git a/hw/mcu/nordic/nrf52xxx/pkg.yml b/hw/mcu/nordic/nrf52xxx/pkg.yml
index 8ba4e48770..63c0fd200b 100644
--- a/hw/mcu/nordic/nrf52xxx/pkg.yml
+++ b/hw/mcu/nordic/nrf52xxx/pkg.yml
@@ -67,3 +67,15 @@ pkg.deps.PWM_2:
 
 pkg.deps.PWM_3:
     - "@apache-mynewt-core/hw/drivers/pwm/pwm_nrf52"
+
+pkg.deps.I2C_0:
+    - "@apache-mynewt-core/hw/bus"
+    - "@apache-mynewt-core/hw/bus/i2c"
+
+pkg.deps.I2C_1:
+    - "@apache-mynewt-core/hw/bus"
+    - "@apache-mynewt-core/hw/bus/i2c"
+
+pkg.deps.SPI_1_MASTER:
+    - "@apache-mynewt-core/hw/bus"
+    - "@apache-mynewt-core/hw/bus/spi"
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
index 77239dec23..5340ee3ac4 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_i2c.c
@@ -310,6 +310,106 @@ hal_i2c_init(uint8_t i2c_num, void *usercfg)
     return (rc);
 }
 
+static inline NRF_TWI_Type *
+hal_i2c_get_regs(uint8_t i2c_num)
+{
+    struct nrf52_hal_i2c *i2c;
+    int rc;
+
+    rc = hal_i2c_resolve(i2c_num, &i2c);
+    if (rc != 0) {
+        return NULL;
+    }
+
+    return i2c->nhi_regs;
+}
+
+int
+hal_i2c_init_hw(uint8_t i2c_num, const struct hal_i2c_hw_settings *cfg)
+{
+    NRF_TWI_Type *regs;
+    NRF_GPIO_Type *port;
+    int index;
+
+    regs = hal_i2c_get_regs(i2c_num);
+    if (!regs) {
+        return HAL_I2C_ERR_INVAL;
+    }
+
+    regs->ENABLE = TWI_ENABLE_ENABLE_Disabled;
+
+    port = HAL_GPIO_PORT(cfg->pin_scl);
+    index = HAL_GPIO_INDEX(cfg->pin_scl);
+    port->PIN_CNF[index] = NRF52_SCL_PIN_CONF;
+
+    port = HAL_GPIO_PORT(cfg->pin_sda);
+    index = HAL_GPIO_INDEX(cfg->pin_sda);
+    port->PIN_CNF[index] = NRF52_SDA_PIN_CONF;
+
+    regs->PSELSCL = cfg->pin_scl;
+    regs->PSELSDA = cfg->pin_sda;
+    regs->FREQUENCY = TWI_FREQUENCY_FREQUENCY_K100;
+
+    return 0;
+}
+
+static int
+hal_i2c_set_enabled(uint8_t i2c_num, bool enabled)
+{
+    NRF_TWI_Type *regs;
+
+    regs = hal_i2c_get_regs(i2c_num);
+    if (!regs) {
+        return HAL_I2C_ERR_INVAL;
+    }
+
+    regs->ENABLE = enabled ? TWI_ENABLE_ENABLE_Enabled : TWI_ENABLE_ENABLE_Disabled;
+
+    return 0;
+}
+
+int
+hal_i2c_enable(uint8_t i2c_num)
+{
+    return hal_i2c_set_enabled(i2c_num, 1);
+}
+
+int
+hal_i2c_disable(uint8_t i2c_num)
+{
+    return hal_i2c_set_enabled(i2c_num, 0);
+}
+
+int
+hal_i2c_config(uint8_t i2c_num, const struct hal_i2c_settings *cfg)
+{
+    NRF_TWI_Type *regs;
+    int freq;
+
+    regs = hal_i2c_get_regs(i2c_num);
+    if (!regs) {
+        return HAL_I2C_ERR_INVAL;
+    }
+
+    switch (cfg->frequency) {
+    case 100:
+        freq = TWI_FREQUENCY_FREQUENCY_K100;
+        break;
+    case 250:
+        freq = TWI_FREQUENCY_FREQUENCY_K250;
+        break;
+    case 400:
+        freq = TWI_FREQUENCY_FREQUENCY_K400;
+        break;
+    default:
+        return HAL_I2C_ERR_INVAL;
+    }
+
+    regs->FREQUENCY = freq;
+
+    return 0;
+}
+
 int
 hal_i2c_master_write(uint8_t i2c_num, struct hal_i2c_master_data *pdata,
                      uint32_t timo, uint8_t last_op)
diff --git a/hw/mcu/nordic/nrf52xxx/src/hal_spi.c b/hw/mcu/nordic/nrf52xxx/src/hal_spi.c
index d4dc3a1215..4a2c5b52df 100644
--- a/hw/mcu/nordic/nrf52xxx/src/hal_spi.c
+++ b/hw/mcu/nordic/nrf52xxx/src/hal_spi.c
@@ -663,6 +663,20 @@ hal_spi_init(int spi_num, void *cfg, uint8_t spi_type)
     return (rc);
 }
 
+int
+hal_spi_init_hw(uint8_t spi_num, uint8_t spi_type,
+                const struct hal_spi_hw_settings *cfg)
+{
+    struct nrf52_hal_spi_cfg hal_cfg;
+
+    hal_cfg.sck_pin = cfg->pin_sck;
+    hal_cfg.mosi_pin = cfg->pin_mosi;
+    hal_cfg.miso_pin = cfg->pin_miso;
+    hal_cfg.ss_pin = cfg->pin_ss;
+
+    return hal_spi_init(spi_num, &hal_cfg, spi_type);
+}
+
 /**
  * Configure the spi. Must be called after the spi is initialized (after
  * hal_spi_init is called) and when the spi is disabled (user must call
diff --git a/hw/mcu/nordic/nrf52xxx/src/nrf52_periph.c b/hw/mcu/nordic/nrf52xxx/src/nrf52_periph.c
index f951aaadd1..0aaacd7d55 100644
--- a/hw/mcu/nordic/nrf52xxx/src/nrf52_periph.c
+++ b/hw/mcu/nordic/nrf52xxx/src/nrf52_periph.c
@@ -24,6 +24,14 @@
 #include "hal/hal_i2c.h"
 #include "hal/hal_spi.h"
 #include "bsp/bsp.h"
+#if MYNEWT_VAL(I2C_0) || MYNEWT_VAL(I2C_1)
+#include "bus/bus.h"
+#include "bus/i2c.h"
+#endif
+#if MYNEWT_VAL(SPI_1_MASTER)
+#include "bus/bus.h"
+#include "bus/spi.h"
+#endif
 #include "nrfx.h"
 #if MYNEWT_VAL(ADC_0)
 #include "adc/adc.h"
@@ -86,19 +94,37 @@ static const struct nrf52_uart_cfg os_bsp_uart1_cfg = {
 #endif
 
 #if MYNEWT_VAL(I2C_0)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c0_cfg = {
+    .i2c_num = 0,
+    .pin_sda = MYNEWT_VAL(I2C_0_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_0_PIN_SCL),
+};
+static struct bus_i2c_dev i2c0_bus;
+#else
 static const struct nrf52_hal_i2c_cfg hal_i2c0_cfg = {
     .scl_pin = MYNEWT_VAL(I2C_0_PIN_SCL),
     .sda_pin = MYNEWT_VAL(I2C_0_PIN_SDA),
     .i2c_frequency = MYNEWT_VAL(I2C_0_FREQ_KHZ),
 };
 #endif
+#endif
 #if MYNEWT_VAL(I2C_1)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_i2c_dev_cfg i2c1_cfg = {
+    .i2c_num = 1,
+    .pin_sda = MYNEWT_VAL(I2C_1_PIN_SDA),
+    .pin_scl = MYNEWT_VAL(I2C_1_PIN_SCL),
+};
+static struct bus_i2c_dev i2c1_bus;
+#else
 static const struct nrf52_hal_i2c_cfg hal_i2c1_cfg = {
     .scl_pin = MYNEWT_VAL(I2C_1_PIN_SCL),
     .sda_pin = MYNEWT_VAL(I2C_1_PIN_SDA),
     .i2c_frequency = MYNEWT_VAL(I2C_1_FREQ_KHZ),
 };
 #endif
+#endif
 
 #if MYNEWT_VAL(SPI_0_MASTER)
 static const struct nrf52_hal_spi_cfg os_bsp_spi0m_cfg = {
@@ -117,6 +143,15 @@ static const struct nrf52_hal_spi_cfg os_bsp_spi0s_cfg = {
 };
 #endif
 #if MYNEWT_VAL(SPI_1_MASTER)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+static const struct bus_spi_dev_cfg spi1_cfg = {
+    .spi_num = 1,
+    .pin_sck = MYNEWT_VAL(SPI_1_MASTER_PIN_SCK),
+    .pin_mosi = MYNEWT_VAL(SPI_1_MASTER_PIN_MOSI),
+    .pin_miso = MYNEWT_VAL(SPI_1_MASTER_PIN_MISO),
+};
+static struct bus_spi_dev spi1_bus;
+#else
 static const struct nrf52_hal_spi_cfg os_bsp_spi1m_cfg = {
     .sck_pin      = MYNEWT_VAL(SPI_1_MASTER_PIN_SCK),
     .mosi_pin     = MYNEWT_VAL(SPI_1_MASTER_PIN_MOSI),
@@ -124,6 +159,7 @@ static const struct nrf52_hal_spi_cfg os_bsp_spi1m_cfg = {
     /* For SPI master, SS pin is controlled as regular GPIO */
 };
 #endif
+#endif
 #if MYNEWT_VAL(SPI_1_SLAVE)
 static const struct nrf52_hal_spi_cfg os_bsp_spi1s_cfg = {
     .sck_pin      = MYNEWT_VAL(SPI_1_SLAVE_PIN_SCK),
@@ -279,13 +315,23 @@ nrf52_periph_create_i2c(void)
     (void)rc;
 
 #if MYNEWT_VAL(I2C_0)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    rc = bus_i2c_dev_create("i2c0", &i2c0_bus, (struct bus_i2c_dev_cfg *)&i2c0_cfg);
+    assert(rc == 0);
+#else
     rc = hal_i2c_init(0, (void *)&hal_i2c0_cfg);
     assert(rc == 0);
 #endif
+#endif
 #if MYNEWT_VAL(I2C_1)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    rc = bus_i2c_dev_create("i2c1", &i2c1_bus, (struct bus_i2c_dev_cfg *)&i2c1_cfg);
+    assert(rc == 0);
+#else
     rc = hal_i2c_init(1, (void *)&hal_i2c1_cfg);
     assert(rc == 0);
 #endif
+#endif
 }
 
 static void
@@ -304,9 +350,14 @@ nrf52_periph_create_spi(void)
     assert(rc == 0);
 #endif
 #if MYNEWT_VAL(SPI_1_MASTER)
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    rc = bus_spi_dev_create("spi1", &spi1_bus, (struct bus_spi_dev_cfg *)&spi1_cfg);
+    assert(rc == 0);
+#else
     rc = hal_spi_init(1, (void *)&os_bsp_spi1m_cfg, HAL_SPI_TYPE_MASTER);
     assert(rc == 0);
 #endif
+#endif
 #if MYNEWT_VAL(SPI_1_SLAVE)
     rc = hal_spi_init(1, (void *)&os_bsp_spi1s_cfg, HAL_SPI_TYPE_SLAVE);
     assert(rc == 0);
diff --git a/hw/sensor/include/sensor/sensor.h b/hw/sensor/include/sensor/sensor.h
index bedf034446..7df28b406e 100644
--- a/hw/sensor/include/sensor/sensor.h
+++ b/hw/sensor/include/sensor/sensor.h
@@ -23,6 +23,10 @@
 #include <string.h>
 #include "os/mynewt.h"
 
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+#include "bus/i2c.h"
+#include "bus/spi.h"
+#endif
 #if MYNEWT_VAL(SENSOR_OIC)
 #include "oic/oc_ri.h"
 #endif
@@ -506,6 +510,9 @@ struct sensor_int {
 
 struct sensor_itf {
 
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    /* Device configuration is stored in bus node */
+#else
     /* Sensor interface type */
     uint8_t si_type;
 
@@ -517,6 +524,7 @@ struct sensor_itf {
 
     /* Sensor address */
     uint16_t si_addr;
+#endif
 
     /* Sensor interface low int pin */
     uint8_t si_low_pin;
@@ -524,8 +532,12 @@ struct sensor_itf {
     /* Sensor interface high int pin */
     uint8_t si_high_pin;
 
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+    /* No need for mutex - locking is done by bus driver */
+#else
     /* Mutex for interface access */
     struct os_mutex *si_lock;
+#endif
 
     /* Sensor interface interrupts pins */
     /* XXX We should probably remove low/high pins and replace it with those
@@ -533,6 +545,16 @@ struct sensor_itf {
     struct sensor_int si_ints[MYNEWT_VAL(SENSOR_MAX_INTERRUPTS_PINS)];
 };
 
+#if MYNEWT_VAL(BUS_DRIVER_PRESENT)
+struct sensor_node_cfg {
+    struct sensor_itf itf;
+    union {
+        struct bus_i2c_node_cfg i2c_node_cfg;
+        struct bus_spi_node_cfg spi_node_cfg;
+    };
+};
+#endif
+
 /*
  * Return the OS device structure corresponding to this sensor
  */
@@ -543,6 +565,16 @@ struct sensor_itf {
  */
 #define SENSOR_GET_ITF(__s) (&((__s)->s_itf))
 
+/*
+ * Return original sensor from sensor interface
+ */
+#define SENSOR_ITF_GET_SENSOR(__itf)    CONTAINER_OF((__itf), struct sensor, s_itf)
+
+/*
+ * Return OS device for original sensor from sensor interface
+ */
+#define SENSOR_ITF_GET_DEVICE(__itf)    SENSOR_GET_DEVICE(SENSOR_ITF_GET_SENSOR((__itf)))
+
 /*
  * Checks if the sensor data is valid and then compares if it is greater than
  * the data that is specified
diff --git a/hw/sensor/pkg.yml b/hw/sensor/pkg.yml
index 7c61a7c429..db270640fe 100644
--- a/hw/sensor/pkg.yml
+++ b/hw/sensor/pkg.yml
@@ -33,6 +33,12 @@ pkg.deps.SENSOR_CLI:
     - "@apache-mynewt-core/sys/shell"
     - "@apache-mynewt-core/util/parse"
 
+# XXX probably both do not need to be always included, but let's keep it like
+# this for now to make things simpler
+pkg.deps.BUS_DRIVER_PRESENT:
+    - "@apache-mynewt-core/hw/bus/i2c"
+    - "@apache-mynewt-core/hw/bus/spi"
+
 pkg.req_apis:
     - console
     
diff --git a/hw/sensor/src/sensor.c b/hw/sensor/src/sensor.c
index 634fccab00..1e9e5da8b6 100644
--- a/hw/sensor/src/sensor.c
+++ b/hw/sensor/src/sensor.c
@@ -868,6 +868,7 @@ sensor_pkg_init(void)
 int
 sensor_itf_lock(struct sensor_itf *si, uint32_t timeout)
 {
+#if !MYNEWT_VAL(BUS_DRIVER_PRESENT)
     int rc;
     os_time_t ticks;
 
@@ -886,6 +887,9 @@ sensor_itf_lock(struct sensor_itf *si, uint32_t timeout)
     }
 
     return (rc);
+#else
+    return 0;
+#endif
 }
 
 /**
@@ -898,11 +902,13 @@ sensor_itf_lock(struct sensor_itf *si, uint32_t timeout)
 void
 sensor_itf_unlock(struct sensor_itf *si)
 {
+#if !MYNEWT_VAL(BUS_DRIVER_PRESENT)
     if (!si->si_lock) {
         return;
     }
 
     os_mutex_release(si->si_lock);
+#endif
 }
 
 


 

----------------------------------------------------------------
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