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/nuttx.git


The following commit(s) were added to refs/heads/master by this push:
     new f8c5b91522 arm64/imx9: Add LPI2C driver
f8c5b91522 is described below

commit f8c5b91522daf98140390e048d0268d247b3c8f8
Author: Ville Juven <[email protected]>
AuthorDate: Wed Mar 27 17:13:08 2024 +0200

    arm64/imx9: Add LPI2C driver
---
 arch/arm64/Kconfig                                 |    1 +
 arch/arm64/src/imx9/Kconfig                        |  249 ++
 arch/arm64/src/imx9/Make.defs                      |    4 +
 arch/arm64/src/imx9/hardware/imx9_lpi2c.h          |  622 +++++
 arch/arm64/src/imx9/imx9_lpi2c.c                   | 2579 ++++++++++++++++++++
 .../arm64/src/imx9/imx9_lpi2c.h                    |   56 +-
 boards/arm64/imx9/imx93-evk/configs/nsh/defconfig  |    6 +
 boards/arm64/imx9/imx93-evk/include/board.h        |   12 +
 boards/arm64/imx9/imx93-evk/src/Makefile           |    4 +
 boards/arm64/imx9/imx93-evk/src/imx93-evk.h        |   12 +
 boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c   |    3 +
 boards/arm64/imx9/imx93-evk/src/imx9_bringup.c     |   10 +
 .../imx93-evk/src/{imx9_bringup.c => imx9_i2c.c}   |   43 +-
 13 files changed, 3554 insertions(+), 47 deletions(-)

diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 37b632f9ae..b9fc7bdb06 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -94,6 +94,7 @@ config ARCH_CHIP_IMX8
 config ARCH_CHIP_IMX9
        bool "NXP i.MX9 Platform (ARMv8.2a)"
        select ARCH_HAVE_ADDRENV
+       select ARCH_HAVE_I2CRESET
        select ARCH_HAVE_IRQTRIGGER
        select ARCH_NEED_ADDRENV_MAPPING
        ---help---
diff --git a/arch/arm64/src/imx9/Kconfig b/arch/arm64/src/imx9/Kconfig
index 9ab957be01..9368c961c1 100644
--- a/arch/arm64/src/imx9/Kconfig
+++ b/arch/arm64/src/imx9/Kconfig
@@ -218,8 +218,257 @@ config IMX9_GPIO_IRQ
        bool "GPIO Interrupt Support"
        default n
 
+config IMX9_LPI2C
+       bool "LPI2C support"
+       default n
+
 config IMX9_PLL
        bool "PLL setup support (WIP)"
        default n
 
+menu "LPI2C Peripherals"
+
+menuconfig IMX9_LPI2C1
+       bool "LPI2C1"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C1
+
+config IMX9_LPI2C1_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C1_DMA
+       bool "Enable DMA for I2C1"
+       default n
+       depends on IMX9_LPI2C_DMA
+
+config IMX9_LPI2C1_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C1_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C1
+
+menuconfig IMX9_LPI2C2
+       bool "LPI2C2"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C2
+
+config IMX9_LPI2C2_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C2_DMA
+       bool "Enable DMA for I2C2"
+       default n
+       depends on IMX9_LPI2C_DMA
+
+config IMX9_LPI2C2_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C2_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C2
+
+menuconfig IMX9_LPI2C3
+       bool "LPI2C3"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C3
+
+config IMX9_LPI2C3_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C3_DMA
+       bool "Enable DMA for I2C3"
+       default n
+       depends on IMX9_LPI2C_DMA
+
+config IMX9_LPI2C3_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C3_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C3
+
+menuconfig IMX9_LPI2C4
+       bool "LPI2C4"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C4
+
+config IMX9_LPI2C4_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C4_DMA
+       bool "Enable DMA for I2C4"
+       default n
+       depends on IMX9_LPI2C_DMA
+
+config IMX9_LPI2C4_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C4_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C4
+
+menuconfig IMX9_LPI2C5
+       bool "LPI2C5"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C5
+
+config IMX9_LPI2C5_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C5_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C5_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C5
+
+menuconfig IMX9_LPI2C6
+       bool "LPI2C6"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C6
+
+config IMX9_LPI2C6_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C6_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C6_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C6
+
+menuconfig IMX9_LPI2C7
+       bool "LPI2C7"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C7
+
+config IMX9_LPI2C7_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C7_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C7_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C7
+
+menuconfig IMX9_LPI2C8
+       bool "LPI2C8"
+       default n
+       select IMX9_LPI2C
+
+if IMX9_LPI2C8
+
+config IMX9_LPI2C8_BUSYIDLE
+       int "Bus idle timeout period in clock cycles"
+       default 0
+
+config IMX9_LPI2C8_FILTSCL
+       int "I2C master digital glitch filters for SCL input in clock cycles"
+       default 0
+
+config IMX9_LPI2C8_FILTSDA
+       int "I2C master digital glitch filters for SDA input in clock cycles"
+       default 0
+
+endif # IMX9_LPI2C8
+
+endmenu # LPI2C Peripherals
+menu "LPI2C Configuration"
+       depends on IMX9_LPI2C
+
+config IMX9_LPI2C_DMA
+       bool "I2C DMA Support"
+       default n
+       depends on IMX9_LPI2C && IMX9_EDMA && !I2C_POLLED
+       ---help---
+               This option enables the DMA for I2C transfers.
+               Note: The user can define CONFIG_I2C_DMAPRIO: a custom priority 
value
+               for the I2C dma streams, else the default priority level is set 
to
+               medium.
+
+config IMX9_LPI2C_DMA_MAXMSG
+       int "Maximum number messages that will be DMAed"
+       default 8
+       depends on IMX9_LPI2C_DMA
+       ---help---
+               This option set the mumber of mesg that can be in a transfer.
+               It is used to allocate space for the 16 bit LPI2C commands
+               that will be DMA-ed to the LPI2C device.
+
+config IMX9_LPI2C_DYNTIMEO
+       bool "Use dynamic timeouts"
+       default n
+       depends on IMX9_LPI2C
+
+config IMX9_LPI2C_DYNTIMEO_USECPERBYTE
+       int "Timeout Microseconds per Byte"
+       default 500
+       depends on IMX9_LPI2C_DYNTIMEO
+
+config IMX9_LPI2C_DYNTIMEO_STARTSTOP
+       int "Timeout for Start/Stop (Milliseconds)"
+       default 1000
+       depends on IMX9_LPI2C_DYNTIMEO
+
+config IMX9_LPI2C_TIMEOSEC
+       int "Timeout seconds"
+       default 0
+       depends on IMX9_LPI2C
+
+config IMX9_LPI2C_TIMEOMS
+       int "Timeout Milliseconds"
+       default 500
+       depends on IMX9_LPI2C && !IMX9_LPI2C_DYNTIMEO
+
+config IMX9_LPI2C_TIMEOTICKS
+       int "Timeout for Done and Stop (ticks)"
+       default 500
+       depends on IMX9_LPI2C && !IMX9_LPI2C_DYNTIMEO
+
+endmenu # LPI2C Configuration
+
 endif # ARCH_CHIP_IMX9
diff --git a/arch/arm64/src/imx9/Make.defs b/arch/arm64/src/imx9/Make.defs
index 0d7427aec3..27a19cb357 100644
--- a/arch/arm64/src/imx9/Make.defs
+++ b/arch/arm64/src/imx9/Make.defs
@@ -46,3 +46,7 @@ endif
 ifeq ($(CONFIG_IMX9_USBDEV),y)
   CHIP_CSRCS += imx9_usbdev.c
 endif
