/****************************************************************************
 * arch/arm/src/stm32/stm32_comp_v2.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.
 *
 ****************************************************************************/

/****************************************************************************
 * Included Files
 ****************************************************************************/

/****************************************************************************
 * Pre-processor Definitions
 ****************************************************************************/

/* Some COMP peripheral must be enabled and the device must be supported */

#define DEVICE_NOT_SUPPORTED

#if defined(CONFIG_STM32_COMP)

#ifndef CONFIG_STM32_SYSCFG
#  error "SYSCFG clock enable must be set"
#endif

#if defined(CONFIG_STM32_STM32G43XX)
#  undef DEVICE_NOT_SUPPORTED
#  if defined(CONFIG_STM32_COMP5) || defined(CONFIG_STM32_COMP6) || \
      defined(CONFIG_STM32_COMP7)
#    error "STM32G43XX supports only COMP1, COMP2, COMP3 and COMP4"
#  endif
#endif

#if defined(DEVICE_NOT_SUPPORTED)
#  error "Device not supported"
#endif

#if defined(CONFIG_STM32_COMP1_OUT) || defined(CONFIG_STM32_COMP2_OUT) || \
    defined(CONFIG_STM32_COMP3_OUT) || defined(CONFIG_STM32_COMP4_OUT) || \
    defined(CONFIG_STM32_COMP5_OUT) || defined(CONFIG_STM32_COMP6_OUT) || \
    defined(CONFIG_STM32_COMP7_OUT)
#  define COMP_OUT_GPIO
#endif

/****************************************************************************
 * Private Types
 ****************************************************************************/

/* This structure describes the configuration of one COMP device */

struct stm32_comp_s
{
  uint8_t inm;                  /* Inverting input selection */
  uint32_t gpio_inm;            /* Inverting input pin */
  uint8_t inp;                  /* Non inverting input selection */
  uint32_t gpio_inp;            /* Non-inverting input pin */
  uint8_t pol;                  /* Output polarity */
  uint8_t hyst;                 /* Comparator hysteresis */
  uint8_t blanking;             /* Blanking source */
  uint8_t lock;                 /* Comparator Lock */
  uint32_t csr;                 /* Control and status register */
};

/****************************************************************************
 * Private Function Prototypes
 ****************************************************************************/

/* COMP Register access */

static inline void     comp_modify_csr(struct stm32_comp_s *priv,
                                       uint32_t clearbits, uint32_t setbits);
static inline uint32_t comp_getreg_csr(struct stm32_comp_s *priv);
static inline void     comp_putreg_csr(struct stm32_comp_s *priv,
                                       uint32_t value);

/* COMP Driver Methods */

#if defined (CONFIG_COMP)
static void comp_shutdown(struct comp_dev_s *dev);
static int  comp_setup(struct comp_dev_s *dev);
static int  comp_read(struct comp_dev_s *dev);
static int  comp_ioctl(struct comp_dev_s *dev, int cmd,
                       unsigned long arg);
#endif

static int  comp_config(struct stm32_comp_s *priv);
static int  comp_enable(struct stm32_comp_s *priv, bool enable);
static bool comp_lock_get(struct stm32_comp_s *priv);
static int  comp_lock_set(struct stm32_comp_s *priv, bool lock);

static int  comp_config_inmpin(struct stm32_comp_s *priv);
static int  comp_config_inppin(struct stm32_comp_s *priv);
#if defined(COMP_OUT_GPIO)
static int  comp_config_outpin(struct stm32_comp_s *priv);
#endif

/****************************************************************************
 * Private Data
 ****************************************************************************/

#ifdef CONFIG_COMP
static const struct comp_ops_s g_compops =
{
  .ao_shutdown  = comp_shutdown,
  .ao_setup     = comp_setup,
  .ao_read      = comp_read,
  .ao_ioctl     = comp_ioctl,
};
#endif

#ifdef CONFIG_STM32_COMP1
static struct stm32_comp_s g_comp1priv =
{
  .inm       = CONFIG_STM32_COMP1_INM,
  .inp       = CONFIG_STM32_COMP1_INP,
  .pol       = CONFIG_STM32_COMP1_POL,
  .hyst      = CONFIG_STM32_COMP1_HYST,
  .blanking  = CONFIG_STM32_COMP1_BLANKSEL,
  .lock      = CONFIG_STM32_COMP1_LOCK,
  .gpio_inp  = GPIO_COMP1_INP,
  .csr       = STM32_COMP1_CSR
};

