[linux-yocto] [PATCH 21/78] drivers/i2c: Collapse AI2C driver implementation mods

Paul Butler butler.paul at gmail.com
Tue Nov 19 20:22:57 PST 2013


From: Michael Bringmann <michael.bringmann at lsi.com>

Signed-off-by: Michael Bringmann <michael.bringmann at lsi.com>
Signed-off-by: Paul Butler <paul.butler at windriver.com>
---
 drivers/i2c/busses/ai2c/Makefile           |    5 +-
 drivers/i2c/busses/ai2c/ai2c_bus.h         |  881 ++++++++++++++++++-
 drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c |    5 +-
 drivers/i2c/busses/ai2c/ai2c_mod.c         | 1267 +++++++++++++++++++++++++++-
 4 files changed, 2137 insertions(+), 21 deletions(-)

diff --git a/drivers/i2c/busses/ai2c/Makefile b/drivers/i2c/busses/ai2c/Makefile
index e618016..276a79c 100644
--- a/drivers/i2c/busses/ai2c/Makefile
+++ b/drivers/i2c/busses/ai2c/Makefile
@@ -7,10 +7,7 @@ MODULE := lsi_acp_i2c
 obj-$(CONFIG_I2C_AXXIA)		+= $(MODULE).o
 
 $(MODULE)-objs			:= ai2c_mod.o \
-				   ai2c_plat.o \
-				   ai2c_bus_axm5500.o \
-				   ai2c_dev_clock.o \
-				   ai2c_sal.o
+				   ai2c_bus_axm5500.o
 
 ccflags-$(CONFIG_I2C_AXXIA) := -DAI2C_MOD_NAME=\"ai2c\" \
 				-DAI2C_MSG_TRACE_LEVEL=ai2c_trace_level \
diff --git a/drivers/i2c/busses/ai2c/ai2c_bus.h b/drivers/i2c/busses/ai2c/ai2c_bus.h
index 8861ae5..9702ad9 100644
--- a/drivers/i2c/busses/ai2c/ai2c_bus.h
+++ b/drivers/i2c/busses/ai2c/ai2c_bus.h
@@ -28,12 +28,870 @@
 #ifndef AI2C_BUS_H
 #define AI2C_BUS_H
 