+
+ifeq ($(CONFIG_IMX9_LPI2C),y)
+  CHIP_CSRCS += imx9_lpi2c.c
+endif
diff --git a/arch/arm64/src/imx9/hardware/imx9_lpi2c.h 
b/arch/arm64/src/imx9/hardware/imx9_lpi2c.h
new file mode 100644
index 0000000000..1c7e47aa88
--- /dev/null
+++ b/arch/arm64/src/imx9/hardware/imx9_lpi2c.h
@@ -0,0 +1,622 @@
+/****************************************************************************
+ * arch/arm64/src/imx9/hardware/imx9_lpi2c.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 __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPI2C_H_
+#define __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPI2C_H_
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Register offsets *********************************************************/
+
+#define IMX9_LPI2C_VERID_OFFSET             0x0000  /* Version ID Register 
offset */
+#define IMX9_LPI2C_PARAM_OFFSET             0x0004  /* Parameter Register 
offset */
+#define IMX9_LPI2C_MCR_OFFSET               0x0010  /* Master Control Register 
offset */
+#define IMX9_LPI2C_MSR_OFFSET               0x0014  /* Master Status Register 
offset */
+#define IMX9_LPI2C_MIER_OFFSET              0x0018  /* Master Interrupt Enable 
Register offset */
+#define IMX9_LPI2C_MDER_OFFSET              0x001c  /* Master DMA Enable 
Register offset */
+#define IMX9_LPI2C_MCFGR0_OFFSET            0x0020  /* Master Config Register 
0 offset */
+#define IMX9_LPI2C_MCFGR1_OFFSET            0x0024  /* Master Config Register 
1 offset */
+#define IMX9_LPI2C_MCFGR2_OFFSET            0x0028  /* Master Config Register 
2 offset */
+#define IMX9_LPI2C_MCFGR3_OFFSET            0x002c  /* Master Config Register 
3 offset */
+#define IMX9_LPI2C_MDMR_OFFSET              0x0040  /* Master Data Match 
Register offset */
+#define IMX9_LPI2C_MCCR0_OFFSET             0x0048  /* Master Clock 
Configuration Register 0 offset */
+#define IMX9_LPI2C_MCCR1_OFFSET             0x0050  /* Master Clock 
Configuration Register 1 offset */
+#define IMX9_LPI2C_MFCR_OFFSET              0x0058  /* Master FIFO Control 
Register offset */
+#define IMX9_LPI2C_MFSR_OFFSET              0x005C  /* Master FIFO Status 
Register offset */
+#define IMX9_LPI2C_MTDR_OFFSET              0x0060  /* Master Transmit Data 
Register offset */
+#define IMX9_LPI2C_MRDR_OFFSET              0x0070  /* Master Receive Data 
Register offset */
+#define IMX9_LPI2C_SCR_OFFSET               0x0110  /* Slave Control Register 
offset */
+#define IMX9_LPI2C_SSR_OFFSET               0x0114  /* Slave Status Register 
offset */
+#define IMX9_LPI2C_SIER_OFFSET              0x0118  /* Slave Interrupt Enable 
Register offset */
+#define IMX9_LPI2C_SDER_OFFSET              0x011c  /* Slave DMA Enable 
Register offset */
+#define IMX9_LPI2C_SCFGR1_OFFSET            0x0124  /* Slave Config Register 1 
offset */
+#define IMX9_LPI2C_SCFGR2_OFFSET            0x0128  /* Slave Config Register 2 
offset */
+#define IMX9_LPI2C_SAMR_OFFSET              0x0140  /* Slave Address Match 
Register offset */
+#define IMX9_LPI2C_SASR_OFFSET              0x0150  /* Slave Address Status 
Register offset */
+#define IMX9_LPI2C_STAR_OFFSET              0x0154  /* Slave Transmit ACK 
Register offset */
+#define IMX9_LPI2C_STDR_OFFSET              0x0160  /* Slave Transmit Data 
Register offset */
+#define IMX9_LPI2C_SRDR_OFFSET              0x0170  /* Slave Receive Data 
Register offset */
+
+/* Register addresses *******************************************************/
+
+/* LPI2C1 Registers */
+
+#define IMX9_LPI2C1_VERID                  (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_VERID_OFFSET)   /* Version ID Register */
+#define IMX9_LPI2C1_PARAM                  (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_PARAM_OFFSET)   /* Parameter Register  */
+#define IMX9_LPI2C1_MCR                    (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MCR_OFFSET)     /* Master Control Register  */
+#define IMX9_LPI2C1_MSR                    (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MSR_OFFSET)     /* Master Status Register  */
+#define IMX9_LPI2C1_MIER                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MIER_OFFSET)    /* Master Interrupt Enable Register  */
+#define IMX9_LPI2C1_MDER                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MDER_OFFSET)    /* Master DMA Enable Register  */
+#define IMX9_LPI2C1_MCFGR0                 (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MCFGR0_OFFSET)  /* Master Config Register 0  */
+#define IMX9_LPI2C1_MCFGR1                 (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MCFGR1_OFFSET)  /* Master Config Register 1  */
+#define IMX9_LPI2C1_MCFGR2                 (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MCFGR2_OFFSET)  /* Master Config Register 2  */
+#define IMX9_LPI2C1_MCFGR3                 (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MCFGR3_OFFSET)  /* Master Config Register 3  */
+#define IMX9_LPI2C1_MDMR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MDMR_OFFSET)    /* Master Data Match Register  */
+#define IMX9_LPI2C1_MCCR0                  (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MCCR0_OFFSET)   /* Master Clock Configuration Register 0  */
+#define IMX9_LPI2C1_MCCR1                  (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MCCR1_OFFSET)   /* Master Clock Configuration Register 1  */
+#define IMX9_LPI2C1_MFCR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MFCR_OFFSET)    /* Master FIFO Control Register  */
+#define IMX9_LPI2C1_MFSR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MFSR_OFFSET)    /* Master FIFO Status Register  */
+#define IMX9_LPI2C1_MTDR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MTDR_OFFSET)    /* Master Transmit Data Register  */
+#define IMX9_LPI2C1_MRDR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_MRDR_OFFSET)    /* Master Receive Data Register  */
+#define IMX9_LPI2C1_SCR                    (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SCR_OFFSET)     /* Slave Control Register  */
+#define IMX9_LPI2C1_SSR                    (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SSR_OFFSET)     /* Slave Status Register  */
+#define IMX9_LPI2C1_SIER                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SIER_OFFSET)    /* Slave Interrupt Enable Register  */
+#define IMX9_LPI2C1_SDER                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SDER_OFFSET)    /* Slave DMA Enable Register  */
+#define IMX9_LPI2C1_SCFGR1                 (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SCFGR1_OFFSET)  /* Slave Config Register 1  */
+#define IMX9_LPI2C1_SCFGR2                 (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SCFGR2_OFFSET)  /* Slave Config Register 2  */
+#define IMX9_LPI2C1_SAMR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SAMR_OFFSET)    /* Slave Address Match Register  */
+#define IMX9_LPI2C1_SASR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SASR_OFFSET)    /* Slave Address Status Register  */
+#define IMX9_LPI2C1_STAR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_STAR_OFFSET)    /* Slave Transmit ACK Register  */
+#define IMX9_LPI2C1_STDR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_STDR_OFFSET)    /* Slave Transmit Data Register  */
+#define IMX9_LPI2C1_SRDR                   (IMX9_LPI2C1_BASE + 
IMX9_LPI2C_SRDR_OFFSET)    /* Slave Receive Data Register  */
+
+/* LPI2C2 Registers */
+
+#define IMX9_LPI2C2_VERID                  (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_VERID_OFFSET)   /* Version ID Register */
+#define IMX9_LPI2C2_PARAM                  (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_PARAM_OFFSET)   /* Parameter Register  */
+#define IMX9_LPI2C2_MCR                    (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MCR_OFFSET)     /* Master Control Register  */
+#define IMX9_LPI2C2_MSR                    (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MSR_OFFSET)     /* Master Status Register  */
+#define IMX9_LPI2C2_MIER                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MIER_OFFSET)    /* Master Interrupt Enable Register  */
+#define IMX9_LPI2C2_MDER                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MDER_OFFSET)    /* Master DMA Enable Register  */
+#define IMX9_LPI2C2_MCFGR0                 (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MCFGR0_OFFSET)  /* Master Config Register 0  */
+#define IMX9_LPI2C2_MCFGR1                 (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MCFGR1_OFFSET)  /* Master Config Register 1  */
+#define IMX9_LPI2C2_MCFGR2                 (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MCFGR2_OFFSET)  /* Master Config Register 2  */
+#define IMX9_LPI2C2_MCFGR3                 (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MCFGR3_OFFSET)  /* Master Config Register 3  */
+#define IMX9_LPI2C2_MDMR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MDMR_OFFSET)    /* Master Data Match Register  */
+#define IMX9_LPI2C2_MCCR0                  (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MCCR0_OFFSET)   /* Master Clock Configuration Register 0  */
+#define IMX9_LPI2C2_MCCR1                  (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MCCR1_OFFSET)   /* Master Clock Configuration Register 1  */
+#define IMX9_LPI2C2_MFCR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MFCR_OFFSET)    /* Master FIFO Control Register  */
+#define IMX9_LPI2C2_MFSR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MFSR_OFFSET)    /* Master FIFO Status Register  */
+#define IMX9_LPI2C2_MTDR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MTDR_OFFSET)    /* Master Transmit Data Register  */
+#define IMX9_LPI2C2_MRDR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_MRDR_OFFSET)    /* Master Receive Data Register  */
+#define IMX9_LPI2C2_SCR                    (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SCR_OFFSET)     /* Slave Control Register  */
+#define IMX9_LPI2C2_SSR                    (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SSR_OFFSET)     /* Slave Status Register  */
+#define IMX9_LPI2C2_SIER                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SIER_OFFSET)    /* Slave Interrupt Enable Register  */
+#define IMX9_LPI2C2_SDER                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SDER_OFFSET)    /* Slave DMA Enable Register  */
+#define IMX9_LPI2C2_SCFGR1                 (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SCFGR1_OFFSET)  /* Slave Config Register 1  */
+#define IMX9_LPI2C2_SCFGR2                 (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SCFGR2_OFFSET)  /* Slave Config Register 2  */
+#define IMX9_LPI2C2_SAMR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SAMR_OFFSET)    /* Slave Address Match Register  */
+#define IMX9_LPI2C2_SASR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SASR_OFFSET)    /* Slave Address Status Register  */
+#define IMX9_LPI2C2_STAR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_STAR_OFFSET)    /* Slave Transmit ACK Register  */
+#define IMX9_LPI2C2_STDR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_STDR_OFFSET)    /* Slave Transmit Data Register  */
+#define IMX9_LPI2C2_SRDR                   (IMX9_LPI2C2_BASE + 
IMX9_LPI2C_SRDR_OFFSET)    /* Slave Receive Data Register  */
+
+/* LPI2C3 Registers */
+
+#define IMX9_LPI2C3_VERID                  (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_VERID_OFFSET)   /* Version ID Register */
+#define IMX9_LPI2C3_PARAM                  (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_PARAM_OFFSET)   /* Parameter Register  */
+#define IMX9_LPI2C3_MCR                    (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MCR_OFFSET)     /* Master Control Register  */
+#define IMX9_LPI2C3_MSR                    (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MSR_OFFSET)     /* Master Status Register  */
+#define IMX9_LPI2C3_MIER                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MIER_OFFSET)    /* Master Interrupt Enable Register  */
+#define IMX9_LPI2C3_MDER                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MDER_OFFSET)    /* Master DMA Enable Register  */
+#define IMX9_LPI2C3_MCFGR0                 (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MCFGR0_OFFSET)  /* Master Config Register 0  */
+#define IMX9_LPI2C3_MCFGR1                 (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MCFGR1_OFFSET)  /* Master Config Register 1  */
+#define IMX9_LPI2C3_MCFGR2                 (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MCFGR2_OFFSET)  /* Master Config Register 2  */
+#define IMX9_LPI2C3_MCFGR3                 (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MCFGR3_OFFSET)  /* Master Config Register 3  */
+#define IMX9_LPI2C3_MDMR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MDMR_OFFSET)    /* Master Data Match Register  */
+#define IMX9_LPI2C3_MCCR0                  (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MCCR0_OFFSET)   /* Master Clock Configuration Register 0  */
+#define IMX9_LPI2C3_MCCR1                  (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MCCR1_OFFSET)   /* Master Clock Configuration Register 1  */
+#define IMX9_LPI2C3_MFCR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MFCR_OFFSET)    /* Master FIFO Control Register  */
+#define IMX9_LPI2C3_MFSR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MFSR_OFFSET)    /* Master FIFO Status Register  */
+#define IMX9_LPI2C3_MTDR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MTDR_OFFSET)    /* Master Transmit Data Register  */
+#define IMX9_LPI2C3_MRDR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_MRDR_OFFSET)    /* Master Receive Data Register  */
+#define IMX9_LPI2C3_SCR                    (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SCR_OFFSET)     /* Slave Control Register  */
+#define IMX9_LPI2C3_SSR                    (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SSR_OFFSET)     /* Slave Status Register  */
+#define IMX9_LPI2C3_SIER                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SIER_OFFSET)    /* Slave Interrupt Enable Register  */
+#define IMX9_LPI2C3_SDER                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SDER_OFFSET)    /* Slave DMA Enable Register  */
+#define IMX9_LPI2C3_SCFGR1                 (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SCFGR1_OFFSET)  /* Slave Config Register 1  */
+#define IMX9_LPI2C3_SCFGR2                 (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SCFGR2_OFFSET)  /* Slave Config Register 2  */
+#define IMX9_LPI2C3_SAMR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SAMR_OFFSET)    /* Slave Address Match Register  */
+#define IMX9_LPI2C3_SASR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SASR_OFFSET)    /* Slave Address Status Register  */
+#define IMX9_LPI2C3_STAR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_STAR_OFFSET)    /* Slave Transmit ACK Register  */
+#define IMX9_LPI2C3_STDR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_STDR_OFFSET)    /* Slave Transmit Data Register  */
+#define IMX9_LPI2C3_SRDR                   (IMX9_LPI2C3_BASE + 
IMX9_LPI2C_SRDR_OFFSET)    /* Slave Receive Data Register  */
+
+/* LPI2C4 Registers */
+
+#define IMX9_LPI2C4_VERID                  (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_VERID_OFFSET)   /* Version ID Register */
+#define IMX9_LPI2C4_PARAM                  (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_PARAM_OFFSET)   /* Parameter Register  */
+#define IMX9_LPI2C4_MCR                    (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MCR_OFFSET)     /* Master Control Register  */
+#define IMX9_LPI2C4_MSR                    (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MSR_OFFSET)     /* Master Status Register  */
+#define IMX9_LPI2C4_MIER                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MIER_OFFSET)    /* Master Interrupt Enable Register  */
+#define IMX9_LPI2C4_MDER                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MDER_OFFSET)    /* Master DMA Enable Register  */
+#define IMX9_LPI2C4_MCFGR0                 (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MCFGR0_OFFSET)  /* Master Config Register 0  */
+#define IMX9_LPI2C4_MCFGR1                 (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MCFGR1_OFFSET)  /* Master Config Register 1  */
+#define IMX9_LPI2C4_MCFGR2                 (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MCFGR2_OFFSET)  /* Master Config Register 2  */
+#define IMX9_LPI2C4_MCFGR3                 (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MCFGR3_OFFSET)  /* Master Config Register 3  */
+#define IMX9_LPI2C4_MDMR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MDMR_OFFSET)    /* Master Data Match Register  */
+#define IMX9_LPI2C4_MCCR0                  (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MCCR0_OFFSET)   /* Master Clock Configuration Register 0  */
+#define IMX9_LPI2C4_MCCR1                  (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MCCR1_OFFSET)   /* Master Clock Configuration Register 1  */
+#define IMX9_LPI2C4_MFCR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MFCR_OFFSET)    /* Master FIFO Control Register  */
+#define IMX9_LPI2C4_MFSR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MFSR_OFFSET)    /* Master FIFO Status Register  */
+#define IMX9_LPI2C4_MTDR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MTDR_OFFSET)    /* Master Transmit Data Register  */
+#define IMX9_LPI2C4_MRDR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_MRDR_OFFSET)    /* Master Receive Data Register  */
+#define IMX9_LPI2C4_SCR                    (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SCR_OFFSET)     /* Slave Control Register  */
+#define IMX9_LPI2C4_SSR                    (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SSR_OFFSET)     /* Slave Status Register  */
+#define IMX9_LPI2C4_SIER                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SIER_OFFSET)    /* Slave Interrupt Enable Register  */
+#define IMX9_LPI2C4_SDER                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SDER_OFFSET)    /* Slave DMA Enable Register  */
+#define IMX9_LPI2C4_SCFGR1                 (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SCFGR1_OFFSET)  /* Slave Config Register 1  */
+#define IMX9_LPI2C4_SCFGR2                 (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SCFGR2_OFFSET)  /* Slave Config Register 2  */
+#define IMX9_LPI2C4_SAMR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SAMR_OFFSET)    /* Slave Address Match Register  */
+#define IMX9_LPI2C4_SASR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SASR_OFFSET)    /* Slave Address Status Register  */
+#define IMX9_LPI2C4_STAR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_STAR_OFFSET)    /* Slave Transmit ACK Register  */
+#define IMX9_LPI2C4_STDR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_STDR_OFFSET)    /* Slave Transmit Data Register  */
+#define IMX9_LPI2C4_SRDR                   (IMX9_LPI2C4_BASE + 
IMX9_LPI2C_SRDR_OFFSET)    /* Slave Receive Data Register  */
+
+/* Register bit definitions *************************************************/
+
+/* LPI2C Version ID Register */
+
+#define LPI2C_VERID_FEATURE_SHIFT           (0)
+#define LPI2C_VERID_FEATURE_MASK            (0xffff << 
LPI2C_VERID_FEATURE_SHIFT)
+#define LPI2C_VERID_MINOR_SHIFT             (16)
+#define LPI2C_VERID_MINOR_MASK              (0xff << LPI2C_VERID_MINOR_SHIFT)
+#define LPI2C_VERID_MAJOR_SHIFT             (24)
+#define LPI2C_VERID_MAJOR_MASK              (0xff << LPI2C_VERID_MAJOR_SHIFT)
+
+/* LPI2C Parameter Register  */
+
+#define LPI2C_PARAM_MTXFIFO_MASK            (0x0f) /* Config number of words 
in master transmit fifo to 2^MTXFIFO (pow(2,MTXFIFO )) */
+#  define LPI2C_PARAM_MTXFIFO_1_WORDS       (0)
+#  define LPI2C_PARAM_MTXFIFO_2_WORDS       (1)
+#  define LPI2C_PARAM_MTXFIFO_4_WORDS       (2)
+#  define LPI2C_PARAM_MTXFIFO_8_WORDS       (3)
+#  define LPI2C_PARAM_MTXFIFO_16_WORDS      (4)
+#  define LPI2C_PARAM_MTXFIFO_32_WORDS      (5)
+#  define LPI2C_PARAM_MTXFIFO_64_WORDS      (6)
+#  define LPI2C_PARAM_MTXFIFO_128_WORDS     (7)
+#  define LPI2C_PARAM_MTXFIFO_256_WORDS     (8)
+#  define LPI2C_PARAM_MTXFIFO_512_WORDS     (9)
+#  define LPI2C_PARAM_MTXFIFO_1024_WORDS    (10)
+#  define LPI2C_PARAM_MTXFIFO_2048_WORDS    (11)
+#  define LPI2C_PARAM_MTXFIFO_4096_WORDS    (12)
+#  define LPI2C_PARAM_MTXFIFO_8192_WORDS    (13)
+#  define LPI2C_PARAM_MTXFIFO_16384_WORDS   (14)
+#  define LPI2C_PARAM_MTXFIFO_32768_WORDS   (15)
+
+#define LPI2C_PARAM_MRXFIFO_SHIFT           (8)
+#define LPI2C_PARAM_MRXFIFO_MASK            (0x0f << 
LPI2C_PARAM_MRXFIFO_SHIFT) /* Config number of words in master receive fifo 
2^MRXFIFO (pow(2,MTRFIFO )) */
+#  define LPI2C_PARAM_MRXFIFO_1_WORDS       (0 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_2_WORDS       (1 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_4_WORDS       (2 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_8_WORDS       (3 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_16_WORDS      (4 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_32_WORDS      (5 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_64_WORDS      (6 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_128_WORDS     (7 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_256_WORDS     (8 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_512_WORDS     (9 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_1024_WORDS    (10 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_2048_WORDS    (11 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_4096_WORDS    (12 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_8192_WORDS    (13 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_16384_WORDS   (14 << LPI2C_PARAM_MRXFIFO_SHIFT)
+#  define LPI2C_PARAM_MRXFIFO_32768_WORDS   (15 << LPI2C_PARAM_MRXFIFO_SHIFT)
+
+/* LPI2C Master Control Register  */
+
+#define LPI2C_MCR_MEN                       (1 << 0)  /* Master Enable Bit */
+#define LPI2C_MCR_RST                       (1 << 1)  /* Software Reset Bit */
+#define LPI2C_MCR_DOZEN                     (1 << 2)  /* Doze Mode Enable Bit 
*/
+#define LPI2C_MCR_DBGEN                     (1 << 3)  /* Debug Enable Bit */
+                                                      /* Bits 7-4 Reserved */
+#define LPI2C_MCR_RTF                       (1 << 8)  /* Reset Transmit FIFO 
Bit */
+#define LPI2C_MCR_RRF                       (1 << 9)  /* Reset Receive FIFO 
Bit */
+                                                      /* Bits 31-10 Reserved */
+
+/* LPI2C Master Status Register  */
+
+#define LPI2C_MSR_TDF                       (1 << 0)  /* Transmit Data Flag 
Bit */
+#define LPI2C_MSR_RDF                       (1 << 1)  /* Receive Data Flag Bit 
*/
+                                                      /* Bits 7-2 Reserved */
+#define LPI2C_MSR_EPF                       (1 << 8)  /* End Packet Flag Bit */
+#define LPI2C_MSR_SDF                       (1 << 9)  /* STOP Detect Flag Bit 
*/
+#define LPI2C_MSR_NDF                       (1 << 10) /* NACK Detect Flag Bit 
*/
+#define LPI2C_MSR_ALF                       (1 << 11) /* Arbitration Lost Flag 
Bit */
+#define LPI2C_MSR_FEF                       (1 << 12) /* FIFO Error Flag Bit */
+#define LPI2C_MSR_PLTF                      (1 << 13) /* Pin Low Timeout Flag 
Bit */
+#define LPI2C_MSR_DMF                       (1 << 14) /* Data Match Flag Bit */
+                                                      /* Bits 23-15 Reserved */
+#define LPI2C_MSR_MBF                       (1 << 24) /* Master Busy Flag Bit 
*/
+#define LPI2C_MSR_BBF                       (1 << 25) /* Bus Busy Flag Bit */
+                                                      /* Bits 31-26 Reserved */
+#define LPI2C_MSR_ERROR_MASK                (LPI2C_MSR_NDF | LPI2C_MSR_ALF | \
+                                             LPI2C_MSR_FEF)
+
+/* LPI2C Master Interrupt Enable Register  */
+
+#define LPI2C_MIER_TDIE                     (1 << 0)  /* Transmit Data 
Interrupt Enable Bit */
+#define LPI2C_MIER_RDIE                     (1 << 1)  /* Receive Data 
Interrupt Enable Bit */
+                                                      /* Bits 7-2 Reserved */
+#define LPI2C_MIER_EPIE                     (1 << 8)  /* End Packet Interrupt 
Enable Bit */
+#define LPI2C_MIER_SDIE                     (1 << 9)  /* STOP Detect Interrupt 
Enable Bit */
+#define LPI2C_MIER_NDIE                     (1 << 10) /* NACK Detect Interrupt 
Enable Bit */
+#define LPI2C_MIER_ALIE                     (1 << 11) /* Arbitration Lost 
Interrupt Enable Bit */
+#define LPI2C_MIER_FEIE                     (1 << 12) /* FIFO Error Interrupt 
Enable Bit */
+#define LPI2C_MIER_PLTIE                    (1 << 13) /* Pin Low Timeout 
Interrupt Enable Bit */
+#define LPI2C_MIER_DMIE                     (1 << 14) /* Data Match Interrupt 
Enable Bit */
+                                                      /* Bits 31-15 Reserved */
+
+/* LPI2C Master DMA Enable Register  */
+
+#define LPI2C_MDER_TDDE                     (1 << 0)  /* Transmit Data DMA 
Enable Bit */
+#define LPI2C_MDER_RDDE                     (1 << 1)  /* Transmit Data DMA 
Enable Bit */
+                                                      /* Bits 31-2 Reserved */
+
+/* LPI2C Master Config Register 0  */
+
+#define LPI2C_MCFG0_HREN                    (1 << 0)  /* Host Request Enable 
Bit */
+#define LPI2C_MCFG0_HRPOL                   (1 << 1)  /* Host Request Polarity 
Bit */
+#define LPI2C_MCFG0_HRSEL                   (1 << 2)  /* Host Request Select 
Bit */
+                                                      /* Bits 7-3 Reserved */
+#define LPI2C_MCFG0_CIRFIFO                 (1 << 8)  /* Circular FIFO Enable 
Bit */
+#define LPI2C_MCFG0_RDMO                    (1 << 9)  /* Receive Data Match 
Only Bit */
+                                                      /* Bits 31-10 Reserved */
+
+/* LPI2C Master Config Register 1  */
+
+#define LPI2C_MCFGR1_PRESCALE_MASK           (7 << 0)  /* Clock Prescaler Bit 
Mask */
+#define LPI2C_MCFGR1_PRESCALE(n)             ((n) & LPI2C_MCFGR1_PRESCALE_MASK)
+#  define LPI2C_MCFGR1_PRESCALE_1            (0)
+#  define LPI2C_MCFGR1_PRESCALE_2            (1)
+#  define LPI2C_MCFGR1_PRESCALE_4            (2)
+#  define LPI2C_MCFGR1_PRESCALE_8            (3)
+#  define LPI2C_MCFGR1_PRESCALE_16           (4)
+#  define LPI2C_MCFGR1_PRESCALE_32           (5)
+#  define LPI2C_MCFGR1_PRESCALE_64           (6)
+#  define LPI2C_MCFGR1_PRESCALE_128          (7)
+#define LPI2C_MCFGR1_AUTOSTOP                (1 << 8)  /* Automatic STOP 
Generation Bit */
+#define LPI2C_MCFGR1_IGNACK                  (1 << 9)  /* Ignore NACK Bit */
+#define LPI2C_MCFGR1_TIMECFG                 (1 << 10) /* Timeout 
Configuration Bit */
+                                                       /* Bits 15-11 Reserved 
*/
+#define LPI2C_MCFGR1_MATCFG_SHIFT            (16)
+#define LPI2C_MCFGR1_MATCFG_MASK             (7 << LPI2C_MCFGR1_MATCFG_SHIFT)  
/* Match Configuration Bit Mask */
+#define LPI2C_MCFGR1_MATCFG(n)               (((n) << 
LPI2C_MCFGR1_MATCFG_SHIFT) & LPI2C_MCFGR1_MATCFG_MASK)
+#  define LPI2C_MCFGR1_MATCFG_DISABLE        (0 << LPI2C_MCFGR1_MATCFG_SHIFT)
+                                                      /* LPI2C_MCFG1_MATCFG = 
001b Reserved */
+#  define LPI2C_MCFGR1_MATCFG2               (2 << LPI2C_MCFGR1_MATCFG_SHIFT)
+#  define LPI2C_MCFGR1_MATCFG3               (3 << LPI2C_MCFGR1_MATCFG_SHIFT)
+#  define LPI2C_MCFGR1_MATCFG4               (4 << LPI2C_MCFGR1_MATCFG_SHIFT)
+#  define LPI2C_MCFGR1_MATCFG5               (5 << LPI2C_MCFGR1_MATCFG_SHIFT)
+#  define LPI2C_MCFGR1_MATCFG6               (6 << LPI2C_MCFGR1_MATCFG_SHIFT)
+#  define LPI2C_MCFGR1_MATCFG7               (7 << LPI2C_MCFGR1_MATCFG_SHIFT)
+                                                     /* Bits 23-19 Reserved */
+#define LPI2C_MCFGR1_PINCFG_SHIFT            (24)
+#define LPI2C_MCFGR1_PINCFG_MASK             (7 << LPI2C_MCFGR1_PINCFG_SHIFT)  
/* Pin Configuration Bit Mask */
+#define LPI2C_MCFGR1_PINCFG(n)               (((n) << 
LPI2C_MCFGR1_PINCFG_SHIFT) & LPI2C_MCFGR1_PINCFG_MASK)
+#  define LPI2C_MCFGR1_PINCFG0               (0 << LPI2C_MCFGR1_PINCFG_SHIFT)
+#  define LPI2C_MCFGR1_PINCFG1               (1 << LPI2C_MCFGR1_PINCFG_SHIFT)
+#  define LPI2C_MCFGR1_PINCFG2               (2 << LPI2C_MCFGR1_PINCFG_SHIFT)
+#  define LPI2C_MCFGR1_PINCFG3               (3 << LPI2C_MCFGR1_PINCFG_SHIFT)
+#  define LPI2C_MCFGR1_PINCFG4               (4 << LPI2C_MCFGR1_PINCFG_SHIFT)
+#  define LPI2C_MCFGR1_PINCFG5               (5 << LPI2C_MCFGR1_PINCFG_SHIFT)
+#  define LPI2C_MCFGR1_PINCFG6               (6 << LPI2C_MCFGR1_PINCFG_SHIFT)
+#  define LPI2C_MCFGR1_PINCFG7               (7 << LPI2C_MCFGR1_PINCFG_SHIFT)
+                                                     /* Bits 31-27 Reserved */
+
+/* LPI2C Master Config Register 2  */
+
+#define LPI2C_MCFG2_BUSIDLE_MASK            (0xfff << 0)  /* Bus Idle Timeout 
Period in Clock Cycles */
+#define LPI2C_MCFG2_BUSIDLE_DISABLE         (0)
+#define LPI2C_MCFG2_BUSIDLE(n)              ((n) & LPI2C_MCFG2_BUSIDLE_MASK)
+                                                     /* Bits 15-12 Reserved */
+#define LPI2C_MCFG2_FILTSCL_SHIFT           (16)
+#define LPI2C_MCFG2_FILTSCL_MASK            (15 << LPI2C_MCFG2_FILTSCL_SHIFT)  
/* Glitch Filter SCL */
+#define LPI2C_MCFG2_FILTSCL_DISABLE         (0 << LPI2C_MCFG2_FILTSCL_SHIFT)
+#define LPI2C_MCFG2_FILTSCL_CYCLES(n)       (((n) << 
LPI2C_MCFG2_FILTSCL_SHIFT) & LPI2C_MCFG2_FILTSCL_MASK)
+                                                     /* Bits 23-20 Reserved */
+#define LPI2C_MCFG2_FILTSDA_SHIFT           (24)
+#define LPI2C_MCFG2_FILTSDA_MASK            (15 << LPI2C_MCFG2_FILTSDA_SHIFT)  
/* Glitch Filter SDA */
+#define LPI2C_MCFG2_FILTSDA_DISABLE         (0 << LPI2C_MCFG2_FILTSDA_SHIFT)
+#define LPI2C_MCFG2_FILTSDA_CYCLES(n)       (((n) << 
LPI2C_MCFG2_FILTSDA_SHIFT) & LPI2C_MCFG2_FILTSDA_MASK)
+                                                     /* Bits 31-28 Reserved */
+
+/* LPI2C Master Config Register 3  */
+
+                                                     /* Bits 7-0 Reserved */
+#define LPI2C_MCFG3_PINLOW_SHIFT            (8)
+#define LPI2C_MCFG3_PINLOW_MASK             (0xfff << 
LPI2C_MCFG3_PINLOW_SHIFT)  /* Configure The Pin Low Timeout in Clock Cycles */
+#define LPI2C_MCFG3_PINLOW_CYCLES(n)        (((n) << LPI2C_MCFG3_PINLOW_SHIFT) 
& LPI2C_MCFG3_PINLOW_MASK)
+                                                     /* Bits 31-20 Reserved */
+
+/* LPI2C Master Data Match Register  */
+
+#define LPI2C_MDMR_MATCH0_SHIFT             (0)
+#define LPI2C_MDMR_MATCH0_MASK              (0xff << LPI2C_MDMR_MATCH0_SHIFT)  
/* Match 0 Value */
+#define LPI2C_MDMR_MATCH0(n)                (((n) << LPI2C_MDMR_MATCH0_SHIFT) 
& LPI2C_MDMR_MATCH0_MASK)
+                                                     /* Bits 15-8 Reserved */
+#define LPI2C_MDMR_MATCH1_SHIFT             (16)
+#define LPI2C_MDMR_MATCH1_MASK              (0xff << LPI2C_MDMR_MATCH1_SHIFT)  
/* Match 1 Value */
+#define LPI2C_MDMR_MATCH1(n)                (((n) << LPI2C_MDMR_MATCH1_SHIFT) 
& LPI2C_MDMR_MATCH1_MASK)
+                                                     /* Bits 31-24 Reserved */
+
+/* LPI2C Master Clock Configuration Register 0 */
+
+#define LPI2C_MCCR0_CLKLO_SHIFT             (0)
+#define LPI2C_MCCR0_CLKLO_MASK              (0x3f << LPI2C_MCCR0_CLKLO_SHIFT)  
/* Clock Low Period */
+#define LPI2C_MCCR0_CLKLO(n)                (((n) << LPI2C_MCCR0_CLKLO_SHIFT) 
& LPI2C_MCCR0_CLKLO_MASK)
+                                                     /* Bits 7-6 Reserved */
+#define LPI2C_MCCR0_CLKHI_SHIFT             (8)
+#define LPI2C_MCCR0_CLKHI_MASK              (0x3f << LPI2C_MCCR0_CLKHI_SHIFT)  
/* Clock High Period */
+#define LPI2C_MCCR0_CLKHI(n)                (((n) << LPI2C_MCCR0_CLKHI_SHIFT) 
& LPI2C_MCCR0_CLKHI_MASK)
+                                                     /* Bits 15-14 Reserved */
+#define LPI2C_MCCR0_SETHOLD_SHIFT           (16)
+#define LPI2C_MCCR0_SETHOLD_MASK            (0x3f << 
LPI2C_MCCR0_SETHOLD_SHIFT)  /* Setup Hold Delay */
+#define LPI2C_MCCR0_SETHOLD(n)              (((n) << 
LPI2C_MCCR0_SETHOLD_SHIFT) & LPI2C_MCCR0_SETHOLD_MASK)
+                                                     /* Bits 23-22 Reserved */
+#define LPI2C_MCCR0_DATAVD_SHIFT            (24)
+#define LPI2C_MCCR0_DATAVD_MASK             (0x3f << LPI2C_MCCR0_DATAVD_SHIFT) 
 /* Setup Hold Delay */
