acassis commented on a change in pull request #4415:
URL: https://github.com/apache/incubator-nuttx/pull/4415#discussion_r696529821



##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */

Review comment:
       Include an empty line after a comment line

##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */
+  msa301_set_axis(priv, 1);
+
+  up_mdelay(5);
+
+  sninfo("Starting....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_stop
+ *
+ * Description:
+ *   Stop the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  /* Disable the accelerometer */

Review comment:
       Ditto

##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */
+  msa301_set_axis(priv, 1);
+
+  up_mdelay(5);
+
+  sninfo("Starting....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_stop
+ *
+ * Description:
+ *   Stop the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  /* Disable the accelerometer */
+  msa301_set_axis(priv, 0);
+
+  // Power suspend
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  sninfo("Stoping....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_read
+ *
+ * Description:
+ *   Read the sensor.
+ *   A sensor in a steady state on a horizontal surface will
+ *   measure 0 g on both the X-axis and Y-axis, whereas the Z-axis will
+ *   measure 1 g. The X- and Y-axis have an offset
+ *   of 40 mg/LSB
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv)
+{
+  DEBUGASSERT(priv != NULL);
+
+  uint8_t xyz_value[6] = { 0 };
+  if (msa301_readreg(priv, MSA301_REG_OUT_X_L, xyz_value, 6) < 0)
+    {
+      return -EIO;
+    }
+
+  priv->sensor_data.x_data = xyz_value[1] << 8 | xyz_value[0];
+  priv->sensor_data.y_data = xyz_value[3] << 8 | xyz_value[2];
+  priv->sensor_data.z_data = xyz_value[5] << 8 | xyz_value[4];
+
+  /* 14 bit resolution */
+  priv->sensor_data.x_data >>= 2;
+  priv->sensor_data.y_data >>= 2;
+  priv->sensor_data.z_data >>= 2;
+
+  float scale = 1;
+  if (priv->range == MSA301_RANGE_2_G)
+    {
+      scale = 4096;
+    }
+  else if (priv->range == MSA301_RANGE_4_G)
+    {
+      scale = 2048;
+    }
+  else if (priv->range == MSA301_RANGE_8_G)
+    {
+      scale = 1024;
+    }
+  else if (priv->range == MSA301_RANGE_16_G)
+    {
+      scale = 512;
+    }
+
+  priv->sensor_data.x_acc = (float)priv->sensor_data.x_data / scale;
+  priv->sensor_data.y_acc = (float)priv->sensor_data.y_data / scale;
+  priv->sensor_data.z_acc = (float)priv->sensor_data.z_data / scale;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_open
+ *
+ * Description:
+ *   This method is called when the device is opened.
+ *
+ ****************************************************************************/
+
+static int msa301_open(FAR struct file *filep)
+{
+  FAR struct inode *       inode;
+  FAR struct msa301_dev_s *priv;
+
+  DEBUGASSERT(filep != NULL);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode != NULL);
+  priv = (FAR struct msa301_dev_s *)inode->i_private;
+
+  DEBUGASSERT(priv != NULL);
+
+  nxsem_wait(&priv->exclsem);
+
+  priv->ops->start(priv);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_close
+ *
+ * Description:
+ *   This method is called when the device is closed.
+ *
+ ****************************************************************************/
+
+static int msa301_close(FAR struct file *filep)
+{
+  FAR struct inode *       inode;
+  FAR struct msa301_dev_s *priv;
+
+  DEBUGASSERT(filep != NULL);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode != NULL);
+  priv = (FAR struct msa301_dev_s *)inode->i_private;
+
+  DEBUGASSERT(priv != NULL);
+
+  priv->ops->stop(priv);
+
+  nxsem_post(&priv->exclsem);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_read
+ *
+ * Description:
+ *   The standard read method.
+ *
+ ****************************************************************************/
+
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen)
+{
+  FAR struct inode *       inode;
+  FAR struct msa301_dev_s *priv;
+
+  /* Sanity check */
+
+  DEBUGASSERT(filep != NULL);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode != NULL);
+  priv = (FAR struct msa301_dev_s *)inode->i_private;
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(buffer != NULL);
+
+  if (buflen < sizeof(struct msa301_sensor_data_s))
+    {
+      return -ENOMEM;
+    }
+
+  if (priv->ops->sensor_read(priv) < 0)
+    {
+      return -EIO;
+    }
+
+  int datalen = sizeof(struct msa301_sensor_data_s);
+  memcpy(buffer, &priv->sensor_data, datalen);
+
+  return datalen;
+}
+
+/****************************************************************************
+ * Name: msa301_write
+ *
+ * Description:
+ *   A dummy write method.
+ *
+ ****************************************************************************/
+
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen)
+{
+  return -ENOSYS;
+}
+
+/****************************************************************************
+ * Name: msa301_ioctl
+ *
+ * Description:
+ *   The standard ioctl method.
+ *
+ ****************************************************************************/
+
+static int msa301_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
+{
+  FAR struct inode *       inode;
+  FAR struct msa301_dev_s *priv;
+  int                      ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(filep != NULL);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode != NULL);
+  priv = (FAR struct msa301_dev_s *)inode->i_private;
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Handle ioctl commands */
+
+  switch (cmd)
+    {
+      case SNIOC_MSA301_START:
+        ret = priv->ops->start(priv);
+        break;
+
+      case SNIOC_MSA301_STOP:
+        ret = priv->ops->stop(priv);
+        break;
+
+      case SNIOC_MSA301_SET_RANGE:
+        ret = msa301_set_range(priv, arg);
+        break;
+
+      case SNIOC_MSA301_SET_RATE:
+        ret = msa301_set_rate(priv, arg);
+        break;
+
+        /* Unrecognized commands */
+      default:
+        snerr("ERROR: Unrecognized cmd: %d arg: %lu\n", cmd, arg);
+        ret = -ENOTTY;
+        break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: msa301_register
+ *
+ * Description:
+ *   Register the msa301 accelerometer, gyroscope device as 'devpath'.
+ *
+ * Input Parameters:
+ *   devpath - The full path to the driver to register, e.g.
+ *             "/dev/msa301".
+ *   i2c     - An I2C driver instance.
+ *   addr    - The I2C address of the msa301 accelerometer, gyroscope or
+ *             magnetometer.
+ *   ops     - The device operations structure.
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops)
+{
+  FAR struct msa301_dev_s *priv;
+  int                      ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(devpath != NULL);
+  DEBUGASSERT(i2c != NULL);
+
+  /* Initialize the device's structure */
+
+  priv = (FAR struct msa301_dev_s *)kmm_malloc(sizeof(*priv));
+  if (priv == NULL)
+    {
+      snerr("ERROR: Failed to allocate instance\n");
+      return -ENOMEM;
+    }
+
+  priv->i2c  = i2c;
+  priv->addr = addr;
+  priv->ops  = ops;
+
+  /* ID check */
+  uint8_t id = 0;

Review comment:
       Ditto! Move to top

##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */
+  msa301_set_axis(priv, 1);
+
+  up_mdelay(5);
+
+  sninfo("Starting....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_stop
+ *
+ * Description:
+ *   Stop the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  /* Disable the accelerometer */
+  msa301_set_axis(priv, 0);
+
+  // Power suspend
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  sninfo("Stoping....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_read
+ *
+ * Description:
+ *   Read the sensor.
+ *   A sensor in a steady state on a horizontal surface will
+ *   measure 0 g on both the X-axis and Y-axis, whereas the Z-axis will
+ *   measure 1 g. The X- and Y-axis have an offset
+ *   of 40 mg/LSB
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv)
+{
+  DEBUGASSERT(priv != NULL);
+
+  uint8_t xyz_value[6] = { 0 };
+  if (msa301_readreg(priv, MSA301_REG_OUT_X_L, xyz_value, 6) < 0)
+    {
+      return -EIO;
+    }
+
+  priv->sensor_data.x_data = xyz_value[1] << 8 | xyz_value[0];
+  priv->sensor_data.y_data = xyz_value[3] << 8 | xyz_value[2];
+  priv->sensor_data.z_data = xyz_value[5] << 8 | xyz_value[4];
+
+  /* 14 bit resolution */
+  priv->sensor_data.x_data >>= 2;
+  priv->sensor_data.y_data >>= 2;
+  priv->sensor_data.z_data >>= 2;
+
+  float scale = 1;
+  if (priv->range == MSA301_RANGE_2_G)
+    {
+      scale = 4096;
+    }
+  else if (priv->range == MSA301_RANGE_4_G)
+    {
+      scale = 2048;
+    }
+  else if (priv->range == MSA301_RANGE_8_G)
+    {
+      scale = 1024;
+    }
+  else if (priv->range == MSA301_RANGE_16_G)
+    {
+      scale = 512;
+    }
+
+  priv->sensor_data.x_acc = (float)priv->sensor_data.x_data / scale;
+  priv->sensor_data.y_acc = (float)priv->sensor_data.y_data / scale;
+  priv->sensor_data.z_acc = (float)priv->sensor_data.z_data / scale;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_open
+ *
+ * Description:
+ *   This method is called when the device is opened.
+ *
+ ****************************************************************************/
+
+static int msa301_open(FAR struct file *filep)
+{
+  FAR struct inode *       inode;
+  FAR struct msa301_dev_s *priv;
+
+  DEBUGASSERT(filep != NULL);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode != NULL);
+  priv = (FAR struct msa301_dev_s *)inode->i_private;
+
+  DEBUGASSERT(priv != NULL);
+
+  nxsem_wait(&priv->exclsem);
+
+  priv->ops->start(priv);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_close
+ *
+ * Description:
+ *   This method is called when the device is closed.
+ *
+ ****************************************************************************/
+
+static int msa301_close(FAR struct file *filep)
+{
+  FAR struct inode *       inode;
+  FAR struct msa301_dev_s *priv;
+
+  DEBUGASSERT(filep != NULL);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode != NULL);
+  priv = (FAR struct msa301_dev_s *)inode->i_private;
+
+  DEBUGASSERT(priv != NULL);
+
+  priv->ops->stop(priv);
+
+  nxsem_post(&priv->exclsem);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_read
+ *
+ * Description:
+ *   The standard read method.
+ *
+ ****************************************************************************/
+
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen)
+{
+  FAR struct inode *       inode;
+  FAR struct msa301_dev_s *priv;
+
+  /* Sanity check */
+
+  DEBUGASSERT(filep != NULL);
+  inode = filep->f_inode;
+
+  DEBUGASSERT(inode != NULL);
+  priv = (FAR struct msa301_dev_s *)inode->i_private;
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(buffer != NULL);
+
+  if (buflen < sizeof(struct msa301_sensor_data_s))
+    {
+      return -ENOMEM;
+    }
+
+  if (priv->ops->sensor_read(priv) < 0)
+    {
+      return -EIO;
+    }
+
+  int datalen = sizeof(struct msa301_sensor_data_s);

Review comment:
       Please declare datalen at the top of the function, it needs to be 
compliant with C89

##########
File path: include/nuttx/sensors/msa301.h
##########
@@ -0,0 +1,118 @@
+#ifndef __MSA301_H
+#define __MSA301_H
+
+#include <nuttx/config.h>
+#include <nuttx/sensors/ioctl.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+#define MSA301_ACCEL_ADDR0     0x26
+
+#define SNIOC_MSA301_START                _SNIOC(0x0001)
+#define SNIOC_MSA301_STOP                 _SNIOC(0x0002)
+#define SNIOC_MSA301_SET_RANGE            _SNIOC(0x0003)
+#define SNIOC_MSA301_SET_RATE             _SNIOC(0x0004)
+
+#define MSA301_REG_PARTID 0x01
+#define MSA301_REG_OUT_X_L 0x02
+#define MSA301_REG_OUT_X_H 0x03
+#define MSA301_REG_OUT_Y_L 0x04
+#define MSA301_REG_OUT_Y_H 0x05
+#define MSA301_REG_OUT_Z_L 0x06
+#define MSA301_REG_OUT_Z_H 0x07
+#define MSA301_REG_MOTIONINT 0x09
+#define MSA301_REG_DATAINT 0x0A
+#define MSA301_REG_CLICKSTATUS 0x0B
+#define MSA301_REG_RESRANGE 0x0F
+#define MSA301_REG_ODR 0x10
+#define MSA301_REG_POWERMODE 0x11
+#define MSA301_REG_INTSET0 0x16
+#define MSA301_REG_INTSET1 0x17
+#define MSA301_REG_INTMAP0 0x19
+#define MSA301_REG_INTMAP1 0x1A
+#define MSA301_REG_TAPDUR 0x2A
+#define MSA301_REG_TAPTH 0x2B
+
+/** The accelerometer ranges */
+typedef enum {
+  MSA301_RANGE_2_G  = 0x0,  ///< +/- 2g
+  MSA301_RANGE_4_G  = 0x1,  ///< +/- 4g
+  MSA301_RANGE_8_G  = 0x2,  ///< +/- 8g
+  MSA301_RANGE_16_G = 0x3, ///< +/- 16g
+} msa301_range_t;
+
+#define MSA301_CTL_RANGE_SHIFT  (0x0)
+#define MSA301_CTL_RANGE_MASK   (0x3<<0)
+
+/** The accelerometer data rate */

Review comment:
       Ditto

##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */
+  msa301_set_axis(priv, 1);
+
+  up_mdelay(5);
+
+  sninfo("Starting....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_stop
+ *
+ * Description:
+ *   Stop the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  /* Disable the accelerometer */
+  msa301_set_axis(priv, 0);
+
+  // Power suspend
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  sninfo("Stoping....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_read
+ *
+ * Description:
+ *   Read the sensor.
+ *   A sensor in a steady state on a horizontal surface will
+ *   measure 0 g on both the X-axis and Y-axis, whereas the Z-axis will
+ *   measure 1 g. The X- and Y-axis have an offset
+ *   of 40 mg/LSB
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv)
+{
+  DEBUGASSERT(priv != NULL);
+
+  uint8_t xyz_value[6] = { 0 };
+  if (msa301_readreg(priv, MSA301_REG_OUT_X_L, xyz_value, 6) < 0)
+    {
+      return -EIO;
+    }
+
+  priv->sensor_data.x_data = xyz_value[1] << 8 | xyz_value[0];
+  priv->sensor_data.y_data = xyz_value[3] << 8 | xyz_value[2];
+  priv->sensor_data.z_data = xyz_value[5] << 8 | xyz_value[4];
+
+  /* 14 bit resolution */
+  priv->sensor_data.x_data >>= 2;
+  priv->sensor_data.y_data >>= 2;
+  priv->sensor_data.z_data >>= 2;
+
+  float scale = 1;

Review comment:
       The variable declaration should be compliant with C89, please move this 
declaration to the top of the function

##########
File path: include/nuttx/sensors/msa301.h
##########
@@ -0,0 +1,118 @@
+#ifndef __MSA301_H
+#define __MSA301_H
+
+#include <nuttx/config.h>
+#include <nuttx/sensors/ioctl.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+#define MSA301_ACCEL_ADDR0     0x26
+
+#define SNIOC_MSA301_START                _SNIOC(0x0001)
+#define SNIOC_MSA301_STOP                 _SNIOC(0x0002)
+#define SNIOC_MSA301_SET_RANGE            _SNIOC(0x0003)
+#define SNIOC_MSA301_SET_RATE             _SNIOC(0x0004)
+
+#define MSA301_REG_PARTID 0x01
+#define MSA301_REG_OUT_X_L 0x02
+#define MSA301_REG_OUT_X_H 0x03
+#define MSA301_REG_OUT_Y_L 0x04
+#define MSA301_REG_OUT_Y_H 0x05
+#define MSA301_REG_OUT_Z_L 0x06
+#define MSA301_REG_OUT_Z_H 0x07
+#define MSA301_REG_MOTIONINT 0x09
+#define MSA301_REG_DATAINT 0x0A
+#define MSA301_REG_CLICKSTATUS 0x0B
+#define MSA301_REG_RESRANGE 0x0F
+#define MSA301_REG_ODR 0x10
+#define MSA301_REG_POWERMODE 0x11
+#define MSA301_REG_INTSET0 0x16
+#define MSA301_REG_INTSET1 0x17
+#define MSA301_REG_INTMAP0 0x19
+#define MSA301_REG_INTMAP1 0x1A
+#define MSA301_REG_TAPDUR 0x2A
+#define MSA301_REG_TAPTH 0x2B
+
+/** The accelerometer ranges */
+typedef enum {
+  MSA301_RANGE_2_G  = 0x0,  ///< +/- 2g
+  MSA301_RANGE_4_G  = 0x1,  ///< +/- 4g
+  MSA301_RANGE_8_G  = 0x2,  ///< +/- 8g
+  MSA301_RANGE_16_G = 0x3, ///< +/- 16g
+} msa301_range_t;
+
+#define MSA301_CTL_RANGE_SHIFT  (0x0)
+#define MSA301_CTL_RANGE_MASK   (0x3<<0)
+
+/** The accelerometer data rate */
+typedef enum {
+  MSA301_RATE_1_HZ = 0,     ///<  1 Hz
+  MSA301_RATE_1_95_HZ = 1,  ///<  1.95 Hz
+  MSA301_RATE_3_9_HZ = 2,   ///<  3.9 Hz
+  MSA301_RATE_7_81_HZ = 3,  ///<  7.81 Hz
+  MSA301_RATE_15_63_HZ = 4, ///<  15.63 Hz
+  MSA301_RATE_31_25_HZ = 5, ///<  31.25 Hz
+  MSA301_RATE_62_5_HZ = 6,  ///<  62.5 Hz
+  MSA301_RATE_125_HZ = 7,   ///<  125 Hz
+  MSA301_RATE_250_HZ = 8,   ///<  250 Hz
+  MSA301_RATE_500_HZ = 9,   ///<  500 Hz
+  MSA301_RATE_1000_HZ = 10,  ///<  1000 Hz
+} msa301_rate_t;
+
+#define MSA301_CTL_RATE_SHIFT (0x0)
+#define MSA301_CTL_RATE_MASK  (0xF<<0)
+
+#define MSA301_ENABLE_AXIS    (0x0)
+#define MSA301_DISABLE_AXIS   (0x7)
+#define MSA301_CTL_AXIS_SHIFT (0x05)
+#define MSA301_CTL_AXIS_MASK  (0x7<<5)
+
+/** The accelerometer power mode */

Review comment:
       Ditto

##########
File path: include/nuttx/sensors/msa301.h
##########
@@ -0,0 +1,118 @@
+#ifndef __MSA301_H
+#define __MSA301_H
+
+#include <nuttx/config.h>
+#include <nuttx/sensors/ioctl.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+#define MSA301_ACCEL_ADDR0     0x26
+
+#define SNIOC_MSA301_START                _SNIOC(0x0001)
+#define SNIOC_MSA301_STOP                 _SNIOC(0x0002)
+#define SNIOC_MSA301_SET_RANGE            _SNIOC(0x0003)
+#define SNIOC_MSA301_SET_RATE             _SNIOC(0x0004)
+
+#define MSA301_REG_PARTID 0x01
+#define MSA301_REG_OUT_X_L 0x02
+#define MSA301_REG_OUT_X_H 0x03
+#define MSA301_REG_OUT_Y_L 0x04
+#define MSA301_REG_OUT_Y_H 0x05
+#define MSA301_REG_OUT_Z_L 0x06
+#define MSA301_REG_OUT_Z_H 0x07
+#define MSA301_REG_MOTIONINT 0x09
+#define MSA301_REG_DATAINT 0x0A
+#define MSA301_REG_CLICKSTATUS 0x0B
+#define MSA301_REG_RESRANGE 0x0F
+#define MSA301_REG_ODR 0x10
+#define MSA301_REG_POWERMODE 0x11
+#define MSA301_REG_INTSET0 0x16
+#define MSA301_REG_INTSET1 0x17
+#define MSA301_REG_INTMAP0 0x19
+#define MSA301_REG_INTMAP1 0x1A
+#define MSA301_REG_TAPDUR 0x2A
+#define MSA301_REG_TAPTH 0x2B
+
+/** The accelerometer ranges */

Review comment:
       Ditto

##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */
+  msa301_set_axis(priv, 1);
+
+  up_mdelay(5);
+
+  sninfo("Starting....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_stop
+ *
+ * Description:
+ *   Stop the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */

Review comment:
       Ditto

##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */
+  msa301_set_axis(priv, 1);
+
+  up_mdelay(5);
+
+  sninfo("Starting....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_stop
+ *
+ * Description:
+ *   Stop the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  /* Disable the accelerometer */
+  msa301_set_axis(priv, 0);
+
+  // Power suspend
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  sninfo("Stoping....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_read
+ *
+ * Description:
+ *   Read the sensor.
+ *   A sensor in a steady state on a horizontal surface will
+ *   measure 0 g on both the X-axis and Y-axis, whereas the Z-axis will
+ *   measure 1 g. The X- and Y-axis have an offset
+ *   of 40 mg/LSB
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv)
+{
+  DEBUGASSERT(priv != NULL);
+
+  uint8_t xyz_value[6] = { 0 };
+  if (msa301_readreg(priv, MSA301_REG_OUT_X_L, xyz_value, 6) < 0)
+    {
+      return -EIO;
+    }
+
+  priv->sensor_data.x_data = xyz_value[1] << 8 | xyz_value[0];
+  priv->sensor_data.y_data = xyz_value[3] << 8 | xyz_value[2];
+  priv->sensor_data.z_data = xyz_value[5] << 8 | xyz_value[4];
+
+  /* 14 bit resolution */

Review comment:
       Ditto

##########
File path: drivers/sensors/msa301.c
##########
@@ -0,0 +1,735 @@
+/****************************************************************************
+ * drivers/sensors/msa301.c
+ *   Author:  <[email protected]>
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ *    used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <nuttx/kmalloc.h>
+#include <nuttx/signal.h>
+#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/sensors/msa301.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+struct msa301_dev_s
+{
+  FAR struct i2c_master_s *      i2c;  /* I2C interface */
+  uint8_t                        addr; /* I2C address */
+  msa301_range_t                 range;
+  FAR const struct msa301_ops_s *ops;
+  sem_t                          exclsem;
+  struct msa301_sensor_data_s    sensor_data; /* Sensor data container     */
+};
+
+struct msa301_ops_s
+{
+  CODE int (*config)(FAR struct msa301_dev_s *priv);
+  CODE int (*start)(FAR struct msa301_dev_s *priv);
+  CODE int (*stop)(FAR struct msa301_dev_s *priv);
+  CODE int (*sensor_read)(FAR struct msa301_dev_s *priv);
+};
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#  ifndef CONFIG_MSA301_I2C_FREQUENCY
+#    define CONFIG_MSA301_I2C_FREQUENCY 400000
+#  endif
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* I2C Helpers */
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval);
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval);
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len);
+
+/* Accelerometer Operations */
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv);
+static int msa301_sensor_read(FAR struct msa301_dev_s *priv);
+
+/* Character Driver Methods */
+
+static int     msa301_open(FAR struct file *filep);
+static int     msa301_close(FAR struct file *filep);
+static ssize_t msa301_read(FAR struct file *filep,
+                           FAR char *buffer, size_t buflen);
+static ssize_t msa301_write(FAR struct file *filep,
+                            FAR const char *buffer, size_t buflen);
+static int     msa301_ioctl(FAR struct file *filep, int cmd,
+                            unsigned long arg);
+
+/* Common Register Function */
+
+static int msa301_register(FAR const char *               devpath,
+                           FAR struct i2c_master_s *      i2c,
+                           uint8_t                        addr,
+                           FAR const struct msa301_ops_s *ops);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct file_operations g_fops = {
+  msa301_open,
+  msa301_close,
+  msa301_read,
+  msa301_write,
+  NULL,
+  msa301_ioctl,
+  NULL
+#  ifndef CONFIG_DISABLE_PSEUDOFS_OPERATIONS
+  ,
+  NULL
+#  endif
+};
+
+static const struct msa301_ops_s g_msa301_sensor_ops = {
+  msa301_sensor_config,
+  msa301_sensor_start,
+  msa301_sensor_stop,
+  msa301_sensor_read,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static int msa301_readreg(FAR struct msa301_dev_s *priv,
+                          uint8_t regaddr, FAR uint8_t *regval, uint8_t len)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, len);
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  return OK;
+}
+/****************************************************************************
+ * Name: msa301_readreg8
+ *
+ * Description:
+ *   Read from an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_readreg8(FAR struct msa301_dev_s *priv,
+                           uint8_t regaddr, FAR uint8_t *regval)
+{
+  struct i2c_config_s config;
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+  DEBUGASSERT(regval != NULL);
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address */
+
+  ret = i2c_write(priv->i2c, &config, &regaddr, sizeof(regaddr));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  /* Restart and read 8 bits from the register */
+
+  ret = i2c_read(priv->i2c, &config, regval, sizeof(*regval));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_read failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, *regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_writereg8
+ *
+ * Description:
+ *   Write to an 8-bit register.
+ *
+ ****************************************************************************/
+
+static int msa301_writereg8(FAR struct msa301_dev_s *priv,
+                            uint8_t regaddr, uint8_t regval)
+{
+  struct i2c_config_s config;
+  uint8_t             buffer[2];
+  int                 ret;
+
+  /* Sanity check */
+
+  DEBUGASSERT(priv != NULL);
+
+  /* Set up a 2-byte message to send */
+
+  buffer[0] = regaddr;
+  buffer[1] = regval;
+
+  /* Set up the I2C configuration */
+
+  config.frequency = CONFIG_MSA301_I2C_FREQUENCY;
+  config.address   = priv->addr;
+  config.addrlen   = 7;
+
+  /* Write the register address followed by the data (no RESTART) */
+
+  ret = i2c_write(priv->i2c, &config, buffer, sizeof(buffer));
+  if (ret < 0)
+    {
+      snerr("ERROR: i2c_write failed: %d\n", ret);
+      return ret;
+    }
+
+  sninfo("addr: %02x value: %02x\n", regaddr, regval);
+
+  return OK;
+}
+
+static int msa301_set_range(FAR struct msa301_dev_s *priv, msa301_range_t 
range)
+{
+  uint8_t ctl;
+
+  if (range > MSA301_RANGE_16_G)
+    {
+      return -1;
+    }
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RANGE_MASK);
+  ctl |= (range << MSA301_CTL_RANGE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  priv->range = range;
+
+  return OK;
+}
+
+static int msa301_set_rate(FAR struct msa301_dev_s *priv, msa301_rate_t rate)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_RATE_MASK);
+  ctl |= (rate << MSA301_CTL_RATE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_set_powermode(FAR struct msa301_dev_s *priv, 
msa301_powermode_t mode)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_POWERMODE, &ctl);
+  ctl &= ~(MSA301_CTL_POWERMODE_MASK);
+  ctl |= (mode << MSA301_CTL_POWERMODE_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_POWERMODE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_resolution(FAR struct msa301_dev_s *priv, 
msa301_resolution_t resolution)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_RESRANGE, &ctl);
+  ctl &= ~(MSA301_CTL_RESOLUTION_MASK);
+  ctl |= (resolution << MSA301_CTL_RESOLUTION_SHIFT);
+  msa301_writereg8(priv, MSA301_REG_RESRANGE, ctl);
+
+  return OK;
+}
+
+static int msa301_set_axis(FAR struct msa301_dev_s *priv, uint8_t enable)
+{
+  uint8_t ctl;
+
+  msa301_readreg8(priv, MSA301_REG_ODR, &ctl);
+  ctl &= ~(MSA301_CTL_AXIS_MASK);
+  if (enable)
+    {
+      ctl |= (MSA301_ENABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+  else
+    {
+      ctl |= (MSA301_DISABLE_AXIS << MSA301_CTL_AXIS_SHIFT);
+    }
+
+  msa301_writereg8(priv, MSA301_REG_ODR, ctl);
+
+  return OK;
+}
+
+static int msa301_sensor_config(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  msa301_set_resolution(priv, MSA301_RESOLUTION_14);
+  msa301_set_rate(priv, MSA301_RATE_500_HZ);
+  msa301_set_range(priv, MSA301_RANGE_4_G);
+  msa301_set_powermode(priv, MSA301_SUSPENDMODE);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_start
+ *
+ * Description:
+ *   Start the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_start(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  // Power normal
+  msa301_set_powermode(priv, MSA301_NORMALMODE);
+
+  /* Enable the accelerometer */
+  msa301_set_axis(priv, 1);
+
+  up_mdelay(5);
+
+  sninfo("Starting....");
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: msa301_sensor_stop
+ *
+ * Description:
+ *   Stop the accelerometer.
+ *
+ ****************************************************************************/
+
+static int msa301_sensor_stop(FAR struct msa301_dev_s *priv)
+{
+  /* Sanity check */
+  DEBUGASSERT(priv != NULL);
+
+  /* Disable the accelerometer */
+  msa301_set_axis(priv, 0);
+
+  // Power suspend

Review comment:
       Don't use C++ comment //

##########
File path: include/nuttx/sensors/msa301.h
##########
@@ -0,0 +1,118 @@
+#ifndef __MSA301_H
+#define __MSA301_H
+
+#include <nuttx/config.h>
+#include <nuttx/sensors/ioctl.h>
+
+#if defined(CONFIG_I2C) && defined(CONFIG_SENSORS_MSA301)
+
+#define MSA301_ACCEL_ADDR0     0x26
+
+#define SNIOC_MSA301_START                _SNIOC(0x0001)
+#define SNIOC_MSA301_STOP                 _SNIOC(0x0002)
+#define SNIOC_MSA301_SET_RANGE            _SNIOC(0x0003)
+#define SNIOC_MSA301_SET_RATE             _SNIOC(0x0004)
+
+#define MSA301_REG_PARTID 0x01
+#define MSA301_REG_OUT_X_L 0x02
+#define MSA301_REG_OUT_X_H 0x03
+#define MSA301_REG_OUT_Y_L 0x04
+#define MSA301_REG_OUT_Y_H 0x05
+#define MSA301_REG_OUT_Z_L 0x06
+#define MSA301_REG_OUT_Z_H 0x07
+#define MSA301_REG_MOTIONINT 0x09
+#define MSA301_REG_DATAINT 0x0A
+#define MSA301_REG_CLICKSTATUS 0x0B
+#define MSA301_REG_RESRANGE 0x0F
+#define MSA301_REG_ODR 0x10
+#define MSA301_REG_POWERMODE 0x11
+#define MSA301_REG_INTSET0 0x16
+#define MSA301_REG_INTSET1 0x17
+#define MSA301_REG_INTMAP0 0x19
+#define MSA301_REG_INTMAP1 0x1A
+#define MSA301_REG_TAPDUR 0x2A
+#define MSA301_REG_TAPTH 0x2B
+
+/** The accelerometer ranges */
+typedef enum {
+  MSA301_RANGE_2_G  = 0x0,  ///< +/- 2g
+  MSA301_RANGE_4_G  = 0x1,  ///< +/- 4g
+  MSA301_RANGE_8_G  = 0x2,  ///< +/- 8g
+  MSA301_RANGE_16_G = 0x3, ///< +/- 16g
+} msa301_range_t;
+
+#define MSA301_CTL_RANGE_SHIFT  (0x0)
+#define MSA301_CTL_RANGE_MASK   (0x3<<0)
+
+/** The accelerometer data rate */
+typedef enum {
+  MSA301_RATE_1_HZ = 0,     ///<  1 Hz
+  MSA301_RATE_1_95_HZ = 1,  ///<  1.95 Hz
+  MSA301_RATE_3_9_HZ = 2,   ///<  3.9 Hz
+  MSA301_RATE_7_81_HZ = 3,  ///<  7.81 Hz
+  MSA301_RATE_15_63_HZ = 4, ///<  15.63 Hz
+  MSA301_RATE_31_25_HZ = 5, ///<  31.25 Hz
+  MSA301_RATE_62_5_HZ = 6,  ///<  62.5 Hz
+  MSA301_RATE_125_HZ = 7,   ///<  125 Hz
+  MSA301_RATE_250_HZ = 8,   ///<  250 Hz
+  MSA301_RATE_500_HZ = 9,   ///<  500 Hz
+  MSA301_RATE_1000_HZ = 10,  ///<  1000 Hz
+} msa301_rate_t;
+
+#define MSA301_CTL_RATE_SHIFT (0x0)
+#define MSA301_CTL_RATE_MASK  (0xF<<0)
+
+#define MSA301_ENABLE_AXIS    (0x0)
+#define MSA301_DISABLE_AXIS   (0x7)
+#define MSA301_CTL_AXIS_SHIFT (0x05)
+#define MSA301_CTL_AXIS_MASK  (0x7<<5)
+
+/** The accelerometer power mode */
+typedef enum {
+  MSA301_NORMALMODE = 0x00,   ///< Normal (high speed) mode
+  MSA301_LOWPOWERMODE = 0x01, ///< Low power (slow speed) mode
+  MSA301_SUSPENDMODE = 0x10, ///< Suspend (sleep) mode
+} msa301_powermode_t;
+
+#define MSA301_CTL_POWERMODE_SHIFT  (0x6)
+#define MSA301_CTL_POWERMODE_MASK   (0x3<<6)
+
+/** The accelerometer read resolution */

Review comment:
       Ditto




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to