You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2020/11/15 13:59:09 UTC

[incubator-nuttx] branch master updated: Support for MAX1161X family of I2C 12 bit ADC chips: MAX11612: 4 channels VCC=5V0 Int VRef=4.096V MAX11613: 4 channels VCC=3V3 Int VRef=2.048V MAX11614: 8 channels VCC=5V0 Int VRef=4.096V MAX11615: 8 channels VCC=3V3 Int VRef=2.048V MAX11616: 12 channels VCC=5V0 Int VRef=4.096V MAX11617: 12 channels VCC=3V3 Int VRef=2.048V Note: The chips' auto-scanning feature is not supported in this revision.

This is an automated email from the ASF dual-hosted git repository.

xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new bf5fa55  Support for MAX1161X family of I2C 12 bit ADC chips: MAX11612:  4 channels VCC=5V0 Int VRef=4.096V MAX11613:  4 channels VCC=3V3 Int VRef=2.048V MAX11614:  8 channels VCC=5V0 Int VRef=4.096V MAX11615:  8 channels VCC=3V3 Int VRef=2.048V MAX11616: 12 channels VCC=5V0 Int VRef=4.096V MAX11617: 12 channels VCC=3V3 Int VRef=2.048V Note: The chips' auto-scanning feature is not supported in this revision.
bf5fa55 is described below

commit bf5fa5557dadc97e3aed5b14dc83db8787588cee
Author: Frank-Christian Kruegel <fc...@istda.com>
AuthorDate: Fri Nov 6 11:01:03 2020 +0100

    Support for MAX1161X family of I2C 12 bit ADC chips:
    MAX11612:  4 channels VCC=5V0 Int VRef=4.096V
    MAX11613:  4 channels VCC=3V3 Int VRef=2.048V
    MAX11614:  8 channels VCC=5V0 Int VRef=4.096V
    MAX11615:  8 channels VCC=3V3 Int VRef=2.048V
    MAX11616: 12 channels VCC=5V0 Int VRef=4.096V
    MAX11617: 12 channels VCC=3V3 Int VRef=2.048V
    Note: The chips' auto-scanning feature is not supported in this revision.
---
 drivers/analog/Kconfig          |  31 +++
 drivers/analog/Make.defs        |   4 +
 drivers/analog/max1161x.c       | 596 ++++++++++++++++++++++++++++++++++++++++
 include/nuttx/analog/adc.h      |  16 ++
 include/nuttx/analog/ioctl.h    |  10 +-
 include/nuttx/analog/max1161x.h | 122 ++++++++
 6 files changed, 776 insertions(+), 3 deletions(-)

diff --git a/drivers/analog/Kconfig b/drivers/analog/Kconfig
index 8fe91d7..c33dd53 100644
--- a/drivers/analog/Kconfig
+++ b/drivers/analog/Kconfig
@@ -157,6 +157,37 @@ config ADS7828_FREQUENCY
 
 endif # ADC_ADS7828
 
+config ADC_MAX1161X
+	bool "Maxim MAX11612-11617 support"
+	default n
+	select I2C
+	---help---
+		Enable driver support for the MAX1161X 12-Bit I2C powered ADC Family.
+
+		This driver supports reading single or multiple ADC conversion result
+		as well as onfiguring the ADC, via ioctl calls.
+
+if ADC_MAX1161X
+
+config MAX1161X_FREQUENCY
+	int "Maxim MAX1161X I2C frequency"
+	default 100000
+	---help---
+		MAX1161X supports standard, fast, and high-speed I2C modes.
+
+choice
+	prompt "Maxim MAX1161X Chip Type"
+
+	config MAX1161X_4CHAN
+		bool "MAX11612/MAX11613 4 Channels"
+	config MAX1161X_8CHAN
+		bool "MAX11614/MAX11615 8 Channels"
+	config MAX1161X_12CHAN
+		bool "MAX11616/MAX11617 12 Channels"
+endchoice
+
+endif # ADC_MAX1161X
+
 endif # ADC
 
 config COMP