-#include "ai2c_types.h"
-#include "regs/ai2c_i2c_regs.h"
-#include "ai2c_plat.h"
+#include <generated/autoconf.h>
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/cdev.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/init.h>
+#include <linux/poll.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+
+#include <linux/io.h>
+#include <linux/ioport.h>
+#include <linux/kernel.h>
+#include <linux/wait.h>
+#include <asm/pgtable.h>
+
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/spinlock.h>
+#include <linux/signal.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c-axxia.h>
+
+#include <linux/version.h>
+
+#include <linux/time.h>
+#include <linux/fcntl.h>
+#include <linux/unistd.h>
+#include <linux/errno.h>
+#include <linux/mman.h>
+#include <linux/types.h>
+
+#include <asm/byteorder.h>
+
+/**************************************************************************
+* Basic Type Definitions, Constants, #Defines, etc.
+**************************************************************************/
+
+    /**************************************************************************
+    * Constants, #Defines, etc.
+    **************************************************************************/
+
+#ifndef NULL
+#define NULL    0
+#endif
+
+#ifndef TRUE
+#define TRUE    1
+#endif
+
+#ifndef FALSE
+#define FALSE   0
+#endif
+
+    /**************************************************************************
+     * 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);
+
+
+/* BEGIN: Important forward type references */
+
+struct ai2c_region_io;
+struct ai2c_priv;
+
+/* END:   Important forward type references */
+
+
+/* --- Linux References --- */
+#ifndef AI2C_MOD_NAME
+#define AI2C_MOD_NAME        "ai2c"
+#endif
+
+
+/* --- Maximum version string length --- */
+#define AI2C_DEV_MAX_VERSION_LENGTH  (41)
+
+
+/* --- 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 }      \
+	}
+
+
+/* --- 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
+ */
+#define AI2C_NCA_CMD_CRBR            (0x00000004)
+#define AI2C_NCA_CMD_CRBW            (0x00000005)
+
+#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)
+
+
+#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) { \
+			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) { \
+			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);
+
+
+    /**************************************************************************
+    * Event/Error Logging
+    **************************************************************************/
+
+/*
+* 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;
+
+
+    /**************************************************************************
+    * Endianness
+    **************************************************************************/
+
+#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
+
+/*
+* 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((u8 *) (addr))
+
+#define AI2C_BUS_READ16_ENDIAN(endian, addr) \
+	in_##endian##16((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((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), (u8 *) (addr))
+
+#define AI2C_BUS_WRITE16_ENDIAN(endian, addr, data) \
+	do { \
+		u16 *__a__ = (u16 *) addr; \
+		u16 __d__ = data; \
+		out_##endian##16((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) \
+	do { \
+		if (endian == AI2C_DEV_ACCESS_BIG_ENDIAN) {  \
+			AI2C_BUS_WRITE16_BE(addr, data);    \
+		} else { \
+			AI2C_BUS_WRITE16_LE(addr, data);    \
+		} \
+	} while (0);
+
+#define AI2C_BUS_WRITE32_ENDIAN(endian, addr, data) \
+	do { \
+		u32 *__a__ = (u32 *) addr; \
+		u32 __d__ = data; \
+		out_##endian##32((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) \
+	do { \
+		if (endian == AI2C_DEV_ACCESS_BIG_ENDIAN) {  \
+			AI2C_BUS_WRITE32_BE(addr, data);    \
+		} else {			            \
+			AI2C_BUS_WRITE32_LE(addr, data);    \
+		} \
+	} while (0);
+
+    /*
+    * 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
+};
+
+
+    /**************************************************************************
+    * More Macros
+    **************************************************************************/
+
+/* Should this 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
+
+    /**************************************************************************
+    * Function Prototypes
+    **************************************************************************/
+
+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);
 
 /*****************************************************************************
-* Constants                                                                  *
+* Internal Data Structure Definitions                                        *
+*****************************************************************************/
+
+    /**********************************************************************
+    * 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                                                                  *
+    **************************************************************************/
+
+#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)
+
+
+/**************************************************************************
+* Driver State management                                                 *
+**************************************************************************/
+
+    /**********************************************************************
+    * Support Memory Mappings for Driver State Structure                  *
+    **********************************************************************/
+
+#define AI2C_PAGE_FLAGS_NONE            (0x00000000)
+#define AI2C_PAGE_FLAGS_I2CBUS          (0x00000001)
+
+struct ai2c_dev_page_s {
+	int    pageId;
+	char   *busName;
+	u32    bus_nr;
+	u64    busAddr; /* 38-bit PCI address */
+	u32    size;
+	u32    endianness;
+	u32    flags;
+	struct axxia_i2c_bus_platform_data  *pdata;
+};
+
+struct ai2c_dev_chip_entry_s {
+	u32	chipType;
+	char	*chipName;
+	u32	numActiveBusses;
+	struct ai2c_i2c_access *api;
+};
+
+
+    /**********************************************************************
+    * 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_chip_entry_s *busCfg;
+
+	/* Memory Mapping/Management constructs */
+	u32 numActiveBusses;
+	struct ai2c_dev_page_s *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;
+
+
+    /**************************************************************************
+    * Shared 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);
+
+/*! @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_stateSetup(struct ai2c_priv **outPriv);
+    @brief This is a one time initialization for the state linking all
+	   of 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_stateSetup(struct ai2c_priv       **outPriv);
+
+/*! @fn int ai2c_memSetup(struct platform_device *pdev,
+			  struct ai2c_priv *priv);
+    @brief This is a per-device to-be-mapped setup for the I2C protocol
+	   layers to be called by the device initialization step.
+    @param[in] inPDev Source platform device data strucure
+    @param[in] inPriv Created device state structure
+    @Returns success/failure status of the operation
+*/
+extern int ai2c_memSetup(struct platform_device *pdev,
+			 struct ai2c_priv       *priv);
+
+/*! @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);
+
+
+/*****************************************************************************
+* Bus Device Protocol Definitions                                            *
 *****************************************************************************/
 
     /*****************************
@@ -92,10 +950,6 @@
 #define DEV_10BIT_AUTO(ioc)          TENBIT_SETENABLED(ioc)
 
 
-/*****************************************************************************
-* Type definitions                                                           *
-*****************************************************************************/
-
 	/*******************************************
 	* Common Protocol State & Callbacks
 	********************************************/
