The registers are 32-bit and in big endian byte order. The PRELOW and PREHIGH
registers are merged into one register. The subsequent registers have their
offset decreased accordingly.

Signed-off-by: Andreas Larsson <[email protected]>
---
 drivers/i2c/busses/i2c-ocores.c |   47 +++++++++++++++++++++++++++++++++++++++
 1 files changed, 47 insertions(+), 0 deletions(-)

diff --git a/drivers/i2c/busses/i2c-ocores.c b/drivers/i2c/busses/i2c-ocores.c
index de93b2d..1895e8c 100644
--- a/drivers/i2c/busses/i2c-ocores.c
+++ b/drivers/i2c/busses/i2c-ocores.c
@@ -4,6 +4,9 @@
  *
  * Peter Korsgaard <[email protected]>
  *
+ * Modified by Andreas Larsson <[email protected]> to support the GRLIB port
+ * of the controller.
+ *
  * This file is licensed under the terms of the GNU General Public License
  * version 2.  This program is licensed "as is" without any warranty of any
  * kind, whether express or implied.
@@ -99,6 +102,40 @@ static inline u8 oc_getreg(struct ocores_i2c *i2c, int reg)
                return ioread8(i2c->base + (reg << i2c->reg_shift));
 }
 
+/* Read and write functions for the GRLIB port of the controller. Registers are
+ * 32-bit big endian and the PRELOW and PREHIGH registers are merged into one
+ * register. The subsequent registers has their offset decreased accordingly. 
*/
+static u8 oc_getreg_grlib(struct ocores_i2c *i2c, int reg)
+{
+       u32 rd;
+       int rreg = reg;
+       if (reg != OCI2C_PRELOW)
+               rreg--;
+       rd = ioread32be(i2c->base + (rreg << i2c->reg_shift));
+       if (reg == OCI2C_PREHIGH)
+               return (u8)rd >> 8;
+       else
+               return (u8)rd;
+}
+
+static void oc_setreg_grlib(struct ocores_i2c *i2c, int reg, u8 value)
+{
+       u32 curr, wr;
+       int rreg = reg;
+       if (reg != OCI2C_PRELOW)
+               rreg--;
+       if (reg == OCI2C_PRELOW || reg == OCI2C_PREHIGH) {
+               curr = ioread32be(i2c->base + (rreg << i2c->reg_shift));
+               if (reg == OCI2C_PRELOW)
+                       wr = (curr & 0xff00) | value;
+               else
+                       wr = (((u32)value) << 8) | (curr & 0xff);
+       } else {
+               wr = value;
+       }
+       iowrite32be(wr, i2c->base + (rreg << i2c->reg_shift));
+}
+
 static void ocores_process(struct ocores_i2c *i2c)
 {
        struct i2c_msg *msg = i2c->msg;
@@ -241,6 +278,7 @@ static int ocores_i2c_of_probe(struct platform_device *pdev,
 {
        struct device_node *np = pdev->dev.of_node;
        u32 val;
+       const char *name;
 
        if (of_property_read_u32(np, "reg-shift", &i2c->reg_shift)) {
                /* no 'reg-shift', check for deprecated 'regstep' */
@@ -265,6 +303,15 @@ static int ocores_i2c_of_probe(struct platform_device 
*pdev,
 
        of_property_read_u32(pdev->dev.of_node, "reg-io-width",
                                &i2c->reg_io_width);
+
+       name = of_get_property(pdev->dev.of_node, "name", NULL);
+       if (name && (!strcmp(name, "GAISLER_I2CMST") ||
+                    !strcmp(name, "01_028"))) {
+               dev_dbg(&pdev->dev, "GRLIB variant of i2c-ocores\n");
+               i2c->setreg = oc_setreg_grlib;
+               i2c->getreg = oc_getreg_grlib;
+       }
+
        return 0;
 }
 #else
-- 
1.7.0.4

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to