public inbox for u-boot@lists.denx.de
 help / color / mirror / Atom feed
* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
@ 2015-12-28 17:47 Moritz Fischer
  2015-12-28 17:47 ` [U-Boot] [RFC 1/2] i2c: Describe Cadence I2C devicetree bindings Moritz Fischer
                   ` (3 more replies)
  0 siblings, 4 replies; 15+ messages in thread
From: Moritz Fischer @ 2015-12-28 17:47 UTC (permalink / raw)
  To: u-boot

Hi all,

I spent some time moving over the zynq-i2c.c to support dm.
While doing that I realized that renaming it to cdns-i2c might
make sense since it now could be used with other SoCs that also use the
the Cadence IP.

This is a first shot, but I'd like to get some early feedback ;-)

Cheers,

    Moritz

PS: I skipped touching the Zynq board files for now, since I wanted to make sure
I get the driver right first ;-)

Moritz Fischer (2):
  i2c: Describe Cadence I2C devicetree bindings
  dm: i2c: Add driver for Cadence I2C IP

 doc/device-tree-bindings/i2c/i2c-cdns.txt |  20 ++
 drivers/i2c/Kconfig                       |   7 +
 drivers/i2c/Makefile                      |   1 +
 drivers/i2c/i2c-cdns.c                    | 339 ++++++++++++++++++++++++++++++
 4 files changed, 367 insertions(+)
 create mode 100644 doc/device-tree-bindings/i2c/i2c-cdns.txt
 create mode 100644 drivers/i2c/i2c-cdns.c