static struct comp_dev_s g_comp1dev =
{
#ifdef CONFIG_COMP
  .ad_ops  = &g_compops,
#endif
  .ad_priv = &g_comp1priv,
};
#endif

#ifdef CONFIG_STM32_COMP2
static struct stm32_comp_s g_comp2priv =
{
  .inm       = CONFIG_STM32_COMP2_INM,
  .inp       = CONFIG_STM32_COMP2_INP,
  .pol       = CONFIG_STM32_COMP2_POL,
  .hyst      = CONFIG_STM32_COMP2_HYST,
  .blanking  = CONFIG_STM32_COMP2_BLANKSEL,
  .lock      = CONFIG_STM32_COMP2_LOCK,
  .gpio_inp  = GPIO_COMP2_INP,
  .csr       = STM32_COMP2_CSR
};

static struct comp_dev_s g_comp2dev =
{
#ifdef CONFIG_COMP
  .ad_ops  = &g_compops,
#endif
  .ad_priv = &g_comp2priv,
};
#endif

#ifdef CONFIG_STM32_COMP3
static struct stm32_comp_s g_comp3priv =
{
  .inm       = CONFIG_STM32_COMP3_INM,
  .inp       = CONFIG_STM32_COMP3_INP,
  .pol       = CONFIG_STM32_COMP3_POL,
  .hyst      = CONFIG_STM32_COMP3_HYST,
  .blanking  = CONFIG_STM32_COMP3_BLANKSEL,
  .lock      = CONFIG_STM32_COMP3_LOCK,
  .gpio_inp  = GPIO_COMP3_INP,
  .csr       = STM32_COMP3_CSR
};

static struct comp_dev_s g_comp3dev =
{
#ifdef CONFIG_COMP
  .ad_ops  = &g_compops,
#endif
  .ad_priv = &g_comp3priv,
};
#endif

#ifdef CONFIG_STM32_COMP4
static struct stm32_comp_s g_comp4priv =
{
  .inm       = CONFIG_STM32_COMP4_INM,
  .inp       = CONFIG_STM32_COMP4_INP,
  .pol       = CONFIG_STM32_COMP4_POL,
  .hyst      = CONFIG_STM32_COMP4_HYST,
  .blanking  = CONFIG_STM32_COMP4_BLANKSEL,
  .lock      = CONFIG_STM32_COMP4_LOCK,
  .gpio_inp  = GPIO_COMP4_INP,
  .csr       = STM32_COMP4_CSR
};

static struct comp_dev_s g_comp4dev =
{
#ifdef CONFIG_COMP
  .ad_ops  = &g_compops,
#endif
  .ad_priv = &g_comp4priv,
};
#endif

#ifdef CONFIG_STM32_COMP5
static struct stm32_comp_s g_comp5priv =
{
  .inm       = CONFIG_STM32_COMP5_INM,
  .inp       = CONFIG_STM32_COMP5_INP,
  .pol       = CONFIG_STM32_COMP5_POL,
  .hyst      = CONFIG_STM32_COMP5_HYST,
  .blanking  = CONFIG_STM32_COMP5_BLANKSEL,
  .lock      = CONFIG_STM32_COMP5_LOCK,
  .gpio_inp  = GPIO_COMP5_INP,
  .csr       = STM32_COMP5_CSR
};

static struct comp_dev_s g_comp5dev =
{
#ifdef CONFIG_COMP
  .ad_ops  = &g_compops,
#endif
  .ad_priv = &g_comp5priv,
};
#endif

#ifdef CONFIG_STM32_COMP6
static struct stm32_comp_s g_comp6priv =
{
  .inm       = CONFIG_STM32_COMP6_INM,
  .inp       = CONFIG_STM32_COMP6_INP,
  .pol       = CONFIG_STM32_COMP6_POL,
  .hyst      = CONFIG_STM32_COMP6_HYST,
  .blanking  = CONFIG_STM32_COMP6_BLANKSEL,
  .lock      = CONFIG_STM32_COMP6_LOCK,
  .gpio_inp  = GPIO_COMP6_INP,
  .csr       = STM32_COMP6_CSR
};

static struct comp_dev_s g_comp6dev =
{
#ifdef CONFIG_COMP
  .ad_ops  = &g_compops,
#endif
  .ad_priv = &g_comp6priv,
};
#endif