+#define LPI2C_MCCR0_DATAVD(n)               (((n) << LPI2C_MCCR0_DATAVD_SHIFT) 
& LPI2C_MCCR0_DATAVD_MASK)
+                                                     /* Bits 31-30 Reserved */
+
+/* LPI2C Master Clock Configuration Register 1 */
+
+#define LPI2C_MCCR1_CLKLO_SHIFT             (0)
+#define LPI2C_MCCR1_CLKLO_MASK              (0x3f << LPI2C_MCCR1_CLKLO_SHIFT)  
/* Clock Low Period */
+#define LPI2C_MCCR1_CLKLO(n)                (((n) << LPI2C_MCCR1_CLKLO_SHIFT) 
& LPI2C_MCCR1_CLKLO_MASK)
+                                                     /* Bits 7-6 Reserved */
+#define LPI2C_MCCR1_CLKHI_SHIFT             (8)
+#define LPI2C_MCCR1_CLKHI_MASK              (0x3f << LPI2C_MCCR1_CLKHI_SHIFT)  
/* Clock High Period */
+#define LPI2C_MCCR1_CLKHI(n)                (((n) << LPI2C_MCCR1_CLKHI_SHIFT) 
& LPI2C_MCCR1_CLKHI_MASK)
+                                                     /* Bits 15-14 Reserved */
+#define LPI2C_MCCR1_SETHOLD_SHIFT           (16)
+#define LPI2C_MCCR1_SETHOLD_MASK            (0x3f << 
LPI2C_MCCR1_SETHOLD_SHIFT)  /* Setup Hold Delay */
+#define LPI2C_MCCR1_SETHOLD(n)              (((n) << 
LPI2C_MCCR1_SETHOLD_SHIFT) & LPI2C_MCCR1_SETHOLD_MASK)
+
+                                                     /* Bits 23-22 Reserved */
+#define LPI2C_MCCR1_DATAVD_SHIFT            (24)
+#define LPI2C_MCCR1_DATAVD_MASK             (0x3f << LPI2C_MCCR1_DATAVD_SHIFT) 
 /* Setup Hold Delay */
+#define LPI2C_MCCR1_DATAVD(n)               (((n) << LPI2C_MCCR1_DATAVD_SHIFT) 
& LPI2C_MCCR1_DATAVD_MASK)
+
+                                                     /* Bits 31-30 Reserved */
+
+/* LPI2C Master FIFO Control Register */
+
+#define LPI2C_MFCR_TXWATER_SHIFT            (0)
+#define LPI2C_MFCR_TXWATER_MASK             (3 << LPI2C_MFCR_TXWATER_SHIFT)  
/* Transmit FIFO Watermark*/
+
+#define LPI2C_MFCR_TXWATER(n)               (((n) << LPI2C_MFCR_TXWATER_SHIFT) 
&  LPI2C_MFCR_TXWATER_MASK)  /* Transmit FIFO Watermark */
+
+                                                     /* Bits 15-2 Reserved */
+#define LPI2C_MFCR_RXWATER_SHIFT            (16)
+#define LPI2C_MFCR_RXWATER_MASK             (3 << LPI2C_MFCR_RXWATER_SHIFT)  
/* Receive FIFO Watermark */
+
+#define LPI2C_MFCR_RXWATER(n)               (((n) << LPI2C_MFCR_RXWATER_SHIFT) 
&  LPI2C_MFCR_RXWATER_MASK)  /* Transmit FIFO Watermark */
+
+                                                     /* Bits 31-18 Reserved */
+
+/* LPI2C Master FIFO Status Register */
+
+#define LPI2C_MFSR_TXCOUNT_SHIFT            (0)
+#define LPI2C_MFSR_TXCOUNT_MASK             (3 << LPI2C_MFSR_TXCOUNT_SHIFT)  
/* Transmit FIFO Count */
+
+                                                     /* Bits 15-2 Reserved */
+#define LPI2C_MFSR_RXCOUNT_SHIFT            (16)
+#define LPI2C_MFSR_RXCOUNT_MASK             (3 << LPI2C_MFSR_RXCOUNT_SHIFT)  
/* Receive FIFO Count */
+
+                                                     /* Bits 31-18 Reserved */
+
+/* LPI2C Master Transmit Data Register */
+
+#define LPI2C_MTDR_DATA_SHIFT               (0)
+#define LPI2C_MTDR_DATA_MASK                (0xff << LPI2C_MTDR_DATA_SHIFT)  
/* Transmit Data */
+#define LPI2C_MTDR_DATA(n)                  ((n) & LPI2C_MTDR_DATA_MASK)
+#define LPI2C_MTDR_CMD_SHIFT                (8)
+#define LPI2C_MTDR_CMD_MASK                 (7 << LPI2C_MTDR_CMD_SHIFT)  /* 
Command Data */
+#define LPI2C_MTDR_CMD(n)                   (((n) << LPI2C_MTDR_CMD_SHIFT) & 
LPI2C_MTDR_CMD_MASK)
+#  define LPI2C_MTDR_CMD_TXD                (0 << LPI2C_MTDR_CMD_SHIFT)
+#  define LPI2C_MTDR_CMD_RXD                (1 << LPI2C_MTDR_CMD_SHIFT)
+#  define LPI2C_MTDR_CMD_STOP               (2 << LPI2C_MTDR_CMD_SHIFT)
+#  define LPI2C_MTDR_CMD_RXD_DISC           (3 << LPI2C_MTDR_CMD_SHIFT)
+#  define LPI2C_MTDR_CMD_START              (4 << LPI2C_MTDR_CMD_SHIFT)
+#  define LPI2C_MTDR_CMD_START_NACK         (5 << LPI2C_MTDR_CMD_SHIFT)
+#  define LPI2C_MTDR_CMD_START_HI           (6 << LPI2C_MTDR_CMD_SHIFT)
+#  define LPI2C_MTDR_CMD_START_HI_NACK      (7 << LPI2C_MTDR_CMD_SHIFT)
+
+                                                     /* Bits 31-11 Reserved */
+
+/* LPI2C Master Receive Data Register */
+
+#define LPI2C_MRDR_DATA_SHIFT               (0)
+#define LPI2C_MRDR_DATA_MASK                (0xff << LPI2C_MRDR_DATA_SHIFT)  
/* Receive Data */
+
+                                                     /* Bits 13-8 Reserved */
+#define LPI2C_MRDR_RXEMPTY_SHIFT            (14)
+#define LPI2C_MRDR_RXEMPTY_MASK             (1 << LPI2C_MRDR_RXEMPTY_SHIFT)  
/* Rx Empty */
+
+                                                     /* Bits 31-15 Reserved */
+
+/* LPI2C Slave Control Register */
+
+#define LPI2C_SCR_SEN                       (1 << 0)  /* Slave Enable Bit */
+#define LPI2C_SCR_RST                       (1 << 1)  /* Software Reset Bit */
+                                                      /* Bits 3-2 Reserved */
+#define LPI2C_SCR_FILTEN                    (1 << 4)  /* Filter Enable Bit */
+#define LPI2C_SCR_FILTDZ                    (1 << 5)  /* Filter Doze Enable 
Bit */
+                                                      /* Bits 7-4 Reserved */
+#define LPI2C_SCR_RTF                       (1 << 8)  /* Reset Transmit FIFO 
Bit */
+#define LPI2C_SCR_RRF                       (1 << 9)  /* Reset Receive FIFO 
Bit */
+                                                      /* Bits 31-10 Reserved */
+
+/* LPI2C Slave Status Register  */
+
+#define LPI2C_SSR_TDF                       (1 << 0)  /* Transmit Data Flag 
Bit */
+#define LPI2C_SSR_RDF                       (1 << 1)  /* Receive Data Flag Bit 
*/
+#define LPI2C_SSR_AVF                       (1 << 2)  /* Address Valid Flag 
Bit */
+#define LPI2C_SSR_TAF                       (1 << 3)  /* Transmit ACK Flag Bit 
*/
+                                                      /* Bits 7-4 Reserved */
+#define LPI2C_SSR_RSF                       (1 << 8)  /* Repeated Start Flag 
Bit */
+#define LPI2C_SSR_SDF                       (1 << 9)  /* STOP Detect Flag Bit 
*/
+#define LPI2C_SSR_BEF                       (1 << 10) /* Bit Error Flag Bit */
+#define LPI2C_SSR_FEF                       (1 << 11) /* FIFO Error Flag Bit */
+#define LPI2C_SSR_AM0F                      (1 << 12) /* Address Match 0 Flag 
Bit */
+#define LPI2C_SSR_AM1F                      (1 << 13) /* Address Match 1 Flag 
Bit */
+#define LPI2C_SSR_GCF                       (1 << 14) /* General Call Flag Bit 
*/
+#define LPI2C_SSR_SARF                      (1 << 15) /* SMBus Alert Response 
Flag Bit */
+                                                      /* Bits 23-16 Reserved */
+#define LPI2C_MSR_SBF                       (1 << 24) /* Slave Busy Flag Bit */
+#define LPI2C_MSR_BBF                       (1 << 25) /* Bus Busy Flag Bit */
+                                                      /* Bits 31-26 Reserved */
+
+/* LPI2C Slave Interrupt Enable Register  */
+
+#define LPI2C_SIER_TDIE                     (1 << 0)  /* Transmit Data 
Interrupt Enable Bit */
+#define LPI2C_SIER_RDIE                     (1 << 1)  /* Receive Data 
Interrupt Enable Bit */
+#define LPI2C_SIER_AVIE                     (1 << 2)  /* Address Valid 
Interrupt Enable Bit */
+#define LPI2C_SIER_TAIE                     (1 << 3)  /* Transmit ACK 
Interrupt Enable Bit */
+                                                      /* Bits 7-4 Reserved */
+#define LPI2C_SIER_RSIE                     (1 << 8)  /* Repeated Start 
Interrupt Enable Bit */
+#define LPI2C_SIER_SDIE                     (1 << 9)  /* STOP Detect Interrupt 
Enable Bit */
+#define LPI2C_SIER_BEIE                     (1 << 10) /* Bit Error Interrupt 
Enable Bit */
+#define LPI2C_SIER_FEIE                     (1 << 11) /* FIFO Error Interrupt 
Enable Bit */
+#define LPI2C_SIER_AM0IE                    (1 << 12) /* Address Match 0 
Interrupt Enable Bit */
+#define LPI2C_SIER_AM1IE                    (1 << 13) /* Address Match 1 
Interrupt Enable Bit */
+#define LPI2C_SIER_GCIE                     (1 << 14) /* General Call 
Interrupt Enable Bit */
+#define LPI2C_SIER_SARIE                    (1 << 15) /* SMBus Alert Response 
Interrupt Enable Bit */
+                                                      /* Bits 31-16 Reserved */
+
+/* LPI2C Slave DMA Enable Register  */
+
+#define LPI2C_SDER_TDDE                     (1 << 0)  /* Transmit Data DMA 
Enable Bit */
+#define LPI2C_SDER_RDDE                     (1 << 1)  /* Transmit Data DMA 
Enable Bit */
+#define LPI2C_SDER_AVDE                     (1 << 2)  /* Address Valid DMA 
Enable Bit */
+                                                      /* Bits 31-3 Reserved */
+
+/* LPI2C Slave Configuration Register 1  */
+
+#define LPI2C_SCFGR1_ADRSTALL               (1 << 0)  /* Address SCL Stall */
+#define LPI2C_SCFGR1_RXSTALL                (1 << 1)  /* RX SCL Stall */
+#define LPI2C_SCFGR1_TXSTALL                (1 << 2)  /* TX Data SCL Stall */
+#define LPI2C_SCFGR1_ACKSTALL               (1 << 3)  /* ACK SCL Stall */
+                                                      /* Bits 7-4 Reserved */
+#define LPI2C_SCFGR1_GCEN                   (1 << 8)  /* General Call Enable */
+#define LPI2C_SCFGR1_SAEN                   (1 << 9)  /* SMBus Alert Enable */
+#define LPI2C_SCFGR1_TXCFG                  (1 << 10) /* Transmit Flag 
Configuration */
+#define LPI2C_SCFGR1_RXCFG                  (1 << 11) /* Receive Data 
Configuration */
+#define LPI2C_SCFGR1_IFNACK                 (1 << 12) /* Ignore NACK */
+#define LPI2C_SCFGR1_HSMEN                  (1 << 13) /* High Speed Mode 
Enable */
+                                                      /* Bits 15-14 Reserved */
+#define LPI2C_SCFG1_ADDRCFG_SHIFT           (16)
+#define LPI2C_SCFG1_ADDRCFG_MASK            (7 << LPI2C_SCFG1_ADDRCFG_SHIFT)  
/* Address Configuration Bit Mask */
+#define LPI2C_SCFG1_ADDRCFG(n)              (((n) << 
LPI2C_SCFG1_ADDRCFG_SHIFT) & LPI2C_SCFG1_ADDRCFG_MASK)
+#  define LPI2C_SCFG1_ADDRCFG0              (0 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+#  define LPI2C_SCFG1_ADDRCFG1              (2 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+#  define LPI2C_SCFG1_ADDRCFG2              (2 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+#  define LPI2C_SCFG1_ADDRCFG3              (3 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+#  define LPI2C_SCFG1_ADDRCFG4              (4 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+#  define LPI2C_SCFG1_ADDRCFG5              (5 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+#  define LPI2C_SCFG1_ADDRCFG6              (6 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+#  define LPI2C_SCFG1_ADDRCFG7              (7 << LPI2C_SCFG1_ADDRCFG_SHIFT)
+                                                      /* Bits 31-19 Reserved */
+
+/* LPI2C Slave Configuration Register 2  */
+
+#define LPI2C_SCFG2_CLKHOLD_MASK            (15 << 0) /* Clock Hold Time */
+#define LPI2C_SCFG2_CLKHOLD(n)              ((n) & LPI2C_SCFG2_CLKHOLD_MASK)
+                                                      /* Bits 7-4 Reserved */
+#define LPI2C_SCFG2_DATAVD_SHIFT            (8)
+#define LPI2C_SCFG2_DATAVD_MASK             (0x3f << LPI2C_SCFG2_DATAVD_SHIFT) 
 /* Data Valid Delay */