-- 
2.4.3

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 1/2] i2c: Describe Cadence I2C devicetree bindings
  2015-12-28 17:47 [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Moritz Fischer
@ 2015-12-28 17:47 ` Moritz Fischer
  2016-01-04  7:09   ` Heiko Schocher
  2015-12-28 17:47 ` [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP Moritz Fischer
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 15+ messages in thread
From: Moritz Fischer @ 2015-12-28 17:47 UTC (permalink / raw)
  To: u-boot

Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
---
 doc/device-tree-bindings/i2c/i2c-cdns.txt | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 doc/device-tree-bindings/i2c/i2c-cdns.txt

diff --git a/doc/device-tree-bindings/i2c/i2c-cdns.txt b/doc/device-tree-bindings/i2c/i2c-cdns.txt
new file mode 100644
index 0000000..202e0b7
--- /dev/null
+++ b/doc/device-tree-bindings/i2c/i2c-cdns.txt
@@ -0,0 +1,20 @@
+Cadence I2C controller Device Tree Bindings
+-------------------------------------------
+
+Required properties:
+- compatible		: Should be "cdns,i2c-r1p10" or "xlnx,zynq-spi-r1p10".
+- reg			: Physical base address and size of I2C registers map.
+- interrupts		: Property with a value describing the interrupt
+			  number.
+- interrupt-parent	: Must be core interrupt controller
+- clocks		: Clock phandles (see clock bindings for details).
+
+Example:
+	i2c0: i2c at e0004000 {
+		compatible = "cdns,i2c-r1p10";
+		reg = <0xe0004000 0x1000>;
+		clocks = <&clkc 38>;
+		interrupts = <0 25 4>;
+		interrupt-parent = <&intc>;
+		status = "disabled";
+	};
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP
  2015-12-28 17:47 [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Moritz Fischer
  2015-12-28 17:47 ` [U-Boot] [RFC 1/2] i2c: Describe Cadence I2C devicetree bindings Moritz Fischer
@ 2015-12-28 17:47 ` Moritz Fischer
  2016-01-04  7:15   ` Heiko Schocher
  2015-12-28 18:35 ` [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Michal Simek
  2016-01-05 15:44 ` Michal Simek
  3 siblings, 1 reply; 15+ messages in thread
From: Moritz Fischer @ 2015-12-28 17:47 UTC (permalink / raw)
  To: u-boot

This is a possible drop in replacement for drivers/i2c/zynq-i2c.c

Since this is cadence IP it has been renamed to cdns-i2c,
to make sense with the compatible string.

Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
---
 drivers/i2c/Kconfig    |   7 +
 drivers/i2c/Makefile   |   1 +
 drivers/i2c/i2c-cdns.c | 339 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 347 insertions(+)
 create mode 100644 drivers/i2c/i2c-cdns.c

diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index 14adda2..c058dc5 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -58,6 +58,13 @@ config DM_I2C_GPIO
 	  bindings are supported.
 	  Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt
 
+config SYS_I2C_CADENCE
+	tristate "Cadence I2C Controller"
+	depends on DM_I2C && (ARCH_ZYNQ || ARM64)
+	help
+	  Say yes here to select Cadence I2C Host Controller. This controller is
+	  e.g. used by Xilinx Zynq.
+
 config SYS_I2C_ROCKCHIP
 	bool "Rockchip I2C driver"
 	depends on DM_I2C
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index 811ad9b..35ad0d3 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
 obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
 obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
 obj-$(CONFIG_SYS_I2C) += i2c_core.o
+obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
 obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
 obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
 obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c
new file mode 100644
index 0000000..fab9609
--- /dev/null
+++ b/drivers/i2c/i2c-cdns.c
@@ -0,0 +1,339 @@
+/*
+ * Copyright (C) 2015 Moritz Fischer <moritz.fischer@ettus.com>
+ * IP from Cadence (ID T-CS-PE-0007-100, Version R1p10f2)
+ *
+ * This file is based on: drivers/i2c/zynq_i2c.c,
+ * with added driver-model support and code cleanup.
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/types.h>
+#include <linux/io.h>
+#include <asm/errno.h>
+#include <dm/device.h>
+#include <dm/root.h>
+#include <i2c.h>
+#include <fdtdec.h>
+#include <mapmem.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+/* i2c register set */
+struct cdns_i2c_regs {
+	u32 control;
+	u32 status;
+	u32 address;
+	u32 data;
+	u32 interrupt_status;
+	u32 transfer_size;
+	u32 slave_mon_pause;
+	u32 time_out;
+	u32 interrupt_mask;
+	u32 interrupt_enable;
+	u32 interrupt_disable;
+};
+
+/* Control register fields */
+#define CDNS_I2C_CONTROL_RW		0x00000001
+#define CDNS_I2C_CONTROL_MS		0x00000002
+#define CDNS_I2C_CONTROL_NEA		0x00000004
+#define CDNS_I2C_CONTROL_ACKEN		0x00000008
+#define CDNS_I2C_CONTROL_HOLD		0x00000010
+#define CDNS_I2C_CONTROL_SLVMON		0x00000020
+#define CDNS_I2C_CONTROL_CLR_FIFO	0x00000040
+#define CDNS_I2C_CONTROL_DIV_B_SHIFT	8
+#define CDNS_I2C_CONTROL_DIV_B_MASK	0x00003F00
+#define CDNS_I2C_CONTROL_DIV_A_SHIFT	14
+#define CDNS_I2C_CONTROL_DIV_A_MASK	0x0000C000
+
+/* Status register values */
+#define CDNS_I2C_STATUS_RXDV	0x00000020
+#define CDNS_I2C_STATUS_TXDV	0x00000040
+#define CDNS_I2C_STATUS_RXOVF	0x00000080
+#define CDNS_I2C_STATUS_BA	0x00000100
+
+/* Interrupt register fields */
+#define CDNS_I2C_INTERRUPT_COMP		0x00000001
+#define CDNS_I2C_INTERRUPT_DATA		0x00000002
+#define CDNS_I2C_INTERRUPT_NACK		0x00000004
+#define CDNS_I2C_INTERRUPT_TO		0x00000008
+#define CDNS_I2C_INTERRUPT_SLVRDY	0x00000010
+#define CDNS_I2C_INTERRUPT_RXOVF	0x00000020
+#define CDNS_I2C_INTERRUPT_TXOVF	0x00000040
+#define CDNS_I2C_INTERRUPT_RXUNF	0x00000080
+#define CDNS_I2C_INTERRUPT_ARBLOST	0x00000200
+
+#define CDNS_I2C_FIFO_DEPTH		16
+#define CDNS_I2C_TRANSFER_SIZE_MAX	255 /* Controller transfer limit */
+
+#ifdef DEBUG
+static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c)
+{
+	int int_status;
+	int status;
+	int_status = readl(&cdns_i2c->interrupt_status);
+
+	status = readl(&cdns_i2c->status);
+	if (int_status || status) {
+		debug("Status: ");
+		if (int_status & CDNS_I2C_INTERRUPT_COMP)
+			debug("COMP ");
+		if (int_status & CDNS_I2C_INTERRUPT_DATA)
+			debug("DATA ");
+		if (int_status & CDNS_I2C_INTERRUPT_NACK)
+			debug("NACK ");
+		if (int_status & CDNS_I2C_INTERRUPT_TO)
+			debug("TO ");
+		if (int_status & CDNS_I2C_INTERRUPT_SLVRDY)
+			debug("SLVRDY ");
+		if (int_status & CDNS_I2C_INTERRUPT_RXOVF)
+			debug("RXOVF ");
+		if (int_status & CDNS_I2C_INTERRUPT_TXOVF)
+			debug("TXOVF ");
+		if (int_status & CDNS_I2C_INTERRUPT_RXUNF)
+			debug("RXUNF ");
+		if (int_status & CDNS_I2C_INTERRUPT_ARBLOST)
+			debug("ARBLOST ");
+		if (status & CDNS_I2C_STATUS_RXDV)
+			debug("RXDV ");
+		if (status & CDNS_I2C_STATUS_TXDV)
+			debug("TXDV ");
+		if (status & CDNS_I2C_STATUS_RXOVF)
+			debug("RXOVF ");
+		if (status & CDNS_I2C_STATUS_BA)
+			debug("BA ");
+		debug("TS%d ", readl(&cdns_i2c->transfer_size));
+		debug("\n");
+	}
+}
+#endif
+
+struct i2c_cdns_bus {
+	int id;
+	struct cdns_i2c_regs __iomem *regs;	/* register base */
+};
+
+
+/** cdns_i2c_probe() - Probe method
+ * @dev: udevice pointer
+ *
+ * DM callback called when device is probed
+ */
+static int cdns_i2c_probe(struct udevice *dev)
+{
+	struct i2c_cdns_bus *bus = dev_get_priv(dev);
+	fdt_addr_t addr;
+	fdt_size_t size;
+
+	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
+	bus->regs = map_sysmem(addr, size);
+
+	if (!bus->regs)
+		return -ENOMEM;
+
+	/* TODO: Calculate dividers based on CPU_CLK_1X */
+	/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */
+	writel((16 << CDNS_I2C_CONTROL_DIV_B_SHIFT) |
+		(2 << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control);
+
+	/* Enable master mode, ack, and 7-bit addressing */
+	setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS |
+		CDNS_I2C_CONTROL_ACKEN | CDNS_I2C_CONTROL_NEA);
+
+	debug("%s bus %d at %p\n", __func__, dev->seq, bus->regs);
+
+	return 0;
+}
+
+static int cdns_i2c_remove(struct udevice *dev)
+{
+	struct i2c_cdns_bus *bus = dev_get_priv(dev);
+
+	debug("%s bus %d at %p\n", __func__, dev->seq, bus->regs);
+
+	unmap_sysmem(bus->regs);
+
+	return 0;
+}
+
+/* Wait for an interrupt */
+static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask)
+{
+	int timeout, int_status;
+
+	for (timeout = 0; timeout < 100; timeout++) {
+		udelay(100);
+		int_status = readl(&cdns_i2c->interrupt_status);
+		if (int_status & mask)
+			break;
+	}
+
+	/* Clear interrupt status flags */
+	writel(int_status & mask, &cdns_i2c->interrupt_status);
+
+	return int_status & mask;
+}
+
+static int cdns_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
+{
+	if (speed != 100000) {
+		printf("%s, failed to set clock speed to %u\n", __func__,
+		       speed);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Probe to see if a chip is present. */
+static int cdns_i2c_probe_chip(struct udevice *bus, uint chip_addr,
+				uint chip_flags)
+{
+	struct i2c_cdns_bus *i2c_bus = dev_get_priv(bus);
+	struct cdns_i2c_regs *regs = i2c_bus->regs;
+
+	/* Attempt to read a byte */
+	setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO |
+		CDNS_I2C_CONTROL_RW);
+	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
+	writel(0xFF, &regs->interrupt_status);
+	writel(chip_addr, &regs->address);
+	writel(1, &regs->transfer_size);
+
+	return (cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
+		CDNS_I2C_INTERRUPT_NACK) &
+		CDNS_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT;
+}
+
+static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
+			       u32 len, bool next_is_read)
+{
+	u8 *cur_data = data;
+
+	struct cdns_i2c_regs *regs = i2c_bus->regs;
+
+	setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO |
+		CDNS_I2C_CONTROL_HOLD);
+
+	/* if next is a read, we need to clear HOLD, doesn't work */
+	if (next_is_read)
+		clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
+
+	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_RW);
+
+	writel(0xFF, &regs->interrupt_status);
+	writel(addr, &regs->address);
+
+	while (len--) {
+		writel(*(cur_data++), &regs->data);
+		if (readl(&regs->transfer_size) == CDNS_I2C_FIFO_DEPTH) {
+			if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP)) {
+				/* Release the bus */
+				clrbits_le32(&regs->control,
+					     CDNS_I2C_CONTROL_HOLD);
+				return -ETIMEDOUT;
+			}
+		}
+	}
+
+	/* All done... release the bus */
+	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
+	/* Wait for the address and data to be sent */
+	if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP))
+		return -ETIMEDOUT;
+	return 0;
+}
+
+static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
+			      u32 len)
+{
+	u32 status;
+	u32 i = 0;
+	u8 *cur_data = data;
+
+	/* TODO: Fix this */
+	struct cdns_i2c_regs *regs = i2c_bus->regs;
+
+	/* Check the hardware can handle the requested bytes */
+	if ((len < 0) || (len > CDNS_I2C_TRANSFER_SIZE_MAX))
+		return -EINVAL;
+
+	setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO |
+		CDNS_I2C_CONTROL_RW);
+
+	/* Start reading data */
+	writel(addr, &regs->address);
+	writel(len, &regs->transfer_size);
+
+	/* Wait for data */
+	do {
+		status = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
+			CDNS_I2C_INTERRUPT_DATA);
+		if (!status) {
+			/* Release the bus */
+			clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
+			return -ETIMEDOUT;
+		}
+		debug("Read %d bytes\n",
+		      len - readl(&regs->transfer_size));
+		for (; i < len - readl(&regs->transfer_size); i++)
+			*(cur_data++) = readl(&regs->data);
+	} while (readl(&regs->transfer_size) != 0);
+	/* All done... release the bus */
+	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
+
+#ifdef DEBUG
+	cdns_i2c_debug_status(regs);
+#endif
+	return 0;
+}
+
+static int cdns_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
+			 int nmsgs)
+{
+	struct i2c_cdns_bus *i2c_bus = dev_get_priv(dev);
+	int ret;
+
+	debug("i2c_xfer: %d messages\n", nmsgs);
+	for (; nmsgs > 0; nmsgs--, msg++) {
+		bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
+
+		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
+		if (msg->flags & I2C_M_RD) {
+			ret = cdns_i2c_read_data(i2c_bus, msg->addr, msg->buf,
+						 msg->len);
+		} else {
+			ret = cdns_i2c_write_data(i2c_bus, msg->addr, msg->buf,
+						  msg->len, next_is_read);
+		}
+		if (ret) {
+			debug("i2c_write: error sending\n");
+			return -EREMOTEIO;
+		}
+	}
+
+	return 0;
+}
+
+static const struct dm_i2c_ops cdns_i2c_ops = {
+	.xfer = cdns_i2c_xfer,
+	.probe_chip	= cdns_i2c_probe_chip,
+	.set_bus_speed = cdns_i2c_set_bus_speed,
+};
+
+static const struct udevice_id cdns_i2c_of_match[] = {
+	{ .compatible = "cdns,i2c-r1p10" },
+	{ /* end of table */ }
+};
+
+U_BOOT_DRIVER(cdns_i2c) = {
+	.name = "i2c-cdns",
+	.id = UCLASS_I2C,
+	.of_match = cdns_i2c_of_match,
+	.probe = cdns_i2c_probe,
+	.remove = cdns_i2c_remove,
+	.priv_auto_alloc_size = sizeof(struct i2c_cdns_bus),
+	.ops = &cdns_i2c_ops,
+};
-- 
2.4.3