diff --git a/drivers/analog/Make.defs b/drivers/analog/Make.defs
index a47f1c4..c5f4fab 100644
--- a/drivers/analog/Make.defs
+++ b/drivers/analog/Make.defs
@@ -107,6 +107,10 @@ ifeq ($(CONFIG_ADC_ADS7828),y)
   CSRCS += ads7828.c
 endif
 
+ifeq ($(CONFIG_ADC_MAX1161X),y)
+  CSRCS += max1161x.c
+endif
+
 ifeq ($(CONFIG_ADC_LTC1867L),y)
   CSRCS += ltc1867l.c
 endif
diff --git a/drivers/analog/max1161x.c b/drivers/analog/max1161x.c
new file mode 100644
index 0000000..1b96c87
--- /dev/null
+++ b/drivers/analog/max1161x.c
@@ -0,0 +1,596 @@
+/****************************************************************************
+ * drivers/analog/max1161x.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * This driver is for a whole family of I2C ADC chips:
+ * +--------------+-----+----+--------+---------+
+ * | Type         | VCC | In | Pkg    | I2C Addr|
+ * +--------------+-----+----+--------+---------+
+ * | MAX11612EUA+ | 5V0 |  4 | 8μMAX  | 0110100 |
+ * | MAX11613EUA+ | 3V3 |  4 | 8μMAX  | 0110100 |
+ * | MAX11613EWC+ | 3V3 |  4 | 12WLP  | 0110100 |
+ * | MAX11614EEE+ | 5V0 |  8 | 16QSOP | 0110011 |
+ * | MAX11615EEE+ | 3V3 |  8 | 16QSOP | 0110011 |
+ * | MAX11615EWE+ | 3V3 |  8 | 16WLP  | 0110011 |
+ * | MAX11616EEE+ | 5V0 | 12 | 16QSOP | 0110101 |
+ * | MAX11617EEE+ | 3V3 | 12 | 16QSOP | 0110101 |
+ * | MAX11617EWE+ | 3V3 | 12 | 16WLP  | 0110101 |
+ * +--------------+-----+----+--------+---------+
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <assert.h>
+#include <debug.h>
+#include <endian.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/i2c/i2c_master.h>
+#include <nuttx/analog/adc.h>
+#include <nuttx/analog/ioctl.h>
+#include <nuttx/analog/max1161x.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#if defined(CONFIG_ADC_MAX1161X)
+
+#if defined(CONFIG_MAX1161X_4CHAN)
+#define MAX1161X_NUM_CHANNELS 4
+#define MAX1161X_CHANNELSTROBED 0x000f
+#define MAX1161X_I2C_ADDR 0x34u
+#elif defined(CONFIG_MAX1161X_8CHAN)
+#define MAX1161X_NUM_CHANNELS 8
+#define MAX1161X_CHANNELSTROBED 0x00ff
+#define MAX1161X_I2C_ADDR 0x33u
+#elif defined(CONFIG_MAX1161X_12CHAN)
+#define MAX1161X_NUM_CHANNELS 12
+#define MAX1161X_CHANNELSTROBED 0x0fff
+#define MAX1161X_I2C_ADDR 0x35u
+#else
+#error "MAX1161X Chip Type not defined"
+#endif
+
+#define MAX1161X_SETUP_MARKER           (1 << 7)
+#define MAX1161X_SETUP_REF_SHIFT        4
+#define MAX1161X_SETUP_REF_MASK         (7 << MAX1161X_SETUP_REF_SHIFT)
+#define MAX1161X_SETUP_CLK              (1 << 3)
+#define MAX1161X_SETUP_UNIBIP           (1 << 2)
+#define MAX1161X_SETUP_RESET            (1 << 1)
+
+#define MAX1161X_CMD_MARKER             (0 << 7)
+#define MAX1161X_CMD_SCAN_SHIFT         5
+#define MAX1161X_CMD_SCAN_MASK          (3 << MAX1161X_CMD_SCAN_SHIFT)
+#define MAX1161X_CMD_CHANNEL_SHIFT      1
+#define MAX1161X_CMD_CHANNEL_MASK       (15 << MAX1161X_CMD_CHANNEL_SHIFT)
+#define MAX1161X_CMD_SNGDIF             (1 << 0)
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct max1161x_dev_s
+{
+  FAR struct i2c_master_s           *i2c;
+  FAR const struct adc_callback_s   *cb;
+  uint8_t                           addr;
+
+  /* List of channels to read on every convert trigger.
+   * Bit position corresponds to channel. i.e. bit0 = 1 to read channel 0.
+   */
+
+  uint16_t                          chanstrobed;
+
+  /* Current configuration of the ADC. There are two bytes holding
+   * the complete configuration - the Setup Byte has Bit 7 always set,
+   * while the command byte has bit 7 alway reset
+   */
+
+  uint8_t                           setupbyte;
+  uint8_t                           cmdbyte;
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* max1161x helpers */
+
+static int max1161x_readchannel(FAR struct max1161x_dev_s *priv,
+                               FAR struct adc_msg_s *msg);
+
+/* ADC methods */
+
+static int  max1161x_bind(FAR struct adc_dev_s *dev,
+                     FAR const struct adc_callback_s *callback);
+static void max1161x_reset(FAR struct adc_dev_s *dev);
+static int  max1161x_setup(FAR struct adc_dev_s *dev);
+static void max1161x_shutdown(FAR struct adc_dev_s *dev);
+static void max1161x_rxint(FAR struct adc_dev_s *dev, bool enable);
+static int  max1161x_ioctl(FAR struct adc_dev_s *dev, int cmd,
+                          unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static const struct adc_ops_s g_adcops =
+{
+  .ao_bind     = max1161x_bind,      /* ao_bind */
+  .ao_reset    = max1161x_reset,     /* ao_reset */
+  .ao_setup    = max1161x_setup,     /* ao_setup */
+  .ao_shutdown = max1161x_shutdown,  /* ao_shutdown */
+  .ao_rxint    = max1161x_rxint,     /* ao_rxint */
+  .ao_ioctl    = max1161x_ioctl      /* ao_read */
+};
+
+static struct max1161x_dev_s g_adcpriv;
+
+static struct adc_dev_s g_adcdev =
+{
+  .ad_ops  = &g_adcops,
+  .ad_priv = &g_adcpriv,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: max1161x_manage_strobe
+ *
+ * Description:
+ *   Controls which channels are read on ANIOC_TRIGGER. By default all
+ *   channels are read.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ ****************************************************************************/
+
+static int max1161x_manage_strobe(FAR struct max1161x_dev_s *priv,
+                                 uint8_t channel, bool add_nremove)
+{
+  int ret = OK;
+
+  if (priv == NULL || channel >= MAX1161X_NUM_CHANNELS)
+    {
+      ret = -EINVAL;
+    }
+  else
+    {
+      uint16_t flag = 1U << channel;
+
+      if (add_nremove)
+        {
+          priv->chanstrobed |= flag;
+        }
+       else
+        {
+          priv->chanstrobed &= ~flag;
+        }
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: max1161x_readchannel
+ *
+ * Description:
+ *   Reads a conversion from the ADC.
+ *
+ * Input Parameters:
+ *   msg - msg->am_channel should be set to the channel to be read.
+ *         msg->am_data will store the result of the read.
+ *
+ * Returned Value:
+ *   0 on success. Negated errno on failure.
+ *
+ * Assumptions/Limitations:
+ *   NOTE: When used in single-ended mode, msg->am_channel will be converted
+ *         to the corresponding channel selection bits in the command byte.
+ *         In differential mode, msg->am_channel is used as the channel
+ *         selection bits. The corresponding "channels" are as follows:
+ *
+ *         msg->am_channel  Analog Source
+ *         0                +CH0, -CH1
+ *         1                +CH1, -CH0
+ *         2                +CH2, -CH3
+ *         3                +CH3, -CH2
+ *         4                +CH4, -CH5
+ *         5                +CH5, -CH4
+ *         6                +CH6, -CH7
+ *         7                +CH7, -CH6
+ *
+ ****************************************************************************/
+
+static int max1161x_readchannel(FAR struct max1161x_dev_s *priv,
+                               FAR struct adc_msg_s *msg)
+{
+  int ret = OK;
+  if (priv == NULL || msg == NULL)
+    {
+      ret = -EINVAL;
+    }
+  else
+    {
+      struct i2c_msg_s i2cmsg[3];
+      uint8_t channel = msg->am_channel & ~(MAX1161X_CMD_CHANNEL_MASK);
+
+      uint8_t setupbyte = priv->setupbyte;
+      uint8_t cmdbyte = priv->cmdbyte & ~(MAX1161X_CMD_CHANNEL_MASK);
+      cmdbyte |= channel << MAX1161X_CMD_CHANNEL_SHIFT;
+
+      i2cmsg[0].frequency = CONFIG_MAX1161X_FREQUENCY;
+      i2cmsg[0].addr = priv->addr;
+      i2cmsg[0].flags = I2C_M_NOSTOP;
+      i2cmsg[0].buffer = &setupbyte;
+      i2cmsg[0].length = sizeof(setupbyte);
+
+      i2cmsg[1].frequency = CONFIG_MAX1161X_FREQUENCY;
+      i2cmsg[1].addr = priv->addr;
+      i2cmsg[1].flags = I2C_M_NOSTOP;
+      i2cmsg[1].buffer = &cmdbyte;
+      i2cmsg[1].length = sizeof(cmdbyte);
+
+      i2cmsg[2].frequency = CONFIG_MAX1161X_FREQUENCY;
+      i2cmsg[2].addr = priv->addr;
+      i2cmsg[2].flags = I2C_M_READ;
+
+      uint16_t buf;
+      i2cmsg[2].buffer = (uint8_t *)(&buf);
+      i2cmsg[2].length = sizeof(buf);
+      ret = I2C_TRANSFER(priv->i2c, i2cmsg, 3);
+      if (ret < 0)
+        {
+            aerr("MAX1161X I2C transfer failed: %d", ret);
+        }
+
+      msg->am_data = be16toh(buf) & 0x0fffu;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: max1161x_bind
+ *
+ * Description:
+ *   Bind the upper-half driver callbacks to the lower-half implementation.
+ *   This must be called early in order to receive ADC event notifications.
+ *
+ ****************************************************************************/
+
+static int max1161x_bind(FAR struct adc_dev_s *dev,
+                        FAR const struct adc_callback_s *callback)
+{
+  FAR struct max1161x_dev_s *priv =
+                        (FAR struct max1161x_dev_s *)dev->ad_priv;
+
+  DEBUGASSERT(priv != NULL);
+  priv->cb = callback;
+  return OK;
+}
+
+/****************************************************************************
+ * Name: max1161x_reset
+ *
+ * Description:
+ *   Reset the ADC device.  Called early to initialize the hardware. This
+ *   is called, before ao_setup() and on error conditions.
+ *
+ ****************************************************************************/
+
+static void max1161x_reset(FAR struct adc_dev_s *dev)
+{
+  FAR struct max1161x_dev_s *priv =
+                              (FAR struct max1161x_dev_s *)dev->ad_priv;
+
+  priv->setupbyte   = MAX1161X_SETUP_MARKER;
+  priv->cmdbyte     = MAX1161X_CMD_MARKER;
+  priv->chanstrobed = MAX1161X_CHANNELSTROBED;
+
+#ifndef MAX1161X_ENABLE_SCAN
+  priv->cmdbyte &= ~(MAX1161X_CMD_SCAN_MASK);
+  priv->cmdbyte |= (MAX1161X_SCAN_NONE << MAX1161X_CMD_SCAN_SHIFT);
+#endif
+}
+
+/****************************************************************************
+ * Name: max1161x_setup
+ *
+ * Description:
+ *   Configure the ADC. This method is called the first time that the ADC
+ *   device is opened.  The MAX1161X is quite simple and nothing special is
+ *   needed to be done.
+ *
+ ****************************************************************************/
+
+static int max1161x_setup(FAR struct adc_dev_s *dev)
+{
+  return OK;
+}
+
+/****************************************************************************
+ * Name: max1161x_shutdown
+ *
+ * Description:
+ *   Disable the ADC.  This method is called when the ADC device is closed.
+ *   This method should reverse the operation of the setup method, but as
+ *   the MAX1161X is quite simple does not need to do anything.
+ *
+ ****************************************************************************/
+
+static void max1161x_shutdown(FAR struct adc_dev_s *dev)
+{
+}
+
+/****************************************************************************
+ * Name: max1161x_rxint
+ *
+ * Description:
+ *   Needed for ADC upper-half compatibility but conversion interrupts
+ *   are not supported by the MAX1161X.
+ *
+ ****************************************************************************/
+
+static void max1161x_rxint(FAR struct adc_dev_s *dev, bool enable)
+{
+}
+
+/****************************************************************************
+ * Name: max1161x_ioctl
+ *
+ * Description:
+ *   All ioctl calls will be routed through this method
+ *
+ ****************************************************************************/
+
+static int max1161x_ioctl(FAR struct adc_dev_s *dev, int cmd,
+                         unsigned long arg)
+{
+  FAR struct max1161x_dev_s *priv =
+                              (FAR struct max1161x_dev_s *)dev->ad_priv;
+  int ret = OK;
+
+  switch (cmd)
+    {
+      case ANIOC_TRIGGER:
+        {
+          struct adc_msg_s msg;
+          int i;
+
+          for (i = 0; (i < MAX1161X_NUM_CHANNELS) && (ret == OK); i++)
+            {
+              if ((priv->chanstrobed >> i) & 1u)
+                {
+                  msg.am_channel = i;
+                  ret = max1161x_readchannel(priv, &msg);
+                  if (ret == OK)
+                    {
+                      priv->cb->au_receive(&g_adcdev, i, msg.am_data);
+                    }
+                }
+            }
+        }
+        break;
+
+      /* Add a channel to list of channels read on ANIOC_TRIGGER */
+
+      case ANIOC_MAX1161X_ADD_CHAN:
+        {
+          ret = max1161x_manage_strobe(priv, (uint8_t)arg, true);
+        }
+        break;
+
+      /* Remove a channel from list of channels read on ANIOC_TRIGGER */
+
+      case ANIOC_MAX1161X_REMOVE_CHAN:
+        {
+          ret = max1161x_manage_strobe(priv, (uint8_t)arg, false);
+        }
+        break;
+
+      /* Read a single channel from the ADC */
+
+      case ANIOC_MAX1161X_READ_CHANNEL:
+        {
+          FAR struct adc_msg_s *msg = (FAR struct adc_msg_s *)arg;
+          ret = max1161x_readchannel(priv, msg);
+        }
+        break;
+
+      /* Set the ADC reference source and pin function */
+
+      case ANIOC_MAX1161X_SET_REF:
+        {
+          switch (arg)
+          {
+            case MAX1161X_REF_VDD_AIN_NC_OFF:
+            case MAX1161X_REF_EXT_RIN_IN_OFF:
+            case MAX1161X_REF_INT_AIN_NC_OFF:
+            case MAX1161X_REF_INT_AIN_NC_ON:
+            case MAX1161X_REF_INT_ROUT_OUT_OFF:
+            case MAX1161X_REF_INT_ROUT_OUT_ON:
+              {
+              priv->setupbyte &= ~(MAX1161X_SETUP_REF_MASK);
+              priv->setupbyte |= (arg << MAX1161X_SETUP_REF_SHIFT);
+              }
+              break;
+
+            default:
+              {
+                ret = -EINVAL;
+              }
+              break;
+          }
+        }
+        break;
+
+      /* Set clock source */
+
+      case ANIOC_MAX1161X_SET_CLOCK:
+        {
+          if (arg == MAX1161X_CLOCK_EXT)
+            {
+              priv->setupbyte |= MAX1161X_SETUP_CLK;
+            }
+          else if (arg == MAX1161X_CLOCK_INT)
+            {
+              priv->setupbyte &= ~MAX1161X_SETUP_CLK;
+            }
+          else
+            {
+              ret = -EINVAL;
+            }
+        }
+        break;
+
+      /* Set the ADC Unipolar/Bipolar Mode */
+
+      case ANIOC_MAX1161X_SET_UNIBIP:
+        {
+          if (arg == MAX1161X_BIPOLAR)
+            {
+              priv->setupbyte |= MAX1161X_SETUP_UNIBIP;
+            }
+          else if (arg == MAX1161X_UNIPOLAR)
+            {
+              priv->setupbyte &= ~MAX1161X_SETUP_UNIBIP;
+            }
+          else
+            {
+              ret = -EINVAL;
+            }
+        }
+        break;
+
+      /* Set the ADC Scan Mode */
+
+      case ANIOC_MAX1161X_SET_SCAN:
+        {
+#ifdef MAX1161X_ENABLE_SCAN
+          switch (arg)
+          {
+            case MAX1161X_SCAN_FROM_ZERO :
+            case MAX1161X_SCAN_EIGHT_TIMES:
+            case MAX1161X_SCAN_UPPER:
+            case MAX1161X_SCAN_NONE:
+              {
+              priv->cmdbyte &= ~(MAX1161X_CMD_SCAN_MASK);
+              priv->cmdbyte |= (arg << MAX1161X_CMD_SCAN_SHIFT);
+              }
+              break;
+
+            default:
+              {
+                ret = -EINVAL;
+              }
+              break;
+          }
+#endif
+        }
+        break;
+
+      /* Set the ADC Single Ended/Differential Mode */
+
+      case ANIOC_MAX1161X_SET_SNGDIF:
+        {
+          if (arg == MAX1161X_SINGLE_ENDED)
+            {
+              priv->cmdbyte |= MAX1161X_CMD_SNGDIF;
+            }
+          else if (arg == MAX1161X_DIFFERENTIAL)
+            {
+              priv->cmdbyte &= ~MAX1161X_CMD_SNGDIF;
+            }
+          else
+            {
+              ret = -EINVAL;
+            }
+        }
+        break;
+
+      /* Command was not recognized */
+
+      default:
+        ret = -ENOTTY;
+        aerr("MAX1161X ERROR: Unrecognized cmd: %d\n", cmd);
+        break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: max1161x_initialize
+ *
+ * Description:
+ *   Initialize the selected adc
+ *
+ * Input Parameters:
+ *   i2c - Pointer to a I2C master struct for the bus the ADC resides on.
+ *
+ * Returned Value:
+ *   Valid ADC device structure reference on success; a NULL on failure
+ *
+ ****************************************************************************/
+
+FAR struct adc_dev_s *max1161x_initialize(FAR struct i2c_master_s *i2c)
+{
+  DEBUGASSERT(i2c != NULL);
+
+  /* Driver state data */
+
+  FAR struct max1161x_dev_s *priv;
+  priv = (FAR struct max1161x_dev_s *)g_adcdev.ad_priv;
+
+  priv->cb   = NULL;
+  priv->i2c  = i2c;
+  priv->addr        = MAX1161X_I2C_ADDR;
+  priv->setupbyte   = MAX1161X_SETUP_MARKER;
+  priv->cmdbyte     = MAX1161X_CMD_MARKER;
+  priv->chanstrobed = MAX1161X_CHANNELSTROBED;
+
+#ifndef MAX1161X_ENABLE_SCAN
+  priv->cmdbyte &= ~(MAX1161X_CMD_SCAN_MASK);
+  priv->cmdbyte |= (MAX1161X_SCAN_NONE << MAX1161X_CMD_SCAN_SHIFT);
+#endif
+
+  return &g_adcdev;
+}
+
+#endif
diff --git a/include/nuttx/analog/adc.h b/include/nuttx/analog/adc.h
index 3e3323a..0fb99c1 100644
--- a/include/nuttx/analog/adc.h
+++ b/include/nuttx/analog/adc.h
@@ -298,6 +298,22 @@ FAR struct adc_dev_s *lmp92001_adc_initialize(FAR struct i2c_master_s *i2c,
 FAR struct adc_dev_s *ads7828_initialize(FAR struct i2c_master_s *i2c,
                                                uint8_t addr);
 
+/****************************************************************************
+ * Name: max1161x_initialize
+ *
+ * Description:
+ *   Initialize ADC
+ *
+ * Input Parameters:
+ *   i2c - Pointer to a valid I2C master struct.
+ *
+ * Returned Value:
+ *   Valid MX1161X device structure reference on success; a NULL on failure
+ *
+ ****************************************************************************/
+
+FAR struct adc_dev_s *max1161x_initialize(FAR struct i2c_master_s *i2c);
+
 #if defined(__cplusplus)
 }
 #endif
diff --git a/include/nuttx/analog/ioctl.h b/include/nuttx/analog/ioctl.h
index 2527983..f9d6653 100644
--- a/include/nuttx/analog/ioctl.h
+++ b/include/nuttx/analog/ioctl.h
@@ -82,13 +82,12 @@
 
 /* See include/nuttx/analog/lm92001.h */
 
-#define AN_LMP92001_FIRST (AN_FIRST + AN_NCMDS + AN_ADS2142_NCMDS)
+#define AN_LMP92001_FIRST (AN_ADS2142_FIRST + AN_ADS2142_NCMDS)
 #define AN_LMP92001_NCMDS 7
 
 /* See include/nuttx/analog/ads7828.h */
 
-#define AN_ADS7828_FIRST (AN_FIRST + AN_NCMDS + AN_ADS2142_NCMDS + \
-                          AN_LMP92001_NCMDS)
+#define AN_ADS7828_FIRST (AN_LMP92001_FIRST + AN_LMP92001_NCMDS)
 #define AN_ADS7828_NCMDS 6
 
 /* See arch/arm/src/stm32l4/stm32l4_adc.h */
@@ -96,6 +95,11 @@
 #define AN_STM32L4_FIRST (AN_ADS7828_FIRST + AN_ADS7828_NCMDS)
 #define AN_STM32L4_NCMDS 2
 
+/* See include/nuttx/analog/max1161x.h */
+
+#define AN_MAX1161X_FIRST (AN_STM32L4_FIRST + AN_STM32L4_NCMDS)
+#define AN_MAX1161X_NCMDS 8
+
 /****************************************************************************
  * Public Function Prototypes
  ****************************************************************************/
diff --git a/include/nuttx/analog/max1161x.h b/include/nuttx/analog/max1161x.h
new file mode 100644
index 0000000..64859f4
--- /dev/null
+++ b/include/nuttx/analog/max1161x.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+ * include/nuttx/analog/max1161x.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_ANALOG_MAX1161X_H
+#define __INCLUDE_NUTTX_ANALOG_MAX1161X_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+#include <nuttx/analog/ioctl.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* IOCTL Commands
+ * Cmd: ANIOC_MAX1161X_SET_REF       Arg: enum max1161x_ref_e
+ * Cmd: ANIOC_MAX1161X_SET_CLOCK     Arg: enum max1161x_clock_e
+ * Cmd: ANIOC_MAX1161X_SET_UNIBIP    Arg: enum max1161x_unibip_e
+ * Cmd: ANIOC_MAX1161X_SET_SCAN      Arg: enum max1161x_scan_e
+ * Cmd: ANIOC_MAX1161X_ADD_CHAN      Arg: uint8_t value
+ * Cmd: ANIOC_MAX1161X_REMOVE_CHAN   Arg: uint8_t value
+ * Cmd: ANIOC_MAX1161X_SET_SNGDIF    Arg: enum max1161x_sngdif_e
+ * Cmd: ANIOC_MAX1161X_READ_CHANNEL  Arg: struct adc_msg_s *channel
+ */
+
+#define ANIOC_MAX1161X_SET_REF       _ANIOC(AN_MAX1161X_FIRST + 0)
+#define ANIOC_MAX1161X_SET_CLOCK     _ANIOC(AN_MAX1161X_FIRST + 1)
+#define ANIOC_MAX1161X_SET_UNIBIP    _ANIOC(AN_MAX1161X_FIRST + 2)
+#define ANIOC_MAX1161X_SET_SCAN      _ANIOC(AN_MAX1161X_FIRST + 3)
+#define ANIOC_MAX1161X_ADD_CHAN      _ANIOC(AN_MAX1161X_FIRST + 4)
+#define ANIOC_MAX1161X_REMOVE_CHAN   _ANIOC(AN_MAX1161X_FIRST + 5)
+#define ANIOC_MAX1161X_SET_SNGDIF    _ANIOC(AN_MAX1161X_FIRST + 6)
+#define ANIOC_MAX1161X_READ_CHANNEL  _ANIOC(AN_MAX1161X_FIRST + 7)
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* Setup Byte */
+
+/****************************************************************************
+ * +----+----+----+------+---------+---------+---------------+
+ * |SEL2|SEL1|SEL0| VREF | Ref Pin | Ref Dir | Int Ref State |
+ * +----+----+----+------+---------+---------+---------------+
+ * | 0  | 0  | x  | VDD  |  AIN    |   NC    |     off       |
+ * | 0  | 1  | x  | EXT  |  RIN    |   IN    |     off       |
+ * | 1  | 0  | 0  | INT  |  AIN    |   NC    |     off       |
+ * | 1  | 0  | 1  | INT  |  AIN    |   NC    |     on        |
+ * | 1  | 1  | 0  | INT  |  ROUT   |   OUT   |     off       |
+ * | 1  | 1  | 1  | INT  |  ROUT   |   OUT   |     on        |
+ * +----+----+----+------+---------+---------+---------------+
+ ****************************************************************************/
+
+enum max1161x_ref_e
+{
+  MAX1161X_REF_VDD_AIN_NC_OFF   = 0u,
+  MAX1161X_REF_EXT_RIN_IN_OFF   = 2u,
+  MAX1161X_REF_INT_AIN_NC_OFF   = 4u,
+  MAX1161X_REF_INT_AIN_NC_ON    = 5u,
+  MAX1161X_REF_INT_ROUT_OUT_OFF = 6u,
+  MAX1161X_REF_INT_ROUT_OUT_ON  = 7u,
+};
+
+enum max1161x_clock_e
+{
+  MAX1161X_CLOCK_INT = 0u,
+  MAX1161X_CLOCK_EXT
+};
+
+enum max1161x_unibip_e
+{
+  MAX1161X_UNIPOLAR = 0u,
+  MAX1161X_BIPOLAR
+};
+
+enum max1161x_reset_e
+{
+  MAX1161X_NO_RESET = 0u,
+  MAX1161X_RESET
+};
+
+/* Configuration Byte */
+
+enum max1161x_scan_e
+{
+  MAX1161X_SCAN_FROM_ZERO = 0u,
+  MAX1161X_SCAN_EIGHT_TIMES,
+  MAX1161X_SCAN_UPPER,
+  MAX1161X_SCAN_NONE
+};
+
+enum max1161x_sngdif_e
+{
+  MAX1161X_DIFFERENTIAL = 0u,
+  MAX1161X_SINGLE_ENDED
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+#endif /* __INCLUDE_NUTTX_ANALOG_MAX1161X_H */