#ifdef CONFIG_STM32_COMP7
static struct stm32_comp_s g_comp7priv =
{
  .inm       = CONFIG_STM32_COMP7_INM,
  .inp       = CONFIG_STM32_COMP7_INP,
  .pol       = CONFIG_STM32_COMP7_POL,
  .hyst      = CONFIG_STM32_COMP7_HYST,
  .blanking  = CONFIG_STM32_COMP7_BLANKSEL,
  .lock      = CONFIG_STM32_COMP7_LOCK,
  .gpio_inp  = GPIO_COMP7_INP,
  .csr       = STM32_COMP7_CSR
};

static struct comp_dev_s g_comp7dev =
{
#ifdef CONFIG_COMP
  .ad_ops  = &g_compops,
#endif
  .ad_priv = &g_comp7priv,
};
#endif

/****************************************************************************
 * Private Functions
 ****************************************************************************/

/****************************************************************************
 * Name: comp_modify_csr
 *
 * Description:
 *   Modify the value of a 32-bit COMP CSR register (not atomic).
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *   clrbits - The bits to clear
 *   setbits - The bits to set
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void comp_modify_csr(struct stm32_comp_s *priv,
                                   uint32_t clearbits, uint32_t setbits)
{
  uint32_t csr = priv->csr;

  modifyreg32(csr, clearbits, setbits);
}

/****************************************************************************
 * Name: comp_getreg_csr
 *
 * Description:
 *   Read the value of an COMP CSR register
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *
 * Returned Value:
 *   The current contents of the COMP CSR register
 *
 ****************************************************************************/

static inline uint32_t comp_getreg_csr(struct stm32_comp_s *priv)
{
  uint32_t csr = priv->csr;

  return getreg32(csr);
}

/****************************************************************************
 * Name: comp_putreg_csr
 *
 * Description:
 *   Write a value to an COMP register.
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *   value  - The value to write to the COMP CSR register
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

static inline void comp_putreg_csr(struct stm32_comp_s *priv,
                                   uint32_t value)
{
  uint32_t csr = priv->csr;

  putreg32(value, csr);
}

/****************************************************************************
 * Name: comp_lock_get
 *
 * Description:
 *   Get COMP lock bit state
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *
 * Returned Value:
 *   True if COMP locked, false if not locked
 *
 ****************************************************************************/

static bool comp_lock_get(struct stm32_comp_s *priv)
{
  uint32_t regval;

  regval = comp_getreg_csr(priv);

  return (((regval & COMP_CSR_LOCK) == 0) ? false : true);
}

/****************************************************************************
 * Name: comp_lock_set
 *
 * Description:
 *   Lock comparator CSR register
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *   enable - lock flag
 *
 * Returned Value:
 *  0 on success, a negated errno value on failure
 *
 ****************************************************************************/

static int comp_lock_set(struct stm32_comp_s *priv, bool lock)
{
  if (comp_lock_get(priv))
    {
      if (lock == false)
        {
          aerr("ERROR: COMP LOCK can be cleared only by a system reset\n");

          return -EPERM;
        }
    }
  else
    {
      if (lock == true)
        {
          comp_modify_csr(priv, 0, COMP_CSR_LOCK);

          priv->lock = 1;
        }
    }

  return OK;
}

/****************************************************************************
 * Name: comp_config_inmpin
 *
 * Description:
 *   Configure comparator inverting input pin. The GPIO that COMPx inverting
 *   input will be assigned is dependent of comparator number and must be
 *   defined in board.h file. See table 196 in RM0440.
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *
 * Returned Value:
 *  0 on success, a negated errno value on failure
 *
 ****************************************************************************/

static int comp_config_inmpin(struct stm32_comp_s *priv)
{
#  if defined(CONFIG_STM32_COMP1)
  if (priv->csr == STM32_COMP1_CSR)
    {
      stm32_configgpio(GPIO_COMP1_INM);
    }
#  endif

#  if defined(CONFIG_STM32_COMP2)
  if (priv->csr == STM32_COMP2_CSR)
    {
      stm32_configgpio(GPIO_COMP2_INM);
    }
#  endif

#  if defined(CONFIG_STM32_COMP3)
  if (priv->csr == STM32_COMP3_CSR)
    {
      stm32_configgpio(GPIO_COMP3_INM);
    }
#  endif

#  if defined(CONFIG_STM32_COMP4)
  if (priv->csr == STM32_COMP4_CSR)
    {
      stm32_configgpio(GPIO_COMP4_INM);
    }
#  endif

#  if defined(CONFIG_STM32_COMP5)
  if (priv->csr == STM32_COMP5_CSR)
    {
      stm32_configgpio(GPIO_COMP5_INM);
    }
#  endif

#  if defined(CONFIG_STM32_COMP6)
  if (priv->csr == STM32_COMP6_CSR)
    {
      stm32_configgpio(GPIO_COMP6_INM);
    }
#  endif

#  if defined(CONFIG_STM32_COMP7)
  if (priv->csr == STM32_COMP7_CSR)
    {
      stm32_configgpio(GPIO_COMP7_INM);
    }
#  endif

  return OK;
}