+#define LPI2C_SCFG2_DATAVD(n)               (((n) << LPI2C_SCFG2_DATAVD_SHIFT) 
& LPI2C_SCFG2_DATAVD_MASK)
+                                                      /* Bits 15-14 Reserved */
+#define LPI2C_SCFG2_FILTSCL_SHIFT           (16)
+#define LPI2C_SCFG2_FILTSCL_MASK            (15 << LPI2C_SCFG2_FILTSCL_SHIFT)  
/* Glitch Filter SCL */
+#define LPI2C_SCFG2_FILTSCL_DISABLE         (0 << LPI2C_SCFG2_FILTSCL_SHIFT)
+#define LPI2C_SCFG2_FILTSCL_CYCLES(n)       (((n) << 
LPI2C_SCFG2_FILTSCL_SHIFT) & LPI2C_SCFG2_FILTSCL_MASK)
+                                                      /* Bits 23-20 Reserved */
+#define LPI2C_SCFG2_FILTSDA_SHIFT           (24)
+#define LPI2C_SCFG2_FILTSDA_MASK            (15 << LPI2C_SCFG2_FILTSDA_SHIFT)  
/* Glitch Filter SDA */
+#define LPI2C_SCFG2_FILTSDA_DISABLE         (0 << LPI2C_SCFG2_FILTSDA_SHIFT)
+#define LPI2C_SCFG2_FILTSDA_CYCLES(n)       (((n) << 
LPI2C_SCFG2_FILTSDA_SHIFT) & LPI2C_SCFG2_FILTSDA_MASK)
+                                                      /* Bits 31-28 Reserved */
+
+/* LPI2C Slave Address Match Register  */
+
+                                                      /* Bit 0 Reserved */
+#define LPI2C_SAMR_ADDR0_SHIFT              (1)
+#define LPI2C_SAMR_ADDR0_MASK               (0x3ff << LPI2C_SAMR_ADDR0_SHIFT)  
/* Address 0 Value */
+#define LPI2C_SAMR_ADDR0(n)                 (((n) << LPI2C_SAMR_ADDR0_SHIFT) & 
LPI2C_SAMR_ADDR0_MASK)
+                                                      /* Bits 16-11 Reserved */
+#define LPI2C_SAMR_ADDR1_SHIFT              (17)
+#define LPI2C_SAMR_ADDR1_MASK               (0x3ff << LPI2C_SAMR_ADDR1_SHIFT)  
/* Address 1 Value */
+#define LPI2C_SAMR_ADDR1(n)                 (((n) << LPI2C_SAMR_ADDR1_SHIFT) & 
LPI2C_SAMR_ADDR1_MASK)
+                                                      /* Bits 31-27 Reserved */
+
+/* LPI2C Slave Address Status Register  */
+
+#define LPI2C_SASR_RADDR_MASK               (0x7ff << 0) /* Received Address */
+
+/*                                                       Bits 16-11
+ *                                                       Reserved
+ */
+
+#define LPI2C_SASR_ANV                      (1 << 14) /* Address Not Valid */
+                                                      /* Bits 31-15 Reserved */
+
+/* LPI2C Slave Transmit ACK Register  */
+
+#define LPI2C_STAR_TXNACK                   (1 << 0)  /* Transmit NACK */
+                                                      /* Bits 31-1 Reserved */
+
+/* LPI2C Slave Transmit Data Register  */
+
+#define LPI2C_STDR_DATA_SHIFT               (0)
+#define LPI2C_STDR_DATA_MASK                (0xff << LPI2C_STDR_DATA_SHIFT)  
/* Transmit Data */
+#define LPI2C_STDR_DATA(n)                  (((n) << LPI2C_STDR_DATA_SHIFT) & 
LPI2C_STDR_DATA_MASK)
+                                                      /* Bits 31-8 Reserved */
+
+/* LPI2C Slave Receive Data Register  */
+
+#define LPI2C_SRDR_DATA_SHIFT               (0)
+#define LPI2C_SRDR_DATA_MASK                (0xff << LPI2C_SRDR_DATA_SHIFT)  
/* Receive Data */
+#define LPI2C_SRDR_DATA(n)                  (((n) << LPI2C_SRDR_DATA_SHIFT) & 
LPI2C_SRDR_DATA_MASK)
+                                                      /* Bits 13-8 Reserved */
+#define LPI2C_STAR_SOF                      (1 << 14) /* RX Empty */
+#define LPI2C_STAR_RXEMPTY                  (1 << 15) /* Start Of Frame */
+                                                      /* Bits 31-16 Reserved */
+
+#endif /* __ARCH_ARM64_SRC_IMX9_HARDWARE_IMX9_LPI2C_H_ */
diff --git a/arch/arm64/src/imx9/imx9_lpi2c.c b/arch/arm64/src/imx9/imx9_lpi2c.c
new file mode 100644
index 0000000000..c1122b1ddc
--- /dev/null
+++ b/arch/arm64/src/imx9/imx9_lpi2c.c
@@ -0,0 +1,2579 @@
+/****************************************************************************
+ * arch/arm64/src/imx9/imx9_lpi2c.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/board/board.h>
+
+#include "arm64_internal.h"
+#include "imx9_ccm.h"
+#include "imx9_clockconfig.h"
+#include "imx9_gpio.h"
+#include "imx9_iomuxc.h"
+#include "imx9_lpi2c.h"
+
+#include "hardware/imx9_ccm.h"
+#include "hardware/imx9_pinmux.h"
+#include "hardware/imx9_lpi2c.h"
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+#  include "chip.h"
+#  include "imx9_edma.h"
+#  include "hardware/imx9_dmamux.h"
+#endif
+
+/* At least one I2C peripheral must be enabled */
+
+#ifdef CONFIG_IMX9_LPI2C
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Configuration ************************************************************/
+
+/* CONFIG_I2C_POLLED may be set so that I2C interrupts will not be used.
+ * Instead, CPU-intensive polling will be used.
+ */
+
+/* Interrupt wait timeout in seconds and milliseconds */
+
+#if !defined(CONFIG_IMX9_LPI2C_TIMEOSEC) && \
+    !defined(CONFIG_IMX9_LPI2C_TIMEOMS)
+#  define CONFIG_IMX9_LPI2C_TIMEOSEC 0
+#  define CONFIG_IMX9_LPI2C_TIMEOMS  500   /* Default is 500 milliseconds */
+#elif !defined(CONFIG_IMX9_LPI2C_TIMEOSEC)
+#  define CONFIG_IMX9_LPI2C_TIMEOSEC 0     /* User provided milliseconds */
+#elif !defined(CONFIG_IMX9_LPI2C_TIMEOMS)
+#  define CONFIG_IMX9_LPI2C_TIMEOMS  0     /* User provided seconds */
+#endif
+
+/* Interrupt wait time timeout in system timer ticks */
+
+#ifndef CONFIG_IMX9_LPI2C_TIMEOTICKS
+#  define CONFIG_IMX9_LPI2C_TIMEOTICKS \
+     (SEC2TICK(CONFIG_IMX9_LPI2C_TIMEOSEC) + \
+      MSEC2TICK(CONFIG_IMX9_LPI2C_TIMEOMS))
+#endif
+
+#ifndef CONFIG_IMX9_LPI2C_DYNTIMEO_STARTSTOP
+#  define CONFIG_IMX9_LPI2C_DYNTIMEO_STARTSTOP \
+     TICK2USEC(CONFIG_IMX9_LPI2C_TIMEOTICKS)
+#endif
+
+/* Debug ********************************************************************/
+
+/* I2C event trace logic.  NOTE:  trace uses the internal, non-standard,
+ * low-level debug interface syslog() but does not require that any other
+ * debug is enabled.
+ */
+
+#ifndef CONFIG_I2C_TRACE
+#  define imx9_lpi2c_tracereset(p)
+#  define imx9_lpi2c_tracenew(p,s)
+#  define imx9_lpi2c_traceevent(p,e,a)
+#  define imx9_lpi2c_tracedump(p)
+#endif
+
+#ifndef CONFIG_I2C_NTRACE
+#  define CONFIG_I2C_NTRACE 32
+#endif
+
+#ifdef CONFIG_I2C_SLAVE
+#  error I2C slave logic is not supported yet for IMX9
+#endif
+
+#define LPI2C_MASTER    1
+#define LPI2C_SLAVE     2
+
+#define LPI2C_MSR_LIMITED_ERROR_MASK (LPI2C_MSR_ERROR_MASK & ~(LPI2C_MSR_FEF))
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/* Interrupt state */
+
+enum imx9_intstate_e
+{
+  INTSTATE_IDLE = 0,      /* No I2C activity */
+  INTSTATE_WAITING,       /* Waiting for completion of interrupt activity */
+  INTSTATE_DONE,          /* Interrupt activity complete */
+};
+
+/* Trace events */
+
+enum imx9_trace_e
+{
+  I2CEVENT_NONE = 0,      /* No events have occurred with this status */
+  I2CEVENT_SENDADDR,      /* Start/Master bit set and address sent, param = 
msgc */
+  I2CEVENT_SENDBYTE,      /* Send byte, param = dcnt */
+  I2CEVENT_RCVBYTE,       /* Read more dta, param = dcnt */
+  I2CEVENT_NOSTART,       /* BTF on last byte with no restart, param = msgc */
+  I2CEVENT_STARTRESTART,  /* Last byte sent, re-starting, param = msgc */
+  I2CEVENT_STOP,          /* Last byte sten, send stop, param = 0 */
+  I2CEVENT_ERROR          /* Error occurred, param = 0 */
+};
+
+/* Trace data */
+
+struct imx9_trace_s
+{
+  uint32_t status;             /* I2C 32-bit SR2|SR1 status */
+  uint32_t count;              /* Interrupt count when status change */
+  enum imx9_intstate_e event;  /* Last event that occurred with this status */
+  uint32_t parm;               /* Parameter associated with the event */
+  clock_t time;                /* First of event or first status */
+};
+
+/* I2C Device hardware configuration */
+
+struct imx9_lpi2c_config_s
+{
+  uint32_t base;               /* LPI2C base address */
+  uint8_t clk_root;            /* LPI2C clock root */
+  uint8_t clk_gate;            /* LPI2C clock gate */
+  uint16_t busy_idle;          /* LPI2C Bus Idle Timeout */
+  uint8_t filtscl;             /* Glitch Filter for SCL pin */
+  uint8_t filtsda;             /* Glitch Filter for SDA pin */
+  iomux_cfg_t scl_pin;         /* Peripheral configuration for SCL as SCL */
+  iomux_cfg_t sda_pin;         /* Peripheral configuration for SDA as SDA */
+#if defined(CONFIG_I2C_RESET)
+  gpio_pinset_t reset_scl_pin; /* GPIO configuration for SCL as GPIO */
+  gpio_pinset_t reset_sda_pin; /* GPIO configuration for SDA as GPIO */
+#endif
+  uint8_t mode;                /* Master or Slave mode */
+#ifndef CONFIG_I2C_POLLED
+  uint32_t irq;                /* Event IRQ */
+#endif
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  uint32_t dma_rxreqsrc;       /* DMA mux rx source */
+  uint32_t dma_txreqsrc;       /* DMA mux tx source */
+#endif
+};
+
+/* I2C Device Private Data */
+
+struct imx9_lpi2c_priv_s
+{
+  /* Standard I2C operations */
+
+  const struct i2c_ops_s *ops;
+
+  /* Port configuration */
+
+  const struct imx9_lpi2c_config_s *config;
+
+  int refs;                    /* Reference count */
+  mutex_t lock;                /* Mutual exclusion mutex */
+#ifndef CONFIG_I2C_POLLED
+  sem_t sem_isr;               /* Interrupt wait semaphore */
+#endif
+  volatile uint8_t intstate;   /* Interrupt handshake (see enum 
imx9_intstate_e) */
+
+  uint8_t msgc;                /* Message count */
+  struct i2c_msg_s *msgv;      /* Message list */
+  uint8_t *ptr;                /* Current message buffer */
+  uint32_t frequency;          /* Current I2C frequency */
+  int dcnt;                    /* Current message length */
+  uint16_t flags;              /* Current message flags */
+
+  /* I2C trace support */
+
+#ifdef CONFIG_I2C_TRACE
+  int tndx;                    /* Trace array index */
+  clock_t start_time;          /* Time when the trace was started */
+
+  /* The actual trace data */
+
+  struct imx9_trace_s trace[CONFIG_I2C_NTRACE];
+#endif
+
+  uint32_t status;             /* End of transfer SR2|SR1 status */
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  DMACH_HANDLE rxdma;                               /* rx DMA handle */
+  DMACH_HANDLE txdma;                               /* tx DMA handle */
+  uint16_t     cmnds[CONFIG_IMX9_LPI2C_DMA_MAXMSG]; /* Commands */
+#endif
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+static inline uint32_t
+imx9_lpi2c_getreg(struct imx9_lpi2c_priv_s *priv, uint16_t offset);
+static inline void imx9_lpi2c_putreg(struct imx9_lpi2c_priv_s *priv,
+                                     uint16_t offset, uint32_t value);
+static inline void imx9_lpi2c_modifyreg(struct imx9_lpi2c_priv_s *priv,
+                                        uint16_t offset, uint32_t clearbits,
+                                        uint32_t setbits);
+
+#ifdef CONFIG_IMX9_LPI2C_DYNTIMEO
+static uint32_t imx9_lpi2c_toticks(int msgc, struct i2c_msg_s *msgs);
+#endif /* CONFIG_IMX9_LPI2C_DYNTIMEO */
+
+static inline int
+imx9_lpi2c_sem_waitdone(struct imx9_lpi2c_priv_s *priv);
+
+#ifdef CONFIG_I2C_TRACE
+static void imx9_lpi2c_tracereset(struct imx9_lpi2c_priv_s *priv);
+static void imx9_lpi2c_tracenew(struct imx9_lpi2c_priv_s *priv,
+                                uint32_t status);
+static void imx9_lpi2c_traceevent(struct imx9_lpi2c_priv_s *priv,
+                                  enum imx9_trace_e event, uint32_t parm);
+static void imx9_lpi2c_tracedump(struct imx9_lpi2c_priv_s *priv);
+#endif /* CONFIG_I2C_TRACE */
+
+static void imx9_lpi2c_setclock(struct imx9_lpi2c_priv_s *priv,
+                                uint32_t frequency);
+static inline void imx9_lpi2c_sendstart(struct imx9_lpi2c_priv_s *priv,
+                                        uint8_t address);
+static inline void imx9_lpi2c_sendstop(struct imx9_lpi2c_priv_s *priv);
+static inline uint32_t
+imx9_lpi2c_getstatus(struct imx9_lpi2c_priv_s *priv);
+
+static int imx9_lpi2c_isr_process(struct imx9_lpi2c_priv_s *priv);
+
+#ifndef CONFIG_I2C_POLLED
+static int imx9_lpi2c_isr(int irq, void *context, void *arg);
+#endif /* !CONFIG_I2C_POLLED */
+
+static void imx9_lpi2c_clock_enable(struct imx9_lpi2c_priv_s *priv);
+static void imx9_lpi2c_clock_disable(struct imx9_lpi2c_priv_s *priv);
+static int imx9_lpi2c_init(struct imx9_lpi2c_priv_s *priv);
+static int imx9_lpi2c_deinit(struct imx9_lpi2c_priv_s *priv);
+static int imx9_lpi2c_transfer(struct i2c_master_s *dev,
+                               struct i2c_msg_s *msgs, int count);
+#ifdef CONFIG_I2C_RESET
+static int imx9_lpi2c_reset(struct i2c_master_s *dev);
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+static void imx9_rxdma_callback(DMACH_HANDLE handle, void *arg, bool done,
+                                int result);
+static void imx9_txdma_callback(DMACH_HANDLE handle, void *arg, bool done,
+                                int result);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* Trace events strings */
+
+#ifdef CONFIG_I2C_TRACE
+static const char *g_trace_names[] =
+{
+  "NONE           ",
+  "SENDADDR       ",
+  "SENDBYTE       ",
+  "RCVBYTE        ",
+  "NOSTART        ",
+  "START/RESTART  ",
+  "STOP           ",
+  "ERROR          "
+};
+#endif
+
+/* I2C interface */
+
+static const struct i2c_ops_s imx9_lpi2c_ops =
+{
+  .transfer = imx9_lpi2c_transfer,
+#ifdef CONFIG_I2C_RESET
+  .reset    = imx9_lpi2c_reset,
+#endif
+};
+
+/* I2C device structures */
+
+#ifdef CONFIG_IMX9_LPI2C1
+static const struct imx9_lpi2c_config_s imx9_lpi2c1_config =
+{
+  .base          = IMX9_LPI2C1_BASE,
+  .clk_root      = CCM_CR_LPI2C1,
+  .clk_gate      = CCM_LPCG_LPI2C1,
+  .busy_idle     = CONFIG_IMX9_LPI2C1_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C1_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C1_FILTSDA,
+  .scl_pin       = MUX_LPI2C1_SCL,
+  .sda_pin       = MUX_LPI2C1_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C1_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C1_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C1,
+#endif
+#ifdef CONFIG_IMX9_LPI2C1_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C1RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C1TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c1_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c1_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C2
+static const struct imx9_lpi2c_config_s imx9_lpi2c2_config =
+{
+  .base          = IMX9_LPI2C2_BASE,
+  .clk_root      = CCM_CR_LPI2C2,
+  .clk_gate      = CCM_LPCG_LPI2C2,
+  .busy_idle     = CONFIG_IMX9_LPI2C2_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C2_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C2_FILTSDA,
+  .scl_pin       = MUX_LPI2C2_SCL,
+  .sda_pin       = MUX_LPI2C2_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C2_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C2_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C2,
+#endif
+#ifdef CONFIG_IMX9_LPI2C2_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C2RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C2TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c2_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c2_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C3
+static const struct imx9_lpi2c_config_s imx9_lpi2c3_config =
+{
+  .base          = IMX9_LPI2C3_BASE,
+  .clk_root      = CCM_CR_LPI2C3,
+  .clk_gate      = CCM_LPCG_LPI2C3,
+  .busy_idle     = CONFIG_IMX9_LPI2C3_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C3_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C3_FILTSDA,
+  .scl_pin       = MUX_LPI2C3_SCL,
+  .sda_pin       = MUX_LPI2C3_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C3_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C3_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C3,
+#endif
+#ifdef CONFIG_IMX9_LPI2C3_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C3RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C3TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c3_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c3_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C4
+static const struct imx9_lpi2c_config_s imx9_lpi2c4_config =
+{
+  .base          = IMX9_LPI2C4_BASE,
+  .clk_root      = CCM_CR_LPI2C4,
+  .clk_gate      = CCM_LPCG_LPI2C4,
+  .busy_idle     = CONFIG_IMX9_LPI2C4_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C4_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C4_FILTSDA,
+  .scl_pin       = MUX_LPI2C4_SCL,
+  .sda_pin       = MUX_LPI2C4_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C4_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C4_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C4,
+#endif
+#ifdef CONFIG_IMX9_LPI2C4_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C4RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C4TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c4_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c4_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C5
+static const struct imx9_lpi2c_config_s imx9_lpi2c5_config =
+{
+  .base          = IMX9_LPI2C5_BASE,
+  .clk_root      = CCM_CR_LPI2C5,
+  .clk_gate      = CCM_LPCG_LPI2C5,
+  .busy_idle     = CONFIG_IMX9_LPI2C5_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C5_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C5_FILTSDA,
+  .scl_pin       = MUX_LPI2C5_SCL,
+  .sda_pin       = MUX_LPI2C5_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C5_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C5_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C5,
+#endif
+#ifdef CONFIG_IMX9_LPI2C5_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C5RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C5TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c5_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c5_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C6
+static const struct imx9_lpi2c_config_s imx9_lpi2c6_config =
+{
+  .base          = IMX9_LPI2C6_BASE,
+  .clk_root      = CCM_CR_LPI2C6,
+  .clk_gate      = CCM_LPCG_LPI2C6,
+  .busy_idle     = CONFIG_IMX9_LPI2C6_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C6_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C6_FILTSDA,
+  .scl_pin       = MUX_LPI2C6_SCL,
+  .sda_pin       = MUX_LPI2C6_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C6_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C6_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C6,
+#endif
+#ifdef CONFIG_IMX9_LPI2C6_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C6RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C6TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c6_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c6_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C7
+static const struct imx9_lpi2c_config_s imx9_lpi2c7_config =
+{
+  .base          = IMX9_LPI2C7_BASE,
+  .clk_root      = CCM_CR_LPI2C7,
+  .clk_gate      = CCM_LPCG_LPI2C7,
+  .busy_idle     = CONFIG_IMX9_LPI2C7_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C7_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C7_FILTSDA,
+  .scl_pin       = MUX_LPI2C7_SCL,
+  .sda_pin       = MUX_LPI2C7_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C7_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C7_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C7,
+#endif
+#ifdef CONFIG_IMX9_LPI2C7_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C7RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C7TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c7_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c7_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C8
+static const struct imx9_lpi2c_config_s imx9_lpi2c8_config =
+{
+  .base          = IMX9_LPI2C8_BASE,
+  .clk_root      = CCM_CR_LPI2C8,
+  .clk_gate      = CCM_LPCG_LPI2C8,
+  .busy_idle     = CONFIG_IMX9_LPI2C8_BUSYIDLE,
+  .filtscl       = CONFIG_IMX9_LPI2C8_FILTSCL,
+  .filtsda       = CONFIG_IMX9_LPI2C8_FILTSDA,
+  .scl_pin       = MUX_LPI2C8_SCL,
+  .sda_pin       = MUX_LPI2C8_SDA,
+#if defined(CONFIG_I2C_RESET)
+  .reset_scl_pin = GPIO_LPI2C8_SCL_RESET,
+  .reset_sda_pin = GPIO_LPI2C8_SDA_RESET,
+#endif
+#ifndef CONFIG_I2C_SLAVE
+  .mode          = LPI2C_MASTER,
+#else
+  .mode          = LPI2C_SLAVE,
+#endif
+#ifndef CONFIG_I2C_POLLED
+  .irq           = IMX9_IRQ_LPI2C8,
+#endif
+#ifdef CONFIG_IMX9_LPI2C8_DMA
+  .dma_rxreqsrc  = DMA_REQUEST_MUXLPI2C8RX,
+  .dma_txreqsrc  = DMA_REQUEST_MUXLPI2C8TX,
+#endif
+};
+
+static struct imx9_lpi2c_priv_s imx9_lpi2c8_priv =
+{
+  .ops           = &imx9_lpi2c_ops,
+  .config        = &imx9_lpi2c8_config,
+  .refs          = 0,
+  .lock          = NXMUTEX_INITIALIZER,
+#ifndef CONFIG_I2C_POLLED
+  .sem_isr       = SEM_INITIALIZER(0),
+#endif
+  .intstate      = INTSTATE_IDLE,
+  .msgc          = 0,
+  .msgv          = NULL,
+  .ptr           = NULL,
+  .dcnt          = 0,
+  .flags         = 0,
+  .status        = 0
+};
+#endif
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: imx9_lpi2c_getreg
+ *
+ * Description:
+ *   Get a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline uint32_t
+imx9_lpi2c_getreg(struct imx9_lpi2c_priv_s *priv, uint16_t offset)
+{
+  return getreg32(priv->config->base + offset);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_putreg
+ *
+ * Description:
+ *  Put a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void imx9_lpi2c_putreg(struct imx9_lpi2c_priv_s *priv,
+                                     uint16_t offset, uint32_t value)
+{
+  putreg32(value, priv->config->base + offset);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_modifyreg
+ *
+ * Description:
+ *   Modify a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void imx9_lpi2c_modifyreg(struct imx9_lpi2c_priv_s *priv,
+                                        uint16_t offset, uint32_t clearbits,
+                                        uint32_t setbits)
+{
+  modifyreg32(priv->config->base + offset, clearbits, setbits);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_toticks
+ *
+ * Description:
+ *   Return a micro-second delay based on the number of bytes left to be
+ *   processed.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMX9_LPI2C_DYNTIMEO
+static uint32_t imx9_lpi2c_toticks(int msgc, struct i2c_msg_s *msgs)
+{
+  int i;
+  size_t bytecount = 0;
+  uint32_t tick    = 0;
+
+  /* Count the number of bytes left to process */
+
+  for (i = 0; i < msgc; i++)
+    {
+      bytecount += msgs[i].length;
+    }
+
+  /* Then return a number of microseconds based on a user provided scaling
+   * factor.
+   */
+
+  tick = USEC2TICK(CONFIG_IMX9_LPI2C_DYNTIMEO_USECPERBYTE * bytecount);
+  if (tick == 0)
+    {
+      tick = 1;
+    }
+
+  return tick;
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_sem_waitdone
+ *
+ * Description:
+ *   Wait for a transfer to complete
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_I2C_POLLED
+static inline int
+imx9_lpi2c_sem_waitdone(struct imx9_lpi2c_priv_s *priv)
+{
+  irqstate_t flags;
+  uint32_t regval;
+  int ret;
+
+  flags = enter_critical_section();
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  if (priv->rxdma == NULL && priv->txdma == NULL)
+    {
+#endif
+      /* Clear the TX and RX FIFOs */
+
+      imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCR_OFFSET, 0,
+                           LPI2C_MCR_RTF | LPI2C_MCR_RRF);
+
+      /* Enable Interrupts when master mode */
+
+      if (priv->config->mode == LPI2C_MASTER)
+        {
+          if ((priv->flags & I2C_M_READ) != 0)
+            {
+              regval = LPI2C_MIER_TDIE | LPI2C_MIER_RDIE |
+                       LPI2C_MIER_NDIE | LPI2C_MIER_ALIE |
+                       LPI2C_MIER_SDIE;
+              imx9_lpi2c_putreg(priv, IMX9_LPI2C_MIER_OFFSET, regval);
+            }
+          else
+            {
+              regval = LPI2C_MIER_TDIE | LPI2C_MIER_NDIE |
+                       LPI2C_MIER_ALIE | LPI2C_MIER_SDIE;
+              imx9_lpi2c_putreg(priv, IMX9_LPI2C_MIER_OFFSET, regval);
+            }
+        }
+
+#ifdef CONFIG_I2C_SLAVE
+      /* Enable Interrupts when slave mode */
+
+      else
+        {
+          /* REVISIT: Slave mode has not been implemented */
+        }
+#endif
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+    }
+#endif
+
+  do
+    {
+      /* Wait until either the transfer is complete or the timeout expires */
+
+#ifdef CONFIG_IMX9_LPI2C_DYNTIMEO
+      ret = nxsem_tickwait_uninterruptible(&priv->sem_isr,
+                       imx9_lpi2c_toticks(priv->msgc, priv->msgv));
+#else
+      ret = nxsem_tickwait_uninterruptible(&priv->sem_isr,
+                                           CONFIG_IMX9_LPI2C_TIMEOTICKS);
+#endif
+      if (ret < 0)
+        {
+          /* Break out of the loop on irrecoverable errors.  This would
+           * include timeouts and mystery errors reported by
+           * nxsem_tickwait_uninterruptible.
+           */
+
+          break;
+        }
+    }
+
+  /* Loop until the interrupt level transfer is complete. */
+
+  while (priv->intstate != INTSTATE_DONE);
+
+  /* Set the interrupt state back to IDLE */
+
+  priv->intstate = INTSTATE_IDLE;
+
+  /* Disable I2C interrupts */
+
+  if (priv->config->mode == LPI2C_MASTER)
+    {
+      imx9_lpi2c_putreg(priv, IMX9_LPI2C_MIER_OFFSET, 0);
+    }
+  else
+    {
+      imx9_lpi2c_putreg(priv, IMX9_LPI2C_SIER_OFFSET, 0);
+    }
+
+  leave_critical_section(flags);
+  return ret;
+}
+#else
+static inline int
+imx9_lpi2c_sem_waitdone(struct imx9_lpi2c_priv_s *priv)
+{
+  clock_t timeout;
+  clock_t start;
+  clock_t elapsed;
+  int ret;
+
+  /* Get the timeout value */
+
+#ifdef CONFIG_IMX9_LPI2C_DYNTIMEO
+  timeout = imx9_lpi2c_toticks(priv->msgc, priv->msgv);
+#else
+  timeout = CONFIG_IMX9_LPI2C_TIMEOTICKS;
+#endif
+  start = clock_systime_ticks();
+
+  do
+    {
+      /* Calculate the elapsed time */
+
+      elapsed = clock_systime_ticks() - start;
+
+      /* Poll by simply calling the timer interrupt handler until it
+       * reports that it is done.
+       */
+
+      imx9_lpi2c_isr_process(priv);
+    }
+
+  /* Loop until the transfer is complete. */
+
+  while (priv->intstate != INTSTATE_DONE && elapsed < timeout);
+
+  i2cinfo("intstate: %d elapsed: %ld threshold: %ld status: %08x\n",
+          priv->intstate, (long)elapsed, (long)timeout, priv->status);
+
+  /* Set the interrupt state back to IDLE */
+
+  ret = priv->intstate == INTSTATE_DONE ? OK : -ETIMEDOUT;
+  priv->intstate = INTSTATE_IDLE;
+  return ret;
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_sem_waitstop
+ *
+ * Description:
+ *   Wait for a STOP to complete
+ *
+ ****************************************************************************/
+
+static inline void
+imx9_lpi2c_sem_waitstop(struct imx9_lpi2c_priv_s *priv)
+{
+  clock_t start;
+  clock_t elapsed;
+  clock_t timeout;
+  uint32_t regval;
+
+  /* Select a timeout */
+
+#ifdef CONFIG_IMX9_LPI2C_DYNTIMEO
+  timeout = USEC2TICK(CONFIG_IMX9_LPI2C_DYNTIMEO_STARTSTOP);
+#else
+  timeout = CONFIG_IMX9_LPI2C_TIMEOTICKS;
+#endif
+
+  /* Wait as stop might still be in progress; but stop might also
+   * be set because of a timeout error: "The [STOP] bit is set and
+   * cleared by software, cleared by hardware when a Stop condition is
+   * detected, set by hardware when a timeout error is detected."
+   */
+
+  start = clock_systime_ticks();
+  do
+    {
+      /* Calculate the elapsed time */
+
+      elapsed = clock_systime_ticks() - start;
+
+      /* Check for STOP condition */
+
+      if (priv->config->mode == LPI2C_MASTER)
+        {
+          regval = imx9_lpi2c_getreg(priv, IMX9_LPI2C_MSR_OFFSET);
+          if ((regval & LPI2C_MSR_SDF) == LPI2C_MSR_SDF)
+            {
+              return;
+            }
+        }
+
+      /* Enable Interrupts when slave mode */
+
+      else
+        {
+          regval = imx9_lpi2c_getreg(priv, IMX9_LPI2C_SSR_OFFSET);
+          if ((regval & LPI2C_SSR_SDF) == LPI2C_SSR_SDF)
+            {
+              return;
+            }
+        }
+
+      /* Check for NACK error */
+
+      if (priv->config->mode == LPI2C_MASTER)
+        {
+          regval = imx9_lpi2c_getreg(priv, IMX9_LPI2C_MSR_OFFSET);
+          if ((regval & LPI2C_MSR_NDF) == LPI2C_MSR_NDF)
+            {
+              return;
+            }
+        }
+
+#ifdef CONFIG_I2C_SLAVE
+      /* Enable Interrupts when slave mode */
+
+      else
+        {
+          /* REVISIT: Slave mode has not been implemented */
+        }
+#endif
+    }
+
+  /* Loop until the stop is complete or a timeout occurs. */
+
+  while (elapsed < timeout);
+
+  /* If we get here then a timeout occurred with the STOP condition
+   * still pending.
+   */
+
+  i2cinfo("Timeout with Status Register: %" PRIx32 "\n", regval);
+}
+
+/****************************************************************************
+ * Name: imx9_rxdma_callback
+ *
+ * Description:
+ *   This function performs the next I2C operation
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+static void imx9_rxdma_callback(DMACH_HANDLE handle, void *arg, bool done,
+                              int result)
+{
+  struct imx9_lpi2c_priv_s *priv = (struct imx9_lpi2c_priv_s *)arg;
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MIER_OFFSET, 0,
+                             LPI2C_MIER_SDIE);
+
+  if (result == OK)
+    {
+      if ((priv->flags & I2C_M_NOSTOP) == 0)
+        {
+          imx9_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+          imx9_lpi2c_sendstop(priv);
+        }
+    }
+  else
+    {
+      uint32_t status = imx9_lpi2c_getstatus(priv);
+
+      if ((status & LPI2C_MSR_ERROR_MASK) != 0)
+        {
+          i2cerr("ERROR: MSR: status: 0x0%" PRIx32 "\n", status);
+
+          imx9_lpi2c_traceevent(priv, I2CEVENT_ERROR, 0);
+        }
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_txdma_callback
+ *
+ * Description:
+ *   This function performs the next I2C operation
+ *
+ ****************************************************************************/
+#ifdef CONFIG_IMX9_LPI2C_DMA
+static void imx9_txdma_callback(DMACH_HANDLE handle, void *arg, bool done,
+                              int result)
+{
+  struct imx9_lpi2c_priv_s *priv = (struct imx9_lpi2c_priv_s *)arg;
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MIER_OFFSET, 0,
+                             LPI2C_MIER_SDIE);
+
+  if (result == OK)
+    {
+      if ((priv->flags & I2C_M_NOSTOP) == 0)
+        {
+          imx9_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+          imx9_lpi2c_sendstop(priv);
+        }
+    }
+  else
+    {
+      uint32_t status = imx9_lpi2c_getstatus(priv);
+
+      if ((status & LPI2C_MSR_ERROR_MASK) != 0)
+        {
+          i2cerr("ERROR: MSR: status: 0x0%" PRIx32 "\n", status);
+
+          imx9_lpi2c_traceevent(priv, I2CEVENT_ERROR, 0);
+        }
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_trace*
+ *
+ * Description:
+ *   I2C trace instrumentation
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_I2C_TRACE
+static void imx9_lpi2c_traceclear(struct imx9_lpi2c_priv_s *priv)
+{
+  struct imx9_trace_s *trace = &priv->trace[priv->tndx];
+
+  trace->status = 0;              /* I2C 32-bit SR2|SR1 status */
+  trace->count  = 0;              /* Interrupt count when status change */
+  trace->event  = I2CEVENT_NONE;  /* Last event that occurred with this status 
*/
+  trace->parm   = 0;              /* Parameter associated with the event */
+  trace->time   = 0;              /* Time of first status or event */
+}
+
+static void imx9_lpi2c_tracereset(struct imx9_lpi2c_priv_s *priv)
+{
+  /* Reset the trace info for a new data collection */
+
+  priv->tndx       = 0;
+  priv->start_time = clock_systime_ticks();
+  imx9_lpi2c_traceclear(priv);
+}
+
+static void imx9_lpi2c_tracenew(struct imx9_lpi2c_priv_s *priv,
+                                uint32_t status)
+{
+  struct imx9_trace_s *trace = &priv->trace[priv->tndx];
+
+  /* Is the current entry uninitialized?  Has the status changed? */
+
+  if (trace->count == 0 || status != trace->status)
+    {
+      /* Yes.. Was it the status changed?  */
+
+      if (trace->count != 0)
+        {
+          /* Yes.. bump up the trace index (unless out of trace entries) */
+
+          if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
+            {
+              i2cerr("ERROR: Trace table overflow\n");
+              return;
+            }
+
+          priv->tndx++;
+          trace = &priv->trace[priv->tndx];
+        }
+
+      /* Initialize the new trace entry */
+
+      imx9_lpi2c_traceclear(priv);
+      trace->status = status;
+      trace->count  = 1;
+      trace->time   = clock_systime_ticks();
+    }
+  else
+    {
+      /* Just increment the count of times that we have seen this status */
+
+      trace->count++;
+    }
+}
+
+static void imx9_lpi2c_traceevent(struct imx9_lpi2c_priv_s *priv,
+                                  enum imx9_trace_e event, uint32_t parm)
+{
+  struct imx9_trace_s *trace;
+
+  if (event != I2CEVENT_NONE)
+    {
+      trace = &priv->trace[priv->tndx];
+
+      /* Initialize the new trace entry */
+
+      trace->event  = event;
+      trace->parm   = parm;
+
+      /* Bump up the trace index (unless we are out of trace entries) */
+
+      if (priv->tndx >= (CONFIG_I2C_NTRACE - 1))
+        {
+          i2cerr("ERROR: Trace table overflow\n");
+          return;
+        }
+
+      priv->tndx++;
+      imx9_lpi2c_traceclear(priv);
+    }
+}
+
+static void imx9_lpi2c_tracedump(struct imx9_lpi2c_priv_s *priv)
+{
+  struct imx9_trace_s *trace;
+  int i;
+
+  syslog(LOG_DEBUG, "Elapsed time: %ld\n",
+         (long)(clock_systime_ticks() - priv->start_time));
+
+  for (i = 0; i < priv->tndx; i++)
+    {
+      trace = &priv->trace[i];
+      syslog(LOG_DEBUG,
+             "%2d. STATUS: %08x COUNT: %3d EVENT: %s(%2d) PARM: %08x "
+             "TIME: %d\n",
+             i + 1, trace->status, trace->count,
+             g_trace_names[trace->event],
+             trace->event, trace->parm, trace->time - priv->start_time);
+    }
+}
+#endif /* CONFIG_I2C_TRACE */
+
+/****************************************************************************
+ * Name: imx9_lpi2c_setclock
+ *
+ * Description:
+ *   Set the I2C clock
+ *
+ ****************************************************************************/
+
+static void imx9_lpi2c_setclock(struct imx9_lpi2c_priv_s *priv,
+                                uint32_t frequency)
+{
+  uint32_t src_freq = 0;
+  uint32_t regval;
+  uint32_t men;
+  uint32_t prescale = 0;
+  uint32_t best_prescale = 0;
+  uint32_t best_clk_hi = 0;
+  uint32_t abs_error = 0;
+  uint32_t best_error = 0xffffffff;
+  uint32_t clk_hi_cycle;
+  uint32_t computed_rate;
+  uint32_t count;
+
+  /* Has the I2C bus frequency changed? */
+
+  if (priv->config->mode == LPI2C_MASTER)
+    {
+      if (frequency != priv->frequency)
+        {
+          /* Disable the selected LPI2C peripheral to configure the new
+           * clock if it is enabled.
+           */
+
+          men = imx9_lpi2c_getreg(priv, IMX9_LPI2C_MCR_OFFSET) &
+                LPI2C_MCR_MEN;
+          if (men)
+            {
+              imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCR_OFFSET,
+                                    LPI2C_MCR_MEN, 0);
+            }
+
+          /* Get the LPI2C clock source frequency */
+
+          imx9_get_rootclock(priv->config->clk_root, &src_freq);
+
+          /* LPI2C output frequency = (Source Clock (Hz)/ 2^prescale) /
+           *   (CLKLO + 1 + CLKHI + 1 + ROUNDDOWN((2 + FILTSCL) / 2^prescale)
+           *
+           * Assume  CLKLO = 2 * CLKHI, SETHOLD = CLKHI, DATAVD = CLKHI / 2
+           */
+
+          for (prescale = 1;
+               (prescale <= 128) && (best_error != 0);
+               prescale *= 2)
+            {
+              for (clk_hi_cycle = 1; clk_hi_cycle < 32; clk_hi_cycle++)
+                {
+                  if (clk_hi_cycle == 1)
+                    {
+                      computed_rate = (src_freq / prescale) /
+                                      (6 + (2 / prescale));
+                    }
+                  else
+                    {
+                      computed_rate = (src_freq / prescale) /
+                                      ((3 * clk_hi_cycle + 2) +
+                                      (2 / prescale));
+                    }
+
+                  if (frequency > computed_rate)
+                    {
+                      abs_error = frequency - computed_rate;
+                    }
+                  else
+                    {
+                      abs_error = computed_rate - frequency;
+                    }
+
+                  if (abs_error < best_error)
+                    {
+                      best_prescale = prescale;
+                      best_clk_hi = clk_hi_cycle;
+                      best_error = abs_error;
+
+                      if (abs_error == 0)
+                        {
+                          break;
+                        }
+                    }
+                }
+            }
+
+          regval = LPI2C_MCCR0_CLKHI(best_clk_hi);
+
+          if (best_clk_hi < 2)
+            {
+              regval |= LPI2C_MCCR0_CLKLO(3) | LPI2C_MCCR0_SETHOLD(2) |
+                        LPI2C_MCCR0_DATAVD(1);
+            }
+          else
+            {
+              regval |= LPI2C_MCCR0_CLKLO(2 * best_clk_hi) |
+                        LPI2C_MCCR0_SETHOLD(best_clk_hi) |
+                        LPI2C_MCCR0_DATAVD(best_clk_hi / 2);
+            }
+
+          imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCCR0_OFFSET, regval);
+
+          for (count = 0; count < 8; count++)
+            {
+              if (best_prescale == (1 << count))
+                {
+                  best_prescale = count;
+                  break;
+                }
+            }
+
+          imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCFGR1_OFFSET,
+                               LPI2C_MCFGR1_PRESCALE_MASK,
+                               LPI2C_MCFGR1_PRESCALE(best_prescale));
+
+          /* Re-enable LPI2C if it was enabled previously */
+
+          if (men)
+            {
+              imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCR_OFFSET, 0,
+                                   LPI2C_MCR_MEN);
+            }
+
+          /* Save the new LPI2C frequency */
+
+          priv->frequency = frequency;
+        }
+    }
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_sendstart
+ *
+ * Description:
+ *   Send the START conditions/force Master mode
+ *
+ ****************************************************************************/
+
+static inline void imx9_lpi2c_sendstart(struct imx9_lpi2c_priv_s *priv,
+                                        uint8_t address)
+{
+  uint32_t txcount = 0;
+  uint32_t status = 0;
+  uint8_t addr;
+
+  /* Generate START condition and send the address */
+
+  /* Disable AUTOSTOP and turn NAK Ignore off */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCFGR1_OFFSET,
+                       LPI2C_MCFGR1_IGNACK | LPI2C_MCFGR1_AUTOSTOP, 0);
+
+  do
+    {
+      txcount = (imx9_lpi2c_getreg(priv, IMX9_LPI2C_MFSR_OFFSET) &
+                 LPI2C_MFSR_TXCOUNT_MASK) >> LPI2C_MFSR_TXCOUNT_SHIFT;
+      txcount = 4 - txcount;
+
+      status = imx9_lpi2c_getreg(priv, IMX9_LPI2C_MSR_OFFSET);
+
+      if (status & LPI2C_MSR_ERROR_MASK)
+        {
+          imx9_lpi2c_putreg(priv, IMX9_LPI2C_MSR_OFFSET,
+                            status & LPI2C_MSR_ERROR_MASK);
+        }
+    }
+  while (txcount == 0);
+
+  if ((priv->flags & I2C_M_READ) != 0)
+    {
+      addr = I2C_READADDR8(address);
+    }
+  else
+    {
+      addr = I2C_WRITEADDR8(address);
+    }
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MTDR_OFFSET,
+                    (LPI2C_MTDR_CMD_START | LPI2C_MTDR_DATA(addr)));
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_sendstop
+ *
+ * Description:
+ *   Send the STOP conditions
+ *
+ ****************************************************************************/
+
+static inline void imx9_lpi2c_sendstop(struct imx9_lpi2c_priv_s *priv)
+{
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MTDR_OFFSET, LPI2C_MTDR_CMD_STOP);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_getstatus
+ *
+ * Description:
+ *   Get 32-bit status
+ *
+ ****************************************************************************/
+
+static inline uint32_t
+imx9_lpi2c_getstatus(struct imx9_lpi2c_priv_s *priv)
+{
+  return imx9_lpi2c_getreg(priv, IMX9_LPI2C_MSR_OFFSET);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_getenabledints
+ *
+ * Description:
+ *   Get 32-bit status
+ *
+ ****************************************************************************/
+
+static inline uint32_t
+imx9_lpi2c_getenabledints(struct imx9_lpi2c_priv_s *priv)
+{
+  return imx9_lpi2c_getreg(priv, IMX9_LPI2C_MIER_OFFSET);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_isr_process
+ *
+ * Description:
+ *  Common Interrupt Service Routine
+ *
+ ****************************************************************************/
+
+static int imx9_lpi2c_isr_process(struct imx9_lpi2c_priv_s *priv)
+{
+  uint32_t status = imx9_lpi2c_getstatus(priv);
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  uint32_t current_status = status;
+
+  if (priv->rxdma != NULL || priv->txdma != NULL)
+    {
+      /* Condition the status with only the enabled interrupts */
+
+      status &= imx9_lpi2c_getenabledints(priv);
+
+      /* Is there an Error condition */
+
+      if (current_status & LPI2C_MSR_LIMITED_ERROR_MASK)
+        {
+          imx9_lpi2c_traceevent(priv, I2CEVENT_ERROR, 0);
+
+          /* Return the full error status */
+
+          priv->status = current_status;
+        }
+
+      /* End of packet or Stop */
+
+      if ((status & (LPI2C_MSR_SDF | LPI2C_MSR_EPF)) != 0)
+        {
+          imx9_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+
+          /* Acknowledge End of packet or Stop */
+
+          imx9_lpi2c_putreg(priv, IMX9_LPI2C_MSR_OFFSET, status &
+                                                           (LPI2C_MSR_SDF |
+                                                           LPI2C_MSR_EPF));
+
+          /* Mark that this transaction stopped */
+
+          priv->msgv = NULL;
+          priv->msgc = 0;
+          priv->dcnt = -1;
+
+          if (priv->intstate == INTSTATE_WAITING)
+            {
+              /* inform the thread that transfer is complete
+               * and wake it up
+               */
+
+              imx9_dmach_stop(priv->txdma);
+              imx9_dmach_stop(priv->rxdma);
+
+              priv->intstate = INTSTATE_DONE;
+              nxsem_post(&priv->sem_isr);
+            }
+        }
+
+      /* Clear the error */
+
+      imx9_lpi2c_putreg(priv, IMX9_LPI2C_MSR_OFFSET,
+                        (current_status & (LPI2C_MSR_NDF |
+                                           LPI2C_MSR_ALF |
+                                           LPI2C_MSR_FEF)));
+      return OK;
+    }
+
+#endif
+  /* Check for new trace setup */
+
+  imx9_lpi2c_tracenew(priv, status);
+
+  if ((status & LPI2C_MSR_LIMITED_ERROR_MASK) == 0)
+    {
+      /* Check if there is more bytes to send */
+
+      if (((priv->flags & I2C_M_READ) == 0) &&
+               (status & LPI2C_MSR_TDF) != 0)
+        {
+          if (priv->dcnt > 0)
+            {
+              imx9_lpi2c_traceevent(priv, I2CEVENT_SENDBYTE, priv->dcnt);
+              imx9_lpi2c_putreg(priv, IMX9_LPI2C_MTDR_OFFSET,
+                                LPI2C_MTDR_CMD_TXD |
+                                LPI2C_MTDR_DATA(*priv->ptr++));
+              priv->dcnt--;
+
+              /* Last byte of last message? */
+
+              if ((priv->msgc <= 0) && (priv->dcnt == 0))
+                {
+                  if ((priv->flags & I2C_M_NOSTOP) == 0)
+                    {
+                      imx9_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+
+                      /* Do this once */
+
+                      priv->flags |= I2C_M_NOSTOP;
+                      imx9_lpi2c_sendstop(priv);
+                    }
+                }
+            }
+        }
+
+      /* Check if there is more bytes to read */
+
+      else if (((priv->flags & I2C_M_READ) != 0) &&
+               (status & LPI2C_MSR_RDF) != 0)
+        {
+          /* Read a byte, if dcnt goes < 0, read dummy bytes to ack ISRs */
+
+          if (priv->dcnt > 0)
+            {
+              imx9_lpi2c_traceevent(priv, I2CEVENT_RCVBYTE, priv->dcnt);
+
+              /* No interrupts or context switches should occur in the
+               * following sequence. Otherwise, additional bytes may be
+               * sent by the device.
+               */
+
+    #ifdef CONFIG_I2C_POLLED
+              irqstate_t flags = enter_critical_section();
+    #endif
+
+              /* Receive a byte */
+
+              *priv->ptr++ = imx9_lpi2c_getreg(priv,
+                                               IMX9_LPI2C_MRDR_OFFSET) &
+                                               LPI2C_MRDR_DATA_MASK;
+              priv->dcnt--;
+
+    #ifdef CONFIG_I2C_POLLED
+              leave_critical_section(flags);
+    #endif
+              /* Last byte of last message? */
+
+              if ((priv->msgc <= 0) && (priv->dcnt == 0))
+                {
+                  if ((priv->flags & I2C_M_NOSTOP) == 0)
+                    {
+                      imx9_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+
+                      /* Do this once */
+
+                      priv->flags |= I2C_M_NOSTOP;
+                      imx9_lpi2c_sendstop(priv);
+                    }
+                }
+            }
+          else
+            {
+              /* Read and discard data */
+
+              imx9_lpi2c_getreg(priv, IMX9_LPI2C_MRDR_OFFSET);
+            }
+        }
+
+      /* Start the first or next message */
+
+      if (priv->dcnt <= 0 && (status & (LPI2C_MSR_EPF | LPI2C_MSR_SDF)) == 0)
+        {
+          if (priv->msgc > 0 && priv->msgv != NULL)
+            {
+              priv->ptr   = priv->msgv->buffer;
+              priv->dcnt  = priv->msgv->length;
+              priv->flags = priv->msgv->flags;
+
+              if ((priv->flags & I2C_M_NOSTART) == 0)
+                {
+                  imx9_lpi2c_traceevent(priv, I2CEVENT_STARTRESTART,
+                                        priv->msgc);
+
+                  /* Do this once */
+
+                  priv->flags |= I2C_M_NOSTART;
+
+                  imx9_lpi2c_sendstart(priv, priv->msgv->addr);
+                }
+              else
+                {
+                  imx9_lpi2c_traceevent(priv, I2CEVENT_NOSTART, priv->msgc);
+                }
+
+              priv->msgv++;
+              priv->msgc--;
+
+              if ((priv->flags & I2C_M_READ) != 0)
+                {
+#ifndef CONFIG_I2C_POLLED
+                  /* Stop TX interrupt */
+
+                  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MIER_OFFSET,
+                                       LPI2C_MIER_TDIE, LPI2C_MIER_RDIE);
+#endif
+                  /* Set LPI2C in read mode */
+
+                  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MTDR_OFFSET,
+                                    LPI2C_MTDR_CMD_RXD |
+                                    LPI2C_MTDR_DATA((priv->dcnt - 1)));
+                }
+              else
+                {
+                  /* Send the first byte from tx buffer */
+
+                  imx9_lpi2c_traceevent(priv, I2CEVENT_SENDBYTE,
+                                        priv->dcnt);
+                  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MTDR_OFFSET,
+                                    LPI2C_MTDR_CMD_TXD |
+                                    LPI2C_MTDR_DATA(*priv->ptr++));
+                  priv->dcnt--;
+
+                  /* Last byte of last message? */
+
+                  if ((priv->msgc <= 0) && (priv->dcnt == 0))
+                    {
+                      if ((priv->flags & I2C_M_NOSTOP) == 0)
+                        {
+                          imx9_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+
+                          /* Do this once */
+
+                          priv->flags |= I2C_M_NOSTOP;
+                          imx9_lpi2c_sendstop(priv);
+                        }
+                    }
+                }
+            }
+        }
+    }
+  else
+    {
+      imx9_lpi2c_traceevent(priv, I2CEVENT_ERROR, 0);
+
+      priv->status = status;
+
+      if ((priv->flags & I2C_M_NOSTOP) == 0)
+        {
+          imx9_lpi2c_traceevent(priv, I2CEVENT_STOP, 0);
+
+          /* Do this once */
+
+          priv->flags |= I2C_M_NOSTOP;
+          imx9_lpi2c_sendstop(priv);
+        }
+
+      /* Clear the error */
+
+      imx9_lpi2c_putreg(priv, IMX9_LPI2C_MSR_OFFSET,
+                        (status & (LPI2C_MSR_NDF | LPI2C_MSR_ALF |
+                                   LPI2C_MSR_FEF | LPI2C_MSR_EPF)));
+    }
+
+  /* Check for endof packet or Stop */
+
+  if ((status & (LPI2C_MSR_EPF | LPI2C_MSR_SDF)) != 0)
+    {
+      /* Reset either or both */
+
+      imx9_lpi2c_putreg(priv, IMX9_LPI2C_MSR_OFFSET, status &
+                         (LPI2C_MSR_EPF | LPI2C_MSR_SDF));
+
+      /* Was it both End of packet and Stop */
+
+      if ((status & (LPI2C_MSR_EPF | LPI2C_MSR_SDF)) ==
+          (LPI2C_MSR_EPF | LPI2C_MSR_SDF))
+        {
+#ifndef CONFIG_I2C_POLLED
+          if (priv->intstate == INTSTATE_WAITING)
+            {
+              /* inform the thread that transfer is complete
+               * and wake it up
+               */
+
+              priv->intstate = INTSTATE_DONE;
+
+              imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MIER_OFFSET,
+                                   LPI2C_MIER_TDIE | LPI2C_MIER_RDIE |
+                                   LPI2C_MIER_NDIE | LPI2C_MIER_ALIE |
+                                   LPI2C_MIER_SDIE | LPI2C_MIER_EPIE, 0);
+              nxsem_post(&priv->sem_isr);
+            }
+#else
+          priv->intstate = INTSTATE_DONE;
+#endif
+        }
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_isr
+ *
+ * Description:
+ *   Common I2C interrupt service routine
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_I2C_POLLED
+static int imx9_lpi2c_isr(int irq, void *context, void *arg)
+{
+  struct imx9_lpi2c_priv_s *priv = (struct imx9_lpi2c_priv_s *)arg;
+
+  DEBUGASSERT(priv != NULL);
+  return imx9_lpi2c_isr_process(priv);
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_clock_enable
+ *
+ * Description:
+ *   Ungate LPI2C clock
+ *
+ ****************************************************************************/
+
+static void imx9_lpi2c_clock_enable(struct imx9_lpi2c_priv_s *priv)
+{
+  imx9_ccm_gate_on(priv->config->clk_gate, true);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_clock_disable
+ *
+ * Description:
+ *   Gate LPI2C clock
+ *
+ ****************************************************************************/
+
+void imx9_lpi2c_clock_disable(struct imx9_lpi2c_priv_s *priv)
+{
+  imx9_ccm_gate_on(priv->config->clk_gate, false);
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_init
+ *
+ * Description:
+ *   Setup the I2C hardware, ready for operation with defaults
+ *
+ ****************************************************************************/
+
+static int imx9_lpi2c_init(struct imx9_lpi2c_priv_s *priv)
+{
+  /* Power-up and configure GPIOs */
+
+  /* Configure pins */
+
+  imx9_iomux_configure(priv->config->scl_pin);
+  imx9_iomux_configure(priv->config->sda_pin);
+
+  /* Enable power and reset the peripheral */
+
+  imx9_lpi2c_clock_enable(priv);
+
+  /* Reset LPI2C before configuring it */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCR_OFFSET, LPI2C_MCR_RST);
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCR_OFFSET, 0);
+
+  /* Disable doze mode (Set DOZEN bit in 1 to disable) */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCR_OFFSET, LPI2C_MCR_DOZEN);
+
+  /* Disable host request */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCFGR0_OFFSET,
+                       LPI2C_MCFG0_HREN | LPI2C_MCFG0_HRSEL,
+                       LPI2C_MCFG0_HRPOL);
+
+  /* Disable AUTOSTOP and turn NAK Ignore off */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCFGR1_OFFSET,
+                       LPI2C_MCFGR1_IGNACK | LPI2C_MCFGR1_AUTOSTOP, 0);
+
+  /* Set tx and rx watermarks */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MFCR_OFFSET,
+                    LPI2C_MFCR_TXWATER(0) | LPI2C_MFCR_RXWATER(0));
+
+  /* Force a frequency update */
+
+  priv->frequency = 0;
+  imx9_lpi2c_setclock(priv, 100000);
+
+  /* Set scl, sda glitch filters and busy idle */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCFGR2_OFFSET,
+                    LPI2C_MCFG2_BUSIDLE(priv->config->busy_idle) |
+                    LPI2C_MCFG2_FILTSCL_CYCLES(priv->config->filtscl) |
+                    LPI2C_MCFG2_FILTSDA_CYCLES(priv->config->filtsda));
+
+  /* Set pin low cycles to 0 (disable) */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCFGR3_OFFSET,
+                    LPI2C_MCFG3_PINLOW_CYCLES(0));
+
+  /* Attach ISRs */
+
+#ifndef CONFIG_I2C_POLLED
+  irq_attach(priv->config->irq, imx9_lpi2c_isr, priv);
+  up_enable_irq(priv->config->irq);
+#endif
+
+  /* Enable I2C */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCR_OFFSET, 0, LPI2C_MCR_MEN);
+  return OK;
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_deinit
+ *
+ * Description:
+ *   Shutdown the I2C hardware
+ *
+ ****************************************************************************/
+
+static int imx9_lpi2c_deinit(struct imx9_lpi2c_priv_s *priv)
+{
+  /* Disable I2C */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCR_OFFSET, LPI2C_MCR_MEN, 0);
+
+  /* Reset LPI2C */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCR_OFFSET, LPI2C_MCR_RST);
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MCR_OFFSET, 0);
+
+  /* Disable and detach interrupts */
+
+#ifndef CONFIG_I2C_POLLED
+  up_disable_irq(priv->config->irq);
+  irq_detach(priv->config->irq);
+#endif
+
+  /* Disable clocking */
+
+  imx9_lpi2c_clock_disable(priv);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Device Driver Operations
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: imx9_lpi2c_dma_command_configure
+ *
+ * Description:
+ *   Create a command TCD
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+static int imx9_lpi2c_dma_command_configure(struct imx9_lpi2c_priv_s *priv,
+                                            uint16_t *ccmd, uint32_t ncmd)
+{
+  struct imx9_edma_xfrconfig_s config;
+  memset(&config, 0, sizeof(config));
+
+  config.saddr  = (uintptr_t) ccmd;
+  config.daddr  = priv->config->base + IMX9_LPI2C_MTDR_OFFSET;
+  config.soff   = sizeof(uint16_t);
+  config.doff   = 0;
+  config.iter   = 1;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = EDMA_16BIT;
+  config.dsize  = EDMA_16BIT;
+  config.nbytes = sizeof(uint16_t) * ncmd;
+
+  up_clean_dcache((uintptr_t)config.saddr,
+                  (uintptr_t)config.saddr + config.nbytes);
+
+  return imx9_dmach_xfrsetup(priv->txdma, &config);
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_dma_data_configure
+ *
+ * Description:
+ *   Create a data TCD
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+static int imx9_lpi2c_dma_data_configure(struct imx9_lpi2c_priv_s *priv,
+                                         struct i2c_msg_s *msg)
+{
+  DMACH_HANDLE dma;
+  struct imx9_edma_xfrconfig_s config;
+  memset(&config, 0, sizeof(config));
+
+  config.iter   = msg->length;
+  config.flags  = EDMA_CONFIG_LINKTYPE_LINKNONE;
+  config.ssize  = EDMA_8BIT;
+  config.dsize  = EDMA_8BIT;
+  config.nbytes = sizeof(msg->buffer[0]);
+
+  if (msg->flags & I2C_M_READ)
+    {
+      dma           = priv->rxdma;
+      config.saddr  = priv->config->base + IMX9_LPI2C_MRDR_OFFSET;
+      config.daddr  = (uintptr_t) msg->buffer;
+      config.soff   = 0;
+      config.doff   = sizeof(msg->buffer[0]);
+      up_invalidate_dcache((uintptr_t)msg->buffer,
+                           (uintptr_t)msg->buffer + msg->length);
+    }
+  else
+    {
+      dma           = priv->txdma;
+      config.saddr  = (uintptr_t) msg->buffer;
+      config.daddr  = priv->config->base + IMX9_LPI2C_MTDR_OFFSET;
+      config.soff   = sizeof(msg->buffer[0]);
+      config.doff   = 0;
+      up_clean_dcache((uintptr_t)msg->buffer,
+                      (uintptr_t)msg->buffer + msg->length);
+    }
+
+  return imx9_dmach_xfrsetup(dma, &config) ? 0 : msg->length;
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_form_command_list
+ *
+ * Description:
+ *   Form the DMA command list
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+static int imx9_lpi2c_form_command_list(struct imx9_lpi2c_priv_s *priv,
+                                        struct i2c_msg_s *msg, int ncmds)
+{
+  ssize_t length = 0;
+
+  if (priv->flags & I2C_M_NOSTART)
+    {
+      if (priv->flags & I2C_M_READ)
+        {
+          /* No start read operation */
+
+          priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_RXD |
+                                 LPI2C_MTDR_DATA(msg->length - 1);
+        }
+    }
+  else
+    {
+      /* A start based read or write operation */
+
+      /* Create bus address with R/W */
+
+      uint16_t badd = (priv->flags & I2C_M_READ) ? I2C_READADDR8(msg->addr) :
+                                                   I2C_WRITEADDR8(msg->addr);
+
+      priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_START | LPI2C_MTDR_DATA(badd);
+
+      if (badd & I2C_READBIT)
+        {
+          length =  msg->length;
+          while (length)
+            {
+              if (length > 256u)
+                {
+                  priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_RXD |
+                                         LPI2C_MTDR_DATA(256u - 1);
+                  length -= 256u;
+                }
+              else
+                {
+                  priv->cmnds[ncmds++] = LPI2C_MTDR_CMD_RXD |
+                                         LPI2C_MTDR_DATA(length - 1);
+                  length = 0;
+                }
+            }
+        }
+    }
+
+  return ncmds;
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_dma_transfer
+ *
+ * Description:
+ *   DMA based I2C transfer function
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+static int imx9_lpi2c_dma_transfer(struct imx9_lpi2c_priv_s *priv)
+{
+  int m;
+  int ntotcmds = 0;
+  int ncmds = 0;
+  uint16_t *ccmnd = NULL;
+
+  /* Disable Interrupts */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MIER_OFFSET, 0);
+
+  /* Disable DMA */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MDER_OFFSET, LPI2C_MDER_TDDE |
+                                                     LPI2C_MDER_RDDE, 0);
+
+  /* Enable AUTOSTOP and NAK Ignore */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCFGR1_OFFSET, 0,
+                       LPI2C_MCFGR1_IGNACK | LPI2C_MCFGR1_AUTOSTOP);
+
+  /* Form chains of TCDs to process the messages */
+
+  for (m = 0; m < priv->msgc; m++)
+    {
+      ncmds = 0;
+      priv->flags = priv->msgv[m].flags;
+
+      /* Form a command list */
+
+      ccmnd = &priv->cmnds[ntotcmds];
+
+      ncmds = imx9_lpi2c_form_command_list(priv, &priv->msgv[m], ntotcmds);
+
+      /* Have commands for this message ? */
+
+      if (ncmds != 0)
+        {
+          /* Build up a TCD with the command from this message */
+
+          imx9_lpi2c_dma_command_configure(priv, ccmnd, ncmds - ntotcmds);
+
+          ntotcmds += ncmds;
+
+          DEBUGASSERT(ntotcmds < CONFIG_IMX9_LPI2C_DMA_MAXMSG);
+
+          imx9_lpi2c_dma_data_configure(priv, &priv->msgv[m]);
+        }
+    }
+
+  /* Clear the TX and RX FIFOs */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MCR_OFFSET, 0,
+                       LPI2C_MCR_RTF | LPI2C_MCR_RRF);
+
+  /* Reset the Error bits */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MSR_OFFSET, LPI2C_MSR_NDF |
+                                                 LPI2C_MSR_ALF |
+                                                 LPI2C_MSR_FEF);
+
+  /* Enable the Iterrupts */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MIER_OFFSET,
+                    LPI2C_MIER_NDIE | LPI2C_MIER_ALIE |
+                    LPI2C_MIER_PLTIE);
+
+  /* Start The DMA */
+
+  imx9_dmach_start(priv->rxdma, imx9_rxdma_callback, (void *)priv);
+  imx9_dmach_start(priv->txdma, imx9_txdma_callback, (void *)priv);
+
+  /* Enable the DMA Request */
+
+  imx9_lpi2c_modifyreg(priv, IMX9_LPI2C_MDER_OFFSET, 0,
+                       LPI2C_MDER_TDDE | LPI2C_MDER_RDDE);
+  return OK;
+}
+#endif
+
+/****************************************************************************
+ * Name: imx9_lpi2c_transfer
+ *
+ * Description:
+ *   Generic I2C transfer function
+ *
+ ****************************************************************************/
+
+static int imx9_lpi2c_transfer(struct i2c_master_s *dev,
+                               struct i2c_msg_s *msgs, int count)
+{
+  struct imx9_lpi2c_priv_s *priv = (struct imx9_lpi2c_priv_s *)dev;
+  int ret;
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  int m;
+#endif
+
+  DEBUGASSERT(count > 0);
+
+  /* Ensure that address or flags don't change meanwhile */
+
+  ret = nxmutex_lock(&priv->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  /* Clear any pending error interrupts */
+
+  imx9_lpi2c_putreg(priv, IMX9_LPI2C_MSR_OFFSET, 0xffffffff);
+
+  /* Old transfers are done */
+
+  /* Reset ptr and dcnt to ensure an unexpected data interrupt doesn't
+   * overwrite stale data.
+   */
+
+  priv->dcnt  = 0;
+  priv->ptr   = NULL;
+
+  priv->msgv  = msgs;
+  priv->msgc  = count;
+  priv->flags = msgs->flags;
+
+  i2cinfo("Flags %x, len %ld\n", msgs->flags, msgs->length);
+
+  /* Reset I2C trace logic */
+
+  imx9_lpi2c_tracereset(priv);
+
+  /* Set I2C clock frequency */
+
+  imx9_lpi2c_setclock(priv, msgs->frequency);
+
+  priv->status = 0;
+
+  /* Signal the interrupt handler that we are waiting.  NOTE:  Interrupts
+   * are currently disabled but will be temporarily re-enabled below when
+   * nxsem_tickwait_uninterruptible() sleeps.
+   */
+
+  priv->intstate = INTSTATE_WAITING;
+
+  /* Wait for an ISR, if there was a timeout, fetch latest status to get
+   * the BUSY flag.
+   */
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  if (priv->rxdma || priv->txdma)
+    {
+      imx9_lpi2c_dma_transfer(priv);
+    }
+#endif
+
+  if (imx9_lpi2c_sem_waitdone(priv) < 0)
+    {
+#ifdef CONFIG_IMX9_LPI2C_DMA
+      if (priv->rxdma != NULL)
+        {
+          imx9_dmach_stop(priv->rxdma);
+        }
+
+      if (priv->txdma != NULL)
+        {
+          imx9_dmach_stop(priv->txdma);
+        }
+
+#endif
+      ret = -ETIMEDOUT;
+      i2cerr("ERROR: Timed out: MSR: status: 0x0%" PRIx32 "\n",
+             priv->status);
+    }
+
+  /* Check for error status conditions */
+
+  else if ((priv->status & LPI2C_MSR_ERROR_MASK) != 0)
+    {
+      /* I2C_SR1_ERRORMASK is the 'OR' of the following individual bits: */
+
+      if (priv->status & LPI2C_MSR_ALF)
+        {
+          /* Arbitration Lost (master mode) */
+
+          i2cerr("Arbitration lost\n");
+          ret = -EAGAIN;
+        }
+      else if (priv->status & LPI2C_MSR_NDF)
+        {
+          /* Acknowledge Failure */
+
+          i2cerr("Ack failure\n");
+          ret = -ENXIO;
+        }
+      else
+        {
+          /* FIFO Error */
+
+          i2cerr("Transfer without start condition\n");
+          ret = -EINVAL;
+        }
+    }
+
+  /* Dump the trace result */
+
+  imx9_lpi2c_tracedump(priv);
+
+  /* Ensure that any ISR happening after we finish can't overwrite any user
+   * data.
+   */
+
+  priv->dcnt = 0;
+  priv->ptr = NULL;
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  if (priv->rxdma)
+    {
+      for (m = 0; m < count; m++)
+        {
+          if (msgs[m].flags & I2C_M_READ)
+            {
+              up_invalidate_dcache((uintptr_t)msgs[m].buffer,
+                                   (uintptr_t)msgs[m].buffer +
+                                              msgs[m].length);
+            }
+        }
+    }
+#endif
+
+  nxmutex_unlock(&priv->lock);
+  return ret;
+}
+
+/****************************************************************************
+ * Name: imx9_lpi2c_reset
+ *
+ * Description:
+ *   Perform an I2C bus reset in an attempt to break loose stuck I2C devices.
+ *
+ * Input Parameters:
+ *   dev   - Device-specific state data
+ *
+ * Returned Value:
+ *   Zero (OK) on success; a negated errno value on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_I2C_RESET
+static int imx9_lpi2c_reset(struct i2c_master_s *dev)
+{
+  struct imx9_lpi2c_priv_s *priv = (struct imx9_lpi2c_priv_s *)dev;
+  unsigned int clock_count;
+  unsigned int stretch_count;
+  uint32_t scl_gpio;
+  uint32_t sda_gpio;
+  uint32_t frequency;
+  int ret;
+
+  DEBUGASSERT(dev);
+
+  /* Our caller must own a ref */
+
+  DEBUGASSERT(priv->refs > 0);
+
+  /* Lock out other clients */
+
+  ret = nxmutex_lock(&priv->lock);
+  if (ret < 0)
+    {
+      return ret;
+    }
+
+  ret = -EIO;
+
+  /* Save the current frequency */
+
+  frequency = priv->frequency;
+
+  /* De-init the port */
+
+  imx9_lpi2c_deinit(priv);
+
+  /* Use GPIO configuration to un-wedge the bus */
+
+  imx9_iomux_gpio(priv->config->scl_pin, true);
+  imx9_iomux_gpio(priv->config->sda_pin, true);
+
+  scl_gpio = priv->config->reset_scl_pin;
+  sda_gpio = priv->config->reset_sda_pin;
+
+  imx9_config_gpio(scl_gpio);
+  imx9_config_gpio(sda_gpio);
+
+  /* Let SDA go high */
+
+  imx9_gpio_write(sda_gpio, 1);
+
+  /* Clock the bus until any slaves currently driving it let it go. */
+
+  clock_count = 0;
+  while (!imx9_gpio_read(sda_gpio))
+    {
+      /* Give up if we have tried too hard */
+
+      if (clock_count++ > 10)
+        {
+          goto out;
+        }
+
+      /* Sniff to make sure that clock stretching has finished.
+       *
+       * If the bus never relaxes, the reset has failed.
+       */
+
+      stretch_count = 0;
+      while (!imx9_gpio_read(scl_gpio))
+        {
+          /* Give up if we have tried too hard */
+
+          if (stretch_count++ > 10)
+            {
+              goto out;
+            }
+
+          up_udelay(10);
+        }
+
+      /* Drive SCL low */
+
+      imx9_gpio_write(scl_gpio, 0);
+      up_udelay(10);
+
+      /* Drive SCL high again */
+
+      imx9_gpio_write(scl_gpio, 1);
+      up_udelay(10);
+    }
+
+  /* Generate a start followed by a stop to reset slave
+   * state machines.
+   */
+
+  imx9_gpio_write(sda_gpio, 0);
+  up_udelay(10);
+  imx9_gpio_write(scl_gpio, 0);
+  up_udelay(10);
+  imx9_gpio_write(scl_gpio, 1);
+  up_udelay(10);
+  imx9_gpio_write(sda_gpio, 1);
+  up_udelay(10);
+
+  /* Re-init the port */
+
+  imx9_lpi2c_init(priv);
+
+  /* Restore the frequency */
+
+  imx9_lpi2c_setclock(priv, frequency);
+  ret = OK;
+
+out:
+
+  /* Release the port for re-use by other clients */
+
+  nxmutex_unlock(&priv->lock);
+  return ret;
+}
+#endif /* CONFIG_I2C_RESET */
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: imx9_i2cbus_initialize
+ *
+ * Description:
+ *   Initialize one I2C bus
+ *
+ ****************************************************************************/
+
+struct i2c_master_s *imx9_i2cbus_initialize(int port)
+{
+  struct imx9_lpi2c_priv_s * priv = NULL;
+  irqstate_t flags;
+
+  /* Get I2C private structure */
+
+  switch (port)
+    {
+#ifdef CONFIG_IMX9_LPI2C1
+    case 1:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c1_priv;
+      break;
+#endif
+#ifdef CONFIG_IMX9_LPI2C2
+    case 2:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c2_priv;
+      break;
+#endif
+#ifdef CONFIG_IMX9_LPI2C3
+    case 3:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c3_priv;
+      break;
+#endif
+#ifdef CONFIG_IMX9_LPI2C4
+    case 4:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c4_priv;
+      break;
+#endif
+#ifdef CONFIG_IMX9_LPI2C5
+    case 5:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c5_priv;
+      break;
+#endif
+#ifdef CONFIG_IMX9_LPI2C6
+    case 6:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c6_priv;
+      break;
+#endif
+#ifdef CONFIG_IMX9_LPI2C7
+    case 7:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c7_priv;
+      break;
+#endif
+#ifdef CONFIG_IMX9_LPI2C8
+    case 8:
+      priv = (struct imx9_lpi2c_priv_s *)&imx9_lpi2c8_priv;
+      break;
+#endif
+    default:
+      return NULL;
+    }
+
+  /* Initialize private data for the first time, increment reference count,
+   * power-up hardware and configure GPIOs.
+   */
+
+  flags = enter_critical_section();
+
+  if ((volatile int)priv->refs++ == 0)
+    {
+      imx9_lpi2c_init(priv);
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+      if (priv->config->dma_txreqsrc != 0)
+        {
+          priv->txdma = imx9_dmach_alloc(priv->config->dma_txreqsrc, 0);
+          DEBUGASSERT(priv->txdma != NULL);
+        }
+
+      if (priv->config->dma_rxreqsrc != 0)
+        {
+          priv->rxdma = imx9_dmach_alloc(priv->config->dma_rxreqsrc, 0);
+          DEBUGASSERT(priv->rxdma != NULL);
+        }
+#endif
+    }
+
+  leave_critical_section(flags);
+
+  return (struct i2c_master_s *)priv;
+}
+
+/****************************************************************************
+ * Name: imx9_i2cbus_uninitialize
+ *
+ * Description:
+ *   Uninitialize an I2C bus
+ *
+ ****************************************************************************/
+
+int imx9_i2cbus_uninitialize(struct i2c_master_s *dev)
+{
+  struct imx9_lpi2c_priv_s *priv = (struct imx9_lpi2c_priv_s *)dev;
+  irqstate_t flags;
+
+  DEBUGASSERT(dev);
+
+  /* Decrement reference count and check for underflow */
+
+  if (priv->refs == 0)
+    {
+      return ERROR;
+    }
+
+  flags = enter_critical_section();
+
+  if (--priv->refs > 0)
+    {
+      leave_critical_section(flags);
+      return OK;
+    }
+
+  leave_critical_section(flags);
+
+  /* Disable power and other HW resource (GPIO's) */
+
+#ifdef CONFIG_IMX9_LPI2C_DMA
+  if (priv->rxdma != NULL)
+    {
+      imx9_dmach_stop(priv->rxdma);
+      imx9_dmach_free(priv->rxdma);
+      priv->rxdma = NULL;
+    }
+
+  if (priv->txdma != NULL)
+    {
+      imx9_dmach_stop(priv->txdma);
+      imx9_dmach_free(priv->txdma);
+      priv->txdma = NULL;
+    }
+#endif
+
+  imx9_lpi2c_deinit(priv);
+
+  return OK;
+}
+
+#endif /* CONFIG_IMX9_LPI2C */
diff --git a/boards/arm64/imx9/imx93-evk/src/imx93-evk.h 
b/arch/arm64/src/imx9/imx9_lpi2c.h
similarity index 59%
copy from boards/arm64/imx9/imx93-evk/src/imx93-evk.h
copy to arch/arm64/src/imx9/imx9_lpi2c.h
index 4b9c0f3a46..d323871fa3 100644
--- a/boards/arm64/imx9/imx93-evk/src/imx93-evk.h
+++ b/arch/arm64/src/imx9/imx9_lpi2c.h
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/arm64/imx9/imx93-evk/src/imx93-evk.h
+ * arch/arm64/src/imx9/imx9_lpi2c.h
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -18,54 +18,54 @@
  *
  ****************************************************************************/
 