^ permalink raw reply related	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
  2015-12-28 17:47 [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Moritz Fischer
  2015-12-28 17:47 ` [U-Boot] [RFC 1/2] i2c: Describe Cadence I2C devicetree bindings Moritz Fischer
  2015-12-28 17:47 ` [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP Moritz Fischer
@ 2015-12-28 18:35 ` Michal Simek
  2015-12-28 19:15   ` Moritz Fischer
  2016-01-05 15:44 ` Michal Simek
  3 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2015-12-28 18:35 UTC (permalink / raw)
  To: u-boot

Hi,

2015-12-28 18:47 GMT+01:00 Moritz Fischer <moritz.fischer@ettus.com>:

> Hi all,
>
> I spent some time moving over the zynq-i2c.c to support dm.
>

ok then where is the series for converting orgin driver to this DM one?


> While doing that I realized that renaming it to cdns-i2c might
> make sense since it now could be used with other SoCs that also use the
> the Cadence IP.
>

No problem with renaming but I would like to see change from origin driver
to this new one
instead of just adding completely new one and keeping old one there.



> This is a first shot, but I'd like to get some early feedback ;-)
>

I will look at it and test it in January.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
  2015-12-28 18:35 ` [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Michal Simek
@ 2015-12-28 19:15   ` Moritz Fischer
  0 siblings, 0 replies; 15+ messages in thread
From: Moritz Fischer @ 2015-12-28 19:15 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Mon, Dec 28, 2015 at 10:35 AM, Michal Simek <monstr@monstr.eu> wrote:

> ok then where is the series for converting orgin driver to this DM one?

Umhh, well it would look like:

$ git rm drivers/i2c/zynq-i2c.c
$ git add drivers/i2c/i2c-cdns.c

Do you want me to add that to the v1?

> No problem with renaming but I would like to see change from origin driver
> to this new one
> instead of just adding completely new one and keeping old one there.

See above. To clarify you mean I should also add the edits to convert the actual
zynq boards over? I need to take a look which ones actually use i2c.

> I will look at it and test it in January.

Thanks.

Cheers,

Moritz

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 1/2] i2c: Describe Cadence I2C devicetree bindings
  2015-12-28 17:47 ` [U-Boot] [RFC 1/2] i2c: Describe Cadence I2C devicetree bindings Moritz Fischer
@ 2016-01-04  7:09   ` Heiko Schocher
  0 siblings, 0 replies; 15+ messages in thread
From: Heiko Schocher @ 2016-01-04  7:09 UTC (permalink / raw)
  To: u-boot

Hello Moritz,

Am 28.12.2015 um 18:47 schrieb Moritz Fischer:
> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
> ---
>   doc/device-tree-bindings/i2c/i2c-cdns.txt | 20 ++++++++++++++++++++
>   1 file changed, 20 insertions(+)
>   create mode 100644 doc/device-tree-bindings/i2c/i2c-cdns.txt

Looks good to me:
Acked-by: Heiko Schocher <hs@denx.de>

bye,
Heiko
>
> diff --git a/doc/device-tree-bindings/i2c/i2c-cdns.txt b/doc/device-tree-bindings/i2c/i2c-cdns.txt
> new file mode 100644
> index 0000000..202e0b7
> --- /dev/null
> +++ b/doc/device-tree-bindings/i2c/i2c-cdns.txt
> @@ -0,0 +1,20 @@
> +Cadence I2C controller Device Tree Bindings
> +-------------------------------------------
> +
> +Required properties:
> +- compatible		: Should be "cdns,i2c-r1p10" or "xlnx,zynq-spi-r1p10".
> +- reg			: Physical base address and size of I2C registers map.
> +- interrupts		: Property with a value describing the interrupt
> +			  number.
> +- interrupt-parent	: Must be core interrupt controller
> +- clocks		: Clock phandles (see clock bindings for details).
> +
> +Example:
> +	i2c0: i2c at e0004000 {
> +		compatible = "cdns,i2c-r1p10";
> +		reg = <0xe0004000 0x1000>;
> +		clocks = <&clkc 38>;
> +		interrupts = <0 25 4>;
> +		interrupt-parent = <&intc>;
> +		status = "disabled";
> +	};
>

-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP
  2015-12-28 17:47 ` [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP Moritz Fischer
@ 2016-01-04  7:15   ` Heiko Schocher
  2016-04-11 12:50     ` Michal Simek
  0 siblings, 1 reply; 15+ messages in thread
From: Heiko Schocher @ 2016-01-04  7:15 UTC (permalink / raw)
  To: u-boot

Hello Moritz,

Am 28.12.2015 um 18:47 schrieb Moritz Fischer:
> This is a possible drop in replacement for drivers/i2c/zynq-i2c.c
>
> Since this is cadence IP it has been renamed to cdns-i2c,
> to make sense with the compatible string.
>
> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
> ---
>   drivers/i2c/Kconfig    |   7 +
>   drivers/i2c/Makefile   |   1 +
>   drivers/i2c/i2c-cdns.c | 339 +++++++++++++++++++++++++++++++++++++++++++++++++
>   3 files changed, 347 insertions(+)
>   create mode 100644 drivers/i2c/i2c-cdns.c

Hmm.. I di not see the remove of "drivers/i2c/zynq-i2c.c" as
you wrote it is a replacement for it ... Can you do this, and
of course adapt the boards which use this driver?

> diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
> index 14adda2..c058dc5 100644
> --- a/drivers/i2c/Kconfig
> +++ b/drivers/i2c/Kconfig
> @@ -58,6 +58,13 @@ config DM_I2C_GPIO
>   	  bindings are supported.
>   	  Binding info: doc/device-tree-bindings/i2c/i2c-gpio.txt
>
> +config SYS_I2C_CADENCE
> +	tristate "Cadence I2C Controller"
> +	depends on DM_I2C && (ARCH_ZYNQ || ARM64)
> +	help
> +	  Say yes here to select Cadence I2C Host Controller. This controller is
> +	  e.g. used by Xilinx Zynq.
> +
>   config SYS_I2C_ROCKCHIP
>   	bool "Rockchip I2C driver"
>   	depends on DM_I2C
> diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
> index 811ad9b..35ad0d3 100644
> --- a/drivers/i2c/Makefile
> +++ b/drivers/i2c/Makefile
> @@ -16,6 +16,7 @@ obj-$(CONFIG_PCA9564_I2C) += pca9564_i2c.o
>   obj-$(CONFIG_TSI108_I2C) += tsi108_i2c.o
>   obj-$(CONFIG_SH_SH7734_I2C) += sh_sh7734_i2c.o
>   obj-$(CONFIG_SYS_I2C) += i2c_core.o
> +obj-$(CONFIG_SYS_I2C_CADENCE) += i2c-cdns.o
>   obj-$(CONFIG_SYS_I2C_DAVINCI) += davinci_i2c.o
>   obj-$(CONFIG_SYS_I2C_DW) += designware_i2c.o
>   obj-$(CONFIG_SYS_I2C_FSL) += fsl_i2c.o
> diff --git a/drivers/i2c/i2c-cdns.c b/drivers/i2c/i2c-cdns.c
> new file mode 100644
> index 0000000..fab9609
> --- /dev/null
> +++ b/drivers/i2c/i2c-cdns.c
> @@ -0,0 +1,339 @@
> +/*
> + * Copyright (C) 2015 Moritz Fischer <moritz.fischer@ettus.com>
> + * IP from Cadence (ID T-CS-PE-0007-100, Version R1p10f2)
> + *
> + * This file is based on: drivers/i2c/zynq_i2c.c,
> + * with added driver-model support and code cleanup.
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <linux/types.h>
> +#include <linux/io.h>
> +#include <asm/errno.h>
> +#include <dm/device.h>
> +#include <dm/root.h>
> +#include <i2c.h>
> +#include <fdtdec.h>
> +#include <mapmem.h>
> +
> +DECLARE_GLOBAL_DATA_PTR;
> +
> +/* i2c register set */
> +struct cdns_i2c_regs {
> +	u32 control;
> +	u32 status;
> +	u32 address;
> +	u32 data;
> +	u32 interrupt_status;
> +	u32 transfer_size;
> +	u32 slave_mon_pause;
> +	u32 time_out;
> +	u32 interrupt_mask;
> +	u32 interrupt_enable;
> +	u32 interrupt_disable;
> +};
> +
> +/* Control register fields */
> +#define CDNS_I2C_CONTROL_RW		0x00000001
> +#define CDNS_I2C_CONTROL_MS		0x00000002
> +#define CDNS_I2C_CONTROL_NEA		0x00000004
> +#define CDNS_I2C_CONTROL_ACKEN		0x00000008
> +#define CDNS_I2C_CONTROL_HOLD		0x00000010
> +#define CDNS_I2C_CONTROL_SLVMON		0x00000020
> +#define CDNS_I2C_CONTROL_CLR_FIFO	0x00000040
> +#define CDNS_I2C_CONTROL_DIV_B_SHIFT	8
> +#define CDNS_I2C_CONTROL_DIV_B_MASK	0x00003F00
> +#define CDNS_I2C_CONTROL_DIV_A_SHIFT	14
> +#define CDNS_I2C_CONTROL_DIV_A_MASK	0x0000C000
> +
> +/* Status register values */
> +#define CDNS_I2C_STATUS_RXDV	0x00000020
> +#define CDNS_I2C_STATUS_TXDV	0x00000040
> +#define CDNS_I2C_STATUS_RXOVF	0x00000080
> +#define CDNS_I2C_STATUS_BA	0x00000100
> +
> +/* Interrupt register fields */
> +#define CDNS_I2C_INTERRUPT_COMP		0x00000001
> +#define CDNS_I2C_INTERRUPT_DATA		0x00000002
> +#define CDNS_I2C_INTERRUPT_NACK		0x00000004
> +#define CDNS_I2C_INTERRUPT_TO		0x00000008
> +#define CDNS_I2C_INTERRUPT_SLVRDY	0x00000010
> +#define CDNS_I2C_INTERRUPT_RXOVF	0x00000020
> +#define CDNS_I2C_INTERRUPT_TXOVF	0x00000040
> +#define CDNS_I2C_INTERRUPT_RXUNF	0x00000080
> +#define CDNS_I2C_INTERRUPT_ARBLOST	0x00000200
> +
> +#define CDNS_I2C_FIFO_DEPTH		16
> +#define CDNS_I2C_TRANSFER_SIZE_MAX	255 /* Controller transfer limit */
> +
> +#ifdef DEBUG
> +static void cdns_i2c_debug_status(struct cdns_i2c_regs *cdns_i2c)
> +{
> +	int int_status;
> +	int status;
> +	int_status = readl(&cdns_i2c->interrupt_status);
> +
> +	status = readl(&cdns_i2c->status);
> +	if (int_status || status) {
> +		debug("Status: ");
> +		if (int_status & CDNS_I2C_INTERRUPT_COMP)
> +			debug("COMP ");
> +		if (int_status & CDNS_I2C_INTERRUPT_DATA)
> +			debug("DATA ");
> +		if (int_status & CDNS_I2C_INTERRUPT_NACK)
> +			debug("NACK ");
> +		if (int_status & CDNS_I2C_INTERRUPT_TO)
> +			debug("TO ");
> +		if (int_status & CDNS_I2C_INTERRUPT_SLVRDY)
> +			debug("SLVRDY ");
> +		if (int_status & CDNS_I2C_INTERRUPT_RXOVF)
> +			debug("RXOVF ");
> +		if (int_status & CDNS_I2C_INTERRUPT_TXOVF)
> +			debug("TXOVF ");
> +		if (int_status & CDNS_I2C_INTERRUPT_RXUNF)
> +			debug("RXUNF ");
> +		if (int_status & CDNS_I2C_INTERRUPT_ARBLOST)
> +			debug("ARBLOST ");
> +		if (status & CDNS_I2C_STATUS_RXDV)
> +			debug("RXDV ");
> +		if (status & CDNS_I2C_STATUS_TXDV)
> +			debug("TXDV ");
> +		if (status & CDNS_I2C_STATUS_RXOVF)
> +			debug("RXOVF ");
> +		if (status & CDNS_I2C_STATUS_BA)
> +			debug("BA ");
> +		debug("TS%d ", readl(&cdns_i2c->transfer_size));
> +		debug("\n");
> +	}
> +}
> +#endif
> +
> +struct i2c_cdns_bus {
> +	int id;
> +	struct cdns_i2c_regs __iomem *regs;	/* register base */
> +};
> +
> +
> +/** cdns_i2c_probe() - Probe method
> + * @dev: udevice pointer
> + *
> + * DM callback called when device is probed
> + */
> +static int cdns_i2c_probe(struct udevice *dev)
> +{
> +	struct i2c_cdns_bus *bus = dev_get_priv(dev);
> +	fdt_addr_t addr;
> +	fdt_size_t size;
> +
> +	addr = fdtdec_get_addr_size(gd->fdt_blob, dev->of_offset, "reg", &size);
> +	bus->regs = map_sysmem(addr, size);
> +
> +	if (!bus->regs)
> +		return -ENOMEM;
> +
> +	/* TODO: Calculate dividers based on CPU_CLK_1X */
> +	/* 111MHz / ( (3 * 17) * 22 ) = ~100KHz */
> +	writel((16 << CDNS_I2C_CONTROL_DIV_B_SHIFT) |
> +		(2 << CDNS_I2C_CONTROL_DIV_A_SHIFT), &bus->regs->control);

We really need a clk framework ...

> +
> +	/* Enable master mode, ack, and 7-bit addressing */
> +	setbits_le32(&bus->regs->control, CDNS_I2C_CONTROL_MS |
> +		CDNS_I2C_CONTROL_ACKEN | CDNS_I2C_CONTROL_NEA);
> +
> +	debug("%s bus %d at %p\n", __func__, dev->seq, bus->regs);
> +
> +	return 0;
> +}
> +
> +static int cdns_i2c_remove(struct udevice *dev)
> +{
> +	struct i2c_cdns_bus *bus = dev_get_priv(dev);
> +
> +	debug("%s bus %d at %p\n", __func__, dev->seq, bus->regs);
> +
> +	unmap_sysmem(bus->regs);
> +
> +	return 0;
> +}
> +
> +/* Wait for an interrupt */
> +static u32 cdns_i2c_wait(struct cdns_i2c_regs *cdns_i2c, u32 mask)
> +{
> +	int timeout, int_status;
> +
> +	for (timeout = 0; timeout < 100; timeout++) {
> +		udelay(100);
> +		int_status = readl(&cdns_i2c->interrupt_status);
> +		if (int_status & mask)
> +			break;
> +	}
> +
> +	/* Clear interrupt status flags */
> +	writel(int_status & mask, &cdns_i2c->interrupt_status);
> +
> +	return int_status & mask;
> +}
> +
> +static int cdns_i2c_set_bus_speed(struct udevice *dev, unsigned int speed)
> +{
> +	if (speed != 100000) {
> +		printf("%s, failed to set clock speed to %u\n", __func__,
> +		       speed);
> +		return -EINVAL;
> +	}
> +
> +	return 0;
> +}
> +
> +/* Probe to see if a chip is present. */
> +static int cdns_i2c_probe_chip(struct udevice *bus, uint chip_addr,
> +				uint chip_flags)
> +{
> +	struct i2c_cdns_bus *i2c_bus = dev_get_priv(bus);
> +	struct cdns_i2c_regs *regs = i2c_bus->regs;
> +
> +	/* Attempt to read a byte */
> +	setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO |
> +		CDNS_I2C_CONTROL_RW);
> +	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
> +	writel(0xFF, &regs->interrupt_status);
> +	writel(chip_addr, &regs->address);
> +	writel(1, &regs->transfer_size);
> +
> +	return (cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
> +		CDNS_I2C_INTERRUPT_NACK) &
> +		CDNS_I2C_INTERRUPT_COMP) ? 0 : -ETIMEDOUT;
> +}
> +
> +static int cdns_i2c_write_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
> +			       u32 len, bool next_is_read)
> +{
> +	u8 *cur_data = data;
> +
> +	struct cdns_i2c_regs *regs = i2c_bus->regs;
> +
> +	setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO |
> +		CDNS_I2C_CONTROL_HOLD);
> +
> +	/* if next is a read, we need to clear HOLD, doesn't work */
> +	if (next_is_read)
> +		clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
> +
> +	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_RW);
> +
> +	writel(0xFF, &regs->interrupt_status);
> +	writel(addr, &regs->address);
> +
> +	while (len--) {
> +		writel(*(cur_data++), &regs->data);
> +		if (readl(&regs->transfer_size) == CDNS_I2C_FIFO_DEPTH) {
> +			if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP)) {
> +				/* Release the bus */
> +				clrbits_le32(&regs->control,
> +					     CDNS_I2C_CONTROL_HOLD);
> +				return -ETIMEDOUT;
> +			}
> +		}
> +	}
> +
> +	/* All done... release the bus */
> +	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
> +	/* Wait for the address and data to be sent */
> +	if (!cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP))
> +		return -ETIMEDOUT;
> +	return 0;
> +}
> +
> +static int cdns_i2c_read_data(struct i2c_cdns_bus *i2c_bus, u32 addr, u8 *data,
> +			      u32 len)
> +{
> +	u32 status;
> +	u32 i = 0;
> +	u8 *cur_data = data;
> +
> +	/* TODO: Fix this */
> +	struct cdns_i2c_regs *regs = i2c_bus->regs;
> +
> +	/* Check the hardware can handle the requested bytes */
> +	if ((len < 0) || (len > CDNS_I2C_TRANSFER_SIZE_MAX))
> +		return -EINVAL;
> +
> +	setbits_le32(&regs->control, CDNS_I2C_CONTROL_CLR_FIFO |
> +		CDNS_I2C_CONTROL_RW);
> +
> +	/* Start reading data */
> +	writel(addr, &regs->address);
> +	writel(len, &regs->transfer_size);
> +
> +	/* Wait for data */
> +	do {
> +		status = cdns_i2c_wait(regs, CDNS_I2C_INTERRUPT_COMP |
> +			CDNS_I2C_INTERRUPT_DATA);
> +		if (!status) {
> +			/* Release the bus */
> +			clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
> +			return -ETIMEDOUT;
> +		}
> +		debug("Read %d bytes\n",
> +		      len - readl(&regs->transfer_size));
> +		for (; i < len - readl(&regs->transfer_size); i++)
> +			*(cur_data++) = readl(&regs->data);
> +	} while (readl(&regs->transfer_size) != 0);
> +	/* All done... release the bus */
> +	clrbits_le32(&regs->control, CDNS_I2C_CONTROL_HOLD);
> +
> +#ifdef DEBUG
> +	cdns_i2c_debug_status(regs);
> +#endif
> +	return 0;
> +}
> +
> +static int cdns_i2c_xfer(struct udevice *dev, struct i2c_msg *msg,
> +			 int nmsgs)
> +{
> +	struct i2c_cdns_bus *i2c_bus = dev_get_priv(dev);
> +	int ret;
> +
> +	debug("i2c_xfer: %d messages\n", nmsgs);
> +	for (; nmsgs > 0; nmsgs--, msg++) {
> +		bool next_is_read = nmsgs > 1 && (msg[1].flags & I2C_M_RD);
> +
> +		debug("i2c_xfer: chip=0x%x, len=0x%x\n", msg->addr, msg->len);
> +		if (msg->flags & I2C_M_RD) {
> +			ret = cdns_i2c_read_data(i2c_bus, msg->addr, msg->buf,
> +						 msg->len);
> +		} else {
> +			ret = cdns_i2c_write_data(i2c_bus, msg->addr, msg->buf,
> +						  msg->len, next_is_read);
> +		}
> +		if (ret) {
> +			debug("i2c_write: error sending\n");
> +			return -EREMOTEIO;
> +		}
> +	}
> +
> +	return 0;
> +}
> +
> +static const struct dm_i2c_ops cdns_i2c_ops = {
> +	.xfer = cdns_i2c_xfer,
> +	.probe_chip	= cdns_i2c_probe_chip,
> +	.set_bus_speed = cdns_i2c_set_bus_speed,
> +};
> +
> +static const struct udevice_id cdns_i2c_of_match[] = {
> +	{ .compatible = "cdns,i2c-r1p10" },
> +	{ /* end of table */ }
> +};
> +
> +U_BOOT_DRIVER(cdns_i2c) = {
> +	.name = "i2c-cdns",
> +	.id = UCLASS_I2C,
> +	.of_match = cdns_i2c_of_match,
> +	.probe = cdns_i2c_probe,
> +	.remove = cdns_i2c_remove,
> +	.priv_auto_alloc_size = sizeof(struct i2c_cdns_bus),
> +	.ops = &cdns_i2c_ops,
> +};
>