/****************************************************************************
 * Name: comp_config_inppin
 *
 * Description:
 *   Configure comparator non-inverting input pin. The IO pin that COMPx
 *   non-inverting input will be assigned is dependent of comparator number
 *   and must be defined in board.h file.
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *
 * Returned Value:
 *  0 on success, a negated errno value on failure
 *
 ****************************************************************************/

static int comp_config_inppin(struct stm32_comp_s *priv)
{
#  if defined(CONFIG_STM32_COMP1)
  if (priv->csr == STM32_COMP1_CSR)
    {
      stm32_configgpio(GPIO_COMP1_INP);
    }
#  endif

#  if defined(CONFIG_STM32_COMP2)
  if (priv->csr == STM32_COMP2_CSR)
    {
      stm32_configgpio(GPIO_COMP2_INP);
    }
#  endif

#  if defined(CONFIG_STM32_COMP3)
  if (priv->csr == STM32_COMP3_CSR)
    {
      stm32_configgpio(GPIO_COMP3_INP);
    }
#  endif

#  if defined(CONFIG_STM32_COMP4)
  if (priv->csr == STM32_COMP4_CSR)
    {
      stm32_configgpio(GPIO_COMP4_INP);
    }
#  endif

#  if defined(CONFIG_STM32_COMP5)
  if (priv->csr == STM32_COMP5_CSR)
    {
      stm32_configgpio(GPIO_COMP5_INP);
    }
#  endif

#  if defined(CONFIG_STM32_COMP6)
  if (priv->csr == STM32_COMP6_CSR)
    {
      stm32_configgpio(GPIO_COMP6_INP);
    }
#  endif

#  if defined(CONFIG_STM32_COMP7)
  if (priv->csr == STM32_COMP7_CSR)
    {
      stm32_configgpio(GPIO_COMP7_INP);
    }
#  endif

  return OK;
}

/****************************************************************************
 * Name: comp_config_outpin
 *
 * Description:
 *   Configure comparator output GPIO pin.
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *
 * Returned Value:
 *  0 on success, a negated errno value on failure
 *
 ****************************************************************************/

#if defined(COMP_OUT_GPIO)
static int comp_config_outpin(struct stm32_comp_s *priv)
{
#  if defined(CONFIG_STM32_COMP1_OUT)
  if (priv->csr == STM32_COMP1_CSR)
    {
      stm32_configgpio(GPIO_COMP1_OUT);
    }
#  endif

#  if defined(CONFIG_STM32_COMP2_OUT)
  if (priv->csr == STM32_COMP2_CSR)
    {
      ainfo("\tOUT assigned to: GPIO\n");
      stm32_configgpio(GPIO_COMP2_OUT);
    }
#  endif

#  if defined(CONFIG_STM32_COMP3_OUT)
  if (priv->csr == STM32_COMP3_CSR)
    {
      stm32_configgpio(GPIO_COMP3_OUT);
    }
#  endif

#  if defined(CONFIG_STM32_COMP4_OUT)
  if (priv->csr == STM32_COMP4_CSR)
    {
      stm32_configgpio(GPIO_COMP4_OUT);
    }
#  endif

#  if defined(CONFIG_STM32_COMP5_OUT)
  if (priv->csr == STM32_COMP5_CSR)
    {
      stm32_configgpio(GPIO_COMP5_OUT);
    }
#  endif

#  if defined(CONFIG_STM32_COMP6_OUT)
  if (priv->csr == STM32_COMP6_CSR)
    {
      stm32_configgpio(GPIO_COMP6_OUT);
    }
#  endif

#  if defined(CONFIG_STM32_COMP7_OUT)
  if (priv->csr == STM32_COMP7_CSR)
    {
      stm32_configgpio(GPIO_COMP7_OUT);
    }
#  endif

  return OK;
}
#endif /* COMP_OUT_GPIO */