-#ifndef __BOARDS_ARM64_IMX9_IMX93_EVK_SRC_IMX93_EVK_H
-#define __BOARDS_ARM64_IMX9_IMX93_EVK_SRC_IMX93_EVK_H
+#ifndef __ARCH_ARM64_SRC_IMX9_IMX9_LPI2C_H
+#define __ARCH_ARM64_SRC_IMX9_IMX9_LPI2C_H
 
 /****************************************************************************
  * Included Files
  ****************************************************************************/
 
 #include <nuttx/config.h>
-
-#include <stdint.h>
-
-/****************************************************************************
- * Public Types
- ****************************************************************************/
-
-/****************************************************************************
- * Public Data
- ****************************************************************************/
-
-#ifndef __ASSEMBLY__
+#include <nuttx/i2c/i2c_master.h>
 
 /****************************************************************************
- * Public Functions Definitions
+ * Public Function Prototypes
  ****************************************************************************/
 
 /****************************************************************************
- * Name: imx9_bringup
+ * Name: imx9_i2cbus_initialize
  *
  * Description:
- *   Bring up board features
+ *   Initialize the selected I2C port. And return a unique instance of struct
+ *   struct i2c_master_s.  This function may be called to obtain multiple
+ *   instances of the interface, each of which may be set up with a
+ *   different frequency and slave address.
+ *
+ * Input Parameters:
+ *   Port number (for hardware that has multiple I2C interfaces)
+ *
+ * Returned Value:
+ *   Valid I2C device structure reference on success; a NULL on failure
  *
  ****************************************************************************/
 
