[linux-yocto] [PATCH 03/87] drivers/i2c/busses: adding ai2c driver
Paul Butler
butler.paul at gmail.com
Mon May 27 09:55:34 PDT 2013
Signed-off-by: Paul Butler <paul.butler at windriver.com>
---
drivers/i2c/busses/Kconfig | 9 +
drivers/i2c/busses/Makefile | 2 +
drivers/i2c/busses/ai2c/Makefile | 19 +
drivers/i2c/busses/ai2c/ai2c_bus.h | 322 ++++
drivers/i2c/busses/ai2c/ai2c_bus_acp3400.c | 150 ++
drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c | 638 +++++++
drivers/i2c/busses/ai2c/ai2c_dev.h | 109 ++
drivers/i2c/busses/ai2c/ai2c_dev_clock.c | 494 ++++++
drivers/i2c/busses/ai2c/ai2c_dev_clock_ext.h | 41 +
drivers/i2c/busses/ai2c/ai2c_dev_pvt.h | 170 ++
drivers/i2c/busses/ai2c/ai2c_mod.c | 351 ++++
drivers/i2c/busses/ai2c/ai2c_plat.c | 842 +++++++++
drivers/i2c/busses/ai2c/ai2c_plat.h | 283 +++
drivers/i2c/busses/ai2c/ai2c_plat_pvt.h | 74 +
drivers/i2c/busses/ai2c/ai2c_sal.c | 106 ++
drivers/i2c/busses/ai2c/ai2c_sal.h | 48 +
drivers/i2c/busses/ai2c/ai2c_sal_linux.h | 318 ++++
drivers/i2c/busses/ai2c/ai2c_sal_types.h | 48 +
drivers/i2c/busses/ai2c/ai2c_types.h | 84 +
drivers/i2c/busses/ai2c/regs/ai2c_axi_timer_regs.h | 202 +++
.../busses/ai2c/regs/ai2c_cfg_node_reg_defines.h | 39 +
drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_regs.h | 146 ++
drivers/i2c/busses/ai2c/regs/ai2c_i2c_regs.h | 1797 ++++++++++++++++++++
drivers/i2c/busses/ai2c/regs/ai2c_regions.h | 82 +
24 files changed, 6374 insertions(+)
create mode 100644 drivers/i2c/busses/ai2c/Makefile
create mode 100644 drivers/i2c/busses/ai2c/ai2c_bus.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_bus_acp3400.c
create mode 100644 drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c
create mode 100644 drivers/i2c/busses/ai2c/ai2c_dev.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_dev_clock.c
create mode 100644 drivers/i2c/busses/ai2c/ai2c_dev_clock_ext.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_dev_pvt.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_mod.c
create mode 100644 drivers/i2c/busses/ai2c/ai2c_plat.c
create mode 100644 drivers/i2c/busses/ai2c/ai2c_plat.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_plat_pvt.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_sal.c
create mode 100644 drivers/i2c/busses/ai2c/ai2c_sal.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_sal_linux.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_sal_types.h
create mode 100644 drivers/i2c/busses/ai2c/ai2c_types.h
create mode 100644 drivers/i2c/busses/ai2c/regs/ai2c_axi_timer_regs.h
create mode 100644 drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_reg_defines.h
create mode 100644 drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_regs.h
create mode 100644 drivers/i2c/busses/ai2c/regs/ai2c_i2c_regs.h
create mode 100644 drivers/i2c/busses/ai2c/regs/ai2c_regions.h
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 57ddada..58acc26 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -916,4 +916,13 @@ config SCx200_ACB
This support is also available as a module. If so, the module
will be called scx200_acb.
+config I2C_AXXIA
+ tristate "Axxia I2C bus support"
+ select I2C_ALGOBIT
+ default y
+ help
+ Say yes if you want to support the I2C bus on Axxia platforms.
+
+ If you don't know, say Y.
+
endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 2f05d7b..69e0e13 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -90,3 +90,5 @@ obj-$(CONFIG_SCx200_ACB) += scx200_acb.o
obj-$(CONFIG_SCx200_I2C) += scx200_i2c.o
ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
+
+obj-y += ai2c/
diff --git a/drivers/i2c/busses/ai2c/Makefile b/drivers/i2c/busses/ai2c/Makefile
new file mode 100644
index 0000000..f8b232f
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/Makefile
@@ -0,0 +1,19 @@
+#
+# Makefile for the lsi_acp_i2c driver.
+#
+
+MODULE := lsi_acp_i2c
+
+obj-$(CONFIG_I2C_AXXIA) += $(MODULE).o
+
+$(MODULE)-objs := ai2c_mod.o \
+ ai2c_plat.o \
+ ai2c_bus_acp3400.o \
+ ai2c_bus_axm5500.o \
+ ai2c_dev_clock.o \
+ ai2c_sal.o
+
+ccflags-$(CONFIG_I2C_AXXIA) := -DAI2C_MOD_NAME=\"ai2c\" \
+ -DAI2C_MSG_TRACE_LEVEL=ai2c_trace_level \
+ -DLINUX -DAI2C_PLATFORM_BUILD \
+ -DAI2C_CHIP_VER=9
diff --git a/drivers/i2c/busses/ai2c/ai2c_bus.h b/drivers/i2c/busses/ai2c/ai2c_bus.h
new file mode 100644
index 0000000..97c9fe5
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_bus.h
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_bus.h
+ * @brief Constants, structs, and APIs used to communicate with the
+ * direct ACP I2C Hardware Layer registers
+ */
+
+#ifndef AI2C_BUS_H
+#define AI2C_BUS_H
+
+#include "ai2c_types.h"
+#include "regs/ai2c_i2c_regs.h"
+#include "ai2c_plat.h"
+
+/*****************************************************************************
+* Constants *
+*****************************************************************************/
+
+ /*****************************
+ * Common *
+ *****************************/
+
+/*! @def AI2C_I2CPROT_MAX_XFR_SIZE
+ @brief Maximum number of bytes that may be moved at one time over the
+ I2C bus.
+*/
+#define AI2C_I2CPROT_MAX_XFR_SIZE 8
+
+/*! @def AI2C_I2CPROT_MAX_BUF_SIZE
+ @brief Maximum number of bytes that may be stored at one time over
+ the I2C bus i.e. size of TXD0+TXD1.
+*/
+#define AI2C_I2CPROT_MAX_BUF_SIZE 8
+
+#define AI2C_I2C_CHECK_COUNT 0xFFFFF
+/* Max number of tries at looking for an I/O success */
+
+ /*****************************
+ * ACP3400 *
+ *****************************/
+
+/*! @def AI2C_I2CPROT_MAX_XFR_BOUND
+ @brief Value mask that is anded with any I2C offset to determine a
+ write transfer boundary. If a transfer is going to cross this
+ byte boundary, it should be broken into two smaller write
+ transactions before and after the boundary.
+*/
+#define AI2C_I2CPROT_MAX_XFR_BOUND (AI2C_I2CPROT_MAX_XFR_SIZE-1)
+
+/*
+ * Device-specific macros and tests for command manipulation
+ */
+#define AI2C_I2CPROT_MASK_TENBIT_ENABLE (0x0001)
+#define AI2C_I2CPROT_MASK_TENBIT_DISABLE (0x0002)
+#define AI2C_I2CPROT_MASK_TENBIT_CONSECUTIVE (0x0004)
+
+#define TENBIT_SETENABLED(ioc) {(ioc)->tenBitMode = \
+ AI2C_I2CPROT_MASK_TENBIT_ENABLE; }
+#define TENBIT_SETDISABLED(ioc) {(ioc)->tenBitMode = \
+ AI2C_I2CPROT_MASK_TENBIT_DISABLE; }
+#define TENBIT_SETCONSECUTIVE(ioc) {(ioc)->tenBitMode |= \
+ AI2C_I2CPROT_MASK_TENBIT_CONSECUTIVE; }
+#define TENBIT_CLRCONSECUTIVE(ioc) {(ioc)->tenBitMode &= \
+ ~AI2C_I2CPROT_MASK_TENBIT_CONSECUTIVE; }
+#define TENBIT_IFENABLED(ioc) ((ioc)->tenBitMode & \
+ AI2C_I2CPROT_MASK_TENBIT_ENABLE)
+#define TENBIT_IFDISABLED(ioc) ((ioc)->tenBitMode & \
+ AI2C_I2CPROT_MASK_TENBIT_DISABLE)
+#define TENBIT_IFCONSECUTIVE(ioc) ((ioc)->tenBitMode & \
+ AI2C_I2CPROT_MASK_TENBIT_CONSECUTIVE)
+
+#define DEV_10BIT_AUTO(ioc) TENBIT_SETENABLED(ioc)
+
+
+/*
+ * Application-specific (BUS) timing constants, types, etc.
+ */
+
+#define CFG_CLK_CONFIG_SCL_LOW (1000) /* (MCC-0x143.0x0.0x1c)
+ bits 9:0 (MCC LPD) */
+#define CFG_CLK_CONFIG_SCL_HIGH (1000) /* (MCC-0x143.0x0.0x1c)
+ bits 25:16 (MCC HPD) */
+#define CFG_START_SETUP_PERIOD (940) /* (MSTSHC-0x143.0x0.0x20)
+ bits 9:0 (MSTSHC SETDU) */
+#define CFG_START_HOLD_PERIOD (800) /* (MSTSHC-0x143.0x0.0x20)
+ bits 25:16 (MSTSHC HLDDU) */
+#define CFG_STOP_SETUP_PERIOD (800) /* (MSPSHC-0x143.0x0.0x24)
+ bits 9:0 (MSPSHC SETDU) */
+#define CFG_STOP_HOLD_PERIOD (0) /* (MSPSHC-0x143.0x0.0x24)
+ bits 25:16 (MSPSHC HLDDU) */
+#define CFG_DATA_SETUP_PERIOD (50) /* (MDSHC-0x143.0x0.0x28)
+ bits 9:0 (MDSHC SETDU) */
+#define CFG_DATA_HOLD_PERIOD (0) /* (MSPSHC-0x143.0x0.0x28)
+ bits 25:16 (MDSHC HLDDU) */
+
+/*! @def AI2C_I2C_IOCONFIG_READ_DEFAULT
+ * @brief Easy default initialization for ai2c_i2c_config_acp3400_t.readTiming.
+ */
+#define AI2C_I2C_IOCONFIG_READ_DEFAULT \
+{ \
+ CFG_CLK_CONFIG_SCL_HIGH, \
+ CFG_CLK_CONFIG_SCL_LOW, \
+ CFG_START_SETUP_PERIOD, \
+ CFG_START_HOLD_PERIOD, \
+ CFG_STOP_SETUP_PERIOD, \
+ CFG_STOP_HOLD_PERIOD, \
+ CFG_DATA_SETUP_PERIOD, \
+ CFG_DATA_HOLD_PERIOD, \
+}
+
+/*! @def AI2C_I2C_IOCONFIG_WRITE_DEFAULT
+ * @brief Easy default initialization for ai2c_i2c_config_acp3400_t.writeTiming.
+ */
+#define AI2C_I2C_IOCONFIG_WRITE_DEFAULT \
+{ \
+ CFG_CLK_CONFIG_SCL_HIGH, \
+ CFG_CLK_CONFIG_SCL_LOW, \
+ CFG_START_SETUP_PERIOD, \
+ CFG_START_HOLD_PERIOD, \
+ CFG_STOP_SETUP_PERIOD, \
+ CFG_STOP_HOLD_PERIOD, \
+ CFG_DATA_SETUP_PERIOD, \
+ CFG_DATA_HOLD_PERIOD, \
+}
+
+#define AI2C_I2C_IOCONFIG_WAITPOSTWRITE_DEFAULT (5000) /* 5ms for each */
+#define AI2C_I2C_IOCONFIG_WAITPOSTREAD_DEFAULT (0) /* 0ms for each */
+
+
+/*****************************************************************************
+* Type definitions *
+*****************************************************************************/
+
+ /*******************************************
+ * Common Protocol State & Callbacks
+ ********************************************/
+
+/*! @typedef ai2c_bus_init_t
+ @brief Signature for callback function that may be called from I2C
+ protocol to initialize environment for an ACP device.
+ @param[in] dev Device handle
+ @param[in] regionId Reference to specific bus within device
+ @returns success/failure of operation
+*/
+typedef int (*ai2c_bus_init_t)(
+ struct ai2c_priv *priv,
+ u32 i2cRegion);
+
+/*! @typedef ai2c_bus_block_write8_t
+ @brief Signature for callback function that may be called from I2C
+ protocol read/write operations to write 8-bit data to the
+ target device.
+ @param[in] dev Device handle
+ @param[in] regionId Bus reference handle
+ @param[in] *adap Ptr to I2C adapter
+ @param[in] *msg Ptr to next I2C message to process
+ @param[in] stop Op flag: append 'stop' to this msg
+ @returns success/failure of operation
+*/
+typedef int (*ai2c_bus_block_write8_t)(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_adapter *adap,
+ struct i2c_msg *msg,
+ int stop);
+
+/*! @typedef ai2c_bus_block_read8_t
+ @brief Signature for callback function that may be called from I2C
+ protocol read/write operations to read 8-bit data from the
+ target device.
+ @param[in] dev Device handle
+ @param[in] regionId Bus reference handle
+ @param[in] *adap Ptr to I2C adapter
+ @param[in] *msg Ptr to next I2C message to process
+ @param[in] stop Op flag: append 'stop' to this msg
+ @returns success/failure of operation
+*/
+typedef int (*ai2c_bus_block_read8_t)(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_adapter *adap,
+ struct i2c_msg *msg,
+ int stop);
+
+struct ai2c_i2c_access {
+ u32 seekPos;
+ u32 maxXfrSize;
+ /*!< Maximum number of bytes for a single
+ * data transfer */
+ u32 deviceLen;
+ /*!< Maximum number of bytes / seek location
+ * where 0 means ignore this setting */
+ ai2c_bus_init_t initFn;
+ ai2c_bus_block_write8_t wrFn;
+ ai2c_bus_block_read8_t rdFn;
+ void *extra;
+};
+
+ /*********************************************
+ * ACP3400-like I2C Devices Definitions, etc.
+ ********************************************/
+
+/*! @struct ai2c_i2c_ioconfig
+ @brief Timing Control Configuration for I2C registers
+*/
+struct ai2c_i2c_ioconfig {
+ u32 clkPulseWidthHigh:10;
+ /*!< Number of pclk durations that equal
+ * high period of SCL*/
+ u32 clkPulseWidthLow:10;
+ /*!< Number of pclk durations that equal
+ * low period of SCL */
+ u32 startSetupTime:10;
+ /*!< Number of pclk durations that equal
+ * setup condition on SDA */
+ u32 startHoldTime:10;
+ /*!< Number of pclk durations that equal
+ * hold condition on SDA */
+ u32 stopSetupTime:10;
+ /*!< Number of pclk durations that equal
+ * stop condition on SDA */
+ u32 stopHoldTime:10;
+ /*!< Number of pclk durations that equal
+ * setup condition on SDA */
+ u32 dataSetupTime:10;
+ /*!< Number of pclk durations that equal
+ * setup condition on SDA for data changing*/
+ u32 dataHoldTime:10;
+ /*!< Number of pclk durations that equal
+ * hold condition on SDA for data changing*/
+};
+
+
+extern struct ai2c_i2c_access ai2c_acp3400_cfg;
+
+ /*********************************************
+ * AXM5500-like I2C Devices Definitions, etc.
+ ********************************************/
+
+extern struct ai2c_i2c_access ai2c_axm5500_cfg;
+
+
+/*****************************************************************************
+* Externally Visible Function Prototypes *
+*****************************************************************************/
+
+/*! @fn int ai2c_bus_init(ai2c_priv_t * inDevHdl);
+ @brief This is a one time initialization for the I2C protocol
+ layers to be called by the chip device initialization step.
+ @param[in] inDevHdl Reference to device handle structure
+ @Returns success/failure status of the operation
+*/
+extern int ai2c_bus_init(struct ai2c_priv *priv);
+
+/*! @fn int ai2c_bus_block_read8(ai2c_priv_t *inDev,
+ ai2c_region_io_t *inRegion, u64 inOffset,
+ u8 *inBuffer, u32 inCount,
+ u32 inFlags);
+ @brief Read num bytes from the offset and store it in buffer.
+ @param[in] dev: handle of device to access
+ @param[in] region: region / slave address to access
+ @param[in] offset: Offset into device to address
+ @param[in] buffer: Read data will be stored this buffer
+ @param[in] count: Number of bytes to be read.
+ @param[in] flags: Extra flags to pass to low-level device I/O functions
+ @Returns success/failure completion status
+*/
+extern int ai2c_bus_block_read8(
+ struct ai2c_priv *priv,
+ u64 inOffset,
+ u8 *inBuffer,
+ u32 inCount,
+ u32 inFlags);
+
+/*! @fn int ai2c_bus_block_write8(ai2c_priv_t *inDev,
+ u64 inOffset,
+ u8 *inBuffer, u32 inCount,
+ u32 inFlags);
+ @brief Write num bytes to the offset from buffer contents.
+ @param[in] dev: handle of device to access
+ @param[in] offset: Offset into device to address
+ @param[in] buffer: Read data will be stored this buffer
+ @param[in] count: Number of bytes to be read.
+ @param[in] flags: Extra flags to pass to low-level device I/O functions
+ @Returns success/failure completion status
+*/
+extern int ai2c_bus_block_write8(
+ struct ai2c_priv *priv,
+ u64 inOffset,
+ u8 *outBuffer,
+ u32 inCount,
+ u32 inFlags);
+
+/*! @fn int ai2c_bus_destroy(ai2c_priv_t * inDevHdl);
+ @brief This function will release resources acquired for the specified
+ I2C region.
+ @param[in] inDevHdl Reference to device handle structure
+ @Returns success/failure status of the operation
+*/
+extern int ai2c_bus_destroy(struct ai2c_priv *priv);
+
+#endif /* defined(AI2C_BUS_H) */
diff --git a/drivers/i2c/busses/ai2c/ai2c_bus_acp3400.c b/drivers/i2c/busses/ai2c/ai2c_bus_acp3400.c
new file mode 100644
index 0000000..0878227
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_bus_acp3400.c
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* #define EXTRA_DEBUG */
+
+#include "ai2c_plat_pvt.h"
+#include "ai2c_dev_clock_ext.h"
+#include "regs/ai2c_i2c_regs.h"
+#include "regs/ai2c_axi_timer_regs.h"
+
+
+/*****************************************************************************
+* Local Macros & Constants *
+*****************************************************************************/
+
+#define AI2C_I2C_ADDR(offset) (0x00000000+(offset))
+
+
+/*****************************************************************************
+* Local Type Definitions *
+*****************************************************************************/
+
+struct localTimer {
+ u32 chipType;
+ u32 i2cRegionId;
+ u32 timerRegionId;
+ u32 baseOffset;
+ u32 timerLoadOffset;
+ u32 timerLoadValue;
+ u32 timerControlOffset;
+ u32 timerControlValue;
+};
+
+/*****************************************************************************
+* Forward Function Declarations *
+*****************************************************************************/
+
+/*****************************************************************************
+* Local State *
+*****************************************************************************/
+
+static u32 protoConfig;
+
+/*****************************************************************************
+* Functions: Initialization & Base Configuration *
+*****************************************************************************/
+
+/*
+ * Title: ai2c_bus_init_acp3400
+ * Description: This function will initialize the timer(s) and other
+ * features used by I2C. This is a one time initialization
+ * and will called by the generic initialization sequence.
+ * Inputs:
+ * @param[in] priv: handle of device to access
+ * @param[in] regionId: Reference to specific bus within device
+ * Returns: completion status
+ */
+static int ai2c_bus_init_acp3400(
+ struct ai2c_priv *priv,
+ u32 regionId)
+{
+ return -ENOSYS;
+}
+
+
+/*
+ * Title: ai2c_bus_block_read8_acp3400
+ * Description:
+ * Read num bytes from the offset and store it in buffer.
+ *
+ * Inputs:
+ * @param[in] dev Device handle
+ * @param[in] regionId Bus reference handle
+ * @param[in] *adap Ptr to I2C adapter
+ * @param[in] *msg Ptr to next I2C message to process
+ * @param[in] stop Op flag: append 'stop' to this msg
+ *
+ * Returns: completion status
+ */
+static int ai2c_bus_block_read8_acp3400(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_adapter *adap,
+ struct i2c_msg *msg,
+ int stop)
+{
+ return -ENOSYS;
+}
+
+
+/*
+ * Title: ai2c_bus_block_write8_acp3400
+ * Description: This function will read count bytes from the buffer
+ * and will store at the offset location in the device.
+ * Inputs:
+ * @param[in] dev Device handle
+ * @param[in] regionId Bus reference handle
+ * @param[in] *adap Ptr to I2C adapter
+ * @param[in] *msg Ptr to next I2C message to process
+ * @param[in] stop Op flag: append 'stop' to this msg
+ * Returns: completion status
+ * actCount: Actual number of bytes written from the ones that were
+ * provided.
+ */
+static int ai2c_bus_block_write8_acp3400(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_adapter *adap,
+ struct i2c_msg *msg,
+ int stop)
+{
+ return -ENOSYS;
+}
+
+
+/*****************************************************************************
+* More Exported State *
+*****************************************************************************/
+
+struct ai2c_i2c_access ai2c_acp3400_cfg = {
+ 0,
+ /* maxXfrSize */ AI2C_I2CPROT_MAX_XFR_SIZE,
+ /* deviceLen */ 0,
+ /* i.e. unbounded */
+
+ ai2c_bus_init_acp3400,
+ ai2c_bus_block_write8_acp3400,
+ ai2c_bus_block_read8_acp3400,
+
+ (void *) &protoConfig,
+};
diff --git a/drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c b/drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c
new file mode 100644
index 0000000..4066125
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/* #define EXTRA_DEBUG */
+
+#include "ai2c_plat_pvt.h"
+#include "ai2c_dev_clock_ext.h"
+#include "regs/ai2c_i2c_regs.h"
+#include "regs/ai2c_axi_timer_regs.h"
+
+
+/*****************************************************************************
+* Functions: Initialization & Base Configuration *
+*****************************************************************************/
+
+/*
+ * Title: ai2c_bus_init_axm5500
+ * Description: This function will initialize the timer(s) and other features
+ * used by I2C. This is a one time initialization and will
+ * called by the generic initialization sequence.
+ * Inputs:
+ * @param[in] dev Device handle
+ * @param[in] ndx Region of the I2C module of interest
+ * Returns: completion status
+ */
+static int ai2c_bus_init_axm5500(struct ai2c_priv *priv,
+ u32 inRegionId)
+{
+ /* To check if I2C timer is initialized or not */
+ int ai2cStatus = AI2C_ST_SUCCESS;
+
+ u32 clockMhz;
+ u32 timerLoad;
+
+ AI2C_LOG(AI2C_MSG_ENTRY,
+ "bus_init_axm5500: enter; rid=%08x\n", inRegionId);
+
+ /* Verify the device */
+ {
+ struct ai2c_region_io *r =
+ ai2c_region_lookup(priv, inRegionId);
+ u32 v0 = 0,
+ v1 = 0,
+ fail = 0;
+
+ AI2C_CALL(ai2c_dev_read32(priv, inRegionId,
+ AI2C_REG_I2C_X7_UDID_W7, &v0));
+ AI2C_CALL(ai2c_dev_read32(priv, inRegionId,
+ AI2C_REG_I2C_X7_UDID_W4, &v1));
+
+ if (v0 != AI2C_REG_I2C_X7_UDID_W7_DEFAULT)
+ fail |= 1;
+
+ if (v1 != AI2C_REG_I2C_X7_UDID_W4_DEFAULT)
+ fail |= 2;
+
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "bus_init_axm5500: 0x%04x.0x%04x.0x%x = 0x%08x (0x%08x)\n",
+ AI2C_NODE_ID(inRegionId), AI2C_TARGET_ID(inRegionId),
+ AI2C_REG_I2C_X7_UDID_W7,
+ v0, AI2C_REG_I2C_X7_UDID_W7_DEFAULT);
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "bus_init_axm5500: 0x%04x.0x%04x.0x%x = 0x%08x (0x%08x)\n",
+ AI2C_NODE_ID(inRegionId), AI2C_TARGET_ID(inRegionId),
+ AI2C_REG_I2C_X7_UDID_W4,
+ v1, AI2C_REG_I2C_X7_UDID_W4_DEFAULT);
+
+ AI2C_LOG(AI2C_MSG_INFO,
+ "%s bus %s : %s\n",
+ priv->busCfg->chipName,
+ priv->pages[r->pageId].busName,
+ (fail) ? "Invalid" : "Valid/Installed");
+
+ if (fail)
+ AI2C_CALL(-ENXIO);
+
+ }
+
+ /* Enable Master Mode */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_GLOBAL_CONTROL, 0x00000001));
+ /* Enable Master Mode Interrupts */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_INTERRUPT_ENABLE, 0x00000001));
+ /* Enable Individual Master Mode Interrupts */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_MST_INT_ENABLE, 0x0000FFF0));
+ /* Enable Individual Slave Mode Interrupts */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_SLV_INT_ENABLE, 0x00000000));
+
+ /* Configure Clock setup registers */
+ /* Assume PCLK=50MHZ, I2C=Fast mode (400KHz) */
+ if (ai2c_dev_clock_mhz(priv, &clockMhz) != AI2C_ST_SUCCESS)
+ clockMhz = 400;
+
+ /* SCL High Time: 1.4 us - 1 PCLK */
+ timerLoad = (clockMhz / 4) - 1;
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_SCL_HIGH_PERIOD, timerLoad));
+ /* SCL Low Time: 1.1 us - 1 PCLK */
+ timerLoad = (clockMhz / 5) - 1;
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_SCL_LOW_PERIOD, 0x00000000));
+ /* SDA Setup Time: SDA setup=600ns with margin */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_SDA_SETUP_TIME, 0x0000001E));
+ /* SDA Hold Time: SDA setup=500ns with margin */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_SDA_HOLD_TIME, 0x00000019));
+ /* Filter > 50ns spikes */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_SPIKE_FLTR_LEN, 0x00000003));
+
+ /* Configure Time-Out Registers */
+ /* Every 10.24ux = 512 x 20ns */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_TIMER_CLOCK_DIV, 0x00000003));
+ /* Desired Time-Out = 25ms */
+ AI2C_CALL(ai2c_dev_write32(priv, inRegionId,
+ AI2C_REG_I2C_X7_WAIT_TIMER_CONTROL, 0x00008989));
+
+AI2C_RETURN_LABEL
+
+ AI2C_LOG(AI2C_MSG_EXIT,
+ "bus_init_axm5500: exit (%d)\n", ai2cStatus);
+
+ if (ai2cStatus)
+ return -ENXIO;
+ else
+ return 0;
+}
+
+/*****************************************************************************
+* Functions: Hardware Layer Communication *
+*****************************************************************************/
+
+/*
+ * Title: ai2c_bus_block_read8_axm5500
+ * Description:
+ * Read num bytes from the device and store it in buffer.
+ *
+ * Inputs:
+ * priv: handle of device to access
+ * regionId: Handle of space corresponding to the bus in use
+ * adap: Current I2C adapter
+ * msg: Current I2C message
+ * stop: Add stop after this message if true
+ *
+ * Returns: completion status
+ */
+static int ai2c_bus_block_read8_axm5500_internal(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_msg *msg,
+ u8 *buffer,
+ u32 count,
+ int stop,
+ u32 *actCount)
+{
+ int ai2cStatus = 0;
+ u32 numInFifo, deadman, i, endit,
+ lTenBitMode = (msg->flags & I2C_M_TEN);
+
+/* Anything available yet? */
+ ai2cStatus = ai2c_dev_read32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_RX_FIFO,
+ &numInFifo);
+ if (ai2cStatus)
+ goto ai2c_return;
+ if ((numInFifo & 0xFF))
+ /* Didn't 'fail', but nothing really moved either */
+ goto ai2c_return;
+
+ /* # of bytes to move */
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_RX_XFER,
+ count);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ /* target slave address */
+ if (lTenBitMode) {
+ u32 a1 = (0x1e << 3) |
+ (((msg->addr >> 8) & 0x3) << 1) |
+ 0x1;
+ u32 a2 = (msg->addr & 0xff);
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_1,
+ a1);
+ /* insert! read */
+ if (ai2cStatus)
+ goto ai2c_return;
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_2,
+ a2);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "read8_i(%d):T: r %x/%x ma1 0x%08x ma2 0x%08x\n",
+ __LINE__, regionId, msg->addr, a1, a2);
+
+ } else {
+
+ u32 a1 = ((msg->addr & 0x7f) << 1) | 0x1;
+ u32 a2 = 0x00000000;
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_1,
+ a1);
+ /* insert! read */
+ if (ai2cStatus)
+ goto ai2c_return;
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_2,
+ a2);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "read8_i(%d): r %x/%x ma1 0x%08x ma2 0x%08x\n",
+ __LINE__, regionId, msg->addr, a1, a2);
+ }
+
+ /* And send it on its way (automatic or manual transfer command) */
+ {
+ u32 r = 0x8 |
+ ((stop) ? 0x1 : 0x0);
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_COMMAND,
+ r);
+ if (ai2cStatus)
+ goto ai2c_return;
+ }
+
+ /* Wait for the data to arrive */
+ for (endit = FALSE, deadman = 0;
+ !endit && (deadman < AI2C_I2C_CHECK_COUNT); deadman++) {
+ u32 reg = 0;
+
+ ai2cStatus = ai2c_dev_read32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_INT_STATUS,
+ ®);
+ if (ai2cStatus)
+ goto ai2c_return;
+ if (stop && ((reg >> 10) & 0x1))
+ endit = TRUE;
+ if (!stop && ((reg >> 11) & 0x1))
+ endit = TRUE;
+ if (reg & 0x00000078) { /* al || nd || na || ts */
+ ai2cStatus = -EBADE;
+ goto ai2c_return;
+ }
+ }
+ if (!endit) {
+ ai2cStatus = -ETIMEDOUT;
+ goto ai2c_return;
+ }
+
+ /* Finally, acquire the queued data */
+ ai2cStatus = ai2c_dev_read32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_RX_BYTES_XFRD,
+ &numInFifo);
+ if (ai2cStatus)
+ goto ai2c_return;
+ (*actCount) = 0;
+ count = MIN((numInFifo & 0xff), count);
+ for (i = 0; i < count; i++) {
+ u32 v;
+
+ ai2cStatus = ai2c_dev_read32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_DATA,
+ &v);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ buffer[i] = (v & 0xff);
+
+ (*actCount)++;
+ }
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "read8_i: l %d [%x,%x,%x,%x,%x,%x,%x,%x]\n",
+ (*actCount),
+ buffer[0], buffer[1], buffer[2], buffer[3],
+ buffer[4], buffer[5], buffer[6], buffer[7]);
+
+AI2C_RETURN_LABEL
+
+ AI2C_LOG(AI2C_MSG_EXIT,
+ "read8_i: exit; st=%d; rcvd=%d\n", ai2cStatus, (*actCount));
+
+ return ai2cStatus;
+}
+
+static int ai2c_bus_block_read8_axm5500(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_adapter *adap,
+ struct i2c_msg *msg,
+ int stop)
+{
+ int ai2cStatus = 0;
+ u32 count = 0;
+ u32 actCount = 0;
+ u32 thisLim = ai2c_axm5500_cfg.maxXfrSize;
+ u32 bytesRead = 0;
+ u8 *buffer = NULL;
+
+ count = msg->len;
+ buffer = msg->buf;
+
+ AI2C_LOG(AI2C_MSG_ENTRY,
+ "read8: entry, rid=%x, l=%d\n", regionId, count);
+
+ for (bytesRead = 0; count > bytesRead;) {
+ u32 thisXfr = MIN(count - bytesRead, thisLim);
+ int tempStop = stop;
+
+ if ((bytesRead + thisXfr) < count)
+ tempStop = 0;
+
+ ai2cStatus = ai2c_bus_block_read8_axm5500_internal(priv,
+ regionId,
+ msg, buffer, thisXfr,
+ tempStop, &actCount);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "read8: l %d [%x,%x,%x,%x,%x,%x,%x,%x]\n",
+ thisXfr,
+ buffer[0], buffer[1], buffer[2], buffer[3],
+ buffer[4], buffer[5], buffer[6], buffer[7]);
+
+ buffer += actCount;
+ bytesRead += actCount;
+ }
+
+AI2C_RETURN_LABEL
+
+ AI2C_LOG(AI2C_MSG_EXIT,
+ "read8: exit; st=%d l=%d\n", ai2cStatus, actCount);
+
+ return ai2cStatus;
+}
+
+
+/*
+ * Title: ai2c_bus_block_write8_axm5500
+ * Description: This function will read count bytes from the buffer
+ * and will store at the approparite location in the device.
+ * Inputs:
+ * priv: handle of device to access
+ * regionId: Handle of space corresponding to the bus in use
+ * adap: Current I2C adapter
+ * msg: Current I2C message
+ * stop: Add stop after this message if true
+ * Returns: completion status
+ */
+static int ai2c_bus_block_write8_axm5500_internal(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_msg *msg,
+ u8 *buffer,
+ u32 count,
+ int stop,
+ u32 *actCount)
+{
+ int ai2cStatus = 0;
+ u32 numInFifo,
+ endit,
+ deadman,
+ i,
+ lTenBitMode = (msg->flags & I2C_M_TEN);
+
+ AI2C_LOG(AI2C_MSG_ENTRY,
+ "write8_i: enter; rid=%x len=%d stop=%d\n",
+ regionId, count, stop);
+
+ /* Is a previous transfer still in progress? */
+ ai2cStatus = ai2c_dev_read32(priv, regionId,
+ AI2C_REG_I2C_X7_MST_TX_FIFO, &numInFifo);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ if ((numInFifo & 0xFF))
+ /* Didn't 'fail', but nothing really moved either */
+ goto ai2c_return;
+
+ /* # of bytes to move */
+ ai2cStatus = ai2c_dev_write32(priv, regionId,
+ AI2C_REG_I2C_X7_MST_TX_XFER, count);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ /* target slave address */
+ if (lTenBitMode) {
+ u32 a1 = (0x1e << 3) |
+ (((msg->addr >> 8) & 0x3) << 1) |
+ 0x0;
+ u32 a2 = (msg->addr & 0xff);
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_1,
+ a1);
+ /* insert! write */
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_2,
+ a2);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "write8_i(%d):T: r %x/%x ma1 0x%08x ma2 0x%08x\n",
+ __LINE__, regionId, AI2C_TARGET_ID(regionId),
+ a1 | 0x0, a2);
+
+ } else {
+
+ u32 a1 = ((msg->addr & 0x7f) << 1) | 0x0;
+ u32 a2 = 0x00000000;
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_1,
+ a1);
+ /* insert! write */
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_ADDR_2,
+ a2);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "write8_i(%d): r %x/%x ma1 0x%08x ma2 0x%08x\n",
+ __LINE__, regionId, AI2C_TARGET_ID(regionId),
+ a1 | 0x0, a2);
+ }
+
+ /* Queue up the data */
+ for (i = 0; i < count; i++) {
+ u32 v = buffer[i];
+
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_DATA,
+ v);
+ if (ai2cStatus)
+ goto ai2c_return;
+ }
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "write8_i(%d): c %d [%x %x %x %x %x %x %x %x]\n",
+ __LINE__, count,
+ buffer[0], buffer[1], buffer[2], buffer[3],
+ buffer[4], buffer[5], buffer[6], buffer[7]);
+
+ /* And send it on its way (automatic or manual transfer command) */
+ {
+ u32 r = 0x8 |
+ ((stop) ? 0x1 : 0x0);
+ ai2cStatus = ai2c_dev_write32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_COMMAND,
+ r);
+ if (ai2cStatus)
+ goto ai2c_return;
+ }
+
+ /* Wait for the data to arrive */
+ for (endit = FALSE, deadman = 0;
+ !endit && (deadman < AI2C_I2C_CHECK_COUNT); deadman++) {
+
+ u32 reg = 0;
+
+ ai2cStatus = ai2c_dev_read32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_INT_STATUS,
+ ®);
+ if (ai2cStatus)
+ goto ai2c_return;
+ if (stop && ((reg >> 10) & 0x1)) /* auto xfer; ss */
+ endit = TRUE;
+ if (!stop && ((reg >> 11) & 0x1)) /* man xfer; sns */
+ endit = TRUE;
+ if (reg & 0x00000078) { /* al || nd || na || ts */
+ ai2cStatus = -EBADE;
+ goto ai2c_return;
+ }
+ }
+
+ if (!endit) {
+ ai2cStatus = -ETIMEDOUT;
+ goto ai2c_return;
+ }
+
+ /* Finally, determine how many bytes were sent successfully */
+ ai2cStatus = ai2c_dev_read32(priv,
+ regionId,
+ AI2C_REG_I2C_X7_MST_TX_BYTES_XFRD,
+ &numInFifo);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ (*actCount) = (numInFifo & 0xFF);
+
+AI2C_RETURN_LABEL
+
+ AI2C_LOG(AI2C_MSG_EXIT,
+ "write8_i: exit; st=%d; num of bytes sent is %d (%d)\n",
+ ai2cStatus, numInFifo, (*actCount));
+
+ return ai2cStatus;
+}
+
+
+static int ai2c_bus_block_write8_axm5500(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ struct i2c_adapter *adap,
+ struct i2c_msg *msg,
+ int stop)
+{
+ int ai2cStatus = 0;
+ u32 countUsed = 0;
+ u32 count;
+ u32 countRem;
+ u32 thisLim = ai2c_axm5500_cfg.maxXfrSize,
+ lTenBitMode = (msg->flags & I2C_M_TEN);
+
+ AI2C_LOG(AI2C_MSG_ENTRY, "write8: entry, rid=%x\n", regionId);
+
+ if (msg->buf == NULL) {
+ AI2C_LOG(AI2C_MSG_DEBUG, "write8: Data buffer is NULL\n");
+ return -EFAULT;
+ }
+
+ if ((msg->addr & 0x1f) == 0x1e)
+ lTenBitMode = TRUE;
+ else
+ lTenBitMode = FALSE;
+
+ countRem = count = msg->len;
+
+ for (countUsed = 0; (count > countUsed);) {
+
+ u32 thisWid = (countRem > thisLim)
+ ? thisLim : countRem;
+ u32 thisXfr = thisWid;
+ u32 actWid = 0;
+ u8 inOutTxd[AI2C_I2CPROT_MAX_BUF_SIZE];
+ u32 k;
+ int tempStop = stop;
+
+ if (thisWid < countRem)
+ tempStop = 0;
+
+ for (k = 0; k < thisWid; k++)
+ inOutTxd[k] = msg->buf[countUsed+k];
+
+ ai2cStatus =
+ ai2c_bus_block_write8_axm5500_internal(priv,
+ regionId, msg,
+ &inOutTxd[0], thisXfr,
+ tempStop, &actWid);
+ if (ai2cStatus)
+ goto ai2c_return;
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "write8: tbm %d l %d aw %d c %d cu %d[%x,%x,%x,%x,%x,%x,%x,%x]\n",
+ lTenBitMode, thisXfr, actWid, count, countUsed,
+ inOutTxd[0], inOutTxd[1], inOutTxd[2], inOutTxd[3],
+ inOutTxd[4], inOutTxd[5], inOutTxd[6], inOutTxd[7]);
+
+ countUsed += actWid;
+ countRem -= actWid;
+ }
+
+AI2C_RETURN_LABEL
+
+ AI2C_LOG(AI2C_MSG_EXIT,
+ "write8: exit; st=%d\n", ai2cStatus);
+ return ai2cStatus;
+}
+
+
+/*****************************************************************************
+* More Exported State *
+*****************************************************************************/
+
+struct ai2c_i2c_access ai2c_axm5500_cfg = {
+ 0,
+ /* maxXfrSize */ AI2C_I2CPROT_MAX_XFR_SIZE,
+ /* deviceLen */ 0,
+ /* i.e. unbounded */
+ ai2c_bus_init_axm5500,
+ ai2c_bus_block_write8_axm5500,
+ ai2c_bus_block_read8_axm5500,
+ NULL,
+};
diff --git a/drivers/i2c/busses/ai2c/ai2c_dev.h b/drivers/i2c/busses/ai2c/ai2c_dev.h
new file mode 100644
index 0000000..fe9493b
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_dev.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file AI2C_dev.h
+ * @brief Exported Device-level APIs.
+ * @addtogroup _device_APIs Device Level APIs
+ * Device-level APIs work with flat memory in each device, specifying
+ * addresses or ranges of addresses. The object-level APIs call these
+ * device-level APIs, and the host program can also call the device-level
+ * APIs directly.
+ *
+ * @{
+ */
+
+#ifndef __AI2C_DEV_H__
+#define __AI2C_DEV_H__
+
+/*
+ * AI2C_dev.h
+ *
+ * This is the external header file for the AI2C device driver.
+ * This provides the function prototypes and associated definitions
+ * needed for the user application to access the device APIs.
+ *
+ */
+
+/*
+ * Includes
+ */
+
+#include "ai2c_types.h"
+
+
+/* --- Maximum version string length --- */
+#define AI2C_DEV_MAX_VERSION_LENGTH (41)
+
+
+/* --- NCA Config Ring Commands --- */
+#define AI2C_NCA_CMD_CRBR (0x00000004)
+#define AI2C_NCA_CMD_CRBW (0x00000005)
+#define AI2C_NCA_CMD_CRSW (0x00000006)
+#define AI2C_NCA_CMD_CRBF (0x00000007)
+#define AI2C_NCA_CMD_CRRMW (0x00000008)
+#define AI2C_NCA_CMD_CRBBW (0x00000009)
+#define AI2C_NCA_CMD_CRBSW (0x0000000A)
+#define AI2C_NCA_CMD_CRBBF (0x0000000B)
+#define AI2C_NCA_CMD_SMBR (0x0000000C)
+#define AI2C_NCA_CMD_SMBW (0x0000000D)
+#define AI2C_NCA_CMD_CSMBR (0x0000000E)
+#define AI2C_NCA_CMD_CSMBW (0x0000000F)
+
+#define AI2C_NCA_NUM_IO_CMDS 12
+
+#define AI2C_CFG_CMD_BUF_SIZE (sizeof(ai2c_coherent_sysmem_io_t))
+
+
+/* --- AI2C Trace Level Definitions --- */
+#define AI2C_MSG_NONE (0x00000000)
+#define AI2C_MSG_INFO (0x00000001)
+#define AI2C_MSG_ERROR (0x00000002)
+#define AI2C_MSG_ENTRY (0x00000004)
+#define AI2C_MSG_EXIT (0x00000008)
+#define AI2C_MSG_CALL (AI2C_MSG_ENTRY | AI2C_MSG_EXIT)
+#define AI2C_MSG_IOR (0x00000010)
+#define AI2C_MSG_IOW (0x00000020)
+#define AI2C_MSG_IORW (AI2C_MSG_IOR | AI2C_MSG_IOW)
+#define AI2C_MSG_MEM (0x00000040)
+#define AI2C_MSG_MDIO (0x00000080)
+#define AI2C_MSG_DEBUG_IO (0x20000000)
+#define AI2C_MSG_DEBUG (0x40000000)
+#define AI2C_MSG_INTR (0x80000000)
+#define AI2C_MSG_ALL (0xFFFFFFFF)
+
+
+/* --- Device Target Access Map --- */
+struct ai2c_access_map {
+ u64 begin;
+ u64 end;
+ s32 word_size_in_bytes;
+ s32 access_size_in_words;
+};
+
+
+#define AI2C_DUMMY_REGION_MAP_INIT \
+ { \
+ { 0x00000000, 0x03000000, AI2C_DEV_ACCESS_RW }, \
+ { 0, 0, AI2C_DEV_ACCESS_NONE } \
+ }
+
+#endif /* __AI2C_DEV_H__ */
diff --git a/drivers/i2c/busses/ai2c/ai2c_dev_clock.c b/drivers/i2c/busses/ai2c/ai2c_dev_clock.c
new file mode 100644
index 0000000..8530231
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_dev_clock.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "ai2c_plat_pvt.h"
+#include "ai2c_dev_clock_ext.h"
+
+/*
+ * Clock MHz calculation support Tables:
+ */
+
+/* Table 1-7: Feedback Divider Pre-Scalar */
+
+static const u8 Prescale[][2] = {
+ {0, 1},
+ {1, 3},
+ {2, 2},
+ {3, 4},
+};
+
+#define Prescale_COUNT (sizeof(Prescale)/(2*sizeof(u8)))
+
+/* Table 1-6: PLL Predivider */
+
+static const u8 Predivider[][2] = {
+ {0, 1},
+ {1, 16},
+ {2, 17},
+ {3, 30},
+ {4, 13},
+ {5, 18},
+ {6, 7},
+ {7, 31},
+ {8, 14},
+ {9, 11},
+ {10, 19},
+ {11, 21},
+ {12, 27},
+ {13, 8},
+ {14, 23},
+ {15, 32},
+ {16, 15},
+ {17, 29},
+ {18, 12},
+ {19, 6},
+ {20, 10},
+ {21, 20},
+ {22, 26},
+ {23, 22},
+ {24, 28},
+ {25, 5},
+ {26, 9},
+ {27, 25},
+ {28, 4},
+ {29, 24},
+ {30, 3},
+ {31, 2},
+};
+
+#define Predivider_COUNT (sizeof(Predivider)/(2*sizeof(u8)))
+
+/* Table 1-5: PLL Forward Dividers A,B */
+
+static const u8 ForwardDivider[][2] = {
+ {0, 1},
+ {1, 2},
+ {2, 28},
+ {3, 27},
+ {4, 22},
+ {5, 21},
+ {6, 30},
+ {7, 29},
+ {8, 24},
+ {9, 23},
+ {10, 12},
+ {11, 11},
+ {12, 16},
+ {13, 15},
+ {14, 32},
+ {15, 31},
+ {16, 26},
+ {17, 25},
+ {18, 20},
+ {19, 19},
+ {20, 10},
+ {21, 9},
+ {22, 14},
+ {23, 13},
+ {24, 18},
+ {25, 17},
+ {26, 8},
+ {27, 7},
+ {28, 6},
+ {29, 5},
+ {30, 4},
+ {31, 3},
+};
+
+#define ForwardDivider_COUNT (sizeof(ForwardDivider)/(2*sizeof(u8)))
+
+/* Table 1-11: PLL Feedback Divider */
+
+static const u8 FeedbackDivider[][2] = {
+ {0, 1},
+ {1, 123},
+ {2, 117},
+ {3, 251},
+ {4, 245},
+ {5, 69},
+ {6, 111},
+ {7, 125},
+ {8, 119},
+ {9, 95},
+ {10, 105},
+ {11, 197},
+ {12, 239},
+ {13, 163},
+ {14, 63},
+ {15, 253},
+ {16, 247},
+ {17, 187},
+ {18, 57},
+ {19, 223},
+ {20, 233},
+ {21, 207},
+ {22, 157},
+ {23, 71},
+ {24, 113},
+ {25, 15},
+ {26, 89},
+ {27, 37},
+ {28, 191},
+ {29, 19},
+ {30, 99},
+ {31, 127},
+ {32, 121},
+ {33, 109},
+ {34, 93},
+ {35, 61},
+ {36, 185},
+ {37, 155},
+ {38, 13},
+ {39, 97},
+ {40, 107},
+ {41, 11},
+ {42, 9},
+ {43, 81},
+ {44, 31},
+ {45, 49},
+ {46, 83},
+ {47, 199},
+ {48, 241},
+ {49, 33},
+ {50, 181},
+ {51, 143},
+ {52, 217},
+ {53, 173},
+ {54, 51},
+ {55, 165},
+ {56, 65},
+ {57, 85},
+ {58, 151},
+ {59, 147},
+ {60, 227},
+ {61, 41},
+ {62, 201},
+ {63, 255},
+ {64, 249},
+ {65, 243},
+ {66, 195},
+ {67, 237},
+ {68, 221},
+ {69, 231},
+ {70, 35},
+ {71, 189},
+ {72, 59},
+ {73, 183},
+ {74, 79},
+ {75, 29},
+ {76, 141},
+ {77, 215},
+ {78, 145},
+ {79, 225},
+ {80, 235},
+ {81, 219},
+ {82, 27},
+ {83, 139},
+ {84, 137},
+ {85, 135},
+ {86, 175},
+ {87, 209},
+ {88, 159},
+ {89, 53},
+ {90, 45},
+ {91, 177},
+ {92, 211},
+ {93, 23},
+ {94, 167},
+ {95, 73},
+ {96, 115},
+ {97, 67},
+ {98, 103},
+ {99, 161},
+ {100, 55},
+ {101, 205},
+ {102, 87},
+ {103, 17},
+ {104, 91},
+ {105, 153},
+ {106, 7},
+ {107, 47},
+ {108, 179},
+ {109, 171},
+ {110, 149},
+ {111, 39},
+ {112, 193},
+ {113, 229},
+ {114, 77},
+ {115, 213},
+ {116, 25},
+ {117, 133},
+ {118, 43},
+ {119, 21},
+ {120, 101},
+ {121, 203},
+ {122, 5},
+ {123, 169},
+ {124, 75},
+ {125, 131},
+ {126, 3},
+ {127, 129},
+ {128, 1},
+ {129, 250},
+ {130, 244},
+ {131, 124},
+ {132, 118},
+ {133, 196},
+ {134, 238},
+ {135, 252},
+ {136, 246},
+ {137, 222},
+ {138, 232},
+ {139, 70},
+ {140, 112},
+ {141, 36},
+ {142, 190},
+ {143, 126},
+ {144, 120},
+ {145, 60},
+ {146, 184},
+ {147, 96},
+ {148, 106},
+ {149, 80},
+ {150, 30},
+ {151, 198},
+ {152, 240},
+ {153, 142},
+ {154, 216},
+ {155, 164},
+ {156, 64},
+ {157, 146},
+ {158, 226},
+ {159, 254},
+ {160, 248},
+ {161, 236},
+ {162, 220},
+ {163, 188},
+ {164, 58},
+ {165, 28},
+ {166, 140},
+ {167, 224},
+ {168, 234},
+ {169, 138},
+ {170, 136},
+ {171, 208},
+ {172, 158},
+ {173, 176},
+ {174, 210},
+ {175, 72},
+ {176, 114},
+ {177, 160},
+ {178, 54},
+ {179, 16},
+ {180, 90},
+ {181, 46},
+ {182, 178},
+ {183, 38},
+ {184, 192},
+ {185, 212},
+ {186, 24},
+ {187, 20},
+ {188, 100},
+ {189, 168},
+ {190, 74},
+ {191, 128},
+ {192, 122},
+ {193, 116},
+ {194, 68},
+ {195, 110},
+ {196, 94},
+ {197, 104},
+ {198, 162},
+ {199, 62},
+ {200, 186},
+ {201, 56},
+ {202, 206},
+ {203, 156},
+ {204, 14},
+ {205, 88},
+ {206, 18},
+ {207, 98},
+ {208, 108},
+ {209, 92},
+ {210, 154},
+ {211, 12},
+ {212, 10},
+ {213, 8},
+ {214, 48},
+ {215, 82},
+ {216, 32},
+ {217, 180},
+ {218, 172},
+ {219, 50},
+ {220, 84},
+ {221, 150},
+ {222, 40},
+ {223, 200},
+ {224, 242},
+ {225, 194},
+ {226, 230},
+ {227, 34},
+ {228, 182},
+ {229, 78},
+ {230, 214},
+ {231, 144},
+ {232, 218},
+ {233, 26},
+ {234, 134},
+ {235, 174},
+ {236, 52},
+ {237, 44},
+ {238, 22},
+ {239, 166},
+ {240, 66},
+ {241, 102},
+ {242, 204},
+ {243, 86},
+ {244, 152},
+ {245, 6},
+ {246, 170},
+ {247, 148},
+ {248, 228},
+ {249, 76},
+ {250, 132},
+ {251, 42},
+ {252, 202},
+ {253, 4},
+ {254, 130},
+ {255, 2},
+};
+
+#define FeedbackDivider_COUNT (sizeof(FeedbackDivider)/(2*sizeof(u8)))
+
+int ai2c_dev_clock_mhz(
+ struct ai2c_priv *priv, /* IN */
+ u32 *clockMhz) /* OUT */
+{
+ int ai2cStatus = AI2C_ST_SUCCESS;
+ u32 sysPllCtrl;
+
+/*
+ * Equation:
+ * PLLOUTA = (CLKI * MULTINT.predivide * MULTINT.maindivide) /
+ * (PREDIV * RANGEA.predivide * RANGEA.maindivide)
+ *
+ * For SYSCLK, read content of sys_pll_ctrl (0x18d.0x0.0xc) defined as:
+ *
+ * Bits SW Name Description Reset
+ * 31:26 R/W prediv SYS PLL pre-divide value 6'h0
+ * 25:19 R/W rangeA SYS PLL range A value 7'h0
+ * 18:12 R/W rangeB SYS PLL range B value 7'h0
+ * 11:1 R/W multInt SYS PLL multiplier value 11'h0
+ * 0 R/W force_reset SYS PLL FF enable bit 1'h1
+ */
+ u32 prediv,
+ rangeA,
+ /* rangeB, */
+ multInt,
+ /* force_reset, */
+ v,
+ clki,
+ multInt_predivide,
+ multInt_maindivide,
+ rangeA_predivide,
+ rangeA_maindivide,
+ SYSCLK;
+
+ if ((clockMhz == NULL) || (priv == NULL))
+ AI2C_CALL(-ENOEXEC);
+
+ if (priv->hw_rev.isFpga) {
+ *clockMhz = 6;
+ return AI2C_ST_SUCCESS;
+ }
+
+ AI2C_CALL(ai2c_dev_read32(priv,
+ AI2C_REGION_CLK_CTRL, 0xC, &sysPllCtrl));
+
+ prediv = (sysPllCtrl >> 26) & 0x3f;
+ rangeA = (sysPllCtrl >> 19) & 0x7f;
+ /* rangeB = (sysPllCtrl >> 12) & 0x7f; */
+ multInt = (sysPllCtrl >> 1) & 0x7ff;
+ /* force_reset = (sysPllCtrl >> 0) & 0x1; */
+
+/*
+ * CLKI is 125Mhz
+ * MULTINT.predivide is the translated value from bits 8:9 of the
+ * multInt field.
+ * MULTINT.maindivide is the translated value from bits 7:0 of the
+ * multInt field.
+ * PREDIV is the translated value form the prediv field.
+ * RANGEA.predivide is the translated value form bits 6:5 of the
+ * rangeA field.
+ * RANGEA.maindivide is the translated value from bits 4:0 of the
+ * rangeA field.
+ */
+ clki = 125;
+
+ v = (multInt >> 8) & 0x3;
+ multInt_predivide = Prescale[v][1];
+
+ v = (multInt >> 0) & 0xff;
+ multInt_maindivide = FeedbackDivider[v][1];
+
+ v = prediv;
+ prediv = Predivider[v][1];
+
+ v = (rangeA >> 5) & 0x3;
+ rangeA_predivide = Prescale[v][1];
+
+ v = (rangeA >> 0) & 0x1f;
+ rangeA_maindivide = ForwardDivider[v][1];
+
+/*
+ * As an example of the SYS clock running at 400Mhz:
+ *
+ * The control register value is 0x02ed4566. It decodes as:
+ * prediv = 0x000
+ * rangeA = 0x05d
+ * multint = 0x2b3
+ *
+ * To get values for the equation:
+ * MULTINT.predivide = 0x02 Translated value from the tables: 2
+ * MULTINT.maindivide = 0xB3 Translated value from the tables: 16
+ * PREDIV = 0x00 Translated value from the tables: 1
+ * RANGEA.predivide = 0x02 Translated value from the tables: 2
+ * RANGEA.maindivide = 0x1d Translated value from the tables: 5
+ *
+ * Filling in the above values:
+ *
+ * SYSCLK = (CLKI * MULTINT.predivide * MULTINT.maindivide) /
+ * (PREDIV * RANGEA.predivide * RANGEA.maindivide)
+ * = (125Mhz * 2 * 16) / (1 * 2 * 5)
+ * = 4000Mhz / 10
+ * = 400Mhz
+ */
+
+ SYSCLK = (clki * multInt_predivide * multInt_maindivide) /
+ (prediv * rangeA_predivide * rangeA_maindivide);
+
+ (*clockMhz) = SYSCLK;
+
+AI2C_RETURN_LABEL
+ return ai2cStatus;
+}
+
diff --git a/drivers/i2c/busses/ai2c/ai2c_dev_clock_ext.h b/drivers/i2c/busses/ai2c/ai2c_dev_clock_ext.h
new file mode 100644
index 0000000..6e50aa5
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_dev_clock_ext.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_dev_clock_pvt.h
+ @brief Low-level (Device) APIs for clock-related calculations
+*/
+
+#ifndef _AI2C_DEV_CLOCK_EXT_H_
+#define _AI2C_DEV_CLOCK_EXT_H_
+
+#include "ai2c_dev_pvt.h"
+
+/**************************************************************************
+* Support Functions APIs *
+**************************************************************************/
+
+extern int ai2c_dev_clock_mhz(
+ struct ai2c_priv *priv, /* IN */
+ u32 *clockMhz); /* OUT: Calculated value */
+
+
+#endif /* _AI2C_DEV_CLOCK_EXT_H_ */
diff --git a/drivers/i2c/busses/ai2c/ai2c_dev_pvt.h b/drivers/i2c/busses/ai2c/ai2c_dev_pvt.h
new file mode 100644
index 0000000..3bae264
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_dev_pvt.h
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef __AI2C_DEV_PVT_H__
+#define __AI2C_DEV_PVT_H__
+
+#include "ai2c_sal.h"
+
+
+/* BEGIN: Important forward type references */
+
+struct ai2c_region_io;
+struct ai2c_priv;
+
+/* END: Important forward type references */
+
+#include "regs/ai2c_regions.h"
+#include "ai2c_dev.h"
+
+/* --- Linux References --- */
+#ifndef AI2C_MOD_NAME
+#define AI2C_MOD_NAME "ai2c"
+#endif
+
+
+/* --- Internal Types & Definitions --- */
+
+#define AI2C_DEV_ACCESS_NONE (0x00)
+#define AI2C_DEV_ACCESS_READ (0x01)
+#define AI2C_DEV_ACCESS_WRITE (0x02)
+#define AI2C_DEV_ACCESS_RW (0x03)
+#define AI2C_DEV_ACCESS_BIG_ENDIAN (0x04)
+#define AI2C_DEV_ACCESS_LITTLE_ENDIAN (0x08)
+
+
+#define AI2C_DEV_SIZE_1KB (1024*1)
+#define AI2C_DEV_SIZE_4KB (1024*4)
+#define AI2C_DEV_SIZE_128KB (1024*128)
+#define AI2C_DEV_SIZE_256KB (1024*256)
+#define AI2C_DEV_SIZE_2MB (1024*1024*2)
+#define AI2C_DEV_SIZE_16MB (1024*1024*16)
+#define AI2C_DEV_SIZE_128MB (1024*1024*128)
+#define AI2C_DEV_SIZE_1GB (1024*1024*1024)
+#define AI2C_DEV_SIZE_NO_SIZE (0)
+
+
+/* read/write fn prototypes for region map function pointers */
+
+typedef int (*_ai2c_dev_read_fn_t) (
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth);
+
+typedef int (*_ai2c_dev_write_fn_t) (
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth);
+
+/*
+ * Structure definition(s) for the region map.
+ * See above for typedef ai2c_region_io_t.
+ */
+struct ai2c_region_io {
+ u32 regionId;
+ struct ai2c_access_map *accessMap;
+ _ai2c_dev_read_fn_t readFn;
+ _ai2c_dev_write_fn_t writeFn;
+ u32 pageId;
+};
+
+/*
+ * Sometimes it would be better to define a range of similar regions
+ * with a single entry in the region map, especially, for regions
+ * that are logical or virtual entities that involve interpretation,
+ * calculated addresses based upon the regionId, or some other
+ * transformation. The alternate region map such definitions.
+ */
+struct ai2c_region_iorng {
+ u32 startRegionId;
+ u32 endRegionId;
+ struct ai2c_access_map *accessMap;
+ _ai2c_dev_read_fn_t readFn;
+ _ai2c_dev_write_fn_t writeFn;
+ u32 pageId;
+};
+
+
+/*
+ * Basic i/o methods
+ */
+
+#ifdef DEBUG_EDEV_IO
+#define AI2C_WRITE_LOG(ctx, dev, pageId, offset, value) \
+ AI2C_MSG(AI2C_MSG_DEBUG_IO, \
+ "%s: pageId=0x%x offset=0x%x addr=0x%x value=0x%02x\n", \
+ ctx, pageId, offset, AI2C_DEV_BUS_ADDR(dev, pageId, offset), value)
+#else
+#define AI2C_WRITE_LOG(ctx, dev, pageId, offset, value)
+#endif
+
+#define AI2C_DEV_BUS_READ8(dev, pageId, offset) \
+ AI2C_BUS_READ8(AI2C_DEV_BUS_ADDR(dev, pageId, offset),\
+ AI2C_DEV_PAGE_ENDIANNESS(pageId))
+
+#define AI2C_DEV_BUS_READ16(dev, pageId, offset) \
+ AI2C_BUS_READ16(AI2C_DEV_BUS_ADDR(dev, pageId, offset),\
+ AI2C_DEV_PAGE_ENDIANNESS(pageId))
+
+#define AI2C_DEV_BUS_READ32(dev, pageId, offset) \
+ AI2C_BUS_READ32(AI2C_DEV_BUS_ADDR(dev, pageId, offset),\
+ AI2C_DEV_PAGE_ENDIANNESS(pageId))
+
+#define AI2C_DEV_BUS_WRITE8(dev, pageId, offset, value) \
+ do { \
+ AI2C_WRITE_LOG("edev_bus_write8", dev, pageId, offset, value); \
+ AI2C_BUS_WRITE8( \
+ AI2C_DEV_BUS_ADDR(dev, pageId, offset), value); \
+ if (AI2C_DEV_PAGE_FLAGS(pageId) == AI2C_IO_SYNC) { \
+ volatile u32 ___val___; \
+ ___val___ = AI2C_BUS_READ32(AI2C_DEV_BUS_ADDR(dev, \
+ AI2C_DEV_PAGE_PCIE0_PEI, AI2C_PEI_CONFIG), \
+ AI2C_DEV_ACCESS_LITTLE_ENDIAN); \
+ } \
+ } while (0);
+
+#define AI2C_DEV_BUS_WRITE16(dev, pageId, offset, value) \
+ do { \
+ AI2C_WRITE_LOG("edev_bus_write16", \
+ dev, pageId, offset, value); \
+ AI2C_BUS_WRITE16( \
+ AI2C_DEV_BUS_ADDR(dev, pageId, offset), value); \
+ if (AI2C_DEV_PAGE_FLAGS(pageId) == AI2C_IO_SYNC) { \
+ volatile u32 ___val___; \
+ ___val___ = AI2C_BUS_READ32(AI2C_DEV_BUS_ADDR(dev, \
+ AI2C_DEV_PAGE_PCIE0_PEI, AI2C_PEI_CONFIG), \
+ AI2C_DEV_ACCESS_LITTLE_ENDIAN); \
+ } \
+ } while (0);
+
+
+#endif /* __AI2C_DEV_PVT_H__ */
diff --git a/drivers/i2c/busses/ai2c/ai2c_mod.c b/drivers/i2c/busses/ai2c/ai2c_mod.c
new file mode 100644
index 0000000..de2167a
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_mod.c
@@ -0,0 +1,351 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_mod.c
+
+ @brief Linux driver implementation of I2C using the ACP I2C
+ features upon an LSI development board (San Antonio,
+ Mission, El Paso, ...)
+
+ @details Command line module parameters (with defaults) include,
+ int ai2c_is_enabled = -1;
+ //Override: DTB option enabled
+ //Values: 0=not, 1=is, -1=check DTB
+ int ai2c_trace_level = (AI2C_MSG_INFO | AI2C_MSG_ERROR);
+ int ai2c_chip_ver = -1;
+ //Optional: Needed to figure out memory map, etc.
+ //Can verify against value from 0xa.0x10.0x2c
+ //Values; 0=X1_REL1
+ // 1=X1_REL2+
+ // 7=X7_REL1+
+
+ @details Several items contained in the 'i2c' section of the '.dts'
+ are used to configure this module including the addresses of
+ the memory partition, IRQ number, number of DMEs to use (when
+ we want to override the inferences based on the chipType), etc.
+*/
+
+/*
+#define DATA_STREAM_DEBUG
+#define AI2C_EXTERNAL_BUILD
+
+#define CONFIG_LSI_UBOOTENV
+#define CONFIG_I2C
+*/
+
+#include "ai2c_plat_pvt.h"
+#include "regs/ai2c_cfg_node_reg_defines.h"
+#include "regs/ai2c_cfg_node_regs.h"
+#include "asm/lsi/acp_ncr.h"
+
+/******************************************************************************
+* --- Linux Module Interface --- *
+******************************************************************************/
+#define AI2C_PARM_INT int
+#define AI2C_PARM_UINT uint
+#define AI2C_MODULE_PARM(v, t) module_param(v, t, (S_IRUSR|S_IRGRP|S_IROTH|\
+ S_IWUSR|S_IWGRP))
+#define AI2C_MODULE_INIT(fn) module_init(fn)
+#define AI2C_MODULE_EXIT(fn) module_exit(fn)
+#define AI2C_MODULE_VERSION(v) MODULE_VERSION(v)
+
+/*****************************
+* --- Module Parameters --- *
+*****************************/
+int AI2C_MSG_TRACE_LEVEL;
+int ai2c_chip_ver; /* Opt: Needed to figure out memory map, etc.
+ * Can verify against value from 0xa.0x10.0x2c
+ * Values; 0=X1_REL1
+ * 1=X1_REL2+
+ * 9=X7_REL1+
+ */
+
+MODULE_LICENSE("GPL");
+
+MODULE_DESCRIPTION("LSI ACP I2C Platform Driver");
+MODULE_AUTHOR("LSI");
+AI2C_MODULE_VERSION("1.0.0");
+
+AI2C_MODULE_PARM(AI2C_MSG_TRACE_LEVEL, AI2C_PARM_INT);
+AI2C_MODULE_PARM(ai2c_chip_ver, AI2C_PARM_INT);
+
+
+/***************************************
+* --- Character Driver Definitions --- *
+***************************************/
+
+
+/*****************************************************************************
+ * Local State
+ *****************************************************************************/
+
+static struct ai2c_priv *ai2cState;
+
+struct local_state {
+ struct i2c_adapter adapter;
+ struct i2c_client *client;
+};
+
+static struct local_state *ai2cModState;
+
+/*****************************************************************************
+ * I2C Algorithm
+ *****************************************************************************/
+
+static int ai2c_master_xfer(
+ struct i2c_adapter *adap,
+ struct i2c_msg msgs[],
+ int num)
+{
+ u32 regionId = (u32) i2c_get_adapdata(adap);
+ struct ai2c_priv *priv = ai2cState;
+ int err = 0;
+ int i;
+
+ AI2C_LOG(AI2C_MSG_ENTRY, ">>>Enter ai2c_master_xfer\n");
+
+ for (i = 0; (i < num) && (err == 0); i++) {
+
+ int stop = (i == (num - 1)) ? 1 : 0;
+
+ if (msgs[i].flags & I2C_M_RD) {
+
+#ifdef DATA_STREAM_DEBUG
+ int j;
+ char buf[80];
+ strcat(buf, "mstRead:");
+#endif /* DATA_STREAM_DEBUG */
+
+ err = priv->pages[i].api->rdFn(priv, regionId,
+ adap, &msgs[i], stop);
+
+#ifdef DATA_STREAM_DEBUG
+ for (j = 0; j < msgs[i].len; j++) {
+
+ char hb[4];
+ sprintf(hb, " %02x", msgs[i].buf[j]);
+ strcat(buf, hb);
+ }
+ printk(KERN_INFO "%s\n", buf);
+#endif /* DATA_STREAM_DEBUG */
+
+ } else {
+
+#ifdef DATA_STREAM_DEBUG
+ int j;
+ char buf[80];
+ strcat(buf, "mstWrite:");
+ for (j = 0; j < msgs[i].len; j++) {
+ char hb[4];
+ sprintf(hb, " %02x", msgs[i].buf[j]);
+ strcat(buf, hb);
+ }
+ printk(KERN_INFO "%s\n", buf);
+#endif /* DATA_STREAM_DEBUG */
+
+ err = priv->pages[i].api->wrFn(priv, regionId,
+ adap, &msgs[i], stop);
+ }
+ }
+
+AI2C_RETURN_LABEL
+ AI2C_LOG(AI2C_MSG_EXIT, ">>>Exit ai2c_master_xfer %d\n", err);
+ return err;
+}
+
+
+static u32 ai2c_func(struct i2c_adapter *adapter)
+{
+ return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR | I2C_FUNC_SMBUS_EMUL;
+}
+
+
+static const struct i2c_algorithm ai2c_algorithm = {
+ .master_xfer = ai2c_master_xfer,
+ .functionality = ai2c_func,
+};
+
+
+/*****************************************************************************
+ * Device Probe/Setup
+ *****************************************************************************/
+
+#ifdef AI2C_PLATFORM_BUILD
+static int __devinit ai2c_probe(struct platform_device *pdev)
+#else
+static int __devinit ai2c_init(void)
+#endif
+{
+ int ai2cStatus = AI2C_ST_SUCCESS;
+ struct ai2c_priv *priv = NULL;
+ int i;
+
+ /* Initialization of externals, initial state */
+ AI2C_MSG_TRACE_LEVEL = (AI2C_MSG_INFO | AI2C_MSG_ERROR);
+ ai2c_chip_ver = -1;
+ ai2cState = NULL;
+
+ AI2C_LOG(AI2C_MSG_ENTRY, ">>>Enter ai2c_probe/init\n");
+
+ AI2C_CALL(ai2c_memSetup(&priv));
+ ai2cState = priv;
+
+ /* Hook up bus driver(s) and devices to tree */
+ ai2cModState =
+ ai2c_malloc(priv->numActiveBusses * sizeof(struct local_state));
+ if (!ai2cModState) {
+ ai2cStatus = -ENOMEM;
+ goto exit_release;
+ }
+ memset(ai2cModState, 0,
+ priv->numActiveBusses * sizeof(struct local_state));
+
+ for (i = 0; i < priv->numActiveBusses; i++) {
+ u32 rid;
+
+ if (priv->pages[i].busName == NULL)
+ continue;
+
+ rid = ai2c_page_to_region(priv, priv->pages[i].pageId);
+ i2c_set_adapdata(&ai2cModState[i].adapter, (void *)rid);
+
+ snprintf(ai2cModState[i].adapter.name,
+ sizeof(ai2cModState[i].adapter.name),
+ "%s", ai2cState->pages[i].busName);
+ ai2cModState[i].adapter.algo = &ai2c_algorithm;
+ ai2cModState[i].adapter.owner = THIS_MODULE;
+ ai2cModState[i].adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
+ ai2cModState[i].adapter.retries = 3;
+ /* Retry up to 3 times on lost
+ * arbitration */
+#ifdef AI2C_PLATFORM_BUILD
+ ai2cModState[i].adapter.dev.parent = &pdev->dev;
+#else
+ ai2cModState[i].adapter.dev.parent = NULL;
+#endif
+ ai2cModState[i].adapter.dev.of_node = NULL;
+
+ /* Add I2C adapter to I2C tree */
+ ai2cStatus = i2c_add_adapter(&ai2cModState[i].adapter);
+ if (ai2cStatus) {
+ printk(KERN_ERR "Failed to add I2C adapter [%d]\n", i);
+ goto exit_release;
+ }
+
+ /* Any detailed bus-specific initialization */
+ ai2cStatus = priv->pages[i].api->initFn(priv, rid);
+ if (ai2cStatus)
+ goto exit_release;
+ }
+
+#ifdef AI2C_PLATFORM_BUILD
+ platform_set_drvdata(pdev, priv);
+#endif
+
+ AI2C_LOG(AI2C_MSG_EXIT, ">>>Exit ai2c_probe/init %d\n", 0);
+ return 0;
+
+AI2C_RETURN_LABEL
+ if (ai2cStatus != -ENOMEM)
+ ai2cStatus = -ENOSYS;
+
+exit_release:
+ ai2c_memDestroy(priv);
+
+ AI2C_LOG(AI2C_MSG_EXIT, ">>>Exit ai2c_probe/init %d\n", ai2cStatus);
+ return ai2cStatus;
+}
+
+#ifdef AI2C_PLATFORM_BUILD
+static int __devexit ai2c_remove(struct platform_device *dev)
+#else
+static void __devexit ai2c_exit(void)
+#endif
+{
+ int i;
+
+ AI2C_LOG(AI2C_MSG_ENTRY, ">>>Enter ai2c_remove/exit\n");
+
+ if (ai2cState != NULL) {
+
+ if (ai2cModState != NULL) {
+
+ for (i = 0; i < ai2cState->numActiveBusses; i++) {
+
+ if (ai2cModState[i].client)
+ i2c_unregister_device(
+ ai2cModState[i].client);
+ i2c_del_adapter(&ai2cModState[i].adapter);
+ }
+ ai2c_free(ai2cModState);
+ }
+
+ ai2c_memDestroy(ai2cState);
+ }
+
+#ifdef AI2C_PLATFORM_BUILD
+ platform_set_drvdata(dev, NULL);
+#endif
+
+ AI2C_LOG(AI2C_MSG_EXIT, ">>>Exit ai2c_remove/exit %d\n", 0);
+
+#ifdef AI2C_PLATFORM_BUILD
+ return 0;
+#endif
+}
+
+/* ------------------------------------------------------------------------- */
+
+#ifdef AI2C_PLATFORM_BUILD
+
+#define ai2c_suspend NULL
+#define ai2c_resume NULL
+
+static struct platform_driver ai2c_driver = {
+ .driver = {
+ .name = "axxia_ai2c", /* Must match with platform-specific
+ * code! */
+ .owner = THIS_MODULE,
+ },
+ .probe = ai2c_probe,
+ .remove = __devexit_p(ai2c_remove),
+ .suspend = ai2c_suspend,
+ .resume = ai2c_resume,
+};
+
+static int __init ai2c_init(void)
+{
+ AI2C_LOG(AI2C_MSG_ENTRY, ">>>Enter ai2c_init\n");
+ return platform_driver_register(&ai2c_driver);
+}
+
+static void __exit ai2c_exit(void)
+{
+ AI2C_LOG(AI2C_MSG_ENTRY, ">>>Enter ai2c_exit\n");
+ platform_driver_unregister(&ai2c_driver);
+}
+
+#endif /* AI2C_PLATFORM_BUILD */
+
+module_init(ai2c_init);
+module_exit(ai2c_exit);
+
diff --git a/drivers/i2c/busses/ai2c/ai2c_plat.c b/drivers/i2c/busses/ai2c/ai2c_plat.c
new file mode 100644
index 0000000..c1f5837
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_plat.c
@@ -0,0 +1,842 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_plat.c
+
+ @brief Linux driver implementation of I2C using the ACP I2C
+ features upon an LSI development board (San Antonio,
+ Mission, El Paso, ...)
+
+ @details Command line module parameters (with defaults) include,
+ int ai2c_trace_level = (AI2C_MSG_INFO | AI2C_MSG_ERROR);
+ int ai2c_chip_ver = -1;
+ //Optional: Needed to figure out memory map, etc.
+ //Can verify against value from 0xa.0x10.0x2c
+ //Values; 0=X1_REL1
+ // 1=X1_REL2+
+ // 7=X7_REL1+
+
+ @details Several items contained in the 'i2c' section of the '.dts'
+ are used to configure this module including the addresses of
+ the memory partition, IRQ number, number of DMEs to use (when
+ we want to override the inferences based on the chipType), etc.
+*/
+
+/*
+#define EXTENDED_GSDBG_INFO
+#define AI2C_EXTERNAL_BUILD
+
+#define CONFIG_LSI_UBOOTENV
+#define CONFIG_I2C
+#define AI2C_CHIP_VER=<verNum>
+*/
+
+#include "ai2c_plat_pvt.h"
+#include "regs/ai2c_cfg_node_reg_defines.h"
+#include "regs/ai2c_cfg_node_regs.h"
+#include "asm/lsi/acp_ncr.h"
+
+/*****************************************************************************
+ * Local State
+ *****************************************************************************/
+/*
+ * This block of code defines the memory addresses for each h/w block
+ * that is accessible as a direct bus i/o operation.
+ *
+ * IMPORTANT: ALL BUS GROUPINGS MUST BE MAINTAINED
+ */
+/* Note: This table now contains the length of the block for wrap checking
+ * and such (when implemented). Note that each table is arranged in
+ * order of the "AI2C_DEV_PAGE_xxx" enumeration.
+ */
+static struct ai2c_dev_page ai2c_dev_page_34xx[AI2C_DEV_PAGE_END_MARKER] = {
+ /* Begin: I2C_0 */
+ {
+ AI2C_DEV_PAGE_I2C_0, "AXXIA_I2C", 0x02000403000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_acp3400_cfg
+ },
+ {
+ AI2C_DEV_PAGE_END_MARKER, NULL, 0x00000000000ULL, 0, 0,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_END_MARKER, NULL, 0x00000000000ULL, 0, 0,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_END_MARKER, NULL, 0x00000000000ULL, 0, 0,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_GPIO_0, NULL, 0x02000400000ULL, /*aka APB1/GPIO0*/
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_RESET_CTRL, NULL, 0x02000003800ULL,
+ AI2C_DEV_SIZE_1KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_TIMER, NULL, 0x02000408000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_GPREG, NULL, 0x0200040C000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ /* End: I2C_0 */
+};
+
+static struct ai2c_dev_page ai2c_dev_page_25xx[AI2C_DEV_PAGE_END_MARKER] = {
+ /* Begin: I2C_0, I2C_1 */
+ {
+ AI2C_DEV_PAGE_I2C_0, "AXXIA_I2C0", 0x02000427000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_acp3400_cfg
+ },
+ {
+ AI2C_DEV_PAGE_I2C_1, "AXXIA_I2C1", 0x02000428000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_acp3400_cfg},
+ {
+ AI2C_DEV_PAGE_END_MARKER, NULL, 0x00000000000ULL, 0, 0,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_END_MARKER, NULL, 0x00000000000ULL, 0, 0,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_GPIO_0, NULL, 0x02000420000ULL,/*aka APB1/GPIO0*/
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_RESET_CTRL, NULL, 0x02000005c00ULL,
+ AI2C_DEV_SIZE_1KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_TIMER, NULL, 0x02000429000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_GPREG, NULL, 0x02000400000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ /* End: I2C_0, I2C_1 */
+};
+
+static struct ai2c_dev_page ai2c_dev_page_55xx[AI2C_DEV_PAGE_END_MARKER] = {
+ /* Begin: I2C_0, I2C_1, I2C_2, I2C_3 (SMB) */
+ {
+ AI2C_DEV_PAGE_I2C_0, "AXXIA_I2C0", 0x02010084000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_axm5500_cfg
+ },
+ {
+ AI2C_DEV_PAGE_I2C_1, "AXXIA_I2C1", 0x02010085000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_axm5500_cfg
+ },
+ {
+ AI2C_DEV_PAGE_I2C_2, "AXXIA_I2C2", 0x02010086000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_axm5500_cfg
+ },
+ {
+ AI2C_DEV_PAGE_I2C_3, "AXXIA_SMB", 0x02010087000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_axm5500_cfg
+ },
+ {
+ AI2C_DEV_PAGE_GPIO_0, NULL, 0x02010092000ULL, /*aka APB1/GPIO1*/
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_RESET_CTRL, NULL, 0x02022060000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_TIMER, NULL, 0x02010091000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_GPREG, NULL, 0x02010094000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ /* End: I2C_1 */
+};
+
+static struct ai2c_dev_page ai2c_dev_page_35xx[AI2C_DEV_PAGE_END_MARKER] = {
+ /* Begin: I2C_0 */
+ {
+ AI2C_DEV_PAGE_I2C_0, "AXXIA_I2C0", 0x02000426000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_axm5500_cfg
+ },
+ {
+ AI2C_DEV_PAGE_I2C_1, "AXXIA_I2C1", 0x02000427000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_axm5500_cfg
+ },
+ {
+ AI2C_DEV_PAGE_I2C_2, "AXXIA_I2C2", 0x02000428000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_I2CBUS, &ai2c_axm5500_cfg
+ },
+ {
+ AI2C_DEV_PAGE_END_MARKER, NULL, 0x00000000000ULL, 0, 0,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_GPIO_0, NULL, 0x02000420000ULL, /*aka APB1/GPIO0*/
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_RESET_CTRL, NULL, 0x02000003800ULL,
+ AI2C_DEV_SIZE_1KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_TIMER, NULL, 0x02000429000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ {
+ AI2C_DEV_PAGE_GPREG, NULL, 0x02000400000ULL,
+ AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+ AI2C_PAGE_FLAGS_NONE, NULL
+ },
+ /* End: I2C_0 */
+};
+
+static struct ai2c_dev_page_entry ai2c_dev_page_index[] = {
+ { AI2C_CHIP_ACP34xx, "ACP34xx", FALSE, ai2c_dev_page_34xx, 2, },
+ { AI2C_CHIP_ACP32xx, "ACP32xx", FALSE, ai2c_dev_page_34xx, 2, },
+ { AI2C_CHIP_ACP25xx, "ACP25xx", FALSE, ai2c_dev_page_25xx, 2, },
+ { AI2C_CHIP_ACP55xx, "AXM55xx", TRUE, ai2c_dev_page_55xx, 4, },
+ { AI2C_CHIP_ACP35xx, "AXM35xx", TRUE, ai2c_dev_page_35xx, 3, },
+};
+
+static int ai2c_dev_page_index_cnt = sizeof(ai2c_dev_page_index) /
+ sizeof(struct ai2c_dev_page_entry);
+
+ /* Region Map
+ * Note: Must be same number of entries (and in same order) in the
+ * arrays of type 'ai2c_dev_page_entry_t' above. Note that
+ * each table is arranged in order of the "AI2C_DEV_PAGE_xxx"
+ * enumeration.
+ */
+
+static struct ai2c_access_map ai2cDummyRegionMap[] = AI2C_DUMMY_REGION_MAP_INIT;
+
+static struct ai2c_region_io ai2c_region_io_map[] = {
+ /* 323.0 */
+ {
+ AI2C_REGION_I2C_0, ai2cDummyRegionMap,
+ __ai2c_dev_direct_read, __ai2c_dev_direct_write,
+ AI2C_DEV_PAGE_I2C_0,
+ },
+ /* 332.0 */
+ {
+ AI2C_REGION_I2C_1, ai2cDummyRegionMap,
+ __ai2c_dev_direct_read, __ai2c_dev_direct_write,
+ AI2C_DEV_PAGE_I2C_1,
+ },
+ /* 332.0 */
+ {
+ AI2C_REGION_I2C_2, ai2cDummyRegionMap,
+ __ai2c_dev_direct_read, __ai2c_dev_direct_write,
+ AI2C_DEV_PAGE_I2C_2,
+ },
+ /* 348.0 */
+ {
+ AI2C_REGION_I2C_3, ai2cDummyRegionMap,
+ __ai2c_dev_direct_read, __ai2c_dev_direct_write,
+ AI2C_DEV_PAGE_I2C_3,
+ },
+ /* 320.0 */
+ {
+ AI2C_REGION_GPIO_0, ai2cDummyRegionMap,
+ __ai2c_dev_direct_read, __ai2c_dev_direct_write,
+ AI2C_DEV_PAGE_GPIO_0,
+ },
+ /* 398.0 */
+ {
+ AI2C_REGION_RESET_CTRL, ai2cDummyRegionMap,
+ __ai2c_dev_dcr_read, __ai2c_dev_dcr_write,
+ AI2C_DEV_PAGE_RESET_CTRL,
+ },
+ /* 326.0 */
+ {
+ AI2C_REGION_TIMER, ai2cDummyRegionMap,
+ __ai2c_dev_direct_read, __ai2c_dev_direct_write,
+ AI2C_DEV_PAGE_TIMER,
+ },
+ /* 329.0 */
+ {
+ AI2C_REGION_GPREG, ai2cDummyRegionMap,
+ __ai2c_dev_direct_read, __ai2c_dev_direct_write,
+ AI2C_DEV_PAGE_GPREG,
+ },
+};
+
+static const u32 ai2c_region_pages_max =
+ sizeof(ai2c_region_io_map) / sizeof(struct ai2c_region_io);
+
+
+/*****************************************************************************
+ * Miscellaneous Utility functions
+ *****************************************************************************/
+
+u32 ai2c_page_to_region(
+ struct ai2c_priv *priv,
+ u32 pageId)
+{
+ int i;
+ for (i = 0; i < ai2c_region_pages_max; i++)
+ if (pageId == ai2c_region_io_map[i].pageId)
+ return ai2c_region_io_map[i].regionId;
+ return AI2C_REGION_NULL;
+}
+
+struct ai2c_region_io *ai2c_region_lookup(
+ struct ai2c_priv *priv,
+ u32 regionId)
+{
+ int i;
+ for (i = 0; i < ai2c_region_pages_max; i++)
+ if (regionId == ai2c_region_io_map[i].regionId)
+ return &ai2c_region_io_map[i];
+ return NULL;
+}
+
+/*****************************************************************************
+ * Read/Write ACP Memory Spaces
+ *****************************************************************************/
+
+/*
+ * ai2c_dev_direct_read
+ *
+ * Perform 32-bit AI2C device I/O to non-ConfigRing region.
+ */
+int ai2c_dev_direct_read(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth)
+{
+ int st = 0;
+ u32 endianness;
+ unsigned long busAddr;
+ u32 i;
+
+ AI2C_MSG(AI2C_MSG_ENTRY,
+ "direct_read enter: %x.%x.%llx %d\n",
+ AI2C_NODE_ID(region->regionId),
+ AI2C_TARGET_ID(region->regionId),
+ (unsigned long long) offset, count);
+
+ if (priv->pageAddr[region->pageId] == 0) {
+ st = -EBADSLT;
+ goto cleanup;
+ }
+
+ busAddr = AI2C_DEV_BUS_ADDR(priv, region->pageId, offset);
+ endianness = AI2C_DEV_PAGE_ENDIANNESS(region->pageId);
+
+ switch (xferWidth) {
+ case 4:
+ for (i = 0; i < count; i++, busAddr += 4, offset += 4) {
+ buffer[i] = AI2C_BUS_READ32(busAddr, endianness);
+ AI2C_MSG(AI2C_MSG_IOR,
+ "direct_read: region=%x offset = %llx busAddr=%lx v=%x\n",
+ region->regionId, offset, busAddr, buffer[i]);
+ }
+ break;
+ case 2:
+ {
+ u16 *p16 = (u16 *) buffer;
+ for (i = 0; i < count; i++, busAddr += 2)
+ p16[i] = AI2C_BUS_READ16(busAddr, endianness);
+ }
+ break;
+ case 1:
+ {
+ u8 *p8 = (u8 *) buffer;
+ for (i = 0; i < count; i++, busAddr += 1)
+ p8[i] = AI2C_BUS_READ8(busAddr);
+ }
+ break;
+ default:
+ st = -EACCES;
+ break;
+ }
+
+cleanup:
+ AI2C_MSG(AI2C_MSG_EXIT,
+ "direct_read exit: st=%d %x.%x.%llx=0x%08x\n",
+ st, AI2C_NODE_ID(region->regionId),
+ AI2C_TARGET_ID(region->regionId), (unsigned long long) offset,
+ buffer[0]);
+ return (int) st;
+}
+
+/*
+ * ai2c_dev_direct_write
+ *
+ * Perform 32-bit AI2C device I/O to non-ConfigRing region.
+ */
+int ai2c_dev_direct_write(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth)
+{
+ int st = 0;
+ u32 endianness;
+ unsigned long busAddr;
+ u32 i;
+
+ AI2C_MSG(AI2C_MSG_ENTRY,
+ "direct_write enter: %x.%x.%llx 0x%08x (%d)\n",
+ AI2C_NODE_ID(region->regionId),
+ AI2C_TARGET_ID(region->regionId),
+ (unsigned long long) offset,
+ buffer[0], count);
+
+ if (priv->pageAddr[region->pageId] == 0) {
+ st = -EBADSLT;
+ goto cleanup;
+ }
+
+ busAddr = AI2C_DEV_BUS_ADDR(priv, region->pageId, offset);
+ endianness = AI2C_DEV_PAGE_ENDIANNESS(region->pageId);
+
+ switch (xferWidth) {
+ case 4:
+ for (i = 0; i < count; i++, busAddr += 4, offset += 4) {
+ AI2C_BUS_WRITE32(busAddr, buffer[i], endianness);
+ AI2C_MSG(AI2C_MSG_IOW,
+ "direct_write: region=%x offset=%llx busAddr=%lx v=%x\n",
+ region->regionId, offset, busAddr, buffer[i]);
+ }
+ break;
+
+ case 2:
+ {
+ u16 *buf16 = (u16 *) buffer;
+ for (i = 0; i < count; i++, busAddr += 2) {
+ AI2C_BUS_WRITE16(busAddr, buf16[i], endianness);
+ AI2C_MSG(AI2C_MSG_IOW,
+ "direct_write: region=%x offset=%llx busAddr=%lx v=%x\n",
+ region->regionId,
+ offset, busAddr, buf16[i]);
+ }
+ }
+ break;
+ case 1:
+ {
+ u8 *buf8 = (u8 *) buffer;
+ for (i = 0; i < count; i++, busAddr++) {
+ AI2C_BUS_WRITE8(busAddr, buf8[i]);
+ AI2C_MSG(AI2C_MSG_IOW,
+ "direct_write: region=%x offset=%llx busAddr=%lx v=%x\n",
+ region->regionId,
+ offset, busAddr, buf8[i]);
+ }
+ }
+ break;
+ default:
+ st = -EACCES;
+ break;
+ }
+
+cleanup:
+ AI2C_MSG(AI2C_MSG_EXIT, "direct_write exit st=%d\n", st);
+ return (int) st;
+}
+
+/*
+ * ai2c_dev_read32
+ *
+ */
+int ai2c_dev_read32(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ u64 offset,
+ u32 *buffer)
+{
+ int ai2cStatus = 0;
+ struct ai2c_region_io *region = ai2c_region_lookup(priv, regionId);
+ unsigned long lflags = 0;
+
+ AI2C_SPINLOCK_INTERRUPT_DISABLE(&priv->regLock, lflags);
+
+ AI2C_MSG(AI2C_MSG_ENTRY,
+ "dev_read32 enter: %x.%x.%llx %d\n",
+ AI2C_NODE_ID(regionId), AI2C_TARGET_ID(regionId),
+ (unsigned long long) offset, 1);
+
+ if (region) {
+ ai2cStatus =
+ AI2C_EDEV_BUS_BLOCK_READ32(priv,
+ region->pageId, offset, 1, buffer);
+
+ } else {
+
+#ifdef CONFIG_LSI_UBOOTENV
+ ai2cStatus = ncr_read(regionId, (u32) offset,
+ 1 * sizeof(u32), buffer);
+#else
+ ai2cStatus = -ENOSYS;
+#endif
+ }
+
+ AI2C_SPINLOCK_INTERRUPT_ENABLE(&priv->regLock, lflags);
+
+ return ai2cStatus;
+}
+
+/*
+ * ai2c_dev_write32
+ *
+ */
+int ai2c_dev_write32(
+ struct ai2c_priv *priv,
+ u32 regionId,
+ u64 offset,
+ u32 buffer)
+{
+ int ai2cStatus = 0;
+ struct ai2c_region_io *region = ai2c_region_lookup(priv, regionId);
+ unsigned long lflags = 0;
+
+ AI2C_SPINLOCK_INTERRUPT_DISABLE(&priv->regLock, lflags);
+
+ AI2C_MSG(AI2C_MSG_ENTRY,
+ "dev_write32 enter: %x.%x.%llx 0x%08x (%d)\n",
+ AI2C_NODE_ID(regionId), AI2C_TARGET_ID(regionId),
+ (unsigned long long) offset, (unsigned int)&buffer, 1);
+
+ if (region) {
+ ai2cStatus =
+ AI2C_EDEV_BUS_BLOCK_WRITE32(priv,
+ region->pageId, offset, 1,
+ &buffer);
+
+ } else {
+
+#ifdef CONFIG_LSI_UBOOTENV
+ ai2cStatus = ncr_write(regionId, (u32) offset,
+ 1 * sizeof(u32), &buffer);
+#else
+ ai2cStatus = -ENOSYS;
+#endif
+ }
+
+ AI2C_SPINLOCK_INTERRUPT_ENABLE(&priv->regLock, lflags);
+
+ return ai2cStatus;
+}
+
+/*
+ * ai2c_dev_dcr_read
+ *
+ * Perform 32-bit AI2C device I/O to non-Config Ring region.
+ */
+int ai2c_dev_dcr_read(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth)
+{
+ return -ENOSYS;
+}
+
+/*
+ * ai2c_dev_dcr_write
+ *
+ * Perform 32-bit AI2C device I/O from non-Config Ring region.
+ */
+int ai2c_dev_dcr_write(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth)
+{
+ return -ENOSYS;
+}
+
+
+/*****************************************************************************
+ * Basic configuration Fill-in
+ *****************************************************************************/
+
+static int ai2c_getChipType(struct ai2c_priv *priv)
+{
+ int ai2cStatus = AI2C_ST_SUCCESS;
+#ifdef CONFIG_LSI_UBOOTENV
+ ai2c_bool_t has_ECID = TRUE;
+ u32 rev_reg;
+ u32 pt_reg;
+ ai2c_cfg_node_node_cfg_r_t node_cfg;
+ ai2c_cfg_node_node_info_0_r_t node_info;
+
+ /*
+ * Determine device revision
+ */
+
+ /* Read the NCA local config node to see if we are an ASIC or FPGA */
+ AI2C_CALL(ai2c_dev_read32(priv, AI2C_REGION_NCA_CFG,
+ AI2C_CFG_NODE_NODE_CFG,
+ (u32 *) &node_cfg));
+ AI2C_CALL(ai2c_dev_read32(priv, AI2C_REGION_NCA_CFG,
+ AI2C_CFG_NODE_NODE_INFO_0,
+ (u32 *) &node_info));
+
+ if (node_cfg.fpga) {
+ priv->hw_rev.isFpga = 1;
+ /* v1 FPGA doesn't have the ECID block */
+ if (node_info.module_revision == 0)
+ has_ECID = FALSE;
+
+ } else
+ priv->hw_rev.isAsic = 1;
+
+ if (node_info.module_revision == AI2C_CHIP_ACP25xx ||
+ node_info.module_revision == AI2C_CHIP_ACP55xx)
+ has_ECID = FALSE;
+
+ /* Get the device chipType/Version from the ECID fuse block */
+ if (has_ECID) {
+
+ AI2C_CALL(ai2c_dev_read32(priv,
+ AI2C_REGION_ID(AI2C_NODE_X1_ECID, 0x10),
+ 0x2c, (u32 *) &rev_reg));
+
+ AI2C_CALL(ai2c_dev_read32(priv,
+ AI2C_REGION_ID(AI2C_NODE_X1_ECID, 0x10),
+ 0x20, &pt_reg));
+
+ priv->hw_rev.chipType = (rev_reg & 0x0000001f);
+ priv->hw_rev.chipVersion = (rev_reg & 0x000007e0) >> 5;
+ priv->hw_rev.cpuDisable = (rev_reg & 0x00007800) >> 11;
+ priv->hw_rev.sppDisable = (rev_reg & 0x00008000) >> 15;
+
+ priv->hw_rev.packageType = (pt_reg & 0xf0000000) >> 28;
+ } else {
+ /* if we don't have an ECID just use the NCA module version */
+ priv->hw_rev.chipType = node_info.module_revision;
+ priv->hw_rev.chipVersion = 0;
+ priv->hw_rev.packageType = 0;
+ priv->hw_rev.cpuDisable = 0;
+ priv->hw_rev.sppDisable = 0;
+ }
+
+ /* fixup chipType for ACP344x variants */
+ switch (priv->hw_rev.chipType) {
+ case 3:
+ case 4:
+ priv->hw_rev.chipType = AI2C_CHIP_ACP34xx;
+ break;
+ case 5:
+ priv->hw_rev.chipType = AI2C_CHIP_ACP34xx;
+ break;
+ default:
+ break;
+ }
+#endif
+
+ /* Environment variable override */
+ if (ai2c_chip_ver != -1) {
+ priv->hw_rev.chipType = ai2c_chip_ver;
+ priv->hw_rev.chipVersion = 0;
+ }
+#ifdef AI2C_CHIP_VER
+ else {
+ priv->hw_rev.chipType = AI2C_CHIP_VER;
+ priv->hw_rev.chipVersion = 0;
+ }
+#endif
+
+ AI2C_LOG(AI2C_MSG_INFO, "AI2C %d.%d.%d %s\n",
+ priv->hw_rev.chipType, priv->hw_rev.chipVersion,
+ priv->hw_rev.packageType,
+ (priv->hw_rev.isFpga) ? "FPGA" : "ASIC");
+
+AI2C_RETURN_LABEL
+ return ai2cStatus;
+}
+
+int ai2c_memSetup(struct ai2c_priv **outPriv)
+{
+ int ai2cStatus = AI2C_ST_SUCCESS;
+ struct ai2c_priv *priv = NULL;
+ int i;
+
+ /* Now for the private memory for this module. */
+ priv = ai2c_malloc(sizeof(struct ai2c_priv));
+ if (!priv) {
+ AI2C_LOG(AI2C_MSG_ERROR,
+ "Could not allocate AI2C private memory root!\n");
+ ai2cStatus = -ENOMEM;
+ goto ai2c_return;
+ }
+ memset(priv, 0, sizeof(struct ai2c_priv));
+
+ /* Check chipType/chipVersion fields of 0xa.0x10.0x2c, first */
+ ai2cStatus = ai2c_getChipType(priv);
+ if (ai2cStatus != AI2C_ST_SUCCESS)
+ goto ai2c_return;
+
+ /* What is the page mapping scheme for this platform? */
+ for (i = 0; i < ai2c_dev_page_index_cnt; i++) {
+
+ if (ai2c_dev_page_index[i].chipType == priv->hw_rev.chipType) {
+ priv->pages = ai2c_dev_page_index[i].pages;
+ priv->busCfg = &ai2c_dev_page_index[i];
+ priv->numActiveBusses =
+ ai2c_dev_page_index[i].numActiveBusses;
+ }
+ }
+ if (priv->pages == NULL) {
+ AI2C_LOG(AI2C_MSG_ERROR,
+ "Can't select memory cfg for chip ver %d\n",
+ priv->hw_rev.chipType);
+ ai2cStatus = -ENXIO;
+ goto ai2c_return;
+ }
+
+ /*
+ * Program Address Map driver tables
+ * Set up the base offsets for SRIO RAB and GRIO access via paged
+ * PLB access.
+ */
+ priv->pageAddr =
+ ai2c_malloc(AI2C_DEV_PAGE_END_MARKER * sizeof(u32));
+ if (priv->pageAddr == NULL) {
+ AI2C_LOG(AI2C_MSG_ERROR,
+ "Could not allocate AI2C pageAddr memory!\n");
+ ai2cStatus = -ENOMEM;
+ goto ai2c_return;
+ }
+ memset(priv->pageAddr, 0,
+ AI2C_DEV_PAGE_END_MARKER * sizeof(u32));
+ for (i = 0; i < AI2C_DEV_PAGE_END_MARKER; i++) {
+
+ if (priv->pages[i].pageId != AI2C_DEV_PAGE_END_MARKER) {
+ priv->pageAddr[i] =
+ (u32) ioremap(priv->pages[i].busAddr,
+ priv->pages[i].size);
+ if (priv->pageAddr[i] == 0) {
+ AI2C_LOG(AI2C_MSG_ERROR,
+ "Could not ioremap AI2C pageAddr memory %d!\n",
+ i);
+ ai2cStatus = -ENOMEM;
+ goto ai2c_return;
+
+ } else {
+
+ AI2C_LOG(AI2C_MSG_DEBUG,
+ "Map page %d (%08x) / %llx for %x => %x\n",
+ priv->pages[i].pageId,
+ ai2c_page_to_region(priv,
+ priv->pages[i].pageId),
+ (unsigned long long)
+ priv->pages[i].busAddr,
+ priv->pages[i].size,
+ priv->pageAddr[i]);
+ }
+ }
+ }
+
+ AI2C_SPINLOCK_INIT(&priv->regLock);
+ AI2C_SPINLOCK_INIT(&priv->ioLock);
+
+AI2C_RETURN_LABEL
+
+ if (ai2cStatus != AI2C_ST_SUCCESS) {
+ if (priv) {
+ if (priv->pageAddr) {
+ for (i = 0; i < AI2C_DEV_PAGE_END_MARKER; i++)
+ if (priv->pageAddr[i] != 0)
+ iounmap(
+ (void __iomem *)priv->pageAddr[i]);
+ ai2c_free(priv->pageAddr);
+ }
+ ai2c_free(priv);
+ }
+ (*outPriv) = NULL;
+ } else
+ (*outPriv) = priv;
+
+ return ai2cStatus;
+}
+
+int ai2c_memDestroy(struct ai2c_priv *inPriv)
+{
+ int ai2cStatus = AI2C_ST_SUCCESS;
+ int i;
+
+ if (inPriv) {
+ if (inPriv->pageAddr) {
+ for (i = 0; i < AI2C_DEV_PAGE_END_MARKER; i++)
+ if (inPriv->pageAddr[i] != 0)
+ iounmap((void __iomem *)inPriv->pageAddr[i]);
+
+ ai2c_free(inPriv->pageAddr);
+ }
+
+ ai2c_free(inPriv);
+ }
+
+ return ai2cStatus;
+}
diff --git a/drivers/i2c/busses/ai2c/ai2c_plat.h b/drivers/i2c/busses/ai2c/ai2c_plat.h
new file mode 100644
index 0000000..faad41b
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_plat.h
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _AI2C_LINUX_H_
+#define _AI2C_LINUX_H_
+
+#include <linux/i2c.h>
+#include <asm/io.h>
+
+#include "ai2c_sal.h"
+#include "ai2c_dev_pvt.h"
+
+/**************************************************************************
+* Constants *
+**************************************************************************/
+
+/**********************************************************************
+* ACP I/O Mapped Functions Stuff *
+**********************************************************************/
+
+#define __ai2c_dev_direct_read ai2c_dev_direct_read
+#define __ai2c_dev_direct_write ai2c_dev_direct_write
+#define __ai2c_dev_indirect_read ai2c_dev_indirect_read
+#define __ai2c_dev_indirect_write ai2c_dev_indirect_write
+#define __ai2c_dev_dcr_read ai2c_dev_dcr_read
+#define __ai2c_dev_dcr_write ai2c_dev_dcr_write
+
+/*
+ * Enumeration of pages/regions tracked by this driver.
+ */
+enum {
+ AI2C_DEV_PAGE_AHB_BEGIN, /* Placeholder (0/1) */
+ AI2C_DEV_PAGE_I2C_0 = AI2C_DEV_PAGE_AHB_BEGIN,
+ AI2C_DEV_PAGE_I2C_1,
+ AI2C_DEV_PAGE_I2C_2,
+ AI2C_DEV_PAGE_I2C_3 /* aka SMB */,
+ AI2C_DEV_PAGE_GPIO_0,
+ AI2C_DEV_PAGE_RESET_CTRL,
+ AI2C_DEV_PAGE_TIMER,
+ AI2C_DEV_PAGE_GPREG,
+ AI2C_DEV_PAGE_AHB_END = AI2C_DEV_PAGE_GPREG,
+
+ AI2C_DEV_PAGE_END_MARKER,
+};
+
+#undef AI2C_DEV_APB_PAGE_BASE
+#define AI2C_DEV_APB_PAGE_BASE AI2C_DEV_PAGE_AHB_BEGIN
+
+
+/**************************************************************************
+* Macros *
+**************************************************************************/
+
+ /*************************************************************************
+ * I/O Macros
+ *************************************************************************/
+
+#define AI2C_EDEV_BUS_READ32(dev, p, o, var) \
+ ai2c_region_io_map[p].readFn(dev, &ai2c_region_io_map[p], \
+ o, (var), 1, 0, AI2C_NCA_CMD_CRBR, 4)
+
+#define AI2C_EDEV_BUS_BLOCK_READ32(dev, p, o, cnt, var) \
+ ai2c_region_io_map[p].readFn(dev, &ai2c_region_io_map[p], \
+ o, (var), cnt, 0, AI2C_NCA_CMD_CRBR, 4)
+
+#define AI2C_EDEV_BUS_WRITE32(dev, p, o, var) \
+ ai2c_region_io_map[p].writeFn(dev, &ai2c_region_io_map[p], \
+ o, (var), 1, 0, AI2C_NCA_CMD_CRBW, 4)
+
+#define AI2C_EDEV_BUS_BLOCK_WRITE32(dev, p, o, cnt, var) \
+ ai2c_region_io_map[p].writeFn(dev, &ai2c_region_io_map[p], \
+ o, (var), cnt, 0, AI2C_NCA_CMD_CRBW, 4)
+
+ /*************************************************************************
+ * Debug Macros
+ *************************************************************************/
+
+#define DBGINFO(args...)
+ /* General debugging */
+#define XDBGINFO(args...)
+ /* Miscellaneous debugging, commented out */
+#define ADBGINFO(args...)
+ /* Address debugging */
+#define D1DBGINFO(args...)
+ /* Track descriptor chain register modifications */
+#define D2DBGINFO(args...)
+ /* Track descriptor chain tracking modifications */
+#define D3DBGINFO(args...)
+ /* Track descriptor chain reset modifications */
+#define D4DBGINFO(args...)
+ /* Track dme+descriptor chain modifications */
+#define ODBGINFO(args...)
+ /* Track tx irq transaction */
+#define O2DBGINFO(args...)
+ /* Track tx foreground transaction */
+#define O3DBGINFO(args...)
+ /* Track numFree changes for tx transaction */
+#define IDBGINFO(args...)
+ /* Track rx irq transaction */
+#define I2DBGINFO(args...)
+ /* Track rx foreground transaction */
+#define I3DBGINFO(args...)
+ /* Track numFree changes for rx transaction */
+#define SDBGINFO(args...)
+ /* Track dme select/release */
+#define DDBGINFO(args...)
+ /* Track dbell irq transaction */
+#define EIDBGINFO(args...)
+ /* Track enable/disable irqs */
+#define GSDBGINFO(args...) printk(args)
+ /* Dump lots of data to console during get_glob_stat */
+#undef MDBG_SUPPORT
+#ifdef MDBG_SUPPORT
+ #define MDBGINFO(args...) printk(args)
+ /* Track maintenance accesses */
+#else
+ #define MDBGINFO(args...)
+#endif
+
+ /**********************************************************************
+ * Macros for Paged Sysmem Access Methods *
+ **********************************************************************/
+
+#define AI2C_EDEV_BUS_PAGE_SHIFT 18
+#define AI2C_EDEV_BUS_PAGE_SIZE ((u64) 1 << AI2C_EDEV_BUS_PAGE_SHIFT)
+
+#define AI2C_EDEV_BUS_PAGE_MASK (AI2C_EDEV_BUS_PAGE_SIZE - 1) /* ??? */
+#define AI2C_EDEV_BUS_PAGE_OFFSET(x) \
+ ((u32) (((x) & (~AI2C_EDEV_BUS_PAGE_MASK)) >> \
+ AI2C_EDEV_BUS_PAGE_SHIFT)) /* ??? */
+
+
+/**********************************************************************
+* Low-level I/O based upon 'page' *
+**********************************************************************/
+
+#define AI2C_DEV_BUS_ADDR(dev, pageId, offset) \
+ ((dev)->pageAddr[pageId] + offset)
+
+#define AI2C_DEV_PAGE_ENDIANNESS(pageId) (priv->pages[pageId].endianness)
+
+
+/**************************************************************************
+* Type Definitions *
+**************************************************************************/
+
+ /**********************************************************************
+ * Support Memory Mappings for Driver State Structure *
+ **********************************************************************/
+
+#define AI2C_PAGE_FLAGS_NONE (0x00000000)
+#define AI2C_PAGE_FLAGS_I2CBUS (0x00000001)
+
+struct ai2c_dev_page {
+ int pageId;
+ char *busName;
+ u64 busAddr; /* 38-bit PCI address */
+ u32 size;
+ u32 endianness;
+ u32 flags;
+ struct ai2c_i2c_access *api;
+};
+
+struct ai2c_dev_page_entry {
+ u32 chipType;
+ char *chipName;
+ bool supportDsFns;
+ struct ai2c_dev_page *pages;
+ u32 numActiveBusses;
+};
+
+
+ /**********************************************************************
+ * Driver State Structure *
+ **********************************************************************/
+
+struct ai2c_priv {
+ spinlock_t regLock;
+ spinlock_t ioLock;
+
+ struct ai2c_rev_id hw_rev;
+
+ /* Static configuration describing selected ACP I2C bus region */
+ struct ai2c_dev_page_entry *busCfg;
+ /* Per module default config */
+ u32 numActiveBusses;
+
+ /* Memory Mapping/Management constructs */
+ struct ai2c_dev_page *pages;
+ /* Per module memory pages */
+
+ /* Memory indexing support to reach selected ACP regions */
+ u32 *pageAddr;
+
+ /* Diagnostics */
+};
+
+/**************************************************************************
+* Exportable State *
+**************************************************************************/
+
+extern int AI2C_MSG_TRACE_LEVEL;
+
+extern int ai2c_chip_ver;
+
+
+/**************************************************************************
+* Exportable Functions *
+**************************************************************************/
+
+extern int ai2c_dev_read32(
+ struct ai2c_priv *dev,
+ u32 regionId,
+ u64 offset,
+ u32 *buffer);
+
+extern int ai2c_dev_write32(
+ struct ai2c_priv *dev,
+ u32 regionId,
+ u64 offset,
+ u32 buffer);
+
+int ai2c_dev_direct_read(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth);
+
+int ai2c_dev_direct_write(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth);
+
+int ai2c_dev_dcr_read(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth);
+
+int ai2c_dev_dcr_write(
+ struct ai2c_priv *priv,
+ struct ai2c_region_io *region,
+ u64 offset,
+ u32 *buffer,
+ u32 count,
+ u32 flags,
+ u32 cmdType,
+ u32 xferWidth);
+
+
+#endif /* _AI2C_PLAT_H_ */
diff --git a/drivers/i2c/busses/ai2c/ai2c_plat_pvt.h b/drivers/i2c/busses/ai2c/ai2c_plat_pvt.h
new file mode 100644
index 0000000..338bb93
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_plat_pvt.h
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_plat_pvt.h
+ * @brief Constants, structs, and APIs used to communicate with the
+ * direct ACP I2C Hardware Layer registers
+ */
+
+#ifndef AI2C_PLAT_PVT_H
+#define AI2C_PLAT_PVT_H
+
+#include "ai2c_plat.h"
+#include "ai2c_bus.h"
+
+/*****************************************************************************
+* Externally Visible Function Prototypes *
+*****************************************************************************/
+
+/*! @fn u32 ai2c_page_to_region(struct ai2c_priv *priv,
+ * u32 pageId);
+ * @brief Map a memory page handle to a regionId handle.
+ @param[in] inPriv Created device state structure
+ @param[in] inPageId Original page id to be mapped
+ @Returns mapped value
+ */
+extern u32 ai2c_page_to_region(struct ai2c_priv *priv, u32 pageId);
+
+/*! @fn u32 *ai2c_region_lookup(struct ai2c_priv *priv,
+ * u32 regionId);
+ * @brief Map a memory region handle to a region description structure.
+ @param[in] inPriv Created device state structure
+ @param[in] inRegionId Original region id to be mapped
+ @Returns mapped value
+ */
+extern struct ai2c_region_io *ai2c_region_lookup(
+ struct ai2c_priv *priv,
+ u32 regionId);
+
+/*! @fn int ai2c_memSetup(struct ai2c_priv **outPriv);
+ @brief This is a one time initialization for the I2C protocol
+ layers to be called by the device initialization step.
+ @param[out] outPriv Created device state structure
+ @Returns success/failure status of the operation
+*/
+extern int ai2c_memSetup(struct ai2c_priv **outPriv);
+
+/*! @fn int ai2c_memDestroy(struct ai2c_priv *inPriv);
+ @brief This function will release resources acquired for the specified
+ I2C device driver.
+ @param[in] inPriv Created device state structure
+ @Returns success/failure status of the operation
+*/
+extern int ai2c_memDestroy(struct ai2c_priv *inPriv);
+
+#endif /* defined(AI2C_PLAT_PVT_H) */
diff --git a/drivers/i2c/busses/ai2c/ai2c_sal.c b/drivers/i2c/busses/ai2c/ai2c_sal.c
new file mode 100644
index 0000000..9b1ea7a
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_sal.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include "ai2c_sal.h"
+
+/*
+ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+ */
+
+/*
+ * definitions of the ai2c_malloc/ai2c_nvm_malloc family of functions.
+ */
+
+void *ai2c_malloc(size_t size)
+{
+ void *p;
+
+ if (size <= 0) {
+#ifdef AI2C_DEBUG
+ AI2C_MSG(AI2C_MSG_DEBUG,
+ "WARNING: ai2c_malloc(%d) passed a zero or less size.\n",
+ size);
+#endif
+ return NULL;
+ }
+
+ p = __ai2c_malloc(size);
+ if (p == NULL)
+ AI2C_MSG(AI2C_MSG_ERROR, "ai2c_malloc(%d) failed.\n", size);
+
+ return p;
+}
+
+void *ai2c_calloc(size_t no, size_t size)
+{
+ void *p;
+
+ if (size <= 0 || no <= 0) {
+#ifdef AI2C_DEBUG
+ AI2C_MSG(AI2C_MSG_DEBUG,
+ "WARNING: ai2c_calloc(no=%d, size=%d) passed a zero or less size.\n",
+ no, size);
+#endif
+ return NULL;
+ }
+
+ p = __ai2c_calloc(no, size);
+ if (p == NULL) {
+ AI2C_MSG(AI2C_MSG_ERROR,
+ "ai2c_calloc(no=%d, size=%d) failed.\n", no, size);
+ }
+ return p;
+}
+
+void *ai2c_realloc(void *ptr, size_t size)
+{
+ if (size <= 0) {
+#ifdef AI2C_DEBUG
+ AI2C_MSG(AI2C_MSG_DEBUG,
+ "WARNING: ai2c_realloc(%d) passed a zero or less size.\n",
+ size);
+#endif
+ return NULL;
+ }
+
+ ptr = __ai2c_realloc(ptr, size);
+ if (ptr == NULL) {
+ AI2C_MSG(AI2C_MSG_ERROR,
+ "ai2c_realloc(ptr=%p, size=%d) failed.\n",
+ ptr, size);
+ }
+ return ptr;
+}
+
+void ai2c_free(void *ptr)
+{
+ if (ptr == NULL) {
+#ifdef AI2C_DEBUG
+ AI2C_MSG(AI2C_MSG_DEBUG,
+ "WARNING: ai2c_free(%p) passed a NULL pointer.\n",
+ ptr);
+#endif
+ return;
+ }
+
+ __ai2c_free(ptr);
+}
diff --git a/drivers/i2c/busses/ai2c/ai2c_sal.h b/drivers/i2c/busses/ai2c/ai2c_sal.h
new file mode 100644
index 0000000..4a39867
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_sal.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_sal.h
+ @brief OS Specific definitions are located here.
+*/
+
+#ifndef __AI2C_SAL_H__
+#define __AI2C_SAL_H__
+
+#include "ai2c_sal_types.h"
+#include "ai2c_dev.h"
+#include "ai2c_sal_linux.h"
+
+/* should not be in sal */
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+#ifndef MAX
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#endif
+
+extern void *ai2c_malloc(size_t size);
+extern void *ai2c_realloc(void *ptr, size_t size);
+extern void *ai2c_calloc(size_t no, size_t size);
+extern void ai2c_free(void *ptr);
+
+#endif /* __AI2C_SAL_H__ */
diff --git a/drivers/i2c/busses/ai2c/ai2c_sal_linux.h b/drivers/i2c/busses/ai2c/ai2c_sal_linux.h
new file mode 100644
index 0000000..4e96249
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_sal_linux.h
@@ -0,0 +1,318 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_sal_linux.h
+ @brief OS Specific definitions are located here.
+*/
+
+
+#ifndef __AI2C_SAL_LINUX_H__
+#define __AI2C_SAL_LINUX_H__
+
+#include <linux/module.h>
+#include <generated/autoconf.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/kthread.h>
+
+#include <linux/io.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/of_platform.h>
+
+#include <linux/sched.h>
+#include <linux/moduleparam.h>
+#include <linux/cdev.h>
+#include <linux/version.h>
+#include <linux/wait.h>
+#include <asm/pgtable.h>
+
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/spinlock.h>
+
+#include <linux/irqdomain.h>
+
+#include <linux/signal.h>
+#include <linux/time.h>
+#include <linux/fcntl.h>
+#include <linux/unistd.h>
+#include <linux/errno.h>
+#include <linux/mman.h>
+
+#include <asm/byteorder.h>
+
+#ifdef __BIG_ENDIAN
+#undef AI2C_BIG_ENDIAN
+#define AI2C_BIG_ENDIAN 9999
+#undef AI2C_LITTLE_ENDIAN
+#endif
+
+#ifdef __LITTLE_ENDIAN
+#undef AI2C_BIG_ENDIAN
+#undef AI2C_LITTLE_ENDIAN
+#define AI2C_LITTLE_ENDIAN 9998
+#endif
+
+
+/*
+* AI2C_MSG
+*
+* Print a message to the system console.
+*/
+#define AI2C_MSG(type, fmt, args...) \
+ do { \
+ if ((type) & AI2C_MSG_TRACE_LEVEL) { \
+ if ((type) == AI2C_MSG_ERROR) \
+ printk(KERN_ERR AI2C_MOD_NAME ": ERROR: "); \
+ else \
+ printk(KERN_WARNING AI2C_MOD_NAME ": "); \
+ printk(fmt, ## args); \
+ } \
+ } while (0)
+
+ /*
+ * AI2C_LOG
+ *
+ * Print a message to the system log device and/or console. This
+ * interface is callable from interrupt level.
+ */
+#define AI2C_LOG \
+ AI2C_MSG
+
+#ifndef AI2C_MSG_TRACE_LEVEL
+#define AI2C_MSG_TRACE_LEVEL ai2c_trace_level
+#endif
+
+extern int AI2C_MSG_TRACE_LEVEL;
+
+
+/*
+* Endian-ness Conversion
+*/
+
+#define AI2C_SWAP16m(n) \
+ ((((u16)(n) >> 8) & 0x00ff) | \
+ (((u16)(n) << 8) & 0xff00))
+
+#define AI2C_SWAP32m(n) \
+ ((((u32)(n) >> 24) & 0x000000ff) | \
+ (((u32)(n) >> 8) & 0x0000ff00) | \
+ (((u32)(n) << 8) & 0x00ff0000) | \
+ (((u32)(n) << 24) & 0xff000000))
+
+#define SWAP16(x) \
+ { { \
+ u16 val = x; \
+ AI2C_SWAP16m(val); \
+ } }
+
+#define SWAP32(x) \
+ { { \
+ u32 val = x; \
+ AI2C_SWAP32m(val); \
+ } }
+
+
+/*
+* Endian-ness I/O
+*/
+
+#ifdef CONFIG_ARM
+
+#define in_be8(x) (*x)
+#define in_be16(x) AI2C_SWAP16m(*x)
+#define in_be32(x) AI2C_SWAP32m(*x)
+
+#define in_le8(x) (*x)
+#define in_le16(x) (*x)
+#define in_le32(x) (*x)
+
+#define out_be8(a, v) (*a) = (v)
+#define out_be16(a, v) (*a) = AI2C_SWAP16m(v)
+#define out_be32(a, v) (*a) = AI2C_SWAP32m(v)
+
+#define out_le8(a, v) (*a) = (v)
+#define out_le16(a, v) (*a) = (v)
+#define out_le32(a, v) (*a) = (v)
+
+#endif /* CONFIG_ARM */
+
+
+#define AI2C_EDEV_BUS_ENFORCE_ORDERING()
+
+#define AI2C_BUS_READ8(addr) \
+ readb((volatile u8 __iomem *) (addr))
+
+#define AI2C_BUS_READ16_ENDIAN(endian, addr) \
+ in_##endian##16((volatile u16 __iomem *) (addr))
+
+
+#define AI2C_BUS_READ16_LE(addr) AI2C_BUS_READ16_ENDIAN(le, addr)
+
+#define AI2C_BUS_READ16_BE(addr) AI2C_BUS_READ16_ENDIAN(be, addr)
+
+#define AI2C_BUS_READ16(addr, endian) \
+ (endian == AI2C_DEV_ACCESS_BIG_ENDIAN) ? \
+ AI2C_BUS_READ16_BE(addr) : AI2C_BUS_READ16_LE(addr)
+
+#define AI2C_BUS_READ32_ENDIAN(endian, addr) \
+ in_##endian##32((volatile u32 __iomem *) (addr))
+
+
+#define AI2C_BUS_READ32_LE(addr) AI2C_BUS_READ32_ENDIAN(le, addr)
+
+#define AI2C_BUS_READ32_BE(addr) AI2C_BUS_READ32_ENDIAN(be, addr)
+
+#define AI2C_BUS_READ32(addr, endian) \
+ (endian == AI2C_DEV_ACCESS_BIG_ENDIAN) ? \
+ AI2C_BUS_READ32_BE(addr) : AI2C_BUS_READ32_LE(addr)
+
+
+#define AI2C_BUS_WRITE8(addr, data) \
+ writeb((data), (volatile u8 __iomem *) (addr))
+
+#define AI2C_BUS_WRITE16_ENDIAN(endian, addr, data) \
+ do { \
+ u16 *__a__ = (u16 *) addr; \
+ u16 __d__ = data; \
+ out_##endian##16((volatile u16 __iomem *) __a__, __d__); \
+ AI2C_EDEV_BUS_ENFORCE_ORDERING(); \
+ } while (0);
+
+#define AI2C_BUS_WRITE16_LE(addr, data) \
+ AI2C_BUS_WRITE16_ENDIAN(le, addr, data)
+
+#define AI2C_BUS_WRITE16_BE(addr, data) \
+ AI2C_BUS_WRITE16_ENDIAN(be, addr, data)
+
+#define AI2C_BUS_WRITE16(addr, data, endian) \
+ if (endian == AI2C_DEV_ACCESS_BIG_ENDIAN) { \
+ AI2C_BUS_WRITE16_BE(addr, data); \
+ } else { \
+ AI2C_BUS_WRITE16_LE(addr, data); \
+ }
+
+#define AI2C_BUS_WRITE32_ENDIAN(endian, addr, data) \
+ do { \
+ u32 *__a__ = (u32 *) addr; \
+ u32 __d__ = data; \
+ out_##endian##32((volatile u32 __iomem *) \
+ __a__, __d__); \
+ AI2C_EDEV_BUS_ENFORCE_ORDERING(); \
+ } while (0);
+
+#define AI2C_BUS_WRITE32_LE(addr, data) \
+ AI2C_BUS_WRITE32_ENDIAN(le, addr, data)
+
+#define AI2C_BUS_WRITE32_BE(addr, data) \
+ AI2C_BUS_WRITE32_ENDIAN(be, addr, data)
+
+#define AI2C_BUS_WRITE32(addr, data, endian) \
+ if (endian == AI2C_DEV_ACCESS_BIG_ENDIAN) { \
+ AI2C_BUS_WRITE32_BE(addr, data); \
+ } else { \
+ AI2C_BUS_WRITE32_LE(addr, data); \
+ }
+
+ /*
+ * Spinlock mutex stuff
+ */
+
+#define AI2C_SPINLOCK_INIT(pSpinlock) \
+ spin_lock_init(pSpinlock)
+
+#define AI2C_SPINLOCK_LOCK(pSpinlock) \
+ spin_lock(pSpinlock)
+
+#define AI2C_SPINLOCK_TRYLOCK(pSpinlock) \
+ spin_trylock(pSpinlock)
+
+#define AI2C_SPINLOCK_UNLOCK(pSpinlock) \
+ spin_unlock(pSpinlock)
+
+#define AI2C_SPINLOCK_INTERRUPT_DISABLE(pSem, flags) \
+ spin_lock_irqsave(pSem, flags)
+
+#define AI2C_SPINLOCK_INTERRUPT_ENABLE(pSem, flags) \
+ spin_unlock_irqrestore(pSem, flags)
+
+#define AI2C_SPINLOCK_SW_INTERRUPT_DISABLE(pSem, flags) \
+ spin_lock_bh(pSem)
+
+#define AI2C_SPINLOCK_SW_INTERRUPT_ENABLE(pSem, flags) \
+ spin_unlock_bh(pSem)
+
+
+ /*
+ * Kernel memory allocation
+ */
+
+#define __ai2c_malloc(size) kmalloc(size, GFP_KERNEL)
+#define __ai2c_free(ptr) kfree(ptr)
+#define __ai2c_realloc(ptr, size) (NULL)
+#define __ai2c_calloc(no, size) kcalloc(no, size, GFP_KERNEL)
+
+
+ /*
+ * Miscellaneous externs not provided by other headers reliably
+ */
+
+extern int snprintf(char *s, size_t n, const char *format, ...);
+
+struct ai2c_rev_id {
+
+#ifdef NCP_BIG_ENDIAN
+ unsigned isAsic:1;
+ unsigned isFpga:1;
+ unsigned isSim:1;
+ unsigned:2;
+ unsigned secDisable:1;
+ unsigned sppDisable:1;
+ unsigned cpuDisable:4;
+ unsigned ecidChipType:5;
+ unsigned:1;
+ unsigned packageType:4;
+ unsigned chipVersion:6;
+ unsigned chipTyp:5;
+#else
+ unsigned chipType:5;
+ unsigned chipVersion:6;
+ unsigned packageType:4;
+ unsigned:1;
+ unsigned ecidChipType:5;
+ unsigned cpuDisable:4;
+ unsigned sppDisable:1;
+ unsigned secDisable:1;
+ unsigned:2;
+ unsigned isSim:1;
+ unsigned isFpga:1;
+ unsigned isAsic:1;
+#endif
+};
+
+
+#endif /* __AI2C_SAL_LINUX_H__ */
diff --git a/drivers/i2c/busses/ai2c/ai2c_sal_types.h b/drivers/i2c/busses/ai2c/ai2c_sal_types.h
new file mode 100644
index 0000000..a6d2263
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_sal_types.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_sal_types.h
+ @brief OS Specific types are located here.
+*/
+
+#ifndef AI2C_SAL_TYPES_H
+#define AI2C_SAL_TYPES_H
+
+#include <linux/types.h>
+
+/**************************************************************************
+* Constants, #Defines, etc.
+**************************************************************************/
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#endif /* AI2C_SAL_TYPES_H */
diff --git a/drivers/i2c/busses/ai2c/ai2c_types.h b/drivers/i2c/busses/ai2c/ai2c_types.h
new file mode 100644
index 0000000..c748823
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/ai2c_types.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef AI2C_TYPES_H
+#define AI2C_TYPES_H
+
+/**************************************************************************
+ * ACP chip types
+ *
+ * These are the base silicon chip types. Each chip may have one
+ * or more variants, but for the purpose of the chipType comparison
+ * we only care about the base silicon version. For any variant the
+ * driver will set the chipType in virtual register 0x301.0.0 to
+ * one of the following.
+ **************************************************************************/
+
+#define AI2C_CHIP_ACP34xx 1
+#define AI2C_CHIP_ACP32xx 2
+#define AI2C_CHIP_ACP25xx 6
+#define AI2C_CHIP_ACP25xx_V2 7
+
+#define AI2C_CHIP_X3X7_HYBRID 7 /* TEMP HACK */
+
+#define AI2C_CHIP_ACP55xx 9 /* AXM55xx, aka X7 */
+#define AI2C_CHIP_ACP35xx 16 /* AXM35xx, aka X3 */
+
+
+/**************************************************************************
+* API Configuration Status Codes, Typedefs, etc.
+**************************************************************************/
+
+#define AI2C_ST_SUCCESS (0)
+
+
+/**************************************************************************
+* Function Call Support Typedefs, Constants, Macros, etc.
+**************************************************************************/
+
+#ifdef AI2C_ERR_DEBUG
+#define AI2C_PRINT_LINE_FILE \
+ AI2C_MSG(AI2C_MSG_INFO, "%s : %s, line = %d\n", \
+ ai2c_status_get(ai2cStatus), __FILE__, __LINE__)
+#else
+#define AI2C_PRINT_LINE_FILE
+#endif /* AI2C_ERR_DEBUG */
+
+#define AI2C_CALL(ai2cFunc) \
+ do { \
+ ai2cStatus = (ai2cFunc); \
+ if (ai2cStatus != AI2C_ST_SUCCESS) { \
+ AI2C_PRINT_LINE_FILE; \
+ goto ai2c_return; \
+ } \
+ } while (0);
+
+
+/*
+ * A general purpose way to eliminate warnings due the the label
+ * not being referenced.
+ */
+#define AI2C_RETURN_LABEL \
+ goto ai2c_return; \
+ai2c_return:
+
+#endif /* AI2C_TYPES_H */
diff --git a/drivers/i2c/busses/ai2c/regs/ai2c_axi_timer_regs.h b/drivers/i2c/busses/ai2c/regs/ai2c_axi_timer_regs.h
new file mode 100644
index 0000000..10adc2c
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/regs/ai2c_axi_timer_regs.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_axi_timer_regs.h
+ * @brief Constants, structs, and APIs used to configure the ACP Timer
+ * associated with various hardware modules and interfaces.
+ */
+
+#ifndef _AI2C_AXI_TIMER_REGS_H_
+#define _AI2C_AXI_TIMER_REGS_H_
+
+/*****************************************************************************
+* Macros & Constants *
+*****************************************************************************/
+
+/*
+ * Register Group offsets
+ *
+ * The ACP has 8 groups of these handles at offsets 0x00, 0x20, 0x40,
+ * 0x60, 0x80, 0xA0, 0xC0, and 0xE0.
+ */
+#define AI2C_TIMER_SSP_OFFSET (0x0000) /*!< Offset to start of
+ SSP timer group */
+#define AI2C_TIMER_I2C_OFFSET (0x0020) /*!< Offset to start of
+ I2C timer group */
+#define AI2C_TIMER_UART0_CLK_OFFSET (0x0040) /*!< Offset to start of
+ UART0 Clk timer group */
+#define AI2C_TIMER_UART1_CLK_OFFSET (0x0060) /*!< Offset to start of
+ UART1 Clk timer group */
+#define AI2C_TIMER_WDOG_RESET_OFFSET (0x0080) /*!< Offset to start of
+ Watchdog Reset timer group */
+#define AI2C_TIMER_GP5_OFFSET (0x00A0) /*!< Offset to start of General
+ Purpose Timer #5 group */
+#define AI2C_TIMER_GP6_OFFSET (0x00C0) /*!< Offset to start of General
+ Purpose Timer #6 group */
+#define AI2C_TIMER_GP7_OFFSET (0x00E0) /*!< Offset to start of General
+ Purpose Timer #7 group */
+
+/*
+ * Register handle offsets
+ */
+
+#define AI2C_REG_TIMER_TLV (0x0000) /*!< Byte offset to Timer
+ load value register */
+#define AI2C_REG_TIMER_TV (0x0004) /*!< Byte offset to Timer
+ value register */
+#define AI2C_REG_TIMER_TC (0x0008) /*!< Byte offset to Timer
+ control register */
+#define AI2C_REG_TIMER_TIC (0x000C) /*!< Byte offset to Timer
+ interrupt clear register */
+#define AI2C_REG_TIMER_RIS (0x0010) /*!< Byte offset to Timer
+ raw interrupt source register */
+#define AI2C_REG_TIMER_IS (0x0014) /*!< Byte offset to Timer
+ interrupt source */
+#define AI2C_REG_TIMER_BLV (0x0018) /*!< Byte offset to Timer
+ background load value register */
+
+
+/*****************************************************************************
+* Register Definitions *
+*****************************************************************************/
+
+/*! @struct ai2c_reg_timer_tlv
+ * @brief Timer load value register
+ * Let:
+ * Prescale=<1..4>
+ * Clk_Period=K MHz
+ * Output Freq=J MHz
+ *
+ * Solve,
+ * Output Freq = (Clk_Period / Timer Prescale) /
+ * (Timer Load Value + 1)
+ * for
+ * "Timer Load Value"
+ *
+ * Example:
+ * Prescale=1, Clk_Period=400 MHz, Output Freq=4 MHz
+ * 4 MHZ = (400 MHz / 1) / (TLV + 1)
+ * TLV = (400/4) - 1
+ * = 99
+ */
+struct ai2c_reg_timer_tlv {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned value:32; /*!< bits 31:00 timer load value */
+#else
+ unsigned value:32; /*!< bits 31:00 timer load value */
+#endif
+};
+
+/*! @struct ai2c_reg_timer_tv
+ * @brief Timer value register
+ */
+struct ai2c_reg_timer_tv {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned value:32; /*!< bits 31:00 timer value */
+#else
+ unsigned value:32; /*!< bits 31:00 timer value */
+#endif
+};
+
+/*! @struct ai2c_reg_timer_tc
+ * @brief Timer control register
+ */
+struct ai2c_reg_timer_tc {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_08:24; /* bits 31:08 reserved */
+ unsigned te:1; /*!< bits 7 timer enable */
+ unsigned rmode:1; /*!< bits 6 mode */
+ unsigned ie:1; /*!< bits 5 interrupt enable */
+ unsigned omode:1; /*!< bits 4 output mode */
+ unsigned pres:2; /*!< bits 3: 2 pre-scaler */
+ unsigned size:1; /*!< bits 1 size */
+ unsigned osm:1; /*!< bits 0 one shot mode */
+#else
+ unsigned osm:1; /*!< bits 0 one shot mode */
+ unsigned size:1; /*!< bits 1 size */
+ unsigned pres:2; /*!< bits 3: 2 pre-scaler */
+ unsigned omode:1; /*!< bits 4 output mode */
+ unsigned ie:1; /*!< bits 5 interrupt enable */
+ unsigned rmode:1; /*!< bits 6 mode */
+ unsigned te:1; /*!< bits 7 timer enable */
+ unsigned reserved_31_08:24; /* bits 31:08 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_timer_tic
+ * @brief Timer interrupt clear register
+ */
+struct ai2c_reg_timer_tic {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned value:31; /* bits 31:01 reserved */
+ unsigned tic:1; /*!< bits 0 timer interrupt clear */
+#else
+ unsigned tic:1; /*!< bits 0 timer interrupt clear */
+ unsigned value:31; /* bits 31:01 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_timer_ris
+ * @brief Timer raw interrupt status register
+ */
+struct ai2c_reg_timer_ris {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved:31; /* bits 31:01 reserved */
+ unsigned ris:1; /*!< bits 0 raw interrupt status */
+#else
+ unsigned ris:1; /*!< bits 0 raw interrupt status */
+ unsigned reserved:31; /* bits 31:01 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_timer_is
+ * @brief Timer interrupt status register
+ */
+struct ai2c_reg_timer_is {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved:31; /* bits 31:01 reserved */
+ unsigned is:1; /*!< bits 0 interrupt status */
+#else
+ unsigned is:1; /*!< bits 0 interrupt status */
+ unsigned reserved:31; /* bits 31:01 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_timer_blv
+ * @brief Timer background load value register
+ */
+struct ai2c_reg_timer_blv {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned value:32; /*!< bits 31:00 background load value */
+#else
+ unsigned value:32; /*!< bits 31:00 background load value */
+#endif
+};
+
+#endif /* _AI2C_AXI_TIMER_REGS_H_ */
diff --git a/drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_reg_defines.h b/drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_reg_defines.h
new file mode 100644
index 0000000..f120fed
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_reg_defines.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#ifndef _AI2C_CFG_NODE_REG_DEFINES_H_
+#define _AI2C_CFG_NODE_REG_DEFINES_H_
+
+ /* NODE 0x1a , TARGET 0xff*/
+
+
+#define AI2C_CFG_NODE_NODE_INFO_0 (0x00000000)
+#define AI2C_CFG_NODE_NODE_INFO_1 (0x00000004)
+#define AI2C_CFG_NODE_NODE_INFO_2 (0x00000008)
+#define AI2C_CFG_NODE_NODE_INFO_3 (0x0000000c)
+#define AI2C_CFG_NODE_NODE_CFG (0x00000010)
+#define AI2C_CFG_NODE_WRITE_ERR_ADDR (0x00000014)
+#define AI2C_CFG_NODE_NODE_ERROR (0x00000018)
+#define AI2C_CFG_NODE_NODE_ERROR_DATA_R (0x0000001c)
+#define AI2C_CFG_NODE_NODE_SCRATCH (0x00000020)
+
+#endif /* _AI2C_CFG_NODE_REG_DEFINES_H_ */
diff --git a/drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_regs.h b/drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_regs.h
new file mode 100644
index 0000000..8d2109a
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/regs/ai2c_cfg_node_regs.h
@@ -0,0 +1,146 @@
+/**************************************************************************
+ ** *
+ ** LSI CONFIDENTIAL *
+ ** PROPRIETARY NOTE *
+ ** *
+ ** This software contains information confidential and proprietary *
+ ** to LSI Inc. It shall not be reproduced in whole or in *
+ ** part, or transferred to other documents, or disclosed to third *
+ ** parties, or used for any purpose other than that for which it was *
+ ** obtained, without the prior written consent of LSI Inc. *
+ ** (c) 2001-2013, LSI Inc. All rights reserved. *
+ ** *
+ ** **********************************************************************/
+
+#ifndef _AI2C_CFG_NODE_REGS_H_
+#define _AI2C_CFG_NODE_REGS_H_
+
+/*! @struct ai2c_cfg_node_node_info_0_r_t
+ * @brief CFG Node Info Register 0
+ * @details This register contains the module type and module revision
+ * for the module containing this CFG Node.
+ */
+struct ai2c_cfg_node_node_info_0_r {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned module_type:16;
+ unsigned module_revision:16;
+#else /* Little Endian */
+ unsigned module_revision:16;
+ unsigned module_type:16;
+#endif
+};
+
+/*! @struct ai2c_cfg_node_node_info_1_r
+ * @brief CFG Node Info Register 1
+ * @details This read-only register contains the module instance
+ * and lower 24 bits of the module info field for the module
+ * containing this CFG Node.
+ */
+struct ai2c_cfg_node_node_info_1_r {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned module_info:24;
+ unsigned module_instance:8;
+#else /* Little Endian */
+ unsigned module_instance:8;
+ unsigned module_info:24;
+#endif
+};
+
+/*! @struct ai2c_cfg_node_node_info_2_r
+ * @brief CFG Node Info Register 2
+ * @details This read-only register contains bits 55:24 of the module info field for the module containing this CFG Node.
+ */
+struct ai2c_cfg_node_node_info_2_r {
+ unsigned int module_info;
+};
+
+/*! @struct ai2c_cfg_node_node_info_3_r
+ * @brief CFG Node Info Register 3
+ * @details This read-only register contains bits 87:56 of the module info field for the module containing this CFG Node.
+ */
+struct ai2c_cfg_node_node_info_3_r {
+ unsigned int module_info;
+};
+
+/*! @struct ai2c_cfg_node_node_cfg_r
+ * @brief CFG Node Configuration Register
+ * @details This register contains fields that control the operation of the CFG node.
+ */
+struct ai2c_cfg_node_node_cfg_r {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned fpga:1;
+ unsigned reserved0:26;
+ unsigned opt_fill:1;
+ unsigned clk_apb_sel:2;
+ unsigned parity_enable:1;
+ unsigned parity_odd:1;
+#else /* Little Endian */
+ unsigned parity_odd:1;
+ unsigned parity_enable:1;
+ unsigned clk_apb_sel:2;
+ unsigned opt_fill:1;
+ unsigned reserved0:26;
+ unsigned fpga:1;
+#endif
+};
+
+/*! @struct ai2c_cfg_node_write_err_addr_r
+ * @brief CFG Node Write Error Address Register
+ * @details This read-only register holds the address associated with the first write error for the last write command.
+ */
+struct ai2c_cfg_node_write_err_addr_r {
+ unsigned int error_address;
+};
+
+/*! @struct ai2c_cfg_node_node_error_r
+ * @brief CFG Node Error Register
+ * @details This register holds the sticky errors detected by the CFG node.
+ */
+struct ai2c_cfg_node_node_error_r {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved0:26;
+ unsigned node_error:1;
+ unsigned parity_error:1;
+ unsigned afifo_overflow:1;
+ unsigned afifo_underflow:1;
+ unsigned dfifo_overflow:1;
+ unsigned dfifo_underflow:1;
+#else /* Little Endian */
+ unsigned dfifo_underflow:1;
+ unsigned dfifo_overflow:1;
+ unsigned afifo_underflow:1;
+ unsigned afifo_overflow:1;
+ unsigned parity_error:1;
+ unsigned node_error:1;
+ unsigned reserved0:26;
+#endif
+};
+
+/*! @struct ai2c_cfg_node_node_error_data_r
+ * @brief CFG Node Error Data Register
+ * @details This register holds the error code associated with the first protocol error detected by the CFG node.
+ */
+struct ai2c_cfg_node_node_error_data_r {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved0:28;
+ unsigned error_code:4;
+#else /* Little Endian */
+ unsigned error_code:4;
+ unsigned reserved0:28;
+#endif
+};
+
+/*! @struct ai2c_cfg_node_node_scratch_r
+ * @brief CFG Node Scratch Register
+ * @details This register is a scratch location for software's use.
+ */
+struct ai2c_cfg_node_node_scratch_r {
+ unsigned int scratch;
+};
+
+#endif /* _AI2C_CFG_NODE_REGS_H_ */
diff --git a/drivers/i2c/busses/ai2c/regs/ai2c_i2c_regs.h b/drivers/i2c/busses/ai2c/regs/ai2c_i2c_regs.h
new file mode 100644
index 0000000..4c1954b
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/regs/ai2c_i2c_regs.h
@@ -0,0 +1,1797 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_i2c_regs.h
+ * @brief I2C Hardware Layer Register Map
+ */
+
+#ifndef _AI2C_I2C_REGS_H_
+#define _AI2C_I2C_REGS_H_
+
+/*!
+ * @defgroup _i2c_hw_regs_ I2C Hardware Register Map
+ * @brief I2C Hardware Registers (i2chwregs)
+ * @details ACP HW registers used to communicate with I2C devices on the
+ * I2C bus immediately associated with the ACP
+ * @{
+ * @ingroup _i2c_
+ */
+
+/******************************************************************************
+ * Register handle offsets (X1/X2 aka ACP3400, ACP2500) *
+ * *
+ * Regions:0x143.0, 0x14c.0 *
+ ******************************************************************************/
+
+#define AI2C_REG_I2C_MAST_XMT_CFG (0x0000) /*!< Offset to reg Master
+ Transmit Config */
+#define AI2C_REG_I2C_MAST_RCV_CFG (0x0004) /*!< Offset to reg Master
+ Receive Config */
+#define AI2C_REG_I2C_MAST_XMT_STAT (0x0008) /*!< Offset to reg Master
+ Transmit Status */
+#define AI2C_REG_I2C_MAST_RCV_STAT (0x000C) /*!< Offset to reg Master
+ Receive Status */
+#define AI2C_REG_I2C_MAST_INT_ENABLE (0x0010) /*!< Offset to reg Master
+ Interrupt Enable */
+#define AI2C_REG_I2C_MAST_INT_CLEAR (0x0014) /*!< Offset to reg Master
+ Interrupt Clear */
+#define AI2C_REG_I2C_MAST_INT_STAT (0x0018) /*!< Offset to reg Master
+ Interrupt Status */
+#define AI2C_REG_I2C_MAST_CLK_CFG (0x001C) /*!< Offset to reg Master
+ Clock Config */
+#define AI2C_REG_I2C_MAST_START_HLD_CFG (0x0020) /*!< Offset to reg Master
+ Start Hold
+ Timing Config */
+#define AI2C_REG_I2C_MAST_STOP_HLD_CFG (0x0024) /*!< Offset to reg Master
+ Stop Hold
+ Timing Config */
+#define AI2C_REG_I2C_MAST_DATA_HLD_CFG (0x0028) /*!< Offset to reg Master
+ Data Hold
+ Timing Config */
+#define AI2C_REG_I2C_MAST_BYPASS_MODE (0x002C) /*!< Offset to reg Master
+ Bypass Mode */
+#define AI2C_REG_I2C_MAST_SLV_ADDRESS (0x0030) /*!< Offset to reg Master
+ Slave Address target */
+#define AI2C_REG_I2C_MAST_TXD0 (0x0034) /*!< Offset to reg Master
+ Transmit Data 0 */
+#define AI2C_REG_I2C_MAST_TXD1 (0x0038) /*!< Offset to reg Master
+ Transmit Data 1 */
+#define AI2C_REG_I2C_MAST_RXD0 (0x003C) /*!< Offset to reg Master
+ Receive Data 0 */
+#define AI2C_REG_I2C_MAST_RXD1 (0x0040) /*!< Offset to reg Master
+ Receive Data 1 */
+#define AI2C_REG_I2C_SLV_TXRXCONFIG (0x0044) /*!< Offset to reg Slave
+ Transmit/Receive
+ Config */
+#define AI2C_REG_I2C_SLV_STAT (0x0048) /*!< Offset to reg
+ Slave Status */
+#define AI2C_REG_I2C_SLV_SELF_ADDRESS (0x004C) /*!< Offset to reg
+ Slave Self Address */
+#define AI2C_REG_I2C_SLV_TXD0 (0x0050) /*!< Offset to reg Slave
+ Transmit Data 0 */
+#define AI2C_REG_I2C_SLV_TXD1 (0x0054) /*!< Offset to reg Slave
+ Transmit Data 1 */
+#define AI2C_REG_I2C_SLV_RXD0 (0x0058) /*!< Offset to reg Slave
+ Receive Data 0 */
+#define AI2C_REG_I2C_SLV_RXD1 (0x005C) /*!< Offset to reg Slave
+ Receive Data 1 */
+#define AI2C_REG_I2C_SLV_INT_ENABLE (0x0060) /*!< Offset to reg Slave
+ Interrupt Enable */
+#define AI2C_REG_I2C_SLV_INT_CLEAR (0x0064) /*!< Offset to reg Slave
+ Interrupt Clear */
+#define AI2C_REG_I2C_SLV_DATA_HLD_CFG (0x0068) /*!< Offset to reg Slave
+ Data Hold
+ Timing Config */
+#define AI2C_REG_I2C_SLV_CLK_CFG (0x006C) /*!< Offset to reg
+ Slave Clock Config */
+
+
+/**********************************
+ * Register Structure definitions *
+ *********************************/
+
+/*! @struct ai2c_reg_i2c_mast_xmt_cfg
+ * @brief I2C Master XMIT Cfg register
+ */
+struct ai2c_reg_i2c_mast_xmt_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:2; /* bits 31:30 reserved */
+ unsigned stop:1; /*!< bits 29 Stop I2C clock */
+ unsigned:18; /* bits 28:11 reserved */
+ unsigned zeroAll:1; /*!< bits 10 Zero all control/data */
+ unsigned command:1; /*!< bits 9 write=0, read=1 */
+ unsigned mastModeActive:1; /*!< bits 8 Master mode active */
+ unsigned tenBitAddr:1; /*!< bits 7 10-bit address mode */
+ unsigned:1; /* bits 6 reserved */
+ unsigned endianness:1; /*!< bits 5 0=BE (def), 1=LE */
+ unsigned numBytes:4; /*!< bits 4:1 number of bytes to xmit*/
+ unsigned xmtReady:1; /*!< bits 0 Transmit Ready */
+#else
+ unsigned xmtReady:1; /*!< bits 0 Transmit Ready */
+ unsigned numBytes:4; /*!< bits 4:1 number of bytes to xmit*/
+ unsigned endianness:1; /*!< bits 5 0=BE (def), 1=LE */
+ unsigned:1; /* bits 6 reserved */
+ unsigned tenBitAddr:1; /*!< bits 7 10-bit address mode */
+ unsigned mastModeActive:1; /*!< bits 8 Master mode active */
+ unsigned command:1; /*!< bits 9 write=0, read=1 */
+ unsigned zeroAll:1; /*!< bits 10 Zero all control/data */
+ unsigned:18; /* bits 28:11 reserved */
+ unsigned stop:1; /*!< bits 29 Stop I2C clock */
+ unsigned:2; /* bits 31:30 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_rcv_cfg
+ * @brief I2C Master RCV Cfg register
+ */
+struct ai2c_reg_i2c_mast_rcv_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_8:24; /* bits 31:8 reserved */
+ unsigned reserved_7_6:2; /* bits 7:6 reserved */
+ unsigned chgEndianness:1; /*!< bits 5 0=BE (def), 1=LE */
+ unsigned numBytes:4; /*!< bits 4:1 number of bytes to rcv */
+ unsigned rcvReady:1; /*!< bits 0 Receive Ready */
+#else
+ unsigned rcvReady:1; /*!< bits 0 Receive Ready */
+ unsigned numBytes:4; /*!< bits 4:1 number of bytes to rcv */
+ unsigned chgEndianness:1; /*!< bits 5 0=BE (def), 1=LE */
+ unsigned reserved_7_6:2; /* bits 7:6 reserved */
+ unsigned reserved_31_8:24; /* bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_xmt_stat
+ * @brief I2C Master XMIT Status register
+ */
+struct ai2c_reg_i2c_mast_xmt_stat {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_8:25; /* bits 31:8 reserved */
+ unsigned reserved_7_2:5; /* bits 7:2 reserved */
+ unsigned xmtError:1; /*!< bits 1 Transmission error */
+ unsigned xmtDone:1; /*!< bits 0 Transmit done */
+#else
+ unsigned xmtDone:1; /*!< bits 0 Transmit done */
+ unsigned xmtError:1; /*!< bits 1 Transmission error */
+ unsigned reserved_7_2:5; /* bits 7:2 reserved */
+ unsigned reserved_31_8:25; /* bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_rcv_stat
+ * @brief I2C Master RCV Status register
+ */
+struct ai2c_reg_i2c_mast_rcv_stat {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_6:26; /* bits 31:6 reserved */
+ unsigned numBytesRcv:4; /*!< bits 5:2 Num Bytes received */
+ unsigned rcvError:1; /*!< bits 1 Reception error */
+ unsigned rcvDone:1; /*!< bits 0 Receive done */
+#else
+ unsigned rcvDone:1; /*!< bits 0 Receive done */
+ unsigned rcvError:1; /*!< bits 1 Reception error */
+ unsigned numBytesRcv:4; /*!< bits 5:2 Num Bytes received */
+ unsigned reserved_31_6:26; /* bits 31:6 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_int_enable
+ * @brief I2C Master Interrupt Enable register
+ */
+struct ai2c_reg_i2c_mast_int_enable {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+ unsigned intRcvErr:1; /*!< bits 3 Enable int on rcv error */
+ unsigned intXmtErr:1; /*!< bits 2 Enable int on xmt error */
+ unsigned intRcvComplete:1; /*!< bits 1 Enable int on completion
+ of received data */
+ unsigned intXmtComplete:1; /*!< bits 0 Enable int on completion
+ of transmitted data */
+#else
+ unsigned intXmtComplete:1; /*!< bits 0 Enable int on completion
+ of transmitted data */
+ unsigned intRcvComplete:1; /*!< bits 1 Enable int on completion
+ of received data */
+ unsigned intXmtErr:1; /*!< bits 2 Enable int on xmt error */
+ unsigned intRcvErr:1; /*!< bits 3 Enable int on rcv error */
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_int_clear
+ * @brief I2C Master Interrupt Clear register
+ */
+struct ai2c_reg_i2c_mast_int_clear {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+ unsigned intRcvErr:1; /*!< bits 3 Clear int on rcv error */
+ unsigned intXmtErr:1; /*!< bits 2 Clear int on xmt error */
+ unsigned intRcvComplete:1; /*!< bits 1 Clear int on completion
+ of received data */
+ unsigned intXmtComplete:1; /*!< bits 0 Clear int on completion
+ of transmitted data */
+#else
+ unsigned intXmtComplete:1; /*!< bits 0 Clear int on completion
+ of transmitted data */
+ unsigned intRcvComplete:1; /*!< bits 1 Clear int on completion
+ of received data */
+ unsigned intXmtErr:1; /*!< bits 2 Clear int on xmt error */
+ unsigned intRcvErr:1; /*!< bits 3 Clear int on rcv error */
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_int_stat
+ * @brief I2C Master Interrupt Status register
+ */
+struct ai2c_reg_i2c_mast_int_stat {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+ unsigned rcvErr:1; /*!< bits 3 Receive error */
+ unsigned xmtDone:1; /*!< bits 2 Transmit done */
+ unsigned rcvDataRdy:1; /*!< bits 1 Receive data ready */
+ unsigned xmtErr:1; /*!< bits 0 Transmit error */
+#else
+ unsigned xmtErr:1; /*!< bits 0 Transmit error */
+ unsigned rcvDataRdy:1; /*!< bits 1 Receive data ready */
+ unsigned xmtDone:1; /*!< bits 2 Transmit done */
+ unsigned rcvErr:1; /*!< bits 3 Receive error */
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_clk_cfg
+ * @brief I2C Master Clock Configuration register
+ */
+struct ai2c_reg_i2c_mast_clk_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+ unsigned pclkHighSCL:10; /*!< bits 25:16 # of pclk durations that
+ equal high period of SCL*/
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkLowSCL:10; /*!< bits 9:0 # of pclk durations that
+ equal low period of SCL */
+#else
+ unsigned pclkLowSCL:10; /*!< bits 9:0 # of pclk durations that
+ equal low period of SCL */
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkHighSCL:10; /*!< bits 25:16 # of pclk durations that
+ equal high period of SCL*/
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_start_hld_cfg
+ * @brief I2C Master Start Hold Timing Configuration register
+ */
+struct ai2c_reg_i2c_mast_start_hld_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+ unsigned pclkStart:10; /*!< bits 25:16 # of pclk durations that
+ equal start cond on SDA */
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA */
+#else
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA */
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkStart:10; /*!< bits 25:16 # of pclk durations that
+ equal start cond on SDA */
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_stop_hld_cfg
+ * @brief I2C Master Stop Hold Timing Configuration register
+ */
+struct ai2c_reg_i2c_mast_stop_hld_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+ unsigned pclkStop:10; /*!< bits 25:16 # of pclk durations that
+ equal stop cond on SDA */
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA */
+#else
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA */
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkStop:10; /*!< bits 25:16 # of pclk durations that
+ equal stop cond on SDA */
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_data_hld_cfg
+ * @brief I2C Master Data Hold Timing Configuration register
+ */
+struct ai2c_reg_i2c_mast_data_hld_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+ unsigned pclkStop:10; /*!< bits 25:16 # of pclk durations that
+ equal stop cond on SDA
+ for data changing */
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA
+ for data changing */
+#else
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA
+ for data changing */
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkStop:10; /*!< bits 25:16 # of pclk durations that
+ equal stop cond on SDA
+ for data changing */
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_bypass_mode
+ * @brief I2C Master Bypass Mode register
+ */
+struct ai2c_reg_i2c_mast_bypass_mode {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_3:29; /* bits 31:3 reserved */
+ unsigned enableBypass:1; /*!< bits 2 Enable bypass mode */
+ unsigned SCLvalue:1; /*!< bits 1 SCL value */
+ unsigned SDAvalue:1; /*!< bits 0 SDA value */
+#else
+ unsigned SDAvalue:1; /*!< bits 0 SDA value */
+ unsigned SCLvalue:1; /*!< bits 1 SCL value */
+ unsigned enableBypass:1; /*!< bits 2 Enable bypass mode */
+ unsigned reserved_31_3:29; /* bits 31:3 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_slv_address
+ * @brief I2C Master Slave Address register
+ */
+struct ai2c_reg_i2c_mast_slv_address {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_16:16; /* bits 31:16 reserved */
+ unsigned targSlvAddr:16; /*!< bits 16:0 Address of the slave
+ device being addressed */
+#else
+ unsigned targSlvAddr:16; /*!< bits 16:0 Address of the slave
+ device being addressed */
+ unsigned reserved_31_16:16; /* bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_txd0
+ * @brief I2C Master Transmit Data 0 register
+ */
+struct ai2c_reg_i2c_mast_txd0 {
+#ifdef AI2C_BIG_ENDIAN
+ unsigned data:32; /*!< bits 31:0 Data to be transmitted */
+#else
+ unsigned data:32; /*!< bits 31:0 Data to be transmitted */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_mast_rxd0_t
+ * @brief I2C Master Receive Data 0 register
+ */
+struct ai2c_reg_i2c_mast_rxd0 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned data:32; /*!< bits 31:0 Data received */
+#else
+ unsigned data:32; /*!< bits 31:0 Data received */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_txrxconfig
+ * @brief I2C Slave Transmit/Receive Config register
+ */
+struct ai2c_reg_i2c_slv_txrxconfig {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_11:21; /* bits 31:11 reserved */
+ unsigned zeroAll:1; /*!< bits 10 Zero all control/data */
+ unsigned rcvEndianness:1; /*!< bits 9 0=BE (def), 1=LE */
+ unsigned slvModeActive:1; /*!< bits 8 Slave mode active */
+ unsigned tenBitAddr:1; /*!< bits 7 10-bit address mode */
+ unsigned xmtEndianness:1; /*!< bits 6 0=BE (def), 1=LE */
+ unsigned numBytes:5; /*!< bits 5:1 number of bytes to xmit*/
+ unsigned xmtReady:1; /*!< bits 0 Transmit Ready */
+#else
+ unsigned xmtReady:1; /*!< bits 0 Transmit Ready */
+ unsigned numBytes:5; /*!< bits 5:1 number of bytes to xmit*/
+ unsigned xmtEndianness:1; /*!< bits 6 0=BE (def), 1=LE */
+ unsigned tenBitAddr:1; /*!< bits 7 10-bit address mode */
+ unsigned slvModeActive:1; /*!< bits 8 Slave mode active */
+ unsigned rcvEndianness:1; /*!< bits 9 0=BE (def), 1=LE */
+ unsigned zeroAll:1; /*!< bits 10 Zero all control/data */
+ unsigned reserved_31_11:21; /* bits 31:11 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_stat
+ * @brief I2C Slave Status register
+ */
+struct ai2c_reg_i2c_slv_stat {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_10:23; /* bits 31:10 reserved */
+ unsigned numBytesRcv:4; /*!< bits 9:5 # bytes rcved on slave
+ transaction */
+ unsigned slvXmtErr:1; /*!< bits 4 Slave xmit in error */
+ unsigned slvXmtDone:1; /*!< bits 3 Slave done xmit data */
+ unsigned rcvErr:1; /*!< bits 2 Rcv data in error */
+ unsigned cmdRcv:1; /*!< bits 1 Command received by slv*/
+ unsigned slvRcvRdy:1; /*!< bits 0 Slv rcved data ready */
+#else
+ unsigned slvRcvRdy:1; /*!< bits 0 Slv rcved data ready */
+ unsigned cmdRcv:1; /*!< bits 1 Command received by slv*/
+ unsigned rcvErr:1; /*!< bits 2 Rcv data in error */
+ unsigned slvXmtDone:1; /*!< bits 3 Slave done xmit data */
+ unsigned slvXmtErr:1; /*!< bits 4 Slave xmit in error */
+ unsigned numBytesRcv:4; /*!< bits 9:5 # bytes rcved on slave
+ transaction */
+ unsigned reserved_31_10:23; /* bits 31:10 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_self_address
+ * @brief I2C Slave Self Address register
+ */
+struct ai2c_reg_i2c_slv_self_address {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned address:32; /*!< bits 31:0 address of APPI2C */
+#else
+ unsigned address:32; /*!< bits 31:0 address of APPI2C */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_txd0
+ * @brief I2C Slave Transmit Data 0 register
+ */
+struct ai2c_reg_i2c_slv_txd0 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned data:32; /*!< bits 31:0 Data to be transmitted */
+#else
+ unsigned data:32; /*!< bits 31:0 Data to be transmitted */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_rxd0
+ * @brief I2C Slave Receive Data 0 register
+ */
+struct ai2c_reg_i2c_slv_rxd0 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned data:32; /*!< bits 31:0 Data received */
+#else
+ unsigned data:32; /*!< bits 31:0 Data received */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_int_enable
+ * @brief I2C Slave Interrupt Enable register
+ */
+struct ai2c_reg_i2c_slv_int_enable {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+ unsigned intRcvErr:1; /*!< bits 3 Enable int on rcv error */
+ unsigned intRcvDataRdy:1; /*!< bits 2 Enable int on rcv ready */
+ unsigned intXmtErr:1; /*!< bits 1 Enable int on xmt error */
+ unsigned intXmtComplete:1; /*!< bits 0 Enable int on completion
+ of transmitted data */
+#else
+ unsigned intXmtComplete:1; /*!< bits 0 Enable int on completion
+ of transmitted data */
+ unsigned intXmtErr:1; /*!< bits 1 Enable int on xmt error */
+ unsigned intRcvDataRdy:1; /*!< bits 2 Enable int on rcv ready */
+ unsigned intRcvErr:1; /*!< bits 3 Enable int on rcv error */
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_int_clear
+ * @brief I2C Slave Interrupt Clear register
+ */
+struct ai2c_reg_i2c_slv_int_clear {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+ unsigned intRcvErr:1; /*!< bits 3 Clear int on rcv error */
+ unsigned intRcvDataRdy:1; /*!< bits 2 Clear int on rcv ready */
+ unsigned intXmtErr:1; /*!< bits 1 Clear int on xmt error */
+ unsigned intXmtComplete:1; /*!< bits 0 Clear int on completion
+ of transmitted data */
+#else
+ unsigned intXmtComplete:1; /*!< bits 0 Clear int on completion
+ of transmitted data */
+ unsigned intXmtErr:1; /*!< bits 1 Clear int on xmt error */
+ unsigned intRcvDataRdy:1; /*!< bits 2 Clear int on rcv ready */
+ unsigned intRcvErr:1; /*!< bits 3 Clear int on rcv error */
+ unsigned reserved_31_4:28; /* bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_data_hld_cfg
+ * @brief I2C Slave Data Hold Timing Config register
+ */
+struct ai2c_reg_i2c_slv_data_hld_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+ unsigned pclkHold:10; /*!< bits 25:16 # of pclk durations that
+ equal hold cond on SDA */
+ unsigned reserved_15_10:6; /*!< bits 15:10 reserved */
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA */
+#else
+ unsigned pclkSetup:10; /*!< bits 9:0 # of pclk durations that
+ equal setup cond on SDA */
+ unsigned reserved_15_10:6; /*!< bits 15:10 reserved */
+ unsigned pclkHold:10; /*!< bits 25:16 # of pclk durations that
+ equal hold cond on SDA */
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_clk_cfg
+ * @brief I2C Slave Clock Config register
+ */
+struct ai2c_reg_i2c_slv_clk_cfg {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+ unsigned pclkLowSCL:10; /*!< bits 25:16 # of pclk durations that
+ equal low period of SCL*/
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkHighSCL:10; /*!< bits 9:0 # of pclk durations that
+ equal high period of SCL*/
+#else
+ unsigned pclkHighSCL:10; /*!< bits 9:0 # of pclk durations that
+ equal high period of SCL*/
+ unsigned reserved_15_10:6; /* bits 15:10 reserved */
+ unsigned pclkLowSCL:10; /*!< bits 25:16 # of pclk durations that
+ equal low period of SCL*/
+ unsigned reserved_31_26:6; /* bits 31:26 reserved */
+#endif
+};
+
+
+/******************************************************************************
+ * Register handle offsets (X7 aka AXM55xx) *
+ * *
+ * Regions:0x143.0, 0x14c.0, 0x152.0 *
+ * *
+ * Regerence: AMBA (tm) Peripheral I2c Bus Controller with SMB Functions *
+ * (API2C) Reference Manual, Version 0.1, April 2011, *
+ * DB13-00329-00. *
+ ******************************************************************************/
+
+#define AI2C_REG_I2C_X7_GLOBAL_CONTROL (0x0000) /*!< Offset to reg
+ Global Control */
+#define AI2C_REG_I2C_X7_INTERRUPT_STATUS (0x0004) /*!< Offset to reg
+ Interrupt Status */
+#define AI2C_REG_I2C_X7_INTERRUPT_ENABLE (0x0008) /*!< Offset to reg
+ Interrupt Enable */
+#define AI2C_REG_I2C_X7_WAIT_TIMER_CONTROL (0x000C) /*!< Offset to reg
+ Wait Timer Control */
+#define AI2C_REG_I2C_X7_IBML_TIMEOUT (0x0010) /*!< Offset to reg
+ IBML Timeout */
+#define AI2C_REG_I2C_X7_IBML_LOW_MEXT (0x0014) /*!< Offset to reg
+ IBML Low MEXT */
+#define AI2C_REG_I2C_X7_IBML_LOW_SEXT (0x0018) /*!< Offset to reg
+ IBML Low SEXT */
+#define AI2C_REG_I2C_X7_TIMER_CLOCK_DIV (0x001C) /*!< Offset to reg
+ Timer Clock Division */
+#define AI2C_REG_I2C_X7_I2C_BUS_MONITOR (0x0020) /*!< Offset to reg I2C
+ Bus Monitor */
+#define AI2C_REG_I2C_X7_SOFT_RESET (0x0024) /*!< Offset to reg Soft
+ Reset */
+#define AI2C_REG_I2C_X7_MST_COMMAND (0x0028) /*!< Offset to reg
+ Master Command */
+#define AI2C_REG_I2C_X7_MST_RX_XFER (0x002C) /*!< Offset to reg
+ Master Receive
+ Transfer */
+#define AI2C_REG_I2C_X7_MST_TX_XFER (0x0030) /*!< Offset to reg
+ Master Transmit
+ Transfer */
+#define AI2C_REG_I2C_X7_MST_ADDR_1 (0x0034) /*!< Offset to reg
+ Master Address 1 */
+#define AI2C_REG_I2C_X7_MST_ADDR_2 (0x0038) /*!< Offset to reg
+ Master Address 2 */
+#define AI2C_REG_I2C_X7_MST_DATA (0x003C) /*!< Offset to reg
+ Master Data */
+#define AI2C_REG_I2C_X7_MST_TX_FIFO (0x0040) /*!< Offset to reg
+ Master Transmit FIFO */
+#define AI2C_REG_I2C_X7_MST_RX_FIFO (0x0044) /*!< Offset to reg
+ Master Receive FIFO */
+#define AI2C_REG_I2C_X7_MST_INT_ENABLE (0x0048) /*!< Offset to reg
+ Master Interrupt
+ Enable */
+#define AI2C_REG_I2C_X7_MST_INT_STATUS (0x004C) /*!< Offset to reg
+ Master Interrupt
+ Status */
+#define AI2C_REG_I2C_X7_MST_TX_BYTES_XFRD (0x0050) /*!< Offset to reg
+ Master TX Bytes
+ Transferred */
+#define AI2C_REG_I2C_X7_MST_RX_BYTES_XFRD (0x0054) /*!< Offset to reg
+ Master RX Bytes
+ Transferred */
+#define AI2C_REG_I2C_X7_SLV_ADDR_DEC_CTL (0x0058) /*!< Offset to reg
+ Slave Address
+ Decrement Ctl */
+#define AI2C_REG_I2C_X7_SLV_ADDR_1 (0x005C) /*!< Offset to reg
+ Slave Address 1 */
+#define AI2C_REG_I2C_X7_SLV_ADDR_2 (0x0060) /*!< Offset to reg
+ Slave Address 2 */
+#define AI2C_REG_I2C_X7_SLV_RX_CTL (0x0064) /*!< Offset to reg
+ Slave Receive Control */
+#define AI2C_REG_I2C_X7_SLV_DATA (0x0068) /*!< Offset to reg
+ Slave Data */
+#define AI2C_REG_I2C_X7_SLV_RX_FIFO (0x006C) /*!< Offset to reg
+ Slave Receive FIFO */
+#define AI2C_REG_I2C_X7_SLV_INT_ENABLE (0x0070) /*!< Offset to reg
+ Slave Interrupt
+ Enable */
+#define AI2C_REG_I2C_X7_SLV_INT_STATUS (0x0074) /*!< Offset to reg
+ Slave Interrupt
+ Status */
+#define AI2C_REG_I2C_X7_SLV_READ_DUMMY (0x0078) /*!< Offset to reg
+ Slave Read Dummy */
+#define AI2C_REG_I2C_X7_SCL_HIGH_PERIOD (0x0080) /*!< Offset to reg
+ SCL High Period */
+#define AI2C_REG_I2C_X7_SCL_LOW_PERIOD (0x0084) /*!< Offset to reg
+ SCL Low Period */
+#define AI2C_REG_I2C_X7_SPIKE_FLTR_LEN (0x0088) /*!< Offset to reg
+ Spike Filter Length */
+#define AI2C_REG_I2C_X7_SDA_SETUP_TIME (0x008C) /*!< Offset to reg
+ SDA Setup Time */
+#define AI2C_REG_I2C_X7_SDA_HOLD_TIME (0x0090) /*!< Offset to reg
+ SDA Hold Time */
+#define AI2C_REG_I2C_X7_SMB_ALERT (0x0094) /*!< Offset to reg
+ SMB Alert */
+#define AI2C_REG_I2C_X7_UDID_W7 (0x0098) /*!< Offset to reg
+ UDID W7 */
+#define AI2C_REG_I2C_X7_UDID_W7_DEFAULT (0x00000008) /*!< Def value reg
+ UDID W7 */
+#define AI2C_REG_I2C_X7_UDID_W6 (0x009C) /*!< Offset to reg
+ UDID W6 */
+#define AI2C_REG_I2C_X7_UDID_W5 (0x00A0) /*!< Offset to reg
+ UDID W5 */
+#define AI2C_REG_I2C_X7_UDID_W4 (0x00A4) /*!< Offset to reg
+ UDID W4 */
+#define AI2C_REG_I2C_X7_UDID_W4_DEFAULT (0x00000004) /*!< Def value reg
+ UDID W4 */
+#define AI2C_REG_I2C_X7_UDID_W3 (0x00A8) /*!< Offset to reg
+ UDID W3 */
+#define AI2C_REG_I2C_X7_UDID_W2 (0x00AC) /*!< Offset to reg
+ UDID W2 */
+#define AI2C_REG_I2C_X7_UDID_W1 (0x00B0) /*!< Offset to reg
+ UDID W1 */
+#define AI2C_REG_I2C_X7_UDID_W0 (0x00B4) /*!< Offset to reg
+ UDID W0 */
+#define AI2C_REG_I2C_X7_ARPPEC_CFG_STAT (0x00B8) /*!< Offset to reg
+ ARPPEC Cfg Status */
+#define AI2C_REG_I2C_X7_SLV_ARP_INT_ENABLE (0x00BC) /*!< Offset to reg
+ Slave ARP Interrupt
+ Enable */
+#define AI2C_REG_I2C_X7_SLV_ARP_INT_STATUS (0x00C0) /*!< Offset to reg
+ Slave ARP Interrupt
+ Status */
+#define AI2C_REG_I2C_X7_MST_ARP_INT_ENABLE (0x00C4) /*!< Offset to reg
+ Master ARP Interrupt
+ Enable */
+#define AI2C_REG_I2C_X7_MST_ARP_INT_STATUS (0x00C8) /*!< Offset to reg
+ Master ARP Interrupt
+ Status */
+/*
+** Unused 0x00CC - 0x00FC
+*/
+
+
+/**********************************
+ * Register Structure definitions *
+ *********************************/
+
+/*! @struct ai2c_reg_i2c_x7_global_control
+ * @brief I2C Global Control register (X7)
+ */
+struct ai2c_reg_i2c_x7_global_control {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:29; /*!< bits 31:3 reserved */
+ unsigned IE:1; /*!< bits 2 enable/disable IBML timers:
+ 0=disable (def), 1=enable */
+ unsigned SE:1; /*!< bits 1 enable/disable SSM address
+ decode:0=disable, 1=enable */
+ unsigned ME:1; /*!< bits 0 enable/disable MSM:
+ 0=disable, 1=enable */
+#else
+ unsigned ME:1; /*!< bits 0 enable/disable MSM:
+ 0=disable, 1=enable */
+ unsigned SE:1; /*!< bits 1 enable/disable SSM address
+ decode:0=disable, 1=enable */
+ unsigned IE:1; /*!< bits 2 enable/disable IBML timers:
+ =disable (def), 1=enable */
+ unsigned:29; /* bits 31:3 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_interrupt_status
+ * @brief I2C Interrupt Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_interrupt_status {
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:28; /*!< bits 31:4 reserved */
+ unsigned mai:1; /*!< bits 3 OR of all master ARP
+ interrupt sources */
+ unsigned sai:1; /*!< bits 2 OR of all slave ARP
+ interrupt sources */
+ unsigned si:1; /*!< bits 1 slave interrupt source(s) OR */
+ unsigned mi:1; /*!< bits 0 master interrupt source(s) OR */
+#else
+ unsigned mi:1; /*!< bits 0 master interrupt source(s) OR */
+ unsigned si:1; /*!< bits 1 slave interrupt source(s) OR */
+ unsigned sai:1; /*!< bits 2 OR of all slave ARP
+ interrupt sources */
+ unsigned mai:1; /*!< bits 3 OR of all master ARP
+ interrupt sources */
+ unsigned:28; /*!< bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_interrupt_enable
+ * @brief I2C Interrupt Enable register (X7)
+ */
+struct ai2c_reg_i2c_x7_interrupt_enable {
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:28; /*!< bits 31:4 reserved */
+ unsigned maie:1; /*!< bits 3 enable of all master ARP
+ interrupt sources */
+ unsigned saie:1; /*!< bits 2 enable of all slave ARP
+ interrupt sources */
+ unsigned sie:1; /*!< bits 1 enable of slave interrupt
+ source(s) */
+ unsigned mie:1; /*!< bits 0 enable of master interrupt
+ source(s) */
+#else
+ unsigned mie:1; /*!< bits 0 enable of master interrupt
+ source(s) */
+ unsigned sie:1; /*!< bits 1 enable of slave interrupt
+ source(s) */
+ unsigned saie:1; /*!< bits 2 enable of all slave ARP
+ interrupt sources */
+ unsigned maie:1; /*!< bits 3 enable of all master ARP
+ interrupt sources */
+ unsigned:28; /*!< bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_wait_timer_control
+ * @brief I2C Master XMIT Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_wait_timer_control {
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned te:1; /*!< bits 15 enable master/slave wait timer */
+ unsigned tlv:15; /*!< bits 14:0 timer load value to extend the
+ SCL low timer */
+#else
+ unsigned tlv:15; /*!< bits 14:0 timer load value to extend the
+ SCL low timer */
+ unsigned te:1; /*!< bits 15 enable master/slave wait timer */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_ibml_timeout
+ * @brief I2C Master RCV Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_ibml_timeout {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned te:1; /*!< bits 15 enable/disable IBML Timeout */
+ unsigned itlv:15; /*!< bits 14:0 timer load value to extend
+ the SCL low timer after high */
+#else
+ unsigned itlv:15; /*!< bits 14:0 timer load value to extend
+ the SCL low timer after high */
+ unsigned te:1; /*!< bits 15 enable/disable IBML Timeout */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_ibml_low_mext
+ * @brief I2C IBML Low MEXT register (X7)
+ */
+struct ai2c_reg_i2c_x7_ibml_low_mext {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned te:1; /*!< bits 15 enable/disable IBML
+ Low MEXT flag*/
+ unsigned imtlv:15; /*!< bits 14:0 timer load value at
+ begin of every master data byte transfer */
+#else
+ unsigned imtlv:15; /*!< bits 14:0 timer load value at begin
+ of every master data byte transfer */
+ unsigned te:1; /*!< bits 15 enable master/slave wait timer */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_low_sext
+ * @brief I2C Master Interrupt Clear register (X7)
+ */
+struct ai2c_reg_i2c_x7_low_sext {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned te:1; /*!< bits 15 enable/disable IBML
+ Low MEXT flag*/
+ unsigned istlv:15; /*!< bits 14:0 timer load value at
+ begin of every slave data byte transfer */
+#else
+ unsigned istlv:15; /*!< bits 14:0 timer load value at begin
+ of every slave data byte transfer */
+ unsigned te:1; /*!< bits 15 enable master/slave wait timer */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_i2c_bus_monitor
+ * @brief I2C Master Interrupt Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_i2c_bus_monitor {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:26; /*!< bits 31:6 reserved */
+ unsigned sdae:1; /*!< bits 5 At least 1 high-to-low
+ transition occurred on SDA status line */
+ unsigned scle:1; /*!< bits 4 At least 1 high-to-low
+ transition occurred on SCL status line */
+ unsigned sdac:1; /*!< bits 3 Controls SDA signal */
+ unsigned sclc:1; /*!< bits 2 Controls SCL signal */
+ unsigned sdas:1; /*!< bits 1 Current value of SDA signal
+ on I2C bus */
+ unsigned scls:1; /*!< bits 0 Current value of SCL signal
+ on I2C bus */
+#else
+ unsigned scls:1; /*!< bits 0 Current value of SCL signal
+ on I2C bus */
+ unsigned sdas:1; /*!< bits 1 Current value of SDA signal
+ on I2C bus */
+ unsigned sclc:1; /*!< bits 2 Controls SCL signal */
+ unsigned sdac:1; /*!< bits 3 Controls SDA signal */
+ unsigned scle:1; /*!< bits 4 At least 1 high-to-low
+ transition occurred on SCL status line */
+ unsigned sdae:1; /*!< bits 5 At least 1 high-to-low
+ transition occurred on SDA status line */
+ unsigned:26; /*!< bits 31:6 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_soft_reset
+ * @brief I2C Soft Reset register (X7)
+ */
+struct ai2c_reg_i2c_x7_soft_reset {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:31; /*!< bits 31:1 reserved */
+ unsigned i2cr:1; /*!< bits 0 Reset the entire API2C module
+ when set to 1 */
+#else
+ unsigned i2cr:1; /*!< bits 0 Reset the entire API2C module
+ when set to 1 */
+ unsigned:31; /*!< bits 31:1 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_command
+ * @brief I2C Master Command register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_command {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:28; /*!< bits 31:4 reserved */
+ unsigned sc:1; /*!< bits 3 Issue command when set to 1 */
+ unsigned cmdtype:3; /*!< bits 2:0 Command type:
+ 000: Manual Mode Transfer
+ 001: Automatic Mode Transfer
+ 010: Sequence Mode Transfer
+ 011: Issue master Stop
+ 111: Flush Master Transmit FIFO */
+#else
+ unsigned cmdtype:3; /*!< bits 2:0 Command type:
+ 000: Manual Mode Transfer
+ 001: Automatic Mode Transfer
+ 010: Sequence Mode Transfer
+ 011: Issue master Stop
+ 111: Flush Master Transmit FIFO */
+ unsigned sc:1; /*!< bits 3 Issue command when set to 1 */
+ unsigned:28; /*!< bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_rx_xfer
+ * @brief I2C Master Receive Transfer Length register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_rx_xfer {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned length:8; /*!< bits 7:0 Number of bytes master receives
+ during read xfer */
+#else
+ unsigned length:8; /*!< bits 7:0 Number of bytes master receives
+ during read xfer */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_tx_xfer
+ * @brief I2C Master Transmit Transfer Length register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_tx_xfer {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned length:8; /*!< bits 7:0 Number of bytes master sends
+ during write xfer */
+#else
+ unsigned length:8; /*!< bits 7:0 Number of bytes master sends
+ during write xfer */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_addr_1
+ * @brief I2C Master Address 1 register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_addr_1 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned i2ca1:7; /*!< bits 7:1 First 7 bits of the address phase
+ of transaction. If bits [7:3] = 11110, then
+ 10-bit addressing is selected, and bits [2:1]
+ become the two most significant bits of a
+ 10-bit address. */
+ unsigned ad:1; /*!< bits 0 Data direction:0=write, 1=read */
+#else
+ unsigned ad:1; /*!< bits 0 Data direction:0=write, 1=read */
+ unsigned i2ca1:7; /*!< bits 7:1 First 7 bits of the address phase
+ of transaction. If bits [7:3] = 11110, then
+ 10-bit addressing is selected, and bits [2:1]
+ become the two most significant bits of a
+ 10-bit address. */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_addr_2
+ * @brief I2C Master Address 2 register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_addr_2 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned i2ca2:8; /*!< bits 7:0 I2C Address bits of a 10-bit
+ I2C address when
+ selected. If 10-bit addressing is enabled, this
+ field is sent as the second byte in the address
+ phase of an I2C transaction. */
+#else
+ unsigned i2ca2:8; /*!< bits 7:0 I2C Address bits of a 10-bit
+ I2C address when selected.
+ If 10-bit addressing is enabled, this
+ field is sent as the second byte in the address
+ phase of an I2C transaction. */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_data
+ * @brief I2C Master Data register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_data {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned data:8; /*!< bits 7:0 Each byte written goes to the
+ Master Transmit FIFO.
+ Each byte read returned from the
+ Master Transmit FIFO. */
+#else
+ unsigned data:8; /*!< bits 7:0 Each byte written goes to the
+ Master Transmit FIFO.
+ Each byte read returned from the
+ Master Transmit FIFO. */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_tx_fifo
+ * @brief I2C Master Transmit FIFO Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_tx_fifo {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:28; /*!< bits 31:4 reserved */
+ unsigned depth:4; /*!< bits 3:0 Number of bytes in
+ master Transmit FIFO */
+#else
+ unsigned depth:4; /*!< bits 3:0 Number of bytes in
+ master Transmit FIFO */
+ unsigned:28; /*!< bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_rx_fifo
+ * @brief I2C Master Receive FIFO Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_rx_fifo {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:28; /*!< bits 31:4 reserved */
+ unsigned depth:4; /*!< bits 3:0 Number of bytes in master
+ Receive FIFO */
+#else
+ unsigned depth:4; /*!< bits 3:0 Number of bytes in master
+ Receive FIFO */
+ unsigned:28; /*!< bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_int_enable
+ * @brief I2C Master Interrupt Enable register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_int_enable {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned mie:12; /*!< bits 15:4 Bits to enable individual
+ interrupt resources */
+ unsigned:4; /*!< bits 3:0 reserved */
+#else
+ unsigned:4; /*!< bits 3:0 reserved */
+ unsigned mie:12; /*!< bits 15:4 Bits to enable individual
+ interrupt resources */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_int_status
+ * @brief I2C Master Interrupt Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_int_status {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned itt:1; /*!< bits 15 */
+ unsigned itlm:1; /*!< bits 14 */
+ unsigned rfl:1; /*!< bits 13 */
+ unsigned tfl:1; /*!< bits 12 */
+ unsigned sns:1; /*!< bits 11 */
+ unsigned ss:1; /*!< bits 10 */
+ unsigned scc:1; /*!< bits 9 */
+ unsigned ip:1; /*!< bits 8 */
+ unsigned tss:1; /*!< bits 7 */
+ unsigned al:1; /*!< bits 6 */
+ unsigned nd:1; /*!< bits 5 */
+ unsigned na:1; /*!< bits 4 */
+ unsigned ts:1; /*!< bits 3 */
+ unsigned stp:1; /*!< bits 2 */
+ unsigned ttp:1; /*!< bits 1 */
+ unsigned rtp:1; /*!< bits 0 */
+#else
+ unsigned rtp:1; /*!< bits 0 */
+ unsigned ttp:1; /*!< bits 1 */
+ unsigned stp:1; /*!< bits 2 */
+ unsigned ts:1; /*!< bits 3 */
+ unsigned na:1; /*!< bits 4 */
+ unsigned nd:1; /*!< bits 5 */
+ unsigned al:1; /*!< bits 6 */
+ unsigned tss:1; /*!< bits 7 */
+ unsigned ip:1; /*!< bits 8 */
+ unsigned scc:1; /*!< bits 9 */
+ unsigned ss:1; /*!< bits 10 */
+ unsigned sns:1; /*!< bits 11 */
+ unsigned tfl:1; /*!< bits 12 */
+ unsigned rfl:1; /*!< bits 13 */
+ unsigned itlm:1; /*!< bits 14 */
+ unsigned itt:1; /*!< bits 15 */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_tx_bytes_xfrd
+ * @brief I2C Master Transmit Bytes Transferred register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_tx_bytes_xfrd {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned num:8; /*!< bits 7:0 Number of bytes
+ transferred successfully */
+#else
+ unsigned num:8; /*!< bits 7:0 Number of bytes
+ transferred successfully */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_rx_bytes_xfrd
+ * @brief I2C Master Receive Bytes Transferred register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_rx_bytes_xfrd {
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned num:8; /*!< bits 7:0 Number of bytes
+ received successfully */
+#else
+ unsigned num:8; /*!< bits 7:0 Number of bytes
+ received successfully */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_addr_dec_ctl
+ * @brief I2C Master Transmit Transfer Length register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_addr_dec_ctl {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:26; /*!< bits 31:6 reserved */
+ unsigned sa2m:8; /*!< bits 5 7-bit or 10-bit slave addressing
+ for Slave Addr Decoder 2 */
+ unsigned sa2e:8; /*!< bits 4 Slave State machine to ACK during
+ addr phase of trans for Slave Addr 2 */
+ unsigned sa1m:8; /*!< bits 3 7-bit or 10-bit slave addressing
+ for Slave Addr Decoder 1 */
+ unsigned sa1e:8; /*!< bits 2 Slave State machine to ACK during
+ addr phase of trans for Slave Addr 1 */
+ unsigned ogce:8; /*!< bits 1 Slave State machine to ACK to
+ General Call Address from its master */
+ unsigned gce:8; /*!< bits 0 Slave State machine to ACK to
+ General Call Address from other masters */
+#else
+ unsigned gce:8; /*!< bits 0 Slave State machine to ACK to
+ General Call Address from other masters */
+ unsigned ogce:8; /*!< bits 1 Slave State machine to ACK to
+ General Call Address from its master */
+ unsigned sa1e:8; /*!< bits 2 Slave State machine to ACK during
+ addr phase of trans for Slave Addr 1 */
+ unsigned sa1m:8; /*!< bits 3 7-bit or 10-bit slave addressing
+ for Slave Addr Decoder 1 */
+ unsigned sa2e:8; /*!< bits 4 Slave State machine to ACK during
+ addr phase of trans for Slave Addr 2 */
+ unsigned sa2m:8; /*!< bits 5 7-bit or 10-bit slave addressing
+ for Slave Addr Decoder 2 */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_addr_1
+ * @brief I2C Slave Address 1 register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_addr_1 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:22; /*!< bits 31:10 reserved */
+ unsigned sa1:10; /*!< bits 9:0 7-bit or 10-bit address */
+#else
+ unsigned sa1:10; /*!< bits 9:0 7-bit or 10-bit address */
+ unsigned:22; /*!< bits 31:10 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_addr_2
+ * @brief I2C Slave Address 2 register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_addr_2 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:22; /*!< bits 31:10 reserved */
+ unsigned sa2:10; /*!< bits 9:0 7-bit or 10-bit address */
+#else
+ unsigned sa2:10; /*!< bits 9:0 7-bit or 10-bit address */
+ unsigned:22; /*!< bits 31:10 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_rx_ctl
+ * @brief I2C Slave Receive Control register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_rx_ctl {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:29; /*!< bits 31:3 reserved */
+ unsigned acgca:1; /*!< bits 2 ACK data (write) phase to GCA */
+ unsigned acsa2:1; /*!< bits 1 ACK for data (write) phase
+ to Slave Addr 2 */
+ unsigned acsa1:1; /*!< bits 0 ACK for data (write) phase
+ to Slave Addr 1 */
+#else
+ unsigned acsa1:1; /*!< bits 0 ACK for data (write) phase
+ to Slave Addr 1 */
+ unsigned acsa2:1; /*!< bits 1 ACK for data (write) phase
+ to Slave Addr 2 */
+ unsigned acgca:1; /*!< bits 2 ACK data (write) phase
+ to GCA */
+ unsigned:29; /*!< bits 31:3 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_data
+ * @brief I2C Slave Data register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_data {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:23; /*!< bits 31:9 reserved */
+ unsigned pec:1; /*!< bits 8 Set to subst PEC data
+ for transmission */
+ unsigned strd:8; /*!< bits 7:0 Read data from top
+ of Receive FIFO
+ Write places transmit data into Slave Read
+ Data Register. */
+#else
+ unsigned strd:8; /*!< bits 7:0 Read data from top
+ of Receive FIFO
+ Write places transmit data into Slave Read
+ Data Register. */
+ unsigned pec:1; /*!< bits 8 Set to subst PEC data
+ for transmission */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_slv_rx_fifo
+ * @brief I2C Slave Receive FIFO Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_rx_fifo {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:24; /*!< bits 31:8 reserved */
+ unsigned pec:1; /*!< bits 7 PEC good or not */
+ unsigned stpc:1; /*!< bits 6 Data transfer termined due to
+ stop condition */
+ unsigned rsc:1; /*!< bits 4 Received byte was first after
+ repeated start */
+ unsigned strc:1; /*!< bits 4 This is first data byte for a
+ slave addr after start */
+ unsigned tnak:1; /*!< bits 3 NAK sent due to timeout */
+ unsigned as:1; /*!< bits 2 Data byte valid (0=ACK, 1=NAK) */
+ unsigned dv:2; /*!< bits 1:0 Data in FIFO is valid and for
+ which slave
+ * 00: empty
+ * 01: Valid for slave addr 1
+ * 10: Valid for slave addr 2
+ * 11: General call address
+ data valid */
+#else
+ unsigned dv:2; /*!< bits 1:0 Data in FIFO is valid and for
+ which slave
+ * 00: empty
+ * 01: Valid for slave addr 1
+ * 10: Valid for slave addr 2
+ * 11: General call address
+ data valid */
+ unsigned as:1; /*!< bits 2 Data byte valid (0=ACK, 1=NAK) */
+ unsigned tnak:1; /*!< bits 3 NAK sent due to timeout */
+ unsigned strc:1; /*!< bits 4 This is first data byte for a
+ slave addr after start */
+ unsigned rsc:1; /*!< bits 4 Received byte was first after
+ repeated start */
+ unsigned stpc:1; /*!< bits 6 Data transfer termined due to
+ stop condition */
+ unsigned pec:1; /*!< bits 7 PEC good or not */
+ unsigned:24; /*!< bits 31:8 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_int_enable
+ * @brief I2C Slave Interrupt Enable register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_int_enable {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned sie2:8; /*!< bits 15:10 Bit enable individual sources in
+ corresponding status reg */
+ unsigned:1; /*!< bits 9 reserved */
+ unsigned sie1:5; /*!< bits 8:4 Bit enable individual sources in
+ corresponding status reg */
+ unsigned:1; /*!< bits 3 reserved */
+ unsigned sie0:3; /*!< bits 2:0 Bit enable individual sources in
+ corresponding status reg */
+#else
+ unsigned sie0:3; /*!< bits 2:0 Bit enable individual sources in
+ corresponding status reg */
+ unsigned:1; /*!< bits 3 reserved */
+ unsigned sie1:5; /*!< bits 8:4 Bit enable individual sources in
+ corresponding status reg */
+ unsigned:1; /*!< bits 9 reserved */
+ unsigned sie2:8; /*!< bits 15:10 Bit enable individual sources in
+ corresponding status reg */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_int_status
+ * @brief I2C Slave Interrupt Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_int_status {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned it:1; /*!< bits 15 See spec for details */
+ unsigned itls:1; /*!< bits 14 See spec for details */
+ unsigned srdre2:1; /*!< bits 13 See spec for details */
+ unsigned srat2:1; /*!< bits 12 See spec for details */
+ unsigned src2:1; /*!< bits 11 See spec for details */
+ unsigned srnd2:1; /*!< bits 10 See spec for details */
+ unsigned srrs2:1; /*!< bits 9 See spec for details */
+ unsigned srs2:1; /*!< bits 8 See spec for details */
+ unsigned srdre1:1; /*!< bits 7 See spec for details */
+ unsigned srat1:1; /*!< bits 6 See spec for details */
+ unsigned src1:1; /*!< bits 5 See spec for details */
+ unsigned srnd1:1; /*!< bits 4 See spec for details */
+ unsigned srrs1:1; /*!< bits 3 See spec for details */
+ unsigned srs1:1; /*!< bits 2 See spec for details */
+ unsigned wtc:1; /*!< bits 1 See spec for details */
+ unsigned rfh:1; /*!< bits 0 See spec for details */
+#else
+ unsigned rfh:1; /*!< bits 0 See spec for details */
+ unsigned wtc:1; /*!< bits 1 See spec for details */
+ unsigned srs1:1; /*!< bits 2 See spec for details */
+ unsigned srrs1:1; /*!< bits 3 See spec for details */
+ unsigned srnd1:1; /*!< bits 4 See spec for details */
+ unsigned src1:1; /*!< bits 5 See spec for details */
+ unsigned srat1:1; /*!< bits 6 See spec for details */
+ unsigned srdre1:1; /*!< bits 7 See spec for details */
+ unsigned srs2:1; /*!< bits 8 See spec for details */
+ unsigned srrs2:1; /*!< bits 9 See spec for details */
+ unsigned srnd2:1; /*!< bits 10 See spec for details */
+ unsigned src2:1; /*!< bits 11 See spec for details */
+ unsigned srat2:1; /*!< bits 12 See spec for details */
+ unsigned srdre2:1; /*!< bits 13 See spec for details */
+ unsigned itls:1; /*!< bits 14 See spec for details */
+ unsigned it:1; /*!< bits 15 See spec for details */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_read_dummy
+ * @brief I2C Slave Read Dummy register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_read_dummy {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:23; /*!< bits 31:9 reserved */
+ unsigned srte:1; /*!< bits 8 Disable/Enable slave read time-out */
+ unsigned dd:8; /*!< bits 7:0 Incoming slave read data */
+#else
+ unsigned dd:8; /*!< bits 7:0 Incoming slave read data */
+ unsigned srte:1; /*!< bits 8 Disable/Enable slave read time-out */
+ unsigned:23; /*!< bits 31:9 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_scl_high_period
+ * @brief I2C SCL High Period register (X7)
+ */
+struct ai2c_reg_i2c_x7_scl_high_period {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned period:16; /*!< bits 15:0 (Desired SCL High Time /
+ PCLK period) - 1 */
+#else
+ unsigned period:16; /*!< bits 15:0 (Desired SCL High Time /r
+i PCLK period) - 1 */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_scl_low_period
+ * @brief I2C SCL Low Period register (X7)
+ */
+struct ai2c_reg_i2c_x7_scl_low_period {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned period:16; /*!< bits 15:0 (Desired SCL Low Time /
+ PCLK period) - 1 */
+#else
+ unsigned period:16; /*!< bits 15:0 (Desired SCL Low Time /
+ PCLK period) - 1 */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_spike_fltr_len
+ * @brief I2C Spike Filter Length register (X7)
+ */
+struct ai2c_reg_i2c_x7_spike_fltr_len {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:27; /*!< bits 31:5 reserved */
+ unsigned fs:5; /*!< bits 4:0 Num of spike filter stages */
+#else
+ unsigned fs:5; /*!< bits 4:0 Num of spike filter stages */
+ unsigned:27; /*!< bits 31:5 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_scl_sda_setup_time
+ * @brief I2C SDA Setup Time register (X7)
+ */
+struct ai2c_reg_i2c_x7_sda_setup_time {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned period:16; /*!< bits 15:0 Suitable period */
+#else
+ unsigned period:16; /*!< bits 15:0 Suitable period */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_sda_hold_time
+ * @brief I2C SDA Hold Time register (X7)
+ */
+struct ai2c_reg_i2c_x7_sda_hold_time {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned period:16; /*!< bits 15:0 Suitable period */
+#else
+ unsigned period:16; /*!< bits 15:0 Suitable period */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_smb_alert
+ * @brief I2C SMB Alert register (X7)
+ */
+struct ai2c_reg_i2c_x7_smb_alert {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:28; /*!< bits 31:4 reserved */
+ unsigned slave_addr_sel:1; /*!< bits 3 Select a slave
+ address register to use in alerts */
+ unsigned smb_alert_pec_enable:1; /*!< bits 2 Suitable period */
+ unsigned smb_alert_enable:1; /*!< bits 1 Suitable period */
+ unsigned smb_alert:1; /*!< bits 0 Suitable period */
+#else
+ unsigned smb_alert:1; /*!< bits 0 Suitable period */
+ unsigned smb_alert_enable:1; /*!< bits 1 Suitable period */
+ unsigned smb_alert_pec_enable:1; /*!< bits 2 Suitable period */
+ unsigned slave_addr_sel:1; /*!< bits 3 Select a slave
+ address register to use in alerts */
+ unsigned:28; /*!< bits 31:4 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w7
+ * @brief I2C UDID 127:112 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w7 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned addr_type:2; /*!< bits 15:14 Types of address */
+ unsigned:5; /*!< bits 13:9 reserved */
+ unsigned pec_supported:1; /*!< bits 8 Ability to support
+ slave PEC check/gen for non-ARP cmd */
+ unsigned:2; /*!< bits 7:6 reserved */
+ unsigned version:3; /*!< bits 5:3 UDID Version 1 */
+ unsigned revision:3; /*!< bits 2:0 Silicon Revision 0 */
+#else
+ unsigned revision:3; /*!< bits 2:0 Silicon Revision 0 */
+ unsigned version:3; /*!< bits 5:3 UDID Version 1 */
+ unsigned:2; /*!< bits 7:6 reserved */
+ unsigned pec_supported:1; /*!< bits 8 Ability to support
+ slave PEC check/gen for non-ARP cmd */
+ unsigned:5; /*!< bits 13:9 reserved */
+ unsigned addr_type:2; /*!< bits 15:14 Types of address */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w6
+ * @brief I2C UDID 111:96 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w6 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned vendorId:16; /*!< bits 15:0 Unique Vendor Id */
+#else
+ unsigned vendorId:16; /*!< bits 15:0 Unique Vendor Id */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w5
+ * @brief I2C UDID 95:80 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w5 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned deviceId:16; /*!< bits 15:0 Unique Device Id */
+#else
+ unsigned deviceId:16; /*!< bits 15:0 Unique Device Id */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w4
+ * @brief I2C UDID 79:64 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w4 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:25; /*!< bits 31:7 reserved */
+ unsigned ipmi:1; /*!< bits 6 Extra capab per IPMI specs */
+ unsigned asf:1; /*!< bits 5 Extra capab per ASF specs */
+ unsigned oem:1; /*!< bits 4 Extra capab per OEM
+ subsystem specs */
+ unsigned smbus_ver:4; /*!< bits 3:0 SMBus Version 2.0 */
+#else
+ unsigned smbus_ver:4; /*!< bits 3:0 SMBus Version 2.0 */
+ unsigned oem:1; /*!< bits 4 Extra capab per OEM
+ subsystem specs */
+ unsigned asf:1; /*!< bits 5 Extra capab per ASF specs */
+ unsigned ipmi:1; /*!< bits 6 Extra capab per IPMI specs */
+ unsigned:25; /*!< bits 31:7 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w3
+ * @brief I2C UDID 63:48 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w3 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned subVendorId:16; /*!< bits 15:0 Subsystem Vendor Id */
+#else
+ unsigned subVendorId:16; /*!< bits 15:0 Subsystem Vendor Id */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w2
+ * @brief I2C UDID 47:32 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w2 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned subDeviceId:16; /*!< bits 15:0 Subsystem Device Id */
+#else
+ unsigned subDeviceId:16; /*!< bits 15:0 Subsystem Device Id */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w1
+ * @brief I2C UDID 31:16 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w1 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned vendorIDHI:16;
+ /*!< bits 15:0 Upper 16-bits of 32-bit unique value
+ * to differentiate between the same
+ * type of device. This field must be
+ * loaded to correct value before ARP
+ * is enabled. */
+#else
+ unsigned vendorIDHI:16;
+ /*!< bits 15:0 Upper 16-bits of 32-bit unique value
+ * to differentiate between the same
+ * type of device. This field must be
+ * loaded to correct value before ARP
+ * is enabled. */
+ unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_udid_w0
+ * @brief I2C UDID 15:0 register (X7)
+ */
+struct ai2c_reg_i2c_x7_udid_w0 {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:16; /*!< bits 31:16 reserved */
+ unsigned vendorIDLO:16;
+ /*!< bits 15:0 Lower 16-bits of 32-bit unique value
+ * to differentiate between the same
+ * type of device. This field must be
+ * loaded to correct value before ARP
+ * is enabled. */
+#else
+ unsigned vendorIDLO:16;
+ /*!< bits 15:0 Lower 16-bits of 32-bit unique value
+ * to differentiate between the same
+ * type of device. This field must be
+ * loaded to correct value before ARP
+ * is enabled. */
+unsigned:16; /*!< bits 31:16 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_arppec_cfg_stat
+ * @brief I2C ARP/PEC Configuration & Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_arppec_cfg_stat {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:26; /*!< bits 31:6 reserved */
+ unsigned slavePECEnable:1; /*!< bits 5 PEC gen/check
+ enabled for non-ARP cmds for slave */
+ unsigned masterPECEnable:1; /*!< bits 4 PEC gen/check enabled
+ for non-ARP cmds for master */
+ unsigned PSAEnable:1; /*!< bits 3 Persistent Slave
+ Address Enabled */
+ unsigned ARPEnable:1; /*!< bits 2 SMBus logic may
+ respond to ARP Slave Commands */
+ unsigned AVFlag:1; /*!< bits 2 Address valid
+ for ARP slave commands */
+ unsigned ARFlag:1; /*!< bits 0 Device address
+ resolved with ARP master */
+#else
+ unsigned ARFlag:1; /*!< bits 0 Device address
+ resolved with ARP master */
+ unsigned AVFlag:1; /*!< bits 2 Address valid
+ for ARP slave commands */
+ unsigned ARPEnable:1; /*!< bits 2 SMBus logic may
+ respond to ARP Slave Commands */
+ unsigned PSAEnable:1; /*!< bits 3 Persistent Slave
+ Address Enabled */
+ unsigned masterPECEnable:1; /*!< bits 4 PEC gen/check enabled
+ for non-ARP cmds for master */
+ unsigned slavePECEnable:1; /*!< bits 5 PEC gen/check enabled
+ for non-ARP cmds for slave */
+ unsigned:26; /*!< bits 31:6 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_arp_int_enable
+ * @brief I2C Slave ARP Interrupt Enable register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_arp_int_enable {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:25; /*!< bits 31:7 reserved */
+ unsigned arpie:7; /*!< bits 6:0 Bit enable individual
+ interrupt sources for ARP Slave Int Stat reg */
+#else
+ unsigned arpie:7; /*!< bits 6:0 Bit enable individual interrupt
+ sources for ARP Slave Int Stat reg */
+ unsigned:25; /*!< bits 31:7 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_slv_arp_int_status
+ * @brief I2C Slave ARP Interrupt Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_slv_arp_int_status {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:25; /*!< bits 31:7 reserved */
+ unsigned SMBAlertResp:7; /*!< bits 6 After receive/reply
+ to Alert Response message */
+ unsigned PrepARPRcv:7; /*!< bits 5 When decode/receive
+ a Prep to ARP command */
+ unsigned RstDevRcv:7; /*!< bits 4 When decode/receive a
+ Reset Device General Command */
+ unsigned GetUDIDRcv:7; /*!< bits 3 After receive/reply to
+ Get UDID General command */
+ unsigned AssignAddrRcv:7; /*!< bits 2 When receive an Assign
+ Address command */
+ unsigned GetUDIDDirectRcv:7; /*!< bits 1 After receive/reply
+ Get UDID Directed Command */
+ unsigned ResetDevDirect:7; /*!< bits 0 When slave receives
+ areset device directed command */
+#else
+ unsigned ResetDevDirect:7; /*!< bits 0 When slave receives
+ areset device directed command */
+ unsigned GetUDIDDirectRcv:7; /*!< bits 1 After receive/reply
+ Get UDID Directed Command */
+ unsigned AssignAddrRcv:7; /*!< bits 2 When receive an
+ Assign Address command */
+ unsigned GetUDIDRcv:7; /*!< bits 3 After receive/reply
+ to Get UDID General command */
+ unsigned RstDevRcv:7; /*!< bits 4 When decode/receive
+ a Reset Device General Command */
+ unsigned PrepARPRcv:7; /*!< bits 5 When decode/receive
+ a Prep to ARP command */
+ unsigned SMBAlertResp:7; /*!< bits 6 After receive/reply
+ to Alert Response message */
+ unsigned:25; /*!< bits 31:7 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_arp_int_enable
+ * @brief I2C Master ARP Interrupt Enable register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_arp_int_enable {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:30; /*!< bits 31:2 reserved */
+ unsigned armmstie:2; /*!< bits 1:0 Bit enable individual
+ interrupt sources for ARP Master
+ Int Stat reg */
+#else
+ unsigned armmstie:2; /*!< bits 1:0 Bit enable individual
+ interrupt sources for ARP Master
+ Int Stat reg */
+ unsigned:30; /*!< bits 31:2 reserved */
+#endif
+};
+
+/*! @struct ai2c_reg_i2c_x7_mst_arp_int_status
+ * @brief I2C Master ARP Interrupt Status register (X7)
+ */
+struct ai2c_reg_i2c_x7_mst_arp_int_status {
+
+#ifdef AI2C_BIG_ENDIAN
+ unsigned:30; /*!< bits 31:2 reserved */
+ unsigned PECRdErr:1; /*!< bits 1 Master Read msg with PECr
+ enabled has detected a PEC error with
+ Slave response */
+ unsigned SMBAlert:1; /*!< bits 0 State of SMB_Alert#
+ signal on the SM Bus */
+#else
+ unsigned SMBAlert:1; /*!< bits 0 State of SMB_Alert#r
+ signal on the SM Bus */
+ unsigned PECRdErr:1; /*!< bits 1 Master Read msg with
+ PEC enabled has detected a PEC error
+ with Slave response */
+ unsigned:30; /*!< bits 31:2 reserved */
+#endif
+};
+
+#endif /* _AI2C_I2C_REGS_H_ */
diff --git a/drivers/i2c/busses/ai2c/regs/ai2c_regions.h b/drivers/i2c/busses/ai2c/regs/ai2c_regions.h
new file mode 100644
index 0000000..a6fe19c
--- /dev/null
+++ b/drivers/i2c/busses/ai2c/regs/ai2c_regions.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2013 LSI Corporation
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+/*! @file ai2c_regions.h
+ @brief Defines to access induvidual regions within the NCP.
+*/
+
+#ifndef __AI2C_REGIONS_H__
+#define __AI2C_REGIONS_H__
+
+
+/*!
+ * Node definitions for all nodes/engines in NCP/X1.
+ * This needs to be kept in-sync with HW.
+ */
+
+#define AI2C_NODE_X1_ECID 0x0A
+
+
+/* ---------------------------------- */
+/* --- AI2C Region ID Support --- */
+/* ---------------------------------- */
+
+
+#define AI2C_NODE_MASK (0xFFFF)
+#define AI2C_TARGET_MASK (0xFFFF)
+
+#define AI2C_NODE_ID(regionId) (((regionId) >> 16) & AI2C_NODE_MASK)
+#define AI2C_TARGET_ID(regionId) ((regionId) & AI2C_TARGET_MASK)
+
+
+#define AI2C_REGION_ID(node, target) \
+ ((u32) \
+ ((((node) & AI2C_NODE_MASK) << 16) | ((target) & AI2C_TARGET_MASK)))
+
+
+/* ---------------------------------- */
+/* --- AI2C Region ID Definitions --- */
+/* ---------------------------------- */
+
+/* Temporary dummy regions */
+#define AI2C_REGION_NULL (AI2C_REGION_ID(0xffff, 0xffff))
+
+
+#define AI2C_REGION_NCA_CFG (AI2C_REGION_ID(0x16, 0xff))
+
+
+#define AI2C_REGION_GPIO_0 (AI2C_REGION_ID(0x140, 0)) /* 320.0 */
+#define AI2C_REGION_I2C_0 (AI2C_REGION_ID(0x143, 0)) /* 323.0 */
+#define AI2C_REGION_TIMER (AI2C_REGION_ID(0x146, 0)) /* 326.0 */
+#define AI2C_REGION_GPREG (AI2C_REGION_ID(0x149, 0)) /* 329.0 */
+#define AI2C_REGION_I2C_1 (AI2C_REGION_ID(0x14c, 0)) /* 332.0 */
+#define AI2C_REGION_I2C_2 (AI2C_REGION_ID(0x152, 0)) /* 338.0 */
+
+#define AI2C_REGION_SMB (AI2C_REGION_ID(0x15c, 0)) /* 348.0 */
+#define AI2C_REGION_I2C_3 AI2C_REGION_SMB
+
+#define AI2C_REGION_CLK_CTRL (AI2C_REGION_ID(0x18d, 0)) /* 397.0 */
+
+#define AI2C_REGION_RESET_CTRL (AI2C_REGION_ID(0x18e, 0)) /* 398.0 */
+
+
+#endif /* __AI2C_REGIONS_H__ */
--
1.8.3
More information about the linux-yocto
mailing list