/****************************************************************************
 * Name: comp_config
 *
 * Description:
 *   Configure comparator and used I/Os. The pin configuration and the input
 *   assignments are COMP index dependent.
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *
 * Returned Value:
 *  0 on success, a negated errno value on failure
 *
 * REVISIT: Where to config comparator output pin ?
 *
 ****************************************************************************/

static int comp_config(struct stm32_comp_s *priv)
{
  uint32_t regval = 0;
  uint32_t value = 0;

  /* Configure COMPx inverting input. */

  value = priv->inm << COMP_CSR_INMSEL_SHIFT;

  switch (priv->inm)
    {
      case COMP_INM_1_4_VREF:
      case COMP_INM_1_2_VREF:
      case COMP_INM_3_4_VREF:

        value |= COMP_CSR_BRGEN;    /* scaler resistor bridge enable */

      case COMP_INM_VREF:

        value |= COMP_CSR_SCALEN;    /* VREFINT scaler enable */
        break;

      case COMP_INM_DAC_1:
      case COMP_INM_DAC_2:

        break;

      case COMP_INM_PIN_1:
      case COMP_INM_PIN_2:

        comp_config_inmpin(priv);
        break;

      default:
        return -EINVAL;
    }

  regval |= value;

  /* Configure COMPx non-inverting input. */

  ainfo("\tINP assigned to GPIO%d\n", priv->inp);

  value = priv->inp << COMP_CSR_INPSEL_SHIFT;
  regval |= value;

  comp_config_inppin(priv);

  /* Configure COMPx polarity */

  if (priv->pol == COMP_POL_INVERTED)
    {
      value = COMP_CSR_POL;
      regval |= value;
    }

  /* Configure COMPx hysteresis */

  switch (priv->hyst)
    {
      case COMP_HYST_DIS:
      case COMP_HYST_10MV:
      case COMP_HYST_20MV:
      case COMP_HYST_30MV:
      case COMP_HYST_40MV:
      case COMP_HYST_50MV:
      case COMP_HYST_60MV:
      case COMP_HYST_70MV:

        value = priv->hyst << COMP_CSR_HYST_SHIFT;
        regval |= value;
        break;

      default:
        return -EINVAL;
    }

  /* Configure COMPx blanking signal source */

  switch (priv->blanking)
    {
      case COMP_BLANKING_DIS:
      case COMP_BLANKING_TIMX_OCY_1:
      case COMP_BLANKING_TIMX_OCY_2:
      case COMP_BLANKING_TIMX_OCY_3:
      case COMP_BLANKING_TIMX_OCY_4:
      case COMP_BLANKING_TIMX_OCY_5:
      case COMP_BLANKING_TIMX_OCY_6:
      case COMP_BLANKING_TIMX_OCY_7:

        value = priv->blanking << COMP_CSR_BLANKING_SHIFT;
        regval |= value;
        break;

      default:
        return -EINVAL;
    }

  /* Set Comparator output selection */

#if defined(COMP_OUT_GPIO)
  comp_config_outpin(priv);
#endif

  /* Save CSR register */

  comp_putreg_csr(priv, regval);

  /* Enable Comparator */

  comp_enable(priv, true);

  /* Lock Comparator if needed */

  if (priv->lock)
    {
      comp_lock_set(priv, true);
    }

  return OK;
}

/****************************************************************************
 * Name: comp_enable
 *
 * Description:
 *   Enable/disable comparator
 *
 * Input Parameters:
 *   priv   - A reference to the COMP structure
 *   enable - enable/disable flag
 *
 * Returned Value:
 *  0 on success, a negated errno value on failure
 *
 ****************************************************************************/

static int comp_enable(struct stm32_comp_s *priv, bool enable)
{
  bool lock;

  ainfo("enable: %d\n", enable ? 1 : 0);

  lock = comp_lock_get(priv);

  if (lock)
    {
      aerr("ERROR: Comparator locked!\n");

      return -EPERM;
    }
  else
    {
      if (enable)
        {
          /* Enable the COMP */

          comp_modify_csr(priv, 0, COMP_CSR_COMPEN);
        }
      else
        {
          /* Disable the COMP */

          comp_modify_csr(priv, COMP_CSR_COMPEN, 0);
        }
    }

  return OK;
}