-#if defined(CONFIG_BOARDCTL) || defined(CONFIG_BOARD_LATE_INITIALIZE)
-int imx9_bringup(void);
-#endif
+struct i2c_master_s *imx9_i2cbus_initialize(int port);
 
 /****************************************************************************
- * Name: imx9_pwm_setup
+ * Name: imx9_i2cbus_uninitialize
  *
  * Description:
- *   Initialize PWM outputs
+ *   De-initialize the selected I2C port, and power down the device.
+ *
+ * Input Parameters:
+ *   Device structure as returned by the imx9_i2cbus_initialize()
+ *
+ * Returned Value:
+ *   OK on success, ERROR when internal reference count mismatch or dev
+ *   points to invalid hardware device.
  *
  ****************************************************************************/
 
-#if defined(CONFIG_PWM)
-int imx9_pwm_setup(void);
-#endif
+int imx9_i2cbus_uninitialize(struct i2c_master_s *dev);
 
-#endif /* __ASSEMBLY__ */
-#endif /* __BOARDS_ARM64_IMX9_IMX93_EVK_SRC_IMX93_EVK_H */
+#endif /* __ARCH_ARM64_SRC_IMX9_IMX9_LPI2C_H */
diff --git a/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig 
b/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig
index e1834dc8ed..64c7f53357 100644
--- a/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig
+++ b/boards/arm64/imx9/imx93-evk/configs/nsh/defconfig
@@ -28,9 +28,14 @@ CONFIG_FS_PROCFS=y
 CONFIG_FS_ROMFS=y
 CONFIG_HAVE_CXX=y
 CONFIG_HAVE_CXXINITIALIZE=y
