[msm8x60] Add support to read platform id from EPROM

This code adds support for I2C driver. I2C driver is used to read
EPROM for detecting product id of msm8660 device.

Change-Id: I66bdfb827048ba9ac97d17a05bb138019f2d5be9
diff --git a/platform/msm8x60/platform.c b/platform/msm8x60/platform.c
index 7fe6f31..28217de 100755
--- a/platform/msm8x60/platform.c
+++ b/platform/msm8x60/platform.c
@@ -37,6 +37,27 @@
 #include <kernel/thread.h>
 #include <platform/debug.h>
 #include <platform/iomap.h>
+#include <i2c_qup.h>
+
+#define CONVERT_ENDIAN_U32(val)                   \
+    ((((uint32_t)(val) & 0x000000FF) << 24) |     \
+     (((uint32_t)(val) & 0x0000FF00) << 8)  |     \
+     (((uint32_t)(val) & 0x00FF0000) >> 8)  |     \
+     (((uint32_t)(val) & 0xFF000000) >> 24))
+
+#define CONVERT_ENDIAN_U16(val)              \
+    ((((uint16_t)(val) & 0x00FF) << 8) |     \
+     (((uint16_t)(val) & 0xFF00) >> 8))
+
+/* Configuration Data Table */
+#define CDT_MAGIC_NUMBER    0x43445400
+struct cdt_header
+{
+    uint32_t magic;   /* Magic number */
+    uint16_t version; /* Version number */
+    uint32_t reserved1;
+    uint32_t reserved2;
+}__attribute__((packed));
 
 void platform_init_interrupts(void);
 void platform_init_timer();
@@ -68,3 +89,46 @@
     writel(0x0, 0x00902D80); //SCSS_CPU1CORE_RESET
     writel(0x3, 0x00902E64); //SCSS_DBG_STATUS_CORE_PWRDUP
 }
+
+static struct qup_i2c_dev* dev = NULL;
+
+uint32_t eprom_read (uint16_t addr, uint8_t count) {
+    uint32_t ret = 0;
+    if(!dev){
+        return ret;
+    }
+    /* Create a i2c_msg buffer, that is used to put the controller into
+     * read mode and then to read some data.
+     */
+    struct i2c_msg msg_buf[] = {
+        {EEPROM_I2C_ADDRESS, I2C_M_WR, 2, &addr},
+        {EEPROM_I2C_ADDRESS, I2C_M_RD, count, &ret}
+    };
+
+    qup_i2c_xfer(dev, msg_buf, 2);
+    return ret;
+}
+
+/* Read EEPROM to find out product id. Return 0 in case of failure */
+uint32_t platform_id_read (void)
+{
+    uint32_t id = 0;
+    uint16_t offset = 0;
+    dev = qup_i2c_init(GSBI8_BASE, 100000, 24000000);
+    if(!dev){
+        return id;
+    }
+    /* Check if EPROM is valid */
+    if (CONVERT_ENDIAN_U32(eprom_read(0, 4)) == CDT_MAGIC_NUMBER)
+    {
+        /* Get offset for platform ID info from Meta Data block 0 */
+        offset = eprom_read(CONVERT_ENDIAN_U16(0 +
+            sizeof(struct cdt_header)), 2);
+        /* Read platform ID */
+        id = eprom_read(CONVERT_ENDIAN_U16(offset), 4);
+        id = CONVERT_ENDIAN_U32(id);
+        id = (id & 0x00FF0000) >> 16;
+    }
+    return id;
+}
+