From 3e0f6f8b7fad9925ee3d8f793427021bee34d544 Mon Sep 17 00:00:00 2001
From: Walter Goossens <walter.goossens@axon.tv>
Date: Wed, 9 Jan 2008 10:56:45 +0000
Subject: [PATCH] nios2: Add platform device for opencores i2c master

Added everything to get the opencores i2c master to work with an
SOPC generated system through the platform device system. I also
did some minor patching to the opencores driver to make it work for
me.

Signed-off-by: Walter Goossens <walter.goossens@axon.tv>
---
 linux-2.6.x/arch/nios2nommu/kernel/setup.c         |   66 ++++++++++++++++++++
 .../scripts/nios2_system.h/opencores_i2c_master.pm |   18 +++++
 linux-2.6.x/drivers/i2c/busses/Kconfig             |   13 ++++
 linux-2.6.x/drivers/i2c/busses/i2c-ocores.c        |    4 +-
 4 files changed, 100 insertions(+), 1 deletions(-)
 create mode 100644 linux-2.6.x/arch/nios2nommu/scripts/nios2_system.h/opencores_i2c_master.pm

diff --git a/linux-2.6.x/arch/nios2nommu/kernel/setup.c b/linux-2.6.x/arch/nios2nommu/kernel/setup.c
index 9bb1f93..98a8008 100644
--- a/linux-2.6.x/arch/nios2nommu/kernel/setup.c
+++ b/linux-2.6.x/arch/nios2nommu/kernel/setup.c
@@ -673,3 +673,69 @@ static int __init i2c_gpio_device_init(void)
 arch_initcall(i2c_gpio_device_init);
 
 #endif // CONFIG_I2C_GPIO
+
+#if defined(CONFIG_I2C_OCORES) && defined(na_ocores_i2c_0)
+
+#include <linux/i2c-ocores.h>
+static struct ocores_i2c_platform_data ocores_i2c_data = {
+  .regstep = 4,
+  .clock_khz = nasys_clock_freq_1000,
+};
+static struct resource ocores_i2c_0_resources[] = {
+  [0] = {
+    .start    = na_ocores_i2c_0,
+    .end    = na_ocores_i2c_0 + 0x20 - 1,
+    .flags    = IORESOURCE_MEM,
+  },
+  [1] = {
+    .start    = na_ocores_i2c_0_irq,
+    .end    = na_ocores_i2c_0_irq,
+    .flags    = IORESOURCE_IRQ,
+  },
+};
+static struct platform_device ocores_i2c_0_device = {
+  .name   = "ocores-i2c",
+  .id   = 0,
+  .num_resources  = ARRAY_SIZE(ocores_i2c_0_resources),
+  .resource = ocores_i2c_0_resources,
+  .dev = {
+    .platform_data = &ocores_i2c_data,
+  },
+};
+
+#if defined(na_ocores_i2c_1)
+static struct resource ocores_i2c_1_resources[] = {
+  [0] = {
+    .start    = na_ocores_i2c_1,
+    .end    = na_ocores_i2c_1 + 0x20 - 1,
+    .flags    = IORESOURCE_MEM,
+  },
+  [1] = {
+    .start    = na_ocores_i2c_1_irq,
+    .end    = na_ocores_i2c_1_irq,
+    .flags    = IORESOURCE_IRQ,
+  },
+};
+static struct platform_device ocores_i2c_1_device = {
+  .name   = "ocores-i2c",
+  .id   = 1,
+  .num_resources  = ARRAY_SIZE(ocores_i2c_1_resources),
+  .resource = ocores_i2c_1_resources,
+  .dev = {
+    .platform_data = &ocores_i2c_data,
+  },
+};
+#endif // na_ocores_i2c_1
+
+static int __init ocores_i2c_device_init(void)
+{
+  /* customizes platform devices, or adds new ones */
+  platform_device_register(&ocores_i2c_0_device);
+#if defined(na_ocores_i2c_1)
+  platform_device_register(&ocores_i2c_1_device);
+#endif // na_ocores_i2c_1
+  return 0;
+}
+arch_initcall(ocores_i2c_device_init);
+
+#endif
diff --git a/linux-2.6.x/arch/nios2nommu/scripts/nios2_system.h/opencores_i2c_master.pm b/linux-2.6.x/arch/nios2nommu/scripts/nios2_system.h/opencores_i2c_master.pm
new file mode 100644
index 0000000..b63a865
--- /dev/null
+++ b/linux-2.6.x/arch/nios2nommu/scripts/nios2_system.h/opencores_i2c_master.pm
@@ -0,0 +1,18 @@
+package opencores_i2c_master;
+
+use base qw(BasicModule);
+use strict;
+
+sub required_module_names {
+	("ocores_i2c_0", "ocores_i2c_1")
+}
+
+sub required_class_name {
+	"opencores_i2c_master";
+}
+
+sub run {
+	opencores_i2c_master->run2 (@_);
+}
+
+1;
diff --git a/linux-2.6.x/drivers/i2c/busses/Kconfig b/linux-2.6.x/drivers/i2c/busses/Kconfig
index 8ed9157..2c09e94 100644
--- a/linux-2.6.x/drivers/i2c/busses/Kconfig
+++ b/linux-2.6.x/drivers/i2c/busses/Kconfig
@@ -297,6 +297,19 @@ config I2C_OCORES
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-ocores.
 
+config I2C_OCORES_SPEED
+	int "I2C Speed (Kbps)"
+	depends on I2C_OCORES
+	default "100"
+	help
+	  Select the I2C speed here the I2C standard defines normal mode as
+	  100 kbps which should be a safe (but slow) choice. Other defined
+	  speeds are 400 for Fast Mode 1000 for Fast Mode Plus and up to 
+	  34000 for High speed mode. The core supports all speeds (even higher
+	  if your bus speed is high enough) but most slave chips won't. 
+	  
+	  Most people will choose 100 or 400 here. If unsure 100 is a safe bet.
+
 config I2C_OMAP
 	tristate "OMAP I2C adapter"
 	depends on I2C && ARCH_OMAP
diff --git a/linux-2.6.x/drivers/i2c/busses/i2c-ocores.c b/linux-2.6.x/drivers/i2c/busses/i2c-ocores.c
index f28a76d..dc7dc8d 100644
--- a/linux-2.6.x/drivers/i2c/busses/i2c-ocores.c
+++ b/linux-2.6.x/drivers/i2c/busses/i2c-ocores.c
@@ -96,6 +96,8 @@ static void ocores_process(struct ocores_i2c *i2c)
 		i2c->state =
 			(msg->flags & I2C_M_RD) ? STATE_READ : STATE_WRITE;
 
+		oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_IACK);
+
 		if (stat & OCI2C_STAT_NACK) {
 			i2c->state = STATE_ERROR;
 			oc_setreg(i2c, OCI2C_CMD, OCI2C_CMD_STOP);
@@ -183,7 +185,7 @@ static void ocores_init(struct ocores_i2c *i2c,
 	/* make sure the device is disabled */
 	oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
 
-	prescale = (pdata->clock_khz / (5*100)) - 1;
+	prescale = (pdata->clock_khz / (5*CONFIG_I2C_OCORES_SPEED)) - 1;
 	oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
 	oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
 
-- 
1.5.3.3