+CONFIG_I2C=y
+CONFIG_I2C_RESET=y
 CONFIG_IDLETHREAD_STACKSIZE=8192
 CONFIG_IMX9_FLEXIO1_PWM=y
 CONFIG_IMX9_GPIO_IRQ=y
+CONFIG_IMX9_LPI2C1=y
+CONFIG_IMX9_LPI2C_DYNTIMEO=y
+CONFIG_IMX9_LPI2C_DYNTIMEO_STARTSTOP=10
 CONFIG_IMX9_TPM3_PWM=y
 CONFIG_IMX9_TPM3_PWM_CHMUX=0x00000003
 CONFIG_IMX9_UART1=y
@@ -60,6 +65,7 @@ CONFIG_START_MONTH=3
 CONFIG_START_YEAR=2022
 CONFIG_SYMTAB_ORDEREDBYNAME=y
 CONFIG_SYSTEM_CDCACM=y
+CONFIG_SYSTEM_I2CTOOL=y
 CONFIG_SYSTEM_NSH=y
 CONFIG_SYSTEM_SYSTEM=y
 CONFIG_SYSTEM_TIME64=y
diff --git a/boards/arm64/imx9/imx93-evk/include/board.h 
b/boards/arm64/imx9/imx93-evk/include/board.h
index bd78f1cf79..6cd4c26e56 100644
--- a/boards/arm64/imx9/imx93-evk/include/board.h
+++ b/boards/arm64/imx9/imx93-evk/include/board.h
@@ -31,6 +31,8 @@
  * Pre-processor Definitions
  ****************************************************************************/
 
