MIPS: Octeon: Add I2C platform device.
authorDavid Daney <ddaney@caviumnetworks.com>
Thu, 7 Jan 2010 21:23:41 +0000 (13:23 -0800)
committerRalf Baechle <ralf@linux-mips.org>
Sat, 27 Feb 2010 11:53:04 +0000 (12:53 +0100)
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
To: linux-mips@linux-mips.org
To: linux-i2c@vger.kernel.org
To: ben-linux@fluff.org
To: khali@linux-fr.org
Cc: Rade Bozic <rade.bozic.ext@nsn.com>
Patchwork: http://patchwork.linux-mips.org/patch/847/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
arch/mips/cavium-octeon/octeon-platform.c
arch/mips/include/asm/octeon/octeon.h

index cfdb4c2..784c1c8 100644 (file)
@@ -159,6 +159,78 @@ out:
 }
 device_initcall(octeon_rng_device_init);
 
+
+#define OCTEON_I2C_IO_BASE 0x1180000001000ull
+#define OCTEON_I2C_IO_UNIT_OFFSET 0x200
+
+static struct octeon_i2c_data octeon_i2c_data[2];
+
+static int __init octeon_i2c_device_init(void)
+{
+       struct platform_device *pd;
+       int ret = 0;
+       int port, num_ports;
+
+       struct resource i2c_resources[] = {
+               {
+                       .flags  = IORESOURCE_MEM,
+               }, {
+                       .flags  = IORESOURCE_IRQ,
+               }
+       };
+
+       if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN52XX))
+               num_ports = 2;
+       else
+               num_ports = 1;
+
+       for (port = 0; port < num_ports; port++) {
+               octeon_i2c_data[port].sys_freq = octeon_get_clock_rate();
+               /*FIXME: should be examined. At the moment is set for 100Khz */
+               octeon_i2c_data[port].i2c_freq = 100000;
+
+               pd = platform_device_alloc("i2c-octeon", port);
+               if (!pd) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               pd->dev.platform_data = octeon_i2c_data + port;
+
+               i2c_resources[0].start =
+                       OCTEON_I2C_IO_BASE + (port * OCTEON_I2C_IO_UNIT_OFFSET);
+               i2c_resources[0].end = i2c_resources[0].start + 0x1f;
+               switch (port) {
+               case 0:
+                       i2c_resources[1].start = OCTEON_IRQ_TWSI;
+                       i2c_resources[1].end = OCTEON_IRQ_TWSI;
+                       break;
+               case 1:
+                       i2c_resources[1].start = OCTEON_IRQ_TWSI2;
+                       i2c_resources[1].end = OCTEON_IRQ_TWSI2;
+                       break;
+               default:
+                       BUG();
+               }
+
+               ret = platform_device_add_resources(pd,
+                                                   i2c_resources,
+                                                   ARRAY_SIZE(i2c_resources));
+               if (ret)
+                       goto fail;
+
+               ret = platform_device_add(pd);
+               if (ret)
+                       goto fail;
+       }
+       return ret;
+fail:
+       platform_device_put(pd);
+out:
+       return ret;
+}
+device_initcall(octeon_i2c_device_init);
+
 /* Octeon SMI/MDIO interface.  */
 static int __init octeon_mdiobus_device_init(void)
 {
index 4d0a8c6..ca6214b 100644 (file)
@@ -213,6 +213,11 @@ struct octeon_cf_data {
        int             dma_engine;     /* -1 for no DMA */
 };
 
+struct octeon_i2c_data {
+       unsigned int    sys_freq;
+       unsigned int    i2c_freq;
+};
+
 extern void octeon_write_lcd(const char *s);
 extern void octeon_check_cpu_bist(void);
 extern int octeon_get_boot_debug_flag(void);