@@ -169,9 +1023,9 @@ struct ai2c_i2c_access {
 extern struct ai2c_i2c_access       ai2c_axm5500_cfg;
 
 
-/*****************************************************************************
-* Externally Visible Function Prototypes                                     *
-*****************************************************************************/
+    /************************************************************************
+    * Externally Visible Function Prototypes                                *
+    ************************************************************************/
 
 /*! @fn int ai2c_bus_init(ai2c_priv_t * inDevHdl);
     @brief This is a one time initialization for the I2C protocol
@@ -228,4 +1082,9 @@ extern int ai2c_bus_block_write8(
 */
 extern int ai2c_bus_destroy(struct ai2c_priv *priv);
 
+extern int ai2c_dev_clock_mhz(
+	struct ai2c_priv         *priv,          /* IN */
+	u32       *clockMhz);     /* OUT: Calculated value */
+
+
 #endif   /* defined(AI2C_BUS_H) */
diff --git a/drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c b/drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c
index 01c1a38..2210d3a 100644
--- a/drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c
+++ b/drivers/i2c/busses/ai2c/ai2c_bus_axm5500.c
@@ -23,10 +23,7 @@
 /* #define EXTRA_DEBUG */
 
 #include "ai2c_bus.h"
-#include "ai2c_plat.h"
-#include "ai2c_dev_clock_ext.h"
-#include "regs/ai2c_i2c_regs.h"
-#include "regs/ai2c_axi_timer_regs.h"
+#include "ai2c_i2c_regs.h"
 
 
 /*****************************************************************************
diff --git a/drivers/i2c/busses/ai2c/ai2c_mod.c b/drivers/i2c/busses/ai2c/ai2c_mod.c
index 63d3521..6692b2e 100644
--- a/drivers/i2c/busses/ai2c/ai2c_mod.c
+++ b/drivers/i2c/busses/ai2c/ai2c_mod.c
@@ -53,13 +53,14 @@
 */
 
 #include "ai2c_bus.h"
-#include "regs/ai2c_cfg_node_reg_defines.h"
-#include "regs/ai2c_cfg_node_regs.h"
+#include "ai2c_i2c_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|\
@@ -71,6 +72,7 @@
 /*****************************
 * --- 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
@@ -108,6 +110,1267 @@ struct local_state {
 static  struct local_state *ai2cModState;
 
 /*****************************************************************************
+ * Local Functions: Memory
+ *****************************************************************************/
+
+/*
+ * 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 0;
+	}
+
+	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 0;
+	}
+
+	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 0;
+	}
+
+	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);
+}
+
+/*****************************************************************************
+ * Clock Support
+ *****************************************************************************/
+
+/*
+ * 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:
+	return ai2cStatus;
+}
+
+/*****************************************************************************
+ * ACP/AXXIA Memory mapping & Device I/O
+ *****************************************************************************/
+
+/*
+ * 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
+ */
+static struct ai2c_dev_page_s ai2c_dev_page[AI2C_DEV_PAGE_END_MARKER] = {
+	{
+		AI2C_DEV_PAGE_I2C_0, "AXXIA_I2C0", 0, 0x00000000000ULL,
+		AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+		AI2C_PAGE_FLAGS_I2CBUS, NULL,
+	},
+	{
+		AI2C_DEV_PAGE_I2C_1, "AXXIA_I2C1", 0, 0x00000000000ULL,
+		AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+		AI2C_PAGE_FLAGS_I2CBUS, NULL,
+	},
+	{
+		AI2C_DEV_PAGE_I2C_2, "AXXIA_I2C2", 0, 0x00000000000ULL,
+		AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+		AI2C_PAGE_FLAGS_I2CBUS, NULL,
+	},
+	{
+		AI2C_DEV_PAGE_I2C_3, "AXXIA_SMB", 0, 0x00000000000ULL,
+		AI2C_DEV_SIZE_4KB, AI2C_DEV_ACCESS_LITTLE_ENDIAN,
+		AI2C_PAGE_FLAGS_I2CBUS, NULL,
+	},
+	{
+		AI2C_DEV_PAGE_END_MARKER, NULL, 0, 0x00000000000ULL, 0, 0,
+		AI2C_PAGE_FLAGS_NONE, NULL,
+	},
+	{
+		AI2C_DEV_PAGE_END_MARKER, NULL, 0, 0x00000000000ULL, 0, 0,
+		AI2C_PAGE_FLAGS_NONE, NULL,
+	},
+	{
+		AI2C_DEV_PAGE_END_MARKER, NULL, 0, 0x00000000000ULL, 0, 0,
+		AI2C_PAGE_FLAGS_NONE, NULL,
+	},
+	{
+		AI2C_DEV_PAGE_END_MARKER, NULL, 0, 0x00000000000ULL, 0, 0,
+		AI2C_PAGE_FLAGS_NONE, NULL,
+	},
+};
+
+static struct ai2c_dev_chip_entry_s ai2c_chip_id[] = {
+	{ AI2C_CHIP_ACP55xx, "AXM55xx", 4, &ai2c_axm5500_cfg, },
+	{ AI2C_CHIP_ACP35xx, "AXM35xx", 3, &ai2c_axm5500_cfg, },
+};
+
+static u32 ai2c_chip_id_count = sizeof(ai2c_chip_id)/
+				sizeof(struct ai2c_dev_chip_entry_s);
+
+	/* Region Map
+	 *   Note: Must be same number of entries (and in same order) as
+	 *	 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;
+	u32	       i;
+#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
+
+	for (i = 0; i < ai2c_chip_id_count; i++) {
+		if (ai2c_chip_id[i].chipType == priv->hw_rev.chipType) {
+			priv->busCfg = &ai2c_chip_id[i];
+			priv->numActiveBusses = ai2c_chip_id[i].numActiveBusses;
+		}
+	}
+	if (priv->busCfg == NULL) {
+		ai2cStatus = -ENXIO;
+		goto ai2c_return;
+	}
+
+	AI2C_LOG(AI2C_MSG_INFO, "%s %d.%d.%d %s\n",
+		priv->busCfg->chipName,
+		priv->hw_rev.chipType, priv->hw_rev.chipVersion,
+		priv->hw_rev.packageType,
+		(priv->hw_rev.isFpga) ? "FPGA" : "ASIC");
+
+ai2c_return:
+	return ai2cStatus;
+}
+
+int ai2c_stateSetup(
+    struct ai2c_priv           **outPriv)
+{
+	int                     ai2cStatus = AI2C_ST_SUCCESS;
+	struct ai2c_priv        *priv = NULL;
+
+	/* 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;
+
+ai2c_return:
+	if (ai2cStatus != AI2C_ST_SUCCESS)
+		(*outPriv) = NULL;
+	else
+		(*outPriv) = priv;
+
+	return ai2cStatus;
+}
+
+int ai2c_memSetup(
+    struct platform_device      *pdev,
+    struct ai2c_priv            *priv)
+{
+	int                     ai2cStatus = AI2C_ST_SUCCESS;
+	struct axxia_i2c_bus_platform_data  *pdata;
+	u32                     busNdx;
+	int                     i;
+
+	/* Where is the current I2C device found on this platform? */
+	pdata = (struct axxia_i2c_bus_platform_data *) pdev->dev.platform_data;
+	if (pdata == NULL) {
+		AI2C_LOG(AI2C_MSG_ERROR,
+			"Can't find platform-specific data!\n");
+		ai2cStatus = -ENXIO;
+		goto ai2c_return;
+	}
+	busNdx = pdata->index;
+
+	priv->pages = ai2c_dev_page;
+
+	if (busNdx > (priv->numActiveBusses-1)) {
+		AI2C_LOG(AI2C_MSG_ERROR, "Invalid I2C bus index (%d)\n",
+			busNdx);
+		ai2cStatus = -ENXIO;
+		goto ai2c_return;
+	}
+
+	priv->pages[busNdx].busName = &pdata->name[0];
+	priv->pages[busNdx].bus_nr  = pdata->bus_nr;
+	priv->pages[busNdx].busAddr = pdata->dev_space.start;
+	priv->pages[busNdx].size    =
+		pdata->dev_space.end - pdata->dev_space.start + 1;
+	priv->pages[busNdx].pdata   = pdata;
+
+	AI2C_LOG(AI2C_MSG_DEBUG,
+		"[%d] ba=0x%010llx (%llx, %llx) sz=0x%x\n",
+		busNdx,
+		priv->pages[busNdx].busAddr,
+		pdata->dev_space.start, pdata->dev_space.end,
+		priv->pages[busNdx].size);
+
+	/*
+	* Interrupt for this bus is in priv->pdata[i].int_space.start
+	*/
+
+	/*
+	* Program Address Map driver tables
+	*/
+	if (priv->pageAddr == NULL) {
+		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->pageAddr[i] ||
+		    (priv->pages[i].busAddr == 0) ||
+		    (priv->pages[i].size == 0) ||
+		    (priv->pages[i].pageId == AI2C_DEV_PAGE_END_MARKER))
+			continue;
+
+		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);
+			AI2C_LOG(AI2C_MSG_DEBUG,
+				"ba=0x%010llx sz=0x%x\n",
+				priv->pages[i].busAddr,
+				priv->pages[i].size);
+			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:
+
+	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);
+		}
+	}
+
+	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 *)inPriv->pageAddr[i]);
+
+			ai2c_free(inPriv->pageAddr);
+		}
+
+		ai2c_free(inPriv);
+	}
+
+	return ai2cStatus;
+}
+
+/*****************************************************************************
  * I2C Algorithm
  *****************************************************************************/
 
-- 
1.8.4.3



More information about the linux-yocto mailing list