+#define IOMUX_LPI2C_DEFAULT  (IOMUXC_PAD_OD_ENABLE | IOMUXC_PAD_FSEL_SFAST | 
IOMUXC_PAD_DSE_X6)
+
 /* FLEXIO to PWM pin muxings */
 
 /* EVK signals
@@ -49,6 +51,16 @@
 
 #define TPM3_PWM3_MUX IOMUX_CFG(IOMUXC_PAD_GPIO_IO24_TPM3_CH3, 
IOMUXC_PAD_FSEL_SFAST | IOMUXC_PAD_DSE_X6, 0)
 
+/* LPI2Cs */
+
+#define MUX_LPI2C1_SCL       IOMUX_CFG(IOMUXC_PAD_I2C1_SCL_LPI2C1_SCL, 
IOMUX_LPI2C_DEFAULT, IOMUXC_MUX_SION_ON)
+#define MUX_LPI2C1_SDA       IOMUX_CFG(IOMUXC_PAD_I2C1_SDA_LPI2C1_SDA, 
IOMUX_LPI2C_DEFAULT, IOMUXC_MUX_SION_ON)
+
+/* I2C reset functionality */
+
+#define GPIO_LPI2C1_SCL_RESET  (GPIO_PORT1 | GPIO_PIN0 | GPIO_OUTPUT | 
GPIO_OUTPUT_ONE)
+#define GPIO_LPI2C1_SDA_RESET  (GPIO_PORT1 | GPIO_PIN1 | GPIO_OUTPUT | 
GPIO_OUTPUT_ONE)
+
 /****************************************************************************
  * Public Data
  ****************************************************************************/
diff --git a/boards/arm64/imx9/imx93-evk/src/Makefile 
b/boards/arm64/imx9/imx93-evk/src/Makefile
index fc2ce19a0c..564a2db926 100644
--- a/boards/arm64/imx9/imx93-evk/src/Makefile
+++ b/boards/arm64/imx9/imx93-evk/src/Makefile
@@ -30,4 +30,8 @@ ifeq ($(CONFIG_PWM),y)
 CSRCS += imx9_pwm.c
 endif
 
+ifeq ($(CONFIG_IMX9_LPI2C),y)
+CSRCS += imx9_i2c.c
+endif
+
 include $(TOPDIR)/boards/Board.mk
diff --git a/boards/arm64/imx9/imx93-evk/src/imx93-evk.h 
b/boards/arm64/imx9/imx93-evk/src/imx93-evk.h
index 4b9c0f3a46..1da0b3b88e 100644
--- a/boards/arm64/imx9/imx93-evk/src/imx93-evk.h
+++ b/boards/arm64/imx9/imx93-evk/src/imx93-evk.h
@@ -67,5 +67,17 @@ int imx9_bringup(void);
 int imx9_pwm_setup(void);
 #endif
 
+/****************************************************************************
+ * Name: imx9_i2c_setup
+ *
+ * Description:
+ *   Initialize I2C devices and driver
+ *
+ ****************************************************************************/
+
+#if defined(CONFIG_I2C_DRIVER)
+int imx9_i2c_initialize(void);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_ARM64_IMX9_IMX93_EVK_SRC_IMX93_EVK_H */
diff --git a/boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c 
b/boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c
index 7443f92ccd..876b9014de 100644
--- a/boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c
+++ b/boards/arm64/imx9/imx93-evk/src/imx9_boardinit.c
@@ -23,8 +23,11 @@
  ****************************************************************************/
 
 #include <nuttx/config.h>
+
 #include <stdint.h>
+
 #include <nuttx/board.h>
+
 #include "imx93-evk.h"
 
 /****************************************************************************
diff --git a/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c 
b/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c
index fc30e67cff..6048509b67 100644
--- a/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c
+++ b/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c
@@ -67,6 +67,16 @@ int imx9_bringup(void)
     }
 #endif
 
+#if defined(CONFIG_I2C_DRIVER)
+  /* Configure I2C peripheral interfaces */
+
+  ret = imx9_i2c_initialize();
+  if (ret < 0)
+    {
+      syslog(LOG_ERR, "Failed to initialize I2C driver: %d\n", ret);
+    }
+#endif
+
   UNUSED(ret);
   return OK;
 }
diff --git a/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c 
b/boards/arm64/imx9/imx93-evk/src/imx9_i2c.c
similarity index 68%
copy from boards/arm64/imx9/imx93-evk/src/imx9_bringup.c
copy to boards/arm64/imx9/imx93-evk/src/imx9_i2c.c
index fc30e67cff..ac30b5da2d 100644
--- a/boards/arm64/imx9/imx93-evk/src/imx9_bringup.c
+++ b/boards/arm64/imx9/imx93-evk/src/imx9_i2c.c
@@ -1,5 +1,5 @@
 /****************************************************************************
- * boards/arm64/imx9/imx93-evk/src/imx9_bringup.c
+ * boards/arm64/imx9/imx93-evk/src/imx9_i2c.c
  *
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -24,49 +24,54 @@
 
 #include <nuttx/config.h>
 
+#include <debug.h>
+#include <errno.h>
 #include <sys/types.h>
-#include <syslog.h>
 
-#include <nuttx/fs/fs.h>
+#include <nuttx/i2c/i2c_master.h>
 
-#include "imx93-evk.h"
+#include "imx9_lpi2c.h"
 
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
 
 /****************************************************************************
- * Name: imx_bringup
+ * Name: board_i2c_init
  *
  * Description:
- *   Bring up board features
+ *   Configure the I2C driver.
+ *
+ * Returned Value:
+ *   Zero (OK) is returned on success; A negated errno value is returned
+ *   to indicate the nature of any failure.
  *
  ****************************************************************************/
 
-int imx9_bringup(void)
+int imx9_i2c_initialize(void)
 {
-  int ret;
+  int ret = OK;
 
-#ifdef CONFIG_FS_PROCFS
-  /* Mount the procfs file system */
+#ifdef CONFIG_IMX9_LPI2C1
+  struct i2c_master_s *i2c;
 
-  ret = nx_mount(NULL, "/proc", "procfs", 0, NULL);
-  if (ret < 0)
+  i2c = imx9_i2cbus_initialize(1);
+  if (i2c == NULL)
     {
-      syslog(LOG_ERR, "ERROR: Failed to mount procfs at /proc: %d\n", ret);
+      i2cerr("ERROR: Failed to init I2C0 interface\n");
+      return -ENODEV;
     }
 #endif
 
-#ifdef CONFIG_PWM
-  /* Configure PWM outputs */
-
-  ret = imx9_pwm_setup();
+#ifdef CONFIG_I2C_DRIVER
+  ret = i2c_register(i2c, 0);
   if (ret < 0)
     {
-      syslog(LOG_ERR, "ERROR: Failed initialize PWM outputs: %d\n", ret);
+      i2cerr("ERROR: Failed to register I2C0 driver: %d\n", ret);
+      imx9_i2cbus_uninitialize(i2c);
+      return ret;
     }
 #endif
 
-  UNUSED(ret);
   return OK;
 }


Reply via email to