Looks good to me, but I cannot test it ...

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
  2015-12-28 17:47 [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Moritz Fischer
                   ` (2 preceding siblings ...)
  2015-12-28 18:35 ` [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Michal Simek
@ 2016-01-05 15:44 ` Michal Simek
  2016-01-05 17:30   ` Moritz Fischer
  3 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2016-01-05 15:44 UTC (permalink / raw)
  To: u-boot

On 28.12.2015 18:47, Moritz Fischer wrote:
> Hi all,
> 
> I spent some time moving over the zynq-i2c.c to support dm.
> While doing that I realized that renaming it to cdns-i2c might
> make sense since it now could be used with other SoCs that also use the
> the Cadence IP.
> 
> This is a first shot, but I'd like to get some early feedback ;-)
> 
> Cheers,
> 
>     Moritz
> 
> PS: I skipped touching the Zynq board files for now, since I wanted to make sure
> I get the driver right first ;-)
> 
> Moritz Fischer (2):
>   i2c: Describe Cadence I2C devicetree bindings
>   dm: i2c: Add driver for Cadence I2C IP
> 
>  doc/device-tree-bindings/i2c/i2c-cdns.txt |  20 ++
>  drivers/i2c/Kconfig                       |   7 +
>  drivers/i2c/Makefile                      |   1 +
>  drivers/i2c/i2c-cdns.c                    | 339 ++++++++++++++++++++++++++++++
>  4 files changed, 367 insertions(+)
>  create mode 100644 doc/device-tree-bindings/i2c/i2c-cdns.txt
>  create mode 100644 drivers/i2c/i2c-cdns.c
> 

I have looked at these patches and I don't know why there is 100k
limitation in cdns_i2c_set_bus_speed. DTS is using 400k in Linux without
any problem.

Unfortunately I found that i2c muxes like pca9548 are not supported yet
but I have create sort of skeleton for that but it looks like that there
is no standard binding where i2c-parent is required. Also every muxes
bus needs to have correct label and alias.

Also I have found that there is eeprom dependency which needs to be
resolved to be able to use this driver instead of old one.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
  2016-01-05 15:44 ` Michal Simek
@ 2016-01-05 17:30   ` Moritz Fischer
  2016-01-06  7:53     ` Michal Simek
  0 siblings, 1 reply; 15+ messages in thread
From: Moritz Fischer @ 2016-01-05 17:30 UTC (permalink / raw)
  To: u-boot

Hi Michal,

On Tue, Jan 5, 2016 at 7:44 AM, Michal Simek <michal.simek@xilinx.com> wrote:

> I have looked at these patches and I don't know why there is 100k
> limitation in cdns_i2c_set_bus_speed. DTS is using 400k in Linux without
> any problem.

Well I could statically calculate the values for 400K, too but anyway that works
only if your CPU_CLK_1X is 111MHz. Is there a way to figure out the CPU_CLK_1X
frequency?

> Unfortunately I found that i2c muxes like pca9548 are not supported yet
> but I have create sort of skeleton for that but it looks like that there
> is no standard binding where i2c-parent is required. Also every muxes
> bus needs to have correct label and alias.

Yeah, I realized that last night when I started playing around with
it. I was trying
to pull in the linux one but didn't get around to finish that yet.

> Also I have found that there is eeprom dependency which needs to be
> resolved to be able to use this driver instead of old one.

Yeah I realized that. Do any of the zynq boards actually use CMD_EEPROM?

Thanks for you feedback,

Moritz

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
  2016-01-05 17:30   ` Moritz Fischer
@ 2016-01-06  7:53     ` Michal Simek
  2016-01-07  5:18       ` Moritz Fischer
  0 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2016-01-06  7:53 UTC (permalink / raw)
  To: u-boot

On 5.1.2016 18:30, Moritz Fischer wrote:
> Hi Michal,
> 
> On Tue, Jan 5, 2016 at 7:44 AM, Michal Simek <michal.simek@xilinx.com> wrote:
> 
>> I have looked at these patches and I don't know why there is 100k
>> limitation in cdns_i2c_set_bus_speed. DTS is using 400k in Linux without
>> any problem.
> 
> Well I could statically calculate the values for 400K, too but anyway that works
> only if your CPU_CLK_1X is 111MHz. Is there a way to figure out the CPU_CLK_1X
> frequency?

Check the clock driver.


>> Unfortunately I found that i2c muxes like pca9548 are not supported yet
>> but I have create sort of skeleton for that but it looks like that there
>> is no standard binding where i2c-parent is required. Also every muxes
>> bus needs to have correct label and alias.
> 
> Yeah, I realized that last night when I started playing around with
> it. I was trying
> to pull in the linux one but didn't get around to finish that yet.

It is simple to create that mux drivers but I am scared about that need
for aliases and also i2c-parent has to go out of mux class too.
I see that it is used in the mainline kernel but it has be changed.


>> Also I have found that there is eeprom dependency which needs to be
>> resolved to be able to use this driver instead of old one.
> 
> Yeah I realized that. Do any of the zynq boards actually use CMD_EEPROM?

We have a code for zc702 to save internal variables to EEPROM. zc706
should have that memory too.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
  2016-01-06  7:53     ` Michal Simek
@ 2016-01-07  5:18       ` Moritz Fischer
  2016-01-07  8:13         ` Michal Simek
  0 siblings, 1 reply; 15+ messages in thread
From: Moritz Fischer @ 2016-01-07  5:18 UTC (permalink / raw)
  To: u-boot

On Tue, Jan 5, 2016 at 11:53 PM, Michal Simek <michal.simek@xilinx.com> wrote:
> On 5.1.2016 18:30, Moritz Fischer wrote:
>> Hi Michal,
>>
>> On Tue, Jan 5, 2016 at 7:44 AM, Michal Simek <michal.simek@xilinx.com> wrote:
>>
>>> I have looked at these patches and I don't know why there is 100k
>>> limitation in cdns_i2c_set_bus_speed. DTS is using 400k in Linux without
>>> any problem.
>>
>> Well I could statically calculate the values for 400K, too but anyway that works
>> only if your CPU_CLK_1X is 111MHz. Is there a way to figure out the CPU_CLK_1X
>> frequency?
>
> Check the clock driver.

Wouldn't that nececitate dm capable clk drivers? Were you talking about
arch/arm/mach-zynq/clk.c?

> It is simple to create that mux drivers but I am scared about that need
> for aliases and also i2c-parent has to go out of mux class too.
> I see that it is used in the mainline kernel but it has be changed.

I'll need to further investigate that.
>
>
>>> Also I have found that there is eeprom dependency which needs to be
>>> resolved to be able to use this driver instead of old one.
>>
>> Yeah I realized that. Do any of the zynq boards actually use CMD_EEPROM?
>
> We have a code for zc702 to save internal variables to EEPROM. zc706
> should have that memory too.

Ok, I'll look into it.

Moritz

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c
  2016-01-07  5:18       ` Moritz Fischer
@ 2016-01-07  8:13         ` Michal Simek
  0 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2016-01-07  8:13 UTC (permalink / raw)
  To: u-boot

On 7.1.2016 06:18, Moritz Fischer wrote:
> On Tue, Jan 5, 2016 at 11:53 PM, Michal Simek <michal.simek@xilinx.com> wrote:
>> On 5.1.2016 18:30, Moritz Fischer wrote:
>>> Hi Michal,
>>>
>>> On Tue, Jan 5, 2016 at 7:44 AM, Michal Simek <michal.simek@xilinx.com> wrote:
>>>
>>>> I have looked at these patches and I don't know why there is 100k
>>>> limitation in cdns_i2c_set_bus_speed. DTS is using 400k in Linux without
>>>> any problem.
>>>
>>> Well I could statically calculate the values for 400K, too but anyway that works
>>> only if your CPU_CLK_1X is 111MHz. Is there a way to figure out the CPU_CLK_1X
>>> frequency?
>>
>> Check the clock driver.
> 
> Wouldn't that nececitate dm capable clk drivers? Were you talking about
> arch/arm/mach-zynq/clk.c?

yes. clk dump shows that information. It means you should be able to get
that information. Probably we will need to create clk driver.

Thanks,
Michal


=> clk dump
clk		frequency
    armpll          1333333320
    ddrpll          1066666656
     iopll           999999990
 cpu_6or4x           666666660
 cpu_3or2x           333333330
    cpu_2x           222222220
    cpu_1x           111111110
    ddr_2x           355555552
    ddr_3x           533333328
       dci            10158730
     lqspi           199999998
       smc            22222222
      pcap           199999998
      gem0            25000000
      gem1            16666667
     fclk0            50000000
     fclk1            50000000
     fclk2            50000000
     fclk3            50000000
     sdio0            50000000
     sdio1            50000000
     uart0            50000000
     uart1            50000000
      spi0            15873016
      spi1            15873016
 usb0_aper           111111110
 usb1_aper           111111110
 gem0_aper           111111110
 gem1_aper           111111110
sdio0_aper           111111110
sdio1_aper           111111110
 spi0_aper           111111110
 spi1_aper           111111110
 can0_aper           111111110
 can1_aper           111111110
 i2c0_aper           111111110
 i2c1_aper           111111110
uart0_aper           111111110
uart1_aper           111111110
 gpio_aper           111111110
lqspi_aper           111111110
  smc_aper           111111110
   dbg_trc            66666666
   dbg_apb            66666666

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP
  2016-01-04  7:15   ` Heiko Schocher
@ 2016-04-11 12:50     ` Michal Simek
  2016-04-12  7:45       ` Heiko Schocher
  0 siblings, 1 reply; 15+ messages in thread
From: Michal Simek @ 2016-04-11 12:50 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 4.1.2016 08:15, Heiko Schocher wrote:
> Hello Moritz,
> 
> Am 28.12.2015 um 18:47 schrieb Moritz Fischer:
>> This is a possible drop in replacement for drivers/i2c/zynq-i2c.c
>>
>> Since this is cadence IP it has been renamed to cdns-i2c,
>> to make sense with the compatible string.
>>
>> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
>> ---
>>   drivers/i2c/Kconfig    |   7 +
>>   drivers/i2c/Makefile   |   1 +
>>   drivers/i2c/i2c-cdns.c | 339
>> +++++++++++++++++++++++++++++++++++++++++++++++++
>>   3 files changed, 347 insertions(+)
>>   create mode 100644 drivers/i2c/i2c-cdns.c
> 
> Hmm.. I di not see the remove of "drivers/i2c/zynq-i2c.c" as
> you wrote it is a replacement for it ... Can you do this, and
> of course adapt the boards which use this driver?

I would like to start to use this driver for ZynqMP and use old driver
for Zynq because there eeprom hasn't been moved.

I found just one problem regarding reading addr from DT which I have fixed.

Thanks,
Michal


-- 
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform


-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 198 bytes
Desc: OpenPGP digital signature
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160411/a2cbb4cb/attachment.sig>

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP
  2016-04-11 12:50     ` Michal Simek
@ 2016-04-12  7:45       ` Heiko Schocher
  2016-04-12  7:59         ` Michal Simek
  0 siblings, 1 reply; 15+ messages in thread
From: Heiko Schocher @ 2016-04-12  7:45 UTC (permalink / raw)
  To: u-boot

Hello Michal,

Sorry for the late reply...

Am 11.04.2016 um 14:50 schrieb Michal Simek:
> Hi Heiko,
>
> On 4.1.2016 08:15, Heiko Schocher wrote:
>> Hello Moritz,
>>
>> Am 28.12.2015 um 18:47 schrieb Moritz Fischer:
>>> This is a possible drop in replacement for drivers/i2c/zynq-i2c.c
>>>
>>> Since this is cadence IP it has been renamed to cdns-i2c,
>>> to make sense with the compatible string.
>>>
>>> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
>>> ---
>>>    drivers/i2c/Kconfig    |   7 +
>>>    drivers/i2c/Makefile   |   1 +
>>>    drivers/i2c/i2c-cdns.c | 339
>>> +++++++++++++++++++++++++++++++++++++++++++++++++
>>>    3 files changed, 347 insertions(+)
>>>    create mode 100644 drivers/i2c/i2c-cdns.c
>>
>> Hmm.. I di not see the remove of "drivers/i2c/zynq-i2c.c" as
>> you wrote it is a replacement for it ... Can you do this, and
>> of course adapt the boards which use this driver?
>
> I would like to start to use this driver for ZynqMP and use old driver
> for Zynq because there eeprom hasn't been moved.
>
> I found just one problem regarding reading addr from DT which I have fixed.

Yes, I just saw the v2 versions... I review them soon.

bye,
Heiko
-- 
DENX Software Engineering GmbH,      Managing Director: Wolfgang Denk
HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP
  2016-04-12  7:45       ` Heiko Schocher
@ 2016-04-12  7:59         ` Michal Simek
  0 siblings, 0 replies; 15+ messages in thread
From: Michal Simek @ 2016-04-12  7:59 UTC (permalink / raw)
  To: u-boot

Hi Heiko,

On 12.4.2016 09:45, Heiko Schocher wrote:
> Hello Michal,
> 
> Sorry for the late reply...
> 
> Am 11.04.2016 um 14:50 schrieb Michal Simek:
>> Hi Heiko,
>>
>> On 4.1.2016 08:15, Heiko Schocher wrote:
>>> Hello Moritz,
>>>
>>> Am 28.12.2015 um 18:47 schrieb Moritz Fischer:
>>>> This is a possible drop in replacement for drivers/i2c/zynq-i2c.c
>>>>
>>>> Since this is cadence IP it has been renamed to cdns-i2c,
>>>> to make sense with the compatible string.
>>>>
>>>> Signed-off-by: Moritz Fischer <moritz.fischer@ettus.com>
>>>> ---
>>>>    drivers/i2c/Kconfig    |   7 +
>>>>    drivers/i2c/Makefile   |   1 +
>>>>    drivers/i2c/i2c-cdns.c | 339
>>>> +++++++++++++++++++++++++++++++++++++++++++++++++
>>>>    3 files changed, 347 insertions(+)
>>>>    create mode 100644 drivers/i2c/i2c-cdns.c
>>>
>>> Hmm.. I di not see the remove of "drivers/i2c/zynq-i2c.c" as
>>> you wrote it is a replacement for it ... Can you do this, and
>>> of course adapt the boards which use this driver?
>>
>> I would like to start to use this driver for ZynqMP and use old driver
>> for Zynq because there eeprom hasn't been moved.
>>
>> I found just one problem regarding reading addr from DT which I have
>> fixed.
> 
> Yes, I just saw the v2 versions... I review them soon.

Thanks,
Michal

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2016-04-12  7:59 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-12-28 17:47 [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Moritz Fischer
2015-12-28 17:47 ` [U-Boot] [RFC 1/2] i2c: Describe Cadence I2C devicetree bindings Moritz Fischer
2016-01-04  7:09   ` Heiko Schocher
2015-12-28 17:47 ` [U-Boot] [RFC 2/2] dm: i2c: Add driver for Cadence I2C IP Moritz Fischer
2016-01-04  7:15   ` Heiko Schocher
2016-04-11 12:50     ` Michal Simek
2016-04-12  7:45       ` Heiko Schocher
2016-04-12  7:59         ` Michal Simek
2015-12-28 18:35 ` [U-Boot] [RFC 0/2] Add cdns-i2c driver as drop in for zynq-i2c Michal Simek
2015-12-28 19:15   ` Moritz Fischer
2016-01-05 15:44 ` Michal Simek
2016-01-05 17:30   ` Moritz Fischer
2016-01-06  7:53     ` Michal Simek
2016-01-07  5:18       ` Moritz Fischer
2016-01-07  8:13         ` Michal Simek

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox