acassis commented on code in PR #12697:
URL: https://github.com/apache/nuttx/pull/12697#discussion_r1677208886


##########
arch/arm/src/s32k1xx/Kconfig:
##########
@@ -227,6 +227,10 @@ config S32K1XX_FLEXCAN2
        default n
        depends on S32K1XX_HAVE_FLEXCAN2
 
+config S32K1XX_FLEXIO_I2C
+       bool "FlexIO I2C"

Review Comment:
   ```suggestion
        bool "FlexIO I2C (emulated I2C)"



##########
arch/arm/src/s32k1xx/s32k1xx_flexio_i2c.c:
##########
@@ -0,0 +1,755 @@
+/****************************************************************************
+ * arch/arm/src/s32k1xx/s32k1xx_flexio_i2c.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
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <sys/types.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/clock.h>
+#include <nuttx/mutex.h>
+#include <nuttx/semaphore.h>
+#include <nuttx/i2c/i2c_master.h>
+
+#include <arch/irq.h>
+
+#include "arm_internal.h"
+#include "s32k1xx_edma.h"
+#include "s32k1xx_pin.h"
+#include "hardware/s32k1xx_dmamux.h"
+#include "hardware/s32k1xx_pinmux.h"
+#include "s32k1xx_flexio_i2c.h"
+#include "s32k1xx_periphclocks.h"
+#include "s32k1xx_pin.h"
+
+#include <arch/board/board.h>
+
+/* At least one I2C peripheral must be enabled */
+#define CONFIG_S32K1XX_FLEXIO_I2C
+#ifdef CONFIG_S32K1XX_FLEXIO_I2C
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define I2C_MAX_FREQUENCY       400000
+#define FLEXIO_TX_IRQ           (1 << priv->config->tx_inst)
+#define FLEXIO_RX_IRQ           (1 << priv->config->rx_inst)
+#define FLEXIO_ADDR_READ(addr)  ((addr << 1 ) | 1)
+#define FLEXIO_ADDR_WRITE(addr) (addr << 1)
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+enum s32k1xx_intstate_e
+{
+  INTSTATE_IDLE = 0,      /* No I2C activity */
+  INTSTATE_RECV_DATA,
+  INTSTATE_WRITE_DATA,
+};
+
+struct s32k1xx_flexio_i2c_config_s
+{
+  int              tx_inst;
+  int              rx_inst;
+  int              timer;
+  int              two_word_timer;
+  uint32_t         flexio_sda_pin;
+  uint32_t         flexio_scl_pin;
+  uint32_t         sda_pin;
+  uint32_t         scl_pin;
+};
+
+struct s32k1xx_flexio_i2cdev_s
+{
+  struct i2c_master_s dev;     /* Generic I2C device */
+  unsigned int     base;       /* Base address of registers */
+  uint16_t         irqid;      /* IRQ for this device */
+  int8_t           port;       /* Port number */
+  uint32_t         base_freq;  /* branch frequency */
+
+  mutex_t          lock;       /* Only one thread can access at a time */
+  sem_t            wait;       /* Place to wait for transfer completion */
+  uint32_t         frequency;  /* Current I2C frequency */
+  int32_t          tx_count;
+  int32_t          reg_buff_offset;
+  int32_t          reg_buff_mod;
+  uint32_t         tx_done;
+
+  struct i2c_msg_s *msgs;
+  int              total_bytes;
+
+  /* Port configuration */
+
+  const struct s32k1xx_flexio_i2c_config_s *config;
+
+  enum s32k1xx_intstate_e state;
+
+  int              error;      /* Error status of each transfers */
+  int              refs;       /* Reference count */
+};
+
+static const struct s32k1xx_flexio_i2c_config_s s32k1xx_flexio_i2c0_config =
+{
+  .tx_inst = 0,
+  .rx_inst = 1,
+  .timer = 1,
+  .two_word_timer = 0,
+  .flexio_sda_pin = FLEXIO_I2C0_SDA,
+  .flexio_scl_pin = FLEXIO_I2C0_SCL,
+  .sda_pin = PIN_FLEXIO_I2C0_SCL,
+  .scl_pin = PIN_FLEXIO_I2C0_SDA,
+};
+
+static struct s32k1xx_flexio_i2cdev_s g_i2c0dev =
+{
+  .port = 0,
+  .base = S32K1XX_FLEXIO_BASE,
+  .irqid = S32K1XX_IRQ_FLEXIO,
+  .lock = NXMUTEX_INITIALIZER,
+  .wait = SEM_INITIALIZER(0),
+  .refs = 0,
+  .config = &s32k1xx_flexio_i2c0_config,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+static void s32k1xx_flexio_i2c_init(struct s32k1xx_flexio_i2cdev_s *priv);
+static int  s32k1xx_flexio_i2c_interrupt(int irq, void *context, void *arg);
+static void s32k1xx_flexio_i2c_set_freq_and_size(
+                                   struct s32k1xx_flexio_i2cdev_s *priv,
+                                   uint32_t frequency, uint8_t num_bytes);
+static int  s32k1xx_flexio_i2c_transfer(struct i2c_master_s *dev,
+                                struct i2c_msg_s *msgs, int count);
+
+static inline uint32_t flexio_getreg32(struct s32k1xx_flexio_i2cdev_s *priv,
+                                    uint32_t offset)
+{
+  return getreg32(priv->base + offset);
+}
+
+static inline void flexio_putreg32(struct s32k1xx_flexio_i2cdev_s *priv,
+                                 uint32_t val, uint32_t offset)
+{
+  putreg32(val, priv->base + offset);
+}
+
+static inline void flexio_modifyreg32(struct s32k1xx_flexio_i2cdev_s *priv,
+              unsigned int offset,
+              uint32_t clearbits,
+              uint32_t setbits)
+{
+  modifyreg32(priv->base + offset, clearbits, setbits);
+}
+
+static inline void
+enable_shifter_status_interrupts(struct s32k1xx_flexio_i2cdev_s *priv,
+                                                    uint32_t mask)
+{
+  flexio_modifyreg32(priv, S32K1XX_FLEXIO_SHIFTSIEN_OFFSET, 0, mask);
+}
+
+static inline void
+disable_shifter_status_interrupts(struct s32k1xx_flexio_i2cdev_s *priv,
+                                                    uint32_t mask)
+{
+  flexio_modifyreg32(priv, S32K1XX_FLEXIO_SHIFTSIEN_OFFSET, mask, 0);
+}
+
+static inline uint32_t
+get_shifter_status_flags(struct s32k1xx_flexio_i2cdev_s *priv)
+{
+  return flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTSTAT_OFFSET);
+}
+
+static inline void
+clear_shifter_status_flags(struct s32k1xx_flexio_i2cdev_s *priv,
+                                                    uint32_t mask)
+{
+  flexio_putreg32(priv, mask, S32K1XX_FLEXIO_SHIFTSTAT_OFFSET);
+}
+
+static inline void
+enable_timer_status_interrupts(struct s32k1xx_flexio_i2cdev_s *priv,
+                                                    uint32_t mask)
+{
+  flexio_modifyreg32(priv, S32K1XX_FLEXIO_TIMIEN_OFFSET, 0, mask);
+}
+
+static inline void
+disable_timer_status_interrupts(struct s32k1xx_flexio_i2cdev_s *priv,
+                                                    uint32_t mask)
+{
+  flexio_modifyreg32(priv, S32K1XX_FLEXIO_TIMIEN_OFFSET, mask, 0);
+}
+
+static inline void
+s32k1xx_flexio_i2c_set_nack(struct s32k1xx_flexio_i2cdev_s *priv)
+{
+  flexio_putreg32(priv, FLEXIO_SHIFTCFG_INSRC_PIN |
+    FLEXIO_SHIFTCFG_SSTOP_ONE |
+    FLEXIO_SHIFTCFG_SSTART_ZERO,
+    S32K1XX_FLEXIO_SHIFTCFG0_OFFSET + priv->config->tx_inst * 0x4);
+}
+
+static inline void
+s32k1xx_flexio_i2c_set_ack(struct s32k1xx_flexio_i2cdev_s *priv)
+{
+  flexio_putreg32(priv, FLEXIO_SHIFTCFG_INSRC_PIN |
+    FLEXIO_SHIFTCFG_SSTOP_ZERO |
+    FLEXIO_SHIFTCFG_SSTART_ZERO,
+    S32K1XX_FLEXIO_SHIFTCFG0_OFFSET + priv->config->tx_inst * 0x4);
+}
+
+static inline void
+s32k1xx_flexio_i2c_clear_errors(struct s32k1xx_flexio_i2cdev_s *priv)
+{
+  flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTBUFBIS0_OFFSET +
+                        priv->config->rx_inst * 0x4);
+  flexio_putreg32(priv, FLEXIO_TX_IRQ | FLEXIO_RX_IRQ,
+                        S32K1XX_FLEXIO_SHIFTERR_OFFSET);
+}
+
+/****************************************************************************
+ * I2C device operations
+ ****************************************************************************/
+
+struct i2c_ops_s s32k1xx_flexio_i2c_ops =
+{
+  .transfer = s32k1xx_flexio_i2c_transfer,
+};
+
+/****************************************************************************
+ * Name: s32k1xx_flexio_i2c_set_freq_and_size
+ *
+ * Description:
+ *   Set the frequency for the next transfer
+ *
+ ****************************************************************************/
+
+static void s32k1xx_flexio_i2c_set_freq_and_size(
+                                   struct s32k1xx_flexio_i2cdev_s *priv,
+                                   uint32_t frequency, uint8_t num_bytes)
+{
+  int divider = ((priv->base_freq / frequency) / 2) - 1;
+
+  if (divider > 0xff)
+    {
+      divider = 0xff;
+    }
+
+  flexio_putreg32(priv, divider |
+                  ((((num_bytes + 1) * 9 + 1) * 2 - 1) << 8),
+                  S32K1XX_FLEXIO_TIMCMP0_OFFSET +
+                  priv->config->two_word_timer * 0x4);
+}
+
+/****************************************************************************
+ * Name: s32k1xx_flexio_i2c_interrupt
+ *
+ * Description:
+ *   The I2C Interrupt Handler
+ *
+ ****************************************************************************/
+
+static int s32k1xx_flexio_i2c_interrupt(int irq, void *context, void *arg)
+{
+  struct s32k1xx_flexio_i2cdev_s *priv =
+          (struct s32k1xx_flexio_i2cdev_s *)arg;
+  struct i2c_msg_s *msg = priv->msgs;
+
+  if ((priv->state == INTSTATE_IDLE))
+    {
+      disable_shifter_status_interrupts(priv, FLEXIO_RX_IRQ);
+      disable_shifter_status_interrupts(priv, FLEXIO_TX_IRQ);
+    }
+  else if ((priv->state == INTSTATE_RECV_DATA))
+    {
+      if (!priv->tx_done && get_shifter_status_flags(priv) & FLEXIO_TX_IRQ)
+        {
+          if (priv->tx_count == msg->length)
+            {
+              /* Send NACK and Stop bit */
+
+              s32k1xx_flexio_i2c_set_nack(priv);
+              flexio_putreg32(priv, 0x00,
+                              S32K1XX_FLEXIO_SHIFTBUFBBS0_OFFSET +
+                              priv->config->tx_inst * 0x4);
+              priv->tx_count++;
+            }
+          else if (priv->tx_count < msg->length)
+            {
+              flexio_putreg32(priv, 0xff,
+                              S32K1XX_FLEXIO_SHIFTBUFBBS0_OFFSET +
+                              priv->config->tx_inst * 0x4);
+              priv->tx_count++;
+            }
+          else
+            {
+              priv->tx_done = 1;
+              disable_shifter_status_interrupts(priv, FLEXIO_TX_IRQ);
+            }
+        }
+
+      if (get_shifter_status_flags(priv) & FLEXIO_RX_IRQ)
+        {
+          if (priv->reg_buff_offset < 0)
+            {
+              flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTBUFBIS0_OFFSET +
+                              priv->config->rx_inst * 0x4);
+
+              /* If RX shifter reports an error then stop bit (ACK)
+               * doesn't go low, thus we get a NACK
+               */
+
+              if (flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTERR_OFFSET) &
+                  FLEXIO_RX_IRQ)
+                {
+                  priv->error = 1;
+                  flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTBUFBIS0_OFFSET +
+                                  priv->config->rx_inst * 0x4);
+                  flexio_putreg32(priv, FLEXIO_RX_IRQ,
+                                  S32K1XX_FLEXIO_SHIFTERR_OFFSET);
+                  disable_shifter_status_interrupts(priv, FLEXIO_RX_IRQ);
+                  disable_shifter_status_interrupts(priv, FLEXIO_TX_IRQ);
+                  priv->state = INTSTATE_IDLE;
+                  nxsem_post(&priv->wait);
+                }
+              else if (msg->length > 1)
+                {
+                  s32k1xx_flexio_i2c_set_ack(priv);
+                }
+            }
+          else
+            {
+              msg->buffer[priv->reg_buff_offset] =
+                  flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTBUFBIS0_OFFSET +
+                                  priv->config->rx_inst * 0x4) & 0xff;
+            }
+
+          priv->reg_buff_offset++;
+          if (priv->reg_buff_offset == msg->length)
+            {
+              disable_shifter_status_interrupts(priv, FLEXIO_RX_IRQ);
+              disable_shifter_status_interrupts(priv, FLEXIO_TX_IRQ);
+              priv->state = INTSTATE_IDLE;
+              nxsem_post(&priv->wait);
+            }
+        }
+    }
+  else if ((priv->state == INTSTATE_WRITE_DATA))
+    {
+      if (!priv->tx_done && get_shifter_status_flags(priv) & FLEXIO_TX_IRQ)
+        {
+          flexio_putreg32(priv, msg->buffer[priv->reg_buff_mod++],
+                          S32K1XX_FLEXIO_SHIFTBUFBBS0_OFFSET +
+                              priv->config->tx_inst * 0x4);
+          priv->tx_count++;
+
+          if (priv->reg_buff_mod % msg->length == 0)
+            {
+              priv->reg_buff_mod = 0;
+              priv->msgs++;
+            }
+
+          if (priv->tx_count == priv->total_bytes)
+            {
+              priv->tx_done = 1;
+              disable_shifter_status_interrupts(priv, FLEXIO_TX_IRQ);
+            }
+        }
+
+      if (get_shifter_status_flags(priv) & FLEXIO_RX_IRQ)
+        {
+          flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTBUFBIS0_OFFSET +
+                                    priv->config->rx_inst * 0x4);
+
+          /* If RX shifter reports an error then stop bit (ACK)
+           * doesn't go low, thus we get a NACK
+           */
+
+          if (priv->reg_buff_offset == 0 &&
+              (flexio_getreg32(priv, S32K1XX_FLEXIO_SHIFTERR_OFFSET) &
+               FLEXIO_RX_IRQ))
+            {
+              priv->error = 1;
+            }
+
+          priv->reg_buff_offset++;
+          if (priv->reg_buff_offset == priv->total_bytes - 1)
+            {
+              disable_shifter_status_interrupts(priv, FLEXIO_RX_IRQ);
+              priv->state = INTSTATE_IDLE;
+              nxsem_post(&priv->wait);
+            }
+        }
+    }
+
+  return OK;
+}
+
+static int set_expiretime(int expire_time, FAR struct timespec *set_time)
+{
+  struct timespec curr_time;
+
+  /* Get current time. */
+
+  if (clock_gettime(CLOCK_REALTIME, &curr_time) != OK)
+    {
+      return ERROR;
+    }
+
+  set_time->tv_sec = expire_time / 1000;
+  set_time->tv_nsec =
+    (expire_time - (set_time->tv_sec * 1000)) * 1000 * 1000;
+
+  set_time->tv_sec += curr_time.tv_sec;
+  set_time->tv_nsec += curr_time.tv_nsec;
+
+  /* Check more than 1 sec. */
+
+  if (set_time->tv_nsec >= (1000 * 1000 * 1000))
+    {
+      set_time->tv_sec += 1;
+      set_time->tv_nsec -= (1000 * 1000 * 1000);
+    }
+
+  return OK;
+}
+
+static void s32k1xx_flexio_i2c_init(struct s32k1xx_flexio_i2cdev_s *priv)
+{
+  /* Reset FlexIO peripheral */
+
+  flexio_modifyreg32(priv, S32K1XX_FLEXIO_CTRL_OFFSET, 0,
+         FLEXIO_CTRL_SWRST);
+  flexio_putreg32(priv, 0, S32K1XX_FLEXIO_CTRL_OFFSET);
+
+  /* Initialize FlexIO peripheral */
+
+  flexio_modifyreg32(priv, S32K1XX_FLEXIO_CTRL_OFFSET,
+         (FLEXIO_CTRL_DOZEN |
+          FLEXIO_CTRL_DBGE |
+          FLEXIO_CTRL_FASTACC |
+          FLEXIO_CTRL_FLEXEN),
+         (FLEXIO_CTRL_DBGE |
+          FLEXIO_CTRL_FLEXEN_DIS));
+
+  /* Start bit enabled (logic 0) and stop bit enabled (logic 1). */
+
+  s32k1xx_flexio_i2c_set_nack(priv);
+
+  /* Transmit mode, output to FXIO pin */
+
+  flexio_putreg32(priv, FLEXIO_SHIFTCTL_TIMSEL(priv->config->timer) |
+      FLEXIO_SHIFTCTL_TIMPOL_PE |
+      FLEXIO_SHIFTCTL_PINCFG_OD |
+      FLEXIO_SHIFTCTL_PINSEL(priv->config->flexio_sda_pin) |
+      FLEXIO_SHIFTCTL_PINPOL_LO |
+      FLEXIO_SHIFTCTL_SMOD_TX,
+      S32K1XX_FLEXIO_SHIFTCTL0_OFFSET + priv->config->tx_inst * 0x4);
+
+  /* Start bit disabled and stop bit enabled
+   * (logic 0) for ACK/NACK detection..
+   */
+
+  flexio_putreg32(priv, FLEXIO_SHIFTCFG_INSRC_PIN |
+      FLEXIO_SHIFTCFG_SSTOP_ZERO |
+      FLEXIO_SHIFTCFG_SSTART_DIS,
+      S32K1XX_FLEXIO_SHIFTCFG0_OFFSET + priv->config->rx_inst * 0x4);
+
+  /* Configure receive using Timer X on falling edge
+   * of clock with input data on Pin X
+   */
+
+  flexio_putreg32(priv, FLEXIO_SHIFTCTL_TIMSEL(priv->config->timer) |
+      FLEXIO_SHIFTCTL_TIMPOL_NE |
+      FLEXIO_SHIFTCTL_PINCFG_DIS |
+      FLEXIO_SHIFTCTL_PINSEL(priv->config->flexio_sda_pin) |
+      FLEXIO_SHIFTCTL_SMOD_RX,
+      S32K1XX_FLEXIO_SHIFTCTL0_OFFSET + priv->config->rx_inst * 0x4);
+
+  /* Configure start bit, stop bit, enable on trigger high,
+   * disable on compare, reset if output equals pin.
+   * Initial clock state is logic 0 and is not affected by reset.
+   */
+
+  flexio_putreg32(priv, FLEXIO_TIMCFG_TSTART_ENA |
+      FLEXIO_TIMCFG_TSTOP_TIMDIS |
+      FLEXIO_TIMCFG_TIMENA_TRGHI |
+      FLEXIO_TIMCFG_TIMDIS_TIMCMP |
+      FLEXIO_TIMCFG_TIMRST_PINOUT |
+      FLEXIO_TIMCFG_TIMOUT_ZERO,
+      S32K1XX_FLEXIO_TIMCFG0_OFFSET + priv->config->two_word_timer * 0x4);
+
+  /* Configure dual 8-bit counter using Pin 1 output enable (SCL open drain),
+   * with Shifter 0 flag as the inverted trigger.
+   */
+
+  flexio_putreg32(priv, FLEXIO_TIMCTL_TRGSEL_SHIFTER(priv->config->tx_inst) |
+      FLEXIO_TIMCTL_TRGPOL_LO |
+      FLEXIO_TIMCTL_TRGSRC_INT |
+      FLEXIO_TIMCTL_PINCFG_OD |
+      FLEXIO_TIMCTL_PINSEL(priv->config->flexio_scl_pin) |
+      FLEXIO_TIMCTL_TIMOD_8BBAUD,
+      S32K1XX_FLEXIO_TIMCTL0_OFFSET + priv->config->two_word_timer * 0x4);
+
+  /* Configure 8-bit transfer. Set TIMCMP[15:0] = (number of bits x 2) - 1. */
+
+  flexio_putreg32(priv, 0xf, S32K1XX_FLEXIO_TIMCMP0_OFFSET +
+                             priv->config->timer * 0x4);
+
+  /* Enable when Timer 0 is enabled, disable when Timer 0 is disabled,
+   * enable start bit and stop bit at end of each word,
+   * decrement on pin input..
+   */
+
+  flexio_putreg32(priv, FLEXIO_TIMCFG_TSTART_ENA |
+      FLEXIO_TIMCFG_TSTOP_TIMCMP |
+      FLEXIO_TIMCFG_TIMENA_TIMENA |
+      FLEXIO_TIMCFG_TIMDIS_TIMDIS |
+      FLEXIO_TIMCFG_TIMDEC_PINBOTHPIN,
+      S32K1XX_FLEXIO_TIMCFG0_OFFSET + priv->config->timer * 0x4);
+
+  /* Configure 16-bit counter using inverted Pin 1 input (SCL).. */
+
+  flexio_putreg32(priv, FLEXIO_TIMCTL_TRGSEL_SHIFTER(priv->config->tx_inst) |
+      FLEXIO_TIMCTL_TRGPOL_LO |
+      FLEXIO_TIMCTL_TRGSRC_INT |
+      FLEXIO_TIMCTL_PINSEL(priv->config->flexio_scl_pin) |
+      FLEXIO_TIMCTL_PINPOL_LO |
+      FLEXIO_TIMCTL_TIMOD_16BCNT,
+      S32K1XX_FLEXIO_TIMCTL0_OFFSET + priv->config->timer * 0x4);
+
+  flexio_modifyreg32(priv, S32K1XX_FLEXIO_CTRL_OFFSET, 0,
+         FLEXIO_CTRL_FLEXEN);
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: s32k1xx_flexio_i2cbus_initialize
+ *
+ * Description:
+ *   Initialise an I2C device
+ *
+ ****************************************************************************/
+
+struct i2c_master_s *s32k1xx_flexio_i2cbus_initialize(int port)
+{
+  struct s32k1xx_flexio_i2cdev_s *priv;
+
+  if (port == 0)
+    {
+      priv          = &g_i2c0dev;
+      priv->dev.ops = &s32k1xx_flexio_i2c_ops;
+    }
+  else
+    {
+      i2cerr("I2C Only support 0\n");
+      return NULL;
+    }
+
+  nxmutex_lock(&priv->lock);
+
+  /* Test if already initialized or not */
+
+  if (1 < ++priv->refs)
+    {
+      nxmutex_unlock(&priv->lock);
+      return &priv->dev;
+    }
+
+  priv->port      = port;
+  priv->frequency = 0;
+
+  s32k1xx_get_pclkfreq(FLEXIO0_CLK, &priv->base_freq);
+
+  /* Configure pins */
+
+  s32k1xx_pinconfig(priv->config->scl_pin);
+  s32k1xx_pinconfig(priv->config->sda_pin);
+
+  s32k1xx_flexio_i2c_init(priv);
+
+  /* Attach Interrupt Handler */
+
+  irq_attach(priv->irqid, s32k1xx_flexio_i2c_interrupt, priv);
+
+  /* Enable Interrupt Handler */
+
+  up_enable_irq(priv->irqid);
+
+  nxmutex_unlock(&priv->lock);
+  return &priv->dev;
+}
+
+/****************************************************************************
+ * Name: s32k1xx_flexio_i2cbus_uninitialize
+ *
+ * Description:
+ *   Uninitialise an I2C device
+ *
+ ****************************************************************************/
+
+int s32k1xx_flexio_i2cbus_uninitialize(struct i2c_master_s *dev)
+{
+  struct s32k1xx_flexio_i2cdev_s *priv =
+              (struct s32k1xx_flexio_i2cdev_s *)dev;
+
+  /* Decrement reference count and check for underflow */
+
+  if (priv->refs == 0)
+    {
+      return ERROR;
+    }
+
+  nxmutex_lock(&priv->lock);
+  if (--priv->refs)
+    {
+      nxmutex_unlock(&priv->lock);
+      return OK;
+    }
+
+  up_disable_irq(priv->irqid);
+  irq_detach(priv->irqid);
+
+  nxmutex_unlock(&priv->lock);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: s32k1xx_flexio_i2c_transfer
+ *
+ * Description:
+ *   Perform a sequence of I2C transfers
+ *
+ * TODO: Multiple i2c_msg_s read operations with the same address are not
+ * currently guaranteed.
+ ****************************************************************************/
+
+static int s32k1xx_flexio_i2c_transfer(struct i2c_master_s *dev,
+                               struct i2c_msg_s *msgs, int count)
+{
+  struct s32k1xx_flexio_i2cdev_s *priv =
+              (struct s32k1xx_flexio_i2cdev_s *)dev;
+  int i;
+  int ret    = 0;
+  int semval = 0;
+  struct timespec abs_time;
+
+  if (msgs->frequency > I2C_MAX_FREQUENCY)
+    {
+      return -EINVAL;
+    }
+
+  DEBUGASSERT(dev != NULL);
+
+  /* Get exclusive access to the I2C bus */
+
+  nxmutex_lock(&priv->lock);
+
+  /* Check wait semaphore value. If the value is not 0, the transfer can not
+   * be performed normally.
+   */
+
+  ret = nxsem_get_value(&priv->wait, &semval);
+  DEBUGASSERT(ret == OK && semval == 0);
+
+  priv->total_bytes = 0;
+
+  for (i = 0; i < count; i++)
+    {
+      priv->total_bytes += msgs[i].length;
+    }
+
+  if (priv->total_bytes < 12)

Review Comment:
   Suggestion include the comment here too:
   /* FlexIO driver can only handle transfers of maximum 12 bytes */



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