/****************************************************************************
 * Name: comp_setup
 *
 * Description:
 *   Configure the COMP. This method is called the first time that the COMP
 *   device is opened. This will occur when the port is first opened. This
 *   setup includes configuring and attaching COMP interrupts.
 *   Interrupts are all disabled upon return.
 *
 * Input Parameters:
 *
 * Returned Value:
 *
 ****************************************************************************/

#ifdef CONFIG_COMP
static int comp_setup(struct comp_dev_s *dev)
{
#warning "Missing logic"

  return OK;
}
#endif

/****************************************************************************
 * Name: comp_shutdown
 *
 * Description:
 *   Disable the COMP. This method is called when the COMP device is closed.
 *   This method reverses the operation the setup method.
 *   Works only if COMP device is not locked.
 *
 * Input Parameters:
 *
 * Returned Value:
 *   None
 *
 ****************************************************************************/

#ifdef CONFIG_COMP
static void comp_shutdown(struct comp_dev_s *dev)
{
#  warning "Missing logic"
}
#endif

/****************************************************************************
 * Name: comp_read
 *
 * Description:
 *  Get the COMP output state.
 *
 * Input Parameters:
 *
 * Returned Value:
 *   0 if output is low (non-inverting input below inverting input),
 *   1 if output is high (non inverting input above inverting input).
 *
 ****************************************************************************/

#ifdef CONFIG_COMP
static int comp_read(struct comp_dev_s *dev)
{
  struct stm32_comp_s *priv;
  uint32_t regval;

  priv = dev->ad_priv;
  regval = comp_getreg_csr(priv);

  return (((regval & COMP_CSR_VALUE) == 0) ? 0 : 1);
}
#endif

/****************************************************************************
 * Name: comp_ioctl
 *
 * Description:
 *   All ioctl calls will be routed through this method.
 *
 * Input Parameters:
 *   dev - pointer to device structure used by the driver
 *   cmd - command
 *   arg - arguments passed with command
 *
 * Returned Value:
 *   Zero on success; a negated errno value on failure.
 *
 ****************************************************************************/

#ifdef CONFIG_COMP
static int comp_ioctl(struct comp_dev_s *dev, int cmd, unsigned long arg)
{
#warning "Missing logic"
  return -ENOTTY;
}
#endif

/****************************************************************************
 * Public Functions
 ****************************************************************************/

/****************************************************************************
 * Name: stm32_compinitialize
 *
 * Description:
 *   Initialize the COMP.
 *
 * Input Parameters:
 *   intf - The COMP interface number.
 *
 * Returned Value:
 *   Valid COMP device structure reference on success; a NULL on failure.
 *
 * Assumptions:
 *   1. Clock to the COMP block has enabled,
 *   2. Board-specific logic has already configured
 *
 ****************************************************************************/

struct comp_dev_s *stm32_compinitialize(int intf)
{
  struct comp_dev_s   *dev;
  struct stm32_comp_s *comp;
  int ret;

  switch (intf)
    {
#ifdef CONFIG_STM32_COMP1
    case 1:
      ainfo("COMP1 selected\n");
      dev = &g_comp1dev;
      break;
#endif

#ifdef CONFIG_STM32_COMP2
    case 2:
      ainfo("COMP2 selected\n");
      dev = &g_comp2dev;
      break;
#endif

#ifdef CONFIG_STM32_COMP3
    case 3:
      ainfo("COMP3 selected\n");
      dev = &g_comp3dev;
      break;
#endif

#ifdef CONFIG_STM32_COMP4
    case 4:
      ainfo("COMP4 selected\n");
      dev = &g_comp4dev;
      break;
#endif

#ifdef CONFIG_STM32_COMP5
    case 5:
      ainfo("COMP5 selected\n");
      dev = &g_comp5dev;
      break;
#endif

#ifdef CONFIG_STM32_COMP6
    case 6:
      ainfo("COMP6 selected\n");
      dev = &g_comp6dev;
      break;
#endif

#ifdef CONFIG_STM32_COMP7
    case 7:
      ainfo("COMP7 selected\n");
      dev = &g_comp7dev;
      break;
#endif

    default:
      aerr("ERROR: No COMP interface defined\n");
      return NULL;
    }

  /* Configure selected comparator */

  comp = dev->ad_priv;

  ret = comp_config(comp);
  if (ret < 0)
    {
      aerr("ERROR: Failed to initialize COMP%d: %d\n", intf, ret);
      return NULL;
    }

  return dev;
}

#endif /* CONFIG_STM32_COMP */