]> git.sur5r.net Git - u-boot/blobdiff - drivers/i2c/mvtwsi.c
net: mvneta: zero Tx descriptors on init
[u-boot] / drivers / i2c / mvtwsi.c
index ab7481a0d4a9ec80e6d3e792715679b893270424..74ac0a4aa78976487f8314ec7c531a7f781d9299 100644 (file)
@@ -1,17 +1,17 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Driver for the TWSI (i2c) controller found on the Marvell
  * orion5x and kirkwood SoC families.
  *
  * Author: Albert Aribaud <albert.u.boot@aribaud.net>
  * Copyright (c) 2010 Albert Aribaud.
- *
- * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
 #include <i2c.h>
-#include <asm/errno.h>
+#include <linux/errno.h>
 #include <asm/io.h>
+#include <linux/bitops.h>
 #include <linux/compat.h>
 #ifdef CONFIG_DM_I2C
 #include <dm.h>
@@ -29,18 +29,26 @@ DECLARE_GLOBAL_DATA_PTR;
 #include <asm/arch/orion5x.h>
 #elif (defined(CONFIG_KIRKWOOD) || defined(CONFIG_ARCH_MVEBU))
 #include <asm/arch/soc.h>
-#elif defined(CONFIG_SUNXI)
+#elif defined(CONFIG_ARCH_SUNXI)
 #include <asm/arch/i2c.h>
 #else
 #error Driver mvtwsi not supported by SoC or board
 #endif
 #endif /* CONFIG_DM_I2C */
 
+/*
+ * On SUNXI, we get CONFIG_SYS_TCLK from this include, so we want to
+ * always have it.
+ */
+#if defined(CONFIG_DM_I2C) && defined(CONFIG_ARCH_SUNXI)
+#include <asm/arch/i2c.h>
+#endif
+
 /*
  * TWSI register structure
  */
 
-#ifdef CONFIG_SUNXI
+#ifdef CONFIG_ARCH_SUNXI
 
 struct  mvtwsi_registers {
        u32 slave_address;
@@ -50,6 +58,7 @@ struct  mvtwsi_registers {
        u32 status;
        u32 baudrate;
        u32 soft_reset;
+       u32 debug; /* Dummy field for build compatibility with mvebu */
 };
 
 #else
@@ -63,8 +72,10 @@ struct  mvtwsi_registers {
                u32 baudrate;   /* When writing */
        };
        u32 xtnd_slave_addr;
-       u32 reserved[2];
+       u32 reserved0[2];
        u32 soft_reset;
+       u32 reserved1[27];
+       u32 debug;
 };
 
 #endif
@@ -399,7 +410,7 @@ static int twsi_stop(struct mvtwsi_registers *twsi, uint tick)
  */
 static uint twsi_calc_freq(const int n, const int m)
 {
-#ifdef CONFIG_SUNXI
+#ifdef CONFIG_ARCH_SUNXI
        return CONFIG_SYS_TCLK / (10 * (m + 1) * (1 << n));
 #else
        return CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n));
@@ -479,10 +490,14 @@ static uint __twsi_i2c_set_bus_speed(struct mvtwsi_registers *twsi,
 static void __twsi_i2c_init(struct mvtwsi_registers *twsi, int speed,
                            int slaveadd, uint *actual_speed)
 {
+       uint tmp_speed;
+
        /* Reset controller */
        twsi_reset(twsi);
        /* Set speed */
-       *actual_speed = __twsi_i2c_set_bus_speed(twsi, speed);
+       tmp_speed = __twsi_i2c_set_bus_speed(twsi, speed);
+       if (actual_speed)
+               *actual_speed = tmp_speed;
        /* Set slave address; even though we don't use it */
        writel(slaveadd, &twsi->slave_address);
        writel(0, &twsi->xtnd_slave_addr);
@@ -595,7 +610,7 @@ static int __twsi_i2c_read(struct mvtwsi_registers *twsi, uchar chip,
                status = i2c_begin(twsi, expected_start, (chip << 1), tick);
                /* Send address bytes */
                while ((status == 0) && alen--)
-                       status = twsi_send(twsi, *(addr++),
+                       status = twsi_send(twsi, addr[alen],
                                           MVTWSI_STATUS_DATA_W_ACK, tick);
                /* Send repeated STARTs after the initial START */
                expected_start = MVTWSI_STATUS_REPEATED_START;
@@ -642,7 +657,7 @@ static int __twsi_i2c_write(struct mvtwsi_registers *twsi, uchar chip,
        status = i2c_begin(twsi, MVTWSI_STATUS_START, (chip << 1), tick);
        /* Send address bytes */
        while ((status == 0) && (alen-- > 0))
-               status = twsi_send(twsi, *(addr++), MVTWSI_STATUS_DATA_W_ACK,
+               status = twsi_send(twsi, addr[alen], MVTWSI_STATUS_DATA_W_ACK,
                                   tick);
        /* Send data bytes */
        while ((status == 0) && (length-- > 0))
@@ -770,20 +785,37 @@ static int mvtwsi_i2c_ofdata_to_platdata(struct udevice *bus)
 {
        struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
 
-       dev->base = dev_get_addr_ptr(bus);
+       dev->base = devfdt_get_addr_ptr(bus);
 
        if (!dev->base)
                return -ENOMEM;
 
-       dev->index = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+       dev->index = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
                                    "cell-index", -1);
-       dev->slaveadd = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+       dev->slaveadd = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
                                       "u-boot,i2c-slave-addr", 0x0);
-       dev->speed = fdtdec_get_int(gd->fdt_blob, bus->of_offset,
+       dev->speed = fdtdec_get_int(gd->fdt_blob, dev_of_offset(bus),
                                    "clock-frequency", 100000);
        return 0;
 }
 
+static void twsi_disable_i2c_slave(struct mvtwsi_registers *twsi)
+{
+       clrbits_le32(&twsi->debug, BIT(18));
+}
+
+static int mvtwsi_i2c_bind(struct udevice *bus)
+{
+       struct mvtwsi_registers *twsi = devfdt_get_addr_ptr(bus);
+
+       /* Disable the hidden slave in i2c0 of these platforms */
+       if ((IS_ENABLED(CONFIG_ARMADA_38X) || IS_ENABLED(CONFIG_KIRKWOOD))
+                       && bus->req_seq == 0)
+               twsi_disable_i2c_slave(twsi);
+
+       return 0;
+}
+
 static int mvtwsi_i2c_probe(struct udevice *bus)
 {
        struct mvtwsi_i2c_dev *dev = dev_get_priv(bus);
@@ -830,6 +862,8 @@ static const struct dm_i2c_ops mvtwsi_i2c_ops = {
 
 static const struct udevice_id mvtwsi_i2c_ids[] = {
        { .compatible = "marvell,mv64xxx-i2c", },
+       { .compatible = "marvell,mv78230-i2c", },
+       { .compatible = "allwinner,sun6i-a31-i2c", },
        { /* sentinel */ }
 };
 
@@ -837,6 +871,7 @@ U_BOOT_DRIVER(i2c_mvtwsi) = {
        .name = "i2c_mvtwsi",
        .id = UCLASS_I2C,
        .of_match = mvtwsi_i2c_ids,
+       .bind = mvtwsi_i2c_bind,
        .probe = mvtwsi_i2c_probe,
        .ofdata_to_platdata = mvtwsi_i2c_ofdata_to_platdata,
        .priv_auto_alloc_size = sizeof(struct mvtwsi_i2c_dev),